diff --git a/.babelrc b/.babelrc index 9772b939..ece1d876 100644 --- a/.babelrc +++ b/.babelrc @@ -1,13 +1,5 @@ { "presets": [ - [ - "env", - { - "modules": false - } - ] - ], - "plugins": [ - "external-helpers" + ["@babel/preset-env"] ] } diff --git a/.eslintignore b/.eslintignore index 32420d72..cbba48f7 100644 --- a/.eslintignore +++ b/.eslintignore @@ -21,7 +21,6 @@ editor/js-hotkeys editor/jspdf/jspdf.min.js editor/jspdf/underscore-min.js -editor/extensions/imagelib/jquery.min.js editor/extensions/mathjax editor/external/* diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 647282f8..00000000 --- a/.eslintrc +++ /dev/null @@ -1,23 +0,0 @@ -{ - "extends": ["standard", "plugin:qunit/recommended"], - "parserOptions": { - "sourceType": "module" - }, - "plugins": ["qunit"], - "env": { - "node": false, - "browser": true - }, - "rules": { - "semi": [2, "always"], - "indent": ["error", 2, {"outerIIFEBody": 0}], - "no-tabs": 0, - "object-property-newline": 0, - "one-var": 0, - "no-var": 2, - "prefer-const": 2, - "no-extra-semi": 2, - "quote-props": [2, "as-needed"], - "object-curly-spacing": ["error", "never"] - } -} diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..f768c89a --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,152 @@ +module.exports = { + extends: [ + "ash-nazg/sauron-node", + "plugin:qunit/recommended", "plugin:testcafe/recommended" + ], + parserOptions: { + sourceType: "module" + }, + // Need to make explicit here for processing by jsdoc/check-examples + plugins: ["qunit"], + env: { + browser: true + }, + settings: { + polyfills: ["url", "promises", "fetch", "queryselector", "object-values"], + jsdoc: { + additionalTagNames: { + // In case we need to extend + customTags: [] + }, + tagNamePreference: { + arg: "param", + return: "returns" + }, + allowOverrideWithoutParam: true, + allowImplementsWithoutParam: true, + allowAugmentsExtendsWithoutParam: true, + // For `jsdoc/check-examples` in `ash-nazg` + matchingFileName: "dummy.md", + rejectExampleCodeRegex: "^`", + } + }, + overrides: [ + // These would otherwise currently break because of these issues: + // 1. `event:` https://github.com/eslint/doctrine/issues/221 and https://github.com/Kuniwak/jsdoctypeparser/pull/49 with https://github.com/Kuniwak/jsdoctypeparser/issues/47 + // 1. `@implements`/`@augments`/`@extends`/`@override`: https://github.com/eslint/doctrine/issues/222 + { + files: [ + "test/utilities_test.js", "editor/svg-editor.js", "editor/svgcanvas.js", + "editor/coords.js", + "editor/extensions/ext-eyedropper.js", "editor/extensions/ext-webappfind.js" + ], + rules: { + "jsdoc/valid-types": "off", + "valid-jsdoc": "off" + } + }, + // Locales have no need for importing outside of SVG-Edit + { + files: [ + "editor/locale/lang.*.js", "editor/extensions/ext-locale/**", + "docs/tutorials/ExtensionDocs.md" + ], + rules: { + "import/no-anonymous-default-export": ["off"] + } + }, + // For extensions, `this` is generally assigned to be the more + // descriptive `svgEditor`; they also have no need for importing outside + // of SVG-Edit + { + files: ["editor/extensions/**/ext-*.js"], + rules: { + "consistent-this": ["error", "svgEditor"], + "import/no-anonymous-default-export": ["off"] + } + }, + // These browser files don't do importing or requiring + { + files: [ + "editor/svgpathseg.js", "editor/touch.js", "editor/typedefs.js", + "editor/redirect-on-no-module-support.js", + "editor/extensions/imagelib/index.js", + "editor/external/dom-polyfill/dom-polyfill.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"] + } + }, + // Our Markdown rules (and used for JSDoc examples as well, by way of + // our use of `matchingFileName` in conjunction with + // `jsdoc/check-examples` within `ash-nazg`) + { + files: ["**/*.md"], + rules: { + "eol-last": ["off"], + "no-console": ["off"], + "no-undef": ["off"], + "no-unused-vars": ["warn"], + "padded-blocks": ["off"], + "import/unambiguous": ["off"], + "import/no-unresolved": ["off"], + "node/no-missing-import": ["off"] + } + }, + // Dis-apply Node rules mistakenly giving errors with browser files + { + files: ["editor/**", "test/**"], + rules: { + "node/no-unsupported-features/node-builtins": ["off"] + } + }, + // We want console in tests! + { + files: ["test/**"], + rules: { + "no-console": ["off"] + } + }, + { + // Node files + files: [ + "docs/jsdoc-config.js", + "build-html.js", "jsdoc-check-overly-generic-types.js", + "rollup.config.js", "rollup-config.config.js" + ], + env: { + node: true, + }, + rules: { + "node/no-unpublished-import": ["off"], + "node/no-unsupported-features/es-syntax": ["off"] + } + }, + { + // As consumed by jsdoc, cannot be expressed as ESM + files: ["docs/jsdoc-config.js"], + parserOptions: { + sourceType: "script" + }, + rules: { + "import/no-commonjs": "off" + } + } + ], + rules: { + // Override these `ash-nazg/sauron` rules which are difficult for us + // to apply at this time + "default-case": ["off"], + "require-unicode-regexp": ["off"], + "max-len": ["off", { + ignoreUrls: true, + ignoreRegExpLiterals: true + }], + "unicorn/prefer-query-selector": ["off"], + "unicorn/prefer-node-append": ["off"] + } +}; diff --git a/.gitignore b/.gitignore index 3c2b54e9..cc2cf75c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +ignore node_modules build/ diff --git a/.htmlhintrc b/.htmlhintrc new file mode 100644 index 00000000..8412d07b --- /dev/null +++ b/.htmlhintrc @@ -0,0 +1,3 @@ +{ + "title-require": false +} diff --git a/.npmignore b/.npmignore index ceaef224..cdd46ea7 100644 --- a/.npmignore +++ b/.npmignore @@ -1,2 +1,8 @@ +ignore screencasts test + +.github/ISSUE_TEMPLATE/bug_report.md +build +jsdoc-check-overly-generic-types.js +lgtm.yml diff --git a/.remarkrc b/.remarkrc index bfbd6972..da24a20e 100644 --- a/.remarkrc +++ b/.remarkrc @@ -1,10 +1,5 @@ { "plugins": { - "lint": { - "ordered-list-marker-value": "one", - "no-missing-blank-lines": false, - "list-item-spacing": false, - "list-item-indent": false - } + "lint-ordered-list-marker-value": "one" } } diff --git a/CHANGES.md b/CHANGES.md index 6b435f3e..f4fda875 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,47 +1,321 @@ -# ? +# SVG-Edit CHANGES -- Known regression for 3.\*: Image libraries [broken](https://github.com/SVG-Edit/svgedit/issues/274) +## ? + +- Fix: Delay icon setting until locales available (fixes #323) +- Fix: Extension with no `placement` to be added to end; + for #326 (@sjernigan) +- Optimization fix: Properly run code conditionally on browser check; + fixes #312 (@ianli-sc) +- Enhancement: Add CAD Placemark extension (@NeiroNx) + +## 4.2.0 + +- Fix: Problem with retaining lines with grid mode (@NeiroNx) +- l10n: Add Chinese (simplified) extension locales (@enlove) +- l10n: Add Russian translation to some strings (@NeiroNx) +- Refactoring: Avoid Firefox console errors with hidden iframe +- npm: Update devDeps + +## 4.1.0 + +- Fix: Avoid cross-frame unsafe `instanceof` +- Enhancement: Add svgcanvas distributions +- Demo: Rename import to match named dist export +- Linting (ESLint): Prefer `addEventListener`, exponentiation operator, + avoiding catastrophic regexes, prefer spread, prefer + `startsWith`/`endsWith`, no fn ref in iterator +- npm: Update devDeps + +## 4.0.1 + +- Fix: Adjust side panel width checking based on device zoom (fixes #298) +- Fix (regression): RGBColor + +## 4.0.0 + +- Breaking change (storage preference cookies): Namespace the cookie as + "svgeditstore" instead of just "store" +- Breaking change: `loadSvgString` now returns a `Promise` rather than + accepting a callback. +- Breaking change: Treat callbacks to `editor.ready` as Promises, only + resolving after all resolve. May require no changes unless for timing. +- Breaking change: Make `editor.runCallbacks` return a `Promise` which + resolves upon all callbacks resolving. +- Breaking change: Require `npx` (used with `babel-node`) to allow Node files + for HTML building and JSDoc type checking to be expressed as ESM. +- Breaking change: `addExtension` now throws upon a repeated attempt to + add an already-added extension +- Breaking change (API): Remove `svgCanvas.rasterExport` fourth (callback) + argument, collapsing fifth (options) to fourth +- Breaking change (API): Remove `svgCanvas.exportPDF` third (callback) + argument +- Breaking change (API): `editor/contextmenu.js` `add` now throws instead + of giving a console error only upon detecting a bad menuitem or + preexisting context menu +- Breaking change (API): Remove `svgCanvas.embedImage` second (callback) + argument +- Breaking change (API): Make `getHelpXML` a class instead of instance method + of `RGBColor` +- Breaking change (internal API): Refactor `dbox` (and + `alert`/`confirm`/`process`/`prompt`/`select`) to avoid a callback argument + in favor of returning a Promise +- 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 +- Fix: Avoid running in extension `langReady` multiple times or serially +- Enhancement (API): Add `svgCanvas.runExtension` to run just one extension and + add `nameFilter` callback to `runExtensions` +- Enhancement (API): Supply `$` (our wrapped jQuery) to extensions so can use + its plugins, e.g., dbox with its `alert` +- Enhancement: Use alert dialog in place of `alert` in webappfind +- Enhancement: `editor.ready` now returns a Promise resolving when all + callbacks have resolved +- Enhancement: Allow `noAlert` option as part of second argument to + `loadSvgString` (and `loadFromURL` and `loadFromDataURI`) to avoid UI + alert (and trigger promise rejection) +- Enhancement: Make `dbox` as a separate module for alert, prompt, etc. dialogs +- Optimization: Recompress images (imageoptim-cli updated) +- Refactoring: Internal `PaintBox` as class; other misc. tweaks; no bitwise + in canvg +- Refactoring: Reuse utilities base64 encoder for SVG icons plugin +- Linting (ESLint): Further linting changes (for editor); rename + `.eslintrc` -> `.eslintrc.js` per recommendation and to more transparently + allow comments; apply new strict `eslint-config-ash-nazg` rules. +- Linting (ESLint): Stricter rules (or switch to warning) +- 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 +- npm: Update devDeps + +## 3.2.0 + +- Refactoring: Avoid unnecessary `addEventListener` `false`; change internal + jPicker function to class (used with `new`) +- Linting (ESLint): Add `valid-jsdoc` rule and make fixes, but turn off for + now due to and + +- Linting (ESLint compat): Add `eslint-plugin-compat` to get browser support + warnings +- Linting (ESLint Markdown JavaScript): Add `eslint-plugin-markdown` with + slightly loosened config (`no-undef` and `padded-blocks` off and + `no-unused-vars` as a warning) +- Linting (ESLint JSDoc code comments): Add `eslint-plugin-jsdoc` and apply to + JSDoc code comments though disable `jsdoc/valid-types` rule for now due to and disable rule + `jsdoc/require-param` due to + ; also of + possible interest: , + , + , + , + , + ; NOTE: + if we need to tap into Markdown within JSDoc, see + for commit not present in npm. +- Docs (README): Indicate minimal polyfills needed for older browsers + (IE <= 11, IE Mobile, Opera Mini, Blackberry Browser <= 10, + Android Browser 4.4.3-4.4.4) +- Docs (JSDoc): Add some Markdown for variables, line breaks; tighten checks + for overly generic types (though allow for `.Function` as in + `jQuery.Function`) and avoid one previously missed instance +- Docs (3.0.0): Clarify +- Docs (ReleaseInstructions): Clarify need for npm permissions to publish +- npm: Update devDeps (including some resolving security vulnerabilities) +- npm: Do a fresh install of all packages and update `package-lock.json` + accordingly; update qunit dist + +## 3.1.1 + +- Fix: Save broken on Firefox (since FF version?) +- Docs (ReleaseInstructions): Clarify build instructions for release +- Docs (ReleaseInstructions): Update per new testing; update + `grep-doc` -> `types-doc` and indicate current failing status; indicate + when `build-doc` will be used; clarify `npm pack` +- Docs: For clarity, rename `grep-jsdoc.js` to + `jsdoc-check-overly-generic-types.js` +- Docs: Move `GenericCallback` to `typedefs.js` for possible (if unlikely) + reuse +- Docs: Mention potentially more frequent release schedule +- npm: Update "grep-doc" to "types-doc" for greater clarity +- npm: Per convention, switch Node-based (headless browser) testing script to + `npm test` and change the browser tests to "browser-test" + +## 3.1.0 + +- Fix (Embedded editor): (Though cross-origin DOM access of iframes apparently + doesn't work now in Chrome or Firefox (which we had been using to disable a + button) nor does cross-origin storage access work in Chrome), PDF export has + been fixed (we download the PDF to workaround data URI limitations in Chrome) + and we avoid opening an extra tab in Chrome PNG export +- Fix (Embedded editor): Avoid using same origin shortcut if there is no + global available to use (e.g., if using the modular editor) +- Fix (Embedded editor): Add events only after load is complete and + svgCanvas is available; also log blocked error objects +- Fix: Have export handler, if triggered, always open a window even if no + window name was given (needed in Chrome to avoid opening an extra window) +- Enhancement: For anyone visiting the ES6 modules entrance file without ESM + support, redirect to non-modular version +- Enhancement: For PDF export, switch Chrome by default to "save" `outputType` +- Enhancement: Add `opts` object to `rasterExport` with `avoidEvent` property + to avoid calling the `exported` event +- Refactoring (canvg): Better type-checking on `canvasRGBA_` (but set + correctly by default anyways) +- Refactoring: Avoid redundant use of \*AttributeNS methods with + `null` value; just use \*Attribute methods without namespace +- Refactoring: Display inline styles within a template for readability + (until we may refactor as class swapping) +- Refactoring: Line breaks +- Refactoring: Reorder path config to group (non-modular-dependent) image + paths together (and correct code comment) +- Docs (CHANGES): clarifications/fixes +- Docs (README): Deemphasize unstable embedded editor fixes +- Docs: Versions section (for migrating) +- Docs: More info on `importLocale` for extensions +- Docs: Add code comment re: use of `extIconsPath` in Mathjax +- Docs (JSDoc): Denote optional arguments +- Docs (JSDoc): Add @this to indicate `ExtensionInitResponse#callback` +- Build: Add comment not to edit xdomain editor directly +- Build: Remove unused `Makefile` + +## 3.0.1 + +- Fix: Revert fix to have extension `mouseup` events run on "zoom" and + "select" modes (#159); breaks polygon selection +- Fix (jgraduate->jpicker): Actually fix issue with color val check when no + other proper results (equal to "all"); prior fix had not covered + original intention + +## 3.0.0 + +- See pre-release version notes below for other changes that are a part + of 3.0.0 +- Breaking change: For checkbox for persisting choice of initial use storage + approval in storage extension dialog, turn on by default for convenience of + most users (must still hit "ok" and users can still turn off the checkbox) +- Breaking change: Remove `storagePromptClosed` state boolean in favor of + `storagePromptState`; used by `ext-storage.js` +- Fix: Map extension click events to "mousedown" so they can be received + on touch devices (since `touch.js` changes `touchstart` to + `mousedown`) (@ClemArt); closes #168 +- Fix: Ensure extension `mouseup` events run on "zoom" and "select" + modes (@iuyiuy); closes #159 +- Fix: Allow language to be properly set back to a different locale and + retaining preference (and ensure language changes are available before + dialog closed) +- Fix: Centering of canvas wasn't being set at proper time; fixes #272 +- Fix (extensions): Ensure `langReady` changes are available by time prefs + dialog is closed and that its changes have occurred by time extensions + have first loaded (`setLang` now returns a Promise rather than `undefined` + as it waits for extension's `langReady` to resolve); this is also useful + with `ext-storage.js` so we know that `extensions_loaded` (which + conditionally updates the canvas based on `storagePromptState`) has seen + `langReady` and the storage extension hasn't set a `storagePromptState` + of "waiting" +- Fix (regression): Extension locale loading for non-English locales +- Enhancement: Allow "Escape" to work with hotkeys within text boxes; + allows escaping out of source textarea (part of #291) +- Enhancement: Allow 'a' also with meta key (command in Mac, ctrl otherwise) + to select all (part of #291) +- Enhancement: Add a global escape key listener to clear the selection +- Refactoring: Change 'a' to lower case in key command to avoid impression + that shift is needed +- Refactoring: Avoid unneeded internal IIFEs; simplify w/h formula +- Refactoring: array extra/spread operator +- npm: Update devDeps + +## 3.0.0-rc.3 + +- Security fix: Ensure all apostrophes are escaped for `toXml` utility +- Security fix/Breaking change (Imagelib): Only allow origins within + `imgLibs` to be accepted for `message` listener +- Security fix/Breaking change (xdomain): Namespace xdomain file to avoid + it being used to modify non-xdomain storage +- Security fix (Imagelib): Avoid XSS +- Security fix (Imagelib): Expose `dropXMLInternalSubset` to extensions + for preventing billion laughs attack (and use in Imagelib) +- Security fix (minor): For embedded API, avoid chance for arbitrary + property setting (though this was only for trusted origins anyways) +- Security fix (minor): For embedded API example, copy params to iframe + source without XSS risk (though params should already be XML-safe + given `encodeURIComponent` and lack of a single quote attribute + context) +- Situational regression: Remove Openclipart as its site's now setting of + `X-Frame-Options` to `"sameorigin"` makes it unusable on our end + for our cross-origin uses (even with an attempt to use their API) - Breaking change (minor): Change export to check `exportWindowName` for filename and change default from `download` to `svg.pdf` to distinguish from other downloads - Fix: Given lack of support now for dataURI export in Chrome, provide - PDF as export (#273 @cuixiping); fixes #124 and #254 + PDF download as export (#273 @cuixiping); fixes #124 and #254 +- Fix: Polygon/polyline in PDF export (#287 @cuixiping); fixes #280 +- Fix: Avoid error if `URL` is not defined (export) +- Fix: Ensure repeated selection of same file overwrites with that + file's contents (fix #289) +- Fix: Avoid errors occurring in Chrome now for `supportsGoodTextCharPos` +- Fix (jPicker): Avoid setting `Math.precision` pseudo-global +- Fix (jPicker): Precision argument had not been passed in previously - Fix (image import): Put src after onload to avoid missing event; check other width/height properties in case offset is 0; fixes #278 - Fix (image export): Export in Chrome; fixes #282 -- Fix (Context menus): Avoid showing double shortcuts (#285); add some - missing ones +- Fix (Context menus regression): Avoid showing double shortcuts (#285); add + some missing ones +- Fix (Star extension): Minor: Avoid erring if `inradius` is `NaN` +- Forward compatibility enhancement: Once IE9 support may be dropped, + we may post messages as objects, so don't break if objects received + (embedded API, xdomain, Imagelib) +- Forward compatibility enhancement: For IAN image library, add + `svgedit=3` param to URL so that it can keep using old API for + SVG-Edit versions before 3, while conditionally using new object-based + API now (and if we switch exclusively to the object-based API in the + future, this site will continue to work) +- Imagelib backward compatibility regression fix: Allow string based API + again so as not to break old SVG-Edit which fail at *presence* of + `namespace` (fixes #274) +- Refactoring: Avoid passing unused arguments, setting unused variables, + and making unnecessary checks; avoid useless call to `createSVGMatrix` +- Refactoring: Avoid useless assignment (courtesty lgtm) +- Refactoring: Destructuring, spread +- Refactoring (jPicker): Use ES6 templates; avoid unnecessary check +- Linting (LGTM): Add `lgtm.yml` file (still some remaining items flagged + but hoping for in-code flagging) +- Linting (LGTM): Flag origin-checked item as safe +- Linting (ESLint): Consistent spacing; new "standard" +- Testing: Add testcafe (ESLint plugin/rules, accessibility test + (failing), ui test beginnings (passing)) +- Docs: Contributing file +- Docs (JSDoc): Missing return value +- Update (Imagelib): Remove extra (and more outdated) jQuery copy +- Build (prerelease change): Switch to `terser` plugin with `uglify` + plugin not supporting ES6+-capable minifier - npm: Update devDeps - npm: Point to official sinon-test package now that ES6 Modules support landed -- Build: Switch to `terser` plugin with `uglify` plugin not - supporting ES6+-capable minifier -- Linting (ESLint): Consistent spacing; new "standard" -# 3.0.0-rc.2 +## 3.0.0-rc.2 - Fix: Avoid extension `includeWith` button conflicts/redundancies; Incorporates #147 - Fix: Ensure shift-key cycling through flyouts works with extension-added `includeWith` as well as toolbarbuttons -- Fix: Apply flyout arrows after extensions callback -- Fix: Ensure SVG icon of flyout right-arrow is cloned to can be applied to +- Fix: Apply flyout arrows after extensions loaded (avoid race condition) +- Fix: Ensure SVG icon of flyout right-arrow is cloned so can be applied to more than one extension - Fix: Ensure line tool shows as selected when "L" key command is used - Fix: Add images (and references) for fallback (#135) -- Fix (svgIcons plugin): Race condition +- Fix (svgIcons plugin regression): Race condition - Fix (canvg): Regression for `text` and `tspan` elements as far as `captureTextNodes` with canvg (inheriting class had set `captureTextNodes` too late) - Fix (canvg): Regression on blur - Fix (canvg): Avoid errors for `tspan` passed to `getGradient` +- Fix (regression): Reapply locale strings - i18n: picking stroke/fill paint and opacity - i18n: Remove eyedropper and imagelib references from main locale (in extension locale now) - i18n: Add placeholders for `pick_stroke_paint_opacity`, `pick_fill_paint_opacity`, `popupWindowBlocked` - i18n: Update `saveFromBrowser` -- i18n: Reapply locale strings - Enhancement: Create xdomain file build which works without ES6 Modules - Enhancement: Build xdomain files dynamically - Optimize: Further image optimizing @@ -54,10 +328,11 @@ - Docs: JSDoc for `setupFlyouts`, `Actions`, `toggleSidePanel`; missing for ToolbarButton -# 3.0.0-rc.1 +## 3.0.0-rc.1 - Security fix: 'extPath', 'imgPath', 'extIconsPath', 'canvgPath', 'langPath', 'jGraduatePath', and 'jspdfPath' were not being prevented + from URL setting - Breaking change: Rename "svgutils.js" to "utilities.js" (make in conformity with JSDoc module naming convention) - Breaking change: Rename "svgedit.js" to "namespaces.js" (to make clear @@ -76,33 +351,21 @@ for consistency - Breaking change: Rename `changeSvgContent()` to `changeSVGContent()` for consistency -- Breaking change: Have `exportPDF` resolve with `output` and `outputType` - rather than `dataurlstring` (as type may vary) - Breaking change: Rename `extensions/mathjax/MathJax.js` to `extensions/mathjax/MathJax.min.js` -- Breaking change: Avoid recent change to have editor ready callbacks - return Promises (we're not using and advantageous to keep sequential) -- Breaking change: Avoid recent addition of locale-side function in - ext-imagelib for l10n - Breaking change: Change name of `ext-arrows.js` from `Arrows` to `arrows` for sake of file path (not localized anyways). -- Breaking change: Change `addlangData` extension event to `addLangData` - for consistency with method name - Breaking change: In interests of modularity/removing globals, remove `window.svgCanvas` and `svgCanvas.ready` as used by older extensions; use `svgEditor.canvas` and `svgEditor.ready` instead - Breaking change: Extension now formatted as export (and `this` is set to editor, including for `callback`) - Breaking change: Locale now formatted as export -- Breaking change: Moved out remaining modular i18n (imagelib) to own folder -- Breaking change: Drop `executeAfterLoads` (and getJSPDF/getCanvg) - Breaking change: `RGBColor` must accept `new` -- Breaking change: canvg - `stackBlurCanvasRGBA` must be set now by function - (`setStackBlurCanvasRGBA`) rather than global; `canvg` now a named export - Breaking change: Avoid passing `canvg`/`buildCanvgCallback` to extensions (have them import) -- Breaking change: Have `readLang` return lang and data but do not call - `setLang` +- Breaking change: Have `readLang` now return a value (lang and data) (as well + as `putLocale` which returns a call to it) but do not call `setLang` - Breaking change: Avoid adding `assignAttributes`, `addSVGElementFromJson`, `call`, `copyElem`, `findDefs`, `getElem`, `getId`, `getIntersectionList`, `getMouseTarget`, `getNextId`, `getUrlFromAttr`, `hasMatrixTransform`, @@ -110,10 +373,29 @@ `recalculateDimensions`, `remapElement`, `removeUnusedDefElems`, `round`, `runExtensions`, `sanitizeSvg`, `setGradient` `transformListToTransform` (and mistaken `toString` export) to `getPrivateMethods` (passed to - extensions) as available as public ones + extensions) as available as public ones (on canvas or editor that is + available to extensions) +- Breaking change (prerelease): Avoid recent addition of locale-side + function in ext-imagelib for l10n +- Breaking change (prerelease): Avoid recent change to have editor ready + callbacks return Promises (we're not using and advantageous to keep + sequential) +- Breaking change (prerelease): Have `exportPDF` resolve with `output` and + `outputType` rather than `dataurlstring` (as type may vary) +- Breaking change (prerelease): Change `addlangData` extension event to + `addLangData` + for consistency with method name +- Breaking change (prerelease): Moved out remaining modular i18n (imagelib) + to own folder +- Breaking change (prerelease): Drop `executeAfterLoads` + (and getJSPDF/getCanvg) +- Breaking change (prerelease): canvg - `stackBlurCanvasRGBA` must be set now + by function (`setStackBlurCanvasRGBA`) rather than global (though it imports + default now); `canvg` now a named export - npm: Add `prepublishOnly` script to ensure building/testing before publish - npm: Update devDeps including Rollup, Sinon -- Fix: Remove redundant (and incorrect) length set. (#256 ; fixes #255) +- Fix: Remove redundant (and incorrect) length set in + `removeFromSelection`. (#256; fixes #255) - Fix: Detection of whether to keep ellipse (rx and ry when just created are now returning 0 instead of null); also with rectangle/square; fixes #262 @@ -136,11 +418,11 @@ type to PNG - Fix (extension): Wrong name for moinsave - Fix (extension): ForeignObject editor -- Fix (Embedded API): Cross-domain may fail to even access `origin` or - `contentDocument` +- Fix (Embedded API): Avoid treating as cross-origin if even access to + `origin` on `contentDocument` is restricted - Fix (Embedded API): Avoid adding URL to iframe src if there are no arguments - Fix (Embedded API): Handle origin issues (fixes #173) -- Fix (Cross-domain usage): Recover from exceptions with `localStorage` +- Fix (Cross-origin usage): Recover from exceptions with `localStorage` - Fix regression (Imagelib): Fix path for non-module version - Update: Update WebAppFind per new API changes - Enhancement: Link to rawgit/raw.githack for live master demos (fixes #43) @@ -185,8 +467,8 @@ - Refactoring: Fix `lang` and `dir` for locales (though not in use currently anyways) - Refactoring: Provide path config for canvg, jspdf -- Refactoring: Drop code for extension as function (already requiring export - to be an object) +- Refactoring: Drop code for `callback` as init function (still may be + present on *return* from the extension `init` method, however). - Refactoring: Object destructuring, `Object.entries`, Object shorthand, array extras, more camelCase variable names - Refactoring: Add a `Command` base class @@ -195,7 +477,7 @@ - Refactoring: Remove unneeded `delimiter` from regex escaping utility - Refactoring: Clearer variable names - Refactoring: Use (non-deprecated) Event constructors -- Refactoring (minor): variadic args through ellipsis +- Refactoring (minor): variadic args through spread operator - Refactoring (minor): `getIssues` to return codes and strings, lbs - Refactoring (minor): Use single quotes in PHP - Docs (Code comments): Coding standards within @@ -208,7 +490,7 @@ (with formatting) was not preserved, though named links were carried over with absolute URLs - Docs: Begin deleting `SvgCanvas.md` as ensuring jsdoc has replacements -- Docs: Add Edtior doc file for help to general users +- Docs: Add Editor doc file for help to general users - Docs: Clarify/simplify install instructions - Docs: Generally update/improve docs (fixes #92) - Docs: Update links to `latest` path (Avoid needing to update such @@ -235,7 +517,7 @@ - Linting (ESLint): Avoid linting jsdoc folder - Testing: Use new Sinon -# 3.0.0-alpha.4 +## 3.0.0-alpha.4 - Docs: Convert more docs to JSDoc and add JSDoc script (thanks, tetedacier!) - Fix `main` on `package.json` to reference UMD distribution and `module` @@ -244,7 +526,7 @@ - Fix (regression): Star tool (radialshift) - Fix (regression): Favicon setting -# 3.0.0-alpha.3 +## 3.0.0-alpha.3 - Change: Default to stylesheet above `editor` directory - Docs: Installation steps @@ -256,7 +538,7 @@ - Fix regression: Avoid abandoning stylesheet loading if one load fails - Fix (ext-connector): Handle case of 2 connecting elements with same y-coordinate (fixes #210 ; thanks, @iuyiuy!) -- Enhancement: Delete the imge upon cancel if it is a new image (fixes #177) +- Enhancement: Delete the image upon cancel if it is a new image (fixes #177) - Enhancement: Allow `addSvgElementFromJson` to accept non-SVG namespaces with explicit `namespace` property as well as the default SVG namespace (fixes #155); document @@ -265,33 +547,39 @@ - Demos: Add svgcanvas demo (Neil Fraser) - npm: Update devDeps -# 3.0.0-alpha.2 +## 3.0.0-alpha.2 - Licensing: Indicate MIT is license type of rgbcolor and rename file to reflect it; rename/add license file name for jgraduate - and screencast to reflect type (Apache 2.0) -contains license information (of type MIT) for Raphael icons + and screencast to reflect type (Apache 2.0); + contains license information (of type MIT) for Raphael icons - Breaking change: Rename config file to `svgedit-config-iife.js` (or - for the module version, `svgedit-config-es.js`); also expect - one directory higher; incorporates #207 (@iuyiuy) -- Breaking change: Separate `extIconsPath` from `extPath` (not copying over icons) + for the module version, `svgedit-config-es.js`); also expect + one directory higher; incorporates #207 (@iuyiuy) +- Breaking change: Separate `extIconsPath` from `extPath` (not copying + over icons) - Breaking change: Don't reference `custom.css` in HTML; can instead be referenced in JavaScript through the config file (provided in `svgedit-config-sample-iife.js`/`svgedit-config-sample-es.js` as `svgedit-custom.css` for better namespacing); incorporates #207 (@iuyiuy) -- Breaking change: Remove minified jgraduate/spinbtn files (minified within Rollup routine) -- Breaking change: Require `new` with `EmbeddedSVGEdit` (allows us to use `class` internally) +- Breaking change: Remove minified jgraduate/spinbtn files (minified within + Rollup routine) +- Breaking change: Require `new` with `EmbeddedSVGEdit` (allows us to use + `class` internally) - Breaking change: `svgcanvas.setUiStrings` must now be called if not using editor in order to get strings (for sake of i18n) (and if using path.js alone, must also have its `setUiStrings` called) - Breaking change (ext-overview-window): Avoid global `overviewWindowGlobals` -- Breaking change (ext-imagelib): Change to object-based encoding for namespacing of -messages (though keep stringifying/parsing ourselves until we remove IE9 support) +- Breaking change (ext-imagelib): Change to object-based encoding for + namespacing of messages (though keep stringifying/parsing ourselves until + we remove IE9 support) - Breaking change: Rename `jquery.js` to `jquery.min.js` -- Breaking change: Remove `scoped` attribute from `style`; it is now deprecated and -obsolete; also move to head (after other stylesheets) +- Breaking change: Remove `scoped` attribute from `style`; it is now + deprecated and obsolete; also move to head (after other stylesheets) +- Breaking change: Avoid zoom with scroll unless shift key pressed - Fix: i18nize path.js strings and canvas notifications - Fix: Attempt i18n for ext-markers -- Fix: Zoom when scrolled; incorporates #169 (@AndrolGenhald), adapting for conventions; also allow avoidance when shift key pressed +- Fix: Zoom centered on cursor when scrolled; incorporates + #169 (@AndrolGenhald), adapting for conventions - Fix: Update Atom feed reference in HTML - Fix: Broken "lv" locale (and inconsistent tabs/spaces pt-PR) - Fix: Inadvertent global assignments (uncovered by ESLint): @@ -307,10 +595,9 @@ obsolete; also move to head (after other stylesheets) `holder` was declared in too nested of a scope * Fix: Avoid `drawnPath` not defined error (currently adds as a global, but should be switching to modules anyways) -- Fix (jgraduate->jpicker): Fix Color val check when `name.length` is empty - (equal to "all") - Fix (jquery.jgraduate.js): Ensure `numstops` is present before check -- Fix (history.js) Relocation of rotational transform had undeclared variable (`elem`) +- Fix (history.js) Relocation of rotational transform had undeclared + variable (`elem`) - Fix (Editor): Restore save alert - Fix (Firefox svgutils.js): tspan (and textPath apparently) have no `getBBox` in Firefox, so recover (fixes FF issue with recalculate test 3: @@ -324,18 +611,16 @@ obsolete; also move to head (after other stylesheets) - Fix (HTML): Update assorted links, including using `https://` - Enhancement: ES6 modules (including jQuery plugins, extensions, locales, tests), along with Babel; make Node build routine for converting modular - source to non-modular + HTML source to non-modular - Enhancement: use `loadStylesheets` for modular stylesheet defining (but parallel loading) - Enhancement: Add `stylesheets` config for modular but parallel stylesheet loading with `@default` option for simple inclusion/exclusion of defaults (if not going with default). -- Enhancement: Further JSDoc (incomplete) - Enhancement (Project size): Remove now unused Python l10n scripts (#238) - Enhancement (Optimization): Compress images using imageoptim (and add npm script) (per #215) -- Enhancement (Editor): Use `https` (instead of `http`) for link default -- Enhancement: Throw Error objects instead of strings (including in jgraduate->jpicker) +- Enhancement (Editor): Use `https` (instead of `http`) for link placeholder - Enhancement: Make SpinButton plugin independent of SVGEdit via generic state object for `tool_scale` - Enhancement: Move `config-sample.js` out of `editor` directory @@ -351,68 +636,160 @@ npm script) (per #215) - Linting: 2 spaces, remove BOM, remove carriage returns, bad characters in Persian locale file - Linting (ESLint): Numerous changes +- Refactoring: Throw Error objects instead of strings (including in + jgraduate->jpicker) - Refactoring: Switch to ESLint in source - Refactoring: Move scripts to own files -- Refactoring: Clean up `svg-editor.html`: consistent indents; avoid extra lbs, avoid long lines +- Refactoring: Clean up `svg-editor.html`: consistent indents; avoid extra + lbs, avoid long lines - Refactoring: Avoid embedded API adding inline JavaScript listener - Refactoring: Move layers and context code to `draw.js` -- Refactoring: Move `pathActions` from `svgcanvas.js` (though preserve aliases to these methods on `canvas`) and `convertPath` from `svgutils.js` to `path.js` -- Refactoring: Move `getStrokedBBox` from `svgcanvas.js` (while keeping an alias) to `svgutils.js` (as `getStrokedBBoxDefaultVisible` to avoid conflict with existing) -- Refactoring/Linting: Enfore `no-extra-semi` and `quote-props` rules +- Refactoring: Move `pathActions` from `svgcanvas.js` (though preserve + aliases to these methods on `canvas`) and `convertPath` from + `svgutils.js` to `path.js` +- Refactoring: Move `getStrokedBBox` from `svgcanvas.js` (while keeping + an alias) to `svgutils.js` (as `getStrokedBBoxDefaultVisible` to avoid + conflict with existing) +- Refactoring/Linting: Enforce `no-extra-semi` and `quote-props` rules - Refactoring: Further avoidance of quotes on properties (as possible) - Refactoring: Use `class` in place of functions where intended as classes - Refactoring: Consistency and granularity in extensions imports -- Refactoring (ext-storage): Move locale info to own file imported by the extension (toward modularity; still should be split into separate files by language and *dynamically* imported, but we'll wait for better `import` support to refactor this) -- Refactoring: For imagelib, add local jQuery copy (using old 1.4.4 as had -been using from server) -- Refactoring: For MathJax, add local copy (using old 2.3 as had been using from -server); server had not been working - Refactoring: Remove `use strict` (implicit in modules) - Refactoring: Remove trailing whitespace, fix some code within comments - Refactoring: Expect `jQuery` global rather than `$` for better modularity -(also to adapt line later once available via `import`) + (also to adapt line later once available via `import`) - Refactoring: Prefer `const` (and then `let`) -- Refactoring: Add block scope keywords closer to first block in which they appear +- Refactoring: Add block scope keywords closer to first block in which + they appear - Refactoring: Use ES6 `class` -- Refactoring `$.isArray` -> `Array.isArray` and avoid some other jQuery core methods -with simple VanillaJS replacements +- Refactoring `$.isArray` -> `Array.isArray` and avoid some other jQuery + core methods with simple VanillaJS replacements - Refactoring: Use abbreviated object property syntax - Refactoring: Object destructuring -- Refactoring: Remove `uiStrings` contents in svg-editor.js (obtains from locale) +- Refactoring: Remove `uiStrings` contents in svg-editor.js (obtains + from locale) - Refactoring: Add favicon to embedded API file - Refactoring: Use arrow functions for brief functions (incomplete) - Refactoring: Use `Array.prototype.includes`/`String.prototype.includes`; -`String.prototype.startsWith`, `String.prototype.trim` -- Refactoring: Remove now unnecessary svgutils do/while resetting of variables + `String.prototype.startsWith`, `String.prototype.trim` +- Refactoring: Remove now unnecessary svgutils do/while resetting + of variables - Refactoring: Use shorthand methods for object literals (avoid ": function") - Refactoring: Avoid quoting object property keys where unnecessary -- Refactoring: Just do truthy/falsey check for lengths in place of comparison to 0 +- Refactoring: Just do truthy/falsey check for lengths in place of + comparison to 0 +- Refactoring: Make jpicker variable declaration indent bearable +- Refactoring (ext-storage): Move locale info to own file imported by the + extension (toward modularity; still should be split into separate files + by language and *dynamically* imported, but we'll wait for better + `import` support to refactor this) +- Refactoring (imagelib): Add local jQuery copy (using old 1.4.4 as had + been using from server) +- Refactoring (MathJax): Add local copy (using old 2.3 as had been using from + server); server had not been working - Refactoring (Testing): Avoid jQuery usage within most test files (defer script, also in preparation for future switch to ES6 modules for tests) -- Refactoring: Make jpicker variable declaration indent bearable - Refactoring (Linting): Finish svgcanvas.js - Docs: Mention in comment no longer an entry file as before - Docs: Migrate old config, extensions, and FAQ docs -- Build: Update minified version of spinbtn/jgraduate/jpicker per linted/improved files +- Docs: Further JSDoc (incomplete) +- Build: Update minified version of spinbtn/jgraduate/jpicker per + linted/improved files - Testing: Move JavaScript out of HTML to own files -- Testing: Add `node-static` to get tests working -- Testing: Fix timing of `all_tests.html` for ensuring expanding iframe size to fit content +- Testing: Fix timing of `all_tests.html` for ensuring expanding iframe + size to fit content - Testing: Add favicon to test files (also may avoid extra log in console) -- Testing: Update QUnit to 2.6.1 (node_modules) and Sinon to 5.0.8 (and add sinon-test at 2.1.3) and enforce eslint-plugin-qunit linting rules; update custom extensions -- Testing: Add node-static for automating (and accessing out-of-directory contents) +- Testing: Update QUnit to 2.6.1 (node_modules) and Sinon to 5.0.8 (and + add sinon-test at 2.1.3) and enforce eslint-plugin-qunit linting rules; + update custom extensions +- Testing: Add `node-static` for automating (and accessing out-of-directory + contents) - Testing: Avoid HTML attributes for styling - Testing: Add npm `test` script - Testing: Comment out unused jQuery SVG test - Testing: Add test1 and svgutils_performance_test to all tests page -- Testing: Due apparently to Path having not been a formal class, the test was calling it without `new`; refactored now with sufficient mock data to take into account it is a class +- Testing: Due apparently to Path having not been a formal class, the test + was calling it without `new`; refactored now with sufficient mock data + to take into account it is a class -# 3.0.0-alpha.1 +## 3.0.0-alpha.1 -(Only released on npm) +(Only released on npm for reserving name rather than being intended as a +testable release; the list below, however, does list the fixes it includes.) -- Provide `package.json` for npm to reserve name (reflecting current state of `master`) +- Fix: Rubberband box is not placed properly (left and top) for imported SVG + images when moved multiple times (#48; PR #49) +- Fix: Remove double-bind of keypresses Z and Y (#59; PR #60) +- Fix: For import SVG image leading to unattached dragtool (PR #7) +- Fix `browser.js` error triggering for `supportsPathInsertItemBefore` and + `supportsPathReplaceItem` when testing whether `replaceItem` and + `insertItemBefore` work, since paths must start with M commands +- Fix: Remove fix that cloned path segments and add tests to show it works; + PR #69 +- Fix: Preserve rx ry attributes on ellipse elements for batik compatibility; + do not strip `rx=0` and `ry=0` from ellipse elements as these values are not + default and hold a special meaning for ellipses (a value of 0 disables + rendering of the element); PR #71 +- Fix: Hidden font-size label/inability to set font size; #62; PR #83 +- Fix: Check for deleted defs after paste; pasting a line with markers + produces invalid SVG if original line was deleted; #82; PR #90 +- Fix: Update layers panel on programmatic call to `createLayer`; #104; + PR #106 +- Fix: Trigger `svgEditorReady` after the canvas is ready (PR #96) and + when opened through an iframe (#93; PR #127) +- Fix: Change the text input bindings to catch more input events (`input` as + well as `keyup`; e.g., trigger for `ALT+keycode`); PR #85 +- Fix: Layers in svgcanvas; PR #107 +- Fix: `createSVGRect()` in `getIntersectionList`; `createSVGRect()` does not + have parameters, they must be set on the object after; PR #138 +- Fix: Resizing an element would set `stroke="null"` on it; PR #142 +- Fix: Importing complex paths (paths with several "M/m" and "Z/z"); PR #195 +- Fix (Firefox 59): Update `pathseg.js` to latest version to fix; #216; PR #217 +- Fix (Firefox): Multiselect not working after zoom (#55; PR #56) +- Fix (Chrome/Opera): No longer saving or exporting in Chrome >= 60; #193; + PR #201 +- Fix (Chrome): Hide Overview panel in Chrome < 49 (rendering and performance + issues); see #26 and ; + PR #44 and #46 +- Fix (IE, Chrome): Some browsers require objects passed to `getInsectionList` + to be of correct the type; PR #67 +- Fix (IE11): `NoModificationAllowedError` upon selecting multiple elements + (#54, PR #57) +- Fix (Browser-specific): Improve `supportsNativeTransformLists` detection + beyond Firefox; PR #158 +- Fix (Browser-specific): Overcome browsers blocking data URIs by Blob URLs + where available for export; #222; PR #224 +- Enhancement: Add ability to set SVG drawings without adding to the undo + stack; PR #208 +- Enhancement: Clipboard that works across tabs and windows; PR #206 +- Enhancement: Add config options for text (font size and family, + stroke width); PR #91 +- Enhancement: Expose current zoom level (`getSnapToGrid`) through canvas for + extensions; PR #87 +- Enhancement: Insist on "image" mode for select image dialog to show, + allowing extensions to add images without this behavior; PR #86 +- Enhancement: Log errors from extensions to the browser console; PR #150 +- Enhancement (i18n): zh-CN language option; PR #125 +- Enhancement: Add `composer.json` to let PHP developers keep track of + svgedit on `packagist.org`; PR #174. +- Enhancement: `addSvgElementFromJson` to create text nodes and build + children; PR #130 +- Optimization: `getBBox` performance improvements; PR #103 +- Optimization: Loading time (by removing unnecessary code); PR #148 +- Localization: French (PR #132) and German (PR #111) updates +- Refactoring: Added `HistoryRecordingService` and separate `layer.js` + file; PR #107 +- Refactoring: Migrate more to `draw.js` and utilities; PR #109 +- Testing: Draw; PR #109 +- Docs: Fix reference link in comment; PR #105 +- Docs: Complete Markdown converted SvgCanvas docs; #92; PR #99 +- Docs: Fix documentation Markdown headings; PR #188 +- Git: Add `build` to ignore; PR #125 +- Build: Additions/changes for Makefile; PR #89 and #108 +- Build: Provide `package.json` for npm to reserve name (reflecting current + state of `master`) -# 2.8.1 (Ellipse) - December 2nd, 2015 +## 2.8.1 (Ellipse) - December 2nd, 2015 For a complete list of changes run: @@ -420,13 +797,16 @@ For a complete list of changes run: git log 81afaa9..5986f1e ``` -- Enhancement: Use `getIntersectionList` when available () -- Enhancement: Switched to https for all URLs () +- Enhancement: Use `getIntersectionList` when available + () +- Enhancement: Switched to https for all URLs + () - Enhancement: Minor administrative updates (docs/, README.md, author emails) -- Fix: Bug where all icons were broken in Safari () +- Fix: Bug where all icons were broken in Safari + () - Fix: Updated translations for "page" and "delete" in 57 locales. -# 2.8 (Ellipse) - November 24th, 2015 +## 2.8 (Ellipse) - November 24th, 2015 For a complete list of changes run: @@ -434,72 +814,149 @@ For a complete list of changes run: git log 4bb15e0..253b4bf ``` -- Enhancement (Experimental): Client-side PDF export (issue [#1156](https://code.google.com/p/svg-edit/issues/detail?id=1156)) (to data: URI) and server-side PDF export (where not supported in browser and using ext-server_opensave.js); uses [jsPDF](https://github.com/MrRio/jsPDF) library -- Enhancement: For image exports, provided "datauri" property to "exported" event. -- Enhancement: Allow config "exportWindowType" of value "new" or "same" to indicate whether to reuse the same export window upon subsequent exports +- Enhancement (Experimental): Client-side PDF export + (issue [#1156](https://code.google.com/p/svg-edit/issues/detail?id=1156)) + (to data: URI) and server-side PDF export (where not supported in browser + and using ext-server_opensave.js); uses + [jsPDF](https://github.com/MrRio/jsPDF) library +- Enhancement: For image exports, provided "datauri" property to "exported" + event. +- Enhancement: Allow config "exportWindowType" of value "new" or "same" to + indicate whether to reuse the same export window upon subsequent exports - Enhancement: Added openclipart support to imagelib extension - Enhancement: allow showGrid to be set before load -- Enhancement: Support loading of (properly URL encoded) non-base64 "data:image/svg+xml;utf8,"-style data URIs -- Enhancement: More clear naming of labels: "Open Image"->"Open SVG" and "Import SVG"->"Import Image" ( issue [#1206](https://code.google.com/p/svg-edit/issues/detail?id=1206)) -- Enhancement: Included reference to (repository-ignored) custom.css file which once created by the user, as with config.js, allows customization without modifying the repo (its main editor file) +- Enhancement: Support loading of (properly URL encoded) non-base64 + "data:image/svg+xml;utf8,"-style data URIs +- Enhancement: More clear naming of labels: "Open Image"->"Open SVG" and + "Import SVG"->"Import Image" ( issue [#1206](https://code.google.com/p/svg-edit/issues/detail?id=1206)) +- Enhancement: Included reference to (repository-ignored) `custom.css` file + which once created by the user, as with config.js, allows customization + without modifying the repo (its main editor file) - Enhancement: Updated Slovenian locale. - Demo enhancement: Support and demonstrate export in embedded editor - Upgrade: canvg version - Upgrade: Added PathSeg polyfill to workaround pathseg removal in browsers. - Fix: pathtool bug where paths were erroneously deleted. - Fix: Context menu did not work for groups. -- Fix: Avoid error in ungrouping function when no elements selected (was impacting MathJax "Ok" button). -- Fix: issue [#1205](https://code.google.com/p/svg-edit/issues/detail?id=1205) with Snap to Grid preventing editing +- Fix: Avoid error in ungrouping function when no elements selected (was + impacting MathJax "Ok" button). +- Fix: issue [#1205](https://code.google.com/p/svg-edit/issues/detail?id=1205) + with Snap to Grid preventing editing - Fix: bug in exportImage if svgEditor.setCustomHandlers calls made - Fix: Ensure "loading..." message closes upon completion or error - Fix: Ensure all dependencies are first available before canvg (and jsPDF) usage - Fix: Allow for empty images - Fix: Minor improvement in display when icon size is set to small - Fix: Based64-encoding issues with Unicode text (e.g., in data URIs or icons) -- Fix: 2.7 regression in filesave.php for SVG saving (used by ext-server_opensave.js when client doesn't support the download attribute) +- Fix: 2.7 regression in filesave.php for SVG saving (used by + `ext-server_opensave.js` when client doesn't support the download attribute) - Potentially breaking API changes (subject to further alteration before release): * Remove 2.7-deprecated "pngsave" (in favor of "exportImage") - * Data URIs must be properly URL encoded (use encodeURIComponent() on the "data:..." prefix and double encodeURIComponent() the remaining content) + * Data URIs must be properly URL encoded (use encodeURIComponent() on the + "data:..." prefix and double encodeURIComponent() the remaining content) * Remove "paramurl" parameter (use "url" or "source" with a data: URI instead) - * svgCanvas.rasterExport now takes an optional window name as the third argument, with the supplied name also being provided as a "exportWindowName" property on the object passed to the [exportImage](https://code.google.com/p/svg-edit/wiki/ExtensionDocs#svgEditor_public_methods) method optionally supplied to svgEditor.setCustomHandlers. - * Change 2.7 allowance of "PDF" as a type in the canvas "rasterExport" method and the "exported" event to instead be moved to the canvas "exportPDF" method and "exportedPDF" event respectively. + * svgCanvas.rasterExport now takes an optional window name as the third + argument, with the supplied name also being provided as a + "exportWindowName" property on the object passed to the [exportImage](https://code.google.com/p/svg-edit/wiki/ExtensionDocs#svgEditor_public_methods) method optionally supplied to svgEditor.setCustomHandlers. + * Change 2.7 allowance of "PDF" as a type in the canvas "rasterExport" + method and the "exported" event to instead be moved to the canvas + "exportPDF" method and "exportedPDF" event respectively. - -# 2.7.1 (applied to 2.7 branch) - April 17, 2014 +## 2.7.1 (applied to 2.7 branch) - April 17, 2014 - Fix important ID situation with embedded API - Update functions available to embedded editor -# 2.7 (Deltoid curve) - April 7th, 2014 +## 2.7 (Deltoid curve) - April 7th, 2014 -- Export to PNG, JPEG, BMP, WEBP (including quality control for JPEG/WEBP) for default editor and for the server_opensave extension +- Export to PNG, JPEG, BMP, WEBP (including quality control for JPEG/WEBP) + for default editor and for the server_opensave extension - Added Star, Polygon, and Panning Extensions r2318 r2319 r2333 -- Added non-default extension, ext-xdomain-messaging.js, moving cross-domain messaging code (as used by the embedded editor) out of core and requiring, when the extension IS included, that configuration (an array "allowedOrigins") be set in order to allow access by any domain (even same domain). -- Cause embedded editor to pass on URL arguments to the child editor (child iframe) -- Added default extension, ext-storage.js moving storage setting code into this (optional) extension; contains dialog to ask user whether they wish to utilize local storage for prefs and/or content; provides configuration options to tweak behaviors. -- Allow for a new file config.js within the editor folder (but not committed to SVN and ignored) which is always loaded and can be used for supplying configuration which happens early enough to affect URL or user storage configuration, in addition to extension behavior configuration. Provided config-sample.js to indicate types of configuration one could use (see also defaultPrefs, defaultExtensions, and defaultConfig within svg-editor.js ) -- Added configuration "preventAllURLConfig", "lockExtensions", and/or "preventURLContentLoading" for greater control of what can be configured via URL. -- Allow second argument object to setConfig containing "allowInitialUserOverride" booleans to allow for preference config in config.js to be overridden by URL or preferences in user storage; also can supply "overwrite" boolean in 2nd argument object if set to false to prevent overwriting of any prior-set configuration (URL config/pref setting occurs in this manner automatically for security reasons). -- Allow server_opensave extension to work wholly client-side (if browser supports the download attribute) +- Added non-default extension, ext-xdomain-messaging.js, moving cross-origin + messaging code (as used by the embedded editor) out of core and requiring, + when the extension IS included, that configuration (an array + "allowedOrigins") be set in order to allow access by any domain (even + same domain). +- Cause embedded editor to pass on URL arguments to the child editor + (child iframe) +- Added default extension, ext-storage.js moving storage setting code into + this (optional) extension; contains dialog to ask user whether they wish + to utilize local storage for prefs and/or content; provides configuration + options to tweak behaviors. +- Allow for a new file config.js within the editor folder (but not committed + to SVN and ignored) which is always loaded and can be used for supplying + configuration which happens early enough to affect URL or user storage + configuration, in addition to extension behavior configuration. Provided + `config-sample.js` to indicate types of configuration one could use + (see also `defaultPrefs`, `defaultExtensions`, and `defaultConfig` within + `svg-editor.js`) +- Added configuration `preventAllURLConfig`, `lockExtensions`, and/or + `preventURLContentLoading` for greater control of what can be configured + via URL. +- Allow second argument object to setConfig containing + `allowInitialUserOverride` booleans to allow for preference config in + `config.js` to be overridden by URL or preferences in user storage; + also can supply "overwrite" boolean in 2nd argument object if set to + `false` to prevent overwriting of any prior-set configuration (URL + config/pref setting occurs in this manner automatically for + security reasons). +- Allow server_opensave extension to work wholly client-side (if + browser supports the download attribute) - Added WebAppFind extension -- Added new php_savefile extension to replace outdated, non-functioning server-save code; requires user to create "savefile_config.php" file and do any validation there (for their own security) -- Use addEventListener for 'beforeunload' event so user can add their own if desired -- Changed locale behavior to always load from locale file, including English. Allow extensions to add new "langReady" callback which is passed an object with "lang" and "uiStrings" properties whenever the locale data is first made available or changed by the user (this callback will not be invoked until the locale data is available). Extensions can add strings to all locales and utilize this mechanism. +- Added new php_savefile extension to replace outdated, non-functioning + server-save code; requires user to create `savefile_config.php` file + and do any validation there (for their own security) +- Use addEventListener for 'beforeunload' event so user can add their + own if desired +- Changed locale behavior to always load from locale file, including + English. Allow extensions to add new `langReady` callback which is passed + an object with `lang` and `uiStrings` properties whenever the locale data + is first made available or changed by the user (this callback will not + be invoked until the locale data is available). Extensions can add + strings to all locales and utilize this mechanism. - Made fixes impacting path issues and also ext-connector.js -- Fixed a bug where the position number supplied on an extension object was too high (e.g., if too few other extensions were included, the extension might not show up because its position was set too high). +- Fixed a bug where the position number supplied on an extension object + was too high (e.g., if too few other extensions were included, + the extension might not show up because its position was set too high). - Added Polish locale - Zoom features - Make extension paths relative within extensions (issue 1184) - Security improvements and other fixes -- Embedded editor can now work same domain without JSON parsing and the consequent potential loss of arguments or return values. +- Embedded editor can now work same domain without JSON parsing and the + consequent potential loss of arguments or return values. - Potentially breaking API changes: - * Disallowed "extPath", "imgPath", "langPath", and "jGraduatePath" setting via URL and prevent cross-domain/cross-folder extensions being set by URL (security enhancement) - * Deprecated "pngsave" option called by setCustomHandlers() in favor of "exportImage" (to accommodate export of other image types). Second argument will now supply, in addition to "issues" and "svg", the properties "type" (currently 'PNG', 'JPEG', 'BMP', 'WEBP'), "mimeType", and "quality" (for 'JPEG' and 'WEBP' types). - * Default extensions will now always load (along with those supplied in the URL unless the latter is prohibited by configuration), so if you do not wish your old code to load all of the default extensions, you will need to add `&noDefaultExtensions=true` to the URL (or add equivalent configuration in config.js). ext-overview_window.js can now be excluded though it is still a default. - * Preferences and configuration options must be within the list supplied within svg-editor.js (should include those of all documented extensions). - * Embedded messaging will no longer work by default for privacy/data integrity reasons. One must include the "ext-xdomain-messaging.js" extension and supply an array configuration item, "allowedOrigins" with potential values including: "\*" (to allow all domains--strongly discouraged!), "null" as a string to allow file:// access, window.location.origin (to allow same domain access), or specific trusted origins. The embedded editor works without the extension if the main editor is on the same domain, but if cross-domain control is needed, the "allowedOrigins" array must be supplied by a call to svgEditor.setConfig({allowedOrigins: [origin1, origin2, etc.]}) in the new config.js file. + * Disallowed "extPath", "imgPath", "langPath", and "jGraduatePath" + setting via URL and prevent cross-origin/cross-folder extensions + being set by URL (security enhancement) + * Deprecated "pngsave" option called by setCustomHandlers() in favor + of "exportImage" (to accommodate export of other image types). + Second argument will now supply, in addition to "issues" and + "svg", the properties "type" (currently 'PNG', 'JPEG', 'BMP', + 'WEBP'), "mimeType", and "quality" (for 'JPEG' and 'WEBP' types). + * Default extensions will now always load (along with those supplied + in the URL unless the latter is prohibited by configuration), so + if you do not wish your old code to load all of the default + extensions, you will need to add `&noDefaultExtensions=true` to the + URL (or add equivalent configuration in `config.js`). + `ext-overview_window.js` can now be excluded though it is still + a default. + * Preferences and configuration options must be within the list supplied + within `svg-editor.js` (should include those of all documented + extensions). + * Embedded messaging will no longer work by default for privacy/data + integrity reasons. One must include the `ext-xdomain-messaging.js` + extension and supply an array configuration item, `allowedOrigins` + with potential values including: "\*" (to allow all + origins--strongly discouraged!), "null" as a string to allow + `file:///` access, window.location.origin (to allow same domain + access), or specific trusted origins. The embedded editor works + without the extension if the main editor is on the same domain, + but if cross-origin control is needed, the `allowedOrigins` array + must be supplied by a call to + `svgEditor.setConfig({allowedOrigins: [origin1, origin2, etc.]})` + in the new `config.js` file. -# 2.6 (Cycloid) - January 15th, 2013 +## 2.6 (Cycloid) - January 15th, 2013 - Support for Internet Explorer 9 - Context menu @@ -512,9 +969,9 @@ git log 4bb15e0..253b4bf - Basic Server-based tools for file opening/saving - In-group editing - Cut/Copy/Paste -- full list: http://code.google.com/p/svg-edit/issues/list?can=1&q=label%3ANeededFor-2.6 +- full list: -# 2.5 - June 15, 2010 +## 2.5 - June 15, 2010 - Open Local Files (Firefox 3.6+ only) - Import SVG into Drawing (Firefox 3.6+ only) @@ -539,7 +996,7 @@ git log 4bb15e0..253b4bf - Inline text editing - Line draw snapping with Shift key -# 2.4 - January 11, 2010 +## 2.4 - January 11, 2010 - Zoom - Layers @@ -561,7 +1018,7 @@ git log 4bb15e0..253b4bf - Text fields for all attributes - Title element -# 2.3 - September 08, 2009 +## 2.3 - September 08, 2009 - Align Objects - Rotate Objects @@ -571,7 +1028,7 @@ git log 4bb15e0..253b4bf - Gradient picking - Polygon Mode (Path Editing, Phase 1) -# 2.2 - July 08, 2009 +## 2.2 - July 08, 2009 - Multiselect Mode - Undo/Redo Actions @@ -582,7 +1039,7 @@ git log 4bb15e0..253b4bf - Resizing of the SVG canvas - Upgraded to jPicker 1.0.8 -# 2.1 - June 17, 2009 +## 2.1 - June 17, 2009 - tooltips added to all UI elements - fix flyout menus @@ -591,7 +1048,7 @@ git log 4bb15e0..253b4bf - fix flyouts when using color picker - change license from GPLv2 to Apache License v2.0 - replaced Farbtastic with jPicker, because of the license issues -- removed dependency on svgcanvas.svg, now created in JavaScript +- removed dependency on `svgcanvas.svg`, now created in JavaScript - added Select tool - using jQuery hosted by Google instead of local version - allow dragging of elements @@ -602,12 +1059,12 @@ git log 4bb15e0..253b4bf - added keystroke shortcuts for all tools - move to top/bottom -# 2.0 - June 03, 2009 +## 2.0 - June 03, 2009 - rewritten SVG-edit, so now it uses OOP - draw ellipse, square - created HTML interface similar to Inkscape -# 1.0 - February 06, 2009 +## 1.0 - February 06, 2009 - SVG-Edit released diff --git a/Makefile b/Makefile deleted file mode 100644 index 3a50532d..00000000 --- a/Makefile +++ /dev/null @@ -1,106 +0,0 @@ -NAME=svg-edit -VERSION=2.8.1 -PACKAGE=$(NAME)-$(VERSION) -MAKEDOCS=naturaldocs/NaturalDocs -CLOSURE=build/tools/closure-compiler.jar -ZIP=zip - -# All files that will be compiled by the Closure compiler. - -JS_FILES=\ - namespaces.js \ - jQuery.attr.js \ - contextmenu/jQuery.contextMenu.js \ - svgpathseg.js \ - browser.js \ - svgtransformlist.js \ - math.js \ - units.js \ - utilities.js \ - sanitize.js \ - history.js \ - historyrecording.js \ - coords.js \ - recalculate.js \ - select.js \ - draw.js \ - layer.js \ - path.js \ - svgcanvas.js \ - svg-editor.js \ - locale/locale.js \ - contextmenu.js - -JS_INPUT_FILES=$(addprefix editor/, $(JS_FILES)) -JS_BUILD_FILES=$(addprefix build/$(PACKAGE)/, $(JS_FILES)) -CLOSURE_JS_ARGS=$(addprefix --js , $(JS_INPUT_FILES)) -COMPILED_JS=editor/svgedit.compiled.js - -all: release firefox opera - -# The build directory relies on the JS being compiled. -build/$(PACKAGE): $(COMPILED_JS) - rm -rf config - mkdir config - if [ -x $(MAKEDOCS) ] ; then $(MAKEDOCS) -i editor/ -o html docs/ -p config/ -oft -r ; fi - - # Make build directory and copy all editor contents into it - mkdir -p build/$(PACKAGE) - cp -r editor/* build/$(PACKAGE) - - # Remove all hidden .svn directories - -find build/$(PACKAGE) -name .svn -type d | xargs rm -rf {} \; - - # Create the release version of the main HTML file. - build/tools/ship.py --i=editor/svg-editor.html --on=svg_edit_release > build/$(PACKAGE)/svg-editor.html - -# NOTE: Some files are not ready for the Closure compiler: (jquery) -# NOTE: Our code safely compiles under SIMPLE_OPTIMIZATIONS -# NOTE: Our code is *not* ready for ADVANCED_OPTIMIZATIONS -# NOTE: WHITESPACE_ONLY and --formatting PRETTY_PRINT is helpful for debugging. -$(COMPILED_JS): - java -jar $(CLOSURE) \ - --compilation_level SIMPLE_OPTIMIZATIONS \ - $(CLOSURE_JS_ARGS) \ - --js_output_file $(COMPILED_JS) - -compile: $(COMPILED_JS) - -release: build/$(PACKAGE) - cd build ; $(ZIP) $(PACKAGE).zip -r $(PACKAGE) ; cd .. - tar -z -c -f build/$(PACKAGE)-src.tar.gz \ - --exclude='\.svn' \ - --exclude='build/*' \ - . - -firefox: build/$(PACKAGE) - mkdir -p build/firefox/content/editor - cp -r firefox-extension/* build/firefox - rm -rf build/firefox/content/.svn - cp -r build/$(PACKAGE)/* build/firefox/content/editor - rm -f build/firefox/content/editor/embedapi.js - cd build/firefox ; $(ZIP) ../$(PACKAGE).xpi -r * ; cd ../.. - -opera: build/$(PACKAGE) - mkdir -p build/opera/editor - cp opera-widget/* build/opera - cp -r build/$(PACKAGE)/* build/opera/editor - cd build/opera ; $(ZIP) ../$(PACKAGE).wgt -r * ; cd ../.. - -chrome: - mkdir -p build/svgedit_app - cp -a chrome-app/* build/svgedit_app - cd build ; $(ZIP) -r $(PACKAGE)-crx.zip svgedit_app ; rm -rf svgedit_app; cd .. - -jgraduate: - java -jar $(CLOSURE) --js editor/jgraduate/jquery.jGraduate.js --js_output_file editor/jgraduate/jquery.jgraduate.min.js -clean: - rm -rf config - rm -rf build/$(PACKAGE) - rm -rf build/firefox - rm -rf build/opera - rm -rf build/$(PACKAGE).zip - rm -rf build/$(PACKAGE)-src.tar.gz - rm -rf build/$(PACKAGE).xpi - rm -rf build/$(PACKAGE).wgt - rm -rf $(COMPILED_JS) diff --git a/README.md b/README.md index e7b9a299..0981d29b 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,23 @@ # ![alt text](https://svg-edit.github.io/svgedit/images/logo48x48.svg "svg-edit logo of a pencil") SVG-edit +[![Dependencies](https://img.shields.io/david/SVG-Edit/svgedit.svg)](https://david-dm.org/SVG-Edit/svgedit) +[![devDependencies](https://img.shields.io/david/dev/SVG-Edit/svgedit.svg)](https://david-dm.org/SVG-Edit/svgedit?type=dev) +[![npm](http://img.shields.io/npm/v/svgedit.svg)](https://www.npmjs.com/package/svgedit) +[![License](https://img.shields.io/npm/l/svgedit.svg)](LICENSE-MIT) +[![Code Quality: Javascript](https://img.shields.io/lgtm/grade/javascript/g/SVG-Edit/svgedit.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/SVG-Edit/svgedit/context:javascript) +[![Total Alerts](https://img.shields.io/lgtm/alerts/g/SVG-Edit/svgedit.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/SVG-Edit/svgedit/alerts) + SVG-edit is a fast, web-based, JavaScript-driven SVG drawing editor that works in any modern browser. +## Help wanted + +While we have made some recent releases to SVG-edit for bug fixes, +refactoring and documentation to make the codebase more maintainable, the +core developers responsible for the bulk of the drawing features are no +longer active with the project, so we would love others familiar with SVG +to join the project. + ## Demo ### [Try SVG-edit here](https://svg-edit.github.io/svgedit/releases/latest/editor/svg-editor.html) @@ -10,9 +25,12 @@ works in any modern browser. See the [latest release](https://svg-edit.github.io/svgedit/releases/latest/editor/svg-editor.html) (or its [ES6-Module](https://svg-edit.github.io/svgedit/releases/latest/editor/svg-editor.html) version, which requires a modern browser). -Also available as a download in [releases](https://github.com/SVG-Edit/svgedit/releases). +You may also try it at (which +redirects to a versioned URL). -For testing the latest version in `master`, you may use or +You may also obtain URLs for specific [releases](https://github.com/SVG-Edit/svgedit/releases). + +For testing the latest version in `master`, you may use . ## Installation @@ -28,6 +46,21 @@ For testing the latest version in `master`, you may use ``` +Note that if you want support for the following browsers, you will at least +need some polyfills. + +For Android Browser 4.4.3-4.4.4, you will need at least `fetch`. + +For the following, you will need at least `URL`, `Promise`, and `fetch`: + +- IE <= 11 +- IE Mobile +- Opera Mini +- Blackberry Browser <= 10 + +And for still older browsers (e.g., IE 8), you will at minimum need a +`querySelector` polyfill. + ### Integrating SVG-edit into your own npm package These steps are only needed if you wish to set up your own npm package @@ -82,6 +115,17 @@ incorporating SVGEdit. ## Recent news +- 2018-12-13 Published 4.2.0 (Chinese (simplified) and Russian locale updates; retaining lines with grid mode) +- 2018-11-29 Published 4.1.0 (Fix for hyphenated locales, svgcanvas distributions) +- 2018-11-16 Published 4.0.0/4.0.1 (Move to Promise-based APIs) +- 2018-11-01 Published 3.2.0 (Update qunit to resolve security vulnerability of a dependency) +- 2018-10-25 Published 3.1.1 (Fix for saving SVG on Firefox) +- 2018-10-24 Published 3.1.0 (Redirect on modular page for non-module-support; + versions document (for migrating)) +- 2018-10-22 Published 3.0.1 (Revert fix affecting polygon selection) +- 2018-10-21 Published 3.0.0 (misc. improvements including centering canvas and + key locale fixes since last RC) +- 2018-09-30 Published 3.0.0-rc.3 with security and other fixes - 2018-07-31 Published 3.0.0-rc.2 with misc. fixes - 2018-07-19 Published 3.0.0-rc.1 allowing for extensions and locales to be expressed as modules diff --git a/build-html.js b/build-html.js index 4af6825c..6898f823 100644 --- a/build-html.js +++ b/build-html.js @@ -1,5 +1,5 @@ /* eslint-env node */ -const fs = require('promise-fs'); +import fs from 'promise-fs'; const filesAndReplacements = [ { @@ -32,6 +32,22 @@ const filesAndReplacements = [ [ '', '' + ], + [ + '', + '' + ] + ] + }, + // Now that file has copied, we can replace the DOCTYPE in xdomain + { + input: 'editor/xdomain-svg-editor-es.html', + output: 'editor/xdomain-svg-editor-es.html', + replacements: [ + [ + '', + ` +` ] ] }, @@ -55,6 +71,33 @@ const filesAndReplacements = [ [ '', '' + ], + [ + '', + '' + ] + ] + }, + { + input: 'editor/extensions/imagelib/openclipart-es.html', + output: 'editor/extensions/imagelib/openclipart.html', + replacements: [ + [ + '', + ` +` + ], + [ + '', + '' + ], + [ + '', + '' + ], + [ + '', + '' ] ] }, @@ -70,32 +113,36 @@ const filesAndReplacements = [ [ '', '' + ], + [ + '', + '' ] ] } ]; -filesAndReplacements.reduce((p, {input, output, replacements}) => { - return p.then(async () => { - let data; - try { - data = await fs.readFile(input, 'utf8'); - } catch (err) { - console.log(`Error reading ${input} file`, err); - } +(async () => { +await filesAndReplacements.reduce(async (p, {input, output, replacements}) => { + await p; + let data; + try { + data = await fs.readFile(input, 'utf8'); + } catch (err) { + console.log(`Error reading ${input} file`, err); // eslint-disable-line no-console + } - data = replacements.reduce((s, [find, replacement]) => { - return s.replace(find, replacement); - }, data); + data = replacements.reduce((s, [fnd, replacement]) => { + return s.replace(fnd, replacement); + }, data); - try { - await fs.writeFile(output, data); - } catch (err) { - console.log(`Error writing file: ${err}`, err); - return; - } - console.log(`Completed file ${input} rewriting!`); - }); -}, Promise.resolve()).then(() => { - console.log('Finished!'); -}); + try { + await fs.writeFile(output, data); + } catch (err) { + console.log(`Error writing file: ${err}`, err); // eslint-disable-line no-console + return; + } + console.log(`Completed file ${input} rewriting!`); // eslint-disable-line no-console +}, Promise.resolve()); +console.log('Finished!'); // eslint-disable-line no-console +})(); diff --git a/demos/canvas.html b/demos/canvas.html index d5d9ee3d..a1219137 100644 --- a/demos/canvas.html +++ b/demos/canvas.html @@ -6,6 +6,7 @@ + @@ -24,7 +25,7 @@ - + + + diff --git a/editor/extensions/imagelib/index.html b/editor/extensions/imagelib/index.html index d9ea0793..522bad0b 100644 --- a/editor/extensions/imagelib/index.html +++ b/editor/extensions/imagelib/index.html @@ -5,8 +5,9 @@ - - - + + + diff --git a/editor/extensions/imagelib/index.js b/editor/extensions/imagelib/index.js index 68d33547..6521469a 100644 --- a/editor/extensions/imagelib/index.js +++ b/editor/extensions/imagelib/index.js @@ -18,9 +18,9 @@ $('a').click(function () { name: $(this).text(), id: href }); - if (!this.href.includes('.svg')) { + if (!href.includes('.svg')) { const img = new Image(); - img.onload = function () { + img.addEventListener('load', function () { const canvas = document.createElement('canvas'); canvas.width = this.width; canvas.height = this.height; @@ -31,12 +31,13 @@ $('a').click(function () { try { data = canvas.toDataURL(); } catch (err) { - // This fails in Firefox with file:// URLs :( - alert('Data URL conversion failed: ' + err); + // This fails in Firefox with `file:///` URLs :( + // Todo: This could use a generic alert library instead + alert('Data URL conversion failed: ' + err); // eslint-disable-line no-alert data = ''; } post({href, data}); - }; + }); img.src = href; } else { // Do ajax request for image's href value diff --git a/editor/extensions/imagelib/jquery.min.js b/editor/extensions/imagelib/jquery.min.js deleted file mode 100644 index 8f3ca2e2..00000000 --- a/editor/extensions/imagelib/jquery.min.js +++ /dev/null @@ -1,167 +0,0 @@ -/*! - * jQuery JavaScript Library v1.4.4 - * http://jquery.com/ - * - * Copyright 2010, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2010, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Thu Nov 11 19:04:53 2010 -0500 - */ -(function(E,B){function ka(a,b,d){if(d===B&&a.nodeType===1){d=a.getAttribute("data-"+b);if(typeof d==="string"){try{d=d==="true"?true:d==="false"?false:d==="null"?null:!c.isNaN(d)?parseFloat(d):Ja.test(d)?c.parseJSON(d):d}catch(e){}c.data(a,b,d)}else d=B}return d}function U(){return false}function ca(){return true}function la(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function Ka(a){var b,d,e,f,h,l,k,o,x,r,A,C=[];f=[];h=c.data(this,this.nodeType?"events":"__events__");if(typeof h==="function")h= -h.events;if(!(a.liveFired===this||!h||!h.live||a.button&&a.type==="click")){if(a.namespace)A=RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)");a.liveFired=this;var J=h.live.slice(0);for(k=0;kd)break;a.currentTarget=f.elem;a.data=f.handleObj.data;a.handleObj=f.handleObj;A=f.handleObj.origHandler.apply(f.elem,arguments);if(A===false||a.isPropagationStopped()){d=f.level;if(A===false)b=false;if(a.isImmediatePropagationStopped())break}}return b}}function Y(a,b){return(a&&a!=="*"?a+".":"")+b.replace(La, -"`").replace(Ma,"&")}function ma(a,b,d){if(c.isFunction(b))return c.grep(a,function(f,h){return!!b.call(f,h,f)===d});else if(b.nodeType)return c.grep(a,function(f){return f===b===d});else if(typeof b==="string"){var e=c.grep(a,function(f){return f.nodeType===1});if(Na.test(b))return c.filter(b,e,!d);else b=c.filter(b,e)}return c.grep(a,function(f){return c.inArray(f,b)>=0===d})}function na(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var e=c.data(a[d++]),f=c.data(this, -e);if(e=e&&e.events){delete f.handle;f.events={};for(var h in e)for(var l in e[h])c.event.add(this,h,e[h][l],e[h][l].data)}}})}function Oa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function oa(a,b,d){var e=b==="width"?a.offsetWidth:a.offsetHeight;if(d==="border")return e;c.each(b==="width"?Pa:Qa,function(){d||(e-=parseFloat(c.css(a,"padding"+this))||0);if(d==="margin")e+=parseFloat(c.css(a, -"margin"+this))||0;else e-=parseFloat(c.css(a,"border"+this+"Width"))||0});return e}function da(a,b,d,e){if(c.isArray(b)&&b.length)c.each(b,function(f,h){d||Ra.test(a)?e(a,h):da(a+"["+(typeof h==="object"||c.isArray(h)?f:"")+"]",h,d,e)});else if(!d&&b!=null&&typeof b==="object")c.isEmptyObject(b)?e(a,""):c.each(b,function(f,h){da(a+"["+f+"]",h,d,e)});else e(a,b)}function S(a,b){var d={};c.each(pa.concat.apply([],pa.slice(0,b)),function(){d[this]=a});return d}function qa(a){if(!ea[a]){var b=c("<"+ -a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d==="")d="block";ea[a]=d}return ea[a]}function fa(a){return c.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var t=E.document,c=function(){function a(){if(!b.isReady){try{t.documentElement.doScroll("left")}catch(j){setTimeout(a,1);return}b.ready()}}var b=function(j,s){return new b.fn.init(j,s)},d=E.jQuery,e=E.$,f,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,l=/\S/,k=/^\s+/,o=/\s+$/,x=/\W/,r=/\d/,A=/^<(\w+)\s*\/?>(?:<\/\1>)?$/, -C=/^[\],:{}\s]*$/,J=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,w=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,I=/(?:^|:|,)(?:\s*\[)+/g,L=/(webkit)[ \/]([\w.]+)/,g=/(opera)(?:.*version)?[ \/]([\w.]+)/,i=/(msie) ([\w.]+)/,n=/(mozilla)(?:.*? rv:([\w.]+))?/,m=navigator.userAgent,p=false,q=[],u,y=Object.prototype.toString,F=Object.prototype.hasOwnProperty,M=Array.prototype.push,N=Array.prototype.slice,O=String.prototype.trim,D=Array.prototype.indexOf,R={};b.fn=b.prototype={init:function(j, -s){var v,z,H;if(!j)return this;if(j.nodeType){this.context=this[0]=j;this.length=1;return this}if(j==="body"&&!s&&t.body){this.context=t;this[0]=t.body;this.selector="body";this.length=1;return this}if(typeof j==="string")if((v=h.exec(j))&&(v[1]||!s))if(v[1]){H=s?s.ownerDocument||s:t;if(z=A.exec(j))if(b.isPlainObject(s)){j=[t.createElement(z[1])];b.fn.attr.call(j,s,true)}else j=[H.createElement(z[1])];else{z=b.buildFragment([v[1]],[H]);j=(z.cacheable?z.fragment.cloneNode(true):z.fragment).childNodes}return b.merge(this, -j)}else{if((z=t.getElementById(v[2]))&&z.parentNode){if(z.id!==v[2])return f.find(j);this.length=1;this[0]=z}this.context=t;this.selector=j;return this}else if(!s&&!x.test(j)){this.selector=j;this.context=t;j=t.getElementsByTagName(j);return b.merge(this,j)}else return!s||s.jquery?(s||f).find(j):b(s).find(j);else if(b.isFunction(j))return f.ready(j);if(j.selector!==B){this.selector=j.selector;this.context=j.context}return b.makeArray(j,this)},selector:"",jquery:"1.4.4",length:0,size:function(){return this.length}, -toArray:function(){return N.call(this,0)},get:function(j){return j==null?this.toArray():j<0?this.slice(j)[0]:this[j]},pushStack:function(j,s,v){var z=b();b.isArray(j)?M.apply(z,j):b.merge(z,j);z.prevObject=this;z.context=this.context;if(s==="find")z.selector=this.selector+(this.selector?" ":"")+v;else if(s)z.selector=this.selector+"."+s+"("+v+")";return z},each:function(j,s){return b.each(this,j,s)},ready:function(j){b.bindReady();if(b.isReady)j.call(t,b);else q&&q.push(j);return this},eq:function(j){return j=== --1?this.slice(j):this.slice(j,+j+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(N.apply(this,arguments),"slice",N.call(arguments).join(","))},map:function(j){return this.pushStack(b.map(this,function(s,v){return j.call(s,v,s)}))},end:function(){return this.prevObject||b(null)},push:M,sort:[].sort,splice:[].splice};b.fn.init.prototype=b.fn;b.extend=b.fn.extend=function(){var j,s,v,z,H,G=arguments[0]||{},K=1,Q=arguments.length,ga=false; -if(typeof G==="boolean"){ga=G;G=arguments[1]||{};K=2}if(typeof G!=="object"&&!b.isFunction(G))G={};if(Q===K){G=this;--K}for(;K0))if(q){var s=0,v=q;for(q=null;j=v[s++];)j.call(t,b);b.fn.trigger&&b(t).trigger("ready").unbind("ready")}}},bindReady:function(){if(!p){p=true;if(t.readyState==="complete")return setTimeout(b.ready,1);if(t.addEventListener){t.addEventListener("DOMContentLoaded",u,false);E.addEventListener("load",b.ready,false)}else if(t.attachEvent){t.attachEvent("onreadystatechange",u);E.attachEvent("onload", -b.ready);var j=false;try{j=E.frameElement==null}catch(s){}t.documentElement.doScroll&&j&&a()}}},isFunction:function(j){return b.type(j)==="function"},isArray:Array.isArray||function(j){return b.type(j)==="array"},isWindow:function(j){return j&&typeof j==="object"&&"setInterval"in j},isNaN:function(j){return j==null||!r.test(j)||isNaN(j)},type:function(j){return j==null?String(j):R[y.call(j)]||"object"},isPlainObject:function(j){if(!j||b.type(j)!=="object"||j.nodeType||b.isWindow(j))return false;if(j.constructor&& -!F.call(j,"constructor")&&!F.call(j.constructor.prototype,"isPrototypeOf"))return false;for(var s in j);return s===B||F.call(j,s)},isEmptyObject:function(j){for(var s in j)return false;return true},error:function(j){throw j;},parseJSON:function(j){if(typeof j!=="string"||!j)return null;j=b.trim(j);if(C.test(j.replace(J,"@").replace(w,"]").replace(I,"")))return E.JSON&&E.JSON.parse?E.JSON.parse(j):(new Function("return "+j))();else b.error("Invalid JSON: "+j)},noop:function(){},globalEval:function(j){if(j&& -l.test(j)){var s=t.getElementsByTagName("head")[0]||t.documentElement,v=t.createElement("script");v.type="text/javascript";if(b.support.scriptEval)v.appendChild(t.createTextNode(j));else v.text=j;s.insertBefore(v,s.firstChild);s.removeChild(v)}},nodeName:function(j,s){return j.nodeName&&j.nodeName.toUpperCase()===s.toUpperCase()},each:function(j,s,v){var z,H=0,G=j.length,K=G===B||b.isFunction(j);if(v)if(K)for(z in j){if(s.apply(j[z],v)===false)break}else for(;H
a";var f=d.getElementsByTagName("*"),h=d.getElementsByTagName("a")[0],l=t.createElement("select"), -k=l.appendChild(t.createElement("option"));if(!(!f||!f.length||!h)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(h.getAttribute("style")),hrefNormalized:h.getAttribute("href")==="/a",opacity:/^0.55$/.test(h.style.opacity),cssFloat:!!h.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:k.selected,deleteExpando:true,optDisabled:false,checkClone:false, -scriptEval:false,noCloneEvent:true,boxModel:null,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableHiddenOffsets:true};l.disabled=true;c.support.optDisabled=!k.disabled;b.type="text/javascript";try{b.appendChild(t.createTextNode("window."+e+"=1;"))}catch(o){}a.insertBefore(b,a.firstChild);if(E[e]){c.support.scriptEval=true;delete E[e]}try{delete b.test}catch(x){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function r(){c.support.noCloneEvent= -false;d.detachEvent("onclick",r)});d.cloneNode(true).fireEvent("onclick")}d=t.createElement("div");d.innerHTML="";a=t.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var r=t.createElement("div");r.style.width=r.style.paddingLeft="1px";t.body.appendChild(r);c.boxModel=c.support.boxModel=r.offsetWidth===2;if("zoom"in r.style){r.style.display="inline";r.style.zoom= -1;c.support.inlineBlockNeedsLayout=r.offsetWidth===2;r.style.display="";r.innerHTML="
";c.support.shrinkWrapBlocks=r.offsetWidth!==2}r.innerHTML="
t
";var A=r.getElementsByTagName("td");c.support.reliableHiddenOffsets=A[0].offsetHeight===0;A[0].style.display="";A[1].style.display="none";c.support.reliableHiddenOffsets=c.support.reliableHiddenOffsets&&A[0].offsetHeight===0;r.innerHTML="";t.body.removeChild(r).style.display= -"none"});a=function(r){var A=t.createElement("div");r="on"+r;var C=r in A;if(!C){A.setAttribute(r,"return;");C=typeof A[r]==="function"}return C};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=f=h=null}})();var ra={},Ja=/^(?:\{.*\}|\[.*\])$/;c.extend({cache:{},uuid:0,expando:"jQuery"+c.now(),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},data:function(a,b,d){if(c.acceptData(a)){a=a==E?ra:a;var e=a.nodeType,f=e?a[c.expando]:null,h= -c.cache;if(!(e&&!f&&typeof b==="string"&&d===B)){if(e)f||(a[c.expando]=f=++c.uuid);else h=a;if(typeof b==="object")if(e)h[f]=c.extend(h[f],b);else c.extend(h,b);else if(e&&!h[f])h[f]={};a=e?h[f]:h;if(d!==B)a[b]=d;return typeof b==="string"?a[b]:a}}},removeData:function(a,b){if(c.acceptData(a)){a=a==E?ra:a;var d=a.nodeType,e=d?a[c.expando]:a,f=c.cache,h=d?f[e]:e;if(b){if(h){delete h[b];d&&c.isEmptyObject(h)&&c.removeData(a)}}else if(d&&c.support.deleteExpando)delete a[c.expando];else if(a.removeAttribute)a.removeAttribute(c.expando); -else if(d)delete f[e];else for(var l in a)delete a[l]}},acceptData:function(a){if(a.nodeName){var b=c.noData[a.nodeName.toLowerCase()];if(b)return!(b===true||a.getAttribute("classid")!==b)}return true}});c.fn.extend({data:function(a,b){var d=null;if(typeof a==="undefined"){if(this.length){var e=this[0].attributes,f;d=c.data(this[0]);for(var h=0,l=e.length;h-1)return true;return false},val:function(a){if(!arguments.length){var b=this[0];if(b){if(c.nodeName(b,"option")){var d=b.attributes.value;return!d||d.specified?b.value:b.text}if(c.nodeName(b,"select")){var e=b.selectedIndex;d=[];var f=b.options;b=b.type==="select-one"; -if(e<0)return null;var h=b?e:0;for(e=b?e+1:f.length;h=0;else if(c.nodeName(this,"select")){var A=c.makeArray(r);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),A)>=0});if(!A.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true}, -attr:function(a,b,d,e){if(!a||a.nodeType===3||a.nodeType===8)return B;if(e&&b in c.attrFn)return c(a)[b](d);e=a.nodeType!==1||!c.isXMLDoc(a);var f=d!==B;b=e&&c.props[b]||b;var h=Ta.test(b);if((b in a||a[b]!==B)&&e&&!h){if(f){b==="type"&&Ua.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");if(d===null)a.nodeType===1&&a.removeAttribute(b);else a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&& -b.specified?b.value:Va.test(a.nodeName)||Wa.test(a.nodeName)&&a.href?0:B;return a[b]}if(!c.support.style&&e&&b==="style"){if(f)a.style.cssText=""+d;return a.style.cssText}f&&a.setAttribute(b,""+d);if(!a.attributes[b]&&a.hasAttribute&&!a.hasAttribute(b))return B;a=!c.support.hrefNormalized&&e&&h?a.getAttribute(b,2):a.getAttribute(b);return a===null?B:a}});var X=/\.(.*)$/,ia=/^(?:textarea|input|select)$/i,La=/\./g,Ma=/ /g,Xa=/[^\w\s.|`]/g,Ya=function(a){return a.replace(Xa,"\\$&")},ua={focusin:0,focusout:0}; -c.event={add:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(c.isWindow(a)&&a!==E&&!a.frameElement)a=E;if(d===false)d=U;else if(!d)return;var f,h;if(d.handler){f=d;d=f.handler}if(!d.guid)d.guid=c.guid++;if(h=c.data(a)){var l=a.nodeType?"events":"__events__",k=h[l],o=h.handle;if(typeof k==="function"){o=k.handle;k=k.events}else if(!k){a.nodeType||(h[l]=h=function(){});h.events=k={}}if(!o)h.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem, -arguments):B};o.elem=a;b=b.split(" ");for(var x=0,r;l=b[x++];){h=f?c.extend({},f):{handler:d,data:e};if(l.indexOf(".")>-1){r=l.split(".");l=r.shift();h.namespace=r.slice(0).sort().join(".")}else{r=[];h.namespace=""}h.type=l;if(!h.guid)h.guid=d.guid;var A=k[l],C=c.event.special[l]||{};if(!A){A=k[l]=[];if(!C.setup||C.setup.call(a,e,r,o)===false)if(a.addEventListener)a.addEventListener(l,o,false);else a.attachEvent&&a.attachEvent("on"+l,o)}if(C.add){C.add.call(a,h);if(!h.handler.guid)h.handler.guid= -d.guid}A.push(h);c.event.global[l]=true}a=null}}},global:{},remove:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(d===false)d=U;var f,h,l=0,k,o,x,r,A,C,J=a.nodeType?"events":"__events__",w=c.data(a),I=w&&w[J];if(w&&I){if(typeof I==="function"){w=I;I=I.events}if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(f in I)c.event.remove(a,f+b)}else{for(b=b.split(" ");f=b[l++];){r=f;k=f.indexOf(".")<0;o=[];if(!k){o=f.split(".");f=o.shift();x=RegExp("(^|\\.)"+ -c.map(o.slice(0).sort(),Ya).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(A=I[f])if(d){r=c.event.special[f]||{};for(h=e||0;h=0){a.type=f=f.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[f]&&c.each(c.cache,function(){this.events&&this.events[f]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType=== -8)return B;a.result=B;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(e=d.nodeType?c.data(d,"handle"):(c.data(d,"__events__")||{}).handle)&&e.apply(d,b);e=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+f]&&d["on"+f].apply(d,b)===false){a.result=false;a.preventDefault()}}catch(h){}if(!a.isPropagationStopped()&&e)c.event.trigger(a,b,e,true);else if(!a.isDefaultPrevented()){var l;e=a.target;var k=f.replace(X,""),o=c.nodeName(e,"a")&&k=== -"click",x=c.event.special[k]||{};if((!x._default||x._default.call(d,a)===false)&&!o&&!(e&&e.nodeName&&c.noData[e.nodeName.toLowerCase()])){try{if(e[k]){if(l=e["on"+k])e["on"+k]=null;c.event.triggered=true;e[k]()}}catch(r){}if(l)e["on"+k]=l;c.event.triggered=false}}},handle:function(a){var b,d,e,f;d=[];var h=c.makeArray(arguments);a=h[0]=c.event.fix(a||E.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;if(!b){e=a.type.split(".");a.type=e.shift();d=e.slice(0).sort();e=RegExp("(^|\\.)"+ -d.join("\\.(?:.*\\.)?")+"(\\.|$)")}a.namespace=a.namespace||d.join(".");f=c.data(this,this.nodeType?"events":"__events__");if(typeof f==="function")f=f.events;d=(f||{})[a.type];if(f&&d){d=d.slice(0);f=0;for(var l=d.length;f-1?c.map(a.options,function(e){return e.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},Z=function(a,b){var d=a.target,e,f;if(!(!ia.test(d.nodeName)||d.readOnly)){e=c.data(d,"_change_data");f=xa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",f);if(!(e===B||f===e))if(e!=null||f){a.type="change";a.liveFired= -B;return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:Z,beforedeactivate:Z,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return Z.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return Z.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,"_change_data",xa(a))}},setup:function(){if(this.type=== -"file")return false;for(var a in V)c.event.add(this,a+".specialChange",V[a]);return ia.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return ia.test(this.nodeName)}};V=c.event.special.change.filters;V.focus=V.beforeactivate}t.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(e){e=c.event.fix(e);e.type=b;return c.event.trigger(e,null,e.target)}c.event.special[b]={setup:function(){ua[b]++===0&&t.addEventListener(a,d,true)},teardown:function(){--ua[b]=== -0&&t.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,e,f){if(typeof d==="object"){for(var h in d)this[b](h,e,d[h],f);return this}if(c.isFunction(e)||e===false){f=e;e=B}var l=b==="one"?c.proxy(f,function(o){c(this).unbind(o,l);return f.apply(this,arguments)}):f;if(d==="unload"&&b!=="one")this.one(d,e,f);else{h=0;for(var k=this.length;h0?this.bind(b,d,e):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});E.attachEvent&&!E.addEventListener&&c(E).bind("unload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}}); -(function(){function a(g,i,n,m,p,q){p=0;for(var u=m.length;p0){F=y;break}}y=y[g]}m[p]=F}}}var d=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,h=false,l=true;[0,0].sort(function(){l=false;return 0});var k=function(g,i,n,m){n=n||[];var p=i=i||t;if(i.nodeType!==1&&i.nodeType!==9)return[];if(!g||typeof g!=="string")return n;var q,u,y,F,M,N=true,O=k.isXML(i),D=[],R=g;do{d.exec("");if(q=d.exec(R)){R=q[3];D.push(q[1]);if(q[2]){F=q[3]; -break}}}while(q);if(D.length>1&&x.exec(g))if(D.length===2&&o.relative[D[0]])u=L(D[0]+D[1],i);else for(u=o.relative[D[0]]?[i]:k(D.shift(),i);D.length;){g=D.shift();if(o.relative[g])g+=D.shift();u=L(g,u)}else{if(!m&&D.length>1&&i.nodeType===9&&!O&&o.match.ID.test(D[0])&&!o.match.ID.test(D[D.length-1])){q=k.find(D.shift(),i,O);i=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]}if(i){q=m?{expr:D.pop(),set:C(m)}:k.find(D.pop(),D.length===1&&(D[0]==="~"||D[0]==="+")&&i.parentNode?i.parentNode:i,O);u=q.expr?k.filter(q.expr, -q.set):q.set;if(D.length>0)y=C(u);else N=false;for(;D.length;){q=M=D.pop();if(o.relative[M])q=D.pop();else M="";if(q==null)q=i;o.relative[M](y,q,O)}}else y=[]}y||(y=u);y||k.error(M||g);if(f.call(y)==="[object Array]")if(N)if(i&&i.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&k.contains(i,y[g])))n.push(u[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&n.push(u[g]);else n.push.apply(n,y);else C(y,n);if(F){k(F,p,n,m);k.uniqueSort(n)}return n};k.uniqueSort=function(g){if(w){h= -l;g.sort(w);if(h)for(var i=1;i0};k.find=function(g,i,n){var m;if(!g)return[];for(var p=0,q=o.order.length;p":function(g,i){var n,m=typeof i==="string",p=0,q=g.length;if(m&&!/\W/.test(i))for(i=i.toLowerCase();p=0))n||m.push(u);else if(n)i[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var i=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=i[1]+(i[2]||1)-0;g[3]=i[3]-0}g[0]=e++;return g},ATTR:function(g,i,n, -m,p,q){i=g[1].replace(/\\/g,"");if(!q&&o.attrMap[i])g[1]=o.attrMap[i];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,i,n,m,p){if(g[1]==="not")if((d.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,i);else{g=k.filter(g[3],i,n,true^p);n||m.push.apply(m,g);return false}else if(o.match.POS.test(g[0])||o.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled=== -true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,i,n){return!!k(n[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"=== -g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,i){return i===0},last:function(g,i,n,m){return i===m.length-1},even:function(g,i){return i%2===0},odd:function(g,i){return i%2===1},lt:function(g,i,n){return in[3]-0},nth:function(g,i,n){return n[3]- -0===i},eq:function(g,i,n){return n[3]-0===i}},filter:{PSEUDO:function(g,i,n,m){var p=i[1],q=o.filters[p];if(q)return q(g,n,i,m);else if(p==="contains")return(g.textContent||g.innerText||k.getText([g])||"").indexOf(i[3])>=0;else if(p==="not"){i=i[3];n=0;for(m=i.length;n=0}},ID:function(g,i){return g.nodeType===1&&g.getAttribute("id")===i},TAG:function(g,i){return i==="*"&&g.nodeType===1||g.nodeName.toLowerCase()=== -i},CLASS:function(g,i){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(i)>-1},ATTR:function(g,i){var n=i[1];n=o.attrHandle[n]?o.attrHandle[n](g):g[n]!=null?g[n]:g.getAttribute(n);var m=n+"",p=i[2],q=i[4];return n==null?p==="!=":p==="="?m===q:p==="*="?m.indexOf(q)>=0:p==="~="?(" "+m+" ").indexOf(q)>=0:!q?m&&n!==false:p==="!="?m!==q:p==="^="?m.indexOf(q)===0:p==="$="?m.substr(m.length-q.length)===q:p==="|="?m===q||m.substr(0,q.length+1)===q+"-":false},POS:function(g,i,n,m){var p=o.setFilters[i[2]]; -if(p)return p(g,n,i,m)}}},x=o.match.POS,r=function(g,i){return"\\"+(i-0+1)},A;for(A in o.match){o.match[A]=RegExp(o.match[A].source+/(?![^\[]*\])(?![^\(]*\))/.source);o.leftMatch[A]=RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[A].source.replace(/\\(\d+)/g,r))}var C=function(g,i){g=Array.prototype.slice.call(g,0);if(i){i.push.apply(i,g);return i}return g};try{Array.prototype.slice.call(t.documentElement.childNodes,0)}catch(J){C=function(g,i){var n=0,m=i||[];if(f.call(g)==="[object Array]")Array.prototype.push.apply(m, -g);else if(typeof g.length==="number")for(var p=g.length;n";n.insertBefore(g,n.firstChild);if(t.getElementById(i)){o.find.ID=function(m,p,q){if(typeof p.getElementById!=="undefined"&&!q)return(p=p.getElementById(m[1]))?p.id===m[1]||typeof p.getAttributeNode!=="undefined"&&p.getAttributeNode("id").nodeValue===m[1]?[p]:B:[]};o.filter.ID=function(m,p){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===p}}n.removeChild(g); -n=g=null})();(function(){var g=t.createElement("div");g.appendChild(t.createComment(""));if(g.getElementsByTagName("*").length>0)o.find.TAG=function(i,n){var m=n.getElementsByTagName(i[1]);if(i[1]==="*"){for(var p=[],q=0;m[q];q++)m[q].nodeType===1&&p.push(m[q]);m=p}return m};g.innerHTML="";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")o.attrHandle.href=function(i){return i.getAttribute("href",2)};g=null})();t.querySelectorAll&& -function(){var g=k,i=t.createElement("div");i.innerHTML="

";if(!(i.querySelectorAll&&i.querySelectorAll(".TEST").length===0)){k=function(m,p,q,u){p=p||t;m=m.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!u&&!k.isXML(p))if(p.nodeType===9)try{return C(p.querySelectorAll(m),q)}catch(y){}else if(p.nodeType===1&&p.nodeName.toLowerCase()!=="object"){var F=p.getAttribute("id"),M=F||"__sizzle__";F||p.setAttribute("id",M);try{return C(p.querySelectorAll("#"+M+" "+m),q)}catch(N){}finally{F|| -p.removeAttribute("id")}}return g(m,p,q,u)};for(var n in g)k[n]=g[n];i=null}}();(function(){var g=t.documentElement,i=g.matchesSelector||g.mozMatchesSelector||g.webkitMatchesSelector||g.msMatchesSelector,n=false;try{i.call(t.documentElement,"[test!='']:sizzle")}catch(m){n=true}if(i)k.matchesSelector=function(p,q){q=q.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(p))try{if(n||!o.match.PSEUDO.test(q)&&!/!=/.test(q))return i.call(p,q)}catch(u){}return k(q,null,null,[p]).length>0}})();(function(){var g= -t.createElement("div");g.innerHTML="
";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){o.order.splice(1,0,"CLASS");o.find.CLASS=function(i,n,m){if(typeof n.getElementsByClassName!=="undefined"&&!m)return n.getElementsByClassName(i[1])};g=null}}})();k.contains=t.documentElement.contains?function(g,i){return g!==i&&(g.contains?g.contains(i):true)}:t.documentElement.compareDocumentPosition? -function(g,i){return!!(g.compareDocumentPosition(i)&16)}:function(){return false};k.isXML=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false};var L=function(g,i){for(var n,m=[],p="",q=i.nodeType?[i]:i;n=o.match.PSEUDO.exec(g);){p+=n[0];g=g.replace(o.match.PSEUDO,"")}g=o.relative[g]?g+"*":g;n=0;for(var u=q.length;n0)for(var h=d;h0},closest:function(a,b){var d=[],e,f,h=this[0];if(c.isArray(a)){var l,k={},o=1;if(h&&a.length){e=0;for(f=a.length;e-1:c(h).is(e))d.push({selector:l,elem:h,level:o})}h= -h.parentNode;o++}}return d}l=cb.test(a)?c(a,b||this.context):null;e=0;for(f=this.length;e-1:c.find.matchesSelector(h,a)){d.push(h);break}else{h=h.parentNode;if(!h||!h.ownerDocument||h===b)break}d=d.length>1?c.unique(d):d;return this.pushStack(d,"closest",a)},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var d=typeof a==="string"?c(a,b||this.context): -c.makeArray(a),e=c.merge(this.get(),d);return this.pushStack(!d[0]||!d[0].parentNode||d[0].parentNode.nodeType===11||!e[0]||!e[0].parentNode||e[0].parentNode.nodeType===11?e:c.unique(e))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a, -2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a, -b){c.fn[a]=function(d,e){var f=c.map(this,b,d);Za.test(a)||(e=d);if(e&&typeof e==="string")f=c.filter(e,f);f=this.length>1?c.unique(f):f;if((this.length>1||ab.test(e))&&$a.test(a))f=f.reverse();return this.pushStack(f,a,bb.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return b.length===1?c.find.matchesSelector(b[0],a)?[b[0]]:[]:c.find.matches(a,b)},dir:function(a,b,d){var e=[];for(a=a[b];a&&a.nodeType!==9&&(d===B||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&& -e.push(a);a=a[b]}return e},nth:function(a,b,d){b=b||1;for(var e=0;a;a=a[d])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var za=/ jQuery\d+="(?:\d+|null)"/g,$=/^\s+/,Aa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Ba=/<([\w:]+)/,db=/\s]+\/)>/g,P={option:[1, -""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};P.optgroup=P.option;P.tbody=P.tfoot=P.colgroup=P.caption=P.thead;P.th=P.td;if(!c.support.htmlSerialize)P._default=[1,"div
","
"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= -c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==B)return this.empty().append((this[0]&&this[0].ownerDocument||t).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, -wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, -prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, -this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,e;(e=this[d])!=null;d++)if(!a||c.filter(a,[e]).length){if(!b&&e.nodeType===1){c.cleanData(e.getElementsByTagName("*"));c.cleanData([e])}e.parentNode&&e.parentNode.removeChild(e)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); -return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,e=this.ownerDocument;if(!d){d=e.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(za,"").replace(fb,'="$1">').replace($,"")],e)[0]}else return this.cloneNode(true)});if(a===true){na(this,b);na(this.find("*"),b.find("*"))}return b},html:function(a){if(a===B)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(za,""):null; -else if(typeof a==="string"&&!Ca.test(a)&&(c.support.leadingWhitespace||!$.test(a))&&!P[(Ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Aa,"<$1>");try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?h.cloneNode(true):h)}k.length&&c.each(k,Oa)}return this}});c.buildFragment=function(a,b,d){var e,f,h;b=b&&b[0]?b[0].ownerDocument||b[0]:t;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===t&&!Ca.test(a[0])&&(c.support.checkClone||!Da.test(a[0]))){f=true;if(h=c.fragments[a[0]])if(h!==1)e=h}if(!e){e=b.createDocumentFragment();c.clean(a,b,e,d)}if(f)c.fragments[a[0]]=h?e:1;return{fragment:e,cacheable:f}};c.fragments={};c.each({appendTo:"append", -prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var e=[];d=c(d);var f=this.length===1&&this[0].parentNode;if(f&&f.nodeType===11&&f.childNodes.length===1&&d.length===1){d[b](this[0]);return this}else{f=0;for(var h=d.length;f0?this.clone(true):this).get();c(d[f])[b](l);e=e.concat(l)}return this.pushStack(e,a,d.selector)}}});c.extend({clean:function(a,b,d,e){b=b||t;if(typeof b.createElement==="undefined")b=b.ownerDocument|| -b[0]&&b[0].ownerDocument||t;for(var f=[],h=0,l;(l=a[h])!=null;h++){if(typeof l==="number")l+="";if(l){if(typeof l==="string"&&!eb.test(l))l=b.createTextNode(l);else if(typeof l==="string"){l=l.replace(Aa,"<$1>");var k=(Ba.exec(l)||["",""])[1].toLowerCase(),o=P[k]||P._default,x=o[0],r=b.createElement("div");for(r.innerHTML=o[1]+l+o[2];x--;)r=r.lastChild;if(!c.support.tbody){x=db.test(l);k=k==="table"&&!x?r.firstChild&&r.firstChild.childNodes:o[1]===""&&!x?r.childNodes:[];for(o=k.length- -1;o>=0;--o)c.nodeName(k[o],"tbody")&&!k[o].childNodes.length&&k[o].parentNode.removeChild(k[o])}!c.support.leadingWhitespace&&$.test(l)&&r.insertBefore(b.createTextNode($.exec(l)[0]),r.firstChild);l=r.childNodes}if(l.nodeType)f.push(l);else f=c.merge(f,l)}}if(d)for(h=0;f[h];h++)if(e&&c.nodeName(f[h],"script")&&(!f[h].type||f[h].type.toLowerCase()==="text/javascript"))e.push(f[h].parentNode?f[h].parentNode.removeChild(f[h]):f[h]);else{f[h].nodeType===1&&f.splice.apply(f,[h+1,0].concat(c.makeArray(f[h].getElementsByTagName("script")))); -d.appendChild(f[h])}return f},cleanData:function(a){for(var b,d,e=c.cache,f=c.event.special,h=c.support.deleteExpando,l=0,k;(k=a[l])!=null;l++)if(!(k.nodeName&&c.noData[k.nodeName.toLowerCase()]))if(d=k[c.expando]){if((b=e[d])&&b.events)for(var o in b.events)f[o]?c.event.remove(k,o):c.removeEvent(k,o,b.handle);if(h)delete k[c.expando];else k.removeAttribute&&k.removeAttribute(c.expando);delete e[d]}}});var Ea=/alpha\([^)]*\)/i,gb=/opacity=([^)]*)/,hb=/-([a-z])/ig,ib=/([A-Z])/g,Fa=/^-?\d+(?:px)?$/i, -jb=/^-?\d/,kb={position:"absolute",visibility:"hidden",display:"block"},Pa=["Left","Right"],Qa=["Top","Bottom"],W,Ga,aa,lb=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){if(arguments.length===2&&b===B)return this;return c.access(this,a,b,true,function(d,e,f){return f!==B?c.style(d,e,f):c.css(d,e)})};c.extend({cssHooks:{opacity:{get:function(a,b){if(b){var d=W(a,"opacity","opacity");return d===""?"1":d}else return a.style.opacity}}},cssNumber:{zIndex:true,fontWeight:true,opacity:true, -zoom:true,lineHeight:true},cssProps:{"float":c.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,d,e){if(!(!a||a.nodeType===3||a.nodeType===8||!a.style)){var f,h=c.camelCase(b),l=a.style,k=c.cssHooks[h];b=c.cssProps[h]||h;if(d!==B){if(!(typeof d==="number"&&isNaN(d)||d==null)){if(typeof d==="number"&&!c.cssNumber[h])d+="px";if(!k||!("set"in k)||(d=k.set(a,d))!==B)try{l[b]=d}catch(o){}}}else{if(k&&"get"in k&&(f=k.get(a,false,e))!==B)return f;return l[b]}}},css:function(a,b,d){var e,f=c.camelCase(b), -h=c.cssHooks[f];b=c.cssProps[f]||f;if(h&&"get"in h&&(e=h.get(a,true,d))!==B)return e;else if(W)return W(a,b,f)},swap:function(a,b,d){var e={},f;for(f in b){e[f]=a.style[f];a.style[f]=b[f]}d.call(a);for(f in b)a.style[f]=e[f]},camelCase:function(a){return a.replace(hb,lb)}});c.curCSS=c.css;c.each(["height","width"],function(a,b){c.cssHooks[b]={get:function(d,e,f){var h;if(e){if(d.offsetWidth!==0)h=oa(d,b,f);else c.swap(d,kb,function(){h=oa(d,b,f)});if(h<=0){h=W(d,b,b);if(h==="0px"&&aa)h=aa(d,b,b); -if(h!=null)return h===""||h==="auto"?"0px":h}if(h<0||h==null){h=d.style[b];return h===""||h==="auto"?"0px":h}return typeof h==="string"?h:h+"px"}},set:function(d,e){if(Fa.test(e)){e=parseFloat(e);if(e>=0)return e+"px"}else return e}}});if(!c.support.opacity)c.cssHooks.opacity={get:function(a,b){return gb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var d=a.style;d.zoom=1;var e=c.isNaN(b)?"":"alpha(opacity="+b*100+")",f= -d.filter||"";d.filter=Ea.test(f)?f.replace(Ea,e):d.filter+" "+e}};if(t.defaultView&&t.defaultView.getComputedStyle)Ga=function(a,b,d){var e;d=d.replace(ib,"-$1").toLowerCase();if(!(b=a.ownerDocument.defaultView))return B;if(b=b.getComputedStyle(a,null)){e=b.getPropertyValue(d);if(e===""&&!c.contains(a.ownerDocument.documentElement,a))e=c.style(a,d)}return e};if(t.documentElement.currentStyle)aa=function(a,b){var d,e,f=a.currentStyle&&a.currentStyle[b],h=a.style;if(!Fa.test(f)&&jb.test(f)){d=h.left; -e=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;h.left=b==="fontSize"?"1em":f||0;f=h.pixelLeft+"px";h.left=d;a.runtimeStyle.left=e}return f===""?"auto":f};W=Ga||aa;if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetHeight;return a.offsetWidth===0&&b===0||!c.support.reliableHiddenOffsets&&(a.style.display||c.css(a,"display"))==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var mb=c.now(),nb=/)<[^<]*)*<\/script>/gi, -ob=/^(?:select|textarea)/i,pb=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,qb=/^(?:GET|HEAD)$/,Ra=/\[\]$/,T=/\=\?(&|$)/,ja=/\?/,rb=/([?&])_=[^&]*/,sb=/^(\w+:)?\/\/([^\/?#]+)/,tb=/%20/g,ub=/#.*$/,Ha=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!=="string"&&Ha)return Ha.apply(this,arguments);else if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var f=a.slice(e,a.length);a=a.slice(0,e)}e="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b=== -"object"){b=c.param(b,c.ajaxSettings.traditional);e="POST"}var h=this;c.ajax({url:a,type:e,dataType:"html",data:b,complete:function(l,k){if(k==="success"||k==="notmodified")h.html(f?c("
").append(l.responseText.replace(nb,"")).find(f):l.responseText);d&&h.each(d,[l.responseText,k,l])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&& -!this.disabled&&(this.checked||ob.test(this.nodeName)||pb.test(this.type))}).map(function(a,b){var d=c(this).val();return d==null?null:c.isArray(d)?c.map(d,function(e){return{name:b.name,value:e}}):{name:b.name,value:d}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:e})}, -getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:e})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return new E.XMLHttpRequest},accepts:{xml:"application/xml, text/xml",html:"text/html", -script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},ajax:function(a){var b=c.extend(true,{},c.ajaxSettings,a),d,e,f,h=b.type.toUpperCase(),l=qb.test(h);b.url=b.url.replace(ub,"");b.context=a&&a.context!=null?a.context:b;if(b.data&&b.processData&&typeof b.data!=="string")b.data=c.param(b.data,b.traditional);if(b.dataType==="jsonp"){if(h==="GET")T.test(b.url)||(b.url+=(ja.test(b.url)?"&":"?")+(b.jsonp||"callback")+"=?");else if(!b.data|| -!T.test(b.data))b.data=(b.data?b.data+"&":"")+(b.jsonp||"callback")+"=?";b.dataType="json"}if(b.dataType==="json"&&(b.data&&T.test(b.data)||T.test(b.url))){d=b.jsonpCallback||"jsonp"+mb++;if(b.data)b.data=(b.data+"").replace(T,"="+d+"$1");b.url=b.url.replace(T,"="+d+"$1");b.dataType="script";var k=E[d];E[d]=function(m){if(c.isFunction(k))k(m);else{E[d]=B;try{delete E[d]}catch(p){}}f=m;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);r&&r.removeChild(A)}}if(b.dataType==="script"&&b.cache===null)b.cache= -false;if(b.cache===false&&l){var o=c.now(),x=b.url.replace(rb,"$1_="+o);b.url=x+(x===b.url?(ja.test(b.url)?"&":"?")+"_="+o:"")}if(b.data&&l)b.url+=(ja.test(b.url)?"&":"?")+b.data;b.global&&c.active++===0&&c.event.trigger("ajaxStart");o=(o=sb.exec(b.url))&&(o[1]&&o[1].toLowerCase()!==location.protocol||o[2].toLowerCase()!==location.host);if(b.dataType==="script"&&h==="GET"&&o){var r=t.getElementsByTagName("head")[0]||t.documentElement,A=t.createElement("script");if(b.scriptCharset)A.charset=b.scriptCharset; -A.src=b.url;if(!d){var C=false;A.onload=A.onreadystatechange=function(){if(!C&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){C=true;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);A.onload=A.onreadystatechange=null;r&&A.parentNode&&r.removeChild(A)}}}r.insertBefore(A,r.firstChild);return B}var J=false,w=b.xhr();if(w){b.username?w.open(h,b.url,b.async,b.username,b.password):w.open(h,b.url,b.async);try{if(b.data!=null&&!l||a&&a.contentType)w.setRequestHeader("Content-Type", -b.contentType);if(b.ifModified){c.lastModified[b.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[b.url]);c.etag[b.url]&&w.setRequestHeader("If-None-Match",c.etag[b.url])}o||w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept",b.dataType&&b.accepts[b.dataType]?b.accepts[b.dataType]+", */*; q=0.01":b.accepts._default)}catch(I){}if(b.beforeSend&&b.beforeSend.call(b.context,w,b)===false){b.global&&c.active--===1&&c.event.trigger("ajaxStop");w.abort();return false}b.global&& -c.triggerGlobal(b,"ajaxSend",[w,b]);var L=w.onreadystatechange=function(m){if(!w||w.readyState===0||m==="abort"){J||c.handleComplete(b,w,e,f);J=true;if(w)w.onreadystatechange=c.noop}else if(!J&&w&&(w.readyState===4||m==="timeout")){J=true;w.onreadystatechange=c.noop;e=m==="timeout"?"timeout":!c.httpSuccess(w)?"error":b.ifModified&&c.httpNotModified(w,b.url)?"notmodified":"success";var p;if(e==="success")try{f=c.httpData(w,b.dataType,b)}catch(q){e="parsererror";p=q}if(e==="success"||e==="notmodified")d|| -c.handleSuccess(b,w,e,f);else c.handleError(b,w,e,p);d||c.handleComplete(b,w,e,f);m==="timeout"&&w.abort();if(b.async)w=null}};try{var g=w.abort;w.abort=function(){w&&Function.prototype.call.call(g,w);L("abort")}}catch(i){}b.async&&b.timeout>0&&setTimeout(function(){w&&!J&&L("timeout")},b.timeout);try{w.send(l||b.data==null?null:b.data)}catch(n){c.handleError(b,w,null,n);c.handleComplete(b,w,e,f)}b.async||L();return w}},param:function(a,b){var d=[],e=function(h,l){l=c.isFunction(l)?l():l;d[d.length]= -encodeURIComponent(h)+"="+encodeURIComponent(l)};if(b===B)b=c.ajaxSettings.traditional;if(c.isArray(a)||a.jquery)c.each(a,function(){e(this.name,this.value)});else for(var f in a)da(f,a[f],b,e);return d.join("&").replace(tb,"+")}});c.extend({active:0,lastModified:{},etag:{},handleError:function(a,b,d,e){a.error&&a.error.call(a.context,b,d,e);a.global&&c.triggerGlobal(a,"ajaxError",[b,a,e])},handleSuccess:function(a,b,d,e){a.success&&a.success.call(a.context,e,d,b);a.global&&c.triggerGlobal(a,"ajaxSuccess", -[b,a])},handleComplete:function(a,b,d){a.complete&&a.complete.call(a.context,b,d);a.global&&c.triggerGlobal(a,"ajaxComplete",[b,a]);a.global&&c.active--===1&&c.event.trigger("ajaxStop")},triggerGlobal:function(a,b,d){(a.context&&a.context.url==null?c(a.context):c.event).trigger(b,d)},httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"), -e=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(e)c.etag[b]=e;return a.status===304},httpData:function(a,b,d){var e=a.getResponseHeader("content-type")||"",f=b==="xml"||!b&&e.indexOf("xml")>=0;a=f?a.responseXML:a.responseText;f&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&e.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&e.indexOf("javascript")>=0)c.globalEval(a);return a}}); -if(E.ActiveXObject)c.ajaxSettings.xhr=function(){if(E.location.protocol!=="file:")try{return new E.XMLHttpRequest}catch(a){}try{return new E.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}};c.support.ajax=!!c.ajaxSettings.xhr();var ea={},vb=/^(?:toggle|show|hide)$/,wb=/^([+\-]=)?([\d+.\-]+)(.*)$/,ba,pa=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b,d){if(a||a===0)return this.animate(S("show", -3),a,b,d);else{d=0;for(var e=this.length;d=0;e--)if(d[e].elem===this){b&&d[e](true);d.splice(e,1)}});b||this.dequeue();return this}});c.each({slideDown:S("show",1),slideUp:S("hide",1),slideToggle:S("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){c.fn[a]=function(d,e,f){return this.animate(b, -d,e,f)}});c.extend({speed:function(a,b,d){var e=a&&typeof a==="object"?c.extend({},a):{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};e.duration=c.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in c.fx.speeds?c.fx.speeds[e.duration]:c.fx.speeds._default;e.old=e.complete;e.complete=function(){e.queue!==false&&c(this).dequeue();c.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,d,e){return d+e*a},swing:function(a,b,d,e){return(-Math.cos(a* -Math.PI)/2+0.5)*e+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a=parseFloat(c.css(this.elem,this.prop));return a&&a>-1E4?a:0},custom:function(a,b,d){function e(l){return f.step(l)} -var f=this,h=c.fx;this.startTime=c.now();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;e.elem=this.elem;if(e()&&c.timers.push(e)&&!ba)ba=setInterval(h.tick,h.interval)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true; -this.custom(this.cur(),0)},step:function(a){var b=c.now(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var e in this.options.curAnim)if(this.options.curAnim[e]!==true)d=false;if(d){if(this.options.overflow!=null&&!c.support.shrinkWrapBlocks){var f=this.elem,h=this.options;c.each(["","X","Y"],function(k,o){f.style["overflow"+o]=h.overflow[k]})}this.options.hide&&c(this.elem).hide();if(this.options.hide|| -this.options.show)for(var l in this.options.curAnim)c.style(this.elem,l,this.options.orig[l]);this.options.complete.call(this.elem)}return false}else{a=b-this.startTime;this.state=a/this.options.duration;b=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||b](this.state,a,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a= -c.timers,b=0;b-1;e={};var x={};if(o)x=f.position();l=o?x.top:parseInt(l,10)||0;k=o?x.left:parseInt(k,10)||0;if(c.isFunction(b))b=b.call(a,d,h);if(b.top!=null)e.top=b.top-h.top+l;if(b.left!=null)e.left=b.left-h.left+k;"using"in b?b.using.call(a, -e):f.css(e)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),e=Ia.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.css(a,"marginTop"))||0;d.left-=parseFloat(c.css(a,"marginLeft"))||0;e.top+=parseFloat(c.css(b[0],"borderTopWidth"))||0;e.left+=parseFloat(c.css(b[0],"borderLeftWidth"))||0;return{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||t.body;a&&!Ia.test(a.nodeName)&& -c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(e){var f=this[0],h;if(!f)return null;if(e!==B)return this.each(function(){if(h=fa(this))h.scrollTo(!a?e:c(h).scrollLeft(),a?e:c(h).scrollTop());else this[d]=e});else return(h=fa(f))?"pageXOffset"in h?h[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&h.document.documentElement[d]||h.document.body[d]:f[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase(); -c.fn["inner"+b]=function(){return this[0]?parseFloat(c.css(this[0],d,"padding")):null};c.fn["outer"+b]=function(e){return this[0]?parseFloat(c.css(this[0],d,e?"margin":"border")):null};c.fn[d]=function(e){var f=this[0];if(!f)return e==null?null:this;if(c.isFunction(e))return this.each(function(l){var k=c(this);k[d](e.call(this,l,k[d]()))});if(c.isWindow(f))return f.document.compatMode==="CSS1Compat"&&f.document.documentElement["client"+b]||f.document.body["client"+b];else if(f.nodeType===9)return Math.max(f.documentElement["client"+ -b],f.body["scroll"+b],f.documentElement["scroll"+b],f.body["offset"+b],f.documentElement["offset"+b]);else if(e===B){f=c.css(f,d);var h=parseFloat(f);return c.isNaN(h)?f:h}else return this.css(d,typeof e==="string"?e:e+"px")}})})(window); diff --git a/editor/extensions/imagelib/openclipart-es.html b/editor/extensions/imagelib/openclipart-es.html new file mode 100644 index 00000000..0f37e30e --- /dev/null +++ b/editor/extensions/imagelib/openclipart-es.html @@ -0,0 +1,15 @@ + + + + + - + + + + + + + + + + diff --git a/editor/extensions/imagelib/openclipart.html b/editor/extensions/imagelib/openclipart.html new file mode 100644 index 00000000..401100b6 --- /dev/null +++ b/editor/extensions/imagelib/openclipart.html @@ -0,0 +1,16 @@ + + + + + + - + + + + + + + + + + diff --git a/editor/extensions/imagelib/openclipart.js b/editor/extensions/imagelib/openclipart.js new file mode 100644 index 00000000..a00cf18a --- /dev/null +++ b/editor/extensions/imagelib/openclipart.js @@ -0,0 +1,346 @@ +import {jml, body, nbsp} from '../../external/jamilih/jml-es.js'; +import $ from '../../external/query-result/esm/index.js'; +import {manipulation} from '../../external/qr-manipulation/dist/index-es.js'; + +manipulation($, jml); + +const baseAPIURL = 'https://openclipart.org/search/json/'; + +const jsVoid = 'javascript: void(0);'; // eslint-disable-line no-script-url + +/** + * Shows results after query submission. + * @param {string} url + * @returns {undefined} + */ +async function processResults (url) { + /** + * @param {string} query + * @returns {external:JamilihArray} + */ + function queryLink (query) { + return ['a', { + href: jsVoid, + dataset: {value: query}, + $on: {click (e) { + e.preventDefault(); + const {value} = this.dataset; + $('#query')[0].$set(value); + $('#openclipart')[0].$submit(); + }} + }, [query]]; + } + + const r = await fetch(url); + const json = await r.json(); + // console.log('json', json); + + if (!json || json.msg !== 'success') { + // Todo: This could use a generic alert library instead + alert('There was a problem downloading the results'); // eslint-disable-line no-alert + return; + } + const {payload, info: { + results: numResults, + pages, + current_page: currentPage + }} = json; + + // $('#page')[0].value = currentPage; + // $('#page')[0].max = pages; + + // Unused properties: + // - `svg_filesize` always 0? + // - `dimensions: { + // png_thumb: {width, height}, + // png_full_lossy: {width, height} + // }` object of relevance? + // - No need for `tags` with `tags_array` + // - `svg`'s: `png_thumb`, `png_full_lossy`, `png_2400px` + const semiColonSep = '; ' + nbsp; + $('#results').jml('div', [ + ['span', [ + 'Number of results: ', + numResults + ]], + semiColonSep, + ['span', [ + 'page ', + currentPage, + ' out of ', + pages + ]], + ...payload.map(({ + title, description, id, + uploader, created, + svg: {url: svgURL}, + detail_link: detailLink, + tags_array: tagsArray, + downloaded_by: downloadedBy, + total_favorites: totalFavorites + }) => { + const imgHW = '100px'; + const colonSep = ': ' + nbsp; + return ['div', [ + ['button', {style: 'margin-right: 8px; border: 2px solid black;', dataset: {id, value: svgURL}, $on: { + async click (e) { + e.preventDefault(); + const {value: svgurl} = this.dataset; + // console.log('this', id, svgurl); + const post = (message) => { + // Todo: Make origin customizable as set by opening window + // Todo: If dropping IE9, avoid stringifying + window.parent.postMessage(JSON.stringify({ + namespace: 'imagelib', + ...message + }), '*'); + }; + // Send metadata (also indicates file is about to be sent) + post({ + name: title, + id: svgurl + }); + const result = await fetch(svgurl); + const svg = await result.text(); + // console.log('url and svg', svgurl, svg); + post({ + href: svgurl, + data: svg + }); + } + }}, [ + // If we wanted interactive versions despite security risk: + // ['object', {data: svgURL, type: 'image/svg+xml'}] + ['img', {src: svgURL, style: `width: ${imgHW}; height: ${imgHW};`}] + ]], + ['b', [title]], + ' ', + ['i', [description]], + ' ', + ['span', [ + '(ID: ', + ['a', { + href: jsVoid, + dataset: {value: id}, + $on: { + click (e) { + e.preventDefault(); + const {value} = this.dataset; + $('#byids')[0].$set(value); + $('#openclipart')[0].$submit(); + } + } + }, [id]], + ')' + ]], + ' ', + ['i', [ + ['a', { + href: detailLink, + target: '_blank' + }, ['Details']] + ]], + ['br'], + ['span', [ + ['u', ['Uploaded by']], colonSep, + queryLink(uploader), + semiColonSep + ]], + ['span', [ + ['u', ['Download count']], colonSep, + downloadedBy, + semiColonSep + ]], + ['span', [ + ['u', ['Times used as favorite']], colonSep, + totalFavorites, + semiColonSep + ]], + ['span', [ + ['u', ['Created date']], colonSep, + created + ]], + ['br'], + ['u', ['Tags']], colonSep, + ...tagsArray.map((tag) => { + return ['span', [ + ' ', + queryLink(tag) + ]]; + }) + ]]; + }), + ['br'], ['br'], + (currentPage === 1 || pages <= 2 + ? '' + : ['span', [ + ['a', { + href: jsVoid, + $on: { + click (e) { + e.preventDefault(); + $('#page')[0].value = 1; + $('#openclipart')[0].$submit(); + } + } + }, ['First']], + ' ' + ]] + ), + (currentPage === 1 + ? '' + : ['span', [ + ['a', { + href: jsVoid, + $on: { + click (e) { + e.preventDefault(); + $('#page')[0].value = currentPage - 1; + $('#openclipart')[0].$submit(); + } + } + }, ['Prev']], + ' ' + ]] + ), + (currentPage === pages + ? '' + : ['span', [ + ['a', { + href: jsVoid, + $on: { + click (e) { + e.preventDefault(); + $('#page')[0].value = currentPage + 1; + $('#openclipart')[0].$submit(); + } + } + }, ['Next']], + ' ' + ]] + ), + (currentPage === pages || pages <= 2 + ? '' + : ['span', [ + ['a', { + href: jsVoid, + $on: { + click (e) { + e.preventDefault(); + $('#page')[0].value = pages; + $('#openclipart')[0].$submit(); + } + } + }, ['Last']], + ' ' + ]] + ) + ]); +} + +jml('div', [ + ['style', [ + `.control { + padding-top: 10px; + }` + ]], + ['form', { + id: 'openclipart', + $custom: { + async $submit () { + const url = new URL(baseAPIURL); + [ + 'query', 'sort', 'amount', 'page', 'byids' + ].forEach((prop) => { + const {value} = $('#' + prop)[0]; + if (value) { + url.searchParams.set(prop, value); + } + }); + await processResults(url); + } + }, + $on: { + submit (e) { + e.preventDefault(); + this.$submit(); + } + } + }, [ + // Todo: i18nize + ['fieldset', [ + ['legend', ['Search terms']], + ['div', {class: 'control'}, [ + ['label', [ + 'Query (Title, description, uploader, or tag): ', + ['input', {id: 'query', name: 'query', placeholder: 'cat', $custom: { + $set (value) { + $('#byids')[0].value = ''; + this.value = value; + } + }, $on: { + change () { + $('#byids')[0].value = ''; + } + }}] + ]] + ]], + ['br'], + ' OR ', + ['br'], + ['div', {class: 'control'}, [ + ['label', [ + 'IDs (single or comma-separated): ', + ['input', {id: 'byids', name: 'ids', placeholder: '271380, 265741', $custom: { + $set (value) { + $('#query')[0].value = ''; + this.value = value; + } + }, $on: { + change () { + $('#query')[0].value = ''; + } + }}] + ]] + ]] + ]], + ['fieldset', [ + ['legend', ['Configuring results']], + ['div', {class: 'control'}, [ + ['label', [ + 'Sort by: ', + ['select', {id: 'sort'}, [ + // Todo: i18nize first values + ['Date', 'date'], + ['Downloads', 'downloads'], + ['Favorited', 'favorites'] + ].map(([text, value = text]) => { + return ['option', {value}, [text]]; + })] + ]] + ]], + ['div', {class: 'control'}, [ + ['label', [ + 'Results per page: ', + ['input', { + id: 'amount', name: 'amount', value: 10, + type: 'number', min: 1, max: 200, step: 1, pattern: '\\d+'}] + ]] + ]], + ['div', {class: 'control'}, [ + ['label', [ + 'Page number: ', + ['input', { + // max: 1, // We'll change this based on available results + id: 'page', name: 'page', value: 1, style: 'width: 40px;', + type: 'number', min: 1, step: 1, pattern: '\\d+' + }] + ]] + ]] + ]], + ['div', {class: 'control'}, [ + ['input', {type: 'submit'}] + ]] + ]], + ['div', {id: 'results'}] +], body); diff --git a/editor/extensions/placemark-icons.xml b/editor/extensions/placemark-icons.xml new file mode 100644 index 00000000..6db97a72 --- /dev/null +++ b/editor/extensions/placemark-icons.xml @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + T + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + T + + + + + + + + T + + + + + diff --git a/editor/extensions/placemark.png b/editor/extensions/placemark.png new file mode 100644 index 00000000..5b15c26c Binary files /dev/null and b/editor/extensions/placemark.png differ diff --git a/editor/external/babel-polyfill/polyfill.js b/editor/external/@babel/polyfill/polyfill.js similarity index 67% rename from editor/external/babel-polyfill/polyfill.js rename to editor/external/@babel/polyfill/polyfill.js index 0910ad25..250b921f 100644 --- a/editor/external/babel-polyfill/polyfill.js +++ b/editor/external/@babel/polyfill/polyfill.js @@ -1,80 +1,262 @@ -(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o Array#indexOf // true -> Array#includes -var toIObject = _dereq_(117); -var toLength = _dereq_(118); -var toAbsoluteIndex = _dereq_(114); +var toIObject = _dereq_(116); +var toLength = _dereq_(117); +var toAbsoluteIndex = _dereq_(113); module.exports = function (IS_INCLUDES) { return function ($this, el, fromIndex) { var O = toIObject($this); @@ -148,7 +321,7 @@ module.exports = function (IS_INCLUDES) { }; }; -},{"114":114,"117":117,"118":118}],12:[function(_dereq_,module,exports){ +},{"113":113,"116":116,"117":117}],20:[function(_dereq_,module,exports){ // 0 -> Array#forEach // 1 -> Array#map // 2 -> Array#filter @@ -156,11 +329,11 @@ module.exports = function (IS_INCLUDES) { // 4 -> Array#every // 5 -> Array#find // 6 -> Array#findIndex -var ctx = _dereq_(25); -var IObject = _dereq_(47); -var toObject = _dereq_(119); -var toLength = _dereq_(118); -var asc = _dereq_(15); +var ctx = _dereq_(32); +var IObject = _dereq_(53); +var toObject = _dereq_(118); +var toLength = _dereq_(117); +var asc = _dereq_(23); module.exports = function (TYPE, $create) { var IS_MAP = TYPE == 1; var IS_FILTER = TYPE == 2; @@ -194,11 +367,11 @@ module.exports = function (TYPE, $create) { }; }; -},{"118":118,"119":119,"15":15,"25":25,"47":47}],13:[function(_dereq_,module,exports){ -var aFunction = _dereq_(3); -var toObject = _dereq_(119); -var IObject = _dereq_(47); -var toLength = _dereq_(118); +},{"117":117,"118":118,"23":23,"32":32,"53":53}],21:[function(_dereq_,module,exports){ +var aFunction = _dereq_(11); +var toObject = _dereq_(118); +var IObject = _dereq_(53); +var toLength = _dereq_(117); module.exports = function (that, callbackfn, aLen, memo, isRight) { aFunction(callbackfn); @@ -224,9 +397,9 @@ module.exports = function (that, callbackfn, aLen, memo, isRight) { return memo; }; -},{"118":118,"119":119,"3":3,"47":47}],14:[function(_dereq_,module,exports){ -var isObject = _dereq_(51); -var isArray = _dereq_(49); +},{"11":11,"117":117,"118":118,"53":53}],22:[function(_dereq_,module,exports){ +var isObject = _dereq_(57); +var isArray = _dereq_(55); var SPECIES = _dereq_(128)('species'); module.exports = function (original) { @@ -242,19 +415,19 @@ module.exports = function (original) { } return C === undefined ? Array : C; }; -},{"128":128,"49":49,"51":51}],15:[function(_dereq_,module,exports){ +},{"128":128,"55":55,"57":57}],23:[function(_dereq_,module,exports){ // 9.4.2.3 ArraySpeciesCreate(originalArray, length) -var speciesConstructor = _dereq_(14); +var speciesConstructor = _dereq_(22); module.exports = function (original, length) { return new (speciesConstructor(original))(length); }; -},{"14":14}],16:[function(_dereq_,module,exports){ +},{"22":22}],24:[function(_dereq_,module,exports){ 'use strict'; -var aFunction = _dereq_(3); -var isObject = _dereq_(51); -var invoke = _dereq_(46); +var aFunction = _dereq_(11); +var isObject = _dereq_(57); +var invoke = _dereq_(52); var arraySlice = [].slice; var factories = {}; @@ -277,9 +450,9 @@ module.exports = Function.bind || function bind(that /* , ...args */) { return bound; }; -},{"3":3,"46":46,"51":51}],17:[function(_dereq_,module,exports){ +},{"11":11,"52":52,"57":57}],25:[function(_dereq_,module,exports){ // getting tag from 19.1.3.6 Object.prototype.toString() -var cof = _dereq_(18); +var cof = _dereq_(26); var TAG = _dereq_(128)('toStringTag'); // ES3 wrong here var ARG = cof(function () { return arguments; }()) == 'Arguments'; @@ -302,26 +475,26 @@ module.exports = function (it) { : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B; }; -},{"128":128,"18":18}],18:[function(_dereq_,module,exports){ +},{"128":128,"26":26}],26:[function(_dereq_,module,exports){ var toString = {}.toString; module.exports = function (it) { return toString.call(it).slice(8, -1); }; -},{}],19:[function(_dereq_,module,exports){ +},{}],27:[function(_dereq_,module,exports){ 'use strict'; -var dP = _dereq_(72).f; -var create = _dereq_(71); +var dP = _dereq_(75).f; +var create = _dereq_(74); var redefineAll = _dereq_(93); -var ctx = _dereq_(25); -var anInstance = _dereq_(6); -var forOf = _dereq_(39); -var $iterDefine = _dereq_(55); -var step = _dereq_(57); -var setSpecies = _dereq_(100); -var DESCRIPTORS = _dereq_(29); -var fastKey = _dereq_(66).fastKey; +var ctx = _dereq_(32); +var anInstance = _dereq_(15); +var forOf = _dereq_(45); +var $iterDefine = _dereq_(61); +var step = _dereq_(63); +var setSpecies = _dereq_(99); +var DESCRIPTORS = _dereq_(36); +var fastKey = _dereq_(70).fastKey; var validate = _dereq_(125); var SIZE = DESCRIPTORS ? '_s' : 'size'; @@ -455,27 +628,16 @@ module.exports = { } }; -},{"100":100,"125":125,"25":25,"29":29,"39":39,"55":55,"57":57,"6":6,"66":66,"71":71,"72":72,"93":93}],20:[function(_dereq_,module,exports){ -// https://github.com/DavidBruant/Map-Set.prototype.toJSON -var classof = _dereq_(17); -var from = _dereq_(10); -module.exports = function (NAME) { - return function toJSON() { - if (classof(this) != NAME) throw TypeError(NAME + "#toJSON isn't generic"); - return from(this); - }; -}; - -},{"10":10,"17":17}],21:[function(_dereq_,module,exports){ +},{"125":125,"15":15,"32":32,"36":36,"45":45,"61":61,"63":63,"70":70,"74":74,"75":75,"93":93,"99":99}],28:[function(_dereq_,module,exports){ 'use strict'; var redefineAll = _dereq_(93); -var getWeak = _dereq_(66).getWeak; -var anObject = _dereq_(7); -var isObject = _dereq_(51); -var anInstance = _dereq_(6); -var forOf = _dereq_(39); -var createArrayMethod = _dereq_(12); -var $has = _dereq_(41); +var getWeak = _dereq_(70).getWeak; +var anObject = _dereq_(16); +var isObject = _dereq_(57); +var anInstance = _dereq_(15); +var forOf = _dereq_(45); +var createArrayMethod = _dereq_(20); +var $has = _dereq_(47); var validate = _dereq_(125); var arrayFind = createArrayMethod(5); var arrayFindIndex = createArrayMethod(6); @@ -553,20 +715,20 @@ module.exports = { ufstore: uncaughtFrozenStore }; -},{"12":12,"125":125,"39":39,"41":41,"51":51,"6":6,"66":66,"7":7,"93":93}],22:[function(_dereq_,module,exports){ +},{"125":125,"15":15,"16":16,"20":20,"45":45,"47":47,"57":57,"70":70,"93":93}],29:[function(_dereq_,module,exports){ 'use strict'; -var global = _dereq_(40); -var $export = _dereq_(33); +var global = _dereq_(46); +var $export = _dereq_(40); var redefine = _dereq_(94); var redefineAll = _dereq_(93); -var meta = _dereq_(66); -var forOf = _dereq_(39); -var anInstance = _dereq_(6); -var isObject = _dereq_(51); -var fails = _dereq_(35); -var $iterDetect = _dereq_(56); -var setToStringTag = _dereq_(101); -var inheritIfRequired = _dereq_(45); +var meta = _dereq_(70); +var forOf = _dereq_(45); +var anInstance = _dereq_(15); +var isObject = _dereq_(57); +var fails = _dereq_(42); +var $iterDetect = _dereq_(62); +var setToStringTag = _dereq_(100); +var inheritIfRequired = _dereq_(51); module.exports = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) { var Base = global[NAME]; @@ -640,13 +802,13 @@ module.exports = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) { return C; }; -},{"101":101,"33":33,"35":35,"39":39,"40":40,"45":45,"51":51,"56":56,"6":6,"66":66,"93":93,"94":94}],23:[function(_dereq_,module,exports){ -var core = module.exports = { version: '2.5.0' }; +},{"100":100,"15":15,"40":40,"42":42,"45":45,"46":46,"51":51,"57":57,"62":62,"70":70,"93":93,"94":94}],30:[function(_dereq_,module,exports){ +var core = module.exports = { version: '2.6.1' }; if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef -},{}],24:[function(_dereq_,module,exports){ +},{}],31:[function(_dereq_,module,exports){ 'use strict'; -var $defineProperty = _dereq_(72); +var $defineProperty = _dereq_(75); var createDesc = _dereq_(92); module.exports = function (object, index, value) { @@ -654,9 +816,9 @@ module.exports = function (object, index, value) { else object[index] = value; }; -},{"72":72,"92":92}],25:[function(_dereq_,module,exports){ +},{"75":75,"92":92}],32:[function(_dereq_,module,exports){ // optional / simple context binding -var aFunction = _dereq_(3); +var aFunction = _dereq_(11); module.exports = function (fn, that, length) { aFunction(fn); if (that === undefined) return fn; @@ -676,10 +838,10 @@ module.exports = function (fn, that, length) { }; }; -},{"3":3}],26:[function(_dereq_,module,exports){ +},{"11":11}],33:[function(_dereq_,module,exports){ 'use strict'; // 20.3.4.36 / 15.9.5.43 Date.prototype.toISOString() -var fails = _dereq_(35); +var fails = _dereq_(42); var getTime = Date.prototype.getTime; var $toISOString = Date.prototype.toISOString; @@ -704,10 +866,10 @@ module.exports = (fails(function () { ':' + lz(d.getUTCSeconds()) + '.' + (m > 99 ? m : '0' + lz(m)) + 'Z'; } : $toISOString; -},{"35":35}],27:[function(_dereq_,module,exports){ +},{"42":42}],34:[function(_dereq_,module,exports){ 'use strict'; -var anObject = _dereq_(7); -var toPrimitive = _dereq_(120); +var anObject = _dereq_(16); +var toPrimitive = _dereq_(119); var NUMBER = 'number'; module.exports = function (hint) { @@ -715,39 +877,39 @@ module.exports = function (hint) { return toPrimitive(anObject(this), hint != NUMBER); }; -},{"120":120,"7":7}],28:[function(_dereq_,module,exports){ +},{"119":119,"16":16}],35:[function(_dereq_,module,exports){ // 7.2.1 RequireObjectCoercible(argument) module.exports = function (it) { if (it == undefined) throw TypeError("Can't call method on " + it); return it; }; -},{}],29:[function(_dereq_,module,exports){ +},{}],36:[function(_dereq_,module,exports){ // Thank's IE8 for his funny defineProperty -module.exports = !_dereq_(35)(function () { +module.exports = !_dereq_(42)(function () { return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7; }); -},{"35":35}],30:[function(_dereq_,module,exports){ -var isObject = _dereq_(51); -var document = _dereq_(40).document; +},{"42":42}],37:[function(_dereq_,module,exports){ +var isObject = _dereq_(57); +var document = _dereq_(46).document; // typeof document.createElement is 'object' in old IE var is = isObject(document) && isObject(document.createElement); module.exports = function (it) { return is ? document.createElement(it) : {}; }; -},{"40":40,"51":51}],31:[function(_dereq_,module,exports){ +},{"46":46,"57":57}],38:[function(_dereq_,module,exports){ // IE 8- don't enum bug keys module.exports = ( 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf' ).split(','); -},{}],32:[function(_dereq_,module,exports){ +},{}],39:[function(_dereq_,module,exports){ // all enumerable object keys, includes symbols -var getKeys = _dereq_(81); -var gOPS = _dereq_(78); -var pIE = _dereq_(82); +var getKeys = _dereq_(83); +var gOPS = _dereq_(80); +var pIE = _dereq_(84); module.exports = function (it) { var result = getKeys(it); var getSymbols = gOPS.f; @@ -760,12 +922,12 @@ module.exports = function (it) { } return result; }; -},{"78":78,"81":81,"82":82}],33:[function(_dereq_,module,exports){ -var global = _dereq_(40); -var core = _dereq_(23); -var hide = _dereq_(42); +},{"80":80,"83":83,"84":84}],40:[function(_dereq_,module,exports){ +var global = _dereq_(46); +var core = _dereq_(30); +var hide = _dereq_(48); var redefine = _dereq_(94); -var ctx = _dereq_(25); +var ctx = _dereq_(32); var PROTOTYPE = 'prototype'; var $export = function (type, name, source) { @@ -805,7 +967,7 @@ $export.U = 64; // safe $export.R = 128; // real proto method for `library` module.exports = $export; -},{"23":23,"25":25,"40":40,"42":42,"94":94}],34:[function(_dereq_,module,exports){ +},{"30":30,"32":32,"46":46,"48":48,"94":94}],41:[function(_dereq_,module,exports){ var MATCH = _dereq_(128)('match'); module.exports = function (KEY) { var re = /./; @@ -819,7 +981,7 @@ module.exports = function (KEY) { } return true; }; -},{"128":128}],35:[function(_dereq_,module,exports){ +},{"128":128}],42:[function(_dereq_,module,exports){ module.exports = function (exec) { try { return !!exec(); @@ -828,24 +990,92 @@ module.exports = function (exec) { } }; -},{}],36:[function(_dereq_,module,exports){ +},{}],43:[function(_dereq_,module,exports){ 'use strict'; -var hide = _dereq_(42); +_dereq_(224); var redefine = _dereq_(94); -var fails = _dereq_(35); -var defined = _dereq_(28); +var hide = _dereq_(48); +var fails = _dereq_(42); +var defined = _dereq_(35); var wks = _dereq_(128); +var regexpExec = _dereq_(96); + +var SPECIES = wks('species'); + +var REPLACE_SUPPORTS_NAMED_GROUPS = !fails(function () { + // #replace needs built-in support for named groups. + // #match works fine because it just return the exec results, even if it has + // a "grops" property. + var re = /./; + re.exec = function () { + var result = []; + result.groups = { a: '7' }; + return result; + }; + return ''.replace(re, '$') !== '7'; +}); + +var SPLIT_WORKS_WITH_OVERWRITTEN_EXEC = (function () { + // Chrome 51 has a buggy "split" implementation when RegExp#exec !== nativeExec + var re = /(?:)/; + var originalExec = re.exec; + re.exec = function () { return originalExec.apply(this, arguments); }; + var result = 'ab'.split(re); + return result.length === 2 && result[0] === 'a' && result[1] === 'b'; +})(); module.exports = function (KEY, length, exec) { var SYMBOL = wks(KEY); - var fns = exec(defined, SYMBOL, ''[KEY]); - var strfn = fns[0]; - var rxfn = fns[1]; - if (fails(function () { + + var DELEGATES_TO_SYMBOL = !fails(function () { + // String methods call symbol-named RegEp methods var O = {}; O[SYMBOL] = function () { return 7; }; return ''[KEY](O) != 7; - })) { + }); + + var DELEGATES_TO_EXEC = DELEGATES_TO_SYMBOL ? !fails(function () { + // Symbol-named RegExp methods call .exec + var execCalled = false; + var re = /a/; + re.exec = function () { execCalled = true; return null; }; + if (KEY === 'split') { + // RegExp[@@split] doesn't call the regex's exec method, but first creates + // a new one. We need to return the patched regex when creating the new one. + re.constructor = {}; + re.constructor[SPECIES] = function () { return re; }; + } + re[SYMBOL](''); + return !execCalled; + }) : undefined; + + if ( + !DELEGATES_TO_SYMBOL || + !DELEGATES_TO_EXEC || + (KEY === 'replace' && !REPLACE_SUPPORTS_NAMED_GROUPS) || + (KEY === 'split' && !SPLIT_WORKS_WITH_OVERWRITTEN_EXEC) + ) { + var nativeRegExpMethod = /./[SYMBOL]; + var fns = exec( + defined, + SYMBOL, + ''[KEY], + function maybeCallNative(nativeMethod, regexp, str, arg2, forceStringMethod) { + if (regexp.exec === regexpExec) { + if (DELEGATES_TO_SYMBOL && !forceStringMethod) { + // The native String method already delegates to @@method (this + // polyfilled function), leasing to infinite recursion. + // We avoid it by directly calling the native @@method method. + return { done: true, value: nativeRegExpMethod.call(regexp, str, arg2) }; + } + return { done: true, value: nativeMethod.call(str, regexp, arg2) }; + } + return { done: false }; + } + ); + var strfn = fns[0]; + var rxfn = fns[1]; + redefine(String.prototype, KEY, strfn); hide(RegExp.prototype, SYMBOL, length == 2 // 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue) @@ -858,10 +1088,10 @@ module.exports = function (KEY, length, exec) { } }; -},{"128":128,"28":28,"35":35,"42":42,"94":94}],37:[function(_dereq_,module,exports){ +},{"128":128,"224":224,"35":35,"42":42,"48":48,"94":94,"96":96}],44:[function(_dereq_,module,exports){ 'use strict'; // 21.2.5.3 get RegExp.prototype.flags -var anObject = _dereq_(7); +var anObject = _dereq_(16); module.exports = function () { var that = anObject(this); var result = ''; @@ -873,53 +1103,12 @@ module.exports = function () { return result; }; -},{"7":7}],38:[function(_dereq_,module,exports){ -'use strict'; -// https://tc39.github.io/proposal-flatMap/#sec-FlattenIntoArray -var isArray = _dereq_(49); -var isObject = _dereq_(51); -var toLength = _dereq_(118); -var ctx = _dereq_(25); -var IS_CONCAT_SPREADABLE = _dereq_(128)('isConcatSpreadable'); - -function flattenIntoArray(target, original, source, sourceLen, start, depth, mapper, thisArg) { - var targetIndex = start; - var sourceIndex = 0; - var mapFn = mapper ? ctx(mapper, thisArg, 3) : false; - var element, spreadable; - - while (sourceIndex < sourceLen) { - if (sourceIndex in source) { - element = mapFn ? mapFn(source[sourceIndex], sourceIndex, original) : source[sourceIndex]; - - spreadable = false; - if (isObject(element)) { - spreadable = element[IS_CONCAT_SPREADABLE]; - spreadable = spreadable !== undefined ? !!spreadable : isArray(element); - } - - if (spreadable && depth > 0) { - targetIndex = flattenIntoArray(target, original, element, toLength(element.length), targetIndex, depth - 1) - 1; - } else { - if (targetIndex >= 0x1fffffffffffff) throw TypeError(); - target[targetIndex] = element; - } - - targetIndex++; - } - sourceIndex++; - } - return targetIndex; -} - -module.exports = flattenIntoArray; - -},{"118":118,"128":128,"25":25,"49":49,"51":51}],39:[function(_dereq_,module,exports){ -var ctx = _dereq_(25); -var call = _dereq_(53); -var isArrayIter = _dereq_(48); -var anObject = _dereq_(7); -var toLength = _dereq_(118); +},{"16":16}],45:[function(_dereq_,module,exports){ +var ctx = _dereq_(32); +var call = _dereq_(59); +var isArrayIter = _dereq_(54); +var anObject = _dereq_(16); +var toLength = _dereq_(117); var getIterFn = _dereq_(129); var BREAK = {}; var RETURN = {}; @@ -941,7 +1130,7 @@ var exports = module.exports = function (iterable, entries, fn, that, ITERATOR) exports.BREAK = BREAK; exports.RETURN = RETURN; -},{"118":118,"129":129,"25":25,"48":48,"53":53,"7":7}],40:[function(_dereq_,module,exports){ +},{"117":117,"129":129,"16":16,"32":32,"54":54,"59":59}],46:[function(_dereq_,module,exports){ // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 var global = module.exports = typeof window != 'undefined' && window.Math == Math ? window : typeof self != 'undefined' && self.Math == Math ? self @@ -949,34 +1138,34 @@ var global = module.exports = typeof window != 'undefined' && window.Math == Mat : Function('return this')(); if (typeof __g == 'number') __g = global; // eslint-disable-line no-undef -},{}],41:[function(_dereq_,module,exports){ +},{}],47:[function(_dereq_,module,exports){ var hasOwnProperty = {}.hasOwnProperty; module.exports = function (it, key) { return hasOwnProperty.call(it, key); }; -},{}],42:[function(_dereq_,module,exports){ -var dP = _dereq_(72); +},{}],48:[function(_dereq_,module,exports){ +var dP = _dereq_(75); var createDesc = _dereq_(92); -module.exports = _dereq_(29) ? function (object, key, value) { +module.exports = _dereq_(36) ? function (object, key, value) { return dP.f(object, key, createDesc(1, value)); } : function (object, key, value) { object[key] = value; return object; }; -},{"29":29,"72":72,"92":92}],43:[function(_dereq_,module,exports){ -var document = _dereq_(40).document; +},{"36":36,"75":75,"92":92}],49:[function(_dereq_,module,exports){ +var document = _dereq_(46).document; module.exports = document && document.documentElement; -},{"40":40}],44:[function(_dereq_,module,exports){ -module.exports = !_dereq_(29) && !_dereq_(35)(function () { - return Object.defineProperty(_dereq_(30)('div'), 'a', { get: function () { return 7; } }).a != 7; +},{"46":46}],50:[function(_dereq_,module,exports){ +module.exports = !_dereq_(36) && !_dereq_(42)(function () { + return Object.defineProperty(_dereq_(37)('div'), 'a', { get: function () { return 7; } }).a != 7; }); -},{"29":29,"30":30,"35":35}],45:[function(_dereq_,module,exports){ -var isObject = _dereq_(51); -var setPrototypeOf = _dereq_(99).set; +},{"36":36,"37":37,"42":42}],51:[function(_dereq_,module,exports){ +var isObject = _dereq_(57); +var setPrototypeOf = _dereq_(98).set; module.exports = function (that, target, C) { var S = target.constructor; var P; @@ -985,7 +1174,7 @@ module.exports = function (that, target, C) { } return that; }; -},{"51":51,"99":99}],46:[function(_dereq_,module,exports){ +},{"57":57,"98":98}],52:[function(_dereq_,module,exports){ // fast apply, http://jsperf.lnkit.com/fast-apply/5 module.exports = function (fn, args, that) { var un = that === undefined; @@ -1003,17 +1192,17 @@ module.exports = function (fn, args, that) { } return fn.apply(that, args); }; -},{}],47:[function(_dereq_,module,exports){ +},{}],53:[function(_dereq_,module,exports){ // fallback for non-array-like ES3 and non-enumerable old V8 strings -var cof = _dereq_(18); +var cof = _dereq_(26); // eslint-disable-next-line no-prototype-builtins module.exports = Object('z').propertyIsEnumerable(0) ? Object : function (it) { return cof(it) == 'String' ? it.split('') : Object(it); }; -},{"18":18}],48:[function(_dereq_,module,exports){ +},{"26":26}],54:[function(_dereq_,module,exports){ // check on default Array iterator -var Iterators = _dereq_(58); +var Iterators = _dereq_(64); var ITERATOR = _dereq_(128)('iterator'); var ArrayProto = Array.prototype; @@ -1021,39 +1210,39 @@ module.exports = function (it) { return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it); }; -},{"128":128,"58":58}],49:[function(_dereq_,module,exports){ +},{"128":128,"64":64}],55:[function(_dereq_,module,exports){ // 7.2.2 IsArray(argument) -var cof = _dereq_(18); +var cof = _dereq_(26); module.exports = Array.isArray || function isArray(arg) { return cof(arg) == 'Array'; }; -},{"18":18}],50:[function(_dereq_,module,exports){ +},{"26":26}],56:[function(_dereq_,module,exports){ // 20.1.2.3 Number.isInteger(number) -var isObject = _dereq_(51); +var isObject = _dereq_(57); var floor = Math.floor; module.exports = function isInteger(it) { return !isObject(it) && isFinite(it) && floor(it) === it; }; -},{"51":51}],51:[function(_dereq_,module,exports){ +},{"57":57}],57:[function(_dereq_,module,exports){ module.exports = function (it) { return typeof it === 'object' ? it !== null : typeof it === 'function'; }; -},{}],52:[function(_dereq_,module,exports){ +},{}],58:[function(_dereq_,module,exports){ // 7.2.8 IsRegExp(argument) -var isObject = _dereq_(51); -var cof = _dereq_(18); +var isObject = _dereq_(57); +var cof = _dereq_(26); var MATCH = _dereq_(128)('match'); module.exports = function (it) { var isRegExp; return isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : cof(it) == 'RegExp'); }; -},{"128":128,"18":18,"51":51}],53:[function(_dereq_,module,exports){ +},{"128":128,"26":26,"57":57}],59:[function(_dereq_,module,exports){ // call something on iterator step with safe closing on error -var anObject = _dereq_(7); +var anObject = _dereq_(16); module.exports = function (iterator, fn, value, entries) { try { return entries ? fn(anObject(value)[0], value[1]) : fn(value); @@ -1065,32 +1254,31 @@ module.exports = function (iterator, fn, value, entries) { } }; -},{"7":7}],54:[function(_dereq_,module,exports){ +},{"16":16}],60:[function(_dereq_,module,exports){ 'use strict'; -var create = _dereq_(71); +var create = _dereq_(74); var descriptor = _dereq_(92); -var setToStringTag = _dereq_(101); +var setToStringTag = _dereq_(100); var IteratorPrototype = {}; // 25.1.2.1.1 %IteratorPrototype%[@@iterator]() -_dereq_(42)(IteratorPrototype, _dereq_(128)('iterator'), function () { return this; }); +_dereq_(48)(IteratorPrototype, _dereq_(128)('iterator'), function () { return this; }); module.exports = function (Constructor, NAME, next) { Constructor.prototype = create(IteratorPrototype, { next: descriptor(1, next) }); setToStringTag(Constructor, NAME + ' Iterator'); }; -},{"101":101,"128":128,"42":42,"71":71,"92":92}],55:[function(_dereq_,module,exports){ +},{"100":100,"128":128,"48":48,"74":74,"92":92}],61:[function(_dereq_,module,exports){ 'use strict'; -var LIBRARY = _dereq_(60); -var $export = _dereq_(33); +var LIBRARY = _dereq_(65); +var $export = _dereq_(40); var redefine = _dereq_(94); -var hide = _dereq_(42); -var has = _dereq_(41); -var Iterators = _dereq_(58); -var $iterCreate = _dereq_(54); -var setToStringTag = _dereq_(101); -var getPrototypeOf = _dereq_(79); +var hide = _dereq_(48); +var Iterators = _dereq_(64); +var $iterCreate = _dereq_(60); +var setToStringTag = _dereq_(100); +var getPrototypeOf = _dereq_(81); var ITERATOR = _dereq_(128)('iterator'); var BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next` var FF_ITERATOR = '@@iterator'; @@ -1124,7 +1312,7 @@ module.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCE // Set @@toStringTag to native iterators setToStringTag(IteratorPrototype, TAG, true); // fix for some old engines - if (!LIBRARY && !has(IteratorPrototype, ITERATOR)) hide(IteratorPrototype, ITERATOR, returnThis); + if (!LIBRARY && typeof IteratorPrototype[ITERATOR] != 'function') hide(IteratorPrototype, ITERATOR, returnThis); } } // fix Array#{values, @@iterator}.name in V8 / FF @@ -1152,7 +1340,7 @@ module.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCE return methods; }; -},{"101":101,"128":128,"33":33,"41":41,"42":42,"54":54,"58":58,"60":60,"79":79,"94":94}],56:[function(_dereq_,module,exports){ +},{"100":100,"128":128,"40":40,"48":48,"60":60,"64":64,"65":65,"81":81,"94":94}],62:[function(_dereq_,module,exports){ var ITERATOR = _dereq_(128)('iterator'); var SAFE_CLOSING = false; @@ -1176,30 +1364,18 @@ module.exports = function (exec, skipClosing) { return safe; }; -},{"128":128}],57:[function(_dereq_,module,exports){ +},{"128":128}],63:[function(_dereq_,module,exports){ module.exports = function (done, value) { return { value: value, done: !!done }; }; -},{}],58:[function(_dereq_,module,exports){ +},{}],64:[function(_dereq_,module,exports){ module.exports = {}; -},{}],59:[function(_dereq_,module,exports){ -var getKeys = _dereq_(81); -var toIObject = _dereq_(117); -module.exports = function (object, el) { - var O = toIObject(object); - var keys = getKeys(O); - var length = keys.length; - var index = 0; - var key; - while (length > index) if (O[key = keys[index++]] === el) return key; -}; - -},{"117":117,"81":81}],60:[function(_dereq_,module,exports){ +},{}],65:[function(_dereq_,module,exports){ module.exports = false; -},{}],61:[function(_dereq_,module,exports){ +},{}],66:[function(_dereq_,module,exports){ // 20.2.2.14 Math.expm1(x) var $expm1 = Math.expm1; module.exports = (!$expm1 @@ -1211,9 +1387,9 @@ module.exports = (!$expm1 return (x = +x) == 0 ? x : x > -1e-6 && x < 1e-6 ? x + x * x / 2 : Math.exp(x) - 1; } : $expm1; -},{}],62:[function(_dereq_,module,exports){ +},{}],67:[function(_dereq_,module,exports){ // 20.2.2.16 Math.fround(x) -var sign = _dereq_(65); +var sign = _dereq_(69); var pow = Math.pow; var EPSILON = pow(2, -52); var EPSILON32 = pow(2, -23); @@ -1236,49 +1412,29 @@ module.exports = Math.fround || function fround(x) { return $sign * result; }; -},{"65":65}],63:[function(_dereq_,module,exports){ +},{"69":69}],68:[function(_dereq_,module,exports){ // 20.2.2.20 Math.log1p(x) module.exports = Math.log1p || function log1p(x) { return (x = +x) > -1e-8 && x < 1e-8 ? x - x * x / 2 : Math.log(1 + x); }; -},{}],64:[function(_dereq_,module,exports){ -// https://rwaldron.github.io/proposal-math-extensions/ -module.exports = Math.scale || function scale(x, inLow, inHigh, outLow, outHigh) { - if ( - arguments.length === 0 - // eslint-disable-next-line no-self-compare - || x != x - // eslint-disable-next-line no-self-compare - || inLow != inLow - // eslint-disable-next-line no-self-compare - || inHigh != inHigh - // eslint-disable-next-line no-self-compare - || outLow != outLow - // eslint-disable-next-line no-self-compare - || outHigh != outHigh - ) return NaN; - if (x === Infinity || x === -Infinity) return x; - return (x - inLow) * (outHigh - outLow) / (inHigh - inLow) + outLow; -}; - -},{}],65:[function(_dereq_,module,exports){ +},{}],69:[function(_dereq_,module,exports){ // 20.2.2.28 Math.sign(x) module.exports = Math.sign || function sign(x) { // eslint-disable-next-line no-self-compare return (x = +x) == 0 || x != x ? x : x < 0 ? -1 : 1; }; -},{}],66:[function(_dereq_,module,exports){ -var META = _dereq_(124)('meta'); -var isObject = _dereq_(51); -var has = _dereq_(41); -var setDesc = _dereq_(72).f; +},{}],70:[function(_dereq_,module,exports){ +var META = _dereq_(123)('meta'); +var isObject = _dereq_(57); +var has = _dereq_(47); +var setDesc = _dereq_(75).f; var id = 0; var isExtensible = Object.isExtensible || function () { return true; }; -var FREEZE = !_dereq_(35)(function () { +var FREEZE = !_dereq_(42)(function () { return isExtensible(Object.preventExtensions({})); }); var setMeta = function (it) { @@ -1324,66 +1480,13 @@ var meta = module.exports = { onFreeze: onFreeze }; -},{"124":124,"35":35,"41":41,"51":51,"72":72}],67:[function(_dereq_,module,exports){ -var Map = _dereq_(160); -var $export = _dereq_(33); -var shared = _dereq_(103)('metadata'); -var store = shared.store || (shared.store = new (_dereq_(266))()); - -var getOrCreateMetadataMap = function (target, targetKey, create) { - var targetMetadata = store.get(target); - if (!targetMetadata) { - if (!create) return undefined; - store.set(target, targetMetadata = new Map()); - } - var keyMetadata = targetMetadata.get(targetKey); - if (!keyMetadata) { - if (!create) return undefined; - targetMetadata.set(targetKey, keyMetadata = new Map()); - } return keyMetadata; -}; -var ordinaryHasOwnMetadata = function (MetadataKey, O, P) { - var metadataMap = getOrCreateMetadataMap(O, P, false); - return metadataMap === undefined ? false : metadataMap.has(MetadataKey); -}; -var ordinaryGetOwnMetadata = function (MetadataKey, O, P) { - var metadataMap = getOrCreateMetadataMap(O, P, false); - return metadataMap === undefined ? undefined : metadataMap.get(MetadataKey); -}; -var ordinaryDefineOwnMetadata = function (MetadataKey, MetadataValue, O, P) { - getOrCreateMetadataMap(O, P, true).set(MetadataKey, MetadataValue); -}; -var ordinaryOwnMetadataKeys = function (target, targetKey) { - var metadataMap = getOrCreateMetadataMap(target, targetKey, false); - var keys = []; - if (metadataMap) metadataMap.forEach(function (_, key) { keys.push(key); }); - return keys; -}; -var toMetaKey = function (it) { - return it === undefined || typeof it == 'symbol' ? it : String(it); -}; -var exp = function (O) { - $export($export.S, 'Reflect', O); -}; - -module.exports = { - store: store, - map: getOrCreateMetadataMap, - has: ordinaryHasOwnMetadata, - get: ordinaryGetOwnMetadata, - set: ordinaryDefineOwnMetadata, - keys: ordinaryOwnMetadataKeys, - key: toMetaKey, - exp: exp -}; - -},{"103":103,"160":160,"266":266,"33":33}],68:[function(_dereq_,module,exports){ -var global = _dereq_(40); -var macrotask = _dereq_(113).set; +},{"123":123,"42":42,"47":47,"57":57,"75":75}],71:[function(_dereq_,module,exports){ +var global = _dereq_(46); +var macrotask = _dereq_(112).set; var Observer = global.MutationObserver || global.WebKitMutationObserver; var process = global.process; var Promise = global.Promise; -var isNode = _dereq_(18)(process) == 'process'; +var isNode = _dereq_(26)(process) == 'process'; module.exports = function () { var head, last, notify; @@ -1410,8 +1513,8 @@ module.exports = function () { notify = function () { process.nextTick(flush); }; - // browsers with MutationObserver - } else if (Observer) { + // browsers with MutationObserver, except iOS Safari - https://github.com/zloirock/core-js/issues/339 + } else if (Observer && !(global.navigator && global.navigator.standalone)) { var toggle = true; var node = document.createTextNode(''); new Observer(flush).observe(node, { characterData: true }); // eslint-disable-line no-new @@ -1420,7 +1523,8 @@ module.exports = function () { }; // environments with maybe non-completely correct, but existent Promise } else if (Promise && Promise.resolve) { - var promise = Promise.resolve(); + // Promise.resolve without an argument throws an error in LG WebOS 2 + var promise = Promise.resolve(undefined); notify = function () { promise.then(flush); }; @@ -1447,10 +1551,10 @@ module.exports = function () { }; }; -},{"113":113,"18":18,"40":40}],69:[function(_dereq_,module,exports){ +},{"112":112,"26":26,"46":46}],72:[function(_dereq_,module,exports){ 'use strict'; // 25.4.1.5 NewPromiseCapability(C) -var aFunction = _dereq_(3); +var aFunction = _dereq_(11); function PromiseCapability(C) { var resolve, reject; @@ -1467,18 +1571,18 @@ module.exports.f = function (C) { return new PromiseCapability(C); }; -},{"3":3}],70:[function(_dereq_,module,exports){ +},{"11":11}],73:[function(_dereq_,module,exports){ 'use strict'; // 19.1.2.1 Object.assign(target, source, ...) -var getKeys = _dereq_(81); -var gOPS = _dereq_(78); -var pIE = _dereq_(82); -var toObject = _dereq_(119); -var IObject = _dereq_(47); +var getKeys = _dereq_(83); +var gOPS = _dereq_(80); +var pIE = _dereq_(84); +var toObject = _dereq_(118); +var IObject = _dereq_(53); var $assign = Object.assign; // should work with symbols and should have deterministic property order (V8 bug) -module.exports = !$assign || _dereq_(35)(function () { +module.exports = !$assign || _dereq_(42)(function () { var A = {}; var B = {}; // eslint-disable-next-line no-undef @@ -1503,25 +1607,25 @@ module.exports = !$assign || _dereq_(35)(function () { } return T; } : $assign; -},{"119":119,"35":35,"47":47,"78":78,"81":81,"82":82}],71:[function(_dereq_,module,exports){ +},{"118":118,"42":42,"53":53,"80":80,"83":83,"84":84}],74:[function(_dereq_,module,exports){ // 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) -var anObject = _dereq_(7); -var dPs = _dereq_(73); -var enumBugKeys = _dereq_(31); -var IE_PROTO = _dereq_(102)('IE_PROTO'); +var anObject = _dereq_(16); +var dPs = _dereq_(76); +var enumBugKeys = _dereq_(38); +var IE_PROTO = _dereq_(101)('IE_PROTO'); var Empty = function () { /* empty */ }; var PROTOTYPE = 'prototype'; // Create object with fake `null` prototype: use iframe Object with cleared prototype var createDict = function () { // Thrash, waste and sodomy: IE GC bug - var iframe = _dereq_(30)('iframe'); + var iframe = _dereq_(37)('iframe'); var i = enumBugKeys.length; var lt = '<'; var gt = '>'; var iframeDocument; iframe.style.display = 'none'; - _dereq_(43).appendChild(iframe); + _dereq_(49).appendChild(iframe); iframe.src = 'javascript:'; // eslint-disable-line no-script-url // createDict = iframe.contentWindow.Object; // html.removeChild(iframe); @@ -1546,13 +1650,13 @@ module.exports = Object.create || function create(O, Properties) { return Properties === undefined ? result : dPs(result, Properties); }; -},{"102":102,"30":30,"31":31,"43":43,"7":7,"73":73}],72:[function(_dereq_,module,exports){ -var anObject = _dereq_(7); -var IE8_DOM_DEFINE = _dereq_(44); -var toPrimitive = _dereq_(120); +},{"101":101,"16":16,"37":37,"38":38,"49":49,"76":76}],75:[function(_dereq_,module,exports){ +var anObject = _dereq_(16); +var IE8_DOM_DEFINE = _dereq_(50); +var toPrimitive = _dereq_(119); var dP = Object.defineProperty; -exports.f = _dereq_(29) ? Object.defineProperty : function defineProperty(O, P, Attributes) { +exports.f = _dereq_(36) ? Object.defineProperty : function defineProperty(O, P, Attributes) { anObject(O); P = toPrimitive(P, true); anObject(Attributes); @@ -1564,12 +1668,12 @@ exports.f = _dereq_(29) ? Object.defineProperty : function defineProperty(O, P, return O; }; -},{"120":120,"29":29,"44":44,"7":7}],73:[function(_dereq_,module,exports){ -var dP = _dereq_(72); -var anObject = _dereq_(7); -var getKeys = _dereq_(81); +},{"119":119,"16":16,"36":36,"50":50}],76:[function(_dereq_,module,exports){ +var dP = _dereq_(75); +var anObject = _dereq_(16); +var getKeys = _dereq_(83); -module.exports = _dereq_(29) ? Object.defineProperties : function defineProperties(O, Properties) { +module.exports = _dereq_(36) ? Object.defineProperties : function defineProperties(O, Properties) { anObject(O); var keys = getKeys(Properties); var length = keys.length; @@ -1579,27 +1683,16 @@ module.exports = _dereq_(29) ? Object.defineProperties : function defineProperti return O; }; -},{"29":29,"7":7,"72":72,"81":81}],74:[function(_dereq_,module,exports){ -'use strict'; -// Forced replacement prototype accessors methods -module.exports = _dereq_(60) || !_dereq_(35)(function () { - var K = Math.random(); - // In FF throws only define methods - // eslint-disable-next-line no-undef, no-useless-call - __defineSetter__.call(null, K, function () { /* empty */ }); - delete _dereq_(40)[K]; -}); - -},{"35":35,"40":40,"60":60}],75:[function(_dereq_,module,exports){ -var pIE = _dereq_(82); +},{"16":16,"36":36,"75":75,"83":83}],77:[function(_dereq_,module,exports){ +var pIE = _dereq_(84); var createDesc = _dereq_(92); -var toIObject = _dereq_(117); -var toPrimitive = _dereq_(120); -var has = _dereq_(41); -var IE8_DOM_DEFINE = _dereq_(44); +var toIObject = _dereq_(116); +var toPrimitive = _dereq_(119); +var has = _dereq_(47); +var IE8_DOM_DEFINE = _dereq_(50); var gOPD = Object.getOwnPropertyDescriptor; -exports.f = _dereq_(29) ? gOPD : function getOwnPropertyDescriptor(O, P) { +exports.f = _dereq_(36) ? gOPD : function getOwnPropertyDescriptor(O, P) { O = toIObject(O); P = toPrimitive(P, true); if (IE8_DOM_DEFINE) try { @@ -1608,10 +1701,10 @@ exports.f = _dereq_(29) ? gOPD : function getOwnPropertyDescriptor(O, P) { if (has(O, P)) return createDesc(!pIE.f.call(O, P), O[P]); }; -},{"117":117,"120":120,"29":29,"41":41,"44":44,"82":82,"92":92}],76:[function(_dereq_,module,exports){ +},{"116":116,"119":119,"36":36,"47":47,"50":50,"84":84,"92":92}],78:[function(_dereq_,module,exports){ // fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window -var toIObject = _dereq_(117); -var gOPN = _dereq_(77).f; +var toIObject = _dereq_(116); +var gOPN = _dereq_(79).f; var toString = {}.toString; var windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames @@ -1629,23 +1722,23 @@ module.exports.f = function getOwnPropertyNames(it) { return windowNames && toString.call(it) == '[object Window]' ? getWindowNames(it) : gOPN(toIObject(it)); }; -},{"117":117,"77":77}],77:[function(_dereq_,module,exports){ +},{"116":116,"79":79}],79:[function(_dereq_,module,exports){ // 19.1.2.7 / 15.2.3.4 Object.getOwnPropertyNames(O) -var $keys = _dereq_(80); -var hiddenKeys = _dereq_(31).concat('length', 'prototype'); +var $keys = _dereq_(82); +var hiddenKeys = _dereq_(38).concat('length', 'prototype'); exports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) { return $keys(O, hiddenKeys); }; -},{"31":31,"80":80}],78:[function(_dereq_,module,exports){ +},{"38":38,"82":82}],80:[function(_dereq_,module,exports){ exports.f = Object.getOwnPropertySymbols; -},{}],79:[function(_dereq_,module,exports){ +},{}],81:[function(_dereq_,module,exports){ // 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O) -var has = _dereq_(41); -var toObject = _dereq_(119); -var IE_PROTO = _dereq_(102)('IE_PROTO'); +var has = _dereq_(47); +var toObject = _dereq_(118); +var IE_PROTO = _dereq_(101)('IE_PROTO'); var ObjectProto = Object.prototype; module.exports = Object.getPrototypeOf || function (O) { @@ -1656,11 +1749,11 @@ module.exports = Object.getPrototypeOf || function (O) { } return O instanceof Object ? ObjectProto : null; }; -},{"102":102,"119":119,"41":41}],80:[function(_dereq_,module,exports){ -var has = _dereq_(41); -var toIObject = _dereq_(117); -var arrayIndexOf = _dereq_(11)(false); -var IE_PROTO = _dereq_(102)('IE_PROTO'); +},{"101":101,"118":118,"47":47}],82:[function(_dereq_,module,exports){ +var has = _dereq_(47); +var toIObject = _dereq_(116); +var arrayIndexOf = _dereq_(19)(false); +var IE_PROTO = _dereq_(101)('IE_PROTO'); module.exports = function (object, names) { var O = toIObject(object); @@ -1675,23 +1768,23 @@ module.exports = function (object, names) { return result; }; -},{"102":102,"11":11,"117":117,"41":41}],81:[function(_dereq_,module,exports){ +},{"101":101,"116":116,"19":19,"47":47}],83:[function(_dereq_,module,exports){ // 19.1.2.14 / 15.2.3.14 Object.keys(O) -var $keys = _dereq_(80); -var enumBugKeys = _dereq_(31); +var $keys = _dereq_(82); +var enumBugKeys = _dereq_(38); module.exports = Object.keys || function keys(O) { return $keys(O, enumBugKeys); }; -},{"31":31,"80":80}],82:[function(_dereq_,module,exports){ +},{"38":38,"82":82}],84:[function(_dereq_,module,exports){ exports.f = {}.propertyIsEnumerable; -},{}],83:[function(_dereq_,module,exports){ +},{}],85:[function(_dereq_,module,exports){ // most Object methods by ES6 should accept primitives -var $export = _dereq_(33); -var core = _dereq_(23); -var fails = _dereq_(35); +var $export = _dereq_(40); +var core = _dereq_(30); +var fails = _dereq_(42); module.exports = function (KEY, exec) { var fn = (core.Object || {})[KEY] || Object[KEY]; var exp = {}; @@ -1699,10 +1792,10 @@ module.exports = function (KEY, exec) { $export($export.S + $export.F * fails(function () { fn(1); }), 'Object', exp); }; -},{"23":23,"33":33,"35":35}],84:[function(_dereq_,module,exports){ -var getKeys = _dereq_(81); -var toIObject = _dereq_(117); -var isEnum = _dereq_(82).f; +},{"30":30,"40":40,"42":42}],86:[function(_dereq_,module,exports){ +var getKeys = _dereq_(83); +var toIObject = _dereq_(116); +var isEnum = _dereq_(84).f; module.exports = function (isEntries) { return function (it) { var O = toIObject(it); @@ -1717,32 +1810,32 @@ module.exports = function (isEntries) { }; }; -},{"117":117,"81":81,"82":82}],85:[function(_dereq_,module,exports){ +},{"116":116,"83":83,"84":84}],87:[function(_dereq_,module,exports){ // all object keys, includes non-enumerable and symbols -var gOPN = _dereq_(77); -var gOPS = _dereq_(78); -var anObject = _dereq_(7); -var Reflect = _dereq_(40).Reflect; +var gOPN = _dereq_(79); +var gOPS = _dereq_(80); +var anObject = _dereq_(16); +var Reflect = _dereq_(46).Reflect; module.exports = Reflect && Reflect.ownKeys || function ownKeys(it) { var keys = gOPN.f(anObject(it)); var getSymbols = gOPS.f; return getSymbols ? keys.concat(getSymbols(it)) : keys; }; -},{"40":40,"7":7,"77":77,"78":78}],86:[function(_dereq_,module,exports){ -var $parseFloat = _dereq_(40).parseFloat; -var $trim = _dereq_(111).trim; +},{"16":16,"46":46,"79":79,"80":80}],88:[function(_dereq_,module,exports){ +var $parseFloat = _dereq_(46).parseFloat; +var $trim = _dereq_(110).trim; -module.exports = 1 / $parseFloat(_dereq_(112) + '-0') !== -Infinity ? function parseFloat(str) { +module.exports = 1 / $parseFloat(_dereq_(111) + '-0') !== -Infinity ? function parseFloat(str) { var string = $trim(String(str), 3); var result = $parseFloat(string); return result === 0 && string.charAt(0) == '-' ? -0 : result; } : $parseFloat; -},{"111":111,"112":112,"40":40}],87:[function(_dereq_,module,exports){ -var $parseInt = _dereq_(40).parseInt; -var $trim = _dereq_(111).trim; -var ws = _dereq_(112); +},{"110":110,"111":111,"46":46}],89:[function(_dereq_,module,exports){ +var $parseInt = _dereq_(46).parseInt; +var $trim = _dereq_(110).trim; +var ws = _dereq_(111); var hex = /^[-+]?0[xX]/; module.exports = $parseInt(ws + '08') !== 8 || $parseInt(ws + '0x16') !== 22 ? function parseInt(str, radix) { @@ -1750,37 +1843,7 @@ module.exports = $parseInt(ws + '08') !== 8 || $parseInt(ws + '0x16') !== 22 ? f return $parseInt(string, (radix >>> 0) || (hex.test(string) ? 16 : 10)); } : $parseInt; -},{"111":111,"112":112,"40":40}],88:[function(_dereq_,module,exports){ -'use strict'; -var path = _dereq_(89); -var invoke = _dereq_(46); -var aFunction = _dereq_(3); -module.exports = function (/* ...pargs */) { - var fn = aFunction(this); - var length = arguments.length; - var pargs = Array(length); - var i = 0; - var _ = path._; - var holder = false; - while (length > i) if ((pargs[i] = arguments[i++]) === _) holder = true; - return function (/* ...args */) { - var that = this; - var aLen = arguments.length; - var j = 0; - var k = 0; - var args; - if (!holder && !aLen) return invoke(fn, pargs, that); - args = pargs.slice(); - if (holder) for (;length > j; j++) if (args[j] === _) args[j] = arguments[k++]; - while (aLen > k) args.push(arguments[k++]); - return invoke(fn, args, that); - }; -}; - -},{"3":3,"46":46,"89":89}],89:[function(_dereq_,module,exports){ -module.exports = _dereq_(40); - -},{"40":40}],90:[function(_dereq_,module,exports){ +},{"110":110,"111":111,"46":46}],90:[function(_dereq_,module,exports){ module.exports = function (exec) { try { return { e: false, v: exec() }; @@ -1790,16 +1853,20 @@ module.exports = function (exec) { }; },{}],91:[function(_dereq_,module,exports){ -var newPromiseCapability = _dereq_(69); +var anObject = _dereq_(16); +var isObject = _dereq_(57); +var newPromiseCapability = _dereq_(72); module.exports = function (C, x) { + anObject(C); + if (isObject(x) && x.constructor === C) return x; var promiseCapability = newPromiseCapability.f(C); var resolve = promiseCapability.resolve; resolve(x); return promiseCapability.promise; }; -},{"69":69}],92:[function(_dereq_,module,exports){ +},{"16":16,"57":57,"72":72}],92:[function(_dereq_,module,exports){ module.exports = function (bitmap, value) { return { enumerable: !(bitmap & 1), @@ -1817,15 +1884,15 @@ module.exports = function (target, src, safe) { }; },{"94":94}],94:[function(_dereq_,module,exports){ -var global = _dereq_(40); -var hide = _dereq_(42); -var has = _dereq_(41); -var SRC = _dereq_(124)('src'); +var global = _dereq_(46); +var hide = _dereq_(48); +var has = _dereq_(47); +var SRC = _dereq_(123)('src'); var TO_STRING = 'toString'; var $toString = Function[TO_STRING]; var TPL = ('' + $toString).split(TO_STRING); -_dereq_(23).inspectSource = function (it) { +_dereq_(30).inspectSource = function (it) { return $toString.call(it); }; @@ -1849,72 +1916,101 @@ _dereq_(23).inspectSource = function (it) { return typeof this == 'function' && this[SRC] || $toString.call(this); }); -},{"124":124,"23":23,"40":40,"41":41,"42":42}],95:[function(_dereq_,module,exports){ -module.exports = function (regExp, replace) { - var replacer = replace === Object(replace) ? function (part) { - return replace[part]; - } : replace; - return function (it) { - return String(it).replace(regExp, replacer); - }; +},{"123":123,"30":30,"46":46,"47":47,"48":48}],95:[function(_dereq_,module,exports){ +'use strict'; + +var classof = _dereq_(25); +var builtinExec = RegExp.prototype.exec; + + // `RegExpExec` abstract operation +// https://tc39.github.io/ecma262/#sec-regexpexec +module.exports = function (R, S) { + var exec = R.exec; + if (typeof exec === 'function') { + var result = exec.call(R, S); + if (typeof result !== 'object') { + throw new TypeError('RegExp exec method returned something other than an Object or null'); + } + return result; + } + if (classof(R) !== 'RegExp') { + throw new TypeError('RegExp#exec called on incompatible receiver'); + } + return builtinExec.call(R, S); }; -},{}],96:[function(_dereq_,module,exports){ +},{"25":25}],96:[function(_dereq_,module,exports){ +'use strict'; + +var regexpFlags = _dereq_(44); + +var nativeExec = RegExp.prototype.exec; +// This always refers to the native implementation, because the +// String#replace polyfill uses ./fix-regexp-well-known-symbol-logic.js, +// which loads this file before patching the method. +var nativeReplace = String.prototype.replace; + +var patchedExec = nativeExec; + +var LAST_INDEX = 'lastIndex'; + +var UPDATES_LAST_INDEX_WRONG = (function () { + var re1 = /a/, + re2 = /b*/g; + nativeExec.call(re1, 'a'); + nativeExec.call(re2, 'a'); + return re1[LAST_INDEX] !== 0 || re2[LAST_INDEX] !== 0; +})(); + +// nonparticipating capturing group, copied from es5-shim's String#split patch. +var NPCG_INCLUDED = /()??/.exec('')[1] !== undefined; + +var PATCH = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED; + +if (PATCH) { + patchedExec = function exec(str) { + var re = this; + var lastIndex, reCopy, match, i; + + if (NPCG_INCLUDED) { + reCopy = new RegExp('^' + re.source + '$(?!\\s)', regexpFlags.call(re)); + } + if (UPDATES_LAST_INDEX_WRONG) lastIndex = re[LAST_INDEX]; + + match = nativeExec.call(re, str); + + if (UPDATES_LAST_INDEX_WRONG && match) { + re[LAST_INDEX] = re.global ? match.index + match[0].length : lastIndex; + } + if (NPCG_INCLUDED && match && match.length > 1) { + // Fix browsers whose `exec` methods don't consistently return `undefined` + // for NPCG, like IE8. NOTE: This doesn' work for /(.?)?/ + // eslint-disable-next-line no-loop-func + nativeReplace.call(match[0], reCopy, function () { + for (i = 1; i < arguments.length - 2; i++) { + if (arguments[i] === undefined) match[i] = undefined; + } + }); + } + + return match; + }; +} + +module.exports = patchedExec; + +},{"44":44}],97:[function(_dereq_,module,exports){ // 7.2.9 SameValue(x, y) module.exports = Object.is || function is(x, y) { // eslint-disable-next-line no-self-compare return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y; }; -},{}],97:[function(_dereq_,module,exports){ -'use strict'; -// https://tc39.github.io/proposal-setmap-offrom/ -var $export = _dereq_(33); -var aFunction = _dereq_(3); -var ctx = _dereq_(25); -var forOf = _dereq_(39); - -module.exports = function (COLLECTION) { - $export($export.S, COLLECTION, { from: function from(source /* , mapFn, thisArg */) { - var mapFn = arguments[1]; - var mapping, A, n, cb; - aFunction(this); - mapping = mapFn !== undefined; - if (mapping) aFunction(mapFn); - if (source == undefined) return new this(); - A = []; - if (mapping) { - n = 0; - cb = ctx(mapFn, arguments[2], 2); - forOf(source, false, function (nextItem) { - A.push(cb(nextItem, n++)); - }); - } else { - forOf(source, false, A.push, A); - } - return new this(A); - } }); -}; - -},{"25":25,"3":3,"33":33,"39":39}],98:[function(_dereq_,module,exports){ -'use strict'; -// https://tc39.github.io/proposal-setmap-offrom/ -var $export = _dereq_(33); - -module.exports = function (COLLECTION) { - $export($export.S, COLLECTION, { of: function of() { - var length = arguments.length; - var A = Array(length); - while (length--) A[length] = arguments[length]; - return new this(A); - } }); -}; - -},{"33":33}],99:[function(_dereq_,module,exports){ +},{}],98:[function(_dereq_,module,exports){ // Works with __proto__ only. Old v8 can't work with null proto objects. /* eslint-disable no-proto */ -var isObject = _dereq_(51); -var anObject = _dereq_(7); +var isObject = _dereq_(57); +var anObject = _dereq_(16); var check = function (O, proto) { anObject(O); if (!isObject(proto) && proto !== null) throw TypeError(proto + ": can't set as prototype!"); @@ -1923,7 +2019,7 @@ module.exports = { set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line function (test, buggy, set) { try { - set = _dereq_(25)(Function.call, _dereq_(75).f(Object.prototype, '__proto__').set, 2); + set = _dereq_(32)(Function.call, _dereq_(77).f(Object.prototype, '__proto__').set, 2); set(test, []); buggy = !(test instanceof Array); } catch (e) { buggy = true; } @@ -1937,11 +2033,11 @@ module.exports = { check: check }; -},{"25":25,"51":51,"7":7,"75":75}],100:[function(_dereq_,module,exports){ +},{"16":16,"32":32,"57":57,"77":77}],99:[function(_dereq_,module,exports){ 'use strict'; -var global = _dereq_(40); -var dP = _dereq_(72); -var DESCRIPTORS = _dereq_(29); +var global = _dereq_(46); +var dP = _dereq_(75); +var DESCRIPTORS = _dereq_(36); var SPECIES = _dereq_(128)('species'); module.exports = function (KEY) { @@ -1952,34 +2048,40 @@ module.exports = function (KEY) { }); }; -},{"128":128,"29":29,"40":40,"72":72}],101:[function(_dereq_,module,exports){ -var def = _dereq_(72).f; -var has = _dereq_(41); +},{"128":128,"36":36,"46":46,"75":75}],100:[function(_dereq_,module,exports){ +var def = _dereq_(75).f; +var has = _dereq_(47); var TAG = _dereq_(128)('toStringTag'); module.exports = function (it, tag, stat) { if (it && !has(it = stat ? it : it.prototype, TAG)) def(it, TAG, { configurable: true, value: tag }); }; -},{"128":128,"41":41,"72":72}],102:[function(_dereq_,module,exports){ -var shared = _dereq_(103)('keys'); -var uid = _dereq_(124); +},{"128":128,"47":47,"75":75}],101:[function(_dereq_,module,exports){ +var shared = _dereq_(102)('keys'); +var uid = _dereq_(123); module.exports = function (key) { return shared[key] || (shared[key] = uid(key)); }; -},{"103":103,"124":124}],103:[function(_dereq_,module,exports){ -var global = _dereq_(40); +},{"102":102,"123":123}],102:[function(_dereq_,module,exports){ +var core = _dereq_(30); +var global = _dereq_(46); var SHARED = '__core-js_shared__'; var store = global[SHARED] || (global[SHARED] = {}); -module.exports = function (key) { - return store[key] || (store[key] = {}); -}; -},{"40":40}],104:[function(_dereq_,module,exports){ +(module.exports = function (key, value) { + return store[key] || (store[key] = value !== undefined ? value : {}); +})('versions', []).push({ + version: core.version, + mode: _dereq_(65) ? 'pure' : 'global', + copyright: '© 2018 Denis Pushkarev (zloirock.ru)' +}); + +},{"30":30,"46":46,"65":65}],103:[function(_dereq_,module,exports){ // 7.3.20 SpeciesConstructor(O, defaultConstructor) -var anObject = _dereq_(7); -var aFunction = _dereq_(3); +var anObject = _dereq_(16); +var aFunction = _dereq_(11); var SPECIES = _dereq_(128)('species'); module.exports = function (O, D) { var C = anObject(O).constructor; @@ -1987,9 +2089,9 @@ module.exports = function (O, D) { return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S); }; -},{"128":128,"3":3,"7":7}],105:[function(_dereq_,module,exports){ +},{"11":11,"128":128,"16":16}],104:[function(_dereq_,module,exports){ 'use strict'; -var fails = _dereq_(35); +var fails = _dereq_(42); module.exports = function (method, arg) { return !!method && fails(function () { @@ -1998,9 +2100,9 @@ module.exports = function (method, arg) { }); }; -},{"35":35}],106:[function(_dereq_,module,exports){ -var toInteger = _dereq_(116); -var defined = _dereq_(28); +},{"42":42}],105:[function(_dereq_,module,exports){ +var toInteger = _dereq_(115); +var defined = _dereq_(35); // true -> String#at // false -> String#codePointAt module.exports = function (TO_STRING) { @@ -2017,20 +2119,20 @@ module.exports = function (TO_STRING) { }; }; -},{"116":116,"28":28}],107:[function(_dereq_,module,exports){ +},{"115":115,"35":35}],106:[function(_dereq_,module,exports){ // helper for String#{startsWith, endsWith, includes} -var isRegExp = _dereq_(52); -var defined = _dereq_(28); +var isRegExp = _dereq_(58); +var defined = _dereq_(35); module.exports = function (that, searchString, NAME) { if (isRegExp(searchString)) throw TypeError('String#' + NAME + " doesn't accept regex!"); return String(defined(that)); }; -},{"28":28,"52":52}],108:[function(_dereq_,module,exports){ -var $export = _dereq_(33); -var fails = _dereq_(35); -var defined = _dereq_(28); +},{"35":35,"58":58}],107:[function(_dereq_,module,exports){ +var $export = _dereq_(40); +var fails = _dereq_(42); +var defined = _dereq_(35); var quot = /"/g; // B.2.3.2.1 CreateHTML(string, tag, attribute, value) var createHTML = function (string, tag, attribute, value) { @@ -2048,11 +2150,11 @@ module.exports = function (NAME, exec) { }), 'String', O); }; -},{"28":28,"33":33,"35":35}],109:[function(_dereq_,module,exports){ +},{"35":35,"40":40,"42":42}],108:[function(_dereq_,module,exports){ // https://github.com/tc39/proposal-string-pad-start-end -var toLength = _dereq_(118); -var repeat = _dereq_(110); -var defined = _dereq_(28); +var toLength = _dereq_(117); +var repeat = _dereq_(109); +var defined = _dereq_(35); module.exports = function (that, maxLength, fillString, left) { var S = String(defined(that)); @@ -2066,10 +2168,10 @@ module.exports = function (that, maxLength, fillString, left) { return left ? stringFiller + S : S + stringFiller; }; -},{"110":110,"118":118,"28":28}],110:[function(_dereq_,module,exports){ +},{"109":109,"117":117,"35":35}],109:[function(_dereq_,module,exports){ 'use strict'; -var toInteger = _dereq_(116); -var defined = _dereq_(28); +var toInteger = _dereq_(115); +var defined = _dereq_(35); module.exports = function repeat(count) { var str = String(defined(this)); @@ -2080,11 +2182,11 @@ module.exports = function repeat(count) { return res; }; -},{"116":116,"28":28}],111:[function(_dereq_,module,exports){ -var $export = _dereq_(33); -var defined = _dereq_(28); -var fails = _dereq_(35); -var spaces = _dereq_(112); +},{"115":115,"35":35}],110:[function(_dereq_,module,exports){ +var $export = _dereq_(40); +var defined = _dereq_(35); +var fails = _dereq_(42); +var spaces = _dereq_(111); var space = '[' + spaces + ']'; var non = '\u200b\u0085'; var ltrim = RegExp('^' + space + space + '*'); @@ -2112,16 +2214,16 @@ var trim = exporter.trim = function (string, TYPE) { module.exports = exporter; -},{"112":112,"28":28,"33":33,"35":35}],112:[function(_dereq_,module,exports){ +},{"111":111,"35":35,"40":40,"42":42}],111:[function(_dereq_,module,exports){ module.exports = '\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003' + '\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF'; -},{}],113:[function(_dereq_,module,exports){ -var ctx = _dereq_(25); -var invoke = _dereq_(46); -var html = _dereq_(43); -var cel = _dereq_(30); -var global = _dereq_(40); +},{}],112:[function(_dereq_,module,exports){ +var ctx = _dereq_(32); +var invoke = _dereq_(52); +var html = _dereq_(49); +var cel = _dereq_(37); +var global = _dereq_(46); var process = global.process; var setTask = global.setImmediate; var clearTask = global.clearImmediate; @@ -2160,7 +2262,7 @@ if (!setTask || !clearTask) { delete queue[id]; }; // Node.js 0.8- - if (_dereq_(18)(process) == 'process') { + if (_dereq_(26)(process) == 'process') { defer = function (id) { process.nextTick(ctx(run, id, 1)); }; @@ -2202,8 +2304,8 @@ module.exports = { clear: clearTask }; -},{"18":18,"25":25,"30":30,"40":40,"43":43,"46":46}],114:[function(_dereq_,module,exports){ -var toInteger = _dereq_(116); +},{"26":26,"32":32,"37":37,"46":46,"49":49,"52":52}],113:[function(_dereq_,module,exports){ +var toInteger = _dereq_(115); var max = Math.max; var min = Math.min; module.exports = function (index, length) { @@ -2211,10 +2313,10 @@ module.exports = function (index, length) { return index < 0 ? max(index + length, 0) : min(index, length); }; -},{"116":116}],115:[function(_dereq_,module,exports){ +},{"115":115}],114:[function(_dereq_,module,exports){ // https://tc39.github.io/ecma262/#sec-toindex -var toInteger = _dereq_(116); -var toLength = _dereq_(118); +var toInteger = _dereq_(115); +var toLength = _dereq_(117); module.exports = function (it) { if (it === undefined) return 0; var number = toInteger(it); @@ -2223,7 +2325,7 @@ module.exports = function (it) { return length; }; -},{"116":116,"118":118}],116:[function(_dereq_,module,exports){ +},{"115":115,"117":117}],115:[function(_dereq_,module,exports){ // 7.1.4 ToInteger var ceil = Math.ceil; var floor = Math.floor; @@ -2231,32 +2333,32 @@ module.exports = function (it) { return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it); }; -},{}],117:[function(_dereq_,module,exports){ +},{}],116:[function(_dereq_,module,exports){ // to indexed object, toObject with fallback for non-array-like ES3 strings -var IObject = _dereq_(47); -var defined = _dereq_(28); +var IObject = _dereq_(53); +var defined = _dereq_(35); module.exports = function (it) { return IObject(defined(it)); }; -},{"28":28,"47":47}],118:[function(_dereq_,module,exports){ +},{"35":35,"53":53}],117:[function(_dereq_,module,exports){ // 7.1.15 ToLength -var toInteger = _dereq_(116); +var toInteger = _dereq_(115); var min = Math.min; module.exports = function (it) { return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991 }; -},{"116":116}],119:[function(_dereq_,module,exports){ +},{"115":115}],118:[function(_dereq_,module,exports){ // 7.1.13 ToObject(argument) -var defined = _dereq_(28); +var defined = _dereq_(35); module.exports = function (it) { return Object(defined(it)); }; -},{"28":28}],120:[function(_dereq_,module,exports){ +},{"35":35}],119:[function(_dereq_,module,exports){ // 7.1.1 ToPrimitive(input [, PreferredType]) -var isObject = _dereq_(51); +var isObject = _dereq_(57); // instead of the ES6 spec version, we didn't implement @@toPrimitive case // and the second argument - flag - preferred type is a string module.exports = function (it, S) { @@ -2268,47 +2370,47 @@ module.exports = function (it, S) { throw TypeError("Can't convert object to primitive value"); }; -},{"51":51}],121:[function(_dereq_,module,exports){ +},{"57":57}],120:[function(_dereq_,module,exports){ 'use strict'; -if (_dereq_(29)) { - var LIBRARY = _dereq_(60); - var global = _dereq_(40); - var fails = _dereq_(35); - var $export = _dereq_(33); - var $typed = _dereq_(123); - var $buffer = _dereq_(122); - var ctx = _dereq_(25); - var anInstance = _dereq_(6); +if (_dereq_(36)) { + var LIBRARY = _dereq_(65); + var global = _dereq_(46); + var fails = _dereq_(42); + var $export = _dereq_(40); + var $typed = _dereq_(122); + var $buffer = _dereq_(121); + var ctx = _dereq_(32); + var anInstance = _dereq_(15); var propertyDesc = _dereq_(92); - var hide = _dereq_(42); + var hide = _dereq_(48); var redefineAll = _dereq_(93); - var toInteger = _dereq_(116); - var toLength = _dereq_(118); - var toIndex = _dereq_(115); - var toAbsoluteIndex = _dereq_(114); - var toPrimitive = _dereq_(120); - var has = _dereq_(41); - var classof = _dereq_(17); - var isObject = _dereq_(51); - var toObject = _dereq_(119); - var isArrayIter = _dereq_(48); - var create = _dereq_(71); - var getPrototypeOf = _dereq_(79); - var gOPN = _dereq_(77).f; + var toInteger = _dereq_(115); + var toLength = _dereq_(117); + var toIndex = _dereq_(114); + var toAbsoluteIndex = _dereq_(113); + var toPrimitive = _dereq_(119); + var has = _dereq_(47); + var classof = _dereq_(25); + var isObject = _dereq_(57); + var toObject = _dereq_(118); + var isArrayIter = _dereq_(54); + var create = _dereq_(74); + var getPrototypeOf = _dereq_(81); + var gOPN = _dereq_(79).f; var getIterFn = _dereq_(129); - var uid = _dereq_(124); + var uid = _dereq_(123); var wks = _dereq_(128); - var createArrayMethod = _dereq_(12); - var createArrayIncludes = _dereq_(11); - var speciesConstructor = _dereq_(104); - var ArrayIterators = _dereq_(141); - var Iterators = _dereq_(58); - var $iterDetect = _dereq_(56); - var setSpecies = _dereq_(100); - var arrayFill = _dereq_(9); - var arrayCopyWithin = _dereq_(8); - var $DP = _dereq_(72); - var $GOPD = _dereq_(75); + var createArrayMethod = _dereq_(20); + var createArrayIncludes = _dereq_(19); + var speciesConstructor = _dereq_(103); + var ArrayIterators = _dereq_(140); + var Iterators = _dereq_(64); + var $iterDetect = _dereq_(62); + var setSpecies = _dereq_(99); + var arrayFill = _dereq_(18); + var arrayCopyWithin = _dereq_(17); + var $DP = _dereq_(75); + var $GOPD = _dereq_(77); var dP = $DP.f; var gOPD = $GOPD.f; var RangeError = global.RangeError; @@ -2750,23 +2852,23 @@ if (_dereq_(29)) { }; } else module.exports = function () { /* empty */ }; -},{"100":100,"104":104,"11":11,"114":114,"115":115,"116":116,"118":118,"119":119,"12":12,"120":120,"122":122,"123":123,"124":124,"128":128,"129":129,"141":141,"17":17,"25":25,"29":29,"33":33,"35":35,"40":40,"41":41,"42":42,"48":48,"51":51,"56":56,"58":58,"6":6,"60":60,"71":71,"72":72,"75":75,"77":77,"79":79,"8":8,"9":9,"92":92,"93":93}],122:[function(_dereq_,module,exports){ +},{"103":103,"113":113,"114":114,"115":115,"117":117,"118":118,"119":119,"121":121,"122":122,"123":123,"128":128,"129":129,"140":140,"15":15,"17":17,"18":18,"19":19,"20":20,"25":25,"32":32,"36":36,"40":40,"42":42,"46":46,"47":47,"48":48,"54":54,"57":57,"62":62,"64":64,"65":65,"74":74,"75":75,"77":77,"79":79,"81":81,"92":92,"93":93,"99":99}],121:[function(_dereq_,module,exports){ 'use strict'; -var global = _dereq_(40); -var DESCRIPTORS = _dereq_(29); -var LIBRARY = _dereq_(60); -var $typed = _dereq_(123); -var hide = _dereq_(42); +var global = _dereq_(46); +var DESCRIPTORS = _dereq_(36); +var LIBRARY = _dereq_(65); +var $typed = _dereq_(122); +var hide = _dereq_(48); var redefineAll = _dereq_(93); -var fails = _dereq_(35); -var anInstance = _dereq_(6); -var toInteger = _dereq_(116); -var toLength = _dereq_(118); -var toIndex = _dereq_(115); -var gOPN = _dereq_(77).f; -var dP = _dereq_(72).f; -var arrayFill = _dereq_(9); -var setToStringTag = _dereq_(101); +var fails = _dereq_(42); +var anInstance = _dereq_(15); +var toInteger = _dereq_(115); +var toLength = _dereq_(117); +var toIndex = _dereq_(114); +var gOPN = _dereq_(79).f; +var dP = _dereq_(75).f; +var arrayFill = _dereq_(18); +var setToStringTag = _dereq_(100); var ARRAY_BUFFER = 'ArrayBuffer'; var DATA_VIEW = 'DataView'; var PROTOTYPE = 'prototype'; @@ -2793,7 +2895,7 @@ var $OFFSET = DESCRIPTORS ? '_o' : BYTE_OFFSET; // IEEE754 conversions based on https://github.com/feross/ieee754 function packIEEE754(value, mLen, nBytes) { - var buffer = Array(nBytes); + var buffer = new Array(nBytes); var eLen = nBytes * 8 - mLen - 1; var eMax = (1 << eLen) - 1; var eBias = eMax >> 1; @@ -2911,7 +3013,7 @@ if (!$typed.ABV) { $ArrayBuffer = function ArrayBuffer(length) { anInstance(this, $ArrayBuffer, ARRAY_BUFFER); var byteLength = toIndex(length); - this._b = arrayFill.call(Array(byteLength), 0); + this._b = arrayFill.call(new Array(byteLength), 0); this[$LENGTH] = byteLength; }; @@ -3028,10 +3130,10 @@ hide($DataView[PROTOTYPE], $typed.VIEW, true); exports[ARRAY_BUFFER] = $ArrayBuffer; exports[DATA_VIEW] = $DataView; -},{"101":101,"115":115,"116":116,"118":118,"123":123,"29":29,"35":35,"40":40,"42":42,"6":6,"60":60,"72":72,"77":77,"9":9,"93":93}],123:[function(_dereq_,module,exports){ -var global = _dereq_(40); -var hide = _dereq_(42); -var uid = _dereq_(124); +},{"100":100,"114":114,"115":115,"117":117,"122":122,"15":15,"18":18,"36":36,"42":42,"46":46,"48":48,"65":65,"75":75,"79":79,"93":93}],122:[function(_dereq_,module,exports){ +var global = _dereq_(46); +var hide = _dereq_(48); +var uid = _dereq_(123); var TYPED = uid('typed_array'); var VIEW = uid('view'); var ABV = !!(global.ArrayBuffer && global.DataView); @@ -3058,38 +3160,44 @@ module.exports = { VIEW: VIEW }; -},{"124":124,"40":40,"42":42}],124:[function(_dereq_,module,exports){ +},{"123":123,"46":46,"48":48}],123:[function(_dereq_,module,exports){ var id = 0; var px = Math.random(); module.exports = function (key) { return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36)); }; -},{}],125:[function(_dereq_,module,exports){ -var isObject = _dereq_(51); +},{}],124:[function(_dereq_,module,exports){ +var global = _dereq_(46); +var navigator = global.navigator; + +module.exports = navigator && navigator.userAgent || ''; + +},{"46":46}],125:[function(_dereq_,module,exports){ +var isObject = _dereq_(57); module.exports = function (it, TYPE) { if (!isObject(it) || it._t !== TYPE) throw TypeError('Incompatible receiver, ' + TYPE + ' required!'); return it; }; -},{"51":51}],126:[function(_dereq_,module,exports){ -var global = _dereq_(40); -var core = _dereq_(23); -var LIBRARY = _dereq_(60); +},{"57":57}],126:[function(_dereq_,module,exports){ +var global = _dereq_(46); +var core = _dereq_(30); +var LIBRARY = _dereq_(65); var wksExt = _dereq_(127); -var defineProperty = _dereq_(72).f; +var defineProperty = _dereq_(75).f; module.exports = function (name) { var $Symbol = core.Symbol || (core.Symbol = LIBRARY ? {} : global.Symbol || {}); if (name.charAt(0) != '_' && !(name in $Symbol)) defineProperty($Symbol, name, { value: wksExt.f(name) }); }; -},{"127":127,"23":23,"40":40,"60":60,"72":72}],127:[function(_dereq_,module,exports){ +},{"127":127,"30":30,"46":46,"65":65,"75":75}],127:[function(_dereq_,module,exports){ exports.f = _dereq_(128); },{"128":128}],128:[function(_dereq_,module,exports){ -var store = _dereq_(103)('wks'); -var uid = _dereq_(124); -var Symbol = _dereq_(40).Symbol; +var store = _dereq_(102)('wks'); +var uid = _dereq_(123); +var Symbol = _dereq_(46).Symbol; var USE_SYMBOL = typeof Symbol == 'function'; var $exports = module.exports = function (name) { @@ -3099,68 +3207,61 @@ var $exports = module.exports = function (name) { $exports.store = store; -},{"103":103,"124":124,"40":40}],129:[function(_dereq_,module,exports){ -var classof = _dereq_(17); +},{"102":102,"123":123,"46":46}],129:[function(_dereq_,module,exports){ +var classof = _dereq_(25); var ITERATOR = _dereq_(128)('iterator'); -var Iterators = _dereq_(58); -module.exports = _dereq_(23).getIteratorMethod = function (it) { +var Iterators = _dereq_(64); +module.exports = _dereq_(30).getIteratorMethod = function (it) { if (it != undefined) return it[ITERATOR] || it['@@iterator'] || Iterators[classof(it)]; }; -},{"128":128,"17":17,"23":23,"58":58}],130:[function(_dereq_,module,exports){ -// https://github.com/benjamingr/RexExp.escape -var $export = _dereq_(33); -var $re = _dereq_(95)(/[\\^$*+?.()|[\]{}]/g, '\\$&'); - -$export($export.S, 'RegExp', { escape: function escape(it) { return $re(it); } }); - -},{"33":33,"95":95}],131:[function(_dereq_,module,exports){ +},{"128":128,"25":25,"30":30,"64":64}],130:[function(_dereq_,module,exports){ // 22.1.3.3 Array.prototype.copyWithin(target, start, end = this.length) -var $export = _dereq_(33); +var $export = _dereq_(40); -$export($export.P, 'Array', { copyWithin: _dereq_(8) }); +$export($export.P, 'Array', { copyWithin: _dereq_(17) }); -_dereq_(5)('copyWithin'); +_dereq_(13)('copyWithin'); -},{"33":33,"5":5,"8":8}],132:[function(_dereq_,module,exports){ +},{"13":13,"17":17,"40":40}],131:[function(_dereq_,module,exports){ 'use strict'; -var $export = _dereq_(33); -var $every = _dereq_(12)(4); +var $export = _dereq_(40); +var $every = _dereq_(20)(4); -$export($export.P + $export.F * !_dereq_(105)([].every, true), 'Array', { +$export($export.P + $export.F * !_dereq_(104)([].every, true), 'Array', { // 22.1.3.5 / 15.4.4.16 Array.prototype.every(callbackfn [, thisArg]) every: function every(callbackfn /* , thisArg */) { return $every(this, callbackfn, arguments[1]); } }); -},{"105":105,"12":12,"33":33}],133:[function(_dereq_,module,exports){ +},{"104":104,"20":20,"40":40}],132:[function(_dereq_,module,exports){ // 22.1.3.6 Array.prototype.fill(value, start = 0, end = this.length) -var $export = _dereq_(33); +var $export = _dereq_(40); -$export($export.P, 'Array', { fill: _dereq_(9) }); +$export($export.P, 'Array', { fill: _dereq_(18) }); -_dereq_(5)('fill'); +_dereq_(13)('fill'); -},{"33":33,"5":5,"9":9}],134:[function(_dereq_,module,exports){ +},{"13":13,"18":18,"40":40}],133:[function(_dereq_,module,exports){ 'use strict'; -var $export = _dereq_(33); -var $filter = _dereq_(12)(2); +var $export = _dereq_(40); +var $filter = _dereq_(20)(2); -$export($export.P + $export.F * !_dereq_(105)([].filter, true), 'Array', { +$export($export.P + $export.F * !_dereq_(104)([].filter, true), 'Array', { // 22.1.3.7 / 15.4.4.20 Array.prototype.filter(callbackfn [, thisArg]) filter: function filter(callbackfn /* , thisArg */) { return $filter(this, callbackfn, arguments[1]); } }); -},{"105":105,"12":12,"33":33}],135:[function(_dereq_,module,exports){ +},{"104":104,"20":20,"40":40}],134:[function(_dereq_,module,exports){ 'use strict'; // 22.1.3.9 Array.prototype.findIndex(predicate, thisArg = undefined) -var $export = _dereq_(33); -var $find = _dereq_(12)(6); +var $export = _dereq_(40); +var $find = _dereq_(20)(6); var KEY = 'findIndex'; var forced = true; // Shouldn't skip holes @@ -3170,13 +3271,13 @@ $export($export.P + $export.F * forced, 'Array', { return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); } }); -_dereq_(5)(KEY); +_dereq_(13)(KEY); -},{"12":12,"33":33,"5":5}],136:[function(_dereq_,module,exports){ +},{"13":13,"20":20,"40":40}],135:[function(_dereq_,module,exports){ 'use strict'; // 22.1.3.8 Array.prototype.find(predicate, thisArg = undefined) -var $export = _dereq_(33); -var $find = _dereq_(12)(5); +var $export = _dereq_(40); +var $find = _dereq_(20)(5); var KEY = 'find'; var forced = true; // Shouldn't skip holes @@ -3186,13 +3287,13 @@ $export($export.P + $export.F * forced, 'Array', { return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); } }); -_dereq_(5)(KEY); +_dereq_(13)(KEY); -},{"12":12,"33":33,"5":5}],137:[function(_dereq_,module,exports){ +},{"13":13,"20":20,"40":40}],136:[function(_dereq_,module,exports){ 'use strict'; -var $export = _dereq_(33); -var $forEach = _dereq_(12)(0); -var STRICT = _dereq_(105)([].forEach, true); +var $export = _dereq_(40); +var $forEach = _dereq_(20)(0); +var STRICT = _dereq_(104)([].forEach, true); $export($export.P + $export.F * !STRICT, 'Array', { // 22.1.3.10 / 15.4.4.18 Array.prototype.forEach(callbackfn [, thisArg]) @@ -3201,18 +3302,18 @@ $export($export.P + $export.F * !STRICT, 'Array', { } }); -},{"105":105,"12":12,"33":33}],138:[function(_dereq_,module,exports){ +},{"104":104,"20":20,"40":40}],137:[function(_dereq_,module,exports){ 'use strict'; -var ctx = _dereq_(25); -var $export = _dereq_(33); -var toObject = _dereq_(119); -var call = _dereq_(53); -var isArrayIter = _dereq_(48); -var toLength = _dereq_(118); -var createProperty = _dereq_(24); +var ctx = _dereq_(32); +var $export = _dereq_(40); +var toObject = _dereq_(118); +var call = _dereq_(59); +var isArrayIter = _dereq_(54); +var toLength = _dereq_(117); +var createProperty = _dereq_(31); var getIterFn = _dereq_(129); -$export($export.S + $export.F * !_dereq_(56)(function (iter) { Array.from(iter); }), 'Array', { +$export($export.S + $export.F * !_dereq_(62)(function (iter) { Array.from(iter); }), 'Array', { // 22.1.2.1 Array.from(arrayLike, mapfn = undefined, thisArg = undefined) from: function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) { var O = toObject(arrayLike); @@ -3240,14 +3341,14 @@ $export($export.S + $export.F * !_dereq_(56)(function (iter) { Array.from(iter); } }); -},{"118":118,"119":119,"129":129,"24":24,"25":25,"33":33,"48":48,"53":53,"56":56}],139:[function(_dereq_,module,exports){ +},{"117":117,"118":118,"129":129,"31":31,"32":32,"40":40,"54":54,"59":59,"62":62}],138:[function(_dereq_,module,exports){ 'use strict'; -var $export = _dereq_(33); -var $indexOf = _dereq_(11)(false); +var $export = _dereq_(40); +var $indexOf = _dereq_(19)(false); var $native = [].indexOf; var NEGATIVE_ZERO = !!$native && 1 / [1].indexOf(1, -0) < 0; -$export($export.P + $export.F * (NEGATIVE_ZERO || !_dereq_(105)($native)), 'Array', { +$export($export.P + $export.F * (NEGATIVE_ZERO || !_dereq_(104)($native)), 'Array', { // 22.1.3.11 / 15.4.4.14 Array.prototype.indexOf(searchElement [, fromIndex]) indexOf: function indexOf(searchElement /* , fromIndex = 0 */) { return NEGATIVE_ZERO @@ -3257,24 +3358,24 @@ $export($export.P + $export.F * (NEGATIVE_ZERO || !_dereq_(105)($native)), 'Arra } }); -},{"105":105,"11":11,"33":33}],140:[function(_dereq_,module,exports){ +},{"104":104,"19":19,"40":40}],139:[function(_dereq_,module,exports){ // 22.1.2.2 / 15.4.3.2 Array.isArray(arg) -var $export = _dereq_(33); +var $export = _dereq_(40); -$export($export.S, 'Array', { isArray: _dereq_(49) }); +$export($export.S, 'Array', { isArray: _dereq_(55) }); -},{"33":33,"49":49}],141:[function(_dereq_,module,exports){ +},{"40":40,"55":55}],140:[function(_dereq_,module,exports){ 'use strict'; -var addToUnscopables = _dereq_(5); -var step = _dereq_(57); -var Iterators = _dereq_(58); -var toIObject = _dereq_(117); +var addToUnscopables = _dereq_(13); +var step = _dereq_(63); +var Iterators = _dereq_(64); +var toIObject = _dereq_(116); // 22.1.3.4 Array.prototype.entries() // 22.1.3.13 Array.prototype.keys() // 22.1.3.29 Array.prototype.values() // 22.1.3.30 Array.prototype[@@iterator]() -module.exports = _dereq_(55)(Array, 'Array', function (iterated, kind) { +module.exports = _dereq_(61)(Array, 'Array', function (iterated, kind) { this._t = toIObject(iterated); // target this._i = 0; // next index this._k = kind; // kind @@ -3299,30 +3400,30 @@ addToUnscopables('keys'); addToUnscopables('values'); addToUnscopables('entries'); -},{"117":117,"5":5,"55":55,"57":57,"58":58}],142:[function(_dereq_,module,exports){ +},{"116":116,"13":13,"61":61,"63":63,"64":64}],141:[function(_dereq_,module,exports){ 'use strict'; // 22.1.3.13 Array.prototype.join(separator) -var $export = _dereq_(33); -var toIObject = _dereq_(117); +var $export = _dereq_(40); +var toIObject = _dereq_(116); var arrayJoin = [].join; // fallback for not array-like strings -$export($export.P + $export.F * (_dereq_(47) != Object || !_dereq_(105)(arrayJoin)), 'Array', { +$export($export.P + $export.F * (_dereq_(53) != Object || !_dereq_(104)(arrayJoin)), 'Array', { join: function join(separator) { return arrayJoin.call(toIObject(this), separator === undefined ? ',' : separator); } }); -},{"105":105,"117":117,"33":33,"47":47}],143:[function(_dereq_,module,exports){ +},{"104":104,"116":116,"40":40,"53":53}],142:[function(_dereq_,module,exports){ 'use strict'; -var $export = _dereq_(33); -var toIObject = _dereq_(117); -var toInteger = _dereq_(116); -var toLength = _dereq_(118); +var $export = _dereq_(40); +var toIObject = _dereq_(116); +var toInteger = _dereq_(115); +var toLength = _dereq_(117); var $native = [].lastIndexOf; var NEGATIVE_ZERO = !!$native && 1 / [1].lastIndexOf(1, -0) < 0; -$export($export.P + $export.F * (NEGATIVE_ZERO || !_dereq_(105)($native)), 'Array', { +$export($export.P + $export.F * (NEGATIVE_ZERO || !_dereq_(104)($native)), 'Array', { // 22.1.3.14 / 15.4.4.15 Array.prototype.lastIndexOf(searchElement [, fromIndex]) lastIndexOf: function lastIndexOf(searchElement /* , fromIndex = @[*-1] */) { // convert -0 to +0 @@ -3337,25 +3438,25 @@ $export($export.P + $export.F * (NEGATIVE_ZERO || !_dereq_(105)($native)), 'Arra } }); -},{"105":105,"116":116,"117":117,"118":118,"33":33}],144:[function(_dereq_,module,exports){ +},{"104":104,"115":115,"116":116,"117":117,"40":40}],143:[function(_dereq_,module,exports){ 'use strict'; -var $export = _dereq_(33); -var $map = _dereq_(12)(1); +var $export = _dereq_(40); +var $map = _dereq_(20)(1); -$export($export.P + $export.F * !_dereq_(105)([].map, true), 'Array', { +$export($export.P + $export.F * !_dereq_(104)([].map, true), 'Array', { // 22.1.3.15 / 15.4.4.19 Array.prototype.map(callbackfn [, thisArg]) map: function map(callbackfn /* , thisArg */) { return $map(this, callbackfn, arguments[1]); } }); -},{"105":105,"12":12,"33":33}],145:[function(_dereq_,module,exports){ +},{"104":104,"20":20,"40":40}],144:[function(_dereq_,module,exports){ 'use strict'; -var $export = _dereq_(33); -var createProperty = _dereq_(24); +var $export = _dereq_(40); +var createProperty = _dereq_(31); // WebKit Array.of isn't generic -$export($export.S + $export.F * _dereq_(35)(function () { +$export($export.S + $export.F * _dereq_(42)(function () { function F() { /* empty */ } return !(Array.of.call(F) instanceof F); }), 'Array', { @@ -3370,41 +3471,41 @@ $export($export.S + $export.F * _dereq_(35)(function () { } }); -},{"24":24,"33":33,"35":35}],146:[function(_dereq_,module,exports){ +},{"31":31,"40":40,"42":42}],145:[function(_dereq_,module,exports){ 'use strict'; -var $export = _dereq_(33); -var $reduce = _dereq_(13); +var $export = _dereq_(40); +var $reduce = _dereq_(21); -$export($export.P + $export.F * !_dereq_(105)([].reduceRight, true), 'Array', { +$export($export.P + $export.F * !_dereq_(104)([].reduceRight, true), 'Array', { // 22.1.3.19 / 15.4.4.22 Array.prototype.reduceRight(callbackfn [, initialValue]) reduceRight: function reduceRight(callbackfn /* , initialValue */) { return $reduce(this, callbackfn, arguments.length, arguments[1], true); } }); -},{"105":105,"13":13,"33":33}],147:[function(_dereq_,module,exports){ +},{"104":104,"21":21,"40":40}],146:[function(_dereq_,module,exports){ 'use strict'; -var $export = _dereq_(33); -var $reduce = _dereq_(13); +var $export = _dereq_(40); +var $reduce = _dereq_(21); -$export($export.P + $export.F * !_dereq_(105)([].reduce, true), 'Array', { +$export($export.P + $export.F * !_dereq_(104)([].reduce, true), 'Array', { // 22.1.3.18 / 15.4.4.21 Array.prototype.reduce(callbackfn [, initialValue]) reduce: function reduce(callbackfn /* , initialValue */) { return $reduce(this, callbackfn, arguments.length, arguments[1], false); } }); -},{"105":105,"13":13,"33":33}],148:[function(_dereq_,module,exports){ +},{"104":104,"21":21,"40":40}],147:[function(_dereq_,module,exports){ 'use strict'; -var $export = _dereq_(33); -var html = _dereq_(43); -var cof = _dereq_(18); -var toAbsoluteIndex = _dereq_(114); -var toLength = _dereq_(118); +var $export = _dereq_(40); +var html = _dereq_(49); +var cof = _dereq_(26); +var toAbsoluteIndex = _dereq_(113); +var toLength = _dereq_(117); var arraySlice = [].slice; // fallback for not array-like ES3 strings and DOM objects -$export($export.P + $export.F * _dereq_(35)(function () { +$export($export.P + $export.F * _dereq_(42)(function () { if (html) arraySlice.call(html); }), 'Array', { slice: function slice(begin, end) { @@ -3415,7 +3516,7 @@ $export($export.P + $export.F * _dereq_(35)(function () { var start = toAbsoluteIndex(begin, len); var upTo = toAbsoluteIndex(end, len); var size = toLength(upTo - start); - var cloned = Array(size); + var cloned = new Array(size); var i = 0; for (; i < size; i++) cloned[i] = klass == 'String' ? this.charAt(start + i) @@ -3424,24 +3525,24 @@ $export($export.P + $export.F * _dereq_(35)(function () { } }); -},{"114":114,"118":118,"18":18,"33":33,"35":35,"43":43}],149:[function(_dereq_,module,exports){ +},{"113":113,"117":117,"26":26,"40":40,"42":42,"49":49}],148:[function(_dereq_,module,exports){ 'use strict'; -var $export = _dereq_(33); -var $some = _dereq_(12)(3); +var $export = _dereq_(40); +var $some = _dereq_(20)(3); -$export($export.P + $export.F * !_dereq_(105)([].some, true), 'Array', { +$export($export.P + $export.F * !_dereq_(104)([].some, true), 'Array', { // 22.1.3.23 / 15.4.4.17 Array.prototype.some(callbackfn [, thisArg]) some: function some(callbackfn /* , thisArg */) { return $some(this, callbackfn, arguments[1]); } }); -},{"105":105,"12":12,"33":33}],150:[function(_dereq_,module,exports){ +},{"104":104,"20":20,"40":40}],149:[function(_dereq_,module,exports){ 'use strict'; -var $export = _dereq_(33); -var aFunction = _dereq_(3); -var toObject = _dereq_(119); -var fails = _dereq_(35); +var $export = _dereq_(40); +var aFunction = _dereq_(11); +var toObject = _dereq_(118); +var fails = _dereq_(42); var $sort = [].sort; var test = [1, 2, 3]; @@ -3452,7 +3553,7 @@ $export($export.P + $export.F * (fails(function () { // V8 bug test.sort(null); // Old WebKit -}) || !_dereq_(105)($sort)), 'Array', { +}) || !_dereq_(104)($sort)), 'Array', { // 22.1.3.25 Array.prototype.sort(comparefn) sort: function sort(comparefn) { return comparefn === undefined @@ -3461,32 +3562,32 @@ $export($export.P + $export.F * (fails(function () { } }); -},{"105":105,"119":119,"3":3,"33":33,"35":35}],151:[function(_dereq_,module,exports){ -_dereq_(100)('Array'); +},{"104":104,"11":11,"118":118,"40":40,"42":42}],150:[function(_dereq_,module,exports){ +_dereq_(99)('Array'); -},{"100":100}],152:[function(_dereq_,module,exports){ +},{"99":99}],151:[function(_dereq_,module,exports){ // 20.3.3.1 / 15.9.4.4 Date.now() -var $export = _dereq_(33); +var $export = _dereq_(40); $export($export.S, 'Date', { now: function () { return new Date().getTime(); } }); -},{"33":33}],153:[function(_dereq_,module,exports){ +},{"40":40}],152:[function(_dereq_,module,exports){ // 20.3.4.36 / 15.9.5.43 Date.prototype.toISOString() -var $export = _dereq_(33); -var toISOString = _dereq_(26); +var $export = _dereq_(40); +var toISOString = _dereq_(33); // PhantomJS / old WebKit has a broken implementations $export($export.P + $export.F * (Date.prototype.toISOString !== toISOString), 'Date', { toISOString: toISOString }); -},{"26":26,"33":33}],154:[function(_dereq_,module,exports){ +},{"33":33,"40":40}],153:[function(_dereq_,module,exports){ 'use strict'; -var $export = _dereq_(33); -var toObject = _dereq_(119); -var toPrimitive = _dereq_(120); +var $export = _dereq_(40); +var toObject = _dereq_(118); +var toPrimitive = _dereq_(119); -$export($export.P + $export.F * _dereq_(35)(function () { +$export($export.P + $export.F * _dereq_(42)(function () { return new Date(NaN).toJSON() !== null || Date.prototype.toJSON.call({ toISOString: function () { return 1; } }) !== 1; }), 'Date', { @@ -3498,13 +3599,13 @@ $export($export.P + $export.F * _dereq_(35)(function () { } }); -},{"119":119,"120":120,"33":33,"35":35}],155:[function(_dereq_,module,exports){ +},{"118":118,"119":119,"40":40,"42":42}],154:[function(_dereq_,module,exports){ var TO_PRIMITIVE = _dereq_(128)('toPrimitive'); var proto = Date.prototype; -if (!(TO_PRIMITIVE in proto)) _dereq_(42)(proto, TO_PRIMITIVE, _dereq_(27)); +if (!(TO_PRIMITIVE in proto)) _dereq_(48)(proto, TO_PRIMITIVE, _dereq_(34)); -},{"128":128,"27":27,"42":42}],156:[function(_dereq_,module,exports){ +},{"128":128,"34":34,"48":48}],155:[function(_dereq_,module,exports){ var DateProto = Date.prototype; var INVALID_DATE = 'Invalid Date'; var TO_STRING = 'toString'; @@ -3518,20 +3619,20 @@ if (new Date(NaN) + '' != INVALID_DATE) { }); } -},{"94":94}],157:[function(_dereq_,module,exports){ +},{"94":94}],156:[function(_dereq_,module,exports){ // 19.2.3.2 / 15.3.4.5 Function.prototype.bind(thisArg, args...) -var $export = _dereq_(33); +var $export = _dereq_(40); -$export($export.P, 'Function', { bind: _dereq_(16) }); +$export($export.P, 'Function', { bind: _dereq_(24) }); -},{"16":16,"33":33}],158:[function(_dereq_,module,exports){ +},{"24":24,"40":40}],157:[function(_dereq_,module,exports){ 'use strict'; -var isObject = _dereq_(51); -var getPrototypeOf = _dereq_(79); +var isObject = _dereq_(57); +var getPrototypeOf = _dereq_(81); var HAS_INSTANCE = _dereq_(128)('hasInstance'); var FunctionProto = Function.prototype; // 19.2.3.6 Function.prototype[@@hasInstance](V) -if (!(HAS_INSTANCE in FunctionProto)) _dereq_(72).f(FunctionProto, HAS_INSTANCE, { value: function (O) { +if (!(HAS_INSTANCE in FunctionProto)) _dereq_(75).f(FunctionProto, HAS_INSTANCE, { value: function (O) { if (typeof this != 'function' || !isObject(O)) return false; if (!isObject(this.prototype)) return O instanceof this; // for environment w/o native `@@hasInstance` logic enough `instanceof`, but add this: @@ -3539,14 +3640,14 @@ if (!(HAS_INSTANCE in FunctionProto)) _dereq_(72).f(FunctionProto, HAS_INSTANCE, return false; } }); -},{"128":128,"51":51,"72":72,"79":79}],159:[function(_dereq_,module,exports){ -var dP = _dereq_(72).f; +},{"128":128,"57":57,"75":75,"81":81}],158:[function(_dereq_,module,exports){ +var dP = _dereq_(75).f; var FProto = Function.prototype; var nameRE = /^\s*function ([^ (]*)/; var NAME = 'name'; // 19.2.4.2 name -NAME in FProto || _dereq_(29) && dP(FProto, NAME, { +NAME in FProto || _dereq_(36) && dP(FProto, NAME, { configurable: true, get: function () { try { @@ -3557,14 +3658,14 @@ NAME in FProto || _dereq_(29) && dP(FProto, NAME, { } }); -},{"29":29,"72":72}],160:[function(_dereq_,module,exports){ +},{"36":36,"75":75}],159:[function(_dereq_,module,exports){ 'use strict'; -var strong = _dereq_(19); +var strong = _dereq_(27); var validate = _dereq_(125); var MAP = 'Map'; // 23.1 Map Objects -module.exports = _dereq_(22)(MAP, function (get) { +module.exports = _dereq_(29)(MAP, function (get) { return function Map() { return get(this, arguments.length > 0 ? arguments[0] : undefined); }; }, { // 23.1.3.6 Map.prototype.get(key) @@ -3578,10 +3679,10 @@ module.exports = _dereq_(22)(MAP, function (get) { } }, strong, true); -},{"125":125,"19":19,"22":22}],161:[function(_dereq_,module,exports){ +},{"125":125,"27":27,"29":29}],160:[function(_dereq_,module,exports){ // 20.2.2.3 Math.acosh(x) -var $export = _dereq_(33); -var log1p = _dereq_(63); +var $export = _dereq_(40); +var log1p = _dereq_(68); var sqrt = Math.sqrt; var $acosh = Math.acosh; @@ -3598,9 +3699,9 @@ $export($export.S + $export.F * !($acosh } }); -},{"33":33,"63":63}],162:[function(_dereq_,module,exports){ +},{"40":40,"68":68}],161:[function(_dereq_,module,exports){ // 20.2.2.5 Math.asinh(x) -var $export = _dereq_(33); +var $export = _dereq_(40); var $asinh = Math.asinh; function asinh(x) { @@ -3610,9 +3711,9 @@ function asinh(x) { // Tor Browser bug: Math.asinh(0) -> -0 $export($export.S + $export.F * !($asinh && 1 / $asinh(0) > 0), 'Math', { asinh: asinh }); -},{"33":33}],163:[function(_dereq_,module,exports){ +},{"40":40}],162:[function(_dereq_,module,exports){ // 20.2.2.7 Math.atanh(x) -var $export = _dereq_(33); +var $export = _dereq_(40); var $atanh = Math.atanh; // Tor Browser bug: Math.atanh(-0) -> 0 @@ -3622,10 +3723,10 @@ $export($export.S + $export.F * !($atanh && 1 / $atanh(-0) < 0), 'Math', { } }); -},{"33":33}],164:[function(_dereq_,module,exports){ +},{"40":40}],163:[function(_dereq_,module,exports){ // 20.2.2.9 Math.cbrt(x) -var $export = _dereq_(33); -var sign = _dereq_(65); +var $export = _dereq_(40); +var sign = _dereq_(69); $export($export.S, 'Math', { cbrt: function cbrt(x) { @@ -3633,9 +3734,9 @@ $export($export.S, 'Math', { } }); -},{"33":33,"65":65}],165:[function(_dereq_,module,exports){ +},{"40":40,"69":69}],164:[function(_dereq_,module,exports){ // 20.2.2.11 Math.clz32(x) -var $export = _dereq_(33); +var $export = _dereq_(40); $export($export.S, 'Math', { clz32: function clz32(x) { @@ -3643,9 +3744,9 @@ $export($export.S, 'Math', { } }); -},{"33":33}],166:[function(_dereq_,module,exports){ +},{"40":40}],165:[function(_dereq_,module,exports){ // 20.2.2.12 Math.cosh(x) -var $export = _dereq_(33); +var $export = _dereq_(40); var exp = Math.exp; $export($export.S, 'Math', { @@ -3654,22 +3755,22 @@ $export($export.S, 'Math', { } }); -},{"33":33}],167:[function(_dereq_,module,exports){ +},{"40":40}],166:[function(_dereq_,module,exports){ // 20.2.2.14 Math.expm1(x) -var $export = _dereq_(33); -var $expm1 = _dereq_(61); +var $export = _dereq_(40); +var $expm1 = _dereq_(66); $export($export.S + $export.F * ($expm1 != Math.expm1), 'Math', { expm1: $expm1 }); -},{"33":33,"61":61}],168:[function(_dereq_,module,exports){ +},{"40":40,"66":66}],167:[function(_dereq_,module,exports){ // 20.2.2.16 Math.fround(x) -var $export = _dereq_(33); +var $export = _dereq_(40); -$export($export.S, 'Math', { fround: _dereq_(62) }); +$export($export.S, 'Math', { fround: _dereq_(67) }); -},{"33":33,"62":62}],169:[function(_dereq_,module,exports){ +},{"40":40,"67":67}],168:[function(_dereq_,module,exports){ // 20.2.2.17 Math.hypot([value1[, value2[, … ]]]) -var $export = _dereq_(33); +var $export = _dereq_(40); var abs = Math.abs; $export($export.S, 'Math', { @@ -3694,13 +3795,13 @@ $export($export.S, 'Math', { } }); -},{"33":33}],170:[function(_dereq_,module,exports){ +},{"40":40}],169:[function(_dereq_,module,exports){ // 20.2.2.18 Math.imul(x, y) -var $export = _dereq_(33); +var $export = _dereq_(40); var $imul = Math.imul; // some WebKit versions fails with big numbers, some has wrong arity -$export($export.S + $export.F * _dereq_(35)(function () { +$export($export.S + $export.F * _dereq_(42)(function () { return $imul(0xffffffff, 5) != -5 || $imul.length != 2; }), 'Math', { imul: function imul(x, y) { @@ -3713,9 +3814,9 @@ $export($export.S + $export.F * _dereq_(35)(function () { } }); -},{"33":33,"35":35}],171:[function(_dereq_,module,exports){ +},{"40":40,"42":42}],170:[function(_dereq_,module,exports){ // 20.2.2.21 Math.log10(x) -var $export = _dereq_(33); +var $export = _dereq_(40); $export($export.S, 'Math', { log10: function log10(x) { @@ -3723,15 +3824,15 @@ $export($export.S, 'Math', { } }); -},{"33":33}],172:[function(_dereq_,module,exports){ +},{"40":40}],171:[function(_dereq_,module,exports){ // 20.2.2.20 Math.log1p(x) -var $export = _dereq_(33); +var $export = _dereq_(40); -$export($export.S, 'Math', { log1p: _dereq_(63) }); +$export($export.S, 'Math', { log1p: _dereq_(68) }); -},{"33":33,"63":63}],173:[function(_dereq_,module,exports){ +},{"40":40,"68":68}],172:[function(_dereq_,module,exports){ // 20.2.2.22 Math.log2(x) -var $export = _dereq_(33); +var $export = _dereq_(40); $export($export.S, 'Math', { log2: function log2(x) { @@ -3739,20 +3840,20 @@ $export($export.S, 'Math', { } }); -},{"33":33}],174:[function(_dereq_,module,exports){ +},{"40":40}],173:[function(_dereq_,module,exports){ // 20.2.2.28 Math.sign(x) -var $export = _dereq_(33); +var $export = _dereq_(40); -$export($export.S, 'Math', { sign: _dereq_(65) }); +$export($export.S, 'Math', { sign: _dereq_(69) }); -},{"33":33,"65":65}],175:[function(_dereq_,module,exports){ +},{"40":40,"69":69}],174:[function(_dereq_,module,exports){ // 20.2.2.30 Math.sinh(x) -var $export = _dereq_(33); -var expm1 = _dereq_(61); +var $export = _dereq_(40); +var expm1 = _dereq_(66); var exp = Math.exp; // V8 near Chromium 38 has a problem with very small numbers -$export($export.S + $export.F * _dereq_(35)(function () { +$export($export.S + $export.F * _dereq_(42)(function () { return !Math.sinh(-2e-17) != -2e-17; }), 'Math', { sinh: function sinh(x) { @@ -3762,10 +3863,10 @@ $export($export.S + $export.F * _dereq_(35)(function () { } }); -},{"33":33,"35":35,"61":61}],176:[function(_dereq_,module,exports){ +},{"40":40,"42":42,"66":66}],175:[function(_dereq_,module,exports){ // 20.2.2.33 Math.tanh(x) -var $export = _dereq_(33); -var expm1 = _dereq_(61); +var $export = _dereq_(40); +var expm1 = _dereq_(66); var exp = Math.exp; $export($export.S, 'Math', { @@ -3776,9 +3877,9 @@ $export($export.S, 'Math', { } }); -},{"33":33,"61":61}],177:[function(_dereq_,module,exports){ +},{"40":40,"66":66}],176:[function(_dereq_,module,exports){ // 20.2.2.34 Math.trunc(x) -var $export = _dereq_(33); +var $export = _dereq_(40); $export($export.S, 'Math', { trunc: function trunc(it) { @@ -3786,24 +3887,24 @@ $export($export.S, 'Math', { } }); -},{"33":33}],178:[function(_dereq_,module,exports){ +},{"40":40}],177:[function(_dereq_,module,exports){ 'use strict'; -var global = _dereq_(40); -var has = _dereq_(41); -var cof = _dereq_(18); -var inheritIfRequired = _dereq_(45); -var toPrimitive = _dereq_(120); -var fails = _dereq_(35); -var gOPN = _dereq_(77).f; -var gOPD = _dereq_(75).f; -var dP = _dereq_(72).f; -var $trim = _dereq_(111).trim; +var global = _dereq_(46); +var has = _dereq_(47); +var cof = _dereq_(26); +var inheritIfRequired = _dereq_(51); +var toPrimitive = _dereq_(119); +var fails = _dereq_(42); +var gOPN = _dereq_(79).f; +var gOPD = _dereq_(77).f; +var dP = _dereq_(75).f; +var $trim = _dereq_(110).trim; var NUMBER = 'Number'; var $Number = global[NUMBER]; var Base = $Number; var proto = $Number.prototype; // Opera ~12 has broken Object#toString -var BROKEN_COF = cof(_dereq_(71)(proto)) == NUMBER; +var BROKEN_COF = cof(_dereq_(74)(proto)) == NUMBER; var TRIM = 'trim' in String.prototype; // 7.1.3 ToNumber(argument) @@ -3841,7 +3942,7 @@ if (!$Number(' 0o1') || !$Number('0b1') || $Number('+0x1')) { && (BROKEN_COF ? fails(function () { proto.valueOf.call(that); }) : cof(that) != NUMBER) ? inheritIfRequired(new Base(toNumber(it)), that, $Number) : toNumber(it); }; - for (var keys = _dereq_(29) ? gOPN(Base) : ( + for (var keys = _dereq_(36) ? gOPN(Base) : ( // ES3: 'MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,' + // ES6 (in case, if modules with ES6 Number statics required before): @@ -3857,16 +3958,16 @@ if (!$Number(' 0o1') || !$Number('0b1') || $Number('+0x1')) { _dereq_(94)(global, NUMBER, $Number); } -},{"111":111,"120":120,"18":18,"29":29,"35":35,"40":40,"41":41,"45":45,"71":71,"72":72,"75":75,"77":77,"94":94}],179:[function(_dereq_,module,exports){ +},{"110":110,"119":119,"26":26,"36":36,"42":42,"46":46,"47":47,"51":51,"74":74,"75":75,"77":77,"79":79,"94":94}],178:[function(_dereq_,module,exports){ // 20.1.2.1 Number.EPSILON -var $export = _dereq_(33); +var $export = _dereq_(40); $export($export.S, 'Number', { EPSILON: Math.pow(2, -52) }); -},{"33":33}],180:[function(_dereq_,module,exports){ +},{"40":40}],179:[function(_dereq_,module,exports){ // 20.1.2.2 Number.isFinite(number) -var $export = _dereq_(33); -var _isFinite = _dereq_(40).isFinite; +var $export = _dereq_(40); +var _isFinite = _dereq_(46).isFinite; $export($export.S, 'Number', { isFinite: function isFinite(it) { @@ -3874,15 +3975,15 @@ $export($export.S, 'Number', { } }); -},{"33":33,"40":40}],181:[function(_dereq_,module,exports){ +},{"40":40,"46":46}],180:[function(_dereq_,module,exports){ // 20.1.2.3 Number.isInteger(number) -var $export = _dereq_(33); +var $export = _dereq_(40); -$export($export.S, 'Number', { isInteger: _dereq_(50) }); +$export($export.S, 'Number', { isInteger: _dereq_(56) }); -},{"33":33,"50":50}],182:[function(_dereq_,module,exports){ +},{"40":40,"56":56}],181:[function(_dereq_,module,exports){ // 20.1.2.4 Number.isNaN(number) -var $export = _dereq_(33); +var $export = _dereq_(40); $export($export.S, 'Number', { isNaN: function isNaN(number) { @@ -3891,10 +3992,10 @@ $export($export.S, 'Number', { } }); -},{"33":33}],183:[function(_dereq_,module,exports){ +},{"40":40}],182:[function(_dereq_,module,exports){ // 20.1.2.5 Number.isSafeInteger(number) -var $export = _dereq_(33); -var isInteger = _dereq_(50); +var $export = _dereq_(40); +var isInteger = _dereq_(56); var abs = Math.abs; $export($export.S, 'Number', { @@ -3903,36 +4004,36 @@ $export($export.S, 'Number', { } }); -},{"33":33,"50":50}],184:[function(_dereq_,module,exports){ +},{"40":40,"56":56}],183:[function(_dereq_,module,exports){ // 20.1.2.6 Number.MAX_SAFE_INTEGER -var $export = _dereq_(33); +var $export = _dereq_(40); $export($export.S, 'Number', { MAX_SAFE_INTEGER: 0x1fffffffffffff }); -},{"33":33}],185:[function(_dereq_,module,exports){ +},{"40":40}],184:[function(_dereq_,module,exports){ // 20.1.2.10 Number.MIN_SAFE_INTEGER -var $export = _dereq_(33); +var $export = _dereq_(40); $export($export.S, 'Number', { MIN_SAFE_INTEGER: -0x1fffffffffffff }); -},{"33":33}],186:[function(_dereq_,module,exports){ -var $export = _dereq_(33); -var $parseFloat = _dereq_(86); +},{"40":40}],185:[function(_dereq_,module,exports){ +var $export = _dereq_(40); +var $parseFloat = _dereq_(88); // 20.1.2.12 Number.parseFloat(string) $export($export.S + $export.F * (Number.parseFloat != $parseFloat), 'Number', { parseFloat: $parseFloat }); -},{"33":33,"86":86}],187:[function(_dereq_,module,exports){ -var $export = _dereq_(33); -var $parseInt = _dereq_(87); +},{"40":40,"88":88}],186:[function(_dereq_,module,exports){ +var $export = _dereq_(40); +var $parseInt = _dereq_(89); // 20.1.2.13 Number.parseInt(string, radix) $export($export.S + $export.F * (Number.parseInt != $parseInt), 'Number', { parseInt: $parseInt }); -},{"33":33,"87":87}],188:[function(_dereq_,module,exports){ +},{"40":40,"89":89}],187:[function(_dereq_,module,exports){ 'use strict'; -var $export = _dereq_(33); -var toInteger = _dereq_(116); -var aNumberValue = _dereq_(4); -var repeat = _dereq_(110); +var $export = _dereq_(40); +var toInteger = _dereq_(115); +var aNumberValue = _dereq_(12); +var repeat = _dereq_(109); var $toFixed = 1.0.toFixed; var floor = Math.floor; var data = [0, 0, 0, 0, 0, 0]; @@ -3988,7 +4089,7 @@ $export($export.P + $export.F * (!!$toFixed && ( 0.9.toFixed(0) !== '1' || 1.255.toFixed(2) !== '1.25' || 1000000000000000128.0.toFixed(0) !== '1000000000000000128' -) || !_dereq_(35)(function () { +) || !_dereq_(42)(function () { // V8 ~ Android 4.3- $toFixed.call({}); })), 'Number', { @@ -4043,11 +4144,11 @@ $export($export.P + $export.F * (!!$toFixed && ( } }); -},{"110":110,"116":116,"33":33,"35":35,"4":4}],189:[function(_dereq_,module,exports){ +},{"109":109,"115":115,"12":12,"40":40,"42":42}],188:[function(_dereq_,module,exports){ 'use strict'; -var $export = _dereq_(33); -var $fails = _dereq_(35); -var aNumberValue = _dereq_(4); +var $export = _dereq_(40); +var $fails = _dereq_(42); +var aNumberValue = _dereq_(12); var $toPrecision = 1.0.toPrecision; $export($export.P + $export.F * ($fails(function () { @@ -4063,143 +4164,143 @@ $export($export.P + $export.F * ($fails(function () { } }); -},{"33":33,"35":35,"4":4}],190:[function(_dereq_,module,exports){ +},{"12":12,"40":40,"42":42}],189:[function(_dereq_,module,exports){ // 19.1.3.1 Object.assign(target, source) -var $export = _dereq_(33); +var $export = _dereq_(40); -$export($export.S + $export.F, 'Object', { assign: _dereq_(70) }); +$export($export.S + $export.F, 'Object', { assign: _dereq_(73) }); -},{"33":33,"70":70}],191:[function(_dereq_,module,exports){ -var $export = _dereq_(33); +},{"40":40,"73":73}],190:[function(_dereq_,module,exports){ +var $export = _dereq_(40); // 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) -$export($export.S, 'Object', { create: _dereq_(71) }); +$export($export.S, 'Object', { create: _dereq_(74) }); -},{"33":33,"71":71}],192:[function(_dereq_,module,exports){ -var $export = _dereq_(33); +},{"40":40,"74":74}],191:[function(_dereq_,module,exports){ +var $export = _dereq_(40); // 19.1.2.3 / 15.2.3.7 Object.defineProperties(O, Properties) -$export($export.S + $export.F * !_dereq_(29), 'Object', { defineProperties: _dereq_(73) }); +$export($export.S + $export.F * !_dereq_(36), 'Object', { defineProperties: _dereq_(76) }); -},{"29":29,"33":33,"73":73}],193:[function(_dereq_,module,exports){ -var $export = _dereq_(33); +},{"36":36,"40":40,"76":76}],192:[function(_dereq_,module,exports){ +var $export = _dereq_(40); // 19.1.2.4 / 15.2.3.6 Object.defineProperty(O, P, Attributes) -$export($export.S + $export.F * !_dereq_(29), 'Object', { defineProperty: _dereq_(72).f }); +$export($export.S + $export.F * !_dereq_(36), 'Object', { defineProperty: _dereq_(75).f }); -},{"29":29,"33":33,"72":72}],194:[function(_dereq_,module,exports){ +},{"36":36,"40":40,"75":75}],193:[function(_dereq_,module,exports){ // 19.1.2.5 Object.freeze(O) -var isObject = _dereq_(51); -var meta = _dereq_(66).onFreeze; +var isObject = _dereq_(57); +var meta = _dereq_(70).onFreeze; -_dereq_(83)('freeze', function ($freeze) { +_dereq_(85)('freeze', function ($freeze) { return function freeze(it) { return $freeze && isObject(it) ? $freeze(meta(it)) : it; }; }); -},{"51":51,"66":66,"83":83}],195:[function(_dereq_,module,exports){ +},{"57":57,"70":70,"85":85}],194:[function(_dereq_,module,exports){ // 19.1.2.6 Object.getOwnPropertyDescriptor(O, P) -var toIObject = _dereq_(117); -var $getOwnPropertyDescriptor = _dereq_(75).f; +var toIObject = _dereq_(116); +var $getOwnPropertyDescriptor = _dereq_(77).f; -_dereq_(83)('getOwnPropertyDescriptor', function () { +_dereq_(85)('getOwnPropertyDescriptor', function () { return function getOwnPropertyDescriptor(it, key) { return $getOwnPropertyDescriptor(toIObject(it), key); }; }); -},{"117":117,"75":75,"83":83}],196:[function(_dereq_,module,exports){ +},{"116":116,"77":77,"85":85}],195:[function(_dereq_,module,exports){ // 19.1.2.7 Object.getOwnPropertyNames(O) -_dereq_(83)('getOwnPropertyNames', function () { - return _dereq_(76).f; +_dereq_(85)('getOwnPropertyNames', function () { + return _dereq_(78).f; }); -},{"76":76,"83":83}],197:[function(_dereq_,module,exports){ +},{"78":78,"85":85}],196:[function(_dereq_,module,exports){ // 19.1.2.9 Object.getPrototypeOf(O) -var toObject = _dereq_(119); -var $getPrototypeOf = _dereq_(79); +var toObject = _dereq_(118); +var $getPrototypeOf = _dereq_(81); -_dereq_(83)('getPrototypeOf', function () { +_dereq_(85)('getPrototypeOf', function () { return function getPrototypeOf(it) { return $getPrototypeOf(toObject(it)); }; }); -},{"119":119,"79":79,"83":83}],198:[function(_dereq_,module,exports){ +},{"118":118,"81":81,"85":85}],197:[function(_dereq_,module,exports){ // 19.1.2.11 Object.isExtensible(O) -var isObject = _dereq_(51); +var isObject = _dereq_(57); -_dereq_(83)('isExtensible', function ($isExtensible) { +_dereq_(85)('isExtensible', function ($isExtensible) { return function isExtensible(it) { return isObject(it) ? $isExtensible ? $isExtensible(it) : true : false; }; }); -},{"51":51,"83":83}],199:[function(_dereq_,module,exports){ +},{"57":57,"85":85}],198:[function(_dereq_,module,exports){ // 19.1.2.12 Object.isFrozen(O) -var isObject = _dereq_(51); +var isObject = _dereq_(57); -_dereq_(83)('isFrozen', function ($isFrozen) { +_dereq_(85)('isFrozen', function ($isFrozen) { return function isFrozen(it) { return isObject(it) ? $isFrozen ? $isFrozen(it) : false : true; }; }); -},{"51":51,"83":83}],200:[function(_dereq_,module,exports){ +},{"57":57,"85":85}],199:[function(_dereq_,module,exports){ // 19.1.2.13 Object.isSealed(O) -var isObject = _dereq_(51); +var isObject = _dereq_(57); -_dereq_(83)('isSealed', function ($isSealed) { +_dereq_(85)('isSealed', function ($isSealed) { return function isSealed(it) { return isObject(it) ? $isSealed ? $isSealed(it) : false : true; }; }); -},{"51":51,"83":83}],201:[function(_dereq_,module,exports){ +},{"57":57,"85":85}],200:[function(_dereq_,module,exports){ // 19.1.3.10 Object.is(value1, value2) -var $export = _dereq_(33); -$export($export.S, 'Object', { is: _dereq_(96) }); +var $export = _dereq_(40); +$export($export.S, 'Object', { is: _dereq_(97) }); -},{"33":33,"96":96}],202:[function(_dereq_,module,exports){ +},{"40":40,"97":97}],201:[function(_dereq_,module,exports){ // 19.1.2.14 Object.keys(O) -var toObject = _dereq_(119); -var $keys = _dereq_(81); +var toObject = _dereq_(118); +var $keys = _dereq_(83); -_dereq_(83)('keys', function () { +_dereq_(85)('keys', function () { return function keys(it) { return $keys(toObject(it)); }; }); -},{"119":119,"81":81,"83":83}],203:[function(_dereq_,module,exports){ +},{"118":118,"83":83,"85":85}],202:[function(_dereq_,module,exports){ // 19.1.2.15 Object.preventExtensions(O) -var isObject = _dereq_(51); -var meta = _dereq_(66).onFreeze; +var isObject = _dereq_(57); +var meta = _dereq_(70).onFreeze; -_dereq_(83)('preventExtensions', function ($preventExtensions) { +_dereq_(85)('preventExtensions', function ($preventExtensions) { return function preventExtensions(it) { return $preventExtensions && isObject(it) ? $preventExtensions(meta(it)) : it; }; }); -},{"51":51,"66":66,"83":83}],204:[function(_dereq_,module,exports){ +},{"57":57,"70":70,"85":85}],203:[function(_dereq_,module,exports){ // 19.1.2.17 Object.seal(O) -var isObject = _dereq_(51); -var meta = _dereq_(66).onFreeze; +var isObject = _dereq_(57); +var meta = _dereq_(70).onFreeze; -_dereq_(83)('seal', function ($seal) { +_dereq_(85)('seal', function ($seal) { return function seal(it) { return $seal && isObject(it) ? $seal(meta(it)) : it; }; }); -},{"51":51,"66":66,"83":83}],205:[function(_dereq_,module,exports){ +},{"57":57,"70":70,"85":85}],204:[function(_dereq_,module,exports){ // 19.1.3.19 Object.setPrototypeOf(O, proto) -var $export = _dereq_(33); -$export($export.S, 'Object', { setPrototypeOf: _dereq_(99).set }); +var $export = _dereq_(40); +$export($export.S, 'Object', { setPrototypeOf: _dereq_(98).set }); -},{"33":33,"99":99}],206:[function(_dereq_,module,exports){ +},{"40":40,"98":98}],205:[function(_dereq_,module,exports){ 'use strict'; // 19.1.3.6 Object.prototype.toString() -var classof = _dereq_(17); +var classof = _dereq_(25); var test = {}; test[_dereq_(128)('toStringTag')] = 'z'; if (test + '' != '[object z]') { @@ -4208,38 +4309,41 @@ if (test + '' != '[object z]') { }, true); } -},{"128":128,"17":17,"94":94}],207:[function(_dereq_,module,exports){ -var $export = _dereq_(33); -var $parseFloat = _dereq_(86); +},{"128":128,"25":25,"94":94}],206:[function(_dereq_,module,exports){ +var $export = _dereq_(40); +var $parseFloat = _dereq_(88); // 18.2.4 parseFloat(string) $export($export.G + $export.F * (parseFloat != $parseFloat), { parseFloat: $parseFloat }); -},{"33":33,"86":86}],208:[function(_dereq_,module,exports){ -var $export = _dereq_(33); -var $parseInt = _dereq_(87); +},{"40":40,"88":88}],207:[function(_dereq_,module,exports){ +var $export = _dereq_(40); +var $parseInt = _dereq_(89); // 18.2.5 parseInt(string, radix) $export($export.G + $export.F * (parseInt != $parseInt), { parseInt: $parseInt }); -},{"33":33,"87":87}],209:[function(_dereq_,module,exports){ +},{"40":40,"89":89}],208:[function(_dereq_,module,exports){ 'use strict'; -var LIBRARY = _dereq_(60); -var global = _dereq_(40); -var ctx = _dereq_(25); -var classof = _dereq_(17); -var $export = _dereq_(33); -var isObject = _dereq_(51); -var aFunction = _dereq_(3); -var anInstance = _dereq_(6); -var forOf = _dereq_(39); -var speciesConstructor = _dereq_(104); -var task = _dereq_(113).set; -var microtask = _dereq_(68)(); -var newPromiseCapabilityModule = _dereq_(69); +var LIBRARY = _dereq_(65); +var global = _dereq_(46); +var ctx = _dereq_(32); +var classof = _dereq_(25); +var $export = _dereq_(40); +var isObject = _dereq_(57); +var aFunction = _dereq_(11); +var anInstance = _dereq_(15); +var forOf = _dereq_(45); +var speciesConstructor = _dereq_(103); +var task = _dereq_(112).set; +var microtask = _dereq_(71)(); +var newPromiseCapabilityModule = _dereq_(72); var perform = _dereq_(90); +var userAgent = _dereq_(124); var promiseResolve = _dereq_(91); var PROMISE = 'Promise'; var TypeError = global.TypeError; var process = global.process; +var versions = process && process.versions; +var v8 = versions && versions.v8 || ''; var $Promise = global[PROMISE]; var isNode = classof(process) == 'process'; var empty = function () { /* empty */ }; @@ -4254,17 +4358,17 @@ var USE_NATIVE = !!function () { exec(empty, empty); }; // unhandled rejections tracking support, NodeJS Promise without it fails @@species test - return (isNode || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise; + return (isNode || typeof PromiseRejectionEvent == 'function') + && promise.then(empty) instanceof FakePromise + // v8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables + // https://bugs.chromium.org/p/chromium/issues/detail?id=830565 + // we can't detect it synchronously, so just check versions + && v8.indexOf('6.6') !== 0 + && userAgent.indexOf('Chrome/66') === -1; } catch (e) { /* empty */ } }(); // helpers -var sameConstructor = LIBRARY ? function (a, b) { - // with library wrapper special case - return a === b || a === $Promise && b === Wrapper; -} : function (a, b) { - return a === b; -}; var isThenable = function (it) { var then; return isObject(it) && typeof (then = it.then) == 'function' ? then : false; @@ -4282,7 +4386,7 @@ var notify = function (promise, isReject) { var resolve = reaction.resolve; var reject = reaction.reject; var domain = reaction.domain; - var result, then; + var result, then, exited; try { if (handler) { if (!ok) { @@ -4292,8 +4396,11 @@ var notify = function (promise, isReject) { if (handler === true) result = value; else { if (domain) domain.enter(); - result = handler(value); - if (domain) domain.exit(); + result = handler(value); // may throw + if (domain) { + domain.exit(); + exited = true; + } } if (result === reaction.promise) { reject(TypeError('Promise-chain cycle')); @@ -4302,6 +4409,7 @@ var notify = function (promise, isReject) { } else resolve(result); } else reject(value); } catch (e) { + if (domain && !exited) domain.exit(); reject(e); } }; @@ -4333,14 +4441,7 @@ var onUnhandled = function (promise) { }); }; var isUnhandled = function (promise) { - if (promise._h == 1) return false; - var chain = promise._a || promise._c; - var i = 0; - var reaction; - while (chain.length > i) { - reaction = chain[i++]; - if (reaction.fail || !isUnhandled(reaction.promise)) return false; - } return true; + return promise._h !== 1 && (promise._a || promise._c).length === 0; }; var onHandleUnhandled = function (promise) { task.call(global, function () { @@ -4436,16 +4537,16 @@ if (!USE_NATIVE) { this.reject = ctx($reject, promise, 1); }; newPromiseCapabilityModule.f = newPromiseCapability = function (C) { - return sameConstructor($Promise, C) + return C === $Promise || C === Wrapper ? new OwnPromiseCapability(C) : newGenericPromiseCapability(C); }; } $export($export.G + $export.W + $export.F * !USE_NATIVE, { Promise: $Promise }); -_dereq_(101)($Promise, PROMISE); -_dereq_(100)(PROMISE); -Wrapper = _dereq_(23)[PROMISE]; +_dereq_(100)($Promise, PROMISE); +_dereq_(99)(PROMISE); +Wrapper = _dereq_(30)[PROMISE]; // statics $export($export.S + $export.F * !USE_NATIVE, PROMISE, { @@ -4460,12 +4561,10 @@ $export($export.S + $export.F * !USE_NATIVE, PROMISE, { $export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, { // 25.4.4.6 Promise.resolve(x) resolve: function resolve(x) { - // instanceof instead of internal slot check because we should fix it without replacement native Promise core - if (x instanceof $Promise && sameConstructor(x.constructor, this)) return x; - return promiseResolve(this, x); + return promiseResolve(LIBRARY && this === Wrapper ? $Promise : this, x); } }); -$export($export.S + $export.F * !(USE_NATIVE && _dereq_(56)(function (iter) { +$export($export.S + $export.F * !(USE_NATIVE && _dereq_(62)(function (iter) { $Promise.all(iter)['catch'](empty); })), PROMISE, { // 25.4.4.1 Promise.all(iterable) @@ -4510,15 +4609,15 @@ $export($export.S + $export.F * !(USE_NATIVE && _dereq_(56)(function (iter) { } }); -},{"100":100,"101":101,"104":104,"113":113,"128":128,"17":17,"23":23,"25":25,"3":3,"33":33,"39":39,"40":40,"51":51,"56":56,"6":6,"60":60,"68":68,"69":69,"90":90,"91":91,"93":93}],210:[function(_dereq_,module,exports){ +},{"100":100,"103":103,"11":11,"112":112,"124":124,"128":128,"15":15,"25":25,"30":30,"32":32,"40":40,"45":45,"46":46,"57":57,"62":62,"65":65,"71":71,"72":72,"90":90,"91":91,"93":93,"99":99}],209:[function(_dereq_,module,exports){ // 26.1.1 Reflect.apply(target, thisArgument, argumentsList) -var $export = _dereq_(33); -var aFunction = _dereq_(3); -var anObject = _dereq_(7); -var rApply = (_dereq_(40).Reflect || {}).apply; +var $export = _dereq_(40); +var aFunction = _dereq_(11); +var anObject = _dereq_(16); +var rApply = (_dereq_(46).Reflect || {}).apply; var fApply = Function.apply; // MS Edge argumentsList argument is optional -$export($export.S + $export.F * !_dereq_(35)(function () { +$export($export.S + $export.F * !_dereq_(42)(function () { rApply(function () { /* empty */ }); }), 'Reflect', { apply: function apply(target, thisArgument, argumentsList) { @@ -4528,16 +4627,16 @@ $export($export.S + $export.F * !_dereq_(35)(function () { } }); -},{"3":3,"33":33,"35":35,"40":40,"7":7}],211:[function(_dereq_,module,exports){ +},{"11":11,"16":16,"40":40,"42":42,"46":46}],210:[function(_dereq_,module,exports){ // 26.1.2 Reflect.construct(target, argumentsList [, newTarget]) -var $export = _dereq_(33); -var create = _dereq_(71); -var aFunction = _dereq_(3); -var anObject = _dereq_(7); -var isObject = _dereq_(51); -var fails = _dereq_(35); -var bind = _dereq_(16); -var rConstruct = (_dereq_(40).Reflect || {}).construct; +var $export = _dereq_(40); +var create = _dereq_(74); +var aFunction = _dereq_(11); +var anObject = _dereq_(16); +var isObject = _dereq_(57); +var fails = _dereq_(42); +var bind = _dereq_(24); +var rConstruct = (_dereq_(46).Reflect || {}).construct; // MS Edge supports only 2 arguments and argumentsList argument is optional // FF Nightly sets third argument as `new.target`, but does not create `this` from it @@ -4577,15 +4676,15 @@ $export($export.S + $export.F * (NEW_TARGET_BUG || ARGS_BUG), 'Reflect', { } }); -},{"16":16,"3":3,"33":33,"35":35,"40":40,"51":51,"7":7,"71":71}],212:[function(_dereq_,module,exports){ +},{"11":11,"16":16,"24":24,"40":40,"42":42,"46":46,"57":57,"74":74}],211:[function(_dereq_,module,exports){ // 26.1.3 Reflect.defineProperty(target, propertyKey, attributes) -var dP = _dereq_(72); -var $export = _dereq_(33); -var anObject = _dereq_(7); -var toPrimitive = _dereq_(120); +var dP = _dereq_(75); +var $export = _dereq_(40); +var anObject = _dereq_(16); +var toPrimitive = _dereq_(119); // MS Edge has broken Reflect.defineProperty - throwing instead of returning false -$export($export.S + $export.F * _dereq_(35)(function () { +$export($export.S + $export.F * _dereq_(42)(function () { // eslint-disable-next-line no-undef Reflect.defineProperty(dP.f({}, 1, { value: 1 }), 1, { value: 2 }); }), 'Reflect', { @@ -4602,11 +4701,11 @@ $export($export.S + $export.F * _dereq_(35)(function () { } }); -},{"120":120,"33":33,"35":35,"7":7,"72":72}],213:[function(_dereq_,module,exports){ +},{"119":119,"16":16,"40":40,"42":42,"75":75}],212:[function(_dereq_,module,exports){ // 26.1.4 Reflect.deleteProperty(target, propertyKey) -var $export = _dereq_(33); -var gOPD = _dereq_(75).f; -var anObject = _dereq_(7); +var $export = _dereq_(40); +var gOPD = _dereq_(77).f; +var anObject = _dereq_(16); $export($export.S, 'Reflect', { deleteProperty: function deleteProperty(target, propertyKey) { @@ -4615,11 +4714,11 @@ $export($export.S, 'Reflect', { } }); -},{"33":33,"7":7,"75":75}],214:[function(_dereq_,module,exports){ +},{"16":16,"40":40,"77":77}],213:[function(_dereq_,module,exports){ 'use strict'; // 26.1.5 Reflect.enumerate(target) -var $export = _dereq_(33); -var anObject = _dereq_(7); +var $export = _dereq_(40); +var anObject = _dereq_(16); var Enumerate = function (iterated) { this._t = anObject(iterated); // target this._i = 0; // next index @@ -4627,7 +4726,7 @@ var Enumerate = function (iterated) { var key; for (key in iterated) keys.push(key); }; -_dereq_(54)(Enumerate, 'Object', function () { +_dereq_(60)(Enumerate, 'Object', function () { var that = this; var keys = that._k; var key; @@ -4643,11 +4742,11 @@ $export($export.S, 'Reflect', { } }); -},{"33":33,"54":54,"7":7}],215:[function(_dereq_,module,exports){ +},{"16":16,"40":40,"60":60}],214:[function(_dereq_,module,exports){ // 26.1.7 Reflect.getOwnPropertyDescriptor(target, propertyKey) -var gOPD = _dereq_(75); -var $export = _dereq_(33); -var anObject = _dereq_(7); +var gOPD = _dereq_(77); +var $export = _dereq_(40); +var anObject = _dereq_(16); $export($export.S, 'Reflect', { getOwnPropertyDescriptor: function getOwnPropertyDescriptor(target, propertyKey) { @@ -4655,11 +4754,11 @@ $export($export.S, 'Reflect', { } }); -},{"33":33,"7":7,"75":75}],216:[function(_dereq_,module,exports){ +},{"16":16,"40":40,"77":77}],215:[function(_dereq_,module,exports){ // 26.1.8 Reflect.getPrototypeOf(target) -var $export = _dereq_(33); -var getProto = _dereq_(79); -var anObject = _dereq_(7); +var $export = _dereq_(40); +var getProto = _dereq_(81); +var anObject = _dereq_(16); $export($export.S, 'Reflect', { getPrototypeOf: function getPrototypeOf(target) { @@ -4667,14 +4766,14 @@ $export($export.S, 'Reflect', { } }); -},{"33":33,"7":7,"79":79}],217:[function(_dereq_,module,exports){ +},{"16":16,"40":40,"81":81}],216:[function(_dereq_,module,exports){ // 26.1.6 Reflect.get(target, propertyKey [, receiver]) -var gOPD = _dereq_(75); -var getPrototypeOf = _dereq_(79); -var has = _dereq_(41); -var $export = _dereq_(33); -var isObject = _dereq_(51); -var anObject = _dereq_(7); +var gOPD = _dereq_(77); +var getPrototypeOf = _dereq_(81); +var has = _dereq_(47); +var $export = _dereq_(40); +var isObject = _dereq_(57); +var anObject = _dereq_(16); function get(target, propertyKey /* , receiver */) { var receiver = arguments.length < 3 ? target : arguments[2]; @@ -4690,9 +4789,9 @@ function get(target, propertyKey /* , receiver */) { $export($export.S, 'Reflect', { get: get }); -},{"33":33,"41":41,"51":51,"7":7,"75":75,"79":79}],218:[function(_dereq_,module,exports){ +},{"16":16,"40":40,"47":47,"57":57,"77":77,"81":81}],217:[function(_dereq_,module,exports){ // 26.1.9 Reflect.has(target, propertyKey) -var $export = _dereq_(33); +var $export = _dereq_(40); $export($export.S, 'Reflect', { has: function has(target, propertyKey) { @@ -4700,10 +4799,10 @@ $export($export.S, 'Reflect', { } }); -},{"33":33}],219:[function(_dereq_,module,exports){ +},{"40":40}],218:[function(_dereq_,module,exports){ // 26.1.10 Reflect.isExtensible(target) -var $export = _dereq_(33); -var anObject = _dereq_(7); +var $export = _dereq_(40); +var anObject = _dereq_(16); var $isExtensible = Object.isExtensible; $export($export.S, 'Reflect', { @@ -4713,16 +4812,16 @@ $export($export.S, 'Reflect', { } }); -},{"33":33,"7":7}],220:[function(_dereq_,module,exports){ +},{"16":16,"40":40}],219:[function(_dereq_,module,exports){ // 26.1.11 Reflect.ownKeys(target) -var $export = _dereq_(33); +var $export = _dereq_(40); -$export($export.S, 'Reflect', { ownKeys: _dereq_(85) }); +$export($export.S, 'Reflect', { ownKeys: _dereq_(87) }); -},{"33":33,"85":85}],221:[function(_dereq_,module,exports){ +},{"40":40,"87":87}],220:[function(_dereq_,module,exports){ // 26.1.12 Reflect.preventExtensions(target) -var $export = _dereq_(33); -var anObject = _dereq_(7); +var $export = _dereq_(40); +var anObject = _dereq_(16); var $preventExtensions = Object.preventExtensions; $export($export.S, 'Reflect', { @@ -4737,10 +4836,10 @@ $export($export.S, 'Reflect', { } }); -},{"33":33,"7":7}],222:[function(_dereq_,module,exports){ +},{"16":16,"40":40}],221:[function(_dereq_,module,exports){ // 26.1.14 Reflect.setPrototypeOf(target, proto) -var $export = _dereq_(33); -var setProto = _dereq_(99); +var $export = _dereq_(40); +var setProto = _dereq_(98); if (setProto) $export($export.S, 'Reflect', { setPrototypeOf: function setPrototypeOf(target, proto) { @@ -4754,16 +4853,16 @@ if (setProto) $export($export.S, 'Reflect', { } }); -},{"33":33,"99":99}],223:[function(_dereq_,module,exports){ +},{"40":40,"98":98}],222:[function(_dereq_,module,exports){ // 26.1.13 Reflect.set(target, propertyKey, V [, receiver]) -var dP = _dereq_(72); -var gOPD = _dereq_(75); -var getPrototypeOf = _dereq_(79); -var has = _dereq_(41); -var $export = _dereq_(33); +var dP = _dereq_(75); +var gOPD = _dereq_(77); +var getPrototypeOf = _dereq_(81); +var has = _dereq_(47); +var $export = _dereq_(40); var createDesc = _dereq_(92); -var anObject = _dereq_(7); -var isObject = _dereq_(51); +var anObject = _dereq_(16); +var isObject = _dereq_(57); function set(target, propertyKey, V /* , receiver */) { var receiver = arguments.length < 4 ? target : arguments[3]; @@ -4777,9 +4876,11 @@ function set(target, propertyKey, V /* , receiver */) { } if (has(ownDesc, 'value')) { if (ownDesc.writable === false || !isObject(receiver)) return false; - existingDescriptor = gOPD.f(receiver, propertyKey) || createDesc(0); - existingDescriptor.value = V; - dP.f(receiver, propertyKey, existingDescriptor); + if (existingDescriptor = gOPD.f(receiver, propertyKey)) { + if (existingDescriptor.get || existingDescriptor.set || existingDescriptor.writable === false) return false; + existingDescriptor.value = V; + dP.f(receiver, propertyKey, existingDescriptor); + } else dP.f(receiver, propertyKey, createDesc(0, V)); return true; } return ownDesc.set === undefined ? false : (ownDesc.set.call(receiver, V), true); @@ -4787,13 +4888,13 @@ function set(target, propertyKey, V /* , receiver */) { $export($export.S, 'Reflect', { set: set }); -},{"33":33,"41":41,"51":51,"7":7,"72":72,"75":75,"79":79,"92":92}],224:[function(_dereq_,module,exports){ -var global = _dereq_(40); -var inheritIfRequired = _dereq_(45); -var dP = _dereq_(72).f; -var gOPN = _dereq_(77).f; -var isRegExp = _dereq_(52); -var $flags = _dereq_(37); +},{"16":16,"40":40,"47":47,"57":57,"75":75,"77":77,"81":81,"92":92}],223:[function(_dereq_,module,exports){ +var global = _dereq_(46); +var inheritIfRequired = _dereq_(51); +var dP = _dereq_(75).f; +var gOPN = _dereq_(79).f; +var isRegExp = _dereq_(58); +var $flags = _dereq_(44); var $RegExp = global.RegExp; var Base = $RegExp; var proto = $RegExp.prototype; @@ -4802,7 +4903,7 @@ var re2 = /a/g; // "new" creates a new object, old webkit buggy here var CORRECT_NEW = new $RegExp(re1) !== re1; -if (_dereq_(29) && (!CORRECT_NEW || _dereq_(35)(function () { +if (_dereq_(36) && (!CORRECT_NEW || _dereq_(42)(function () { re2[_dereq_(128)('match')] = false; // RegExp constructor can alter flags and IsRegExp works correct with @@match return $RegExp(re1) != re1 || $RegExp(re2) == re2 || $RegExp(re1, 'i') != '/a/i'; @@ -4830,63 +4931,243 @@ if (_dereq_(29) && (!CORRECT_NEW || _dereq_(35)(function () { _dereq_(94)(global, 'RegExp', $RegExp); } -_dereq_(100)('RegExp'); +_dereq_(99)('RegExp'); -},{"100":100,"128":128,"29":29,"35":35,"37":37,"40":40,"45":45,"52":52,"72":72,"77":77,"94":94}],225:[function(_dereq_,module,exports){ +},{"128":128,"36":36,"42":42,"44":44,"46":46,"51":51,"58":58,"75":75,"79":79,"94":94,"99":99}],224:[function(_dereq_,module,exports){ +'use strict'; +var regexpExec = _dereq_(96); +_dereq_(40)({ + target: 'RegExp', + proto: true, + forced: regexpExec !== /./.exec +}, { + exec: regexpExec +}); + +},{"40":40,"96":96}],225:[function(_dereq_,module,exports){ // 21.2.5.3 get RegExp.prototype.flags() -if (_dereq_(29) && /./g.flags != 'g') _dereq_(72).f(RegExp.prototype, 'flags', { +if (_dereq_(36) && /./g.flags != 'g') _dereq_(75).f(RegExp.prototype, 'flags', { configurable: true, - get: _dereq_(37) + get: _dereq_(44) }); -},{"29":29,"37":37,"72":72}],226:[function(_dereq_,module,exports){ +},{"36":36,"44":44,"75":75}],226:[function(_dereq_,module,exports){ +'use strict'; + +var anObject = _dereq_(16); +var toLength = _dereq_(117); +var advanceStringIndex = _dereq_(14); +var regExpExec = _dereq_(95); + // @@match logic -_dereq_(36)('match', 1, function (defined, MATCH, $match) { - // 21.1.3.11 String.prototype.match(regexp) - return [function match(regexp) { - 'use strict'; - var O = defined(this); - var fn = regexp == undefined ? undefined : regexp[MATCH]; - return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[MATCH](String(O)); - }, $match]; +_dereq_(43)('match', 1, function (defined, MATCH, $match, maybeCallNative) { + return [ + // `String.prototype.match` method + // https://tc39.github.io/ecma262/#sec-string.prototype.match + function match(regexp) { + var O = defined(this); + var fn = regexp == undefined ? undefined : regexp[MATCH]; + return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[MATCH](String(O)); + }, + // `RegExp.prototype[@@match]` method + // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@match + function (regexp) { + var res = maybeCallNative($match, regexp, this); + if (res.done) return res.value; + var rx = anObject(regexp); + var S = String(this); + if (!rx.global) return regExpExec(rx, S); + var fullUnicode = rx.unicode; + rx.lastIndex = 0; + var A = []; + var n = 0; + var result; + while ((result = regExpExec(rx, S)) !== null) { + var matchStr = String(result[0]); + A[n] = matchStr; + if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength(rx.lastIndex), fullUnicode); + n++; + } + return n === 0 ? null : A; + } + ]; }); -},{"36":36}],227:[function(_dereq_,module,exports){ +},{"117":117,"14":14,"16":16,"43":43,"95":95}],227:[function(_dereq_,module,exports){ +'use strict'; + +var anObject = _dereq_(16); +var toObject = _dereq_(118); +var toLength = _dereq_(117); +var toInteger = _dereq_(115); +var advanceStringIndex = _dereq_(14); +var regExpExec = _dereq_(95); +var max = Math.max; +var min = Math.min; +var floor = Math.floor; +var SUBSTITUTION_SYMBOLS = /\$([$&`']|\d\d?|<[^>]*>)/g; +var SUBSTITUTION_SYMBOLS_NO_NAMED = /\$([$&`']|\d\d?)/g; + +var maybeToString = function (it) { + return it === undefined ? it : String(it); +}; + // @@replace logic -_dereq_(36)('replace', 2, function (defined, REPLACE, $replace) { - // 21.1.3.14 String.prototype.replace(searchValue, replaceValue) - return [function replace(searchValue, replaceValue) { - 'use strict'; - var O = defined(this); - var fn = searchValue == undefined ? undefined : searchValue[REPLACE]; - return fn !== undefined - ? fn.call(searchValue, O, replaceValue) - : $replace.call(String(O), searchValue, replaceValue); - }, $replace]; +_dereq_(43)('replace', 2, function (defined, REPLACE, $replace, maybeCallNative) { + return [ + // `String.prototype.replace` method + // https://tc39.github.io/ecma262/#sec-string.prototype.replace + function replace(searchValue, replaceValue) { + var O = defined(this); + var fn = searchValue == undefined ? undefined : searchValue[REPLACE]; + return fn !== undefined + ? fn.call(searchValue, O, replaceValue) + : $replace.call(String(O), searchValue, replaceValue); + }, + // `RegExp.prototype[@@replace]` method + // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@replace + function (regexp, replaceValue) { + var res = maybeCallNative($replace, regexp, this, replaceValue); + if (res.done) return res.value; + + var rx = anObject(regexp); + var S = String(this); + var functionalReplace = typeof replaceValue === 'function'; + if (!functionalReplace) replaceValue = String(replaceValue); + var global = rx.global; + if (global) { + var fullUnicode = rx.unicode; + rx.lastIndex = 0; + } + var results = []; + while (true) { + var result = regExpExec(rx, S); + if (result === null) break; + results.push(result); + if (!global) break; + var matchStr = String(result[0]); + if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength(rx.lastIndex), fullUnicode); + } + var accumulatedResult = ''; + var nextSourcePosition = 0; + for (var i = 0; i < results.length; i++) { + result = results[i]; + var matched = String(result[0]); + var position = max(min(toInteger(result.index), S.length), 0); + var captures = []; + // NOTE: This is equivalent to + // captures = result.slice(1).map(maybeToString) + // but for some reason `nativeSlice.call(result, 1, result.length)` (called in + // the slice polyfill when slicing native arrays) "doesn't work" in safari 9 and + // causes a crash (https://pastebin.com/N21QzeQA) when trying to debug it. + for (var j = 1; j < result.length; j++) captures.push(maybeToString(result[j])); + var namedCaptures = result.groups; + if (functionalReplace) { + var replacerArgs = [matched].concat(captures, position, S); + if (namedCaptures !== undefined) replacerArgs.push(namedCaptures); + var replacement = String(replaceValue.apply(undefined, replacerArgs)); + } else { + replacement = getSubstitution(matched, S, position, captures, namedCaptures, replaceValue); + } + if (position >= nextSourcePosition) { + accumulatedResult += S.slice(nextSourcePosition, position) + replacement; + nextSourcePosition = position + matched.length; + } + } + return accumulatedResult + S.slice(nextSourcePosition); + } + ]; + + // https://tc39.github.io/ecma262/#sec-getsubstitution + function getSubstitution(matched, str, position, captures, namedCaptures, replacement) { + var tailPos = position + matched.length; + var m = captures.length; + var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED; + if (namedCaptures !== undefined) { + namedCaptures = toObject(namedCaptures); + symbols = SUBSTITUTION_SYMBOLS; + } + return $replace.call(replacement, symbols, function (match, ch) { + var capture; + switch (ch.charAt(0)) { + case '$': return '$'; + case '&': return matched; + case '`': return str.slice(0, position); + case "'": return str.slice(tailPos); + case '<': + capture = namedCaptures[ch.slice(1, -1)]; + break; + default: // \d\d? + var n = +ch; + if (n === 0) return ch; + if (n > m) { + var f = floor(n / 10); + if (f === 0) return ch; + if (f <= m) return captures[f - 1] === undefined ? ch.charAt(1) : captures[f - 1] + ch.charAt(1); + return ch; + } + capture = captures[n - 1]; + } + return capture === undefined ? '' : capture; + }); + } }); -},{"36":36}],228:[function(_dereq_,module,exports){ +},{"115":115,"117":117,"118":118,"14":14,"16":16,"43":43,"95":95}],228:[function(_dereq_,module,exports){ +'use strict'; + +var anObject = _dereq_(16); +var sameValue = _dereq_(97); +var regExpExec = _dereq_(95); + // @@search logic -_dereq_(36)('search', 1, function (defined, SEARCH, $search) { - // 21.1.3.15 String.prototype.search(regexp) - return [function search(regexp) { - 'use strict'; - var O = defined(this); - var fn = regexp == undefined ? undefined : regexp[SEARCH]; - return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[SEARCH](String(O)); - }, $search]; +_dereq_(43)('search', 1, function (defined, SEARCH, $search, maybeCallNative) { + return [ + // `String.prototype.search` method + // https://tc39.github.io/ecma262/#sec-string.prototype.search + function search(regexp) { + var O = defined(this); + var fn = regexp == undefined ? undefined : regexp[SEARCH]; + return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[SEARCH](String(O)); + }, + // `RegExp.prototype[@@search]` method + // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@search + function (regexp) { + var res = maybeCallNative($search, regexp, this); + if (res.done) return res.value; + var rx = anObject(regexp); + var S = String(this); + var previousLastIndex = rx.lastIndex; + if (!sameValue(previousLastIndex, 0)) rx.lastIndex = 0; + var result = regExpExec(rx, S); + if (!sameValue(rx.lastIndex, previousLastIndex)) rx.lastIndex = previousLastIndex; + return result === null ? -1 : result.index; + } + ]; }); -},{"36":36}],229:[function(_dereq_,module,exports){ +},{"16":16,"43":43,"95":95,"97":97}],229:[function(_dereq_,module,exports){ +'use strict'; + +var isRegExp = _dereq_(58); +var anObject = _dereq_(16); +var speciesConstructor = _dereq_(103); +var advanceStringIndex = _dereq_(14); +var toLength = _dereq_(117); +var callRegExpExec = _dereq_(95); +var regexpExec = _dereq_(96); +var $min = Math.min; +var $push = [].push; +var $SPLIT = 'split'; +var LENGTH = 'length'; +var LAST_INDEX = 'lastIndex'; + +// eslint-disable-next-line no-empty +var SUPPORTS_Y = !!(function () { try { return new RegExp('x', 'y'); } catch (e) {} })(); + // @@split logic -_dereq_(36)('split', 2, function (defined, SPLIT, $split) { - 'use strict'; - var isRegExp = _dereq_(52); - var _split = $split; - var $push = [].push; - var $SPLIT = 'split'; - var LENGTH = 'length'; - var LAST_INDEX = 'lastIndex'; +_dereq_(43)('split', 2, function (defined, SPLIT, $split, maybeCallNative) { + var internalSplit; if ( 'abbc'[$SPLIT](/(b)*/)[1] == 'c' || 'test'[$SPLIT](/(?:)/, -1)[LENGTH] != 4 || @@ -4895,13 +5176,12 @@ _dereq_(36)('split', 2, function (defined, SPLIT, $split) { '.'[$SPLIT](/()()/)[LENGTH] > 1 || ''[$SPLIT](/.?/)[LENGTH] ) { - var NPCG = /()??/.exec('')[1] === undefined; // nonparticipating capturing group // based on es5-shim implementation, need to rework it - $split = function (separator, limit) { + internalSplit = function (separator, limit) { var string = String(this); if (separator === undefined && limit === 0) return []; // If `separator` is not a regex, use native split - if (!isRegExp(separator)) return _split.call(string, separator, limit); + if (!isRegExp(separator)) return $split.call(string, separator, limit); var output = []; var flags = (separator.ignoreCase ? 'i' : '') + (separator.multiline ? 'm' : '') + @@ -4911,19 +5191,11 @@ _dereq_(36)('split', 2, function (defined, SPLIT, $split) { var splitLimit = limit === undefined ? 4294967295 : limit >>> 0; // Make `global` and avoid `lastIndex` issues by working with a copy var separatorCopy = new RegExp(separator.source, flags + 'g'); - var separator2, match, lastIndex, lastLength, i; - // Doesn't need flags gy, but they don't hurt - if (!NPCG) separator2 = new RegExp('^' + separatorCopy.source + '$(?!\\s)', flags); - while (match = separatorCopy.exec(string)) { - // `separatorCopy.lastIndex` is not reliable cross-browser - lastIndex = match.index + match[0][LENGTH]; + var match, lastIndex, lastLength; + while (match = regexpExec.call(separatorCopy, string)) { + lastIndex = separatorCopy[LAST_INDEX]; if (lastIndex > lastLastIndex) { output.push(string.slice(lastLastIndex, match.index)); - // Fix browsers whose `exec` methods don't consistently return `undefined` for NPCG - // eslint-disable-next-line no-loop-func - if (!NPCG && match[LENGTH] > 1) match[0].replace(separator2, function () { - for (i = 1; i < arguments[LENGTH] - 2; i++) if (arguments[i] === undefined) match[i] = undefined; - }); if (match[LENGTH] > 1 && match.index < string[LENGTH]) $push.apply(output, match.slice(1)); lastLength = match[0][LENGTH]; lastLastIndex = lastIndex; @@ -4938,24 +5210,82 @@ _dereq_(36)('split', 2, function (defined, SPLIT, $split) { }; // Chakra, V8 } else if ('0'[$SPLIT](undefined, 0)[LENGTH]) { - $split = function (separator, limit) { - return separator === undefined && limit === 0 ? [] : _split.call(this, separator, limit); + internalSplit = function (separator, limit) { + return separator === undefined && limit === 0 ? [] : $split.call(this, separator, limit); }; + } else { + internalSplit = $split; } - // 21.1.3.17 String.prototype.split(separator, limit) - return [function split(separator, limit) { - var O = defined(this); - var fn = separator == undefined ? undefined : separator[SPLIT]; - return fn !== undefined ? fn.call(separator, O, limit) : $split.call(String(O), separator, limit); - }, $split]; + + return [ + // `String.prototype.split` method + // https://tc39.github.io/ecma262/#sec-string.prototype.split + function split(separator, limit) { + var O = defined(this); + var splitter = separator == undefined ? undefined : separator[SPLIT]; + return splitter !== undefined + ? splitter.call(separator, O, limit) + : internalSplit.call(String(O), separator, limit); + }, + // `RegExp.prototype[@@split]` method + // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@split + // + // NOTE: This cannot be properly polyfilled in engines that don't support + // the 'y' flag. + function (regexp, limit) { + var res = maybeCallNative(internalSplit, regexp, this, limit, internalSplit !== $split); + if (res.done) return res.value; + + var rx = anObject(regexp); + var S = String(this); + var C = speciesConstructor(rx, RegExp); + + var unicodeMatching = rx.unicode; + var flags = (rx.ignoreCase ? 'i' : '') + + (rx.multiline ? 'm' : '') + + (rx.unicode ? 'u' : '') + + (SUPPORTS_Y ? 'y' : 'g'); + + // ^(? + rx + ) is needed, in combination with some S slicing, to + // simulate the 'y' flag. + var splitter = new C(SUPPORTS_Y ? rx : '^(?:' + rx.source + ')', flags); + var lim = limit === undefined ? 0xffffffff : limit >>> 0; + if (lim === 0) return []; + if (S.length === 0) return callRegExpExec(splitter, S) === null ? [S] : []; + var p = 0; + var q = 0; + var A = []; + while (q < S.length) { + splitter.lastIndex = SUPPORTS_Y ? q : 0; + var z = callRegExpExec(splitter, SUPPORTS_Y ? S : S.slice(q)); + var e; + if ( + z === null || + (e = $min(toLength(splitter.lastIndex + (SUPPORTS_Y ? 0 : q)), S.length)) === p + ) { + q = advanceStringIndex(S, q, unicodeMatching); + } else { + A.push(S.slice(p, q)); + if (A.length === lim) return A; + for (var i = 1; i <= z.length - 1; i++) { + A.push(z[i]); + if (A.length === lim) return A; + } + q = p = e; + } + } + A.push(S.slice(p)); + return A; + } + ]; }); -},{"36":36,"52":52}],230:[function(_dereq_,module,exports){ +},{"103":103,"117":117,"14":14,"16":16,"43":43,"58":58,"95":95,"96":96}],230:[function(_dereq_,module,exports){ 'use strict'; _dereq_(225); -var anObject = _dereq_(7); -var $flags = _dereq_(37); -var DESCRIPTORS = _dereq_(29); +var anObject = _dereq_(16); +var $flags = _dereq_(44); +var DESCRIPTORS = _dereq_(36); var TO_STRING = 'toString'; var $toString = /./[TO_STRING]; @@ -4964,7 +5294,7 @@ var define = function (fn) { }; // 21.2.5.14 RegExp.prototype.toString() -if (_dereq_(35)(function () { return $toString.call({ source: 'a', flags: 'b' }) != '/a/b'; })) { +if (_dereq_(42)(function () { return $toString.call({ source: 'a', flags: 'b' }) != '/a/b'; })) { define(function toString() { var R = anObject(this); return '/'.concat(R.source, '/', @@ -4977,14 +5307,14 @@ if (_dereq_(35)(function () { return $toString.call({ source: 'a', flags: 'b' }) }); } -},{"225":225,"29":29,"35":35,"37":37,"7":7,"94":94}],231:[function(_dereq_,module,exports){ +},{"16":16,"225":225,"36":36,"42":42,"44":44,"94":94}],231:[function(_dereq_,module,exports){ 'use strict'; -var strong = _dereq_(19); +var strong = _dereq_(27); var validate = _dereq_(125); var SET = 'Set'; // 23.2 Set Objects -module.exports = _dereq_(22)(SET, function (get) { +module.exports = _dereq_(29)(SET, function (get) { return function Set() { return get(this, arguments.length > 0 ? arguments[0] : undefined); }; }, { // 23.2.3.1 Set.prototype.add(value) @@ -4993,46 +5323,46 @@ module.exports = _dereq_(22)(SET, function (get) { } }, strong); -},{"125":125,"19":19,"22":22}],232:[function(_dereq_,module,exports){ +},{"125":125,"27":27,"29":29}],232:[function(_dereq_,module,exports){ 'use strict'; // B.2.3.2 String.prototype.anchor(name) -_dereq_(108)('anchor', function (createHTML) { +_dereq_(107)('anchor', function (createHTML) { return function anchor(name) { return createHTML(this, 'a', 'name', name); }; }); -},{"108":108}],233:[function(_dereq_,module,exports){ +},{"107":107}],233:[function(_dereq_,module,exports){ 'use strict'; // B.2.3.3 String.prototype.big() -_dereq_(108)('big', function (createHTML) { +_dereq_(107)('big', function (createHTML) { return function big() { return createHTML(this, 'big', '', ''); }; }); -},{"108":108}],234:[function(_dereq_,module,exports){ +},{"107":107}],234:[function(_dereq_,module,exports){ 'use strict'; // B.2.3.4 String.prototype.blink() -_dereq_(108)('blink', function (createHTML) { +_dereq_(107)('blink', function (createHTML) { return function blink() { return createHTML(this, 'blink', '', ''); }; }); -},{"108":108}],235:[function(_dereq_,module,exports){ +},{"107":107}],235:[function(_dereq_,module,exports){ 'use strict'; // B.2.3.5 String.prototype.bold() -_dereq_(108)('bold', function (createHTML) { +_dereq_(107)('bold', function (createHTML) { return function bold() { return createHTML(this, 'b', '', ''); }; }); -},{"108":108}],236:[function(_dereq_,module,exports){ +},{"107":107}],236:[function(_dereq_,module,exports){ 'use strict'; -var $export = _dereq_(33); -var $at = _dereq_(106)(false); +var $export = _dereq_(40); +var $at = _dereq_(105)(false); $export($export.P, 'String', { // 21.1.3.3 String.prototype.codePointAt(pos) codePointAt: function codePointAt(pos) { @@ -5040,16 +5370,16 @@ $export($export.P, 'String', { } }); -},{"106":106,"33":33}],237:[function(_dereq_,module,exports){ +},{"105":105,"40":40}],237:[function(_dereq_,module,exports){ // 21.1.3.6 String.prototype.endsWith(searchString [, endPosition]) 'use strict'; -var $export = _dereq_(33); -var toLength = _dereq_(118); -var context = _dereq_(107); +var $export = _dereq_(40); +var toLength = _dereq_(117); +var context = _dereq_(106); var ENDS_WITH = 'endsWith'; var $endsWith = ''[ENDS_WITH]; -$export($export.P + $export.F * _dereq_(34)(ENDS_WITH), 'String', { +$export($export.P + $export.F * _dereq_(41)(ENDS_WITH), 'String', { endsWith: function endsWith(searchString /* , endPosition = @length */) { var that = context(this, searchString, ENDS_WITH); var endPosition = arguments.length > 1 ? arguments[1] : undefined; @@ -5062,36 +5392,36 @@ $export($export.P + $export.F * _dereq_(34)(ENDS_WITH), 'String', { } }); -},{"107":107,"118":118,"33":33,"34":34}],238:[function(_dereq_,module,exports){ +},{"106":106,"117":117,"40":40,"41":41}],238:[function(_dereq_,module,exports){ 'use strict'; // B.2.3.6 String.prototype.fixed() -_dereq_(108)('fixed', function (createHTML) { +_dereq_(107)('fixed', function (createHTML) { return function fixed() { return createHTML(this, 'tt', '', ''); }; }); -},{"108":108}],239:[function(_dereq_,module,exports){ +},{"107":107}],239:[function(_dereq_,module,exports){ 'use strict'; // B.2.3.7 String.prototype.fontcolor(color) -_dereq_(108)('fontcolor', function (createHTML) { +_dereq_(107)('fontcolor', function (createHTML) { return function fontcolor(color) { return createHTML(this, 'font', 'color', color); }; }); -},{"108":108}],240:[function(_dereq_,module,exports){ +},{"107":107}],240:[function(_dereq_,module,exports){ 'use strict'; // B.2.3.8 String.prototype.fontsize(size) -_dereq_(108)('fontsize', function (createHTML) { +_dereq_(107)('fontsize', function (createHTML) { return function fontsize(size) { return createHTML(this, 'font', 'size', size); }; }); -},{"108":108}],241:[function(_dereq_,module,exports){ -var $export = _dereq_(33); -var toAbsoluteIndex = _dereq_(114); +},{"107":107}],241:[function(_dereq_,module,exports){ +var $export = _dereq_(40); +var toAbsoluteIndex = _dereq_(113); var fromCharCode = String.fromCharCode; var $fromCodePoint = String.fromCodePoint; @@ -5114,35 +5444,35 @@ $export($export.S + $export.F * (!!$fromCodePoint && $fromCodePoint.length != 1) } }); -},{"114":114,"33":33}],242:[function(_dereq_,module,exports){ +},{"113":113,"40":40}],242:[function(_dereq_,module,exports){ // 21.1.3.7 String.prototype.includes(searchString, position = 0) 'use strict'; -var $export = _dereq_(33); -var context = _dereq_(107); +var $export = _dereq_(40); +var context = _dereq_(106); var INCLUDES = 'includes'; -$export($export.P + $export.F * _dereq_(34)(INCLUDES), 'String', { +$export($export.P + $export.F * _dereq_(41)(INCLUDES), 'String', { includes: function includes(searchString /* , position = 0 */) { return !!~context(this, searchString, INCLUDES) .indexOf(searchString, arguments.length > 1 ? arguments[1] : undefined); } }); -},{"107":107,"33":33,"34":34}],243:[function(_dereq_,module,exports){ +},{"106":106,"40":40,"41":41}],243:[function(_dereq_,module,exports){ 'use strict'; // B.2.3.9 String.prototype.italics() -_dereq_(108)('italics', function (createHTML) { +_dereq_(107)('italics', function (createHTML) { return function italics() { return createHTML(this, 'i', '', ''); }; }); -},{"108":108}],244:[function(_dereq_,module,exports){ +},{"107":107}],244:[function(_dereq_,module,exports){ 'use strict'; -var $at = _dereq_(106)(true); +var $at = _dereq_(105)(true); // 21.1.3.27 String.prototype[@@iterator]() -_dereq_(55)(String, 'String', function (iterated) { +_dereq_(61)(String, 'String', function (iterated) { this._t = String(iterated); // target this._i = 0; // next index // 21.1.5.2.1 %StringIteratorPrototype%.next() @@ -5156,19 +5486,19 @@ _dereq_(55)(String, 'String', function (iterated) { return { value: point, done: false }; }); -},{"106":106,"55":55}],245:[function(_dereq_,module,exports){ +},{"105":105,"61":61}],245:[function(_dereq_,module,exports){ 'use strict'; // B.2.3.10 String.prototype.link(url) -_dereq_(108)('link', function (createHTML) { +_dereq_(107)('link', function (createHTML) { return function link(url) { return createHTML(this, 'a', 'href', url); }; }); -},{"108":108}],246:[function(_dereq_,module,exports){ -var $export = _dereq_(33); -var toIObject = _dereq_(117); -var toLength = _dereq_(118); +},{"107":107}],246:[function(_dereq_,module,exports){ +var $export = _dereq_(40); +var toIObject = _dereq_(116); +var toLength = _dereq_(117); $export($export.S, 'String', { // 21.1.2.4 String.raw(callSite, ...substitutions) @@ -5185,33 +5515,33 @@ $export($export.S, 'String', { } }); -},{"117":117,"118":118,"33":33}],247:[function(_dereq_,module,exports){ -var $export = _dereq_(33); +},{"116":116,"117":117,"40":40}],247:[function(_dereq_,module,exports){ +var $export = _dereq_(40); $export($export.P, 'String', { // 21.1.3.13 String.prototype.repeat(count) - repeat: _dereq_(110) + repeat: _dereq_(109) }); -},{"110":110,"33":33}],248:[function(_dereq_,module,exports){ +},{"109":109,"40":40}],248:[function(_dereq_,module,exports){ 'use strict'; // B.2.3.11 String.prototype.small() -_dereq_(108)('small', function (createHTML) { +_dereq_(107)('small', function (createHTML) { return function small() { return createHTML(this, 'small', '', ''); }; }); -},{"108":108}],249:[function(_dereq_,module,exports){ +},{"107":107}],249:[function(_dereq_,module,exports){ // 21.1.3.18 String.prototype.startsWith(searchString [, position ]) 'use strict'; -var $export = _dereq_(33); -var toLength = _dereq_(118); -var context = _dereq_(107); +var $export = _dereq_(40); +var toLength = _dereq_(117); +var context = _dereq_(106); var STARTS_WITH = 'startsWith'; var $startsWith = ''[STARTS_WITH]; -$export($export.P + $export.F * _dereq_(34)(STARTS_WITH), 'String', { +$export($export.P + $export.F * _dereq_(41)(STARTS_WITH), 'String', { startsWith: function startsWith(searchString /* , position = 0 */) { var that = context(this, searchString, STARTS_WITH); var index = toLength(Math.min(arguments.length > 1 ? arguments[1] : undefined, that.length)); @@ -5222,70 +5552,70 @@ $export($export.P + $export.F * _dereq_(34)(STARTS_WITH), 'String', { } }); -},{"107":107,"118":118,"33":33,"34":34}],250:[function(_dereq_,module,exports){ +},{"106":106,"117":117,"40":40,"41":41}],250:[function(_dereq_,module,exports){ 'use strict'; // B.2.3.12 String.prototype.strike() -_dereq_(108)('strike', function (createHTML) { +_dereq_(107)('strike', function (createHTML) { return function strike() { return createHTML(this, 'strike', '', ''); }; }); -},{"108":108}],251:[function(_dereq_,module,exports){ +},{"107":107}],251:[function(_dereq_,module,exports){ 'use strict'; // B.2.3.13 String.prototype.sub() -_dereq_(108)('sub', function (createHTML) { +_dereq_(107)('sub', function (createHTML) { return function sub() { return createHTML(this, 'sub', '', ''); }; }); -},{"108":108}],252:[function(_dereq_,module,exports){ +},{"107":107}],252:[function(_dereq_,module,exports){ 'use strict'; // B.2.3.14 String.prototype.sup() -_dereq_(108)('sup', function (createHTML) { +_dereq_(107)('sup', function (createHTML) { return function sup() { return createHTML(this, 'sup', '', ''); }; }); -},{"108":108}],253:[function(_dereq_,module,exports){ +},{"107":107}],253:[function(_dereq_,module,exports){ 'use strict'; // 21.1.3.25 String.prototype.trim() -_dereq_(111)('trim', function ($trim) { +_dereq_(110)('trim', function ($trim) { return function trim() { return $trim(this, 3); }; }); -},{"111":111}],254:[function(_dereq_,module,exports){ +},{"110":110}],254:[function(_dereq_,module,exports){ 'use strict'; // ECMAScript 6 symbols shim -var global = _dereq_(40); -var has = _dereq_(41); -var DESCRIPTORS = _dereq_(29); -var $export = _dereq_(33); +var global = _dereq_(46); +var has = _dereq_(47); +var DESCRIPTORS = _dereq_(36); +var $export = _dereq_(40); var redefine = _dereq_(94); -var META = _dereq_(66).KEY; -var $fails = _dereq_(35); -var shared = _dereq_(103); -var setToStringTag = _dereq_(101); -var uid = _dereq_(124); +var META = _dereq_(70).KEY; +var $fails = _dereq_(42); +var shared = _dereq_(102); +var setToStringTag = _dereq_(100); +var uid = _dereq_(123); var wks = _dereq_(128); var wksExt = _dereq_(127); var wksDefine = _dereq_(126); -var keyOf = _dereq_(59); -var enumKeys = _dereq_(32); -var isArray = _dereq_(49); -var anObject = _dereq_(7); -var toIObject = _dereq_(117); -var toPrimitive = _dereq_(120); +var enumKeys = _dereq_(39); +var isArray = _dereq_(55); +var anObject = _dereq_(16); +var isObject = _dereq_(57); +var toIObject = _dereq_(116); +var toPrimitive = _dereq_(119); var createDesc = _dereq_(92); -var _create = _dereq_(71); -var gOPNExt = _dereq_(76); -var $GOPD = _dereq_(75); -var $DP = _dereq_(72); -var $keys = _dereq_(81); +var _create = _dereq_(74); +var gOPNExt = _dereq_(78); +var $GOPD = _dereq_(77); +var $DP = _dereq_(75); +var $keys = _dereq_(83); var gOPD = $GOPD.f; var dP = $DP.f; var gOPN = gOPNExt.f; @@ -5408,11 +5738,11 @@ if (!USE_NATIVE) { $GOPD.f = $getOwnPropertyDescriptor; $DP.f = $defineProperty; - _dereq_(77).f = gOPNExt.f = $getOwnPropertyNames; - _dereq_(82).f = $propertyIsEnumerable; - _dereq_(78).f = $getOwnPropertySymbols; + _dereq_(79).f = gOPNExt.f = $getOwnPropertyNames; + _dereq_(84).f = $propertyIsEnumerable; + _dereq_(80).f = $getOwnPropertySymbols; - if (DESCRIPTORS && !_dereq_(60)) { + if (DESCRIPTORS && !_dereq_(65)) { redefine(ObjectProto, 'propertyIsEnumerable', $propertyIsEnumerable, true); } @@ -5438,9 +5768,9 @@ $export($export.S + $export.F * !USE_NATIVE, 'Symbol', { : SymbolRegistry[key] = $Symbol(key); }, // 19.4.2.5 Symbol.keyFor(sym) - keyFor: function keyFor(key) { - if (isSymbol(key)) return keyOf(SymbolRegistry, key); - throw TypeError(key + ' is not a symbol!'); + keyFor: function keyFor(sym) { + if (!isSymbol(sym)) throw TypeError(sym + ' is not a symbol!'); + for (var key in SymbolRegistry) if (SymbolRegistry[key] === sym) return key; }, useSetter: function () { setter = true; }, useSimple: function () { setter = false; } @@ -5470,15 +5800,14 @@ $JSON && $export($export.S + $export.F * (!USE_NATIVE || $fails(function () { return _stringify([S]) != '[null]' || _stringify({ a: S }) != '{}' || _stringify(Object(S)) != '{}'; })), 'JSON', { stringify: function stringify(it) { - if (it === undefined || isSymbol(it)) return; // IE8 returns string on undefined var args = [it]; var i = 1; var replacer, $replacer; while (arguments.length > i) args.push(arguments[i++]); - replacer = args[1]; - if (typeof replacer == 'function') $replacer = replacer; - if ($replacer || !isArray(replacer)) replacer = function (key, value) { - if ($replacer) value = $replacer.call(this, key, value); + $replacer = replacer = args[1]; + if (!isObject(replacer) && it === undefined || isSymbol(it)) return; // IE8 returns string on undefined + if (!isArray(replacer)) replacer = function (key, value) { + if (typeof $replacer == 'function') value = $replacer.call(this, key, value); if (!isSymbol(value)) return value; }; args[1] = replacer; @@ -5487,7 +5816,7 @@ $JSON && $export($export.S + $export.F * (!USE_NATIVE || $fails(function () { }); // 19.4.3.4 Symbol.prototype[@@toPrimitive](hint) -$Symbol[PROTOTYPE][TO_PRIMITIVE] || _dereq_(42)($Symbol[PROTOTYPE], TO_PRIMITIVE, $Symbol[PROTOTYPE].valueOf); +$Symbol[PROTOTYPE][TO_PRIMITIVE] || _dereq_(48)($Symbol[PROTOTYPE], TO_PRIMITIVE, $Symbol[PROTOTYPE].valueOf); // 19.4.3.5 Symbol.prototype[@@toStringTag] setToStringTag($Symbol, 'Symbol'); // 20.2.1.9 Math[@@toStringTag] @@ -5495,17 +5824,17 @@ setToStringTag(Math, 'Math', true); // 24.3.3 JSON[@@toStringTag] setToStringTag(global.JSON, 'JSON', true); -},{"101":101,"103":103,"117":117,"120":120,"124":124,"126":126,"127":127,"128":128,"29":29,"32":32,"33":33,"35":35,"40":40,"41":41,"42":42,"49":49,"59":59,"60":60,"66":66,"7":7,"71":71,"72":72,"75":75,"76":76,"77":77,"78":78,"81":81,"82":82,"92":92,"94":94}],255:[function(_dereq_,module,exports){ +},{"100":100,"102":102,"116":116,"119":119,"123":123,"126":126,"127":127,"128":128,"16":16,"36":36,"39":39,"40":40,"42":42,"46":46,"47":47,"48":48,"55":55,"57":57,"65":65,"70":70,"74":74,"75":75,"77":77,"78":78,"79":79,"80":80,"83":83,"84":84,"92":92,"94":94}],255:[function(_dereq_,module,exports){ 'use strict'; -var $export = _dereq_(33); -var $typed = _dereq_(123); -var buffer = _dereq_(122); -var anObject = _dereq_(7); -var toAbsoluteIndex = _dereq_(114); -var toLength = _dereq_(118); -var isObject = _dereq_(51); -var ArrayBuffer = _dereq_(40).ArrayBuffer; -var speciesConstructor = _dereq_(104); +var $export = _dereq_(40); +var $typed = _dereq_(122); +var buffer = _dereq_(121); +var anObject = _dereq_(16); +var toAbsoluteIndex = _dereq_(113); +var toLength = _dereq_(117); +var isObject = _dereq_(57); +var ArrayBuffer = _dereq_(46).ArrayBuffer; +var speciesConstructor = _dereq_(103); var $ArrayBuffer = buffer.ArrayBuffer; var $DataView = buffer.DataView; var $isView = $typed.ABV && ArrayBuffer.isView; @@ -5522,7 +5851,7 @@ $export($export.S + $export.F * !$typed.CONSTR, ARRAY_BUFFER, { } }); -$export($export.P + $export.U + $export.F * _dereq_(35)(function () { +$export($export.P + $export.U + $export.F * _dereq_(42)(function () { return !new $ArrayBuffer(2).slice(1, undefined).byteLength; }), ARRAY_BUFFER, { // 24.1.4.3 ArrayBuffer.prototype.slice(start, end) @@ -5530,97 +5859,97 @@ $export($export.P + $export.U + $export.F * _dereq_(35)(function () { if ($slice !== undefined && end === undefined) return $slice.call(anObject(this), start); // FF fix var len = anObject(this).byteLength; var first = toAbsoluteIndex(start, len); - var final = toAbsoluteIndex(end === undefined ? len : end, len); - var result = new (speciesConstructor(this, $ArrayBuffer))(toLength(final - first)); + var fin = toAbsoluteIndex(end === undefined ? len : end, len); + var result = new (speciesConstructor(this, $ArrayBuffer))(toLength(fin - first)); var viewS = new $DataView(this); var viewT = new $DataView(result); var index = 0; - while (first < final) { + while (first < fin) { viewT.setUint8(index++, viewS.getUint8(first++)); } return result; } }); -_dereq_(100)(ARRAY_BUFFER); +_dereq_(99)(ARRAY_BUFFER); -},{"100":100,"104":104,"114":114,"118":118,"122":122,"123":123,"33":33,"35":35,"40":40,"51":51,"7":7}],256:[function(_dereq_,module,exports){ -var $export = _dereq_(33); -$export($export.G + $export.W + $export.F * !_dereq_(123).ABV, { - DataView: _dereq_(122).DataView +},{"103":103,"113":113,"117":117,"121":121,"122":122,"16":16,"40":40,"42":42,"46":46,"57":57,"99":99}],256:[function(_dereq_,module,exports){ +var $export = _dereq_(40); +$export($export.G + $export.W + $export.F * !_dereq_(122).ABV, { + DataView: _dereq_(121).DataView }); -},{"122":122,"123":123,"33":33}],257:[function(_dereq_,module,exports){ -_dereq_(121)('Float32', 4, function (init) { +},{"121":121,"122":122,"40":40}],257:[function(_dereq_,module,exports){ +_dereq_(120)('Float32', 4, function (init) { return function Float32Array(data, byteOffset, length) { return init(this, data, byteOffset, length); }; }); -},{"121":121}],258:[function(_dereq_,module,exports){ -_dereq_(121)('Float64', 8, function (init) { +},{"120":120}],258:[function(_dereq_,module,exports){ +_dereq_(120)('Float64', 8, function (init) { return function Float64Array(data, byteOffset, length) { return init(this, data, byteOffset, length); }; }); -},{"121":121}],259:[function(_dereq_,module,exports){ -_dereq_(121)('Int16', 2, function (init) { +},{"120":120}],259:[function(_dereq_,module,exports){ +_dereq_(120)('Int16', 2, function (init) { return function Int16Array(data, byteOffset, length) { return init(this, data, byteOffset, length); }; }); -},{"121":121}],260:[function(_dereq_,module,exports){ -_dereq_(121)('Int32', 4, function (init) { +},{"120":120}],260:[function(_dereq_,module,exports){ +_dereq_(120)('Int32', 4, function (init) { return function Int32Array(data, byteOffset, length) { return init(this, data, byteOffset, length); }; }); -},{"121":121}],261:[function(_dereq_,module,exports){ -_dereq_(121)('Int8', 1, function (init) { +},{"120":120}],261:[function(_dereq_,module,exports){ +_dereq_(120)('Int8', 1, function (init) { return function Int8Array(data, byteOffset, length) { return init(this, data, byteOffset, length); }; }); -},{"121":121}],262:[function(_dereq_,module,exports){ -_dereq_(121)('Uint16', 2, function (init) { +},{"120":120}],262:[function(_dereq_,module,exports){ +_dereq_(120)('Uint16', 2, function (init) { return function Uint16Array(data, byteOffset, length) { return init(this, data, byteOffset, length); }; }); -},{"121":121}],263:[function(_dereq_,module,exports){ -_dereq_(121)('Uint32', 4, function (init) { +},{"120":120}],263:[function(_dereq_,module,exports){ +_dereq_(120)('Uint32', 4, function (init) { return function Uint32Array(data, byteOffset, length) { return init(this, data, byteOffset, length); }; }); -},{"121":121}],264:[function(_dereq_,module,exports){ -_dereq_(121)('Uint8', 1, function (init) { +},{"120":120}],264:[function(_dereq_,module,exports){ +_dereq_(120)('Uint8', 1, function (init) { return function Uint8Array(data, byteOffset, length) { return init(this, data, byteOffset, length); }; }); -},{"121":121}],265:[function(_dereq_,module,exports){ -_dereq_(121)('Uint8', 1, function (init) { +},{"120":120}],265:[function(_dereq_,module,exports){ +_dereq_(120)('Uint8', 1, function (init) { return function Uint8ClampedArray(data, byteOffset, length) { return init(this, data, byteOffset, length); }; }, true); -},{"121":121}],266:[function(_dereq_,module,exports){ +},{"120":120}],266:[function(_dereq_,module,exports){ 'use strict'; -var each = _dereq_(12)(0); +var each = _dereq_(20)(0); var redefine = _dereq_(94); -var meta = _dereq_(66); -var assign = _dereq_(70); -var weak = _dereq_(21); -var isObject = _dereq_(51); -var fails = _dereq_(35); +var meta = _dereq_(70); +var assign = _dereq_(73); +var weak = _dereq_(28); +var isObject = _dereq_(57); +var fails = _dereq_(42); var validate = _dereq_(125); var WEAK_MAP = 'WeakMap'; var getWeak = meta.getWeak; @@ -5651,7 +5980,7 @@ var methods = { }; // 23.3 WeakMap Objects -var $WeakMap = module.exports = _dereq_(22)(WEAK_MAP, wrapper, methods, weak, true, true); +var $WeakMap = module.exports = _dereq_(29)(WEAK_MAP, wrapper, methods, weak, true, true); // IE11 WeakMap frozen keys fix if (fails(function () { return new $WeakMap().set((Object.freeze || Object)(tmp), 7).get(tmp) != 7; })) { @@ -5673,14 +6002,14 @@ if (fails(function () { return new $WeakMap().set((Object.freeze || Object)(tmp) }); } -},{"12":12,"125":125,"21":21,"22":22,"35":35,"51":51,"66":66,"70":70,"94":94}],267:[function(_dereq_,module,exports){ +},{"125":125,"20":20,"28":28,"29":29,"42":42,"57":57,"70":70,"73":73,"94":94}],267:[function(_dereq_,module,exports){ 'use strict'; -var weak = _dereq_(21); +var weak = _dereq_(28); var validate = _dereq_(125); var WEAK_SET = 'WeakSet'; // 23.4 WeakSet Objects -_dereq_(22)(WEAK_SET, function (get) { +_dereq_(29)(WEAK_SET, function (get) { return function WeakSet() { return get(this, arguments.length > 0 ? arguments[0] : undefined); }; }, { // 23.4.3.1 WeakSet.prototype.add(value) @@ -5689,58 +6018,11 @@ _dereq_(22)(WEAK_SET, function (get) { } }, weak, false, true); -},{"125":125,"21":21,"22":22}],268:[function(_dereq_,module,exports){ -'use strict'; -// https://tc39.github.io/proposal-flatMap/#sec-Array.prototype.flatMap -var $export = _dereq_(33); -var flattenIntoArray = _dereq_(38); -var toObject = _dereq_(119); -var toLength = _dereq_(118); -var aFunction = _dereq_(3); -var arraySpeciesCreate = _dereq_(15); - -$export($export.P, 'Array', { - flatMap: function flatMap(callbackfn /* , thisArg */) { - var O = toObject(this); - var sourceLen, A; - aFunction(callbackfn); - sourceLen = toLength(O.length); - A = arraySpeciesCreate(O, 0); - flattenIntoArray(A, O, O, sourceLen, 0, 1, callbackfn, arguments[1]); - return A; - } -}); - -_dereq_(5)('flatMap'); - -},{"118":118,"119":119,"15":15,"3":3,"33":33,"38":38,"5":5}],269:[function(_dereq_,module,exports){ -'use strict'; -// https://tc39.github.io/proposal-flatMap/#sec-Array.prototype.flatten -var $export = _dereq_(33); -var flattenIntoArray = _dereq_(38); -var toObject = _dereq_(119); -var toLength = _dereq_(118); -var toInteger = _dereq_(116); -var arraySpeciesCreate = _dereq_(15); - -$export($export.P, 'Array', { - flatten: function flatten(/* depthArg = 1 */) { - var depthArg = arguments[0]; - var O = toObject(this); - var sourceLen = toLength(O.length); - var A = arraySpeciesCreate(O, 0); - flattenIntoArray(A, O, O, sourceLen, 0, depthArg === undefined ? 1 : toInteger(depthArg)); - return A; - } -}); - -_dereq_(5)('flatten'); - -},{"116":116,"118":118,"119":119,"15":15,"33":33,"38":38,"5":5}],270:[function(_dereq_,module,exports){ +},{"125":125,"28":28,"29":29}],268:[function(_dereq_,module,exports){ 'use strict'; // https://github.com/tc39/Array.prototype.includes -var $export = _dereq_(33); -var $includes = _dereq_(11)(true); +var $export = _dereq_(40); +var $includes = _dereq_(19)(true); $export($export.P, 'Array', { includes: function includes(el /* , fromIndex = 0 */) { @@ -5748,218 +6030,12 @@ $export($export.P, 'Array', { } }); -_dereq_(5)('includes'); +_dereq_(13)('includes'); -},{"11":11,"33":33,"5":5}],271:[function(_dereq_,module,exports){ -// https://github.com/rwaldron/tc39-notes/blob/master/es6/2014-09/sept-25.md#510-globalasap-for-enqueuing-a-microtask -var $export = _dereq_(33); -var microtask = _dereq_(68)(); -var process = _dereq_(40).process; -var isNode = _dereq_(18)(process) == 'process'; - -$export($export.G, { - asap: function asap(fn) { - var domain = isNode && process.domain; - microtask(domain ? domain.bind(fn) : fn); - } -}); - -},{"18":18,"33":33,"40":40,"68":68}],272:[function(_dereq_,module,exports){ -// https://github.com/ljharb/proposal-is-error -var $export = _dereq_(33); -var cof = _dereq_(18); - -$export($export.S, 'Error', { - isError: function isError(it) { - return cof(it) === 'Error'; - } -}); - -},{"18":18,"33":33}],273:[function(_dereq_,module,exports){ -// https://github.com/tc39/proposal-global -var $export = _dereq_(33); - -$export($export.G, { global: _dereq_(40) }); - -},{"33":33,"40":40}],274:[function(_dereq_,module,exports){ -// https://tc39.github.io/proposal-setmap-offrom/#sec-map.from -_dereq_(97)('Map'); - -},{"97":97}],275:[function(_dereq_,module,exports){ -// https://tc39.github.io/proposal-setmap-offrom/#sec-map.of -_dereq_(98)('Map'); - -},{"98":98}],276:[function(_dereq_,module,exports){ -// https://github.com/DavidBruant/Map-Set.prototype.toJSON -var $export = _dereq_(33); - -$export($export.P + $export.R, 'Map', { toJSON: _dereq_(20)('Map') }); - -},{"20":20,"33":33}],277:[function(_dereq_,module,exports){ -// https://rwaldron.github.io/proposal-math-extensions/ -var $export = _dereq_(33); - -$export($export.S, 'Math', { - clamp: function clamp(x, lower, upper) { - return Math.min(upper, Math.max(lower, x)); - } -}); - -},{"33":33}],278:[function(_dereq_,module,exports){ -// https://rwaldron.github.io/proposal-math-extensions/ -var $export = _dereq_(33); - -$export($export.S, 'Math', { DEG_PER_RAD: Math.PI / 180 }); - -},{"33":33}],279:[function(_dereq_,module,exports){ -// https://rwaldron.github.io/proposal-math-extensions/ -var $export = _dereq_(33); -var RAD_PER_DEG = 180 / Math.PI; - -$export($export.S, 'Math', { - degrees: function degrees(radians) { - return radians * RAD_PER_DEG; - } -}); - -},{"33":33}],280:[function(_dereq_,module,exports){ -// https://rwaldron.github.io/proposal-math-extensions/ -var $export = _dereq_(33); -var scale = _dereq_(64); -var fround = _dereq_(62); - -$export($export.S, 'Math', { - fscale: function fscale(x, inLow, inHigh, outLow, outHigh) { - return fround(scale(x, inLow, inHigh, outLow, outHigh)); - } -}); - -},{"33":33,"62":62,"64":64}],281:[function(_dereq_,module,exports){ -// https://gist.github.com/BrendanEich/4294d5c212a6d2254703 -var $export = _dereq_(33); - -$export($export.S, 'Math', { - iaddh: function iaddh(x0, x1, y0, y1) { - var $x0 = x0 >>> 0; - var $x1 = x1 >>> 0; - var $y0 = y0 >>> 0; - return $x1 + (y1 >>> 0) + (($x0 & $y0 | ($x0 | $y0) & ~($x0 + $y0 >>> 0)) >>> 31) | 0; - } -}); - -},{"33":33}],282:[function(_dereq_,module,exports){ -// https://gist.github.com/BrendanEich/4294d5c212a6d2254703 -var $export = _dereq_(33); - -$export($export.S, 'Math', { - imulh: function imulh(u, v) { - var UINT16 = 0xffff; - var $u = +u; - var $v = +v; - var u0 = $u & UINT16; - var v0 = $v & UINT16; - var u1 = $u >> 16; - var v1 = $v >> 16; - var t = (u1 * v0 >>> 0) + (u0 * v0 >>> 16); - return u1 * v1 + (t >> 16) + ((u0 * v1 >>> 0) + (t & UINT16) >> 16); - } -}); - -},{"33":33}],283:[function(_dereq_,module,exports){ -// https://gist.github.com/BrendanEich/4294d5c212a6d2254703 -var $export = _dereq_(33); - -$export($export.S, 'Math', { - isubh: function isubh(x0, x1, y0, y1) { - var $x0 = x0 >>> 0; - var $x1 = x1 >>> 0; - var $y0 = y0 >>> 0; - return $x1 - (y1 >>> 0) - ((~$x0 & $y0 | ~($x0 ^ $y0) & $x0 - $y0 >>> 0) >>> 31) | 0; - } -}); - -},{"33":33}],284:[function(_dereq_,module,exports){ -// https://rwaldron.github.io/proposal-math-extensions/ -var $export = _dereq_(33); - -$export($export.S, 'Math', { RAD_PER_DEG: 180 / Math.PI }); - -},{"33":33}],285:[function(_dereq_,module,exports){ -// https://rwaldron.github.io/proposal-math-extensions/ -var $export = _dereq_(33); -var DEG_PER_RAD = Math.PI / 180; - -$export($export.S, 'Math', { - radians: function radians(degrees) { - return degrees * DEG_PER_RAD; - } -}); - -},{"33":33}],286:[function(_dereq_,module,exports){ -// https://rwaldron.github.io/proposal-math-extensions/ -var $export = _dereq_(33); - -$export($export.S, 'Math', { scale: _dereq_(64) }); - -},{"33":33,"64":64}],287:[function(_dereq_,module,exports){ -// http://jfbastien.github.io/papers/Math.signbit.html -var $export = _dereq_(33); - -$export($export.S, 'Math', { signbit: function signbit(x) { - // eslint-disable-next-line no-self-compare - return (x = +x) != x ? x : x == 0 ? 1 / x == Infinity : x > 0; -} }); - -},{"33":33}],288:[function(_dereq_,module,exports){ -// https://gist.github.com/BrendanEich/4294d5c212a6d2254703 -var $export = _dereq_(33); - -$export($export.S, 'Math', { - umulh: function umulh(u, v) { - var UINT16 = 0xffff; - var $u = +u; - var $v = +v; - var u0 = $u & UINT16; - var v0 = $v & UINT16; - var u1 = $u >>> 16; - var v1 = $v >>> 16; - var t = (u1 * v0 >>> 0) + (u0 * v0 >>> 16); - return u1 * v1 + (t >>> 16) + ((u0 * v1 >>> 0) + (t & UINT16) >>> 16); - } -}); - -},{"33":33}],289:[function(_dereq_,module,exports){ -'use strict'; -var $export = _dereq_(33); -var toObject = _dereq_(119); -var aFunction = _dereq_(3); -var $defineProperty = _dereq_(72); - -// B.2.2.2 Object.prototype.__defineGetter__(P, getter) -_dereq_(29) && $export($export.P + _dereq_(74), 'Object', { - __defineGetter__: function __defineGetter__(P, getter) { - $defineProperty.f(toObject(this), P, { get: aFunction(getter), enumerable: true, configurable: true }); - } -}); - -},{"119":119,"29":29,"3":3,"33":33,"72":72,"74":74}],290:[function(_dereq_,module,exports){ -'use strict'; -var $export = _dereq_(33); -var toObject = _dereq_(119); -var aFunction = _dereq_(3); -var $defineProperty = _dereq_(72); - -// B.2.2.3 Object.prototype.__defineSetter__(P, setter) -_dereq_(29) && $export($export.P + _dereq_(74), 'Object', { - __defineSetter__: function __defineSetter__(P, setter) { - $defineProperty.f(toObject(this), P, { set: aFunction(setter), enumerable: true, configurable: true }); - } -}); - -},{"119":119,"29":29,"3":3,"33":33,"72":72,"74":74}],291:[function(_dereq_,module,exports){ +},{"13":13,"19":19,"40":40}],269:[function(_dereq_,module,exports){ // https://github.com/tc39/proposal-object-values-entries -var $export = _dereq_(33); -var $entries = _dereq_(84)(true); +var $export = _dereq_(40); +var $entries = _dereq_(86)(true); $export($export.S, 'Object', { entries: function entries(it) { @@ -5967,13 +6043,13 @@ $export($export.S, 'Object', { } }); -},{"33":33,"84":84}],292:[function(_dereq_,module,exports){ +},{"40":40,"86":86}],270:[function(_dereq_,module,exports){ // https://github.com/tc39/proposal-object-getownpropertydescriptors -var $export = _dereq_(33); -var ownKeys = _dereq_(85); -var toIObject = _dereq_(117); -var gOPD = _dereq_(75); -var createProperty = _dereq_(24); +var $export = _dereq_(40); +var ownKeys = _dereq_(87); +var toIObject = _dereq_(116); +var gOPD = _dereq_(77); +var createProperty = _dereq_(31); $export($export.S, 'Object', { getOwnPropertyDescriptors: function getOwnPropertyDescriptors(object) { @@ -5991,50 +6067,10 @@ $export($export.S, 'Object', { } }); -},{"117":117,"24":24,"33":33,"75":75,"85":85}],293:[function(_dereq_,module,exports){ -'use strict'; -var $export = _dereq_(33); -var toObject = _dereq_(119); -var toPrimitive = _dereq_(120); -var getPrototypeOf = _dereq_(79); -var getOwnPropertyDescriptor = _dereq_(75).f; - -// B.2.2.4 Object.prototype.__lookupGetter__(P) -_dereq_(29) && $export($export.P + _dereq_(74), 'Object', { - __lookupGetter__: function __lookupGetter__(P) { - var O = toObject(this); - var K = toPrimitive(P, true); - var D; - do { - if (D = getOwnPropertyDescriptor(O, K)) return D.get; - } while (O = getPrototypeOf(O)); - } -}); - -},{"119":119,"120":120,"29":29,"33":33,"74":74,"75":75,"79":79}],294:[function(_dereq_,module,exports){ -'use strict'; -var $export = _dereq_(33); -var toObject = _dereq_(119); -var toPrimitive = _dereq_(120); -var getPrototypeOf = _dereq_(79); -var getOwnPropertyDescriptor = _dereq_(75).f; - -// B.2.2.5 Object.prototype.__lookupSetter__(P) -_dereq_(29) && $export($export.P + _dereq_(74), 'Object', { - __lookupSetter__: function __lookupSetter__(P) { - var O = toObject(this); - var K = toPrimitive(P, true); - var D; - do { - if (D = getOwnPropertyDescriptor(O, K)) return D.set; - } while (O = getPrototypeOf(O)); - } -}); - -},{"119":119,"120":120,"29":29,"33":33,"74":74,"75":75,"79":79}],295:[function(_dereq_,module,exports){ +},{"116":116,"31":31,"40":40,"77":77,"87":87}],271:[function(_dereq_,module,exports){ // https://github.com/tc39/proposal-object-values-entries -var $export = _dereq_(33); -var $values = _dereq_(84)(false); +var $export = _dereq_(40); +var $values = _dereq_(86)(false); $export($export.S, 'Object', { values: function values(it) { @@ -6042,214 +6078,13 @@ $export($export.S, 'Object', { } }); -},{"33":33,"84":84}],296:[function(_dereq_,module,exports){ -'use strict'; -// https://github.com/zenparsing/es-observable -var $export = _dereq_(33); -var global = _dereq_(40); -var core = _dereq_(23); -var microtask = _dereq_(68)(); -var OBSERVABLE = _dereq_(128)('observable'); -var aFunction = _dereq_(3); -var anObject = _dereq_(7); -var anInstance = _dereq_(6); -var redefineAll = _dereq_(93); -var hide = _dereq_(42); -var forOf = _dereq_(39); -var RETURN = forOf.RETURN; - -var getMethod = function (fn) { - return fn == null ? undefined : aFunction(fn); -}; - -var cleanupSubscription = function (subscription) { - var cleanup = subscription._c; - if (cleanup) { - subscription._c = undefined; - cleanup(); - } -}; - -var subscriptionClosed = function (subscription) { - return subscription._o === undefined; -}; - -var closeSubscription = function (subscription) { - if (!subscriptionClosed(subscription)) { - subscription._o = undefined; - cleanupSubscription(subscription); - } -}; - -var Subscription = function (observer, subscriber) { - anObject(observer); - this._c = undefined; - this._o = observer; - observer = new SubscriptionObserver(this); - try { - var cleanup = subscriber(observer); - var subscription = cleanup; - if (cleanup != null) { - if (typeof cleanup.unsubscribe === 'function') cleanup = function () { subscription.unsubscribe(); }; - else aFunction(cleanup); - this._c = cleanup; - } - } catch (e) { - observer.error(e); - return; - } if (subscriptionClosed(this)) cleanupSubscription(this); -}; - -Subscription.prototype = redefineAll({}, { - unsubscribe: function unsubscribe() { closeSubscription(this); } -}); - -var SubscriptionObserver = function (subscription) { - this._s = subscription; -}; - -SubscriptionObserver.prototype = redefineAll({}, { - next: function next(value) { - var subscription = this._s; - if (!subscriptionClosed(subscription)) { - var observer = subscription._o; - try { - var m = getMethod(observer.next); - if (m) return m.call(observer, value); - } catch (e) { - try { - closeSubscription(subscription); - } finally { - throw e; - } - } - } - }, - error: function error(value) { - var subscription = this._s; - if (subscriptionClosed(subscription)) throw value; - var observer = subscription._o; - subscription._o = undefined; - try { - var m = getMethod(observer.error); - if (!m) throw value; - value = m.call(observer, value); - } catch (e) { - try { - cleanupSubscription(subscription); - } finally { - throw e; - } - } cleanupSubscription(subscription); - return value; - }, - complete: function complete(value) { - var subscription = this._s; - if (!subscriptionClosed(subscription)) { - var observer = subscription._o; - subscription._o = undefined; - try { - var m = getMethod(observer.complete); - value = m ? m.call(observer, value) : undefined; - } catch (e) { - try { - cleanupSubscription(subscription); - } finally { - throw e; - } - } cleanupSubscription(subscription); - return value; - } - } -}); - -var $Observable = function Observable(subscriber) { - anInstance(this, $Observable, 'Observable', '_f')._f = aFunction(subscriber); -}; - -redefineAll($Observable.prototype, { - subscribe: function subscribe(observer) { - return new Subscription(observer, this._f); - }, - forEach: function forEach(fn) { - var that = this; - return new (core.Promise || global.Promise)(function (resolve, reject) { - aFunction(fn); - var subscription = that.subscribe({ - next: function (value) { - try { - return fn(value); - } catch (e) { - reject(e); - subscription.unsubscribe(); - } - }, - error: reject, - complete: resolve - }); - }); - } -}); - -redefineAll($Observable, { - from: function from(x) { - var C = typeof this === 'function' ? this : $Observable; - var method = getMethod(anObject(x)[OBSERVABLE]); - if (method) { - var observable = anObject(method.call(x)); - return observable.constructor === C ? observable : new C(function (observer) { - return observable.subscribe(observer); - }); - } - return new C(function (observer) { - var done = false; - microtask(function () { - if (!done) { - try { - if (forOf(x, false, function (it) { - observer.next(it); - if (done) return RETURN; - }) === RETURN) return; - } catch (e) { - if (done) throw e; - observer.error(e); - return; - } observer.complete(); - } - }); - return function () { done = true; }; - }); - }, - of: function of() { - for (var i = 0, l = arguments.length, items = Array(l); i < l;) items[i] = arguments[i++]; - return new (typeof this === 'function' ? this : $Observable)(function (observer) { - var done = false; - microtask(function () { - if (!done) { - for (var j = 0; j < items.length; ++j) { - observer.next(items[j]); - if (done) return; - } observer.complete(); - } - }); - return function () { done = true; }; - }); - } -}); - -hide($Observable.prototype, OBSERVABLE, function () { return this; }); - -$export($export.G, { Observable: $Observable }); - -_dereq_(100)('Observable'); - -},{"100":100,"128":128,"23":23,"3":3,"33":33,"39":39,"40":40,"42":42,"6":6,"68":68,"7":7,"93":93}],297:[function(_dereq_,module,exports){ +},{"40":40,"86":86}],272:[function(_dereq_,module,exports){ // https://github.com/tc39/proposal-promise-finally 'use strict'; -var $export = _dereq_(33); -var core = _dereq_(23); -var global = _dereq_(40); -var speciesConstructor = _dereq_(104); +var $export = _dereq_(40); +var core = _dereq_(30); +var global = _dereq_(46); +var speciesConstructor = _dereq_(103); var promiseResolve = _dereq_(91); $export($export.P + $export.R, 'Promise', { 'finally': function (onFinally) { @@ -6265,289 +6100,44 @@ $export($export.P + $export.R, 'Promise', { 'finally': function (onFinally) { ); } }); -},{"104":104,"23":23,"33":33,"40":40,"91":91}],298:[function(_dereq_,module,exports){ -'use strict'; -// https://github.com/tc39/proposal-promise-try -var $export = _dereq_(33); -var newPromiseCapability = _dereq_(69); -var perform = _dereq_(90); - -$export($export.S, 'Promise', { 'try': function (callbackfn) { - var promiseCapability = newPromiseCapability.f(this); - var result = perform(callbackfn); - (result.e ? promiseCapability.reject : promiseCapability.resolve)(result.v); - return promiseCapability.promise; -} }); - -},{"33":33,"69":69,"90":90}],299:[function(_dereq_,module,exports){ -var metadata = _dereq_(67); -var anObject = _dereq_(7); -var toMetaKey = metadata.key; -var ordinaryDefineOwnMetadata = metadata.set; - -metadata.exp({ defineMetadata: function defineMetadata(metadataKey, metadataValue, target, targetKey) { - ordinaryDefineOwnMetadata(metadataKey, metadataValue, anObject(target), toMetaKey(targetKey)); -} }); - -},{"67":67,"7":7}],300:[function(_dereq_,module,exports){ -var metadata = _dereq_(67); -var anObject = _dereq_(7); -var toMetaKey = metadata.key; -var getOrCreateMetadataMap = metadata.map; -var store = metadata.store; - -metadata.exp({ deleteMetadata: function deleteMetadata(metadataKey, target /* , targetKey */) { - var targetKey = arguments.length < 3 ? undefined : toMetaKey(arguments[2]); - var metadataMap = getOrCreateMetadataMap(anObject(target), targetKey, false); - if (metadataMap === undefined || !metadataMap['delete'](metadataKey)) return false; - if (metadataMap.size) return true; - var targetMetadata = store.get(target); - targetMetadata['delete'](targetKey); - return !!targetMetadata.size || store['delete'](target); -} }); - -},{"67":67,"7":7}],301:[function(_dereq_,module,exports){ -var Set = _dereq_(231); -var from = _dereq_(10); -var metadata = _dereq_(67); -var anObject = _dereq_(7); -var getPrototypeOf = _dereq_(79); -var ordinaryOwnMetadataKeys = metadata.keys; -var toMetaKey = metadata.key; - -var ordinaryMetadataKeys = function (O, P) { - var oKeys = ordinaryOwnMetadataKeys(O, P); - var parent = getPrototypeOf(O); - if (parent === null) return oKeys; - var pKeys = ordinaryMetadataKeys(parent, P); - return pKeys.length ? oKeys.length ? from(new Set(oKeys.concat(pKeys))) : pKeys : oKeys; -}; - -metadata.exp({ getMetadataKeys: function getMetadataKeys(target /* , targetKey */) { - return ordinaryMetadataKeys(anObject(target), arguments.length < 2 ? undefined : toMetaKey(arguments[1])); -} }); - -},{"10":10,"231":231,"67":67,"7":7,"79":79}],302:[function(_dereq_,module,exports){ -var metadata = _dereq_(67); -var anObject = _dereq_(7); -var getPrototypeOf = _dereq_(79); -var ordinaryHasOwnMetadata = metadata.has; -var ordinaryGetOwnMetadata = metadata.get; -var toMetaKey = metadata.key; - -var ordinaryGetMetadata = function (MetadataKey, O, P) { - var hasOwn = ordinaryHasOwnMetadata(MetadataKey, O, P); - if (hasOwn) return ordinaryGetOwnMetadata(MetadataKey, O, P); - var parent = getPrototypeOf(O); - return parent !== null ? ordinaryGetMetadata(MetadataKey, parent, P) : undefined; -}; - -metadata.exp({ getMetadata: function getMetadata(metadataKey, target /* , targetKey */) { - return ordinaryGetMetadata(metadataKey, anObject(target), arguments.length < 3 ? undefined : toMetaKey(arguments[2])); -} }); - -},{"67":67,"7":7,"79":79}],303:[function(_dereq_,module,exports){ -var metadata = _dereq_(67); -var anObject = _dereq_(7); -var ordinaryOwnMetadataKeys = metadata.keys; -var toMetaKey = metadata.key; - -metadata.exp({ getOwnMetadataKeys: function getOwnMetadataKeys(target /* , targetKey */) { - return ordinaryOwnMetadataKeys(anObject(target), arguments.length < 2 ? undefined : toMetaKey(arguments[1])); -} }); - -},{"67":67,"7":7}],304:[function(_dereq_,module,exports){ -var metadata = _dereq_(67); -var anObject = _dereq_(7); -var ordinaryGetOwnMetadata = metadata.get; -var toMetaKey = metadata.key; - -metadata.exp({ getOwnMetadata: function getOwnMetadata(metadataKey, target /* , targetKey */) { - return ordinaryGetOwnMetadata(metadataKey, anObject(target) - , arguments.length < 3 ? undefined : toMetaKey(arguments[2])); -} }); - -},{"67":67,"7":7}],305:[function(_dereq_,module,exports){ -var metadata = _dereq_(67); -var anObject = _dereq_(7); -var getPrototypeOf = _dereq_(79); -var ordinaryHasOwnMetadata = metadata.has; -var toMetaKey = metadata.key; - -var ordinaryHasMetadata = function (MetadataKey, O, P) { - var hasOwn = ordinaryHasOwnMetadata(MetadataKey, O, P); - if (hasOwn) return true; - var parent = getPrototypeOf(O); - return parent !== null ? ordinaryHasMetadata(MetadataKey, parent, P) : false; -}; - -metadata.exp({ hasMetadata: function hasMetadata(metadataKey, target /* , targetKey */) { - return ordinaryHasMetadata(metadataKey, anObject(target), arguments.length < 3 ? undefined : toMetaKey(arguments[2])); -} }); - -},{"67":67,"7":7,"79":79}],306:[function(_dereq_,module,exports){ -var metadata = _dereq_(67); -var anObject = _dereq_(7); -var ordinaryHasOwnMetadata = metadata.has; -var toMetaKey = metadata.key; - -metadata.exp({ hasOwnMetadata: function hasOwnMetadata(metadataKey, target /* , targetKey */) { - return ordinaryHasOwnMetadata(metadataKey, anObject(target) - , arguments.length < 3 ? undefined : toMetaKey(arguments[2])); -} }); - -},{"67":67,"7":7}],307:[function(_dereq_,module,exports){ -var $metadata = _dereq_(67); -var anObject = _dereq_(7); -var aFunction = _dereq_(3); -var toMetaKey = $metadata.key; -var ordinaryDefineOwnMetadata = $metadata.set; - -$metadata.exp({ metadata: function metadata(metadataKey, metadataValue) { - return function decorator(target, targetKey) { - ordinaryDefineOwnMetadata( - metadataKey, metadataValue, - (targetKey !== undefined ? anObject : aFunction)(target), - toMetaKey(targetKey) - ); - }; -} }); - -},{"3":3,"67":67,"7":7}],308:[function(_dereq_,module,exports){ -// https://tc39.github.io/proposal-setmap-offrom/#sec-set.from -_dereq_(97)('Set'); - -},{"97":97}],309:[function(_dereq_,module,exports){ -// https://tc39.github.io/proposal-setmap-offrom/#sec-set.of -_dereq_(98)('Set'); - -},{"98":98}],310:[function(_dereq_,module,exports){ -// https://github.com/DavidBruant/Map-Set.prototype.toJSON -var $export = _dereq_(33); - -$export($export.P + $export.R, 'Set', { toJSON: _dereq_(20)('Set') }); - -},{"20":20,"33":33}],311:[function(_dereq_,module,exports){ -'use strict'; -// https://github.com/mathiasbynens/String.prototype.at -var $export = _dereq_(33); -var $at = _dereq_(106)(true); - -$export($export.P, 'String', { - at: function at(pos) { - return $at(this, pos); - } -}); - -},{"106":106,"33":33}],312:[function(_dereq_,module,exports){ -'use strict'; -// https://tc39.github.io/String.prototype.matchAll/ -var $export = _dereq_(33); -var defined = _dereq_(28); -var toLength = _dereq_(118); -var isRegExp = _dereq_(52); -var getFlags = _dereq_(37); -var RegExpProto = RegExp.prototype; - -var $RegExpStringIterator = function (regexp, string) { - this._r = regexp; - this._s = string; -}; - -_dereq_(54)($RegExpStringIterator, 'RegExp String', function next() { - var match = this._r.exec(this._s); - return { value: match, done: match === null }; -}); - -$export($export.P, 'String', { - matchAll: function matchAll(regexp) { - defined(this); - if (!isRegExp(regexp)) throw TypeError(regexp + ' is not a regexp!'); - var S = String(this); - var flags = 'flags' in RegExpProto ? String(regexp.flags) : getFlags.call(regexp); - var rx = new RegExp(regexp.source, ~flags.indexOf('g') ? flags : 'g' + flags); - rx.lastIndex = toLength(regexp.lastIndex); - return new $RegExpStringIterator(rx, S); - } -}); - -},{"118":118,"28":28,"33":33,"37":37,"52":52,"54":54}],313:[function(_dereq_,module,exports){ +},{"103":103,"30":30,"40":40,"46":46,"91":91}],273:[function(_dereq_,module,exports){ 'use strict'; // https://github.com/tc39/proposal-string-pad-start-end -var $export = _dereq_(33); -var $pad = _dereq_(109); +var $export = _dereq_(40); +var $pad = _dereq_(108); +var userAgent = _dereq_(124); -$export($export.P, 'String', { +// https://github.com/zloirock/core-js/issues/280 +$export($export.P + $export.F * /Version\/10\.\d+(\.\d+)? Safari\//.test(userAgent), 'String', { padEnd: function padEnd(maxLength /* , fillString = ' ' */) { return $pad(this, maxLength, arguments.length > 1 ? arguments[1] : undefined, false); } }); -},{"109":109,"33":33}],314:[function(_dereq_,module,exports){ +},{"108":108,"124":124,"40":40}],274:[function(_dereq_,module,exports){ 'use strict'; // https://github.com/tc39/proposal-string-pad-start-end -var $export = _dereq_(33); -var $pad = _dereq_(109); +var $export = _dereq_(40); +var $pad = _dereq_(108); +var userAgent = _dereq_(124); -$export($export.P, 'String', { +// https://github.com/zloirock/core-js/issues/280 +$export($export.P + $export.F * /Version\/10\.\d+(\.\d+)? Safari\//.test(userAgent), 'String', { padStart: function padStart(maxLength /* , fillString = ' ' */) { return $pad(this, maxLength, arguments.length > 1 ? arguments[1] : undefined, true); } }); -},{"109":109,"33":33}],315:[function(_dereq_,module,exports){ -'use strict'; -// https://github.com/sebmarkbage/ecmascript-string-left-right-trim -_dereq_(111)('trimLeft', function ($trim) { - return function trimLeft() { - return $trim(this, 1); - }; -}, 'trimStart'); - -},{"111":111}],316:[function(_dereq_,module,exports){ -'use strict'; -// https://github.com/sebmarkbage/ecmascript-string-left-right-trim -_dereq_(111)('trimRight', function ($trim) { - return function trimRight() { - return $trim(this, 2); - }; -}, 'trimEnd'); - -},{"111":111}],317:[function(_dereq_,module,exports){ +},{"108":108,"124":124,"40":40}],275:[function(_dereq_,module,exports){ _dereq_(126)('asyncIterator'); -},{"126":126}],318:[function(_dereq_,module,exports){ -_dereq_(126)('observable'); - -},{"126":126}],319:[function(_dereq_,module,exports){ -// https://github.com/tc39/proposal-global -var $export = _dereq_(33); - -$export($export.S, 'System', { global: _dereq_(40) }); - -},{"33":33,"40":40}],320:[function(_dereq_,module,exports){ -// https://tc39.github.io/proposal-setmap-offrom/#sec-weakmap.from -_dereq_(97)('WeakMap'); - -},{"97":97}],321:[function(_dereq_,module,exports){ -// https://tc39.github.io/proposal-setmap-offrom/#sec-weakmap.of -_dereq_(98)('WeakMap'); - -},{"98":98}],322:[function(_dereq_,module,exports){ -// https://tc39.github.io/proposal-setmap-offrom/#sec-weakset.from -_dereq_(97)('WeakSet'); - -},{"97":97}],323:[function(_dereq_,module,exports){ -// https://tc39.github.io/proposal-setmap-offrom/#sec-weakset.of -_dereq_(98)('WeakSet'); - -},{"98":98}],324:[function(_dereq_,module,exports){ -var $iterators = _dereq_(141); -var getKeys = _dereq_(81); +},{"126":126}],276:[function(_dereq_,module,exports){ +var $iterators = _dereq_(140); +var getKeys = _dereq_(83); var redefine = _dereq_(94); -var global = _dereq_(40); -var hide = _dereq_(42); -var Iterators = _dereq_(58); +var global = _dereq_(46); +var hide = _dereq_(48); +var Iterators = _dereq_(64); var wks = _dereq_(128); var ITERATOR = wks('iterator'); var TO_STRING_TAG = wks('toStringTag'); @@ -6601,246 +6191,48 @@ for (var collections = getKeys(DOMIterables), i = 0; i < collections.length; i++ } } -},{"128":128,"141":141,"40":40,"42":42,"58":58,"81":81,"94":94}],325:[function(_dereq_,module,exports){ -var $export = _dereq_(33); -var $task = _dereq_(113); +},{"128":128,"140":140,"46":46,"48":48,"64":64,"83":83,"94":94}],277:[function(_dereq_,module,exports){ +var $export = _dereq_(40); +var $task = _dereq_(112); $export($export.G + $export.B, { setImmediate: $task.set, clearImmediate: $task.clear }); -},{"113":113,"33":33}],326:[function(_dereq_,module,exports){ +},{"112":112,"40":40}],278:[function(_dereq_,module,exports){ // ie9- setTimeout & setInterval additional parameters fix -var global = _dereq_(40); -var $export = _dereq_(33); -var invoke = _dereq_(46); -var partial = _dereq_(88); -var navigator = global.navigator; -var MSIE = !!navigator && /MSIE .\./.test(navigator.userAgent); // <- dirty ie9- check +var global = _dereq_(46); +var $export = _dereq_(40); +var userAgent = _dereq_(124); +var slice = [].slice; +var MSIE = /MSIE .\./.test(userAgent); // <- dirty ie9- check var wrap = function (set) { - return MSIE ? function (fn, time /* , ...args */) { - return set(invoke( - partial, - [].slice.call(arguments, 2), + return function (fn, time /* , ...args */) { + var boundArgs = arguments.length > 2; + var args = boundArgs ? slice.call(arguments, 2) : false; + return set(boundArgs ? function () { // eslint-disable-next-line no-new-func - typeof fn == 'function' ? fn : Function(fn) - ), time); - } : set; + (typeof fn == 'function' ? fn : Function(fn)).apply(this, args); + } : fn, time); + }; }; $export($export.G + $export.B + $export.F * MSIE, { setTimeout: wrap(global.setTimeout), setInterval: wrap(global.setInterval) }); -},{"33":33,"40":40,"46":46,"88":88}],327:[function(_dereq_,module,exports){ -_dereq_(254); -_dereq_(191); -_dereq_(193); -_dereq_(192); -_dereq_(195); -_dereq_(197); -_dereq_(202); -_dereq_(196); -_dereq_(194); -_dereq_(204); -_dereq_(203); -_dereq_(199); -_dereq_(200); -_dereq_(198); -_dereq_(190); -_dereq_(201); -_dereq_(205); -_dereq_(206); -_dereq_(157); -_dereq_(159); -_dereq_(158); -_dereq_(208); -_dereq_(207); -_dereq_(178); -_dereq_(188); -_dereq_(189); -_dereq_(179); -_dereq_(180); -_dereq_(181); -_dereq_(182); -_dereq_(183); -_dereq_(184); -_dereq_(185); -_dereq_(186); -_dereq_(187); -_dereq_(161); -_dereq_(162); -_dereq_(163); -_dereq_(164); -_dereq_(165); -_dereq_(166); -_dereq_(167); -_dereq_(168); -_dereq_(169); -_dereq_(170); -_dereq_(171); -_dereq_(172); -_dereq_(173); -_dereq_(174); -_dereq_(175); -_dereq_(176); -_dereq_(177); -_dereq_(241); -_dereq_(246); -_dereq_(253); -_dereq_(244); -_dereq_(236); -_dereq_(237); -_dereq_(242); -_dereq_(247); -_dereq_(249); -_dereq_(232); -_dereq_(233); -_dereq_(234); -_dereq_(235); -_dereq_(238); -_dereq_(239); -_dereq_(240); -_dereq_(243); -_dereq_(245); -_dereq_(248); -_dereq_(250); -_dereq_(251); -_dereq_(252); -_dereq_(152); -_dereq_(154); -_dereq_(153); -_dereq_(156); -_dereq_(155); -_dereq_(140); -_dereq_(138); -_dereq_(145); -_dereq_(142); -_dereq_(148); -_dereq_(150); -_dereq_(137); -_dereq_(144); -_dereq_(134); -_dereq_(149); -_dereq_(132); -_dereq_(147); -_dereq_(146); -_dereq_(139); -_dereq_(143); -_dereq_(131); -_dereq_(133); -_dereq_(136); -_dereq_(135); -_dereq_(151); -_dereq_(141); -_dereq_(224); -_dereq_(230); -_dereq_(225); -_dereq_(226); -_dereq_(227); -_dereq_(228); -_dereq_(229); -_dereq_(209); -_dereq_(160); -_dereq_(231); -_dereq_(266); -_dereq_(267); -_dereq_(255); -_dereq_(256); -_dereq_(261); -_dereq_(264); -_dereq_(265); -_dereq_(259); -_dereq_(262); -_dereq_(260); -_dereq_(263); -_dereq_(257); -_dereq_(258); -_dereq_(210); -_dereq_(211); -_dereq_(212); -_dereq_(213); -_dereq_(214); -_dereq_(217); -_dereq_(215); -_dereq_(216); -_dereq_(218); -_dereq_(219); -_dereq_(220); -_dereq_(221); -_dereq_(223); -_dereq_(222); -_dereq_(270); -_dereq_(268); -_dereq_(269); -_dereq_(311); -_dereq_(314); -_dereq_(313); -_dereq_(315); -_dereq_(316); -_dereq_(312); -_dereq_(317); -_dereq_(318); -_dereq_(292); -_dereq_(295); -_dereq_(291); -_dereq_(289); -_dereq_(290); -_dereq_(293); -_dereq_(294); -_dereq_(276); -_dereq_(310); -_dereq_(275); -_dereq_(309); -_dereq_(321); -_dereq_(323); -_dereq_(274); -_dereq_(308); -_dereq_(320); -_dereq_(322); -_dereq_(273); -_dereq_(319); -_dereq_(272); -_dereq_(277); +},{"124":124,"40":40,"46":46}],279:[function(_dereq_,module,exports){ _dereq_(278); -_dereq_(279); -_dereq_(280); -_dereq_(281); -_dereq_(283); -_dereq_(282); -_dereq_(284); -_dereq_(285); -_dereq_(286); -_dereq_(288); -_dereq_(287); -_dereq_(297); -_dereq_(298); -_dereq_(299); -_dereq_(300); -_dereq_(302); -_dereq_(301); -_dereq_(304); -_dereq_(303); -_dereq_(305); -_dereq_(306); -_dereq_(307); -_dereq_(271); -_dereq_(296); -_dereq_(326); -_dereq_(325); -_dereq_(324); -module.exports = _dereq_(23); +_dereq_(277); +_dereq_(276); +module.exports = _dereq_(30); -},{"131":131,"132":132,"133":133,"134":134,"135":135,"136":136,"137":137,"138":138,"139":139,"140":140,"141":141,"142":142,"143":143,"144":144,"145":145,"146":146,"147":147,"148":148,"149":149,"150":150,"151":151,"152":152,"153":153,"154":154,"155":155,"156":156,"157":157,"158":158,"159":159,"160":160,"161":161,"162":162,"163":163,"164":164,"165":165,"166":166,"167":167,"168":168,"169":169,"170":170,"171":171,"172":172,"173":173,"174":174,"175":175,"176":176,"177":177,"178":178,"179":179,"180":180,"181":181,"182":182,"183":183,"184":184,"185":185,"186":186,"187":187,"188":188,"189":189,"190":190,"191":191,"192":192,"193":193,"194":194,"195":195,"196":196,"197":197,"198":198,"199":199,"200":200,"201":201,"202":202,"203":203,"204":204,"205":205,"206":206,"207":207,"208":208,"209":209,"210":210,"211":211,"212":212,"213":213,"214":214,"215":215,"216":216,"217":217,"218":218,"219":219,"220":220,"221":221,"222":222,"223":223,"224":224,"225":225,"226":226,"227":227,"228":228,"229":229,"23":23,"230":230,"231":231,"232":232,"233":233,"234":234,"235":235,"236":236,"237":237,"238":238,"239":239,"240":240,"241":241,"242":242,"243":243,"244":244,"245":245,"246":246,"247":247,"248":248,"249":249,"250":250,"251":251,"252":252,"253":253,"254":254,"255":255,"256":256,"257":257,"258":258,"259":259,"260":260,"261":261,"262":262,"263":263,"264":264,"265":265,"266":266,"267":267,"268":268,"269":269,"270":270,"271":271,"272":272,"273":273,"274":274,"275":275,"276":276,"277":277,"278":278,"279":279,"280":280,"281":281,"282":282,"283":283,"284":284,"285":285,"286":286,"287":287,"288":288,"289":289,"290":290,"291":291,"292":292,"293":293,"294":294,"295":295,"296":296,"297":297,"298":298,"299":299,"300":300,"301":301,"302":302,"303":303,"304":304,"305":305,"306":306,"307":307,"308":308,"309":309,"310":310,"311":311,"312":312,"313":313,"314":314,"315":315,"316":316,"317":317,"318":318,"319":319,"320":320,"321":321,"322":322,"323":323,"324":324,"325":325,"326":326}],328:[function(_dereq_,module,exports){ -(function (global){ +},{"276":276,"277":277,"278":278,"30":30}],280:[function(_dereq_,module,exports){ /** - * Copyright (c) 2014, Facebook, Inc. - * All rights reserved. + * Copyright (c) 2014-present, Facebook, Inc. * - * This source code is licensed under the BSD-style license found in the - * https://raw.github.com/facebook/regenerator/master/LICENSE file. An - * additional grant of patent rights can be found in the PATENTS file in - * the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ !(function(global) { @@ -7006,29 +6398,17 @@ module.exports = _dereq_(23); return Promise.resolve(value).then(function(unwrapped) { // When a yielded Promise is resolved, its final value becomes // the .value of the Promise<{value,done}> result for the - // current iteration. If the Promise is rejected, however, the - // result for this iteration will be rejected with the same - // reason. Note that rejections of yielded Promises are not - // thrown back into the generator function, as is the case - // when an awaited Promise is rejected. This difference in - // behavior between yield and await is important, because it - // allows the consumer to decide what to do with the yielded - // rejection (swallow it and continue, manually .throw it back - // into the generator, abandon iteration, whatever). With - // await, by contrast, there is no opportunity to examine the - // rejection reason outside the generator function, so the - // only option is to throw it from the await expression, and - // let the generator function handle the exception. + // current iteration. result.value = unwrapped; resolve(result); - }, reject); + }, function(error) { + // If a rejected Promise was yielded, throw the rejection back + // into the async generator function so it can be handled there. + return invoke("throw", error, resolve, reject); + }); } } - if (typeof global.process === "object" && global.process.domain) { - invoke = global.process.domain.bind(invoke); - } - var previousPromise; function enqueue(method, arg) { @@ -7562,13 +6942,12 @@ module.exports = _dereq_(23); } }; })( - // Among the various tricks for obtaining a reference to the global - // object, this seems to be the most reliable technique that does not - // use indirect eval (which violates Content Security Policy). - typeof global === "object" ? global : - typeof window === "object" ? window : - typeof self === "object" ? self : this + // In sloppy mode, unbound `this` refers to the global object, fallback to + // Function constructor if we're in global strict mode. That is sadly a form + // of indirect eval which violates Content Security Policy. + (function() { + return this || (typeof self === "object" && self); + })() || Function("return this")() ); -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{}]},{},[1]); diff --git a/editor/external/@babel/polyfill/polyfill.min.js b/editor/external/@babel/polyfill/polyfill.min.js new file mode 100644 index 00000000..4e69797e --- /dev/null +++ b/editor/external/@babel/polyfill/polyfill.min.js @@ -0,0 +1,4 @@ +!function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var c="function"==typeof require&&require;if(!u&&c)return c(o,!0);if(i)return i(o,!0);var a=new Error("Cannot find module '"+o+"'");throw a.code="MODULE_NOT_FOUND",a}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(n){var r=t[o][1][n];return s(r||n)},f,f.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o2?arguments[2]:void 0,s=Math.min((void 0===f?u:i(f,u))-a,u-c),l=1;for(a0;)a in r?r[c]=r[a]:delete r[c],c+=l,a+=l;return r}},{113:113,117:117,118:118}],18:[function(t,n,r){"use strict";var e=t(118),i=t(113),o=t(117);n.exports=function fill(t){for(var n=e(this),r=o(n.length),u=arguments.length,c=i(u>1?arguments[1]:void 0,r),a=u>2?arguments[2]:void 0,f=void 0===a?r:i(a,r);f>c;)n[c++]=t;return n}},{113:113,117:117,118:118}],19:[function(t,n,r){var e=t(116),i=t(117),o=t(113);n.exports=function(t){return function(n,r,u){var c,a=e(n),f=i(a.length),s=o(u,f);if(t&&r!=r){for(;f>s;)if((c=a[s++])!=c)return!0}else for(;f>s;s++)if((t||s in a)&&a[s]===r)return t||s||0;return!t&&-1}}},{113:113,116:116,117:117}],20:[function(t,n,r){var e=t(32),i=t(53),o=t(118),u=t(117),c=t(23);n.exports=function(t,n){var r=1==t,a=2==t,f=3==t,s=4==t,l=6==t,h=5==t||l,p=n||c;return function(n,c,v){for(var d,y,g=o(n),x=i(g),m=e(c,v,3),b=u(x.length),S=0,w=r?p(n,b):a?p(n,0):void 0;b>S;S++)if((h||S in x)&&(d=x[S],y=m(d,S,g),t))if(r)w[S]=y;else if(y)switch(t){case 3:return!0;case 5:return d;case 6:return S;case 2:w.push(d)}else if(s)return!1;return l?-1:f||s?s:w}}},{117:117,118:118,23:23,32:32,53:53}],21:[function(t,n,r){var e=t(11),i=t(118),o=t(53),u=t(117);n.exports=function(t,n,r,c,a){e(n);var f=i(t),s=o(f),l=u(f.length),h=a?l-1:0,p=a?-1:1;if(r<2)for(;;){if(h in s){c=s[h],h+=p;break}if(h+=p,a?h<0:l<=h)throw TypeError("Reduce of empty array with no initial value")}for(;a?h>=0:l>h;h+=p)h in s&&(c=n(c,s[h],h,f));return c}},{11:11,117:117,118:118,53:53}],22:[function(t,n,r){var e=t(57),i=t(55),o=t(128)("species");n.exports=function(t){var n;return i(t)&&(n=t.constructor,"function"!=typeof n||n!==Array&&!i(n.prototype)||(n=void 0),e(n)&&null===(n=n[o])&&(n=void 0)),void 0===n?Array:n}},{128:128,55:55,57:57}],23:[function(t,n,r){var e=t(22);n.exports=function(t,n){return new(e(t))(n)}},{22:22}],24:[function(t,n,r){"use strict";var e=t(11),i=t(57),o=t(52),u=[].slice,c={},a=function(t,n,r){if(!(n in c)){for(var e=[],i=0;i1?arguments[1]:void 0,3);r=r?r.n:this._f;)for(e(r.v,r.k,this);r&&r.r;)r=r.p},has:function has(t){return!!y(v(this,n),t)}}),h&&e(s.prototype,"size",{get:function(){return v(this,n)[d]}}),s},def:function(t,n,r){var e,i,o=y(t,n);return o?o.v=r:(t._l=o={i:i=p(n,!0),k:n,v:r,p:e=t._l,n:void 0,r:!1},t._f||(t._f=o),e&&(e.n=o),t[d]++,"F"!==i&&(t._i[i]=o)),t},getEntry:y,setStrong:function(t,n,r){f(t,n,function(t,r){this._t=v(t,n),this._k=r,this._l=void 0},function(){for(var t=this,n=t._k,r=t._l;r&&r.r;)r=r.p;return t._t&&(t._l=r=r?r.n:t._t._f)?"keys"==n?s(0,r.k):"values"==n?s(0,r.v):s(0,[r.k,r.v]):(t._t=void 0,s(1))},r?"entries":"values",!r,!0),l(n)}}},{125:125,15:15,32:32,36:36,45:45,61:61,63:63,70:70,74:74,75:75,93:93,99:99}],28:[function(t,n,r){"use strict";var e=t(93),i=t(70).getWeak,o=t(16),u=t(57),c=t(15),a=t(45),f=t(20),s=t(47),l=t(125),h=f(5),p=f(6),v=0,d=function(t){return t._l||(t._l=new y)},y=function(){this.a=[]},g=function(t,n){return h(t.a,function(t){return t[0]===n})};y.prototype={get:function(t){var n=g(this,t);if(n)return n[1]},has:function(t){return!!g(this,t)},set:function(t,n){var r=g(this,t);r?r[1]=n:this.a.push([t,n])},delete:function(t){var n=p(this.a,function(n){return n[0]===t});return~n&&this.a.splice(n,1),!!~n}},n.exports={getConstructor:function(t,n,r,o){var f=t(function(t,e){c(t,f,n,"_i"),t._t=n,t._i=v++,t._l=void 0,void 0!=e&&a(e,r,t[o],t)});return e(f.prototype,{delete:function(t){if(!u(t))return!1;var r=i(t);return!0===r?d(l(this,n)).delete(t):r&&s(r,this._i)&&delete r[this._i]},has:function has(t){if(!u(t))return!1;var r=i(t);return!0===r?d(l(this,n)).has(t):r&&s(r,this._i)}}),f},def:function(t,n,r){var e=i(o(n),!0);return!0===e?d(t).set(n,r):e[t._i]=r,t},ufstore:d}},{125:125,15:15,16:16,20:20,45:45,47:47,57:57,70:70,93:93}],29:[function(t,n,r){"use strict";var e=t(46),i=t(40),o=t(94),u=t(93),c=t(70),a=t(45),f=t(15),s=t(57),l=t(42),h=t(62),p=t(100),v=t(51);n.exports=function(t,n,r,d,y,g){var x=e[t],m=x,b=y?"set":"add",S=m&&m.prototype,w={},_=function(t){var n=S[t];o(S,t,"delete"==t?function(t){return!(g&&!s(t))&&n.call(this,0===t?0:t)}:"has"==t?function has(t){return!(g&&!s(t))&&n.call(this,0===t?0:t)}:"get"==t?function get(t){return g&&!s(t)?void 0:n.call(this,0===t?0:t)}:"add"==t?function add(t){return n.call(this,0===t?0:t),this}:function set(t,r){return n.call(this,0===t?0:t,r),this})};if("function"==typeof m&&(g||S.forEach&&!l(function(){(new m).entries().next()}))){var E=new m,F=E[b](g?{}:-0,1)!=E,I=l(function(){E.has(1)}),O=h(function(t){new m(t)}),P=!g&&l(function(){for(var t=new m,n=5;n--;)t[b](n,n);return!t.has(-0)});O||(m=n(function(n,r){f(n,m,t);var e=v(new x,n,m);return void 0!=r&&a(r,y,e[b],e),e}),m.prototype=S,S.constructor=m),(I||P)&&(_("delete"),_("has"),y&&_("get")),(P||F)&&_(b),g&&S.clear&&delete S.clear}else m=d.getConstructor(n,t,y,b),u(m.prototype,r),c.NEED=!0;return p(m,t),w[t]=m,i(i.G+i.W+i.F*(m!=x),w),g||d.setStrong(m,t,y),m}},{100:100,15:15,40:40,42:42,45:45,46:46,51:51,57:57,62:62,70:70,93:93,94:94}],30:[function(t,n,r){var e=n.exports={version:"2.6.1"};"number"==typeof __e&&(__e=e)},{}],31:[function(t,n,r){"use strict";var e=t(75),i=t(92);n.exports=function(t,n,r){n in t?e.f(t,n,i(0,r)):t[n]=r}},{75:75,92:92}],32:[function(t,n,r){var e=t(11);n.exports=function(t,n,r){if(e(t),void 0===n)return t;switch(r){case 1:return function(r){return t.call(n,r)};case 2:return function(r,e){return t.call(n,r,e)};case 3:return function(r,e,i){return t.call(n,r,e,i)}}return function(){return t.apply(n,arguments)}}},{11:11}],33:[function(t,n,r){"use strict";var e=t(42),i=Date.prototype.getTime,o=Date.prototype.toISOString,u=function(t){return t>9?t:"0"+t};n.exports=e(function(){return"0385-07-25T07:06:39.999Z"!=o.call(new Date(-5e13-1))})||!e(function(){o.call(new Date(NaN))})?function toISOString(){if(!isFinite(i.call(this)))throw RangeError("Invalid time value");var t=this,n=t.getUTCFullYear(),r=t.getUTCMilliseconds(),e=n<0?"-":n>9999?"+":"";return e+("00000"+Math.abs(n)).slice(e?-6:-4)+"-"+u(t.getUTCMonth()+1)+"-"+u(t.getUTCDate())+"T"+u(t.getUTCHours())+":"+u(t.getUTCMinutes())+":"+u(t.getUTCSeconds())+"."+(r>99?r:"0"+u(r))+"Z"}:o},{42:42}],34:[function(t,n,r){"use strict";var e=t(16),i=t(119);n.exports=function(t){if("string"!==t&&"number"!==t&&"default"!==t)throw TypeError("Incorrect hint");return i(e(this),"number"!=t)}},{119:119,16:16}],35:[function(t,n,r){n.exports=function(t){if(void 0==t)throw TypeError("Can't call method on "+t);return t}},{}],36:[function(t,n,r){n.exports=!t(42)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},{42:42}],37:[function(t,n,r){var e=t(57),i=t(46).document,o=e(i)&&e(i.createElement);n.exports=function(t){return o?i.createElement(t):{}}},{46:46,57:57}],38:[function(t,n,r){n.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},{}],39:[function(t,n,r){var e=t(83),i=t(80),o=t(84);n.exports=function(t){var n=e(t),r=i.f;if(r)for(var u,c=r(t),a=o.f,f=0;c.length>f;)a.call(t,u=c[f++])&&n.push(u);return n}},{80:80,83:83,84:84}],40:[function(t,n,r){var e=t(46),i=t(30),o=t(48),u=t(94),c=t(32),a=function(t,n,r){var f,s,l,h,p=t&a.F,v=t&a.G,d=t&a.S,y=t&a.P,g=t&a.B,x=v?e:d?e[n]||(e[n]={}):(e[n]||{}).prototype,m=v?i:i[n]||(i[n]={}),b=m.prototype||(m.prototype={});v&&(r=n);for(f in r)s=!p&&x&&void 0!==x[f],l=(s?x:r)[f],h=g&&s?c(l,e):y&&"function"==typeof l?c(Function.call,l):l,x&&u(x,f,l,t&a.U),m[f]!=l&&o(m,f,h),y&&b[f]!=l&&(b[f]=l)};e.core=i,a.F=1,a.G=2,a.S=4,a.P=8,a.B=16,a.W=32,a.U=64,a.R=128,n.exports=a},{30:30,32:32,46:46,48:48,94:94}],41:[function(t,n,r){var e=t(128)("match");n.exports=function(t){var n=/./;try{"/./"[t](n)}catch(r){try{return n[e]=!1,!"/./"[t](n)}catch(t){}}return!0}},{128:128}],42:[function(t,n,r){n.exports=function(t){try{return!!t()}catch(t){return!0}}},{}],43:[function(t,n,r){"use strict";t(224);var e=t(94),i=t(48),o=t(42),u=t(35),c=t(128),a=t(96),f=c("species"),s=!o(function(){var t=/./;return t.exec=function(){var t=[];return t.groups={a:"7"},t},"7"!=="".replace(t,"$")}),l=function(){var t=/(?:)/,n=t.exec;t.exec=function(){return n.apply(this,arguments)};var r="ab".split(t);return 2===r.length&&"a"===r[0]&&"b"===r[1]}();n.exports=function(t,n,r){var h=c(t),p=!o(function(){var n={};return n[h]=function(){return 7},7!=""[t](n)}),v=p?!o(function(){var n=!1,r=/a/;return r.exec=function(){return n=!0,null},"split"===t&&(r.constructor={},r.constructor[f]=function(){return r}),r[h](""),!n}):void 0;if(!p||!v||"replace"===t&&!s||"split"===t&&!l){var d=/./[h],y=r(u,h,""[t],function maybeCallNative(t,n,r,e,i){return n.exec===a?p&&!i?{done:!0,value:d.call(n,r,e)}:{done:!0,value:t.call(r,n,e)}:{done:!1}}),g=y[0],x=y[1];e(String.prototype,t,g),i(RegExp.prototype,h,2==n?function(t,n){return x.call(t,this,n)}:function(t){return x.call(t,this)})}}},{128:128,224:224,35:35,42:42,48:48,94:94,96:96}],44:[function(t,n,r){"use strict";var e=t(16);n.exports=function(){var t=e(this),n="";return t.global&&(n+="g"),t.ignoreCase&&(n+="i"),t.multiline&&(n+="m"),t.unicode&&(n+="u"),t.sticky&&(n+="y"),n}},{16:16}],45:[function(t,n,r){var e=t(32),i=t(59),o=t(54),u=t(16),c=t(117),a=t(129),f={},s={},r=n.exports=function(t,n,r,l,h){var p,v,d,y,g=h?function(){return t}:a(t),x=e(r,l,n?2:1),m=0;if("function"!=typeof g)throw TypeError(t+" is not iterable!");if(o(g)){for(p=c(t.length);p>m;m++)if((y=n?x(u(v=t[m])[0],v[1]):x(t[m]))===f||y===s)return y}else for(d=g.call(t);!(v=d.next()).done;)if((y=i(d,x,v.value,n))===f||y===s)return y};r.BREAK=f,r.RETURN=s},{117:117,129:129,16:16,32:32,54:54,59:59}],46:[function(t,n,r){var e=n.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=e)},{}],47:[function(t,n,r){var e={}.hasOwnProperty;n.exports=function(t,n){return e.call(t,n)}},{}],48:[function(t,n,r){var e=t(75),i=t(92);n.exports=t(36)?function(t,n,r){return e.f(t,n,i(1,r))}:function(t,n,r){return t[n]=r,t}},{36:36,75:75,92:92}],49:[function(t,n,r){var e=t(46).document;n.exports=e&&e.documentElement},{46:46}],50:[function(t,n,r){n.exports=!t(36)&&!t(42)(function(){return 7!=Object.defineProperty(t(37)("div"),"a",{get:function(){return 7}}).a})},{36:36,37:37,42:42}],51:[function(t,n,r){var e=t(57),i=t(98).set;n.exports=function(t,n,r){var o,u=n.constructor;return u!==r&&"function"==typeof u&&(o=u.prototype)!==r.prototype&&e(o)&&i&&i(t,o),t}},{57:57,98:98}],52:[function(t,n,r){n.exports=function(t,n,r){var e=void 0===r;switch(n.length){case 0:return e?t():t.call(r);case 1:return e?t(n[0]):t.call(r,n[0]);case 2:return e?t(n[0],n[1]):t.call(r,n[0],n[1]);case 3:return e?t(n[0],n[1],n[2]):t.call(r,n[0],n[1],n[2]);case 4:return e?t(n[0],n[1],n[2],n[3]):t.call(r,n[0],n[1],n[2],n[3])}return t.apply(r,n)}},{}],53:[function(t,n,r){var e=t(26);n.exports=Object("z").propertyIsEnumerable(0)?Object:function(t){return"String"==e(t)?t.split(""):Object(t)}},{26:26}],54:[function(t,n,r){var e=t(64),i=t(128)("iterator"),o=Array.prototype;n.exports=function(t){return void 0!==t&&(e.Array===t||o[i]===t)}},{128:128,64:64}],55:[function(t,n,r){var e=t(26);n.exports=Array.isArray||function isArray(t){return"Array"==e(t)}},{26:26}],56:[function(t,n,r){var e=t(57),i=Math.floor;n.exports=function isInteger(t){return!e(t)&&isFinite(t)&&i(t)===t}},{57:57}],57:[function(t,n,r){n.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},{}],58:[function(t,n,r){var e=t(57),i=t(26),o=t(128)("match");n.exports=function(t){var n;return e(t)&&(void 0!==(n=t[o])?!!n:"RegExp"==i(t))}},{128:128,26:26,57:57}],59:[function(t,n,r){var e=t(16);n.exports=function(t,n,r,i){try{return i?n(e(r)[0],r[1]):n(r)}catch(n){var o=t.return;throw void 0!==o&&e(o.call(t)),n}}},{16:16}],60:[function(t,n,r){"use strict";var e=t(74),i=t(92),o=t(100),u={};t(48)(u,t(128)("iterator"),function(){return this}),n.exports=function(t,n,r){t.prototype=e(u,{next:i(1,r)}),o(t,n+" Iterator")}},{100:100,128:128,48:48,74:74,92:92}],61:[function(t,n,r){"use strict";var e=t(65),i=t(40),o=t(94),u=t(48),c=t(64),a=t(60),f=t(100),s=t(81),l=t(128)("iterator"),h=!([].keys&&"next"in[].keys()),p=function(){return this};n.exports=function(t,n,r,v,d,y,g){a(r,n,v);var x,m,b,S=function(t){if(!h&&t in F)return F[t];switch(t){case"keys":return function keys(){return new r(this,t)};case"values":return function values(){return new r(this,t)}}return function entries(){return new r(this,t)}},w=n+" Iterator",_="values"==d,E=!1,F=t.prototype,I=F[l]||F["@@iterator"]||d&&F[d],O=I||S(d),P=d?_?S("entries"):O:void 0,A="Array"==n?F.entries||I:I;if(A&&(b=s(A.call(new t)))!==Object.prototype&&b.next&&(f(b,w,!0),e||"function"==typeof b[l]||u(b,l,p)),_&&I&&"values"!==I.name&&(E=!0,O=function values(){return I.call(this)}),e&&!g||!h&&!E&&F[l]||u(F,l,O),c[n]=O,c[w]=p,d)if(x={values:_?O:S("values"),keys:y?O:S("keys"),entries:P},g)for(m in x)m in F||o(F,m,x[m]);else i(i.P+i.F*(h||E),n,x);return x}},{100:100,128:128,40:40,48:48,60:60,64:64,65:65,81:81,94:94}],62:[function(t,n,r){var e=t(128)("iterator"),i=!1;try{var o=[7][e]();o.return=function(){i=!0},Array.from(o,function(){throw 2})}catch(t){}n.exports=function(t,n){if(!n&&!i)return!1;var r=!1;try{var o=[7],u=o[e]();u.next=function(){return{done:r=!0}},o[e]=function(){return u},t(o)}catch(t){}return r}},{128:128}],63:[function(t,n,r){n.exports=function(t,n){return{value:n,done:!!t}}},{}],64:[function(t,n,r){n.exports={}},{}],65:[function(t,n,r){n.exports=!1},{}],66:[function(t,n,r){var e=Math.expm1;n.exports=!e||e(10)>22025.465794806718||e(10)<22025.465794806718||-2e-17!=e(-2e-17)?function expm1(t){return 0==(t=+t)?t:t>-1e-6&&t<1e-6?t+t*t/2:Math.exp(t)-1}:e},{}],67:[function(t,n,r){var e=t(69),i=Math.pow,o=i(2,-52),u=i(2,-23),c=i(2,127)*(2-u),a=i(2,-126),f=function(t){return t+1/o-1/o};n.exports=Math.fround||function fround(t){var n,r,i=Math.abs(t),s=e(t);return ic||r!=r?s*(1/0):s*r)}},{69:69}],68:[function(t,n,r){n.exports=Math.log1p||function log1p(t){return(t=+t)>-1e-8&&t<1e-8?t-t*t/2:Math.log(1+t)}},{}],69:[function(t,n,r){n.exports=Math.sign||function sign(t){return 0==(t=+t)||t!=t?t:t<0?-1:1}},{}],70:[function(t,n,r){var e=t(123)("meta"),i=t(57),o=t(47),u=t(75).f,c=0,a=Object.isExtensible||function(){return!0},f=!t(42)(function(){return a(Object.preventExtensions({}))}),s=function(t){u(t,e,{value:{i:"O"+ ++c,w:{}}})},l=function(t,n){if(!i(t))return"symbol"==typeof t?t:("string"==typeof t?"S":"P")+t;if(!o(t,e)){if(!a(t))return"F";if(!n)return"E";s(t)}return t[e].i},h=function(t,n){if(!o(t,e)){if(!a(t))return!0;if(!n)return!1;s(t)}return t[e].w},p=function(t){return f&&v.NEED&&a(t)&&!o(t,e)&&s(t),t},v=n.exports={KEY:e,NEED:!1,fastKey:l,getWeak:h,onFreeze:p}},{123:123,42:42,47:47,57:57,75:75}],71:[function(t,n,r){var e=t(46),i=t(112).set,o=e.MutationObserver||e.WebKitMutationObserver,u=e.process,c=e.Promise,a="process"==t(26)(u);n.exports=function(){var t,n,r,f=function(){var e,i;for(a&&(e=u.domain)&&e.exit();t;){i=t.fn,t=t.next;try{i()}catch(e){throw t?r():n=void 0,e}}n=void 0,e&&e.enter()};if(a)r=function(){u.nextTick(f)};else if(!o||e.navigator&&e.navigator.standalone)if(c&&c.resolve){var s=c.resolve(void 0);r=function(){s.then(f)}}else r=function(){i.call(e,f)};else{var l=!0,h=document.createTextNode("");new o(f).observe(h,{characterData:!0}),r=function(){h.data=l=!l}}return function(e){var i={fn:e,next:void 0};n&&(n.next=i),t||(t=i,r()),n=i}}},{112:112,26:26,46:46}],72:[function(t,n,r){"use strict";function PromiseCapability(t){var n,r;this.promise=new t(function(t,e){if(void 0!==n||void 0!==r)throw TypeError("Bad Promise constructor");n=t,r=e}),this.resolve=e(n),this.reject=e(r)}var e=t(11);n.exports.f=function(t){return new PromiseCapability(t)}},{11:11}],73:[function(t,n,r){"use strict";var e=t(83),i=t(80),o=t(84),u=t(118),c=t(53),a=Object.assign;n.exports=!a||t(42)(function(){var t={},n={},r=Symbol(),e="abcdefghijklmnopqrst";return t[r]=7,e.split("").forEach(function(t){n[t]=t}),7!=a({},t)[r]||Object.keys(a({},n)).join("")!=e})?function assign(t,n){for(var r=u(t),a=arguments.length,f=1,s=i.f,l=o.f;a>f;)for(var h,p=c(arguments[f++]),v=s?e(p).concat(s(p)):e(p),d=v.length,y=0;d>y;)l.call(p,h=v[y++])&&(r[h]=p[h]);return r}:a},{118:118,42:42,53:53,80:80,83:83,84:84}],74:[function(t,n,r){var e=t(16),i=t(76),o=t(38),u=t(101)("IE_PROTO"),c=function(){},a=function(){var n,r=t(37)("iframe"),e=o.length;for(r.style.display="none",t(49).appendChild(r),r.src="javascript:",n=r.contentWindow.document,n.open(),n.write(" + @@ -25,7 +26,7 @@ - + diff --git a/editor/svg-editor.html b/editor/svg-editor.html index c6149346..4bfc9031 100644 --- a/editor/svg-editor.html +++ b/editor/svg-editor.html @@ -16,6 +16,7 @@ + @@ -26,7 +27,7 @@ - + diff --git a/editor/svg-editor.js b/editor/svg-editor.js index 1095829b..5829e86b 100644 --- a/editor/svg-editor.js +++ b/editor/svg-editor.js @@ -13,14 +13,16 @@ import {importSetGlobalDefault} from './external/dynamic-import-polyfill/importM import SvgCanvas from './svgcanvas.js'; import Layer from './layer.js'; -import jqPluginJSHotkeys from './js-hotkeys/jquery.hotkeys.min.js'; -import jqPluginBBQ from './jquerybbq/jquery.bbq.min.js'; -import jqPluginSVGIcons from './svgicons/jQuery.svgIcons.js'; -import jqPluginJGraduate from './jgraduate/jQuery.jGraduate.js'; -import jqPluginSpinBtn from './spinbtn/jQuery.SpinButton.js'; -import jqPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr` -import jqPluginContextMenu from './contextmenu/jQuery.contextMenu.js'; -import jqPluginJPicker from './jgraduate/jQuery.jPicker.js'; +import jQueryPluginJSHotkeys from './js-hotkeys/jquery.hotkeys.min.js'; +import jQueryPluginBBQ from './jquerybbq/jquery.bbq.min.js'; +import jQueryPluginSVGIcons from './svgicons/jQuery.svgIcons.js'; +import jQueryPluginJGraduate from './jgraduate/jQuery.jGraduate.js'; +import jQueryPluginSpinButton from './spinbtn/jQuery.SpinButton.js'; +import jQueryPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr` +import jQueryPluginContextMenu from './contextmenu/jQuery.contextMenu.js'; +import jQueryPluginJPicker from './jgraduate/jQuery.jPicker.js'; +import jQueryPluginDBox from './dbox.js'; + import { readLang, putLocale, setStrings, @@ -46,9 +48,9 @@ import loadStylesheets from './external/load-stylesheets/index-es.js'; const editor = {}; const $ = [ - jqPluginJSHotkeys, jqPluginBBQ, jqPluginSVGIcons, jqPluginJGraduate, - jqPluginSpinBtn, jqPluginSVG, jqPluginContextMenu, jqPluginJPicker -].reduce(($, cb) => cb($), jQuery); + jQueryPluginJSHotkeys, jQueryPluginBBQ, jQueryPluginSVGIcons, jQueryPluginJGraduate, + jQueryPluginSpinButton, jQueryPluginSVG, jQueryPluginContextMenu, jQueryPluginJPicker +].reduce((jq, func) => func(jq), jQuery); /* if (!$.loadingStylesheets) { @@ -87,9 +89,10 @@ editor.langChanged = false; */ editor.showSaveWarning = false; /** -* @type {boolean} + * Will be set to a boolean by `ext-storage.js` + * @type {"ignore"|"waiting"|"closed"} */ -editor.storagePromptClosed = false; // For use with ext-storage.js +editor.storagePromptState = 'ignore'; const callbacks = [], /** @@ -180,7 +183,7 @@ const callbacks = [], * @property {boolean} [emptyStorageOnDecline=false] Used by `ext-storage.js`; empty any prior storage if the user declines to store * @property {string[]} [extensions=module:SVGEditor~defaultExtensions] Extensions to load on startup. Use an array in `setConfig` and comma separated file names in the URL. Extension names must begin with "ext-". Note that as of version 2.7, paths containing "/", "\", or ":", are disallowed for security reasons. Although previous versions of this list would entirely override the default list, as of version 2.7, the defaults will always be added to this explicit list unless the configuration `noDefaultExtensions` is included. * @property {module:SVGEditor.Stylesheet[]} [stylesheets=["@default"]] An array of required stylesheets to load in parallel; include the value `"@default"` within this array to ensure all default stylesheets are loaded. - * @property {string[]} [allowedOrigins=[]] Used by `ext-xdomain-messaging.js` to indicate which origins are permitted for cross-domain messaging (e.g., between the embedded editor and main editor code). Besides explicit domains, one might add '' to allow all domains (not recommended for privacy/data integrity of your user's content!), `window.location.origin` for allowing the same origin (should be safe if you trust all apps on your domain), 'null' to allow `file://` URL usage + * @property {string[]} [allowedOrigins=[]] Used by `ext-xdomain-messaging.js` to indicate which origins are permitted for cross-domain messaging (e.g., between the embedded editor and main editor code). Besides explicit domains, one might add '*' to allow all domains (not recommended for privacy/data integrity of your user's content!), `window.location.origin` for allowing the same origin (should be safe if you trust all apps on your domain), 'null' to allow `file:///` URL usage * @property {null|PlainObject} [colorPickerCSS=null] Object of CSS properties mapped to values (for jQuery) to apply to the color picker. See {@link http://api.jquery.com/css/#css-properties}. A `null` value (the default) will cause the CSS to default to `left` with a position equal to that of the `fill_color` or `stroke_color` element minus 140, and a `bottom` equal to 40 * @property {string} [paramurl] This was available via URL only. Allowed an un-encoded URL within the query string (use "url" or "source" with a data: URI instead) * @property {Float} [canvas_expansion=3] The minimum area visible outside the canvas, as a multiple of the image dimensions. The larger the number, the more one can scroll outside the canvas. @@ -242,13 +245,13 @@ const callbacks = [], no_save_warning: false, // PATH CONFIGURATION // The following path configuration items are disallowed in the URL (as should any future path configurations) + langPath: 'locale/', // Default will be changed if this is a non-modular load + extPath: 'extensions/', // Default will be changed if this is a non-modular load + canvgPath: 'canvg/', // Default will be changed if this is a non-modular load + jspdfPath: 'jspdf/', // Default will be changed if this is a non-modular load imgPath: 'images/', - langPath: 'locale/', // Default will be changed if this is a modular load - extPath: 'extensions/', // Default will be changed if this is a modular load - canvgPath: 'canvg/', // Default will be changed if this is a modular load - jspdfPath: 'jspdf/', // Default will be changed if this is a modular load - extIconsPath: 'extensions/', jGraduatePath: 'jgraduate/images/', + extIconsPath: 'extensions/', // DOCUMENT PROPERTIES // Change the following to a preference (already in the Document Properties dialog)? dimensions: [640, 480], @@ -293,56 +296,74 @@ let svgCanvas, urldata, extensions: [], stylesheets: [], /** - * Can use window.location.origin to indicate the current + * Can use `location.origin` to indicate the current * origin. Can contain a '*' to allow all domains or 'null' (as - * a string) to support all file:// URLs. Cannot be set by + * a string) to support all `file:///` URLs. Cannot be set by * URL for security reasons (not safe, at least for * privacy or data integrity of SVG content). * Might have been fairly safe to allow - * `new URL(window.location.href).origin` by default but + * `new URL(location.href).origin` by default but * avoiding it ensures some more security that even third * party apps on the same domain also cannot communicate * with this app by default. - * For use with ext-xdomain-messaging.js + * For use with `ext-xdomain-messaging.js` * @todo We might instead make as a user-facing preference. */ allowedOrigins: [] }; -function loadSvgString (str, callback) { +/** + * + * @param {string} str SVG string + * @param {PlainObject} [opts={}] + * @param {boolean} [opts.noAlert] + * @throws {Error} Upon failure to load SVG + * @returns {Promise} Resolves to undefined upon success (or if `noAlert` is + * falsey, though only until after the `alert` is closed); rejects if SVG + * loading fails and `noAlert` is truthy. + */ +async function loadSvgString (str, {noAlert} = {}) { const success = svgCanvas.setSvgString(str) !== false; - callback = callback || $.noop; if (success) { - callback(true); // eslint-disable-line standard/no-callback-literal - } else { - $.alert(uiStrings.notification.errorLoadingSVG, function () { - callback(false); // eslint-disable-line standard/no-callback-literal - }); + return; } + + if (!noAlert) { + await $.alert(uiStrings.notification.errorLoadingSVG); + return; + } + throw new Error('Error loading SVG'); } /** * @function module:SVGEditor~getImportLocale - * @param {string} defaultLang - * @param {string} defaultName + * @param {PlainObject} defaults + * @param {string} defaults.defaultLang + * @param {string} defaults.defaultName * @returns {module:SVGEditor~ImportLocale} */ function getImportLocale ({defaultLang, defaultName}) { /** * @function module:SVGEditor~ImportLocale - * @param {string} [name] Defaults to `defaultName` of {@link module:SVGEditor~getImportLocale} - * @param {string} [lang=defaultLang] Defaults to `defaultLang` of {@link module:SVGEditor~getImportLocale} + * @param {PlainObject} localeInfo + * @param {string} [localeInfo.name] Defaults to `defaultName` 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} */ - return async function importLocale ({name = defaultName, lang = defaultLang} = {}) { - async function importLocale (lang) { - const url = `${curConfig.extPath}ext-locale/${name}/${lang}.js`; + return async function importLocaleDefaulting ({name = defaultName, lang = defaultLang} = {}) { + /** + * + * @param {string} language + * @returns {Promise} Resolves to {@link module:locale.LocaleStrings} + */ + function importLocale (language) { + const url = `${curConfig.extPath}ext-locale/${name}/${language}.js`; return importSetGlobalDefault(url, { - global: `svgEditorExtensionLocale_${name}_${lang}` + global: `svgEditorExtensionLocale_${name}_${language.replace(/-/g, '_')}` }); } try { - return importLocale(lang); + return await importLocale(lang); } catch (err) { return importLocale('en'); } @@ -354,10 +375,10 @@ 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} [val] The value. If the value supplied is missing or falsey, no change to the preference will be made. -* @returns {string} If val is missing or falsey, the value of the previously stored preference will be returned. +* @returns {string|undefined} If val is missing or falsey, the value of the previously stored preference will be returned. * @todo Can we change setting on the jQuery namespace (onto editor) to avoid conflicts? * @todo Review whether any remaining existing direct references to * getting `curPrefs` can be changed to use `$.pref()` getting to ensure @@ -374,7 +395,7 @@ $.pref = function (key, val) { * @implements {module:SVGEditor.Prefs} */ editor.curPrefs = curPrefs; // Update exported value - return; + return undefined; } return (key in curPrefs) ? curPrefs[key] : defaultPrefs[key]; }; @@ -404,7 +425,7 @@ editor.setStrings = setStrings; editor.loadContentAndPrefs = function () { if (!curConfig.forceStorage && (curConfig.noStorageOnLoad || - !document.cookie.match(/(?:^|;\s*)store=(?:prefsAndContent|prefsOnly)/) + !document.cookie.match(/(?:^|;\s*)svgeditstore=(?:prefsAndContent|prefsOnly)/) ) ) { return; @@ -414,7 +435,7 @@ editor.loadContentAndPrefs = function () { if (editor.storage && // Cookies do not have enough available memory to hold large documents (curConfig.forceStorage || (!curConfig.noStorageOnLoad && - document.cookie.match(/(?:^|;\s*)store=prefsAndContent/)) + document.cookie.match(/(?:^|;\s*)svgeditstore=prefsAndContent/)) ) ) { const name = 'svgedit-' + curConfig.canvasName; @@ -425,22 +446,20 @@ editor.loadContentAndPrefs = function () { } // LOAD PREFS - for (const key in defaultPrefs) { - if (defaultPrefs.hasOwnProperty(key)) { // It's our own config, so we don't need to iterate up the prototype chain - const storeKey = 'svg-edit-' + key; - if (editor.storage) { - const val = editor.storage.getItem(storeKey); - if (val) { - defaultPrefs[key] = String(val); // Convert to string for FF (.value fails in Webkit) - } - } else if (window.widget) { - defaultPrefs[key] = window.widget.preferenceForKey(storeKey); - } else { - const result = document.cookie.match(new RegExp('(?:^|;\\s*)' + Utils.regexEscape(encodeURIComponent(storeKey)) + '=([^;]+)')); - defaultPrefs[key] = result ? decodeURIComponent(result[1]) : ''; + Object.keys(defaultPrefs).forEach((key) => { + const storeKey = 'svg-edit-' + key; + if (editor.storage) { + const val = editor.storage.getItem(storeKey); + if (val) { + defaultPrefs[key] = String(val); // Convert to string for FF (.value fails in Webkit) } + } else if (window.widget) { + defaultPrefs[key] = window.widget.preferenceForKey(storeKey); + } else { + const result = document.cookie.match(new RegExp('(?:^|;\\s*)' + Utils.regexEscape(encodeURIComponent(storeKey)) + '=([^;]+)')); + defaultPrefs[key] = result ? decodeURIComponent(result[1]) : ''; } - } + }); }; /** @@ -465,6 +484,13 @@ editor.loadContentAndPrefs = function () { */ editor.setConfig = function (opts, cfgCfg) { cfgCfg = cfgCfg || {}; + /** + * + * @param {module:SVGEditor.Config|module:SVGEditor.Prefs} cfgObj + * @param {string} key + * @param {Any} val See {@link module:SVGEditor.Config} or {@link module:SVGEditor.Prefs} + * @returns {undefined} + */ function extendOrAdd (cfgObj, key, val) { if (cfgObj[key] && typeof cfgObj[key] === 'object') { $.extend(true, cfgObj[key], val); @@ -473,12 +499,12 @@ editor.setConfig = function (opts, cfgCfg) { } } $.each(opts, function (key, val) { - if (opts.hasOwnProperty(key)) { + if ({}.hasOwnProperty.call(opts, key)) { // Only allow prefs defined in defaultPrefs - if (defaultPrefs.hasOwnProperty(key)) { + if ({}.hasOwnProperty.call(defaultPrefs, key)) { if (cfgCfg.overwrite === false && ( curConfig.preventAllURLConfig || - curPrefs.hasOwnProperty(key) + {}.hasOwnProperty.call(curPrefs, key) )) { return; } @@ -499,30 +525,26 @@ editor.setConfig = function (opts, cfgCfg) { } curConfig[key] = curConfig[key].concat(val); // We will handle any dupes later // Only allow other curConfig if defined in defaultConfig - } else if (defaultConfig.hasOwnProperty(key)) { + } else if ({}.hasOwnProperty.call(defaultConfig, key)) { if (cfgCfg.overwrite === false && ( curConfig.preventAllURLConfig || - curConfig.hasOwnProperty(key) + {}.hasOwnProperty.call(curConfig, key) )) { return; } // Potentially overwriting of previously set config - if (curConfig.hasOwnProperty(key)) { + if ({}.hasOwnProperty.call(curConfig, key)) { if (cfgCfg.overwrite === false) { return; } extendOrAdd(curConfig, key, val); + } else if (cfgCfg.allowInitialUserOverride === true) { + extendOrAdd(defaultConfig, key, val); + } else if (defaultConfig[key] && typeof defaultConfig[key] === 'object') { + curConfig[key] = Array.isArray(defaultConfig[key]) ? [] : {}; + $.extend(true, curConfig[key], val); // Merge properties recursively, e.g., on initFill, initStroke objects } else { - if (cfgCfg.allowInitialUserOverride === true) { - extendOrAdd(defaultConfig, key, val); - } else { - if (defaultConfig[key] && typeof defaultConfig[key] === 'object') { - curConfig[key] = {}; - $.extend(true, curConfig[key], val); // Merge properties recursively, e.g., on initFill, initStroke objects - } else { - curConfig[key] = val; - } - } + curConfig[key] = val; } } } @@ -618,7 +640,7 @@ editor.randomizeIds = function (arg) { }; /** -* Auto-run after a Promise microtask +* Auto-run after a Promise microtask. * @returns {undefined} */ editor.init = function () { @@ -658,11 +680,20 @@ editor.init = function () { goodLangs.push(this.value); }); + /** + * Sets up current preferences based on defaults. + * @returns {undefined} + */ function setupCurPrefs () { curPrefs = $.extend(true, {}, defaultPrefs, curPrefs); // Now safe to merge with priority for curPrefs in the event any are already set // Export updated prefs editor.curPrefs = curPrefs; } + + /** + * Sets up current config based on defaults. + * @returns {undefined} + */ function setupCurConfig () { curConfig = $.extend(true, {}, defaultConfig, curConfig); // Now safe to merge with priority for curConfig in the event any are already set @@ -702,8 +733,8 @@ editor.init = function () { // ones given potential to interact in undesirable // ways with other script resources [ - 'extPath', 'imgPath', 'extIconsPath', 'canvgPath', - 'langPath', 'jGraduatePath', 'jspdfPath' + 'langPath', 'extPath', 'canvgPath', 'jspdfPath', + 'imgPath', 'jGraduatePath', 'extIconsPath' ].forEach(function (pathConfig) { if (urldata[pathConfig]) { delete urldata[pathConfig]; @@ -746,7 +777,7 @@ editor.init = function () { })(); /** - * Called internally + * Called internally. * @param {string|Element|external:jQuery} elem * @param {string|external:jQuery} iconId * @param {Float} forcedSize Not in use @@ -755,7 +786,8 @@ editor.init = function () { const setIcon = editor.setIcon = function (elem, iconId, forcedSize) { const icon = (typeof iconId === 'string') ? $.getSvgIcon(iconId, true) : iconId.clone(); if (!icon) { - console.log('NOTE: Icon image missing: ' + iconId); + // Todo: Investigate why this still occurs in some cases + console.log('NOTE: Icon image missing: ' + iconId); // eslint-disable-line no-console return; } $(elem).empty().append(icon); @@ -771,14 +803,19 @@ editor.init = function () { const extAndLocaleFunc = async function () { // const lang = ('lang' in curPrefs) ? curPrefs.lang : null; const {langParam, langData} = await editor.putLocale(null, goodLangs, curConfig); - setLang(langParam, langData); + await setLang(langParam, langData); + + const {ok, cancel} = uiStrings.common; + jQueryPluginDBox($, {ok, cancel}); + + setIcons(); // Wait for dbox as needed for i18n try { await Promise.all( curConfig.extensions.map(async (extname) => { const extName = extname.match(/^ext-(.+)\.js/); if (!extName) { // Ensure URL cannot specify some other unintended file in the extPath - return; + return undefined; } const url = curConfig.extPath + extname; // Todo: Replace this with `return import(url);` when @@ -798,14 +835,17 @@ editor.init = function () { }); const {name = extName[1], init} = imported; 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) { - console.log(err); - console.error('Extension failed to load: ' + extname + '; ' + err); + // Todo: Add config to alert any errors + console.log(err); // eslint-disable-line no-console + console.error('Extension failed to load: ' + extname + '; ' + err); // eslint-disable-line no-console + return undefined; } }) ); - svgCanvas.bind('extensions_added', + svgCanvas.bind( + 'extensions_added', /** * @param {external:Window} win * @param {module:svgcanvas.SvgCanvas#event:extensions_added} data @@ -819,6 +859,11 @@ editor.init = function () { $('.flyout_arrow_horiz:empty').each(function () { $(this).append($.getSvgIcon('arrow_right', true).width(5).height(5)); }); + + if (editor.storagePromptState === 'ignore') { + updateCanvas(true); + } + messageQueue.forEach( /** * @param {module:svgcanvas.SvgCanvas#event:message} messageObj @@ -833,12 +878,17 @@ editor.init = function () { ); svgCanvas.call('extensions_added'); } catch (err) { - console.log(err); + // Todo: Report errors through the UI + console.log(err); // eslint-disable-line no-console } }; const stateObj = {tool_scale: editor.tool_scale}; + /** + * + * @returns {undefined} + */ const setFlyoutPositions = function () { $('.tools_flyout').each(function () { const shower = $('#' + this.id + '_show'); @@ -848,6 +898,9 @@ editor.init = function () { }); }; + /** + * @type {string} + */ const uaPrefix = (function () { const regex = /^(Moz|Webkit|Khtml|O|ms|Icab)(?=[A-Z])/; const someScript = document.getElementsByTagName('script')[0]; @@ -865,6 +918,11 @@ editor.init = function () { return ''; }()); + /** + * @param {external:jQuery} elems + * @param {Float} scale + * @returns {undefined} + */ const scaleElements = function (elems, scale) { // const prefix = '-' + uaPrefix.toLowerCase() + '-'; // Currently unused const sides = ['top', 'left', 'bottom', 'right']; @@ -880,8 +938,8 @@ editor.init = function () { for (let i = 0; i < 4; i++) { const s = sides[i]; let cur = el.data('orig_margin-' + s); - if (cur == null) { - cur = parseInt(el.css('margin-' + s), 10); + if (Utils.isNullish(cur)) { + cur = parseInt(el.css('margin-' + s)); // Cache the original margin el.data('orig_margin-' + s, cur); } @@ -1107,270 +1165,282 @@ editor.init = function () { setFlyoutPositions(); }; - $.svgIcons(curConfig.imgPath + 'svg_edit_icons.svg', { - w: 24, h: 24, - id_match: false, - no_img: !isWebkit(), // Opera & Firefox 4 gives odd behavior w/images - fallback_path: curConfig.imgPath, - fallback: { - logo: 'logo.png', - select: 'select.png', - select_node: 'select_node.png', + /** + * Setup SVG icons + */ + function setIcons () { + $.svgIcons(curConfig.imgPath + 'svg_edit_icons.svg', { + w: 24, h: 24, + id_match: false, + no_img: !isWebkit(), // Opera & Firefox 4 gives odd behavior w/images + fallback_path: curConfig.imgPath, + fallback: { + logo: 'logo.png', - square: 'square.png', - rect: 'rect.png', - fh_rect: 'freehand-square.png', - circle: 'circle.png', - ellipse: 'ellipse.png', - fh_ellipse: 'freehand-circle.png', - pencil: 'fhpath.png', - pen: 'line.png', - text: 'text.png', - path: 'path.png', - add_subpath: 'add_subpath.png', - close_path: 'closepath.png', - open_path: 'openpath.png', + select: 'select.png', + select_node: 'select_node.png', - image: 'image.png', - zoom: 'zoom.png', + square: 'square.png', + rect: 'rect.png', + fh_rect: 'freehand-square.png', + circle: 'circle.png', + ellipse: 'ellipse.png', + fh_ellipse: 'freehand-circle.png', + pencil: 'fhpath.png', + pen: 'line.png', + text: 'text.png', + path: 'path.png', + add_subpath: 'add_subpath.png', + close_path: 'closepath.png', + open_path: 'openpath.png', - arrow_right: 'flyouth.png', - arrow_right_big: 'arrow_right_big.png', - arrow_down: 'dropdown.gif', - fill: 'fill.png', - stroke: 'stroke.png', - opacity: 'opacity.png', + image: 'image.png', + zoom: 'zoom.png', - new_image: 'clear.png', - save: 'save.png', - export: 'export.png', - open: 'open.png', - import: 'import.png', - docprops: 'document-properties.png', - source: 'source.png', - wireframe: 'wireframe.png', + arrow_right: 'flyouth.png', + arrow_right_big: 'arrow_right_big.png', + arrow_down: 'dropdown.gif', + fill: 'fill.png', + stroke: 'stroke.png', + opacity: 'opacity.png', - undo: 'undo.png', - redo: 'redo.png', + new_image: 'clear.png', + save: 'save.png', + export: 'export.png', + open: 'open.png', + import: 'import.png', + docprops: 'document-properties.png', + source: 'source.png', + wireframe: 'wireframe.png', - clone: 'clone.png', - delete: 'delete.png', - go_up: 'go-up.png', - go_down: 'go-down.png', - context_menu: 'context_menu.png', - move_bottom: 'move_bottom.png', - move_top: 'move_top.png', - to_path: 'to_path.png', - link_controls: 'link_controls.png', - reorient: 'reorient.png', - group_elements: 'shape_group_elements.png', + undo: 'undo.png', + redo: 'redo.png', - ungroup: 'shape_ungroup.png', - unlink_use: 'unlink_use.png', - width: 'width.png', - height: 'height.png', - c_radius: 'c_radius.png', - angle: 'angle.png', - blur: 'blur.png', - fontsize: 'fontsize.png', - align: 'align.png', + clone: 'clone.png', + delete: 'delete.png', + go_up: 'go-up.png', + go_down: 'go-down.png', + context_menu: 'context_menu.png', + move_bottom: 'move_bottom.png', + move_top: 'move_top.png', + to_path: 'to_path.png', + link_controls: 'link_controls.png', + reorient: 'reorient.png', + group_elements: 'shape_group_elements.png', - align_left: 'align-left.png', - align_center: 'align-center.png', - align_right: 'align-right.png', - align_top: 'align-top.png', - align_middle: 'align-middle.png', - align_bottom: 'align-bottom.png', + ungroup: 'shape_ungroup.png', + unlink_use: 'unlink_use.png', + width: 'width.png', + height: 'height.png', + c_radius: 'c_radius.png', + angle: 'angle.png', + blur: 'blur.png', + fontsize: 'fontsize.png', + align: 'align.png', - linecap_butt: 'linecap_butt.png', - linecap_square: 'linecap_square.png', - linecap_round: 'linecap_round.png', - linejoin_miter: 'linejoin_miter.png', - linejoin_bevel: 'linejoin_bevel.png', - linejoin_round: 'linejoin_round.png', - eye: 'eye.png', - no_color: 'no_color.png', + align_left: 'align-left.png', + align_center: 'align-center.png', + align_right: 'align-right.png', + align_top: 'align-top.png', + align_middle: 'align-middle.png', + align_bottom: 'align-bottom.png', - ok: 'save.png', - cancel: 'cancel.png', - warning: 'warning.png', + linecap_butt: 'linecap_butt.png', + linecap_square: 'linecap_square.png', + linecap_round: 'linecap_round.png', + linejoin_miter: 'linejoin_miter.png', + linejoin_bevel: 'linejoin_bevel.png', + linejoin_round: 'linejoin_round.png', + eye: 'eye.png', + no_color: 'no_color.png', - node_delete: 'node_delete.png', - node_clone: 'node_clone.png', + ok: 'save.png', + cancel: 'cancel.png', + warning: 'warning.png', - globe_link: 'globe_link.png' - }, - placement: { - '#logo': 'logo', + node_delete: 'node_delete.png', + node_clone: 'node_clone.png', - '#tool_clear div,#layer_new': 'new_image', - '#tool_save div': 'save', - '#tool_export div': 'export', - '#tool_open div div': 'open', - '#tool_import div div': 'import', - '#tool_source': 'source', - '#tool_docprops > div': 'docprops', - '#tool_wireframe': 'wireframe', + globe_link: 'globe_link.png' + }, + placement: { + '#logo': 'logo', - '#tool_undo': 'undo', - '#tool_redo': 'redo', + '#tool_clear div,#layer_new': 'new_image', + '#tool_save div': 'save', + '#tool_export div': 'export', + '#tool_open div div': 'open', + '#tool_import div div': 'import', + '#tool_source': 'source', + '#tool_docprops > div': 'docprops', + '#tool_wireframe': 'wireframe', - '#tool_select': 'select', - '#tool_fhpath': 'pencil', - '#tool_line': 'pen', - '#tool_rect,#tools_rect_show': 'rect', - '#tool_square': 'square', - '#tool_fhrect': 'fh_rect', - '#tool_ellipse,#tools_ellipse_show': 'ellipse', - '#tool_circle': 'circle', - '#tool_fhellipse': 'fh_ellipse', - '#tool_path': 'path', - '#tool_text,#layer_rename': 'text', - '#tool_image': 'image', - '#tool_zoom': 'zoom', + '#tool_undo': 'undo', + '#tool_redo': 'redo', - '#tool_clone,#tool_clone_multi': 'clone', - '#tool_node_clone': 'node_clone', - '#layer_delete,#tool_delete,#tool_delete_multi': 'delete', - '#tool_node_delete': 'node_delete', - '#tool_add_subpath': 'add_subpath', - '#tool_openclose_path': 'open_path', - '#tool_move_top': 'move_top', - '#tool_move_bottom': 'move_bottom', - '#tool_topath': 'to_path', - '#tool_node_link': 'link_controls', - '#tool_reorient': 'reorient', - '#tool_group_elements': 'group_elements', - '#tool_ungroup': 'ungroup', - '#tool_unlink_use': 'unlink_use', + '#tool_select': 'select', + '#tool_fhpath': 'pencil', + '#tool_line': 'pen', + '#tool_rect,#tools_rect_show': 'rect', + '#tool_square': 'square', + '#tool_fhrect': 'fh_rect', + '#tool_ellipse,#tools_ellipse_show': 'ellipse', + '#tool_circle': 'circle', + '#tool_fhellipse': 'fh_ellipse', + '#tool_path': 'path', + '#tool_text,#layer_rename': 'text', + '#tool_image': 'image', + '#tool_zoom': 'zoom', - '#tool_alignleft, #tool_posleft': 'align_left', - '#tool_aligncenter, #tool_poscenter': 'align_center', - '#tool_alignright, #tool_posright': 'align_right', - '#tool_aligntop, #tool_postop': 'align_top', - '#tool_alignmiddle, #tool_posmiddle': 'align_middle', - '#tool_alignbottom, #tool_posbottom': 'align_bottom', - '#cur_position': 'align', + '#tool_clone,#tool_clone_multi': 'clone', + '#tool_node_clone': 'node_clone', + '#layer_delete,#tool_delete,#tool_delete_multi': 'delete', + '#tool_node_delete': 'node_delete', + '#tool_add_subpath': 'add_subpath', + '#tool_openclose_path': 'open_path', + '#tool_move_top': 'move_top', + '#tool_move_bottom': 'move_bottom', + '#tool_topath': 'to_path', + '#tool_node_link': 'link_controls', + '#tool_reorient': 'reorient', + '#tool_group_elements': 'group_elements', + '#tool_ungroup': 'ungroup', + '#tool_unlink_use': 'unlink_use', - '#linecap_butt,#cur_linecap': 'linecap_butt', - '#linecap_round': 'linecap_round', - '#linecap_square': 'linecap_square', + '#tool_alignleft, #tool_posleft': 'align_left', + '#tool_aligncenter, #tool_poscenter': 'align_center', + '#tool_alignright, #tool_posright': 'align_right', + '#tool_aligntop, #tool_postop': 'align_top', + '#tool_alignmiddle, #tool_posmiddle': 'align_middle', + '#tool_alignbottom, #tool_posbottom': 'align_bottom', + '#cur_position': 'align', - '#linejoin_miter,#cur_linejoin': 'linejoin_miter', - '#linejoin_round': 'linejoin_round', - '#linejoin_bevel': 'linejoin_bevel', + '#linecap_butt,#cur_linecap': 'linecap_butt', + '#linecap_round': 'linecap_round', + '#linecap_square': 'linecap_square', - '#url_notice': 'warning', + '#linejoin_miter,#cur_linejoin': 'linejoin_miter', + '#linejoin_round': 'linejoin_round', + '#linejoin_bevel': 'linejoin_bevel', - '#layer_up': 'go_up', - '#layer_down': 'go_down', - '#layer_moreopts': 'context_menu', - '#layerlist td.layervis': 'eye', + '#url_notice': 'warning', - '#tool_source_save,#tool_docprops_save,#tool_prefs_save': 'ok', - '#tool_source_cancel,#tool_docprops_cancel,#tool_prefs_cancel': 'cancel', + '#layer_up': 'go_up', + '#layer_down': 'go_down', + '#layer_moreopts': 'context_menu', + '#layerlist td.layervis': 'eye', - '#rwidthLabel, #iwidthLabel': 'width', - '#rheightLabel, #iheightLabel': 'height', - '#cornerRadiusLabel span': 'c_radius', - '#angleLabel': 'angle', - '#linkLabel,#tool_make_link,#tool_make_link_multi': 'globe_link', - '#zoomLabel': 'zoom', - '#tool_fill label': 'fill', - '#tool_stroke .icon_label': 'stroke', - '#group_opacityLabel': 'opacity', - '#blurLabel': 'blur', - '#font_sizeLabel': 'fontsize', + '#tool_source_save,#tool_docprops_save,#tool_prefs_save': 'ok', + '#tool_source_cancel,#tool_docprops_cancel,#tool_prefs_cancel': 'cancel', - '.flyout_arrow_horiz': 'arrow_right', - '.dropdown button, #main_button .dropdown': 'arrow_down', - '#palette .palette_item:first, #fill_bg, #stroke_bg': 'no_color' - }, - resize: { - '#logo .svg_icon': 28, - '.flyout_arrow_horiz .svg_icon': 5, - '.layer_button .svg_icon, #layerlist td.layervis .svg_icon': 14, - '.dropdown button .svg_icon': 7, - '#main_button .dropdown .svg_icon': 9, - '.palette_item:first .svg_icon': 15, - '#fill_bg .svg_icon, #stroke_bg .svg_icon': 16, - '.toolbar_button button .svg_icon': 16, - '.stroke_tool div div .svg_icon': 20, - '#tools_bottom label .svg_icon': 18 - }, - callback (icons) { - $('.toolbar_button button > svg, .toolbar_button button > img').each(function () { - $(this).parent().prepend(this); - }); + '#rwidthLabel, #iwidthLabel': 'width', + '#rheightLabel, #iheightLabel': 'height', + '#cornerRadiusLabel span': 'c_radius', + '#angleLabel': 'angle', + '#linkLabel,#tool_make_link,#tool_make_link_multi': 'globe_link', + '#zoomLabel': 'zoom', + '#tool_fill label': 'fill', + '#tool_stroke .icon_label': 'stroke', + '#group_opacityLabel': 'opacity', + '#blurLabel': 'blur', + '#font_sizeLabel': 'fontsize', - const tleft = $('#tools_left'); + '.flyout_arrow_horiz': 'arrow_right', + '.dropdown button, #main_button .dropdown': 'arrow_down', + '#palette .palette_item:first, #fill_bg, #stroke_bg': 'no_color' + }, + resize: { + '#logo .svg_icon': 28, + '.flyout_arrow_horiz .svg_icon': 5, + '.layer_button .svg_icon, #layerlist td.layervis .svg_icon': 14, + '.dropdown button .svg_icon': 7, + '#main_button .dropdown .svg_icon': 9, + '.palette_item:first .svg_icon': 15, + '#fill_bg .svg_icon, #stroke_bg .svg_icon': 16, + '.toolbar_button button .svg_icon': 16, + '.stroke_tool div div .svg_icon': 20, + '#tools_bottom label .svg_icon': 18 + }, + async callback (icons) { + $('.toolbar_button button > svg, .toolbar_button button > img').each(function () { + $(this).parent().prepend(this); + }); - let minHeight; - if (tleft.length) { - minHeight = tleft.offset().top + tleft.outerHeight(); - } + const tleft = $('#tools_left'); - const size = $.pref('iconsize'); - editor.setIconSize(size || ($(window).height() < minHeight ? 's' : 'm')); + let minHeight; + if (tleft.length) { + minHeight = tleft.offset().top + tleft.outerHeight(); + } - // Look for any missing flyout icons from plugins - $('.tools_flyout').each(function () { - const shower = $('#' + this.id + '_show'); - const sel = shower.attr('data-curopt'); - // Check if there's an icon here - if (!shower.children('svg, img').length) { - const clone = $(sel).children().clone(); - if (clone.length) { - clone[0].removeAttribute('style'); // Needed for Opera - shower.append(clone); + const size = $.pref('iconsize'); + editor.setIconSize(size || ($(window).height() < minHeight ? 's' : 'm')); + + // Look for any missing flyout icons from plugins + $('.tools_flyout').each(function () { + const shower = $('#' + this.id + '_show'); + const sel = shower.attr('data-curopt'); + // Check if there's an icon here + if (!shower.children('svg, img').length) { + const clone = $(sel).children().clone(); + if (clone.length) { + clone[0].removeAttribute('style'); // Needed for Opera + shower.append(clone); + } + } + }); + + /** + * Since stylesheets may be added out of order, we indicate the desired order + * for defaults and others after them (in an indeterminate order). + * @param {string} stylesheetFile + * @returns {Integer|PositiveInfinity} + */ + function getStylesheetPriority (stylesheetFile) { + switch (stylesheetFile) { + case 'jgraduate/css/jPicker.css': + return 1; + case 'jgraduate/css/jGraduate.css': + return 2; + case 'svg-editor.css': + return 3; + case 'spinbtn/jQuery.SpinButton.css': + return 4; + default: + return Infinity; } } - }); - - function getStylesheetPriority (stylesheet) { - switch (stylesheet) { - case 'jgraduate/css/jPicker.css': - return 1; - case 'jgraduate/css/jGraduate.css': - return 2; - case 'svg-editor.css': - return 3; - case 'spinbtn/jQuery.SpinButton.css': - return 4; - default: - return Infinity; + let stylesheets = $.loadingStylesheets.sort((a, b) => { + const priorityA = getStylesheetPriority(a); + const priorityB = getStylesheetPriority(b); + if (priorityA === priorityB) { + return 0; + } + return priorityA > priorityB; + }); + if (curConfig.stylesheets.length) { + // Ensure a copy with unique items + stylesheets = [...new Set(curConfig.stylesheets)]; + const idx = stylesheets.indexOf('@default'); + if (idx > -1) { + stylesheets.splice(idx, 1, ...$.loadingStylesheets); + } } - } - let stylesheets = $.loadingStylesheets.sort((a, b) => { - const priorityA = getStylesheetPriority(a); - const priorityB = getStylesheetPriority(b); - if (priorityA === priorityB) { - return 0; - } - return priorityA > priorityB; - }); - if (curConfig.stylesheets.length) { - // Ensure a copy with unique items - stylesheets = [...new Set(curConfig.stylesheets)]; - const idx = stylesheets.indexOf('@default'); - if (idx > -1) { - stylesheets.splice(idx, 1, ...$.loadingStylesheets); - } - } - loadStylesheets(stylesheets, {acceptErrors: ({stylesheetURL, reject, resolve}) => { - if ($.loadingStylesheets.includes(stylesheetURL)) { - reject(new Error(`Missing expected stylesheet: ${stylesheetURL}`)); - return; - } - resolve(); - }}).then(() => { + await loadStylesheets(stylesheets, { + acceptErrors ({stylesheetURL, reject, resolve}) { + if ($.loadingStylesheets.includes(stylesheetURL)) { + reject(new Error(`Missing expected stylesheet: ${stylesheetURL}`)); + return; + } + resolve(); + } + }); $('#svg_container')[0].style.visibility = 'visible'; - editor.runCallbacks(); - }); - } - }); - + await editor.runCallbacks(); + } + }); + } /** * @name module:SVGEditor.canvas * @type {module:svgcanvas.SvgCanvas} @@ -1379,7 +1449,8 @@ editor.init = function () { document.getElementById('svgcanvas'), curConfig ); - const palette = [ // Todo: Make into configuration item? + const palette = [ + // Todo: Make into configuration item? '#000000', '#3f3f3f', '#7f7f7f', '#bfbfbf', '#ffffff', '#ff0000', '#ff7f00', '#ffff00', '#7fff00', '#00ff00', '#00ff7f', '#00ffff', '#007fff', @@ -1433,106 +1504,24 @@ editor.init = function () { } }()); - // This sets up alternative dialog boxes. They mostly work the same way as - // their UI counterparts, expect instead of returning the result, a callback - // needs to be included that returns the result as its first parameter. - // In the future we may want to add additional types of dialog boxes, since - // they should be easy to handle this way. - (function () { - $('#dialog_container').draggable({ - cancel: '#dialog_content, #dialog_buttons *', - containment: 'window' - }).css('position', 'absolute'); - const box = $('#dialog_box'), - btnHolder = $('#dialog_buttons'), - dialogContent = $('#dialog_content'), - dbox = function (type, msg, callback, defaultVal, opts, changeCb, checkbox) { - dialogContent.html('

' + msg.replace(/\n/g, '

') + '

') - .toggleClass('prompt', (type === 'prompt')); - btnHolder.empty(); - - const ok = $('').appendTo(btnHolder); - - if (type !== 'alert') { - $('') - .appendTo(btnHolder) - .click(function () { - box.hide(); - if (callback) { - callback(false); // eslint-disable-line standard/no-callback-literal - } - }); - } - - let ctrl, chkbx; - if (type === 'prompt') { - ctrl = $('').prependTo(btnHolder); - ctrl.val(defaultVal || ''); - ctrl.bind('keydown', 'return', function () { ok.click(); }); - } else if (type === 'select') { - const div = $('
'); - ctrl = $('').appendTo(label); - chkbx.val(checkbox.value); - if (checkbox.tooltip) { - label.attr('title', checkbox.tooltip); - } - chkbx.prop('checked', !!checkbox.checked); - div.append($('
').append(label)); - } - $.each(opts || [], function (opt, val) { - if (typeof val === 'object') { - ctrl.append($('
', { class: 'tools_flyout', @@ -2876,20 +2961,30 @@ editor.init = function () { return div; }; - // TODO: Combine this with addDropDown or find other way to optimize - const addAltDropDown = function (elem, list, callback, opts) { - const button = $(elem); + /** + * @param {string} elemSel + * @param {string} listSel + * @param {external:jQuery.Function} callback + * @param {PlainObject} opts + * @param {boolean} opts.dropUp + * @param {boolean} opts.seticon + * @param {boolean} opts.multiclick + * @todo Combine this with `addDropDown` or find other way to optimize. + * @returns {undefined} + */ + const addAltDropDown = function (elemSel, listSel, callback, opts) { + const button = $(elemSel); const {dropUp} = opts; - list = $(list); + const list = $(listSel); if (dropUp) { - $(elem).addClass('dropup'); + $(elemSel).addClass('dropup'); } - list.find('li').bind('mouseup', function () { + list.find('li').bind('mouseup', function (...args) { if (opts.seticon) { setIcon('#cur_' + button[0].id, $(this).children()); $(this).addClass('current').siblings().removeClass('current'); } - callback.apply(this, arguments); + callback.apply(this, ...args); }); let onButton = false; @@ -2940,11 +3035,11 @@ editor.init = function () { * @param {external:Window} win * @param {module:svgcanvas.SvgCanvas#event:extension_added} ext * @listens module:svgcanvas.SvgCanvas#event:extension_added - * @returns {Promise} Resolves to `undefined` + * @returns {Promise|undefined} Resolves to `undefined` */ - const extAdded = function (win, ext) { + const extAdded = async function (win, ext) { if (!ext) { - return; + return undefined; } let cbCalled = false; let resizeDone = false; @@ -2952,16 +3047,22 @@ editor.init = function () { if (ext.langReady) { if (editor.langChanged) { // We check for this since the "lang" pref could have been set by storage const lang = $.pref('lang'); - ext.langReady({ + await ext.langReady({ lang, uiStrings, importLocale: getImportLocale({defaultLang: lang, defaultName: ext.name}) }); + loadedExtensionNames.push(ext.name); } else { extsPreLang.push(ext); } } + /** + * Clear resize timer if present and if not previously performed, + * perform an icon resize. + * @returns {undefined} + */ function prepResize () { if (resizeTimer) { clearTimeout(resizeTimer); @@ -2975,6 +3076,10 @@ editor.init = function () { } } + /** + * + * @returns {undefined} + */ const runCallback = function () { if (ext.callback && !cbCalled) { cbCalled = true; @@ -3013,7 +3118,7 @@ editor.init = function () { let html; // TODO: Allow support for other types, or adding to existing tool switch (tool.type) { - case 'tool_button': + case 'tool_button': { html = '
' + tool.id + '
'; const div = $(html).appendTo(panel); if (tool.events) { @@ -3022,7 +3127,7 @@ editor.init = function () { }); } break; - case 'select': + } case 'select': { html = '' + ''; + '" size="' + (tool.size || '4') + + '" value="' + (tool.defval || '') + '" type="text"/>'; // Creates the tool, hides & adds it, returns the select element @@ -3081,8 +3187,7 @@ editor.init = function () { }); } break; - - default: + } default: break; } }); @@ -3165,7 +3270,7 @@ editor.init = function () { parent = '#main_menu ul'; break; } - let flyoutHolder, curH, showBtn, refData, refBtn; + let flyoutHolder, showBtn, refData, refBtn; const button = $((btn.list || btn.type === 'app_menu') ? '
  • ' : '
    ') .attr('id', id) .attr('title', btn.title) @@ -3175,7 +3280,7 @@ editor.init = function () { if ($(parent).children().eq(btn.position).length) { $(parent).children().eq(btn.position).before(button); } else { - $(parent).children().last().before(button); + $(parent).children().last().after(button); } } else { button.appendTo(parent); @@ -3210,7 +3315,7 @@ editor.init = function () { // TODO: Find way to set the current icon using the iconloader if this is not default // Include data for extension button as well as ref button - curH = holders['#' + flyoutHolder[0].id] = [{ + /* curH = */ holders['#' + flyoutHolder[0].id] = [{ sel: '#' + id, fn: btn.events.click, icon: btn.id, @@ -3271,7 +3376,7 @@ editor.init = function () { // TODO: Find way to set the current icon using the iconloader if this is not default // Include data for extension button as well as ref button - curH = holders['#' + flyoutHolder[0].id] = [{ + const curH = holders['#' + flyoutHolder[0].id] = [{ sel: '#' + id, fn: btn.events.click, icon: btn.id, @@ -3301,6 +3406,11 @@ editor.init = function () { // Add given events to button $.each(btn.events, function (name, func) { if (name === 'click' && btn.type === 'mode') { + // `touch.js` changes `touchstart` to `mousedown`, + // so we must map extension click events as well + if (isTouch() && name === 'click') { + name = 'mousedown'; + } if (btn.includeWith) { button.bind(name, func); } else { @@ -3330,7 +3440,7 @@ editor.init = function () { }); if (svgicons) { - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { // eslint-disable-line promise/avoid-new $.svgIcons(svgicons, { w: 24, h: 24, id_match: false, @@ -3353,6 +3463,12 @@ editor.init = function () { return runCallback(); }; + /** + * @param {string} color + * @param {Float} opac + * @param {string} type + * @returns {module:jGraduate~Paint} + */ const getPaint = function (color, opac, type) { // update the editor's fill paint const opts = {alpha: opac}; @@ -3390,7 +3506,7 @@ editor.init = function () { exportWindow = window.open('', exportWindowName); // A hack to get the window via JSON-able name without opening a new one } if (!exportWindow || exportWindow.closed) { - $.alert(uiStrings.notification.popupWindowBlocked); + /* await */ $.alert(uiStrings.notification.popupWindowBlocked); return; } exportWindow.location.href = data.output; @@ -3401,8 +3517,9 @@ editor.init = function () { 'updateCanvas', /** * @param {external:Window} win - * @param {false} center - * @param {module:math.XYObject} newCtr + * @param {PlainObject} centerInfo + * @param {false} centerInfo.center + * @param {module:math.XYObject} centerInfo.newCtr * @listens module:svgcanvas.SvgCanvas#event:updateCanvas * @returns {undefined} */ @@ -3416,7 +3533,8 @@ editor.init = function () { let str = '
    '; $.each(palette, function (i, item) { - str += '
    '; + str += '
    '; }); $('#palette').append(str); @@ -3442,14 +3560,23 @@ editor.init = function () { $('#image_save_opts input').val([$.pref('img_save')]); + /** + * @implements {module:jQuerySpinButton.ValueCallback} + */ const changeRectRadius = function (ctl) { svgCanvas.setRectRadius(ctl.value); }; + /** + * @implements {module:jQuerySpinButton.ValueCallback} + */ const changeFontSize = function (ctl) { svgCanvas.setFontSize(ctl.value); }; + /** + * @implements {module:jQuerySpinButton.ValueCallback} + */ const changeStrokeWidth = function (ctl) { let val = ctl.value; if (val === 0 && selectedElement && ['line', 'polyline'].includes(selectedElement.nodeName)) { @@ -3458,13 +3585,21 @@ editor.init = function () { svgCanvas.setStrokeWidth(val); }; + /** + * @implements {module:jQuerySpinButton.ValueCallback} + */ const changeRotationAngle = function (ctl) { svgCanvas.setRotationAngle(ctl.value); - $('#tool_reorient').toggleClass('disabled', parseInt(ctl.value, 10) === 0); + $('#tool_reorient').toggleClass('disabled', parseInt(ctl.value) === 0); }; + /** + * @param {external:jQuery.fn.SpinButton} ctl Spin Button + * @param {string} [val=ctl.value] + * @returns {undefined} + */ const changeOpacity = function (ctl, val) { - if (val == null) { val = ctl.value; } + if (Utils.isNullish(val)) { val = ctl.value; } $('#group_opacity').val(val); if (!ctl || !ctl.handle) { $('#opac_slider').slider('option', 'value', val); @@ -3472,8 +3607,14 @@ editor.init = function () { svgCanvas.setOpacity(val / 100); }; + /** + * @param {external:jQuery.fn.SpinButton} ctl Spin Button + * @param {string} [val=ctl.value] + * @param {boolean} noUndo + * @returns {undefined} + */ const changeBlur = function (ctl, val, noUndo) { - if (val == null) { val = ctl.value; } + if (Utils.isNullish(val)) { val = ctl.value; } $('#blur').val(val); let complete = false; if (!ctl || !ctl.handle) { @@ -3502,9 +3643,13 @@ editor.init = function () { // fired when user wants to move elements to another layer let promptMoveLayerOnce = false; - $('#selLayerNames').change(function () { + $('#selLayerNames').change(async function () { const destLayer = this.options[this.selectedIndex].value; const confirmStr = uiStrings.notification.QmoveElemsToLayer.replace('%s', destLayer); + /** + * @param {boolean} ok + * @returns {undefined} + */ const moveToLayer = function (ok) { if (!ok) { return; } promptMoveLayerOnce = true; @@ -3516,7 +3661,11 @@ editor.init = function () { if (promptMoveLayerOnce) { moveToLayer(true); } else { - $.confirm(confirmStr, moveToLayer); + const ok = await $.confirm(confirmStr); + if (!ok) { + return; + } + moveToLayer(true); } } }); @@ -3555,8 +3704,8 @@ editor.init = function () { const valid = isValidUnit(attr, val, selectedElement); if (!valid) { - $.alert(uiStrings.notification.invalidAttrValGiven); this.value = selectedElement.getAttribute(attr); + /* await */ $.alert(uiStrings.notification.invalidAttrValGiven); return false; } @@ -3585,6 +3734,7 @@ editor.init = function () { svgCanvas.changeSelectedAttribute(attr, val); } this.blur(); + return true; }); // Prevent selection of elements when shift-clicking @@ -3628,7 +3778,7 @@ editor.init = function () { panning = false, keypan = false; $('#svgcanvas').bind('mousemove mouseup', function (evt) { - if (panning === false) { return; } + if (panning === false) { return true; } wArea.scrollLeft -= (evt.clientX - lastX); wArea.scrollTop -= (evt.clientY - lastY); @@ -3645,6 +3795,7 @@ editor.init = function () { lastY = evt.clientY; return false; } + return true; }); $(window).mouseup(function () { @@ -3819,7 +3970,7 @@ editor.init = function () { editor.addDropDown('#opacity_dropdown', function () { if ($(this).find('div').length) { return; } - const perc = parseInt($(this).text().split('%')[0], 10); + const perc = parseInt($(this).text().split('%')[0]); changeOpacity(false, perc); }, true); @@ -3899,12 +4050,16 @@ editor.init = function () { // Unfocus text input when workarea is mousedowned. (function () { let inp; + /** + * + * @returns {undefined} + */ const unfocus = function () { $(inp).blur(); }; $('#svg_editor').find('button, select, input:not(#text)').focus(function () { - inp = this; + inp = this; // eslint-disable-line consistent-this uiContext = 'toolbars'; workarea.mousedown(unfocus); }).blur(function () { @@ -3917,60 +4072,100 @@ editor.init = function () { }); }()); + /** + * + * @returns {undefined} + */ const clickFHPath = function () { if (toolButtonClick('#tool_fhpath')) { svgCanvas.setMode('fhpath'); } }; + /** + * + * @returns {undefined} + */ const clickLine = function () { if (toolButtonClick('#tool_line')) { svgCanvas.setMode('line'); } }; + /** + * + * @returns {undefined} + */ const clickSquare = function () { if (toolButtonClick('#tool_square')) { svgCanvas.setMode('square'); } }; + /** + * + * @returns {undefined} + */ const clickRect = function () { if (toolButtonClick('#tool_rect')) { svgCanvas.setMode('rect'); } }; + /** + * + * @returns {undefined} + */ const clickFHRect = function () { if (toolButtonClick('#tool_fhrect')) { svgCanvas.setMode('fhrect'); } }; + /** + * + * @returns {undefined} + */ const clickCircle = function () { if (toolButtonClick('#tool_circle')) { svgCanvas.setMode('circle'); } }; + /** + * + * @returns {undefined} + */ const clickEllipse = function () { if (toolButtonClick('#tool_ellipse')) { svgCanvas.setMode('ellipse'); } }; + /** + * + * @returns {undefined} + */ const clickFHEllipse = function () { if (toolButtonClick('#tool_fhellipse')) { svgCanvas.setMode('fhellipse'); } }; + /** + * + * @returns {undefined} + */ const clickImage = function () { if (toolButtonClick('#tool_image')) { svgCanvas.setMode('image'); } }; + /** + * + * @returns {undefined} + */ const clickZoom = function () { if (toolButtonClick('#tool_zoom')) { svgCanvas.setMode('zoom'); @@ -3978,6 +4173,10 @@ editor.init = function () { } }; + /** + * @param {Float} multiplier + * @returns {undefined} + */ const zoomImage = function (multiplier) { const res = svgCanvas.getResolution(); multiplier = multiplier ? res.zoom * multiplier : 1; @@ -3988,6 +4187,10 @@ editor.init = function () { updateCanvas(true); }; + /** + * + * @returns {undefined} + */ const dblclickZoom = function () { if (toolButtonClick('#tool_zoom')) { zoomImage(); @@ -3995,38 +4198,61 @@ editor.init = function () { } }; + /** + * + * @returns {undefined} + */ const clickText = function () { if (toolButtonClick('#tool_text')) { svgCanvas.setMode('text'); } }; + /** + * + * @returns {undefined} + */ const clickPath = function () { if (toolButtonClick('#tool_path')) { svgCanvas.setMode('path'); } }; - // Delete is a contextual tool that only appears in the ribbon if - // an element has been selected + /** + * Delete is a contextual tool that only appears in the ribbon if + * an element has been selected. + * @returns {undefined} + */ const deleteSelected = function () { - if (selectedElement != null || multiselected) { + if (!Utils.isNullish(selectedElement) || multiselected) { svgCanvas.deleteSelectedElements(); } }; + /** + * + * @returns {undefined} + */ const cutSelected = function () { - if (selectedElement != null || multiselected) { + if (!Utils.isNullish(selectedElement) || multiselected) { svgCanvas.cutSelectedElements(); } }; + /** + * + * @returns {undefined} + */ const copySelected = function () { - if (selectedElement != null || multiselected) { + if (!Utils.isNullish(selectedElement) || multiselected) { svgCanvas.copySelectedElements(); } }; + /** + * + * @returns {undefined} + */ const pasteInCenter = function () { const zoom = svgCanvas.getZoom(); const x = (workarea[0].scrollLeft + workarea.width() / 2) / zoom - svgCanvas.contentW; @@ -4034,46 +4260,76 @@ editor.init = function () { svgCanvas.pasteElements('point', x, y); }; + /** + * + * @returns {undefined} + */ const moveToTopSelected = function () { - if (selectedElement != null) { + if (!Utils.isNullish(selectedElement)) { svgCanvas.moveToTopSelectedElement(); } }; + /** + * + * @returns {undefined} + */ const moveToBottomSelected = function () { - if (selectedElement != null) { + if (!Utils.isNullish(selectedElement)) { svgCanvas.moveToBottomSelectedElement(); } }; + /** + * @param {"Up"|"Down"} dir + * @returns {undefined} + */ const moveUpDownSelected = function (dir) { - if (selectedElement != null) { + if (!Utils.isNullish(selectedElement)) { svgCanvas.moveUpDownSelected(dir); } }; + /** + * + * @returns {undefined} + */ const convertToPath = function () { - if (selectedElement != null) { + if (!Utils.isNullish(selectedElement)) { svgCanvas.convertToPath(); } }; + /** + * + * @returns {undefined} + */ const reorientPath = function () { - if (selectedElement != null) { + if (!Utils.isNullish(selectedElement)) { path.reorient(); } }; - const makeHyperlink = function () { - if (selectedElement != null || multiselected) { - $.prompt(uiStrings.notification.enterNewLinkURL, 'http://', function (url) { - if (url) { svgCanvas.makeHyperlink(url); } - }); + /** + * + * @returns {Promise} Resolves to `undefined` + */ + const makeHyperlink = async function () { + if (!Utils.isNullish(selectedElement) || multiselected) { + const url = await $.prompt(uiStrings.notification.enterNewLinkURL, 'http://'); + if (url) { + svgCanvas.makeHyperlink(url); + } } }; + /** + * @param {Float} dx + * @param {Float} dy + * @returns {undefined} + */ const moveSelected = function (dx, dy) { - if (selectedElement != null || multiselected) { + if (!Utils.isNullish(selectedElement) || multiselected) { if (curConfig.gridSnapping) { // Use grid snap value regardless of zoom level const multi = svgCanvas.getZoom() * curConfig.snappingStep; @@ -4084,24 +4340,40 @@ editor.init = function () { } }; + /** + * + * @returns {undefined} + */ const linkControlPoints = function () { $('#tool_node_link').toggleClass('push_button_pressed tool_button'); const linked = $('#tool_node_link').hasClass('push_button_pressed'); path.linkControlPoints(linked); }; + /** + * + * @returns {undefined} + */ const clonePathNode = function () { if (path.getNodePoint()) { path.clonePathNode(); } }; + /** + * + * @returns {undefined} + */ const deletePathNode = function () { if (path.getNodePoint()) { path.deletePathNode(); } }; + /** + * + * @returns {undefined} + */ const addSubPath = function () { const button = $('#tool_add_subpath'); const sp = !button.hasClass('push_button_pressed'); @@ -4109,20 +4381,37 @@ editor.init = function () { path.addSubPath(sp); }; + /** + * + * @returns {undefined} + */ const opencloseSubPath = function () { path.opencloseSubPath(); }; + /** + * + * @returns {undefined} + */ const selectNext = function () { svgCanvas.cycleElement(1); }; + /** + * + * @returns {undefined} + */ const selectPrev = function () { svgCanvas.cycleElement(0); }; + /** + * @param {0|1} cw + * @param {Integer} step + * @returns {undefined} + */ const rotateSelected = function (cw, step) { - if (selectedElement == null || multiselected) { return; } + if (Utils.isNullish(selectedElement) || multiselected) { return; } if (!cw) { step *= -1; } const angle = parseFloat($('#angle').val()) + step; svgCanvas.setRotationAngle(angle); @@ -4131,36 +4420,49 @@ editor.init = function () { /** * @fires module:svgcanvas.SvgCanvas#event:ext-onNewDocument - * @returns {undefined} + * @returns {Promise} Resolves to `undefined` */ - const clickClear = function () { + const clickClear = async function () { const [x, y] = curConfig.dimensions; - $.confirm(uiStrings.notification.QwantToClear, function (ok) { - if (!ok) { return; } - setSelectMode(); - svgCanvas.clear(); - svgCanvas.setResolution(x, y); - updateCanvas(true); - zoomImage(); - populateLayers(); - updateContextPanel(); - prepPaints(); - svgCanvas.runExtensions('onNewDocument'); - }); + const ok = await $.confirm(uiStrings.notification.QwantToClear); + if (!ok) { + return; + } + setSelectMode(); + svgCanvas.clear(); + svgCanvas.setResolution(x, y); + updateCanvas(true); + zoomImage(); + populateLayers(); + updateContextPanel(); + prepPaints(); + svgCanvas.runExtensions('onNewDocument'); }; + /** + * + * @returns {false} + */ const clickBold = function () { svgCanvas.setBold(!svgCanvas.getBold()); updateContextPanel(); return false; }; + /** + * + * @returns {false} + */ const clickItalic = function () { svgCanvas.setItalic(!svgCanvas.getItalic()); updateContextPanel(); return false; }; + /** + * + * @returns {undefined} + */ const clickSave = function () { // In the future, more options can be provided here const saveOpts = { @@ -4171,59 +4473,17 @@ editor.init = function () { }; let loadingURL; - const clickExport = function () { - $.select('Select an image type for export: ', [ + /** + * + * @returns {Promise} Resolves to `undefined` + */ + const clickExport = async function () { + const imgType = await $.select('Select an image type for export: ', [ // See http://kangax.github.io/jstests/toDataUrl_mime_type_test/ for a useful list of MIME types and browser support // 'ICO', // Todo: Find a way to preserve transparency in SVG-Edit if not working presently and do full packaging for x-icon; then switch back to position after 'PNG' 'PNG', 'JPEG', 'BMP', 'WEBP', 'PDF' - ], async function (imgType) { // todo: replace hard-coded msg with uiStrings.notification. - if (!imgType) { - return; - } - // Open placeholder window (prevents popup) - let exportWindowName; - function openExportWindow () { - const str = uiStrings.notification.loadingImage; - if (curConfig.exportWindowType === 'new') { - editor.exportWindowCt++; - } - exportWindowName = curConfig.canvasName + editor.exportWindowCt; - let popHTML, popURL; - if (loadingURL) { - popURL = loadingURL; - } else { - popHTML = ` - - - ${str} - -

    ${str}

    - `; - if (typeof URL && URL.createObjectURL) { - const blob = new Blob([popHTML], {type: 'text/html'}); - popURL = URL.createObjectURL(blob); - } else { - popURL = 'data:text/html;base64;charset=utf-8,' + Utils.encode64(popHTML); - } - loadingURL = popURL; - } - exportWindow = window.open(popURL, exportWindowName); - } - const chrome = isChrome(); - if (imgType === 'PDF') { - if (!customExportPDF && !chrome) { - openExportWindow(); - } - svgCanvas.exportPDF(exportWindowName, chrome ? 'save' : undefined); - } else { - if (!customExportImage) { - openExportWindow(); - } - const quality = parseInt($('#image-slider').val(), 10) / 100; - /* const results = */ await svgCanvas.rasterExport(imgType, quality, exportWindowName); - } - }, function () { + ], function () { const sel = $(this); if (sel.val() === 'JPEG' || sel.val() === 'WEBP') { if (!$('#image-slider').length) { @@ -4235,19 +4495,81 @@ editor.init = function () { } else { $('#image-slider').parent().remove(); } - }); + }); // todo: replace hard-coded msg with uiStrings.notification. + if (!imgType) { + return; + } + // Open placeholder window (prevents popup) + let exportWindowName; + + /** + * + * @returns {undefined} + */ + function openExportWindow () { + const {loadingImage} = uiStrings.notification; + if (curConfig.exportWindowType === 'new') { + editor.exportWindowCt++; + } + exportWindowName = curConfig.canvasName + editor.exportWindowCt; + let popHTML, popURL; + if (loadingURL) { + popURL = loadingURL; + } else { + popHTML = ` + + + ${loadingImage} + +

    ${loadingImage}

    + `; + if (typeof URL !== 'undefined' && URL.createObjectURL) { + const blob = new Blob([popHTML], {type: 'text/html'}); + popURL = URL.createObjectURL(blob); + } else { + popURL = 'data:text/html;base64;charset=utf-8,' + Utils.encode64(popHTML); + } + loadingURL = popURL; + } + exportWindow = window.open(popURL, exportWindowName); + } + const chrome = isChrome(); + if (imgType === 'PDF') { + if (!customExportPDF && !chrome) { + openExportWindow(); + } + svgCanvas.exportPDF(exportWindowName); + } else { + if (!customExportImage) { + openExportWindow(); + } + const quality = parseInt($('#image-slider').val()) / 100; + /* const results = */ await svgCanvas.rasterExport(imgType, quality, exportWindowName); + } }; - // by default, svgCanvas.open() is a no-op. - // it is up to an extension mechanism (opera widget, etc) - // to call setCustomHandlers() which will make it do something + /** + * By default, svgCanvas.open() is a no-op. It is up to an extension + * mechanism (opera widget, etc.) to call `setCustomHandlers()` which + * will make it do something. + * @returns {undefined} + */ const clickOpen = function () { svgCanvas.open(); }; + /** + * + * @returns {undefined} + */ const clickImport = function () { + /* */ }; + /** + * + * @returns {undefined} + */ const clickUndo = function () { if (undoMgr.getUndoStackSize() > 0) { undoMgr.undo(); @@ -4255,6 +4577,10 @@ editor.init = function () { } }; + /** + * + * @returns {undefined} + */ const clickRedo = function () { if (undoMgr.getRedoStackSize() > 0) { undoMgr.redo(); @@ -4262,6 +4588,10 @@ editor.init = function () { } }; + /** + * + * @returns {undefined} + */ const clickGroup = function () { // group if (multiselected) { @@ -4272,23 +4602,35 @@ editor.init = function () { } }; + /** + * + * @returns {undefined} + */ const clickClone = function () { svgCanvas.cloneSelectedElements(20, 20); }; + /** + * + * @returns {undefined} + */ const clickAlign = function () { const letter = this.id.replace('tool_align', '').charAt(0); svgCanvas.alignSelectedElements(letter, $('#align_relative_to').val()); }; + /** + * + * @returns {undefined} + */ const clickWireframe = function () { $('#tool_wireframe').toggleClass('push_button_pressed tool_button'); workarea.toggleClass('wireframe'); if (supportsNonSS) { return; } - let wfRules = $('#wireframe_rules'); + const wfRules = $('#wireframe_rules'); if (!wfRules.length) { - wfRules = $('').appendTo('head'); + /* wfRules = */ $('').appendTo('head'); } else { wfRules.empty(); } @@ -4304,6 +4646,10 @@ editor.init = function () { let docprops = false; let preferences = false; + /** + * + * @returns {undefined} + */ const showDocProperties = function () { if (docprops) { return; } docprops = true; @@ -4325,14 +4671,16 @@ editor.init = function () { $('#svg_docprops').show(); }; + /** + * + * @returns {undefined} + */ const showPreferences = function () { if (preferences) { return; } preferences = true; $('#main_menu').hide(); // Update background color with current one - const blocks = $('#bg_blocks div'); - const curBg = 'cur_background'; const canvasBg = curPrefs.bkgd_color; const url = $.pref('bkgd_url'); blocks.each(function () { @@ -4352,13 +4700,21 @@ editor.init = function () { $('#svg_prefs').show(); }; + /** + * + * @returns {undefined} + */ const hideSourceEditor = function () { $('#svg_source_editor').hide(); editingsource = false; $('#svg_source_textarea').blur(); }; - const saveSourceEditor = function () { + /** + * + * @returns {Promise} Resolves to `undefined` + */ + const saveSourceEditor = async function () { if (!editingsource) { return; } const saveChanges = function () { @@ -4371,16 +4727,21 @@ editor.init = function () { }; if (!svgCanvas.setSvgString($('#svg_source_textarea').val())) { - $.confirm(uiStrings.notification.QerrorsRevertToSource, function (ok) { - if (!ok) { return false; } - saveChanges(); - }); - } else { + const ok = await $.confirm(uiStrings.notification.QerrorsRevertToSource); + if (!ok) { + return; + } saveChanges(); + return; } + saveChanges(); setSelectMode(); }; + /** + * + * @returns {undefined} + */ const hideDocProperties = function () { $('#svg_docprops').hide(); $('#canvas_width,#canvas_height').removeAttr('disabled'); @@ -4389,11 +4750,19 @@ editor.init = function () { docprops = false; }; + /** + * + * @returns {undefined} + */ const hidePreferences = function () { $('#svg_prefs').hide(); preferences = false; }; + /** + * + * @returns {boolean} Whether there were problems saving the document properties + */ const saveDocProperties = function () { // set title const newTitle = $('#canvas_title').val(); @@ -4405,23 +4774,23 @@ editor.init = function () { const height = $('#canvas_height'), h = height.val(); if (w !== 'fit' && !isValidUnit('width', w)) { - $.alert(uiStrings.notification.invalidAttrValGiven); width.parent().addClass('error'); + /* await */ $.alert(uiStrings.notification.invalidAttrValGiven); return false; } width.parent().removeClass('error'); if (h !== 'fit' && !isValidUnit('height', h)) { - $.alert(uiStrings.notification.invalidAttrValGiven); height.parent().addClass('error'); + /* await */ $.alert(uiStrings.notification.invalidAttrValGiven); return false; } height.parent().removeClass('error'); if (!svgCanvas.setResolution(w, h)) { - $.alert(uiStrings.notification.noContentToFitTo); + /* await */ $.alert(uiStrings.notification.noContentToFitTo); return false; } @@ -4429,14 +4798,15 @@ editor.init = function () { $.pref('img_save', $('#image_save_opts :checked').val()); updateCanvas(); hideDocProperties(); + return true; }; /** - * Save user preferences based on current values in the UI + * Save user preferences based on current values in the UI. * @function module:SVGEditor.savePreferences * @returns {undefined} */ - const savePreferences = editor.savePreferences = function () { + const savePreferences = editor.savePreferences = async function () { // Set background const color = $('#bg_blocks div.cur_background').css('background-color') || '#FFF'; setBackground(color, $('#canvas_bg_url').val()); @@ -4444,7 +4814,8 @@ editor.init = function () { // set language const lang = $('#lang_select').val(); if (lang !== $.pref('lang')) { - editor.putLocale(lang, goodLangs, curConfig); + const {langParam, langData} = await editor.putLocale(lang, goodLangs, curConfig); + await setLang(langParam, langData); } // set icon size @@ -4468,7 +4839,11 @@ editor.init = function () { let resetScrollPos = $.noop; - const cancelOverlays = function () { + /** + * + * @returns {Promise} Resolves to `undefined` + */ + const cancelOverlays = async function () { $('#dialog_box').hide(); if (!editingsource && !docprops && !preferences) { if (curContext) { @@ -4479,9 +4854,10 @@ editor.init = function () { if (editingsource) { if (origSource !== $('#svg_source_textarea').val()) { - $.confirm(uiStrings.notification.QignoreSourceChanges, function (ok) { - if (ok) { hideSourceEditor(); } - }); + const ok = await $.confirm(uiStrings.notification.QignoreSourceChanges); + if (ok) { + hideSourceEditor(); + } } else { hideSourceEditor(); } @@ -4497,35 +4873,36 @@ editor.init = function () { // Fix for Issue 781: Drawing area jumps to top-left corner on window resize (IE9) if (isIE()) { - (() => { - resetScrollPos = function () { - if (workarea[0].scrollLeft === 0 && workarea[0].scrollTop === 0) { - workarea[0].scrollLeft = curScrollPos.left; - workarea[0].scrollTop = curScrollPos.top; - } - }; + resetScrollPos = function () { + if (workarea[0].scrollLeft === 0 && workarea[0].scrollTop === 0) { + workarea[0].scrollLeft = curScrollPos.left; + workarea[0].scrollTop = curScrollPos.top; + } + }; + curScrollPos = { + left: workarea[0].scrollLeft, + top: workarea[0].scrollTop + }; + + $(window).resize(resetScrollPos); + editor.ready(function () { + // TODO: Find better way to detect when to do this to minimize + // flickering effect + return new Promise((resolve, reject) => { // eslint-disable-line promise/avoid-new + setTimeout(function () { + resetScrollPos(); + resolve(); + }, 500); + }); + }); + + workarea.scroll(function () { curScrollPos = { left: workarea[0].scrollLeft, top: workarea[0].scrollTop }; - - $(window).resize(resetScrollPos); - editor.ready(function () { - // TODO: Find better way to detect when to do this to minimize - // flickering effect - setTimeout(function () { - resetScrollPos(); - }, 500); - }); - - workarea.scroll(function () { - curScrollPos = { - left: workarea[0].scrollLeft, - top: workarea[0].scrollTop - }; - }); - })(); + }); } $(window).resize(function (evt) { @@ -4537,20 +4914,18 @@ editor.init = function () { setFlyoutPositions(); }); - (() => { - workarea.scroll(function () { - // TODO: jQuery's scrollLeft/Top() wouldn't require a null check - if ($('#ruler_x').length) { - $('#ruler_x')[0].scrollLeft = workarea[0].scrollLeft; - } - if ($('#ruler_y').length) { - $('#ruler_y')[0].scrollTop = workarea[0].scrollTop; - } - }); - })(); + workarea.scroll(function () { + // TODO: jQuery's scrollLeft/Top() wouldn't require a null check + if ($('#ruler_x').length) { + $('#ruler_x')[0].scrollLeft = workarea[0].scrollLeft; + } + if ($('#ruler_y').length) { + $('#ruler_y')[0].scrollTop = workarea[0].scrollTop; + } + }); $('#url_notice').click(function () { - $.alert(this.title); + /* await */ $.alert(this.title); }); $('#change_image_url').click(promptImgURL); @@ -4584,7 +4959,10 @@ editor.init = function () { // NOTE: This code is not used yet until I can figure out how to successfully bind ctrl/meta // in Opera and Chrome if (isMac() && !window.opera) { - const shortcutButtons = ['tool_clear', 'tool_save', 'tool_source', 'tool_undo', 'tool_redo', 'tool_clone']; + const shortcutButtons = [ + 'tool_clear', 'tool_save', 'tool_source', + 'tool_undo', 'tool_redo', 'tool_clone' + ]; let i = shortcutButtons.length; while (i--) { const button = document.getElementById(shortcutButtons[i]); @@ -4596,8 +4974,12 @@ editor.init = function () { } } - // TODO: go back to the color boxes having white background-color and then setting - // background-image to none.png (otherwise partially transparent gradients look weird) + /** + * @param {external:jQuery} elem + * @todo Go back to the color boxes having white background-color and then setting + * background-image to none.png (otherwise partially transparent gradients look weird) + * @returns {undefined} + */ const colorPicker = function (elem) { const picker = elem.attr('id') === 'stroke_color' ? 'stroke' : 'fill'; // const opacity = (picker == 'stroke' ? $('#stroke_opacity') : $('#fill_opacity')); @@ -4632,30 +5014,30 @@ editor.init = function () { ); }; - const PaintBox = function (container, type) { - let paintColor, paintOpacity; - const cur = curConfig[type === 'fill' ? 'initFill' : 'initStroke']; - // set up gradients to be used for the buttons - const svgdocbox = new DOMParser().parseFromString( - ` - - - `, - 'text/xml' - ); + class PaintBox { + constructor (container, type) { + const cur = curConfig[type === 'fill' ? 'initFill' : 'initStroke']; + // set up gradients to be used for the buttons + const svgdocbox = new DOMParser().parseFromString( + ` + + + `, + 'text/xml' + ); - let docElem = svgdocbox.documentElement; - docElem = $(container)[0].appendChild(document.importNode(docElem, true)); - docElem.setAttribute('width', 16.5); + let docElem = svgdocbox.documentElement; + docElem = $(container)[0].appendChild(document.importNode(docElem, true)); + docElem.setAttribute('width', 16.5); - this.rect = docElem.firstElementChild; - this.defs = docElem.getElementsByTagName('defs')[0]; - this.grad = this.defs.firstElementChild; - this.paint = new $.jGraduate.Paint({solidColor: cur.color}); - this.type = type; - - this.setPaint = function (paint, apply) { + this.rect = docElem.firstElementChild; + this.defs = docElem.getElementsByTagName('defs')[0]; + this.grad = this.defs.firstElementChild; + this.paint = new $.jGraduate.Paint({solidColor: cur.color}); + this.type = type; + } + setPaint (paint, apply) { this.paint = paint; const ptype = paint.type; @@ -4667,24 +5049,25 @@ editor.init = function () { fillAttr = (paint[ptype] !== 'none') ? '#' + paint[ptype] : paint[ptype]; break; case 'linearGradient': - case 'radialGradient': + case 'radialGradient': { this.grad.remove(); this.grad = this.defs.appendChild(paint[ptype]); const id = this.grad.id = 'gradbox_' + this.type; fillAttr = 'url(#' + id + ')'; break; } + } this.rect.setAttribute('fill', fillAttr); this.rect.setAttribute('opacity', opac); if (apply) { - svgCanvas.setColor(this.type, paintColor, true); - svgCanvas.setPaintOpacity(this.type, paintOpacity, true); + svgCanvas.setColor(this.type, this._paintColor, true); + svgCanvas.setPaintOpacity(this.type, this._paintOpacity, true); } - }; + } - this.update = function (apply) { + update (apply) { if (!selectedElement) { return; } const {type} = this; @@ -4713,46 +5096,48 @@ editor.init = function () { if (gPaint === null) { // No common color, don't update anything - paintColor = null; + this._paintColor = null; return; } - paintColor = gPaint; - paintOpacity = 1; + this._paintColor = gPaint; + this._paintOpacity = 1; break; - } default: - paintOpacity = parseFloat(selectedElement.getAttribute(type + '-opacity')); - if (isNaN(paintOpacity)) { - paintOpacity = 1.0; + } default: { + this._paintOpacity = parseFloat(selectedElement.getAttribute(type + '-opacity')); + if (isNaN(this._paintOpacity)) { + this._paintOpacity = 1.0; } const defColor = type === 'fill' ? 'black' : 'none'; - paintColor = selectedElement.getAttribute(type) || defColor; + this._paintColor = selectedElement.getAttribute(type) || defColor; + } } if (apply) { - svgCanvas.setColor(type, paintColor, true); - svgCanvas.setPaintOpacity(type, paintOpacity, true); + svgCanvas.setColor(type, this._paintColor, true); + svgCanvas.setPaintOpacity(type, this._paintOpacity, true); } - paintOpacity *= 100; + this._paintOpacity *= 100; - const paint = getPaint(paintColor, paintOpacity, type); + const paint = getPaint(this._paintColor, this._paintOpacity, type); // update the rect inside #fill_color/#stroke_color this.setPaint(paint); - }; + } - this.prep = function () { + prep () { const ptype = this.paint.type; switch (ptype) { case 'linearGradient': - case 'radialGradient': + case 'radialGradient': { const paint = new $.jGraduate.Paint({copy: this.paint}); - svgCanvas.setPaint(type, paint); + svgCanvas.setPaint(this.type, paint); break; } - }; - }; + } + } + } paintBox.fill = new PaintBox('#fill_color', 'fill'); paintBox.stroke = new PaintBox('#stroke_color', 'stroke'); @@ -4793,7 +5178,10 @@ editor.init = function () { $('#image_save_opts [value=embed]').attr('disabled', 'disabled'); $('#image_save_opts input').val(['ref']); $.pref('img_save', 'ref'); - $('#image_opt_embed').css('color', '#666').attr('title', uiStrings.notification.featNotSupported); + $('#image_opt_embed').css('color', '#666').attr( + 'title', + uiStrings.notification.featNotSupported + ); } }); }, 1000); @@ -4842,25 +5230,28 @@ editor.init = function () { }); // ask for a layer name - $('#layer_new').click(function () { + $('#layer_new').click(async function () { let uniqName, i = svgCanvas.getCurrentDrawing().getNumLayers(); do { uniqName = uiStrings.layers.layer + ' ' + (++i); } while (svgCanvas.getCurrentDrawing().hasLayer(uniqName)); - $.prompt(uiStrings.notification.enterUniqueLayerName, uniqName, function (newName) { - if (!newName) { return; } - if (svgCanvas.getCurrentDrawing().hasLayer(newName)) { - $.alert(uiStrings.notification.dupeLayerName); - return; - } - svgCanvas.createLayer(newName); - updateContextPanel(); - populateLayers(); - }); + const newName = await $.prompt(uiStrings.notification.enterUniqueLayerName, uniqName); + if (!newName) { return; } + if (svgCanvas.getCurrentDrawing().hasLayer(newName)) { + /* await */ $.alert(uiStrings.notification.dupeLayerName); + return; + } + svgCanvas.createLayer(newName); + updateContextPanel(); + populateLayers(); }); + /** + * + * @returns {undefined} + */ function deleteLayer () { if (svgCanvas.deleteCurrentLayer()) { updateContextPanel(); @@ -4873,21 +5264,28 @@ editor.init = function () { } } - function cloneLayer () { + /** + * + * @returns {undefined} + */ + async function cloneLayer () { const name = svgCanvas.getCurrentDrawing().getCurrentLayerName() + ' copy'; - $.prompt(uiStrings.notification.enterUniqueLayerName, name, function (newName) { - if (!newName) { return; } - if (svgCanvas.getCurrentDrawing().hasLayer(newName)) { - $.alert(uiStrings.notification.dupeLayerName); - return; - } - svgCanvas.cloneLayer(newName); - updateContextPanel(); - populateLayers(); - }); + const newName = await $.prompt(uiStrings.notification.enterUniqueLayerName, name); + if (!newName) { return; } + if (svgCanvas.getCurrentDrawing().hasLayer(newName)) { + /* await */ $.alert(uiStrings.notification.dupeLayerName); + return; + } + svgCanvas.cloneLayer(newName); + updateContextPanel(); + populateLayers(); } + /** + * + * @returns {undefined} + */ function mergeLayer () { if ($('#layerlist tr.layersel').index() === svgCanvas.getCurrentDrawing().getNumLayers() - 1) { return; @@ -4897,6 +5295,10 @@ editor.init = function () { populateLayers(); } + /** + * @param {Integer} pos + * @returns {undefined} + */ function moveLayer (pos) { const total = svgCanvas.getCurrentDrawing().getNumLayers(); @@ -4918,19 +5320,18 @@ editor.init = function () { moveLayer(1); }); - $('#layer_rename').click(function () { + $('#layer_rename').click(async function () { // const curIndex = $('#layerlist tr.layersel').prevAll().length; // Currently unused const oldName = $('#layerlist tr.layersel td.layername').text(); - $.prompt(uiStrings.notification.enterNewLayerName, '', function (newName) { - if (!newName) { return; } - if (oldName === newName || svgCanvas.getCurrentDrawing().hasLayer(newName)) { - $.alert(uiStrings.notification.layerHasThatName); - return; - } + const newName = await $.prompt(uiStrings.notification.enterNewLayerName, ''); + if (!newName) { return; } + if (oldName === newName || svgCanvas.getCurrentDrawing().hasLayer(newName)) { + /* await */ $.alert(uiStrings.notification.layerHasThatName); + return; + } - svgCanvas.renameCurrentLayer(newName); - populateLayers(); - }); + svgCanvas.renameCurrentLayer(newName); + populateLayers(); }); const SIDEPANEL_MAXWIDTH = 300; @@ -4946,23 +5347,27 @@ editor.init = function () { const rulerX = $('#ruler_x'); $('#sidepanels').width('+=' + delta); $('#layerpanel').width('+=' + delta); - rulerX.css('right', parseInt(rulerX.css('right'), 10) + delta); - workarea.css('right', parseInt(workarea.css('right'), 10) + delta); + rulerX.css('right', parseInt(rulerX.css('right')) + delta); + workarea.css('right', parseInt(workarea.css('right')) + delta); svgCanvas.runExtensions('workareaResized'); }; + /** + * @param {Event} evt + * @returns {undefined} + */ const resizeSidePanel = function (evt) { if (!allowmove) { return; } if (sidedrag === -1) { return; } sidedragging = true; let deltaX = sidedrag - evt.pageX; - let sideWidth = $('#sidepanels').width(); + const sideWidth = $('#sidepanels').width(); if (sideWidth + deltaX > SIDEPANEL_MAXWIDTH) { deltaX = SIDEPANEL_MAXWIDTH - sideWidth; - sideWidth = SIDEPANEL_MAXWIDTH; + // sideWidth = SIDEPANEL_MAXWIDTH; } else if (sideWidth + deltaX < 2) { deltaX = 2 - sideWidth; - sideWidth = 2; + // sideWidth = 2; } if (deltaX === 0) { return; } sidedrag -= deltaX; @@ -4970,13 +5375,16 @@ editor.init = function () { }; /** - * If width is non-zero, then fully close it, otherwise fully open it + * If width is non-zero, then fully close it; otherwise fully open it. * @param {boolean} close Forces the side panel closed * @returns {undefined} */ const toggleSidePanel = function (close) { + const dpr = window.devicePixelRatio || 1; const w = $('#sidepanels').width(); - const deltaX = (w > 2 || close ? 2 : SIDEPANEL_OPENWIDTH) - w; + const isOpened = (dpr < 1 ? w : w / dpr) > 2; + const zoomAdjustedSidepanelWidth = (dpr < 1 ? 1 : dpr) * SIDEPANEL_OPENWIDTH; + const deltaX = (isOpened || close ? 0 : zoomAdjustedSidepanelWidth) - w; changeSidePanelWidth(deltaX); }; @@ -5016,6 +5424,9 @@ editor.init = function () { $(window).bind('load resize', centerCanvas); + /** + * @implements {module:jQuerySpinButton.StepCallback} + */ function stepFontSize (elem, step) { const origVal = Number(elem.value); const sugVal = origVal + step; @@ -5037,6 +5448,9 @@ editor.init = function () { return sugVal; } + /** + * @implements {module:jQuerySpinButton.StepCallback} + */ function stepZoom (elem, step) { const origVal = Number(elem.value); if (origVal === 0) { return 100; } @@ -5087,6 +5501,10 @@ editor.init = function () { // Prevent browser from erroneously repopulating fields $('input,select').attr('autocomplete', 'off'); + const dialogSelectors = [ + '#tool_source_cancel', '#tool_docprops_cancel', + '#tool_prefs_cancel', '.overlay' + ]; /** * Associate all button actions as well as non-button keyboard shortcuts * @namespace {PlainObject} module:SVGEditor~Actions @@ -5111,7 +5529,8 @@ editor.init = function () { const toolButtons = [ {sel: '#tool_select', fn: clickSelect, evt: 'click', key: ['V', true]}, {sel: '#tool_fhpath', fn: clickFHPath, evt: 'click', key: ['Q', true]}, - {sel: '#tool_line', fn: clickLine, evt: 'click', key: ['L', true], parent: '#tools_line', prepend: true}, + {sel: '#tool_line', fn: clickLine, evt: 'click', key: ['L', true], + parent: '#tools_line', prepend: true}, {sel: '#tool_rect', fn: clickRect, evt: 'mouseup', key: ['R', true], parent: '#tools_rect', icon: 'rect'}, {sel: '#tool_square', fn: clickSquare, evt: 'mouseup', @@ -5141,8 +5560,19 @@ editor.init = function () { {sel: '#tool_import', fn: clickImport, evt: 'mouseup'}, {sel: '#tool_source', fn: showSourceEditor, evt: 'click', key: ['U', true]}, {sel: '#tool_wireframe', fn: clickWireframe, evt: 'click', key: ['F', true]}, - {sel: '#tool_source_cancel,.overlay,#tool_docprops_cancel,#tool_prefs_cancel', - fn: cancelOverlays, evt: 'click', key: ['esc', false, false], hidekey: true}, + { + key: ['esc', false, false], + fn () { + if (dialogSelectors.every((sel) => { + return $(sel + ':hidden').length; + })) { + svgCanvas.clearSelection(); + } + }, + hidekey: true + }, + {sel: dialogSelectors.join(','), fn: cancelOverlays, evt: 'click', + key: ['esc', false, false], hidekey: true}, {sel: '#tool_source_save', fn: saveSourceEditor, evt: 'click'}, {sel: '#tool_docprops_save', fn: saveDocProperties, evt: 'click'}, {sel: '#tool_docprops', fn: showDocProperties, evt: 'mouseup'}, @@ -5203,7 +5633,8 @@ editor.init = function () { {key: ['alt+shift+down', true], fn () { svgCanvas.cloneSelectedElements(0, 10); }}, {key: ['alt+shift+left', true], fn () { svgCanvas.cloneSelectedElements(-10, 0); }}, {key: ['alt+shift+right', true], fn () { svgCanvas.cloneSelectedElements(10, 0); }}, - {key: 'A', fn () { svgCanvas.selectAllInCurrentLayer(); }}, + {key: 'a', fn () { svgCanvas.selectAllInCurrentLayer(); }}, + {key: modKey + 'a', fn () { svgCanvas.selectAllInCurrentLayer(); }}, // Standard shortcuts {key: modKey + 'z', fn: clickUndo}, @@ -5235,6 +5666,8 @@ editor.init = function () { btn = $(opts.sel); if (!btn.length) { return true; } // Skip if markup does not exist if (opts.evt) { + // `touch.js` changes `touchstart` to `mousedown`, + // so we must map tool button click events as well if (isTouch() && opts.evt === 'click') { opts.evt = 'mousedown'; } @@ -5272,10 +5705,10 @@ editor.init = function () { } else { keyval = opts.key; } - keyval += ''; + keyval = String(keyval); const {fn} = opts; - $.each(keyval.split('/'), function (i, key) { + $.each(keyval.split('/'), function (j, key) { $(document).bind('keydown', key, function (e) { fn(); if (pd) { @@ -5296,6 +5729,7 @@ editor.init = function () { } } } + return true; }); // Setup flyouts @@ -5304,7 +5738,9 @@ editor.init = function () { // Misc additional actions // Make 'return' keypress trigger the change event - $('.attr_changer, #image_url').bind('keydown', 'return', + $('.attr_changer, #image_url').bind( + 'keydown', + 'return', function (evt) { $(this).change(); evt.preventDefault(); @@ -5394,7 +5830,7 @@ editor.init = function () { toggleSidePanel(); } - $('#rulers').toggle(!!curConfig.showRulers); + $('#rulers').toggle(Boolean(curConfig.showRulers)); if (curConfig.showRulers) { $('#show_rulers')[0].checked = true; @@ -5418,15 +5854,31 @@ editor.init = function () { }); // init SpinButtons - $('#rect_rx').SpinButton({min: 0, max: 1000, stateObj, callback: changeRectRadius}); - $('#stroke_width').SpinButton({min: 0, max: 99, smallStep: 0.1, stateObj, callback: changeStrokeWidth}); - $('#angle').SpinButton({min: -180, max: 180, step: 5, stateObj, callback: changeRotationAngle}); - $('#font_size').SpinButton({min: 0.001, stepfunc: stepFontSize, stateObj, callback: changeFontSize}); - $('#group_opacity').SpinButton({min: 0, max: 100, step: 5, stateObj, callback: changeOpacity}); - $('#blur').SpinButton({min: 0, max: 10, step: 0.1, stateObj, callback: changeBlur}); - $('#zoom').SpinButton({min: 0.001, max: 10000, step: 50, stepfunc: stepZoom, stateObj, callback: changeZoom}) - // Set default zoom - .val(svgCanvas.getZoom() * 100); + $('#rect_rx').SpinButton({ + min: 0, max: 1000, stateObj, callback: changeRectRadius + }); + $('#stroke_width').SpinButton({ + min: 0, max: 99, smallStep: 0.1, stateObj, callback: changeStrokeWidth + }); + $('#angle').SpinButton({ + min: -180, max: 180, step: 5, stateObj, callback: changeRotationAngle + }); + $('#font_size').SpinButton({ + min: 0.001, stepfunc: stepFontSize, stateObj, callback: changeFontSize + }); + $('#group_opacity').SpinButton({ + min: 0, max: 100, step: 5, stateObj, callback: changeOpacity + }); + $('#blur').SpinButton({ + min: 0, max: 10, step: 0.1, stateObj, callback: changeBlur + }); + $('#zoom').SpinButton({ + min: 0.001, max: 10000, step: 50, stepfunc: stepZoom, + stateObj, callback: changeZoom + // Set default zoom + }).val( + svgCanvas.getZoom() * 100 + ); $('#workarea').contextMenu( { @@ -5478,10 +5930,17 @@ editor.init = function () { } ); + /** + * Implements {@see module:jQueryContextMenu.jQueryContextMenuListener} + * @param {"dupe"|"delete"|"merge_down"|"merge_all"} action + * @param {external:jQuery} el + * @param {{x: Float, y: Float, docX: Float, docY: Float}} pos + * @returns {undefined} + */ const lmenuFunc = function (action, el, pos) { switch (action) { case 'dupe': - cloneLayer(); + /* await */ cloneLayer(); break; case 'delete': deleteLayer(); @@ -5521,6 +5980,9 @@ editor.init = function () { $('#cmenu_canvas li').disableContextMenu(); canvMenu.enableContextMenuItems('#delete,#cut,#copy'); + /** + * @returns {undefined} + */ function enableOrDisableClipboard () { let svgeditClipboard; try { @@ -5550,10 +6012,11 @@ editor.init = function () { e.returnValue = uiStrings.notification.unsavedChanges; // Firefox needs this when beforeunload set by addEventListener (even though message is not used) return uiStrings.notification.unsavedChanges; } - }, false); + return true; + }); /** - * Expose the uiStrings + * Expose the `uiStrings`. * @function module:SVGEditor.canvas.getUIStrings * @returns {module:SVGEditor.uiStrings} */ @@ -5562,34 +6025,43 @@ editor.init = function () { }; /** - * @callback module:SVGEditor.OpenPrepCallback - * @param {boolean} noChanges - * @returns {undefined} + * @returns {Promise} Resolves to boolean indicating `true` if there were no changes + * and `false` after the user confirms. */ - /** - * @param {module:SVGEditor.OpenPrepCallback} func Confirmation dialog callback - * @returns {undefined} - */ - editor.openPrep = function (func) { + editor.openPrep = function () { $('#main_menu').hide(); if (undoMgr.getUndoStackSize() === 0) { - func(true); - } else { - $.confirm(uiStrings.notification.QwantToOpen, func); + return true; } + return $.confirm(uiStrings.notification.QwantToOpen); }; + /** + * + * @param {Event} e + * @returns {undefined} + */ function onDragEnter (e) { e.stopPropagation(); e.preventDefault(); // and indicator should be displayed here, such as "drop files here" } + /** + * + * @param {Event} e + * @returns {undefined} + */ function onDragOver (e) { e.stopPropagation(); e.preventDefault(); } + /** + * + * @param {Event} e + * @returns {undefined} + */ function onDragLeave (e) { e.stopPropagation(); e.preventDefault(); @@ -5600,6 +6072,10 @@ editor.init = function () { // and provide a file input to click. When that change event fires, it will // get the text contents of the file and send it to the canvas if (window.FileReader) { + /** + * @param {Event} e + * @returns {undefined} + */ const importImage = function (e) { $.process_cancel(uiStrings.notification.loadingImage); e.stopPropagation(); @@ -5615,85 +6091,89 @@ editor.init = function () { } else */ - if (file.type.includes('image')) { - // Detected an image - // svg handling - let reader; - if (file.type.includes('svg')) { - reader = new FileReader(); - reader.onloadend = function (e) { - const newElement = svgCanvas.importSvgString(e.target.result, true); - svgCanvas.ungroupSelectedElement(); - svgCanvas.ungroupSelectedElement(); - svgCanvas.groupSelectedElements(); + if (!file.type.includes('image')) { + return; + } + // Detected an image + // svg handling + let reader; + if (file.type.includes('svg')) { + reader = new FileReader(); + reader.onloadend = function (ev) { + const newElement = svgCanvas.importSvgString(ev.target.result, true); + svgCanvas.ungroupSelectedElement(); + svgCanvas.ungroupSelectedElement(); + svgCanvas.groupSelectedElements(); + svgCanvas.alignSelectedElements('m', 'page'); + svgCanvas.alignSelectedElements('c', 'page'); + // highlight imported element, otherwise we get strange empty selectbox + svgCanvas.selectOnly([newElement]); + $('#dialog_box').hide(); + }; + reader.readAsText(file); + } else { + // bitmap handling + reader = new FileReader(); + reader.onloadend = function ({target: {result}}) { + /** + * Insert the new image until we know its dimensions + * @param {Float} width + * @param {Float} height + * @returns {undefined} + */ + const insertNewImage = function (width, height) { + const newImage = svgCanvas.addSVGElementFromJson({ + element: 'image', + attr: { + x: 0, + y: 0, + width, + height, + id: svgCanvas.getNextId(), + style: 'pointer-events:inherit' + } + }); + svgCanvas.setHref(newImage, result); + svgCanvas.selectOnly([newImage]); svgCanvas.alignSelectedElements('m', 'page'); svgCanvas.alignSelectedElements('c', 'page'); - // highlight imported element, otherwise we get strange empty selectbox - svgCanvas.selectOnly([newElement]); + updateContextPanel(); $('#dialog_box').hide(); }; - reader.readAsText(file); - } else { - // bitmap handling - reader = new FileReader(); - reader.onloadend = function ({target: {result}}) { - // let's insert the new image until we know its dimensions - const insertNewImage = function (width, height) { - const newImage = svgCanvas.addSVGElementFromJson({ - element: 'image', - attr: { - x: 0, - y: 0, - width, - height, - id: svgCanvas.getNextId(), - style: 'pointer-events:inherit' - } - }); - svgCanvas.setHref(newImage, result); - svgCanvas.selectOnly([newImage]); - svgCanvas.alignSelectedElements('m', 'page'); - svgCanvas.alignSelectedElements('c', 'page'); - updateContextPanel(); - $('#dialog_box').hide(); - }; - // create dummy img so we know the default dimensions - let imgWidth = 100; - let imgHeight = 100; - const img = new Image(); - img.style.opacity = 0; - img.onload = function () { - imgWidth = img.offsetWidth || img.naturalWidth || img.width; - imgHeight = img.offsetHeight || img.naturalHeight || img.height; - insertNewImage(imgWidth, imgHeight); - }; - img.src = result; - }; - reader.readAsDataURL(file); - } + // create dummy img so we know the default dimensions + let imgWidth = 100; + let imgHeight = 100; + const img = new Image(); + img.style.opacity = 0; + img.addEventListener('load', function () { + imgWidth = img.offsetWidth || img.naturalWidth || img.width; + imgHeight = img.offsetHeight || img.naturalHeight || img.height; + insertNewImage(imgWidth, imgHeight); + }); + img.src = result; + }; + reader.readAsDataURL(file); } }; - workarea[0].addEventListener('dragenter', onDragEnter, false); - workarea[0].addEventListener('dragover', onDragOver, false); - workarea[0].addEventListener('dragleave', onDragLeave, false); - workarea[0].addEventListener('drop', importImage, false); + workarea[0].addEventListener('dragenter', onDragEnter); + workarea[0].addEventListener('dragover', onDragOver); + workarea[0].addEventListener('dragleave', onDragLeave); + workarea[0].addEventListener('drop', importImage); - const open = $('').change(function () { - const f = this; - editor.openPrep(function (ok) { - if (!ok) { return; } - svgCanvas.clear(); - if (f.files.length === 1) { - $.process_cancel(uiStrings.notification.loadingImage); - const reader = new FileReader(); - reader.onloadend = function (e) { - loadSvgString(e.target.result); - updateCanvas(); - }; - reader.readAsText(f.files[0]); - } - }); + const open = $('').click(async function () { + const ok = await editor.openPrep(); + if (!ok) { return; } + svgCanvas.clear(); + if (this.files.length === 1) { + $.process_cancel(uiStrings.notification.loadingImage); + const reader = new FileReader(); + reader.onloadend = async function (e) { + await loadSvgString(e.target.result); + updateCanvas(); + }; + reader.readAsText(this.files[0]); + } }); $('#tool_open').show().prepend(open); @@ -5701,23 +6181,21 @@ editor.init = function () { $('#tool_import').show().prepend(imgImport); } - // $(function () { updateCanvas(true); - // }); - // const revnums = 'svg-editor.js ($Rev$) '; // revnums += svgCanvas.getVersion(); // $('#copyright')[0].setAttribute('title', revnums); + const loadedExtensionNames = []; /** * @function module:SVGEditor.setLang * @param {string} lang The language code * @param {module:locale.LocaleStrings} allStrings See {@tutorial LocaleDocs} * @fires module:svgcanvas.SvgCanvas#event:ext-langReady * @fires module:svgcanvas.SvgCanvas#event:ext-langChanged - * @returns {undefined} + * @returns {Promise} A Promise which resolves to `undefined` */ - const setLang = editor.setLang = function (lang, allStrings) { + const setLang = editor.setLang = async function (lang, allStrings) { editor.langChanged = true; $.pref('lang', lang); $('#lang_select').val(lang); @@ -5741,16 +6219,25 @@ editor.init = function () { // In case extensions loaded before the locale, now we execute a callback on them if (extsPreLang.length) { - while (extsPreLang.length) { - const ext = extsPreLang.shift(); - ext.langReady({ + await Promise.all(extsPreLang.map((ext) => { + loadedExtensionNames.push(ext.name); + return ext.langReady({ lang, uiStrings, importLocale: getImportLocale({defaultLang: lang, defaultName: ext.name}) }); - } + })); + extsPreLang.length = 0; } else { - svgCanvas.runExtensions('langReady', /** @type {module:svgcanvas.SvgCanvas#event:ext-langReady} */ {lang, uiStrings}); + loadedExtensionNames.forEach((loadedExtensionName) => { + this.runExtension( + loadedExtensionName, + 'langReady', + /** @type {module:svgcanvas.SvgCanvas#event:ext-langReady} */ { + lang, uiStrings, importLocale: getImportLocale({defaultLang: lang, defaultName: loadedExtensionName}) + } + ); + }); } svgCanvas.runExtensions('langChanged', /** @type {module:svgcanvas.SvgCanvas#event:ext-langChanged} */ lang); @@ -5780,9 +6267,9 @@ editor.init = function () { */ { /** - * Gets an array of results from extensions with a `addLangData` method + * Gets an array of results from extensions with a `addLangData` method, * returning an object with a `data` property set to its locales (to be - * merged with regular locales) + * merged with regular locales). * @param {string} langParam * @fires module:svgcanvas.SvgCanvas#event:ext-addLangData * @todo Can we forego this in favor of `langReady` (or forego `langReady`)? @@ -5794,8 +6281,7 @@ editor.init = function () { /** * @function * @type {module:svgcanvas.ExtensionVarBuilder} - * @param {string} defaultLang - * @param {string} defaultName + * @param {string} name * @returns {module:svgcanvas.SvgCanvas#event:ext-addLangData} */ (name) => { // We pass in a function as we don't know the extension name here when defining this `addLangData` method @@ -5815,53 +6301,75 @@ editor.init = function () { if (document.location.protocol === 'file:') { setTimeout(extAndLocaleFunc, 100); } else { - // Returns a promise (if we wanted to fire 'extensions-loaded' event, potentially useful to hide interface as some extension locales are only available after this) + // Returns a promise (if we wanted to fire 'extensions-loaded' event, + // potentially useful to hide interface as some extension locales + // are only available after this) extAndLocaleFunc(); } }; /** * @callback module:SVGEditor.ReadyCallback -* @returns {undefined} +* @returns {Promise|undefined} */ /** * Queues a callback to be invoked when the editor is ready (or * to be invoked immediately if it is already ready--i.e., -* if `svgEditor.runCallbacks` has been run) +* if `runCallbacks` has been run). * @param {module:SVGEditor.ReadyCallback} cb Callback to be queued to invoke -* @returns {undefined} +* @returns {Promise} Resolves when all callbacks, including the supplied have resolved */ -editor.ready = function (cb) { - if (!isReady) { - callbacks.push(cb); - } else { - cb(); - } +editor.ready = function (cb) { // eslint-disable-line promise/prefer-await-to-callbacks + return new Promise((resolve, reject) => { // eslint-disable-line promise/avoid-new + if (isReady) { + resolve(cb()); // eslint-disable-line callback-return, promise/prefer-await-to-callbacks + return; + } + callbacks.push([cb, resolve, reject]); + }); }; /** * Invokes the callbacks previous set by `svgEditor.ready` -* @returns {undefined} +* @returns {Promise} Resolves to `undefined` if all callbacks succeeded and rejects otherwise */ -editor.runCallbacks = function () { - callbacks.forEach((cb) => { - cb(); +editor.runCallbacks = async function () { + try { + await Promise.all(callbacks.map(([cb]) => { + return cb(); // eslint-disable-line promise/prefer-await-to-callbacks + })); + } catch (err) { + callbacks.forEach(([, , reject]) => { + reject(); + }); + throw err; + } + callbacks.forEach(([, resolve]) => { + resolve(); }); isReady = true; }; /** * @param {string} str The SVG string to load -* @returns {undefined} +* @param {PlainObject} [opts={}] +* @param {boolean} [opts.noAlert=false] Option to avoid alert to user and instead get rejected promise +* @returns {Promise} */ -editor.loadFromString = function (str) { - editor.ready(function () { - loadSvgString(str); +editor.loadFromString = function (str, {noAlert} = {}) { + editor.ready(async function () { + try { + await loadSvgString(str, {noAlert}); + } catch (err) { + if (noAlert) { + throw err; + } + } }); }; /** -* Not presently in use +* Not presently in use. * @param {PlainObject} featList * @returns {undefined} */ @@ -5879,77 +6387,84 @@ editor.disableUI = function (featList) { */ /** * @param {string} url URL from which to load an SVG string via Ajax -* @param {PlainObject} [opts] May contain properties: `cache`, `callback` -* @param {boolean} opts.cache -* @param {module:SVGEditor.URLLoadCallback} opts.callback Invoked with `true` or `false` depending on success -* @returns {undefined} +* @param {PlainObject} [opts={}] May contain properties: `cache`, `callback` +* @param {boolean} [opts.cache] +* @param {boolean} [opts.noAlert] +* @returns {Promise} Resolves to `undefined` or rejects upon bad loading of +* the SVG (or upon failure to parse the loaded string) when `noAlert` is +* enabled */ -editor.loadFromURL = function (url, opts) { - if (!opts) { opts = {}; } - - const {cache, callback: cb} = opts; - - editor.ready(function () { - $.ajax({ - url, - dataType: 'text', - cache: !!cache, - beforeSend () { - $.process_cancel(uiStrings.notification.loadingImage); - }, - success (str) { - loadSvgString(str, cb); - }, - error (xhr, stat, err) { - if (xhr.status !== 404 && xhr.responseText) { - loadSvgString(xhr.responseText, cb); - } else { - $.alert(uiStrings.notification.URLloadFail + ': \n' + err, cb); +editor.loadFromURL = function (url, {cache, noAlert} = {}) { + return editor.ready(function () { + return new Promise((resolve, reject) => { // eslint-disable-line promise/avoid-new + $.ajax({ + url, + dataType: 'text', + cache: Boolean(cache), + beforeSend () { + $.process_cancel(uiStrings.notification.loadingImage); + }, + success (str) { + resolve(loadSvgString(str, {noAlert})); + }, + error (xhr, stat, err) { + if (xhr.status !== 404 && xhr.responseText) { + resolve(loadSvgString(xhr.responseText, {noAlert})); + return; + } + if (noAlert) { + reject(new Error('URLLoadFail')); + return; + } + $.alert(uiStrings.notification.URLLoadFail + ': \n' + err); + resolve(); + }, + complete () { + $('#dialog_box').hide(); } - }, - complete () { - $('#dialog_box').hide(); - } + }); }); }); }; /** * @param {string} str The Data URI to base64-decode (if relevant) and load -* @returns {undefined} +* @param {PlainObject} [opts={}] +* @param {boolean} [opts.noAlert] +* @returns {Promise} Resolves to `undefined` and rejects if loading SVG string fails and `noAlert` is enabled */ -editor.loadFromDataURI = function (str) { +editor.loadFromDataURI = function (str, {noAlert} = {}) { editor.ready(function () { let base64 = false; let pre = str.match(/^data:image\/svg\+xml;base64,/); if (pre) { base64 = true; } else { - pre = str.match(/^data:image\/svg\+xml(?:;(?:utf8)?)?,/); + pre = str.match(/^data:image\/svg\+xml(?:;|;utf8)?,/); } if (pre) { pre = pre[0]; } const src = str.slice(pre.length); - loadSvgString(base64 ? Utils.decode64(src) : decodeURIComponent(src)); + return loadSvgString(base64 ? Utils.decode64(src) : decodeURIComponent(src), {noAlert}); }); }; /** * @param {string} name Used internally; no need for i18n. * @param {module:svgcanvas.ExtensionInitCallback} init Config to be invoked on this module - * @param {module:SVGEditor~ImportLocale} importLocale Importer defaulting to pth with current extension name and locale + * @param {module:svgcanvas.ExtensionInitArgs} initArgs * @throws {Error} If called too early * @returns {Promise} Resolves to `undefined` */ -editor.addExtension = function (name, init, importLocale) { +editor.addExtension = function (name, init, initArgs) { // Note that we don't want this on editor.ready since some extensions // may want to run before then (like server_opensave). // $(function () { if (!svgCanvas) { throw new Error('Extension added too early'); } - return svgCanvas.addExtension.call(this, name, init, importLocale); + return svgCanvas.addExtension.call(this, name, init, initArgs); // }); }; @@ -5962,12 +6477,13 @@ editor.ready(() => { let extensionsAdded = false; const messageQueue = []; /** - * @param {Any} data - * @param {string} origin + * @param {PlainObject} info + * @param {Any} info.data + * @param {string} info.origin * @fires module:svgcanvas.SvgCanvas#event:message * @returns {undefined} */ -const messageListener = ({data, origin}) => { +const messageListener = ({data, origin}) => { // eslint-disable-line no-shadow // console.log('data, origin, extensionsAdded', data, origin, extensionsAdded); const messageObj = {data, origin}; if (!extensionsAdded) { @@ -5982,9 +6498,15 @@ window.addEventListener('message', messageListener); // Run init once DOM is loaded // jQuery(editor.init); -Promise.resolve().then(() => { + +(async () => { +try { // We wait a micro-task to let the svgEditor variable be defined for module checks + await Promise.resolve(); editor.init(); -}); +} catch (err) { + console.error(err); // eslint-disable-line no-console +} +})(); export default editor; diff --git a/editor/svgcanvas.js b/editor/svgcanvas.js index 2d5c25dd..91c63f2d 100644 --- a/editor/svgcanvas.js +++ b/editor/svgcanvas.js @@ -1,4 +1,4 @@ -/* eslint-disable indent */ +/* eslint-disable indent, unicorn/no-fn-reference-in-iterator */ /* globals jQuery, jsPDF */ /** * Numerous tools for working with the editor's "canvas" @@ -18,9 +18,15 @@ // Todo: Obtain/adapt latest jsPDF to utilize ES Module for `jsPDF`/avoid global import './svgpathseg.js'; -import jqPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr` - -import * as draw from './draw.js'; +import jQueryPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr` +import jQueryPluginDBox from './dbox.js'; +import * as draw from './draw.js'; // eslint-disable-line import/no-duplicates +import { // eslint-disable-line no-duplicate-imports + identifyLayers, createLayer, cloneLayer, deleteCurrentLayer, + setCurrentLayer, renameCurrentLayer, setCurrentLayerPosition, + setLayerVisibility, moveSelectedToLayer, mergeLayer, mergeAllLayers, + leaveContext, setContext +} from './draw.js'; // eslint-disable-line import/no-duplicates import * as pathModule from './path.js'; import {sanitizeSvg} from './sanitize.js'; import {getReverseNS, NS} from './namespaces.js'; @@ -31,10 +37,11 @@ import { preventClickDefault, snapToGrid, walkTree, walkTreePost, getBBoxOfElementAsPath, convertToPath, toXml, encode64, decode64, dataURLToObjectURL, createObjectURL, - getVisibleElements, - init as utilsInit, getBBox as utilsGetBBox, getStrokedBBoxDefaultVisible + getVisibleElements, dropXMLInteralSubset, + init as utilsInit, getBBox as utilsGetBBox, getStrokedBBoxDefaultVisible, + isNullish } from './utilities.js'; -import * as history from './history.js'; +import * as hstry from './history.js'; import { transformPoint, matrixMultiply, hasMatrixTransform, transformListToTransform, getMatrix, snapToAngle, isIdentity, rectsIntersect, transformBox @@ -60,28 +67,29 @@ import { } from './recalculate.js'; import { getSelectorManager, + Selector, init as selectInit } from './select.js'; -const $ = jqPluginSVG(jQuery); +let $ = jQueryPluginSVG(jQuery); const { MoveElementCommand, InsertElementCommand, RemoveElementCommand, ChangeElementCommand, BatchCommand, UndoManager, HistoryEventTypes -} = history; +} = hstry; if (!window.console) { window.console = {}; - window.console.log = function (str) {}; - window.console.dir = function (str) {}; + window.console.log = function (str) { /* */ }; + window.console.dir = function (str) { /* */ }; } if (window.opera) { window.console.log = function (str) { window.opera.postError(str); }; - window.console.dir = function (str) {}; + window.console.dir = function (str) { /* */ }; } /** -* The main SvgCanvas class that manages all SVG-related functions +* The main SvgCanvas class that manages all SVG-related functions. * @memberof module:svgcanvas * * @borrows module:coords.remapElement as #remapElement @@ -131,7 +139,7 @@ if (config) { // Array with width/height of canvas const {dimensions} = curConfig; -const canvas = this; +const canvas = this; // eslint-disable-line consistent-this // "document" element associated with the container (same as window.document using default svg-editor.js) // NOTE: This is not actually a SVG document, but an HTML document. @@ -200,7 +208,7 @@ clearSvgContentElement(); let idprefix = 'svg_'; /** -* Changes the ID prefix to the given value +* Changes the ID prefix to the given value. * @function module:svgcanvas.SvgCanvas#setIdPrefix * @param {string} p - String with the new prefix * @returns {undefined} @@ -303,7 +311,7 @@ const getJsonFromSvgElement = this.getJsonFromSvgElement = function (data) { }; /** -* This should really be an intersection implementing all rather than a union +* This should really be an intersection implementing all rather than a union. * @function module:svgcanvas.SvgCanvas#addSVGElementFromJson * @implements {module:utilities.EditorContext#addSVGElementFromJson|module:path.EditorContext#addSVGElementFromJson} */ @@ -382,13 +390,13 @@ unitsInit( canvas.convertToNum = convertToNum; /** -* This should really be an intersection implementing all rather than a union +* This should really be an intersection implementing all rather than a union. * @implements {module:draw.DrawCanvasInit#getSVGContent|module:utilities.EditorContext#getSVGContent} */ const getSVGContent = () => { return svgcontent; }; /** -* Should really be an intersection with all needing to apply rather than a union +* Should really be an intersection with all needing to apply rather than a union. * @function module:svgcanvas.SvgCanvas#getSelectedElements * @implements {module:utilities.EditorContext#getSelectedElements|module:draw.DrawCanvasInit#getSelectedElements|module:path.EditorContext#getSelectedElements} */ @@ -396,10 +404,10 @@ const getSelectedElements = this.getSelectedElems = function () { return selectedElements; }; -const pathActions = pathModule.pathActions; +const {pathActions} = pathModule; /** -* This should actually be an intersection as all interfaces should be met +* This should actually be an intersection as all interfaces should be met. * @implements {module:utilities.EditorContext#getSVGRoot|module:recalculate.EditorContext#getSVGRoot|module:coords.EditorContext#getSVGRoot|module:path.EditorContext#getSVGRoot} */ const getSVGRoot = () => svgroot; @@ -435,7 +443,7 @@ canvas.assignAttributes = assignAttributes; this.cleanupElement = cleanupElement; /** -* This should actually be an intersection not a union as all should apply +* This should actually be an intersection not a union as all should apply. * @implements {module:coords.EditorContext|module:path.EditorContext} */ const getGridSnapping = () => { return curConfig.gridSnapping; }; @@ -503,8 +511,8 @@ const undoMgr = canvas.undoMgr = new UndoManager({ } if (cmdType === InsertElementCommand.type()) { if (isApply) { restoreRefElems(cmd.elem); } - } else { - if (!isApply) { restoreRefElems(cmd.elem); } + } else if (!isApply) { + restoreRefElems(cmd.elem); } if (cmd.elem.tagName === 'use') { setUseData(cmd.elem); @@ -541,7 +549,7 @@ const undoMgr = canvas.undoMgr = new UndoManager({ }); /** -* This should really be an intersection applying to all types rather than a union +* This should really be an intersection applying to all types rather than a union. * @function module:svgcanvas~addCommandToHistory * @implements {module:path.EditorContext#addCommandToHistory|module:draw.DrawCanvasInit#addCommandToHistory} */ @@ -550,7 +558,7 @@ const addCommandToHistory = function (cmd) { }; /** -* This should really be an intersection applying to all types rather than a union +* This should really be an intersection applying to all types rather than a union. * @function module:svgcanvas.SvgCanvas#getZoom * @implements {module:path.EditorContext#getCurrentZoom|module:select.SVGFactory#getCurrentZoom} */ @@ -562,7 +570,7 @@ const getCurrentZoom = this.getZoom = function () { return currentZoom; }; * @implements {module:path.EditorContext#round} */ const round = this.round = function (val) { - return parseInt(val * currentZoom, 10) / currentZoom; + return parseInt(val * currentZoom) / currentZoom; }; selectInit( @@ -602,29 +610,30 @@ const getId = canvas.getId = function () { }; /** -* The "implements" should really be an intersection applying to all types rather than a union +* The "implements" should really be an intersection applying to all types rather than a union. * @function module:svgcanvas.SvgCanvas#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 {module:svgcanvas.SvgCanvas#event:GenericCanvasEvent} arg - Argument to pass through to the callback function. -* @returns {undefined} +* @returns {module:svgcanvas.EventHandlerReturn|undefined} */ const call = function (ev, arg) { if (events[ev]) { return events[ev](window, arg); } + return undefined; }; /** * Clears the selection. The 'selected' handler is then optionally called. -* This should really be an intersection applying to all types rather than a union +* This should really be an intersection applying to all types rather than a union. * @function module:svgcanvas.SvgCanvas#clearSelection * @implements {module:draw.DrawCanvasInit#clearSelection|module:path.EditorContext#clearSelection} * @fires module:svgcanvas.SvgCanvas#event:selected */ const clearSelection = this.clearSelection = function (noCall) { selectedElements.forEach((elem) => { - if (elem == null) { + if (isNullish(elem)) { return; } selectorManager.releaseSelector(elem); @@ -646,7 +655,7 @@ const addToSelection = this.addToSelection = function (elemsToAdd, showGrips) { let j = 0; while (j < selectedElements.length) { - if (selectedElements[j] == null) { + if (isNullish(selectedElements[j])) { break; } ++j; @@ -692,15 +701,16 @@ const addToSelection = this.addToSelection = function (elemsToAdd, showGrips) { selectedElements.sort(function (a, b) { if (a && b && a.compareDocumentPosition) { - return 3 - (b.compareDocumentPosition(a) & 6); + return 3 - (b.compareDocumentPosition(a) & 6); // eslint-disable-line no-bitwise } - if (a == null) { + if (isNullish(a)) { return 1; } + return 0; }); // Make sure first elements are not null - while (selectedElements[0] == null) { + while (isNullish(selectedElements[0])) { selectedElements.shift(0); } }; @@ -717,7 +727,7 @@ const getOpacity = function () { * @implements {module:path.EditorContext#getMouseTarget} */ const getMouseTarget = this.getMouseTarget = function (evt) { - if (evt == null) { + if (isNullish(evt)) { return null; } let mouseTarget = evt.target; @@ -814,10 +824,12 @@ pathModule.init( return rubberBox; }, /** - * @param {boolean} closedSubpath - * @param {SVGCircleElement[]} grips + * @param {PlainObject} ptsInfo + * @param {boolean} ptsInfo.closedSubpath + * @param {SVGCircleElement[]} ptsInfo.grips * @fires module:svgcanvas.SvgCanvas#event:pointsAdded * @fires module:svgcanvas.SvgCanvas#event:selected + * @returns {undefined} */ addPtsToSelection ({closedSubpath, grips}) { // TODO: Correct this: @@ -827,8 +839,9 @@ pathModule.init( call('selected', grips); }, /** - * @param {ChangeElementCommand} cmd - * @param {SVGPathElement} elem + * @param {PlainObject} changes + * @param {ChangeElementCommand} changes.cmd + * @param {SVGPathElement} changes.elem * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ @@ -878,8 +891,7 @@ $(opacAni).attr({ const restoreRefElems = function (elem) { // Look for missing reference elements, restore any found const attrs = $(elem).attr(refAttrs); - for (const o in attrs) { - const val = attrs[o]; + Object.values(attrs).forEach((val) => { if (val && val.startsWith('url(')) { const id = getUrlFromAttr(val).substr(1); const ref = getElem(id); @@ -888,7 +900,7 @@ const restoreRefElems = function (elem) { delete removedElements[id]; } } - } + }); const childs = elem.getElementsByTagName('*'); @@ -970,6 +982,9 @@ let // Canvas point for the most recent right click lastClickPoint = null; +this.runExtension = function (name, action, vars) { + return this.runExtensions(action, vars, false, (n) => n === name); +}; /** * @typedef {module:svgcanvas.ExtensionMouseDownStatus|module:svgcanvas.ExtensionMouseUpStatus|module:svgcanvas.ExtensionIDsUpdatedStatus|module:locale.ExtensionLocaleData[]|undefined} module:svgcanvas.ExtensionStatus * @tutorial ExtensionDocs @@ -977,6 +992,12 @@ let /** * @callback module:svgcanvas.ExtensionVarBuilder * @param {string} name The name of the extension +* @returns {module:svgcanvas.SvgCanvas#event:ext-addLangData} +*/ +/** +* @callback module:svgcanvas.ExtensionNameFilter +* @param {string} name +* @returns {boolean} */ /** * @todo Consider: Should this return an array by default, so extension results aren't overwritten? @@ -985,11 +1006,15 @@ let * @param {"mouseDown"|"mouseMove"|"mouseUp"|"zoomChanged"|"IDsUpdated"|"canvasUpdated"|"toolButtonStateUpdate"|"selectedChanged"|"elementTransition"|"elementChanged"|"langReady"|"langChanged"|"addLangData"|"onNewDocument"|"workareaResized"} action * @param {module:svgcanvas.SvgCanvas#event:ext-mouseDown|module:svgcanvas.SvgCanvas#event:ext-mouseMove|module:svgcanvas.SvgCanvas#event:ext-mouseUp|module:svgcanvas.SvgCanvas#event:ext-zoomChanged|module:svgcanvas.SvgCanvas#event:ext-IDsUpdated|module:svgcanvas.SvgCanvas#event:ext-canvasUpdated|module:svgcanvas.SvgCanvas#event:ext-toolButtonStateUpdate|module:svgcanvas.SvgCanvas#event:ext-selectedChanged|module:svgcanvas.SvgCanvas#event:ext-elementTransition|module:svgcanvas.SvgCanvas#event:ext-elementChanged|module:svgcanvas.SvgCanvas#event:ext-langReady|module:svgcanvas.SvgCanvas#event:ext-langChanged|module:svgcanvas.SvgCanvas#event:ext-addLangData|module:svgcanvas.SvgCanvas#event:ext-onNewDocument|module:svgcanvas.SvgCanvas#event:ext-workareaResized|module:svgcanvas.ExtensionVarBuilder} [vars] * @param {boolean} [returnArray] +* @param {module:svgcanvas.ExtensionNameFilter} nameFilter * @returns {GenericArray.|module:svgcanvas.ExtensionStatus|false} See {@tutorial ExtensionDocs} on the ExtensionStatus. */ -const runExtensions = this.runExtensions = function (action, vars, returnArray) { +const runExtensions = this.runExtensions = function (action, vars, returnArray, nameFilter) { let result = returnArray ? [] : false; $.each(extensions, function (name, ext) { + if (nameFilter && !nameFilter(name)) { + return; + } if (ext && action in ext) { if (typeof vars === 'function') { vars = vars(name); // ext, action @@ -1102,6 +1127,7 @@ const runExtensions = this.runExtensions = function (action, vars, returnArray) */ /** * @function module:svgcanvas.ExtensionInitResponse#callback + * @this module:SVGEditor * @param {module:svgcanvas.SvgCanvas#event:ext-callback} arg * @returns {undefined} */ @@ -1113,53 +1139,56 @@ const runExtensions = this.runExtensions = function (action, vars, returnArray) * @returns {Promise} Resolves to [ExtensionInitResponse]{@link module:svgcanvas.ExtensionInitResponse} or `undefined` */ /** -* Add an extension to the editor +* @typedef {PlainObject} module:svgcanvas.ExtensionInitArgs +* @param {external:jQuery} initArgs.$ +* @param {module:SVGEditor~ImportLocale} initArgs.importLocale +*/ +/** +* Add an extension to the editor. * @function module:svgcanvas.SvgCanvas#addExtension * @param {string} name - String with the ID of the extension. Used internally; no need for i18n. * @param {module:svgcanvas.ExtensionInitCallback} [extInitFunc] - Function supplied by the extension with its data -* @param {module:SVGEditor~ImportLocale} importLocale +* @param {module:svgcanvas.ExtensionInitArgs} initArgs * @fires module:svgcanvas.SvgCanvas#event:extension_added -* @throws {TypeError} If `extInitFunc` is not a function +* @throws {TypeError|Error} `TypeError` if `extInitFunc` is not a function, `Error` +* if extension of supplied name already exists * @returns {Promise} Resolves to `undefined` */ -this.addExtension = async function (name, extInitFunc, importLocale) { +this.addExtension = async function (name, extInitFunc, {$: jq, importLocale}) { if (typeof extInitFunc !== 'function') { throw new TypeError('Function argument expected for `svgcanvas.addExtension`'); } - let extObj = {}; - if (!(name in extensions)) { - // Provide private vars/funcs here. Is there a better way to do this? - /** - * @typedef {module:svgcanvas.PrivateMethods} module:svgcanvas.ExtensionArgumentObject - * @property {SVGSVGElement} svgroot See {@link module:svgcanvas~svgroot} - * @property {SVGSVGElement} svgcontent See {@link module:svgcanvas~svgcontent} - * @property {!(string|Integer)} nonce See {@link module:draw.Drawing#getNonce} - * @property {module:select.SelectorManager} selectorManager - * @property {module:SVGEditor~ImportLocale} importLocale - */ - /** - * @type {module:svgcanvas.ExtensionArgumentObject} - * @see {@link module:svgcanvas.PrivateMethods} source for the other methods/properties - */ - const argObj = $.extend(canvas.getPrivateMethods(), { - importLocale, - svgroot, - svgcontent, - nonce: getCurrentDrawing().getNonce(), - selectorManager - }); - if (extInitFunc) { - extObj = await extInitFunc(argObj); - } - if (extObj) { - extObj.name = name; - } - - extensions[name] = extObj; - return call('extension_added', extObj); - } else { - console.log('Cannot add extension "' + name + '", an extension by that name already exists.'); + if (name in extensions) { + throw new Error('Cannot add extension "' + name + '", an extension by that name already exists.'); } + // Provide private vars/funcs here. Is there a better way to do this? + /** + * @typedef {module:svgcanvas.PrivateMethods} module:svgcanvas.ExtensionArgumentObject + * @property {SVGSVGElement} svgroot See {@link module:svgcanvas~svgroot} + * @property {SVGSVGElement} svgcontent See {@link module:svgcanvas~svgcontent} + * @property {!(string|Integer)} nonce See {@link module:draw.Drawing#getNonce} + * @property {module:select.SelectorManager} selectorManager + * @property {module:SVGEditor~ImportLocale} importLocale + */ + /** + * @type {module:svgcanvas.ExtensionArgumentObject} + * @see {@link module:svgcanvas.PrivateMethods} source for the other methods/properties + */ + const argObj = $.extend(canvas.getPrivateMethods(), { + $: jq, + importLocale, + svgroot, + svgcontent, + nonce: getCurrentDrawing().getNonce(), + selectorManager + }); + const extObj = await extInitFunc(argObj); + if (extObj) { + extObj.name = name; + } + + extensions[name] = extObj; + return call('extension_added', extObj); }; /** @@ -1169,13 +1198,13 @@ this.addExtension = async function (name, extInitFunc, importLocale) { * We brute-force `getIntersectionList` for browsers that do not support it (Firefox). * * Reference: -* Firefox does not implement `getIntersectionList()`, see {@link https://bugzilla.mozilla.org/show_bug.cgi?id=501421} +* Firefox does not implement `getIntersectionList()`, see {@link https://bugzilla.mozilla.org/show_bug.cgi?id=501421}. * @function module:svgcanvas.SvgCanvas#getIntersectionList * @param {SVGRect} rect * @returns {Element[]|NodeList} Bbox elements */ const getIntersectionList = this.getIntersectionList = function (rect) { - if (rubberBox == null) { return null; } + if (isNullish(rubberBox)) { return null; } const parent = currentGroup || getCurrentDrawing().getCurrentLayer(); @@ -1184,9 +1213,9 @@ const getIntersectionList = this.getIntersectionList = function (rect) { rubberBBox = rubberBox.getBBox(); const bb = svgcontent.createSVGRect(); - for (const o in rubberBBox) { + ['x', 'y', 'width', 'height', 'top', 'right', 'bottom', 'left'].forEach((o) => { bb[o] = rubberBBox[o] / currentZoom; - } + }); rubberBBox = bb; } else { rubberBBox = svgcontent.createSVGRect(); @@ -1197,17 +1226,17 @@ const getIntersectionList = this.getIntersectionList = function (rect) { } let resultList = null; - if (!isIE) { + if (!isIE()) { if (typeof svgroot.getIntersectionList === 'function') { // Offset the bbox of the rubber box by the offset of the svgcontent element. - rubberBBox.x += parseInt(svgcontent.getAttribute('x'), 10); - rubberBBox.y += parseInt(svgcontent.getAttribute('y'), 10); + rubberBBox.x += parseInt(svgcontent.getAttribute('x')); + rubberBBox.y += parseInt(svgcontent.getAttribute('y')); resultList = svgroot.getIntersectionList(rubberBBox, parent); } } - if (resultList == null || typeof resultList.item !== 'function') { + if (isNullish(resultList) || typeof resultList.item !== 'function') { resultList = []; if (!curBBoxes.length) { @@ -1242,7 +1271,7 @@ this.getVisibleElements = getVisibleElements; /** * Get all elements that have a BBox (excludes ``, ``, etc). * Note that 0-opacity, off-screen etc elements are still considered "visible" -* for this function +* for this function. * @function module:svgcanvas.SvgCanvas#getVisibleElementsAndBBoxes * @param {Element} parent - The parent DOM element to search within * @returns {ElementAndBBox[]} An array with objects that include: @@ -1261,7 +1290,7 @@ const getVisibleElementsAndBBoxes = this.getVisibleElementsAndBBoxes = function }; /** -* Wrap an SVG element into a group element, mark the group as 'gsvg' +* Wrap an SVG element into a group element, mark the group as 'gsvg'. * @function module:svgcanvas.SvgCanvas#groupSvgElem * @param {Element} elem - SVG element to wrap * @returns {undefined} @@ -1384,15 +1413,22 @@ canvas.call = call; * @type {module:svgcanvas.SvgCanvas#event:selected|module:svgcanvas.SvgCanvas#event:changed|module:svgcanvas.SvgCanvas#event:contextset|module:svgcanvas.SvgCanvas#event:pointsAdded|module:svgcanvas.SvgCanvas#event:extension_added|module:svgcanvas.SvgCanvas#event:extensions_added|module:svgcanvas.SvgCanvas#event:message|module:svgcanvas.SvgCanvas#event:transition|module:svgcanvas.SvgCanvas#event:zoomed|module:svgcanvas.SvgCanvas#event:updateCanvas|module:svgcanvas.SvgCanvas#event:saved|module:svgcanvas.SvgCanvas#event:exported|module:svgcanvas.SvgCanvas#event:exportedPDF|module:svgcanvas.SvgCanvas#event:setnonce|module:svgcanvas.SvgCanvas#event:unsetnonce|undefined} */ +/** + * The promise return, if present, resolves to `undefined` + * (`extension_added`, `exported`, `saved`) + * @typedef {Promise|undefined} module:svgcanvas.EventHandlerReturn +*/ + /** * @callback module:svgcanvas.EventHandler * @param {external:Window} win * @param {module:svgcanvas.SvgCanvas#event:GenericCanvasEvent} arg * @listens module:svgcanvas.SvgCanvas#event:GenericCanvasEvent +* @returns {module:svgcanvas.EventHandlerReturn} */ /** -* Attaches a callback function to an event +* Attaches a callback function to an event. * @function module:svgcanvas.SvgCanvas#bind * @param {"changed"|"contextset"|"selected"|"pointsAdded"|"extension_added"|"extensions_added"|"message"|"transition"|"zoomed"|"updateCanvas"|"zoomDone"|"saved"|"exported"|"exportedPDF"|"setnonce"|"unsetnonce"|"cleared"} ev - String indicating the name of the event * @param {module:svgcanvas.EventHandler} f - The callback function to bind to the event @@ -1451,7 +1487,7 @@ const ffClone = function (elem) { /** * Removes any old rotations if present, prepends a new rotation at the -* transformed center +* transformed center. * @function module:svgcanvas.SvgCanvas#setRotationAngle * @param {string|Float} val - The new rotation angle in degrees * @param {boolean} preventUndo - Indicates whether the action should be undoable or not @@ -1502,12 +1538,12 @@ this.setRotationAngle = function (val, preventUndo) { // } const selector = selectorManager.requestSelector(selectedElements[0]); selector.resize(); - selector.updateGripCursors(val); + Selector.updateGripCursors(val); }; /** * Runs `recalculateDimensions` on the selected elements, -* adding the changes to a single batch command +* adding the changes to a single batch command. * @function module:svgcanvas.SvgCanvas#recalculateAllSelectedDimensions * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} @@ -1533,13 +1569,13 @@ const recalculateAllSelectedDimensions = this.recalculateAllSelectedDimensions = }; /** - * Debug tool to easily see the current matrix in the browser's console + * Debug tool to easily see the current matrix in the browser's console. * @function module:svgcanvas~logMatrix * @param {SVGMatrix} m The matrix * @returns {undefined} */ const logMatrix = function (m) { - console.log([m.a, m.b, m.c, m.d, m.e, m.f]); + console.log([m.a, m.b, m.c, m.d, m.e, m.f]); // eslint-disable-line no-console }; // Root Current Transformation Matrix in user units @@ -1552,7 +1588,7 @@ let rootSctm = null; // TODO: do we need to worry about selectedBBoxes here? /** -* Selects only the given elements, shortcut for clearSelection(); addToSelection() +* Selects only the given elements, shortcut for `clearSelection(); addToSelection()`. * @function module:svgcanvas.SvgCanvas#selectOnly * @param {Element[]} elems - an array of DOM elements to be selected * @param {boolean} showGrips - Indicates whether the resize grips should be shown @@ -1573,7 +1609,7 @@ const selectOnly = this.selectOnly = function (elems, showGrips) { * @returns {undefined} */ /* const removeFromSelection = */ this.removeFromSelection = function (elemsToRemove) { - if (selectedElements[0] == null) { return; } + if (isNullish(selectedElements[0])) { return; } if (!elemsToRemove.length) { return; } // find every element and remove it from our array copy @@ -1671,10 +1707,11 @@ const getBsplinePoint = function (t) { }; }; /** + * Follows these conditions: * - When we are in a create mode, the element is added to the canvas but the * action is not recorded until mousing up. * - When we are in select mode, select the element, remember the position - * and do nothing else + * and do nothing else. * @param {MouseEvent} evt * @fires module:svgcanvas.SvgCanvas#event:ext-mouseDown * @returns {undefined} @@ -1730,7 +1767,7 @@ const mouseDown = function (evt) { // if it is a selector grip, then it must be a single element selected, // set the mouseTarget to that and update the mode to rotate/resize - if (mouseTarget === selectorManager.selectorParentGroup && selectedElements[0] != null) { + if (mouseTarget === selectorManager.selectorParentGroup && !isNullish(selectedElements[0])) { const grip = evt.target; const griptype = elData(grip, 'type'); // rotating @@ -1745,7 +1782,7 @@ const mouseDown = function (evt) { } startTransform = mouseTarget.getAttribute('transform'); - let i, strokeW; + const tlist = getTransformList(mouseTarget); switch (currentMode) { case 'select': @@ -1771,8 +1808,8 @@ const mouseDown = function (evt) { if (!rightClick) { // insert a dummy transform so if the element(s) are moved it will have // a transform to use for its translate - for (i = 0; i < selectedElements.length; ++i) { - if (selectedElements[i] == null) { continue; } + for (let i = 0; i < selectedElements.length; ++i) { + if (isNullish(selectedElements[i])) { continue; } const slist = getTransformList(selectedElements[i]); if (slist.numberOfItems) { slist.insertItemBefore(svgroot.createSVGTransform(), 0); @@ -1784,7 +1821,7 @@ const mouseDown = function (evt) { } else if (!rightClick) { clearSelection(); currentMode = 'multiselect'; - if (rubberBox == null) { + if (isNullish(rubberBox)) { rubberBox = selectorManager.getRubberBandBox(); } rStartX *= currentZoom; @@ -1805,7 +1842,7 @@ const mouseDown = function (evt) { break; case 'zoom': started = true; - if (rubberBox == null) { + if (isNullish(rubberBox)) { rubberBox = selectorManager.getRubberBandBox(); } assignAttributes(rubberBox, { @@ -1816,7 +1853,7 @@ const mouseDown = function (evt) { display: 'inline' }, 100); break; - case 'resize': + case 'resize': { started = true; startX = x; startY = y; @@ -1853,10 +1890,10 @@ const mouseDown = function (evt) { let delayedStroke; if (iswebkit) { delayedStroke = function (ele) { - const _stroke = ele.getAttributeNS(null, 'stroke'); - ele.removeAttributeNS(null, 'stroke'); + const stroke_ = ele.getAttribute('stroke'); + ele.removeAttribute('stroke'); // Re-apply stroke after delay. Anything higher than 1 seems to cause flicker - if (_stroke !== null) setTimeout(function () { ele.setAttributeNS(null, 'stroke', _stroke); }, 0); + if (stroke_ !== null) setTimeout(function () { ele.setAttribute('stroke', stroke_); }, 0); }; } mouseTarget.style.vectorEffect = 'non-scaling-stroke'; @@ -1864,7 +1901,7 @@ const mouseDown = function (evt) { const all = mouseTarget.getElementsByTagName('*'), len = all.length; - for (i = 0; i < len; i++) { + for (let i = 0; i < len; i++) { if (!all[i].style) { // mathML continue; } @@ -1874,14 +1911,15 @@ const mouseDown = function (evt) { } } break; - case 'fhellipse': + } case 'fhellipse': case 'fhrect': case 'fhpath': start.x = realX; start.y = realY; started = true; dAttr = realX + ',' + realY + ' '; - strokeW = parseFloat(curShape.stroke_width) === 0 ? 1 : curShape.stroke_width; + // Commented out as doing nothing now: + // strokeW = parseFloat(curShape.stroke_width) === 0 ? 1 : curShape.stroke_width; addSVGElementFromJson({ element: 'polyline', curStyles: true, @@ -1899,7 +1937,7 @@ const mouseDown = function (evt) { freehand.miny = realY; freehand.maxy = realY; break; - case 'image': + case 'image': { started = true; const newImage = addSVGElementFromJson({ element: 'image', @@ -1916,7 +1954,7 @@ const mouseDown = function (evt) { setHref(newImage, lastGoodImgUrl); preventClickDefault(newImage); break; - case 'square': + } case 'square': // FIXME: once we create the rect, we lose information that this was a square // (for resizing purposes this could be important) // Fallthrough @@ -1937,9 +1975,9 @@ const mouseDown = function (evt) { } }); break; - case 'line': + case 'line': { started = true; - strokeW = Number(curShape.stroke_width) === 0 ? 1 : curShape.stroke_width; + const strokeW = Number(curShape.stroke_width) === 0 ? 1 : curShape.stroke_width; addSVGElementFromJson({ element: 'line', curStyles: true, @@ -1961,7 +1999,7 @@ const mouseDown = function (evt) { } }); break; - case 'circle': + } case 'circle': started = true; addSVGElementFromJson({ element: 'circle', @@ -2104,16 +2142,19 @@ const mouseMove = function (evt) { dy = snapToGrid(dy); } + /* + // Commenting out as currently has no effect if (evt.shiftKey) { xya = snapToAngle(startX, startY, x, y); ({x, y} = xya); } + */ if (dx !== 0 || dy !== 0) { len = selectedElements.length; for (i = 0; i < len; ++i) { selected = selectedElements[i]; - if (selected == null) { break; } + if (isNullish(selected)) { break; } // if (i === 0) { // const box = utilsGetBBox(selected); // selectedBBoxes[i].x = box.x + dx; @@ -2307,8 +2348,8 @@ const mouseMove = function (evt) { y2 = xya.y; } - shape.setAttributeNS(null, 'x2', x2); - shape.setAttributeNS(null, 'y2', y2); + shape.setAttribute('x2', x2); + shape.setAttribute('y2', y2); break; } case 'foreignObject': // fall through @@ -2353,7 +2394,7 @@ const mouseMove = function (evt) { if (curConfig.gridSnapping) { rad = snapToGrid(rad); } - shape.setAttributeNS(null, 'r', rad); + shape.setAttribute('r', rad); break; } case 'ellipse': { c = $(shape).attr(['cx', 'cy']); @@ -2364,9 +2405,9 @@ const mouseMove = function (evt) { y = snapToGrid(y); cy = snapToGrid(cy); } - shape.setAttributeNS(null, 'rx', Math.abs(x - cx)); + shape.setAttribute('rx', Math.abs(x - cx)); const ry = Math.abs(evt.shiftKey ? (x - cx) : (y - cy)); - shape.setAttributeNS(null, 'ry', ry); + shape.setAttribute('ry', ry); break; } case 'fhellipse': @@ -2379,7 +2420,7 @@ const mouseMove = function (evt) { // Fallthrough case 'fhpath': { // dAttr += + realX + ',' + realY + ' '; - // shape.setAttributeNS(null, 'points', dAttr); + // shape.setAttribute('points', dAttr); end.x = realX; end.y = realY; if (controllPoint2.x && controllPoint2.y) { for (i = 0; i < STEP_COUNT - 1; i++) { @@ -2405,8 +2446,7 @@ const mouseMove = function (evt) { start = {x: end.x, y: end.y}; break; // update path stretch line coordinates - } case 'path': { - } +} case 'path': // fall through case 'pathedit': { x *= currentZoom; @@ -2539,16 +2579,16 @@ const mouseUp = function (evt) { // intentionally fall-through to select here case 'resize': case 'multiselect': - if (rubberBox != null) { + if (!isNullish(rubberBox)) { rubberBox.setAttribute('display', 'none'); curBBoxes = []; } currentMode = 'select'; // Fallthrough case 'select': - if (selectedElements[0] != null) { + if (!isNullish(selectedElements[0])) { // if we only have one selected element - if (selectedElements[1] == null) { + if (isNullish(selectedElements[1])) { // set our current stroke/fill properties to the element's const selected = selectedElements[0]; switch (selected.tagName) { @@ -2583,7 +2623,7 @@ const mouseUp = function (evt) { if (realX !== rStartX || realY !== rStartY) { const len = selectedElements.length; for (let i = 0; i < len; ++i) { - if (selectedElements[i] == null) { break; } + if (isNullish(selectedElements[i])) { break; } if (!selectedElements[i].firstChild) { // Not needed for groups (incorrectly resizes elems), possibly not needed at all? selectorManager.requestSelector(selectedElements[i]).resize(); @@ -2592,7 +2632,7 @@ const mouseUp = function (evt) { // no change in position/size, so maybe we should move to pathedit } else { t = evt.target; - if (selectedElements[0].nodeName === 'path' && selectedElements[1] == null) { + if (selectedElements[0].nodeName === 'path' && isNullish(selectedElements[1])) { pathActions.select(selectedElements[0]); // if it was a path // else, if it was selected and this is a shift-click, remove it from selection @@ -2608,15 +2648,15 @@ const mouseUp = function (evt) { const elem = selectedElements[0]; if (elem) { elem.removeAttribute('style'); - walkTree(elem, function (elem) { - elem.removeAttribute('style'); + walkTree(elem, function (el) { + el.removeAttribute('style'); }); } } } return; - case 'zoom': - if (rubberBox != null) { + case 'zoom': { + if (!isNullish(rubberBox)) { rubberBox.setAttribute('display', 'none'); } const factor = evt.shiftKey ? 0.5 : 2; @@ -2628,7 +2668,7 @@ const mouseUp = function (evt) { factor }); return; - case 'fhpath': + } case 'fhpath': { // Check that the path contains at least 2 points; a degenerate one-point path // causes problems. // Webkit ignores how we set the points attribute with commas and uses space @@ -2649,7 +2689,7 @@ const mouseUp = function (evt) { element = pathActions.smoothPolylineIntoPath(element); } break; - case 'line': + } case 'line': attrs = $(element).attr(['x1', 'x2', 'y1', 'y2']); keep = (attrs.x1 !== attrs.x2 || attrs.y1 !== attrs.y2); break; @@ -2709,7 +2749,7 @@ const mouseUp = function (evt) { selectOnly([element]); textActions.start(element); break; - case 'path': + case 'path': { // set element to null here so that it is not removed nor finalized element = null; // continue to be set to true so that mouseMove happens @@ -2719,7 +2759,7 @@ const mouseUp = function (evt) { ({element} = res); ({keep} = res); break; - case 'pathedit': + } case 'pathedit': keep = true; element = null; pathActions.mouseUp(evt); @@ -2729,7 +2769,7 @@ const mouseUp = function (evt) { element = null; textActions.mouseUp(evt, mouseX, mouseY); break; - case 'rotate': + case 'rotate': { keep = true; element = null; currentMode = 'select'; @@ -2741,7 +2781,7 @@ const mouseUp = function (evt) { recalculateAllSelectedDimensions(); call('changed', selectedElements); break; - default: + } default: // This could occur in an extension break; } @@ -2768,7 +2808,7 @@ const mouseUp = function (evt) { } }); - if (!keep && element != null) { + if (!keep && !isNullish(element)) { getCurrentDrawing().releaseId(getId()); element.remove(); element = null; @@ -2793,7 +2833,7 @@ const mouseUp = function (evt) { canvas.setMode('select'); selectOnly([t], true); } - } else if (element != null) { + } else if (!isNullish(element)) { /** * @name module:svgcanvas.SvgCanvas#addedNew * @type {boolean} @@ -2930,8 +2970,8 @@ $(container).bind( // content offset from canvas in screen pixels const wOffset = workarea.offset(); - const wOffsetLeft = wOffset['left'] + rulerwidth; - const wOffsetTop = wOffset['top'] + rulerwidth; + const wOffsetLeft = wOffset.left + rulerwidth; + const wOffsetTop = wOffset.top + rulerwidth; const delta = (evt.wheelDelta) ? evt.wheelDelta : (evt.detail) ? -evt.detail : 0; if (!delta) { return; } @@ -3001,6 +3041,11 @@ let matrix; let lastX, lastY; let allowDbl; +/** + * + * @param {Integer} index + * @returns {undefined} + */ function setCursor (index) { const empty = (textinput.value === ''); $(textinput).focus(); @@ -3051,6 +3096,13 @@ function setCursor (index) { if (selblock) { selblock.setAttribute('d', ''); } } +/** + * + * @param {Integer} start + * @param {Integer} end + * @param {boolean} skipInput + * @returns {undefined} + */ function setSelection (start, end, skipInput) { if (start === end) { setCursor(end); @@ -3094,6 +3146,12 @@ function setSelection (start, end, skipInput) { }); } +/** + * + * @param {Float} mouseX + * @param {Float} mouseY + * @returns {Integer} + */ function getIndexFromPoint (mouseX, mouseY) { // Position cursor here const pt = svgroot.createSVGPoint(); @@ -3121,10 +3179,23 @@ function getIndexFromPoint (mouseX, mouseY) { return charpos; } +/** + * + * @param {Float} mouseX + * @param {Float} mouseY + * @returns {undefined} + */ function setCursorFromPoint (mouseX, mouseY) { setCursor(getIndexFromPoint(mouseX, mouseY)); } +/** + * + * @param {Float} x + * @param {Float} y + * @param {boolean} apply + * @returns {undefined} + */ function setEndSelectionFromPoint (x, y, apply) { const i1 = textinput.selectionStart; const i2 = getIndexFromPoint(x, y); @@ -3134,6 +3205,12 @@ function setEndSelectionFromPoint (x, y, apply) { setSelection(start, end, !apply); } +/** + * + * @param {Float} xIn + * @param {Float} yIn + * @returns {module:math.XYObject} + */ function screenToPt (xIn, yIn) { const out = { x: xIn, @@ -3152,6 +3229,12 @@ function screenToPt (xIn, yIn) { return out; } +/** + * + * @param {Float} xIn + * @param {Float} yIn + * @returns {module:math.XYObject} + */ function ptToScreen (xIn, yIn) { const out = { x: xIn, @@ -3179,11 +3262,21 @@ function hideCursor () { } */ +/** + * + * @param {Event} evt + * @returns {undefined} + */ function selectAll (evt) { setSelection(0, curtext.textContent.length); $(this).unbind(evt); } +/** + * + * @param {Event} evt + * @returns {undefined} + */ function selectWord (evt) { if (!allowDbl || !curtext) { return; } @@ -3252,7 +3345,7 @@ return /** @lends module:svgcanvas.SvgCanvas#textActions */ { setEndSelectionFromPoint(pt.x, pt.y); }, /** - * @param {external:MouseEvent} + * @param {external:MouseEvent} evt * @param {Float} mouseX * @param {Float} mouseY * @returns {undefined} @@ -3496,13 +3589,13 @@ const removeUnusedDefElems = this.removeUnusedDefElems = function () { }; /** -* Main function to set up the SVG content for output +* Main function to set up the SVG content for output. * @function module:svgcanvas.SvgCanvas#svgCanvasToString * @returns {string} The SVG image for output */ this.svgCanvasToString = function () { // keep calling it until there are none to remove - while (removeUnusedDefElems() > 0) {} + while (removeUnusedDefElems() > 0) {} // eslint-disable-line no-empty pathActions.clear(true); @@ -3550,7 +3643,7 @@ this.svgCanvasToString = function () { }; /** -* Sub function ran on each SVG element to convert it to a string as desired +* Sub function ran on each SVG element to convert it to a string as desired. * @function module:svgcanvas.SvgCanvas#svgToString * @param {Element} elem - The SVG element to convert * @param {Integer} indent - Number of spaces to indent this tag @@ -3563,12 +3656,13 @@ this.svgToString = function (elem, indent) { if (elem) { cleanupElement(elem); - const attrs = Array.from(elem.attributes); - let i; + const attrs = [...elem.attributes]; 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 (let i = 0; i < indent; i++) { out.push(' '); } out.push('<'); out.push(elem.nodeName); if (elem.id === 'svgcontent') { // Process root element separately @@ -3607,15 +3701,15 @@ this.svgToString = function (elem, indent) { } $.each(this.attributes, function (i, attr) { - const uri = attr.namespaceURI; - if (uri && !nsuris[uri] && nsMap[uri] !== 'xmlns' && nsMap[uri] !== 'xml') { - nsuris[uri] = true; - out.push(' xmlns:' + nsMap[uri] + '="' + uri + '"'); + const u = attr.namespaceURI; + if (u && !nsuris[u] && nsMap[u] !== 'xmlns' && nsMap[u] !== 'xml') { + nsuris[u] = true; + out.push(' xmlns:' + nsMap[u] + '="' + u + '"'); } }); }); - i = attrs.length; + let i = attrs.length; const attrNames = ['width', 'height', 'xmlns', 'x', 'y', 'viewBox', 'id', 'overflow']; while (i--) { const attr = attrs[i]; @@ -3635,10 +3729,10 @@ this.svgToString = function (elem, indent) { } } else { // Skip empty defs - if (elem.nodeName === 'defs' && !elem.firstChild) { return; } + if (elem.nodeName === 'defs' && !elem.firstChild) { return ''; } const mozAttrs = ['-moz-math-font-style', '_moz-math-font-style']; - for (i = attrs.length - 1; i >= 0; i--) { + for (let i = attrs.length - 1; i >= 0; i--) { const attr = attrs[i]; let attrVal = toXml(attr.value); // remove bogus attributes added by Gecko @@ -3680,21 +3774,21 @@ this.svgToString = function (elem, indent) { indent++; let bOneLine = false; - for (i = 0; i < childs.length; i++) { + for (let i = 0; i < childs.length; i++) { const child = childs.item(i); switch (child.nodeType) { case 1: // element node out.push('\n'); out.push(this.svgToString(childs.item(i), indent)); break; - case 3: // text node + case 3: { // text node const str = child.nodeValue.replace(/^\s+|\s+$/g, ''); if (str !== '') { bOneLine = true; out.push(String(toXml(str))); } break; - case 4: // cdata node + } case 4: // cdata node out.push('\n'); out.push(new Array(indent + 1).join(' ')); out.push('<![CDATA['); @@ -3713,7 +3807,7 @@ this.svgToString = function (elem, indent) { indent--; if (!bOneLine) { out.push('\n'); - for (i = 0; i < indent; i++) { out.push(' '); } + for (let i = 0; i < indent; i++) { out.push(' '); } } out.push('</'); out.push(elem.nodeName); out.push('>'); } else { @@ -3730,14 +3824,14 @@ this.svgToString = function (elem, indent) { * @returns {undefined} */ /** -* Converts a given image file to a data URL when possible, then runs a given callback +* Converts a given image file to a data URL when possible, then runs a given callback. * @function module:svgcanvas.SvgCanvas#embedImage * @param {string} src - The path/URL of the image -* @param {module:svgcanvas.ImageEmbeddedCallback} [callback] - Function to run when image data is found * @returns {Promise} Resolves to Data URL (string|false) */ -this.embedImage = function (src, callback) { - return new Promise(function (resolve, reject) { +this.embedImage = function (src) { + // Todo: Remove this Promise in favor of making an async/await `Image.load` utility + return new Promise(function (resolve, reject) { // eslint-disable-line promise/avoid-new // load in the image and once it's loaded, get the dimensions $(new Image()).load(function (response, status, xhr) { if (status === 'error') { @@ -3759,14 +3853,13 @@ this.embedImage = function (src, callback) { encodableImages[src] = false; } lastGoodImgUrl = src; - if (callback) { callback(encodableImages[src]); } resolve(encodableImages[src]); }).attr('src', src); }); }; /** -* Sets a given URL to be a "last good image" URL +* Sets a given URL to be a "last good image" URL. * @function module:svgcanvas.SvgCanvas#setGoodImage * @param {string} val * @returns {undefined} @@ -3776,11 +3869,12 @@ this.setGoodImage = function (val) { }; /** -* Does nothing by default, handled by optional widget/extension +* Does nothing by default, handled by optional widget/extension. * @function module:svgcanvas.SvgCanvas#open * @returns {undefined} */ this.open = function () { + /* */ }; /** @@ -3805,7 +3899,14 @@ this.save = function (opts) { }; /** -* Codes only is useful for locale-independent detection +* @typedef {PlainObject} module:svgcanvas.IssuesAndCodes +* @property {string[]} issueCodes The locale-independent code names +* @property {string[]} issues The localized descriptions +*/ + +/** +* Codes only is useful for locale-independent detection. +* @returns {module:svgcanvas.IssuesAndCodes} */ function getIssues () { // remove the selected outline before serializing @@ -3854,58 +3955,57 @@ let canvg; * @property {string} exportWindowName A convenience for passing along a `window.name` to target a window on which the export could be added */ -/** - * Function to run when image data is found - * @callback module:svgcanvas.ImageExportedCallback - * @param {module:svgcanvas.ImageExportedResults} obj - * @returns {undefined} - */ /** * Generates a PNG (or JPG, BMP, WEBP) Data URL based on the current image, * then calls "exported" with an object including the string, image -* information, and any issues found +* information, and any issues found. * @function module:svgcanvas.SvgCanvas#rasterExport * @param {"PNG"|"JPEG"|"BMP"|"WEBP"|"ICO"} [imgType="PNG"] * @param {Float} [quality] Between 0 and 1 * @param {string} [exportWindowName] -* @param {module:svgcanvas.ImageExportedCallback} [cb] +* @param {PlainObject} [opts] +* @param {boolean} [opts.avoidEvent] * @fires module:svgcanvas.SvgCanvas#event:exported * @todo Confirm/fix ICO type * @returns {Promise} Resolves to {@link module:svgcanvas.ImageExportedResults} */ -this.rasterExport = function (imgType, quality, exportWindowName, cb) { +this.rasterExport = async function (imgType, quality, exportWindowName, opts = {}) { const type = imgType === 'ICO' ? 'BMP' : (imgType || 'PNG'); const mimeType = 'image/' + type.toLowerCase(); const {issues, issueCodes} = getIssues(); const svg = this.svgCanvasToString(); - return new Promise(async (resolve, reject) => { - if (!canvg) { - ({canvg} = await importSetGlobal(curConfig.canvgPath + 'canvg.js', { - global: 'canvg' - })); - } - if (!$('#export_canvas').length) { - $('<canvas>', {id: 'export_canvas'}).hide().appendTo('body'); - } - const c = $('#export_canvas')[0]; - c.width = canvas.contentW; - c.height = canvas.contentH; + if (!canvg) { + ({canvg} = await importSetGlobal(curConfig.canvgPath + 'canvg.js', { + global: 'canvg' + })); + } + if (!$('#export_canvas').length) { + $('<canvas>', {id: 'export_canvas'}).hide().appendTo('body'); + } + const c = $('#export_canvas')[0]; + c.width = canvas.contentW; + c.height = canvas.contentH; - await canvg(c, svg); + await canvg(c, svg); + // Todo: Make async/await utility in place of `toBlob`, so we can remove this constructor + return new Promise((resolve, reject) => { // eslint-disable-line promise/avoid-new const dataURLType = type.toLowerCase(); const datauri = quality ? c.toDataURL('image/' + dataURLType, quality) : c.toDataURL('image/' + dataURLType); let bloburl; + /** + * Called when `bloburl` is available for export. + * @returns {undefined} + */ function done () { const obj = { datauri, bloburl, svg, issues, issueCodes, type: imgType, mimeType, quality, exportWindowName }; - call('exported', obj); - if (cb) { - cb(obj); + if (!opts.avoidEvent) { + call('exported', obj); } resolve(obj); } @@ -3946,82 +4046,72 @@ this.rasterExport = function (imgType, quality, exportWindowName, cb) { * @property {string} exportWindowName */ -/** - * Function to run when PDF data is found - * @callback module:svgcanvas.PDFExportedCallback - * @param {module:svgcanvas.PDFExportedResults} obj - * @returns {undefined} - */ /** * Generates a PDF based on the current image, then calls "exportedPDF" with -* an object including the string, the data URL, and any issues found +* an object including the string, the data URL, and any issues found. * @function module:svgcanvas.SvgCanvas#exportPDF -* @param {string} exportWindowName Will also be used for the download file name here +* @param {string} [exportWindowName] Will also be used for the download file name here * @param {external:jsPDF.OutputType} [outputType="dataurlstring"] -* @param {module:svgcanvas.PDFExportedCallback} cb * @fires module:svgcanvas.SvgCanvas#event:exportedPDF * @returns {Promise} Resolves to {@link module:svgcanvas.PDFExportedResults} */ -this.exportPDF = function (exportWindowName, outputType, cb) { - const that = this; - return new Promise(async (resolve, reject) => { - if (!window.jsPDF) { - // Todo: Switch to `import()` when widely supported and available (also allow customization of path) - await importScript([ - // We do not currently have these paths configurable as they are - // currently global-only, so not Rolled-up - 'jspdf/underscore-min.js', - 'jspdf/jspdf.min.js' - ]); +this.exportPDF = async function ( + exportWindowName, + outputType = isChrome() ? 'save' : undefined +) { + if (!window.jsPDF) { + // Todo: Switch to `import()` when widely supported and available (also allow customization of path) + await importScript([ + // We do not currently have these paths configurable as they are + // currently global-only, so not Rolled-up + 'jspdf/underscore-min.js', + 'jspdf/jspdf.min.js' + ]); - const modularVersion = !('svgEditor' in window) || - !window.svgEditor || - window.svgEditor.modules !== false; - // Todo: Switch to `import()` when widely supported and available (also allow customization of path) - await importScript(curConfig.jspdfPath + 'jspdf.plugin.svgToPdf.js', { - type: modularVersion - ? 'module' - : 'text/javascript' - }); - // await importModule('jspdf/jspdf.plugin.svgToPdf.js'); - } - - const res = getResolution(); - const orientation = res.w > res.h ? 'landscape' : 'portrait'; - const unit = 'pt'; // curConfig.baseUnit; // We could use baseUnit, but that is presumably not intended for export purposes - - // Todo: Give options to use predefined jsPDF formats like "a4", etc. from pull-down (with option to keep customizable) - const doc = jsPDF({ - orientation, - unit, - format: [res.w, res.h] - // , compressPdf: true + const modularVersion = !('svgEditor' in window) || + !window.svgEditor || + window.svgEditor.modules !== false; + // Todo: Switch to `import()` when widely supported and available (also allow customization of path) + await importScript(curConfig.jspdfPath + 'jspdf.plugin.svgToPdf.js', { + type: modularVersion + ? 'module' + : 'text/javascript' }); - const docTitle = getDocumentTitle(); - doc.setProperties({ - title: docTitle /* , - subject: '', - author: '', - keywords: '', - creator: '' */ - }); - const {issues, issueCodes} = getIssues(); - const svg = that.svgCanvasToString(); - doc.addSVG(svg, 0, 0); + // await importModule('jspdf/jspdf.plugin.svgToPdf.js'); + } - // doc.output('save'); // Works to open in a new - // window; todo: configure this and other export - // options to optionally work in this manner as - // opposed to opening a new tab - outputType = outputType || 'dataurlstring'; - const obj = {svg, issues, issueCodes, exportWindowName, outputType}; - obj.output = doc.output(outputType, outputType === 'save' ? (exportWindowName || 'svg.pdf') : undefined); - if (cb) { - cb(obj); - } - resolve(obj); - call('exportedPDF', obj); + const res = getResolution(); + const orientation = res.w > res.h ? 'landscape' : 'portrait'; + const unit = 'pt'; // curConfig.baseUnit; // We could use baseUnit, but that is presumably not intended for export purposes + + // Todo: Give options to use predefined jsPDF formats like "a4", etc. from pull-down (with option to keep customizable) + const doc = jsPDF({ + orientation, + unit, + format: [res.w, res.h] + // , compressPdf: true }); + const docTitle = getDocumentTitle(); + doc.setProperties({ + title: docTitle /* , + subject: '', + author: '', + keywords: '', + creator: '' */ + }); + const {issues, issueCodes} = getIssues(); + const svg = this.svgCanvasToString(); + doc.addSVG(svg, 0, 0); + + // doc.output('save'); // Works to open in a new + // window; todo: configure this and other export + // options to optionally work in this manner as + // opposed to opening a new tab + outputType = outputType || 'dataurlstring'; + const obj = {svg, issues, issueCodes, exportWindowName, outputType}; + obj.output = doc.output(outputType, outputType === 'save' ? (exportWindowName || 'svg.pdf') : undefined); + call('exportedPDF', obj); + return obj; }; /** @@ -4038,7 +4128,7 @@ this.getSvgString = function () { * This function determines whether to use a nonce in the prefix, when * generating IDs for future documents in SVG-Edit. * If you're controlling SVG-Edit externally, and want randomized IDs, call -* this BEFORE calling svgCanvas.setSvgString +* this BEFORE calling `svgCanvas.setSvgString`. * @function module:svgcanvas.SvgCanvas#randomizeIds * @param {boolean} [enableRandomization] If true, adds a nonce to the prefix. Thus * `svgCanvas.randomizeIds() <==> svgCanvas.randomizeIds(true)` @@ -4053,7 +4143,7 @@ this.randomizeIds = function (enableRandomization) { }; /** -* Ensure each element has a unique ID +* Ensure each element has a unique ID. * @function module:svgcanvas.SvgCanvas#uniquifyElems * @param {Element} g - The parent element of the tree to give unique IDs * @returns {undefined} @@ -4147,7 +4237,7 @@ const uniquifyElems = this.uniquifyElems = function (g) { }; /** -* Assigns reference data for each use element +* Assigns reference data for each use element. * @function module:svgcanvas.SvgCanvas#setUseData * @param {Element} parent * @returns {undefined} @@ -4171,7 +4261,7 @@ const setUseData = this.setUseData = function (parent) { }; /** -* Converts gradients from userSpaceOnUse to objectBoundingBox +* Converts gradients from userSpaceOnUse to objectBoundingBox. * @function module:svgcanvas.SvgCanvas#convertGradients * @param {Element} elem * @returns {undefined} @@ -4186,14 +4276,14 @@ const convertGradients = this.convertGradients = function (elem) { } elems.each(function () { - const grad = this; + const grad = this; // eslint-disable-line consistent-this if ($(grad).attr('gradientUnits') === 'userSpaceOnUse') { // TODO: Support more than one element with this ref by duplicating parent grad - const elems = $(svgcontent).find('[fill="url(#' + grad.id + ')"],[stroke="url(#' + grad.id + ')"]'); - if (!elems.length) { return; } + const fillStrokeElems = $(svgcontent).find('[fill="url(#' + grad.id + ')"],[stroke="url(#' + grad.id + ')"]'); + if (!fillStrokeElems.length) { return; } // get object's bounding box - const bb = utilsGetBBox(elems[0]); + const bb = utilsGetBBox(fillStrokeElems[0]); // This will occur if the element is inside a <defs> or a <symbol>, // in which we shouldn't need to convert anyway. @@ -4249,7 +4339,7 @@ const convertGradients = this.convertGradients = function (elem) { }; /** -* Converts selected/given `<use>` or child SVG element to a group +* Converts selected/given `<use>` or child SVG element to a group. * @function module:svgcanvas.SvgCanvas#convertToGroup * @param {Element} elem * @fires module:svgcanvas.SvgCanvas#event:selected @@ -4287,8 +4377,8 @@ const convertToGroup = this.convertToGroup = function (elem) { if (vb) { const nums = vb.split(' '); - pos.x -= +nums[0]; - pos.y -= +nums[1]; + pos.x -= Number(nums[0]); + pos.y -= Number(nums[1]); } // Not ideal, but works @@ -4359,7 +4449,7 @@ const convertToGroup = this.convertToGroup = function (elem) { try { recalculateDimensions(n); } catch (e) { - console.log(e); + console.log(e); // eslint-disable-line no-console } }); @@ -4377,7 +4467,7 @@ const convertToGroup = this.convertToGroup = function (elem) { addCommandToHistory(batchCmd); } else { - console.log('Unexpected element to ungroup:', elem); + console.log('Unexpected element to ungroup:', elem); // eslint-disable-line no-console } }; @@ -4435,7 +4525,7 @@ this.setSvgString = function (xmlString, preventUndo) { // change image href vals if possible content.find('image').each(function () { - const image = this; + const image = this; // eslint-disable-line consistent-this preventClickDefault(image); const val = getHref(this); if (val) { @@ -4551,7 +4641,7 @@ this.setSvgString = function (xmlString, preventUndo) { if (!preventUndo) addCommandToHistory(batchCmd); call('changed', [svgcontent]); } catch (e) { - console.log(e); + console.log(e); // eslint-disable-line no-console return false; } @@ -4614,12 +4704,12 @@ this.importSvgString = function (xmlString) { // if no explicit viewbox, create one out of the width and height vb = innervb ? innervb.split(' ') : [0, 0, innerw, innerh]; for (j = 0; j < 4; ++j) { - vb[j] = +(vb[j]); + vb[j] = Number(vb[j]); } // TODO: properly handle preserveAspectRatio const // canvasw = +svgcontent.getAttribute('width'), - canvash = +svgcontent.getAttribute('height'); + canvash = Number(svgcontent.getAttribute('height')); // imported content should be 1/3 of the canvas on its largest dimension if (innerh > innerw) { @@ -4682,7 +4772,7 @@ this.importSvgString = function (xmlString) { addCommandToHistory(batchCmd); call('changed', [svgcontent]); } catch (e) { - console.log(e); + console.log(e); // eslint-disable-line no-console return null; } @@ -4692,13 +4782,14 @@ this.importSvgString = function (xmlString) { // Could deprecate, but besides external uses, their usage makes clear that // canvas is a dependency for all of these -[ - 'identifyLayers', 'createLayer', 'cloneLayer', 'deleteCurrentLayer', - 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', - 'setLayerVisibility', 'moveSelectedToLayer', 'mergeLayer', 'mergeAllLayers', - 'leaveContext', 'setContext' -].forEach((prop) => { - canvas[prop] = draw[prop]; +const dr = { + identifyLayers, createLayer, cloneLayer, deleteCurrentLayer, + setCurrentLayer, renameCurrentLayer, setCurrentLayerPosition, + setLayerVisibility, moveSelectedToLayer, mergeLayer, mergeAllLayers, + leaveContext, setContext +}; +Object.entries(dr).forEach(([prop, propVal]) => { + canvas[prop] = propVal; }); draw.init( /** @@ -4821,18 +4912,19 @@ this.getVersion = function () { }; /** -* Update interface strings with given values +* Update interface strings with given values. * @function module:svgcanvas.SvgCanvas#setUiStrings * @param {module:path.uiStrings} strs - Object with strings (see the [locales API]{@link module:locale.LocaleStrings} and the [tutorial]{@tutorial LocaleDocs}) * @returns {undefined} */ this.setUiStrings = function (strs) { Object.assign(uiStrings, strs.notification); + $ = jQueryPluginDBox($, strs.common); pathModule.setUiStrings(strs); }; /** -* Update configuration options with given values +* Update configuration options with given values. * @function module:svgcanvas.SvgCanvas#setConfig * @param {module:SVGEditor.Config} opts - Object with options * @returns {undefined} @@ -4843,12 +4935,13 @@ this.setConfig = function (opts) { /** * @function module:svgcanvas.SvgCanvas#getTitle -* @param {Element} elem -* @returns {string|undefined} the current group/SVG's title contents +* @param {Element} [elem] +* @returns {string|undefined} the current group/SVG's title contents or +* `undefined` if no element is passed nd there are no selected elements. */ this.getTitle = function (elem) { elem = elem || selectedElements[0]; - if (!elem) { return; } + if (!elem) { return undefined; } elem = $(elem).data('gsvg') || $(elem).data('symbol') || elem; const childs = elem.childNodes; for (let i = 0; i < childs.length; i++) { @@ -4860,7 +4953,7 @@ this.getTitle = function (elem) { }; /** -* Sets the group/SVG's title content +* Sets the group/SVG's title content. * @function module:svgcanvas.SvgCanvas#setGroupTitle * @param {string} val * @todo Combine this with `setDocumentTitle` @@ -4906,7 +4999,7 @@ const getDocumentTitle = this.getDocumentTitle = function () { /** * Adds/updates a title element for the document with the given name. -* This is an undoable action +* This is an undoable action. * @function module:svgcanvas.SvgCanvas#setDocumentTitle * @param {string} newTitle - String with the new title * @returns {undefined} @@ -4941,7 +5034,7 @@ this.setDocumentTitle = function (newTitle) { }; /** -* Returns the editor's namespace URL, optionally adding it to the root element +* Returns the editor's namespace URL, optionally adding it to the root element. * @function module:svgcanvas.SvgCanvas#getEditorNS * @param {boolean} [add] - Indicates whether or not to add the namespace value * @returns {string} The editor's namespace URL @@ -4954,10 +5047,10 @@ this.getEditorNS = function (add) { }; /** -* Changes the document's dimensions to the given size +* Changes the document's dimensions to the given size. * @function module:svgcanvas.SvgCanvas#setResolution * @param {Float|"fit"} x - Number with the width of the new dimensions in user units. -* Can also be the string "fit" to indicate "fit to content" +* Can also be the string "fit" to indicate "fit to content". * @param {Float} y - Number with the height of the new dimensions in user units. * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {boolean} Indicates if resolution change was successful. @@ -5037,7 +5130,7 @@ this.getOffset = function () { * @property {module:utilities.BBoxObject} bbox */ /** -* Sets the zoom level on the canvas-side based on the given value +* Sets the zoom level on the canvas-side based on the given value. * @function module:svgcanvas.SvgCanvas#setBBoxZoom * @param {"selection"|"canvas"|"content"|"layer"|module:SVGEditor.BBoxObjectWithFactor} val - Bounding box object to zoom to or string indicating zoom option. Note: the object value type is defined in `svg-editor.js` * @param {Integer} editorW - The editor's workarea box's width @@ -5047,7 +5140,7 @@ this.getOffset = function () { this.setBBoxZoom = function (val, editorW, editorH) { let spacer = 0.85; let bb; - const calcZoom = function (bb) { + const calcZoom = function (bb) { // eslint-disable-line no-shadow if (!bb) { return false; } const wZoom = Math.round((editorW / bb.width) * 100 * spacer) / 100; const hZoom = Math.round((editorH / bb.height) * 100 * spacer) / 100; @@ -5067,24 +5160,29 @@ this.setBBoxZoom = function (val, editorW, editorH) { } switch (val) { - case 'selection': - if (!selectedElements[0]) { return; } - const selectedElems = $.map(selectedElements, function (n) { if (n) { return n; } }); + case 'selection': { + if (!selectedElements[0]) { return undefined; } + const selectedElems = $.map(selectedElements, function (n) { + if (n) { + return n; + } + return undefined; + }); bb = getStrokedBBoxDefaultVisible(selectedElems); break; - case 'canvas': + } case 'canvas': { const res = getResolution(); spacer = 0.95; bb = {width: res.w, height: res.h, x: 0, y: 0}; break; - case 'content': + } case 'content': bb = getStrokedBBoxDefaultVisible(); break; case 'layer': bb = getStrokedBBoxDefaultVisible(getVisibleElements(getCurrentDrawing().getCurrentLayer())); break; default: - return; + return undefined; } return calcZoom(bb); }; @@ -5160,7 +5258,7 @@ this.setBBoxZoom = function (val, editorW, editorH) { */ /** -* Sets the zoom to the given level +* Sets the zoom to the given level. * @function module:svgcanvas.SvgCanvas#setZoom * @param {Float} zoomLevel - Float indicating the zoom level to change to * @fires module:svgcanvas.SvgCanvas#event:ext-zoomChanged @@ -5187,7 +5285,7 @@ this.getMode = function () { }; /** -* Sets the editor's mode to the given string +* Sets the editor's mode to the given string. * @function module:svgcanvas.SvgCanvas#setMode * @param {string} name - String with the new mode to change to * @returns {undefined} @@ -5218,7 +5316,7 @@ this.getColor = function (type) { }; /** -* Change the current stroke/fill color/gradient value +* Change the current stroke/fill color/gradient value. * @function module:svgcanvas.SvgCanvas#setColor * @param {string} type - String indicating fill or stroke * @param {string} val - The value to set the stroke attribute to @@ -5230,6 +5328,11 @@ this.setColor = function (type, val, preventUndo) { curShape[type] = val; curProperties[type + '_paint'] = {type: 'solidColor'}; const elems = []; + /** + * + * @param {Element} e + * @returns {undefined} + */ function addNonG (e) { if (e.nodeName !== 'g') { elems.push(e); @@ -5241,14 +5344,12 @@ this.setColor = function (type, val, preventUndo) { if (elem) { if (elem.tagName === 'g') { walkTree(elem, addNonG); - } else { - if (type === 'fill') { - if (elem.tagName !== 'polyline' && elem.tagName !== 'line') { - elems.push(elem); - } - } else { + } else if (type === 'fill') { + if (elem.tagName !== 'polyline' && elem.tagName !== 'line') { elems.push(elem); } + } else { + elems.push(elem); } } } @@ -5263,7 +5364,7 @@ this.setColor = function (type, val, preventUndo) { }; /** -* Apply the current gradient to selected element's fill or stroke +* Apply the current gradient to selected element's fill or stroke. * @function module:svgcanvas.SvgCanvas#setGradient * @param {"fill"|"stroke"} type - String indicating "fill" or "stroke" to apply to an element * @returns {undefined} @@ -5287,7 +5388,7 @@ const setGradient = this.setGradient = function (type) { }; /** -* Check if exact gradient already exists +* Check if exact gradient already exists. * @function module:svgcanvas~findDuplicateGradient * @param {SVGGradientElement} grad - The gradient DOM element to compare to others * @returns {SVGGradientElement} The existing gradient if found, `null` if not @@ -5312,7 +5413,7 @@ const findDuplicateGradient = function (grad) { const ogAttrs = $(og).attr(radAttrs); let diff = false; - $.each(radAttrs, function (i, attr) { + $.each(radAttrs, function (j, attr) { if (gradAttrs[attr] !== ogAttrs[attr]) { diff = true; } }); @@ -5348,7 +5449,7 @@ const findDuplicateGradient = function (grad) { }; /** -* Set a color/gradient to a fill/stroke +* Set a color/gradient to a fill/stroke. * @function module:svgcanvas.SvgCanvas#setPaint * @param {"fill"|"stroke"} type - String with "fill" or "stroke" * @param {module:jGraduate.jGraduatePaintOptions} paint - The jGraduate paint object to apply @@ -5401,7 +5502,7 @@ this.getStrokeWidth = function () { /** * Sets the stroke width for the current selected elements. -* When attempting to set a line's width to 0, this changes it to 1 instead +* When attempting to set a line's width to 0, this changes it to 1 instead. * @function module:svgcanvas.SvgCanvas#setStrokeWidth * @param {Float} val - A Float indicating the new stroke width value * @fires module:svgcanvas.SvgCanvas#event:changed @@ -5415,6 +5516,11 @@ this.setStrokeWidth = function (val) { curProperties.stroke_width = val; const elems = []; + /** + * + * @param {Element} e + * @returns {undefined} + */ function addNonG (e) { if (e.nodeName !== 'g') { elems.push(e); @@ -5438,7 +5544,7 @@ this.setStrokeWidth = function (val) { }; /** -* Set the given stroke-related attribute the given value for selected elements +* Set the given stroke-related attribute the given value for selected elements. * @function module:svgcanvas.SvgCanvas#setStrokeAttr * @param {string} attr - String with the attribute name * @param {string|Float} val - String or number with the attribute value @@ -5494,7 +5600,7 @@ this.getStyle = function () { this.getOpacity = getOpacity; /** -* Sets the given opacity to the current selected elements +* Sets the given opacity on the current selected elements. * @function module:svgcanvas.SvgCanvas#setOpacity * @param {string} val * @returns {undefined} @@ -5521,7 +5627,7 @@ this.getStrokeOpacity = function () { }; /** -* Sets the current fill/stroke opacity +* Sets the current fill/stroke opacity. * @function module:svgcanvas.SvgCanvas#setPaintOpacity * @param {string} type - String with "fill" or "stroke" * @param {Float} val - Float with the new opacity value @@ -5538,7 +5644,7 @@ this.setPaintOpacity = function (type, val, preventUndo) { }; /** -* Gets the current fill/stroke opacity +* Gets the current fill/stroke opacity. * @function module:svgcanvas.SvgCanvas#getPaintOpacity * @param {"fill"|"stroke"} type - String with "fill" or "stroke" * @returns {Float} Fill/stroke opacity @@ -5548,7 +5654,7 @@ this.getPaintOpacity = function (type) { }; /** -* Gets the `stdDeviation` blur value of the given element +* Gets the `stdDeviation` blur value of the given element. * @function module:svgcanvas.SvgCanvas#getBlur * @param {Element} elem - The element to check the blur value for * @returns {string} stdDeviation blur attribute value @@ -5575,7 +5681,7 @@ let filter = null; let filterHidden = false; /** -* Sets the `stdDeviation` blur value on the selected element without being undoable +* Sets the `stdDeviation` blur value on the selected element without being undoable. * @function module:svgcanvas.SvgCanvas#setBlurNoUndo * @param {Float} val - The new `stdDeviation` value * @returns {undefined} @@ -5596,7 +5702,7 @@ canvas.setBlurNoUndo = function (val) { changeSelectedAttributeNoUndo('filter', 'url(#' + elem.id + '_blur)'); } if (isWebkit()) { - console.log('e', elem); + // console.log('e', elem); // eslint-disable-line no-console elem.removeAttribute('filter'); elem.setAttribute('filter', 'url(#' + elem.id + '_blur)'); } @@ -5605,6 +5711,10 @@ canvas.setBlurNoUndo = function (val) { } }; +/** + * + * @returns {undefined} + */ function finishChange () { const bCmd = canvas.undoMgr.finishUndoableChange(); curCommand.addSubCommand(bCmd); @@ -5615,34 +5725,32 @@ function finishChange () { /** * Sets the `x`, `y`, `width`, `height` values of the filter element in order to -* make the blur not be clipped. Removes them if not neeeded +* make the blur not be clipped. Removes them if not neeeded. * @function module:svgcanvas.SvgCanvas#setBlurOffsets -* @param {Element} filter - The filter DOM element to update +* @param {Element} filterElem - The filter DOM element to update * @param {Float} stdDev - The standard deviation value on which to base the offset size * @returns {undefined} */ -canvas.setBlurOffsets = function (filter, stdDev) { +canvas.setBlurOffsets = function (filterElem, stdDev) { if (stdDev > 3) { // TODO: Create algorithm here where size is based on expected blur - assignAttributes(filter, { + assignAttributes(filterElem, { x: '-50%', y: '-50%', width: '200%', height: '200%' }, 100); - } else { - // Removing these attributes hides text in Chrome (see Issue 579) - if (!isWebkit()) { - filter.removeAttribute('x'); - filter.removeAttribute('y'); - filter.removeAttribute('width'); - filter.removeAttribute('height'); - } + // Removing these attributes hides text in Chrome (see Issue 579) + } else if (!isWebkit()) { + filterElem.removeAttribute('x'); + filterElem.removeAttribute('y'); + filterElem.removeAttribute('width'); + filterElem.removeAttribute('height'); } }; /** -* Adds/updates the blur filter to the selected element +* Adds/updates the blur filter to the selected element. * @function module:svgcanvas.SvgCanvas#setBlur * @param {Float} val - Float with the new `stdDeviation` blur value * @param {boolean} complete - Whether or not the action should be completed (to add to the undo manager) @@ -5711,30 +5819,30 @@ canvas.setBlur = function (val, complete) { }()); /** -* Check whether selected element is bold or not +* Check whether selected element is bold or not. * @function module:svgcanvas.SvgCanvas#getBold * @returns {boolean} Indicates whether or not element is bold */ this.getBold = function () { // should only have one element selected const selected = selectedElements[0]; - if (selected != null && selected.tagName === 'text' && - selectedElements[1] == null) { + if (!isNullish(selected) && selected.tagName === 'text' && + isNullish(selectedElements[1])) { return (selected.getAttribute('font-weight') === 'bold'); } return false; }; /** -* Make the selected element bold or normal +* Make the selected element bold or normal. * @function module:svgcanvas.SvgCanvas#setBold * @param {boolean} b - Indicates bold (`true`) or normal (`false`) * @returns {undefined} */ this.setBold = function (b) { const selected = selectedElements[0]; - if (selected != null && selected.tagName === 'text' && - selectedElements[1] == null) { + if (!isNullish(selected) && selected.tagName === 'text' && + isNullish(selectedElements[1])) { changeSelectedAttribute('font-weight', b ? 'bold' : 'normal'); } if (!selectedElements[0].textContent) { @@ -5743,29 +5851,29 @@ this.setBold = function (b) { }; /** -* Check whether selected element is italic or not +* Check whether selected element is in italics or not. * @function module:svgcanvas.SvgCanvas#getItalic * @returns {boolean} Indicates whether or not element is italic */ this.getItalic = function () { const selected = selectedElements[0]; - if (selected != null && selected.tagName === 'text' && - selectedElements[1] == null) { + if (!isNullish(selected) && selected.tagName === 'text' && + isNullish(selectedElements[1])) { return (selected.getAttribute('font-style') === 'italic'); } return false; }; /** -* Make the selected element italic or normal +* Make the selected element italic or normal. * @function module:svgcanvas.SvgCanvas#setItalic -* @param {boolean} b - Indicates italic (`true`) or normal (`false`) +* @param {boolean} i - Indicates italic (`true`) or normal (`false`) * @returns {undefined} */ this.setItalic = function (i) { const selected = selectedElements[0]; - if (selected != null && selected.tagName === 'text' && - selectedElements[1] == null) { + if (!isNullish(selected) && selected.tagName === 'text' && + isNullish(selectedElements[1])) { changeSelectedAttribute('font-style', i ? 'italic' : 'normal'); } if (!selectedElements[0].textContent) { @@ -5782,7 +5890,7 @@ this.getFontFamily = function () { }; /** -* Set the new font family +* Set the new font family. * @function module:svgcanvas.SvgCanvas#setFontFamily * @param {string} val - String with the new font family * @returns {undefined} @@ -5796,7 +5904,7 @@ this.setFontFamily = function (val) { }; /** -* Set the new font color +* Set the new font color. * @function module:svgcanvas.SvgCanvas#setFontColor * @param {string} val - String with the new font color * @returns {undefined} @@ -5823,7 +5931,7 @@ this.getFontSize = function () { }; /** -* Applies the given font size to the selected element +* Applies the given font size to the selected element. * @function module:svgcanvas.SvgCanvas#setFontSize * @param {Float} val - Float with the new font size * @returns {undefined} @@ -5842,12 +5950,12 @@ this.setFontSize = function (val) { */ this.getText = function () { const selected = selectedElements[0]; - if (selected == null) { return ''; } + if (isNullish(selected)) { return ''; } return selected.textContent; }; /** -* Updates the text element with the given string +* Updates the text element with the given string. * @function module:svgcanvas.SvgCanvas#setTextContent * @param {string} val - String with the new text * @returns {undefined} @@ -5860,7 +5968,7 @@ this.setTextContent = function (val) { /** * Sets the new image URL for the selected image element. Updates its size if -* a new URL is given +* a new URL is given. * @function module:svgcanvas.SvgCanvas#setImageURL * @param {string} val - String with the image URL/path * @fires module:svgcanvas.SvgCanvas#event:changed @@ -5871,14 +5979,14 @@ this.setImageURL = function (val) { if (!elem) { return; } const attrs = $(elem).attr(['width', 'height']); - let setsize = (!attrs.width || !attrs.height); + const setsize = (!attrs.width || !attrs.height); const curHref = getHref(elem); // Do nothing if no URL change or size change - if (curHref !== val) { - setsize = true; - } else if (!setsize) { return; } + if (curHref === val && !setsize) { + return; + } const batchCmd = new BatchCommand('Change Image URL'); @@ -5887,24 +5995,20 @@ this.setImageURL = function (val) { '#href': curHref })); - if (setsize) { - $(new Image()).load(function () { - const changes = $(elem).attr(['width', 'height']); + $(new Image()).load(function () { + const changes = $(elem).attr(['width', 'height']); - $(elem).attr({ - width: this.width, - height: this.height - }); + $(elem).attr({ + width: this.width, + height: this.height + }); - selectorManager.requestSelector(elem).resize(); + selectorManager.requestSelector(elem).resize(); - batchCmd.addSubCommand(new ChangeElementCommand(elem, changes)); - addCommandToHistory(batchCmd); - call('changed', [elem]); - }).attr('src', val); - } else { + batchCmd.addSubCommand(new ChangeElementCommand(elem, changes)); addCommandToHistory(batchCmd); - } + call('changed', [elem]); + }).attr('src', val); }; /** @@ -5941,7 +6045,8 @@ this.setLinkURL = function (val) { }; /** -* Sets the `rx` and `ry` values to the selected `rect` element to change its corner radius +* Sets the `rx` and `ry` values to the selected `rect` element +* to change its corner radius. * @function module:svgcanvas.SvgCanvas#setRectRadius * @param {string|Float} val - The new radius * @fires module:svgcanvas.SvgCanvas#event:changed @@ -5949,7 +6054,7 @@ this.setLinkURL = function (val) { */ this.setRectRadius = function (val) { const selected = selectedElements[0]; - if (selected != null && selected.tagName === 'rect') { + if (!isNullish(selected) && selected.tagName === 'rect') { const r = selected.getAttribute('rx'); if (r !== String(val)) { selected.setAttribute('rx', val); @@ -5961,7 +6066,7 @@ this.setRectRadius = function (val) { }; /** -* Wraps the selected element(s) in an anchor element or converts group to one +* Wraps the selected element(s) in an anchor element or converts group to one. * @function module:svgcanvas.SvgCanvas#makeHyperlink * @param {string} url * @returns {undefined} @@ -5996,7 +6101,7 @@ this.setSegType = function (newType) { }; /** -* Convert selected element to a path, or get the BBox of an element-as-path +* Convert selected element to a path, or get the BBox of an element-as-path. * @function module:svgcanvas.SvgCanvas#convertToPath * @todo (codedread): Remove the getBBox argument and split this function into two. * @param {Element} elem - The DOM element to be converted @@ -6005,12 +6110,12 @@ this.setSegType = function (newType) { * Otherwise the resulting path element is returned. */ this.convertToPath = function (elem, getBBox) { - if (elem == null) { + if (isNullish(elem)) { const elems = selectedElements; - $.each(elems, function (i, elem) { - if (elem) { canvas.convertToPath(elem); } + $.each(elems, function (i, el) { + if (el) { canvas.convertToPath(el); } }); - return; + return undefined; } if (getBBox) { return getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions); @@ -6029,7 +6134,7 @@ this.convertToPath = function (elem, getBBox) { opacity: curShape.opacity, visibility: 'hidden' }; - return convertToPath(elem, attrs, addSVGElementFromJson, pathActions, clearSelection, addToSelection, history, addCommandToHistory); + return convertToPath(elem, attrs, addSVGElementFromJson, pathActions, clearSelection, addToSelection, hstry, addCommandToHistory); }; /** @@ -6048,11 +6153,11 @@ const changeSelectedAttributeNoUndo = function (attr, newValue, elems) { elems = elems || selectedElements; let i = elems.length; const noXYElems = ['g', 'polyline', 'path']; - const goodGAttrs = ['transform', 'opacity', 'filter']; + // const goodGAttrs = ['transform', 'opacity', 'filter']; while (i--) { let elem = elems[i]; - if (elem == null) { continue; } + if (isNullish(elem)) { continue; } // Set x,y vals on elements that don't have them if ((attr === 'x' || attr === 'y') && noXYElems.includes(elem.tagName)) { @@ -6064,10 +6169,10 @@ const changeSelectedAttributeNoUndo = function (attr, newValue, elems) { } // only allow the transform/opacity/filter attribute to change on <g> elements, slightly hacky - // TODO: FIXME: This doesn't seem right. Where's the body of this if statement? - if (elem.tagName === 'g' && goodGAttrs.includes(attr)) {} + // TODO: FIXME: Missing statement body + // if (elem.tagName === 'g' && goodGAttrs.includes(attr)) {} let oldval = attr === '#text' ? elem.textContent : elem.getAttribute(attr); - if (oldval == null) { oldval = ''; } + if (isNullish(oldval)) { oldval = ''; } if (oldval !== String(newValue)) { if (attr === '#text') { // const oldW = utilsGetBBox(elem).width; @@ -6160,7 +6265,7 @@ const changeSelectedAttributeNoUndo = function (attr, newValue, elems) { * subset to this function in the `elems` argument. * @function module:svgcanvas.SvgCanvas#changeSelectedAttribute * @param {string} attr - String with the attribute name -* @param {string|Float} newValue - String or number with the new attribute value +* @param {string|Float} val - String or number with the new attribute value * @param {Element[]} elems - The DOM elements to apply the change to * @returns {undefined} */ @@ -6179,7 +6284,7 @@ const changeSelectedAttribute = this.changeSelectedAttribute = function (attr, v /** * Removes all selected elements from the DOM and adds the change to the -* history stack +* history stack. * @function module:svgcanvas.SvgCanvas#deleteSelectedElements * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} @@ -6191,7 +6296,7 @@ this.deleteSelectedElements = function () { for (let i = 0; i < len; ++i) { const selected = selectedElements[i]; - if (selected == null) { break; } + if (isNullish(selected)) { break; } let parent = selected.parentNode; let t = selected; @@ -6222,7 +6327,7 @@ this.deleteSelectedElements = function () { /** * Removes all selected elements from the DOM and adds the change to the -* history stack. Remembers removed elements on the clipboard +* history stack. Remembers removed elements on the clipboard. * @function module:svgcanvas.SvgCanvas#cutSelectedElements * @returns {undefined} */ @@ -6232,7 +6337,7 @@ this.cutSelectedElements = function () { }; /** -* Remembers the current selected elements on the clipboard +* Remembers the current selected elements on the clipboard. * @function module:svgcanvas.SvgCanvas#copySelectedElements * @returns {undefined} */ @@ -6270,6 +6375,11 @@ this.pasteElements = function (type, x, y) { const changedIDs = {}; // Recursively replace IDs and record the changes + /** + * + * @param {module:svgcanvas.SVGAsJSON} elem + * @returns {undefined} + */ function checkIDs (elem) { if (elem.attr && elem.attr.id) { changedIDs[elem.attr.id] = getNextId(); @@ -6347,7 +6457,7 @@ this.pasteElements = function (type, x, y) { }; /** -* Wraps all the selected elements in a group (`g`) element +* Wraps all the selected elements in a group (`g`) element. * @function module:svgcanvas.SvgCanvas#groupSelectedElements * @param {"a"|"g"} [type="g"] - type of element to group into, defaults to `<g>` * @param {string} [urlArg] @@ -6388,7 +6498,7 @@ this.groupSelectedElements = function (type, urlArg) { let i = selectedElements.length; while (i--) { let elem = selectedElements[i]; - if (elem == null) { continue; } + if (isNullish(elem)) { continue; } if (elem.parentNode.tagName === 'a' && elem.parentNode.childNodes.length === 1) { elem = elem.parentNode; @@ -6407,11 +6517,11 @@ this.groupSelectedElements = function (type, urlArg) { /** * Pushes all appropriate parent group properties down to its children, then -* removes them from the group +* removes them from the group. * @function module:svgcanvas.SvgCanvas#pushGroupProperties * @param {SVGAElement|SVGGElement} g * @param {boolean} undoable -* @returns {undefined} +* @returns {BatchCommand|undefined} */ const pushGroupProperties = this.pushGroupProperties = function (g, undoable) { const children = g.childNodes; @@ -6590,11 +6700,12 @@ const pushGroupProperties = this.pushGroupProperties = function (g, undoable) { if (undoable && !batchCmd.isEmpty()) { return batchCmd; } + return undefined; }; /** * Unwraps all the elements in a selected group (`g`) element. This requires -* significant recalculations to apply group's transforms, etc. to its children +* significant recalculations to apply group's transforms, etc. to its children. * @function module:svgcanvas.SvgCanvas#ungroupSelectedElement * @returns {undefined} */ @@ -6665,14 +6776,14 @@ this.ungroupSelectedElement = function () { /** * Repositions the selected element to the bottom in the DOM to appear on top of -* other elements +* other elements. * @function module:svgcanvas.SvgCanvas#moveToTopSelectedElement * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ this.moveToTopSelectedElement = function () { const [selected] = selectedElements; - if (selected != null) { + if (!isNullish(selected)) { let t = selected; const oldParent = t.parentNode; const oldNextSibling = t.nextSibling; @@ -6688,14 +6799,14 @@ this.moveToTopSelectedElement = function () { /** * Repositions the selected element to the top in the DOM to appear under -* other elements +* other elements. * @function module:svgcanvas.SvgCanvas#moveToBottomSelectedElement * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ this.moveToBottomSelectedElement = function () { const [selected] = selectedElements; - if (selected != null) { + if (!isNullish(selected)) { let t = selected; const oldParent = t.parentNode; const oldNextSibling = t.nextSibling; @@ -6720,7 +6831,7 @@ this.moveToBottomSelectedElement = function () { /** * Moves the select element up or down the stack, based on the visibly -* intersecting elements +* intersecting elements. * @function module:svgcanvas.SvgCanvas#moveUpDownSelected * @param {"Up"|"Down"} dir - String that's either 'Up' or 'Down' * @fires module:svgcanvas.SvgCanvas#event:changed @@ -6741,9 +6852,9 @@ this.moveUpDownSelected = function (dir) { if (this === selected) { foundCur = true; } - return; + return true; } - closest = this; + closest = this; // eslint-disable-line consistent-this return false; }); if (!closest) { return; } @@ -6761,13 +6872,13 @@ this.moveUpDownSelected = function (dir) { }; /** -* Moves selected elements on the X/Y axis +* Moves selected elements on the X/Y axis. * @function module:svgcanvas.SvgCanvas#moveSelectedElements * @param {Float} dx - Float with the distance to move on the x-axis * @param {Float} dy - Float with the distance to move on the y-axis * @param {boolean} undoable - Boolean indicating whether or not the action should be undoable * @fires module:svgcanvas.SvgCanvas#event:changed -* @returns {BatchCommand} Batch command for the move +* @returns {BatchCommand|undefined} Batch command for the move */ this.moveSelectedElements = function (dx, dy, undoable) { // if undoable is not sent, default to true @@ -6781,7 +6892,7 @@ this.moveSelectedElements = function (dx, dy, undoable) { let i = selectedElements.length; while (i--) { const selected = selectedElements[i]; - if (selected != null) { + if (!isNullish(selected)) { // if (i === 0) { // selectedBBoxes[0] = utilsGetBBox(selected); // } @@ -6828,11 +6939,12 @@ this.moveSelectedElements = function (dx, dy, undoable) { call('changed', selectedElements); return batchCmd; } + return undefined; }; /** * Create deep DOM copies (clones) of all selected elements and move them slightly -* from their originals +* from their originals. * @function module:svgcanvas.SvgCanvas#cloneSelectedElements * @param {Float} x Float with the distance to move on the x-axis * @param {Float} y Float with the distance to move on the y-axis @@ -6843,13 +6955,19 @@ this.cloneSelectedElements = function (x, y) { const batchCmd = new BatchCommand('Clone Elements'); // find all the elements selected (stop at first null) const len = selectedElements.length; + /** + * Sorts an array numerically and ascending. + * @param {Element} a + * @param {Element} b + * @returns {Integer} + */ function sortfunction (a, b) { - return ($(b).index() - $(a).index()); // causes an array to be sorted numerically and ascending + return ($(b).index() - $(a).index()); } selectedElements.sort(sortfunction); for (i = 0; i < len; ++i) { elem = selectedElements[i]; - if (elem == null) { break; } + if (isNullish(elem)) { break; } } // use slice to quickly get the subset of elements we need const copiedElements = selectedElements.slice(0, i); @@ -6873,7 +6991,7 @@ this.cloneSelectedElements = function (x, y) { }; /** -* Aligns selected elements +* Aligns selected elements. * @function module:svgcanvas.SvgCanvas#alignSelectedElements * @param {string} type - String with single character indicating the alignment type * @param {"selected"|"largest"|"smallest"|"page"} relativeTo @@ -6887,7 +7005,7 @@ this.alignSelectedElements = function (type, relativeTo) { miny = Number.MAX_VALUE, maxy = Number.MIN_VALUE; let curwidth = Number.MIN_VALUE, curheight = Number.MIN_VALUE; for (let i = 0; i < len; ++i) { - if (selectedElements[i] == null) { break; } + if (isNullish(selectedElements[i])) { break; } const elem = selectedElements[i]; bboxes[i] = getStrokedBBoxDefaultVisible([elem]); @@ -6940,7 +7058,7 @@ this.alignSelectedElements = function (type, relativeTo) { const dx = new Array(len); const dy = new Array(len); for (let i = 0; i < len; ++i) { - if (selectedElements[i] == null) { break; } + if (isNullish(selectedElements[i])) { break; } // const elem = selectedElements[i]; const bbox = bboxes[i]; dx[i] = 0; @@ -6995,7 +7113,7 @@ this.contentH = getResolution().h; */ /** -* Updates the editor canvas width/height/position after a zoom has occurred +* Updates the editor canvas width/height/position after a zoom has occurred. * @function module:svgcanvas.SvgCanvas#updateCanvas * @param {Float} w - Float with the new width * @param {Float} h - Float with the new height @@ -7008,8 +7126,8 @@ this.updateCanvas = function (w, h) { const bg = $('#canvasBackground')[0]; const oldX = svgcontent.getAttribute('x'); const oldY = svgcontent.getAttribute('y'); - const x = (w / 2 - this.contentW * currentZoom / 2); - const y = (h / 2 - this.contentH * currentZoom / 2); + const x = ((w - this.contentW * currentZoom) / 2); + const y = ((h - this.contentH * currentZoom) / 2); assignAttributes(svgcontent, { width: this.contentW * currentZoom, @@ -7035,6 +7153,7 @@ this.updateCanvas = function (w, h) { } selectorManager.selectorParentGroup.setAttribute('transform', 'translate(' + x + ',' + y + ')'); + /** * Invoked upon updates to the canvas. * @event module:svgcanvas.SvgCanvas#event:ext-canvasUpdated @@ -7057,7 +7176,7 @@ this.updateCanvas = function (w, h) { }; /** -* Set the background of the editor (NOT the actual document) +* Set the background of the editor (NOT the actual document). * @function module:svgcanvas.SvgCanvas#setBackground * @param {string} color - String with fill color to apply * @param {string} url - URL or path to image to use @@ -7087,7 +7206,7 @@ this.setBackground = function (color, url) { }; /** -* Select the next/previous element within the current layer +* Select the next/previous element within the current layer. * @function module:svgcanvas.SvgCanvas#cycleElement * @param {boolean} next - true = next and false = previous element * @fires module:svgcanvas.SvgCanvas#event:selected @@ -7099,7 +7218,7 @@ this.cycleElement = function (next) { let elem = false; const allElems = getVisibleElements(currentGroup || getCurrentDrawing().getCurrentLayer()); if (!allElems.length) { return; } - if (curElem == null) { + if (isNullish(curElem)) { num = next ? allElems.length - 1 : 0; elem = allElems[num]; } else { @@ -7130,6 +7249,7 @@ this.clear(); * @property {module:history.HistoryCommand} BatchCommand * @property {module:history.HistoryCommand} ChangeElementCommand * @property {module:utilities.decode64} decode64 +* @property {module:utilities.dropXMLInteralSubset} dropXMLInteralSubset * @property {module:utilities.encode64} encode64 * @property {module:svgcanvas~ffClone} ffClone * @property {module:svgcanvas~findDuplicateGradient} findDuplicateGradient @@ -7169,6 +7289,7 @@ this.getPrivateMethods = function () { BatchCommand, ChangeElementCommand, decode64, + dropXMLInteralSubset, encode64, ffClone, findDefs, diff --git a/editor/svgicons/jQuery.svgIcons.js b/editor/svgicons/jQuery.svgIcons.js index a973c1b3..546cd602 100644 --- a/editor/svgicons/jQuery.svgIcons.js +++ b/editor/svgicons/jQuery.svgIcons.js @@ -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 * @@ -94,35 +96,41 @@ $(function() { /** * @function module:jQuerySVGIcons.jQuerySVGIcons * @param {external:jQuery} $ Its keys include all icon IDs and the values, the icon as a jQuery object + * @returns {external:jQuery} The enhanced jQuery object */ -export default function ($) { +export default function jQueryPluginSVGIcons ($) { const svgIcons = {}; let fixIDs; + /** + * List of raster images with each + * key being the SVG icon ID to replace, and the value the image file name + * @typedef {PlainObject.<string, string>} external:jQuery.svgIcons.Fallback + */ /** * @function external:jQuery.svgIcons * @param {string} file The location of a local SVG or SVGz file - * @param {PlainObject} [options] - * @param {Float} [options.w] The icon widths - * @param {Float} [options.h] The icon heights - * @param {PlainObject.<string, string>} [options.fallback] List of raster images with each - key being the SVG icon ID to replace, and the value the image file name - * @param {string} [options.fallback_path] The path to use for all images + * @param {PlainObject} [opts] + * @param {Float} [opts.w] The icon widths + * @param {Float} [opts.h] The icon heights + * @param {external:jQuery.svgIcons.Fallback} [opts.fallback] + * @param {string} [opts.fallback_path] The path to use for all images listed under "fallback" - * @param {boolean} [options.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, rather than include the SVG icon. - * @param {PlainObject.<string, string>} [options.placement] List with selectors for keys and SVG icon ids + * @param {PlainObject.<string, string>} [opts.placement] List with selectors for keys and SVG icon ids as values. This provides a custom method of adding icons. - * @param {PlainObject.<string, module:jQuerySVGIcons.Size>} [options.resize] List with selectors for keys and numbers + * @param {PlainObject.<string, module:jQuerySVGIcons.Size>} [opts.resize] List with selectors for keys and numbers as values. This allows an easy way to resize specific icons. - * @param {module:jQuerySVGIcons.SVGIconsLoadedCallback} [options.callback] A function to call when all icons have been loaded. - * @param {boolean} [options.id_match=true] Automatically attempt to match SVG icon ids with + * @param {module:jQuerySVGIcons.SVGIconsLoadedCallback} [opts.callback] A function to call when all icons have been loaded. + * @param {boolean} [opts.id_match=true] Automatically attempt to match SVG icon ids with corresponding HTML id - * @param {boolean} [options.no_img] Prevent attempting to convert the icon into an `<img>` + * @param {boolean} [opts.no_img] Prevent attempting to convert the icon into an `<img>` element (may be faster, help for browser consistency) - * @param {boolean} [options.svgz] Indicate that the file is an SVGZ file, and thus not to + * @param {boolean} [opts.svgz] Indicate that the file is an SVGZ file, and thus not to parse as XML. SVGZ files add compression benefits, but getting data from them fails in Firefox 2 and older. + * @returns {undefined} */ $.svgIcons = function (file, opts = {}) { const svgns = 'http://www.w3.org/2000/svg', @@ -130,8 +138,10 @@ export default function ($) { iconW = opts.w || 24, iconH = opts.h || 24; let elems, svgdoc, testImg, - iconsMade = false, dataLoaded = false, loadAttempts = 0; - const isOpera = !!window.opera, + iconsMade = false, + dataLoaded = false, + loadAttempts = 0; + const isOpera = Boolean(window.opera), // ua = navigator.userAgent, // isSafari = (ua.includes('Safari/') && !ua.includes('Chrome/')), dataPre = 'data:image/svg+xml;charset=utf-8;base64,'; @@ -167,24 +177,28 @@ export default function ($) { $(function () { useFallback(); }); - } else { - if (err.responseText) { - svgdoc = parser.parseFromString(err.responseText, 'text/xml'); + } else if (err.responseText) { + svgdoc = parser.parseFromString(err.responseText, 'text/xml'); - if (!svgdoc.childNodes.length) { - $(useFallback); - } - $(function () { - getIcons('ajax'); - }); - } else { + if (!svgdoc.childNodes.length) { $(useFallback); } + $(function () { + getIcons('ajax'); + }); + } else { + $(useFallback); } } }); } + /** + * + * @param {"ajax"|0|undefined} evt + * @param {boolean} [noWait] + * @returns {undefined} + */ function getIcons (evt, noWait) { if (evt !== 'ajax') { if (dataLoaded) return; @@ -229,6 +243,14 @@ export default function ($) { } } + /** + * + * @param {external:jQuery} target + * @param {external:jQuery} icon A wrapped `defs` or Image + * @param {string} id SVG icon ID + * @param {string} setID + * @returns {undefined} + */ function setIcon (target, icon, id, setID) { if (isOpera) icon.css('visibility', 'hidden'); if (opts.replace) { @@ -247,6 +269,11 @@ export default function ($) { } let holder; + /** + * @param {external:jQuery} icon A wrapped `defs` or Image + * @param {string} id SVG icon ID + * @returns {undefined} + */ function addIcon (icon, id) { if (opts.id_match === undefined || opts.id_match !== false) { setIcon(holder, icon, id, true); @@ -254,7 +281,13 @@ export default function ($) { svgIcons[id] = icon; } - function makeIcons (toImage, fallback) { + /** + * + * @param {boolean} [toImage] + * @param {external:jQuery.svgIcons.Fallback} [fallback] + * @returns {undefined} + */ + function makeIcons (toImage = false, fallback) { if (iconsMade) return; if (opts.no_img) toImage = false; @@ -288,7 +321,7 @@ export default function ($) { const svgroot = document.createElementNS(svgns, 'svg'); // Per https://www.w3.org/TR/xml-names11/#defaulting, the namespace for // attributes should have no value. - svgroot.setAttributeNS(null, 'viewBox', [0, 0, iconW, iconH].join(' ')); + svgroot.setAttribute('viewBox', [0, 0, iconW, iconH].join(' ')); let svg = elem.getElementsByTagNameNS(svgns, 'svg')[0]; @@ -357,13 +390,14 @@ export default function ($) { let idElems; if (isOpera) { idElems = defs.find('*').filter(function () { - return !!this.id; + return Boolean(this.id); }); } else { idElems = defs.find('[id]'); } - const allElems = svgEl[0].getElementsByTagName('*'), len = allElems.length; + const allElems = svgEl[0].getElementsByTagName('*'), + len = allElems.length; idElems.each(function (i) { const {id} = this; @@ -407,49 +441,20 @@ export default function ($) { return svgEl; }; + /** + * @returns {undefined} + */ function useFallback () { if (file.includes('.svgz')) { const regFile = file.replace('.svgz', '.svg'); if (window.console) { - console.log('.svgz failed, trying with .svg'); + console.log('.svgz failed, trying with .svg'); // eslint-disable-line no-console } $.svgIcons(regFile, opts); } else if (opts.fallback) { makeIcons(false, opts.fallback); } } - - function encode64 (input) { - // base64 strings are 4/3 larger than the original string - if (window.btoa) return window.btoa(input); - const _keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; - const output = new Array(Math.floor((input.length + 2) / 3) * 4); - - let i = 0, p = 0; - do { - const chr1 = input.charCodeAt(i++); - const chr2 = input.charCodeAt(i++); - const chr3 = input.charCodeAt(i++); - - const enc1 = chr1 >> 2; - const enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); - - let enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); - let enc4 = chr3 & 63; - if (isNaN(chr2)) { - enc3 = enc4 = 64; - } else if (isNaN(chr3)) { - enc4 = 64; - } - - output[p++] = _keyStr.charAt(enc1); - output[p++] = _keyStr.charAt(enc2); - output[p++] = _keyStr.charAt(enc3); - output[p++] = _keyStr.charAt(enc4); - } while (i < input.length); - - return output.join(''); - } }; /** diff --git a/editor/svgpathseg.js b/editor/svgpathseg.js index e208fc39..15118504 100644 --- a/editor/svgpathseg.js +++ b/editor/svgpathseg.js @@ -16,6 +16,10 @@ * including the latest spec changes which were implemented in Firefox 43 and * Chrome 46. */ +/* eslint-disable no-shadow, class-methods-use-this */ +// Linting: We avoid `no-shadow` as ESLint thinks these are still available globals +// Linting: We avoid `class-methods-use-this` as this is a polyfill that must +// follow the conventions (() => { if (!('SVGPathSeg' in window)) { // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSeg @@ -591,7 +595,7 @@ if (!('SVGPathSegList' in window) || !('appendItem' in window.SVGPathSegList.pro return []; } - const owningPathSegList = this; + const owningPathSegList = this; // eslint-disable-line consistent-this class Builder { constructor () { @@ -800,7 +804,7 @@ if (!('SVGPathSegList' in window) || !('appendItem' in window.SVGPathSegList.pro number *= sign; if (exponent) { - number *= Math.pow(10, expsign * exponent); + number *= 10 ** (expsign * exponent); } if (startIndex === this._currentIndex) { @@ -883,10 +887,10 @@ if (!('SVGPathSegList' in window) || !('appendItem' in window.SVGPathSegList.pro } case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL: { const points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()}; return new SVGPathSegCurvetoQuadraticRel(owningPathSegList, points.x, points.y, points.x1, points.y1); - } case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS: + } case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS: { const points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()}; return new SVGPathSegCurvetoQuadraticAbs(owningPathSegList, points.x, points.y, points.x1, points.y1); - case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL: + } case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL: return new SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, this._parseNumber(), this._parseNumber()); case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS: return new SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, this._parseNumber(), this._parseNumber()); diff --git a/editor/svgtransformlist.js b/editor/svgtransformlist.js index a5872b0b..1b99d0d3 100644 --- a/editor/svgtransformlist.js +++ b/editor/svgtransformlist.js @@ -12,7 +12,11 @@ import {supportsNativeTransformLists} from './browser.js'; const svgroot = document.createElementNS(NS.SVG, 'svg'); -// Helper function. +/** + * Helper function to convert `SVGTransform` to a string. + * @param {SVGTransform} xform + * @returns {string} + */ function transformToString (xform) { const m = xform.matrix; let text = ''; @@ -114,8 +118,9 @@ let listMap_ = {}; * These methods do not currently raise any exceptions. * These methods also do not check that transforms are being inserted. This is basically * implementing as much of SVGTransformList that we need to get the job done. +* @implements {module:SVGTransformList.SVGEditTransformList} */ -export class SVGTransformList { +export class SVGTransformList {// eslint-disable-line no-shadow /** * @param {Element} elem */ @@ -125,7 +130,7 @@ export class SVGTransformList { // TODO: how do we capture the undo-ability in the changed transform list? this._update = function () { let tstr = ''; - /* const concatMatrix = */ svgroot.createSVGMatrix(); + // /* const concatMatrix = */ svgroot.createSVGMatrix(); for (let i = 0; i < this.numberOfItems; ++i) { const xform = this._list.getItem(i); tstr += transformToString(xform) + ' '; @@ -170,7 +175,7 @@ export class SVGTransformList { } else if (name === 'rotate' && values.length === 1) { values.push(0, 0); } - xform[fname].apply(xform, values); + xform[fname](...values); this._list.appendItem(xform); } } @@ -179,20 +184,15 @@ export class SVGTransformList { if (item) { // Check if this transform is already in a transformlist, and // remove it if so. - let found = false; - for (const id in listMap_) { - const tl = listMap_[id]; + Object.values(listMap_).some((tl) => { for (let i = 0, len = tl._xforms.length; i < len; ++i) { if (tl._xforms[i] === item) { - found = true; tl.removeItem(i); - break; + return true; } } - if (found) { - break; - } - } + return false; + }); } }; @@ -330,14 +330,14 @@ export const resetListMap = function () { * @param {Element} elem - a DOM Element * @returns {undefined} */ -export let removeElementFromListMap = function (elem) { +export let removeElementFromListMap = function (elem) { // eslint-disable-line import/no-mutable-exports if (elem.id && listMap_[elem.id]) { delete listMap_[elem.id]; } }; /** -* Returns an object that behaves like a `SVGTransformList` for the given DOM element +* Returns an object that behaves like a `SVGTransformList` for the given DOM element. * @function module:SVGTransformList.getTransformList * @param {Element} elem - DOM element to get a transformlist from * @todo The polyfill should have `SVGAnimatedTransformList` and this should use it @@ -372,11 +372,12 @@ export const getTransformList = function (elem) { * @param {Element} elem */ /** -* For unit-testing +* Replace `removeElementFromListMap` for unit-testing. * @function module:SVGTransformList.changeRemoveElementFromListMap * @param {module:SVGTransformList.removeElementFromListMap} cb Passed a single argument `elem` * @returns {undefined} */ -export const changeRemoveElementFromListMap = function (cb) { + +export const changeRemoveElementFromListMap = function (cb) { // eslint-disable-line promise/prefer-await-to-callbacks removeElementFromListMap = cb; }; diff --git a/editor/touch.js b/editor/touch.js index f6996b67..256e665d 100644 --- a/editor/touch.js +++ b/editor/touch.js @@ -1,4 +1,9 @@ // http://ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript/ +/** + * + * @param {Event} ev + * @returns {undefined} + */ function touchHandler (ev) { const {changedTouches} = ev, first = changedTouches[0]; @@ -11,7 +16,7 @@ function touchHandler (ev) { default: return; } - const {screenX, screenY, clientX, clientY} = first; + const {screenX, screenY, clientX, clientY} = first; // eslint-disable-line no-shadow const simulatedEvent = new MouseEvent(type, { // Event interface bubbles: true, diff --git a/editor/typedefs.js b/editor/typedefs.js index 0b39edf0..7422b42e 100644 --- a/editor/typedefs.js +++ b/editor/typedefs.js @@ -10,14 +10,20 @@ * @typedef {null|boolean|Float|string|GenericArray|PlainObject} JSON */ +/** +* @callback GenericCallback +* @param {...*} args Signature dependent on the function +* @returns {*} Return dependent on the function +*/ + /** * This should only be used for objects known to be potentially arbitrary in form. * For those whose determination has not yet been made, simply use type `object` * (or type `?` if it may also be a primitive). -* @typedef {object} ArbitraryObject +* @typedef {Object} ArbitraryObject */ /** -* @typedef {object} ArbitraryModule +* @typedef {Object} ArbitraryModule */ /** * This should only be used for objects known to be potentially arbitrary in form, @@ -44,3 +50,12 @@ /** * @external Window */ + +/** + * @external JamilihArray + * @type {GenericArray} + * @property {string} 0 Element name + * @property {PlainObject<string, string>|JamilihArray} [1] Generally a map from an attribute name to attribute value, but also adds event handlers, etc. + * @property {JamilihArray} [2] Children + * @see {@link https://github.com/brettz9/jamilih/} + */ diff --git a/editor/units.js b/editor/units.js index 103dcfd8..d5f83416 100644 --- a/editor/units.js +++ b/editor/units.js @@ -7,6 +7,7 @@ */ import {NS} from './namespaces.js'; +import {isNullish} from './utilities.js'; const wAttrs = ['x', 'x1', 'cx', 'rx', 'width']; const hAttrs = ['y', 'y1', 'cy', 'ry', 'height']; @@ -40,7 +41,7 @@ let typeMap_ = {}; */ /** * @function module:units.ElementContainer#getElement - * @returns {Element} An element in the container given an id + * @returns {?Element} An element in the container given an id */ /** * @function module:units.ElementContainer#getHeight @@ -134,8 +135,7 @@ export const getTypeMap = function () { export const shortFloat = function (val) { const digits = elementContainer_.getRoundDigits(); if (!isNaN(val)) { - // Note that + converts to Number - return +((+val).toFixed(digits)); + return Number(Number(val).toFixed(digits)); } if (Array.isArray(val)) { return shortFloat(val[0]) + ',' + shortFloat(val[1]); @@ -144,8 +144,10 @@ export const shortFloat = function (val) { }; /** -* Converts the number to given unit or baseUnit +* Converts the number to given unit or baseUnit. * @function module:units.convertUnit +* @param {string|Float} val +* @param {"em"|"ex"|"in"|"cm"|"mm"|"pt"|"pc"|"px"|"%"} [unit] * @returns {Float} */ export const convertUnit = function (val, unit) { @@ -212,7 +214,7 @@ const attrsToConvert = { }; /** -* Converts all applicable attributes to the configured baseUnit +* Converts all applicable attributes to the configured baseUnit. * @function module:units.convertAttrs * @param {Element} element - A DOM element whose attributes should be converted * @returns {undefined} @@ -240,7 +242,7 @@ export const convertAttrs = function (element) { /** * Converts given values to numbers. Attributes must be supplied in -* case a percentage is given +* case a percentage is given. * * @function module:units.convertToNum * @param {string} attr - Name of the attribute associated with the value @@ -271,10 +273,11 @@ export const convertToNum = function (attr, val) { }; /** -* Check if an attribute's value is in a valid format +* Check if an attribute's value is in a valid format. * @function module:units.isValidUnit * @param {string} attr - The name of the attribute associated with the value * @param {string} val - The attribute value to check +* @param {Element} selectedElement * @returns {boolean} Whether the unit is valid */ export const isValidUnit = function (attr, val, selectedElement) { @@ -301,7 +304,7 @@ export const isValidUnit = function (attr, val, selectedElement) { // not already present try { const elem = elementContainer_.getElement(val); - result = (elem == null || elem === selectedElement); + result = (isNullish(elem) || elem === selectedElement); } catch (e) {} return result; } diff --git a/editor/utilities.js b/editor/utilities.js index bdd97743..b60273bb 100644 --- a/editor/utilities.js +++ b/editor/utilities.js @@ -8,7 +8,7 @@ */ import './svgpathseg.js'; -import jqPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr` +import jQueryPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr` import {NS} from './namespaces.js'; import {getTransformList} from './svgtransformlist.js'; import {setUnitAttr, getTypeMap} from './units.js'; @@ -22,7 +22,7 @@ import { } from './browser.js'; // Constants -const $ = jqPluginSVG(jQuery); +const $ = jQueryPluginSVG(jQuery); // String used to encode base64. const KEYSTR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; @@ -102,6 +102,17 @@ export const init = function (editorContext) { svgroot_ = editorContext.getSVGRoot(); }; +/** + * Used to prevent the [Billion laughs attack]{@link https://en.wikipedia.org/wiki/Billion_laughs_attack}. + * @function module:utilities.dropXMLInteralSubset + * @param {string} str String to be processed + * @returns {string} The string with entity declarations in the internal subset removed + * @todo This might be needed in other places `parseFromString` is used even without LGTM flagging + */ +export const dropXMLInteralSubset = (str) => { + return str.replace(/(<!DOCTYPE\s+\w*\s*\[).*(\?\]>)/, '$1$2'); +}; + /** * Converts characters in a string to XML-friendly entities. * @function module:utilities.toXml @@ -112,7 +123,12 @@ export const init = function (editorContext) { export const toXml = function (str) { // ' is ok in XML, but not HTML // > does not normally need escaping, though it can if within a CDATA expression (and preceded by "]]") - return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/, '''); + return str + .replace(/&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); // Note: `'` is XML only }; /** @@ -122,9 +138,9 @@ export const toXml = function (str) { * @param {string} str - The string to be converted * @returns {string} The converted string */ -export const fromXml = function (str) { +export function fromXml (str) { return $('<p/>').html(str).text(); -}; +} // This code was written by Tyler Akins and has been placed in the // public domain. It would be nice if you left this header intact. @@ -134,35 +150,38 @@ export const fromXml = function (str) { // also precalculate the size of the array needed. /** -* Converts a string to base64 +* Converts a string to base64. * @function module:utilities.encode64 * @param {string} input * @returns {string} Base64 output */ -export const encode64 = function (input) { +export function encode64 (input) { // base64 strings are 4/3 larger than the original string input = encodeUTF8(input); // convert non-ASCII characters // input = convertToXMLReferences(input); if (window.btoa) { return window.btoa(input); // Use native if available } - const output = []; - output.length = Math.floor((input.length + 2) / 3) * 4; + const output = new Array(Math.floor((input.length + 2) / 3) * 4); - let i = 0, p = 0; + let i = 0, + p = 0; do { const chr1 = input.charCodeAt(i++); const chr2 = input.charCodeAt(i++); const chr3 = input.charCodeAt(i++); + /* eslint-disable no-bitwise */ const enc1 = chr1 >> 2; const enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); let enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); let enc4 = chr3 & 63; + /* eslint-enable no-bitwise */ if (isNaN(chr2)) { - enc3 = enc4 = 64; + enc3 = 64; + enc4 = 64; } else if (isNaN(chr3)) { enc4 = 64; } @@ -174,15 +193,15 @@ export const encode64 = function (input) { } while (i < input.length); return output.join(''); -}; +} /** -* Converts a string from base64 +* Converts a string from base64. * @function module:utilities.decode64 * @param {string} input Base64-encoded input * @returns {string} Decoded output */ -export const decode64 = function (input) { +export function decode64 (input) { if (window.atob) { return decodeUTF8(window.atob(input)); } @@ -199,30 +218,32 @@ export const decode64 = function (input) { const enc3 = KEYSTR.indexOf(input.charAt(i++)); const enc4 = KEYSTR.indexOf(input.charAt(i++)); + /* eslint-disable no-bitwise */ const chr1 = (enc1 << 2) | (enc2 >> 4); const chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); const chr3 = ((enc3 & 3) << 6) | enc4; + /* eslint-enable no-bitwise */ output += String.fromCharCode(chr1); if (enc3 !== 64) { - output = output + String.fromCharCode(chr2); + output += String.fromCharCode(chr2); } if (enc4 !== 64) { - output = output + String.fromCharCode(chr3); + output += String.fromCharCode(chr3); } } while (i < input.length); return decodeUTF8(output); -}; +} /** * @function module:utilities.decodeUTF8 * @param {string} argString * @returns {string} */ -export const decodeUTF8 = function (argString) { +export function decodeUTF8 (argString) { return decodeURIComponent(escape(argString)); -}; +} // codedread:does not seem to work with webkit-based browsers on OSX // Brettz9: please test again as function upgraded /** @@ -235,7 +256,7 @@ export const encodeUTF8 = function (argString) { }; /** - * convert dataURL to object URL + * Convert dataURL to object URL. * @function module:utilities.dataURLToObjectURL * @param {string} dataurl * @returns {string} object URL or empty string @@ -244,7 +265,8 @@ export const dataURLToObjectURL = function (dataurl) { if (typeof Uint8Array === 'undefined' || typeof Blob === 'undefined' || typeof URL === 'undefined' || !URL.createObjectURL) { return ''; } - const arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], + const arr = dataurl.split(','), + mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]); let n = bstr.length; const u8arr = new Uint8Array(n); @@ -256,7 +278,7 @@ export const dataURLToObjectURL = function (dataurl) { }; /** - * get object URL for a blob object + * Get object URL for a blob object. * @function module:utilities.createObjectURL * @param {Blob} blob A Blob object or File object * @returns {string} object URL or empty string @@ -280,7 +302,7 @@ export const blankPageObjectURL = (function () { })(); /** -* Converts a string to use XML references (for non-ASCII) +* Converts a string to use XML references (for non-ASCII). * @function module:utilities.convertToXMLReferences * @param {string} input * @returns {string} Decimal numeric character references @@ -299,8 +321,8 @@ export const convertToXMLReferences = function (input) { }; /** -* Cross-browser compatible method of converting a string to an XML tree -* found this function [here]{@link http://groups.google.com/group/jquery-dev/browse_thread/thread/c6d11387c580a77f} +* Cross-browser compatible method of converting a string to an XML tree. +* Found this function [here]{@link http://groups.google.com/group/jquery-dev/browse_thread/thread/c6d11387c580a77f}. * @function module:utilities.text2xml * @param {string} sXML * @throws {Error} @@ -353,7 +375,7 @@ export const bboxToObj = function ({x, y, width, height}) { */ /** -* Walks the tree and executes the callback on each element in a top-down fashion +* Walks the tree and executes the callback on each element in a top-down fashion. * @function module:utilities.walkTree * @param {Element} elem - DOM element to traverse * @param {module:utilities.TreeWalker} cbFn - Callback function to run on each element @@ -370,7 +392,7 @@ export const walkTree = function (elem, cbFn) { }; /** -* Walks the tree and executes the callback on each element in a depth-first fashion +* Walks the tree and executes the callback on each element in a depth-first fashion. * @function module:utilities.walkTreePost * @todo FIXME: Shouldn't this be calling walkTreePost? * @param {Element} elem - DOM element to traverse @@ -419,18 +441,18 @@ export const getUrlFromAttr = function (attrVal) { * @param {Element} elem * @returns {string} The given element's `xlink:href` value */ -export let getHref = function (elem) { +export let getHref = function (elem) { // eslint-disable-line import/no-mutable-exports return elem.getAttributeNS(NS.XLINK, 'href'); }; /** -* Sets the given element's `xlink:href` value +* Sets the given element's `xlink:href` value. * @function module:utilities.setHref * @param {Element} elem * @param {string} val * @returns {undefined} */ -export let setHref = function (elem, val) { +export let setHref = function (elem, val) { // eslint-disable-line import/no-mutable-exports elem.setAttributeNS(NS.XLINK, 'xlink:href', val); }; @@ -460,7 +482,7 @@ export const findDefs = function () { /** * Get correct BBox for a path in Webkit. -* Converted from code found [here]{@link http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html} +* Converted from code found [here]{@link http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html}. * @function module:utilities.getPathBBox * @param {SVGPathElement} path - The path DOM element to get the BBox for * @returns {module:utilities.BBoxObject} A BBox-like object @@ -473,6 +495,15 @@ export const getPathBBox = function (path) { const start = seglist.getItem(0); let P0 = [start.x, start.y]; + const getCalc = function (j, P1, P2, P3) { + return function (t) { + return 1 - (t ** 3) * P0[j] + + 3 * 1 - (t ** 2) * t * P1[j] + + 3 * (1 - t) * (t ** 2) * P2[j] + + (t ** 3) * P3[j]; + }; + }; + for (let i = 0; i < tot; i++) { const seg = seglist.getItem(i); @@ -488,28 +519,21 @@ export const getPathBBox = function (path) { P3 = [seg.x, seg.y]; for (let j = 0; j < 2; j++) { - const calc = function (t) { - return Math.pow(1 - t, 3) * P0[j] + - 3 * Math.pow(1 - t, 2) * t * P1[j] + - 3 * (1 - t) * Math.pow(t, 2) * P2[j] + - Math.pow(t, 3) * P3[j]; - }; + const calc = getCalc(j, P1, P2, P3); const b = 6 * P0[j] - 12 * P1[j] + 6 * P2[j]; const a = -3 * P0[j] + 9 * P1[j] - 9 * P2[j] + 3 * P3[j]; const c = 3 * P1[j] - 3 * P0[j]; if (a === 0) { - if (b === 0) { - continue; - } + if (b === 0) { continue; } const t = -c / b; if (t > 0 && t < 1) { bounds[j].push(calc(t)); } continue; } - const b2ac = Math.pow(b, 2) - 4 * c * a; + const b2ac = (b ** 2) - 4 * c * a; if (b2ac < 0) { continue; } const t1 = (-b + Math.sqrt(b2ac)) / (2 * a); if (t1 > 0 && t1 < 1) { bounds[j].push(calc(t1)); } @@ -584,7 +608,7 @@ function groupBBFix (selected) { /** * Get the given/selected element's bounding box object, convert it to be more -* usable when necessary +* usable when necessary. * @function module:utilities.getBBox * @param {Element} elem - Optional DOM element to get the BBox for * @returns {module:utilities.BBoxObject} Bounding box object @@ -601,15 +625,15 @@ export const getBBox = function (elem) { selected.textContent = 'a'; // Some character needed for the selector to use. ret = selected.getBBox(); selected.textContent = ''; - } else { - if (selected.getBBox) { ret = selected.getBBox(); } + } else if (selected.getBBox) { + ret = selected.getBBox(); } break; case 'path': if (!supportsPathBBox()) { ret = getPathBBox(selected); - } else { - if (selected.getBBox) { ret = selected.getBBox(); } + } else if (selected.getBBox) { + ret = selected.getBBox(); } break; case 'g': @@ -619,7 +643,7 @@ export const getBBox = function (elem) { default: if (elname === 'use') { - ret = groupBBFix(selected, true); + ret = groupBBFix(selected); // , true); } if (elname === 'use' || (elname === 'foreignObject' && isWebkit())) { if (!ret) { ret = selected.getBBox(); } @@ -708,12 +732,13 @@ export const getPathDFromElement = function (elem) { let d, a, rx, ry; switch (elem.tagName) { case 'ellipse': - case 'circle': + case 'circle': { a = $(elem).attr(['rx', 'ry', 'cx', 'cy']); const {cx, cy} = a; ({rx, ry} = a); if (elem.tagName === 'circle') { - rx = ry = $(elem).attr('r'); + ry = $(elem).attr('r'); + rx = ry; } d = getPathDFromSegments([ @@ -725,7 +750,7 @@ export const getPathDFromElement = function (elem) { ['Z', []] ]); break; - case 'path': + } case 'path': d = elem.getAttribute('d'); break; case 'line': @@ -738,11 +763,13 @@ export const getPathDFromElement = function (elem) { case 'polygon': d = 'M' + elem.getAttribute('points') + ' Z'; break; - case 'rect': + case 'rect': { const r = $(elem).attr(['rx', 'ry']); ({rx, ry} = r); const b = elem.getBBox(); - const {x, y} = b, w = b.width, h = b.height; + const {x, y} = b, + w = b.width, + h = b.height; num = 4 - num; // Why? Because! if (!rx && !ry) { @@ -770,7 +797,7 @@ export const getPathDFromElement = function (elem) { ]); } break; - default: + } default: break; } @@ -797,7 +824,7 @@ export const getExtraAttributesForConvertToPath = function (elem) { }; /** -* Get the BBox of an element-as-path +* Get the BBox of an element-as-path. * @function module:utilities.getBBoxOfElementAsPath * @param {Element} elem - The DOM element to be probed * @param {module:utilities.EditorContext#addSVGElementFromJson} addSVGElementFromJson - Function to add the path element to the current layer. See canvas.addSVGElementFromJson @@ -815,11 +842,11 @@ export const getBBoxOfElementAsPath = function (elem, addSVGElementFromJson, pat path.setAttribute('transform', eltrans); } - const parent = elem.parentNode; + const {parentNode} = elem; if (elem.nextSibling) { elem.before(path); } else { - parent.append(path); + parentNode.append(path); } const d = getPathDFromElement(elem); @@ -850,12 +877,12 @@ export const getBBoxOfElementAsPath = function (elem, addSVGElementFromJson, pat * @param {module:path.pathActions} pathActions - If a transform exists, pathActions.resetOrientation() is used. See: canvas.pathActions. * @param {module:draw.DrawCanvasInit#clearSelection|module:path.EditorContext#clearSelection} clearSelection - see [canvas.clearSelection]{@link module:svgcanvas.SvgCanvas#clearSelection} * @param {module:path.EditorContext#addToSelection} addToSelection - see [canvas.addToSelection]{@link module:svgcanvas.SvgCanvas#addToSelection} -* @param {module:history} history - see history module +* @param {module:history} hstry - see history module * @param {module:path.EditorContext#addCommandToHistory|module:draw.DrawCanvasInit#addCommandToHistory} addCommandToHistory - see [canvas.addCommandToHistory]{@link module:svgcanvas~addCommandToHistory} * @returns {SVGPathElement|null} The converted path element or null if the DOM element was not recognized. */ -export const convertToPath = function (elem, attrs, addSVGElementFromJson, pathActions, clearSelection, addToSelection, history, addCommandToHistory) { - const batchCmd = new history.BatchCommand('Convert element to Path'); +export const convertToPath = function (elem, attrs, addSVGElementFromJson, pathActions, clearSelection, addToSelection, hstry, addCommandToHistory) { + const batchCmd = new hstry.BatchCommand('Convert element to Path'); // Any attribute on the element not covered by the passed-in attributes attrs = $.extend({}, attrs, getExtraAttributesForConvertToPath(elem)); @@ -871,11 +898,11 @@ export const convertToPath = function (elem, attrs, addSVGElementFromJson, pathA } const {id} = elem; - const parent = elem.parentNode; + const {parentNode} = elem; if (elem.nextSibling) { elem.before(path); } else { - parent.append(path); + parentNode.append(path); } const d = getPathDFromElement(elem); @@ -893,8 +920,8 @@ export const convertToPath = function (elem, attrs, addSVGElementFromJson, pathA } const {nextSibling} = elem; - batchCmd.addSubCommand(new history.RemoveElementCommand(elem, nextSibling, parent)); - batchCmd.addSubCommand(new history.InsertElementCommand(path)); + batchCmd.addSubCommand(new hstry.RemoveElementCommand(elem, nextSibling, parent)); + batchCmd.addSubCommand(new hstry.InsertElementCommand(path)); clearSelection(); elem.remove(); @@ -928,14 +955,14 @@ export const convertToPath = function (elem, attrs, addSVGElementFromJson, pathA * getBBox then apply the angle and any transforms. * * @param {Float} angle - The rotation angle in degrees -* @param {boolean} hasMatrixTransform - True if there is a matrix transform +* @param {boolean} hasAMatrixTransform - True if there is a matrix transform * @returns {boolean} True if the bbox can be optimized. */ -function bBoxCanBeOptimizedOverNativeGetBBox (angle, hasMatrixTransform) { +function bBoxCanBeOptimizedOverNativeGetBBox (angle, hasAMatrixTransform) { const angleModulo90 = angle % 90; const closeTo90 = angleModulo90 < -89.99 || angleModulo90 > 89.99; const closeTo0 = angleModulo90 > -0.001 && angleModulo90 < 0.001; - return hasMatrixTransform || !(closeTo0 || closeTo90); + return hasAMatrixTransform || !(closeTo0 || closeTo90); } /** @@ -968,13 +995,15 @@ export const getBBoxWithTransform = function (elem, addSVGElementFromJson, pathA // TODO: why ellipse and not circle const elemNames = ['ellipse', 'path', 'line', 'polyline', 'polygon']; if (elemNames.includes(elem.tagName)) { - bb = goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions); + goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions); + bb = goodBb; } else if (elem.tagName === 'rect') { // Look for radius const rx = elem.getAttribute('rx'); const ry = elem.getAttribute('ry'); if (rx || ry) { - bb = goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions); + goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions); + bb = goodBb; } } } @@ -1001,7 +1030,12 @@ export const getBBoxWithTransform = function (elem, addSVGElementFromJson, pathA return bb; }; -// TODO: This is problematic with large stroke-width and, for example, a single horizontal line. The calculated BBox extends way beyond left and right sides. +/** + * @param {Element} elem + * @returns {Float} + * @todo This is problematic with large stroke-width and, for example, a single + * horizontal line. The calculated BBox extends way beyond left and right sides. + */ function getStrokeOffsetForBBox (elem) { const sw = elem.getAttribute('stroke-width'); return (!isNaN(sw) && elem.getAttribute('stroke') !== 'none') ? sw / 2 : 0; @@ -1016,7 +1050,7 @@ function getStrokeOffsetForBBox (elem) { */ /** -* Get the bounding box for one or more stroked and/or transformed elements +* Get the bounding box for one or more stroked and/or transformed elements. * @function module:utilities.getStrokedBBox * @param {Element[]} elems - Array with DOM elements to check * @param {module:utilities.EditorContext#addSVGElementFromJson} addSVGElementFromJson - Function to add the path element to the current layer. See canvas.addSVGElementFromJson @@ -1077,18 +1111,18 @@ export const getStrokedBBox = function (elems, addSVGElementFromJson, pathAction /** * Get all elements that have a BBox (excludes `<defs>`, `<title>`, etc). * Note that 0-opacity, off-screen etc elements are still considered "visible" -* for this function +* for this function. * @function module:utilities.getVisibleElements -* @param {Element} parent - The parent DOM element to search within +* @param {Element} parentElement - The parent DOM element to search within * @returns {Element[]} All "visible" elements. */ -export const getVisibleElements = function (parent) { - if (!parent) { - parent = $(editorContext_.getSVGContent()).children(); // Prevent layers from being included +export const getVisibleElements = function (parentElement) { + if (!parentElement) { + parentElement = $(editorContext_.getSVGContent()).children(); // Prevent layers from being included } const contentElems = []; - $(parent).children().each(function (i, elem) { + $(parentElement).children().each(function (i, elem) { if (elem.getBBox) { contentElems.push(elem); } @@ -1097,7 +1131,7 @@ export const getVisibleElements = function (parent) { }; /** -* Get the bounding box for one or more stroked and/or transformed elements +* Get the bounding box for one or more stroked and/or transformed elements. * @function module:utilities.getStrokedBBoxDefaultVisible * @param {Element[]} elems - Array with DOM elements to check * @returns {module:utilities.BBoxObject} A single bounding box object @@ -1131,13 +1165,13 @@ export const getRotationAngleFromTransformList = function (tlist, toRad) { }; /** -* Get the rotation angle of the given/selected DOM element +* Get the rotation angle of the given/selected DOM element. * @function module:utilities.getRotationAngle * @param {Element} [elem] - DOM element to get the angle for. Default to first of selected elements. * @param {boolean} [toRad=false] - When true returns the value in radians rather than degrees * @returns {Float} The angle in degrees or radians */ -export let getRotationAngle = function (elem, toRad) { +export let getRotationAngle = function (elem, toRad) { // eslint-disable-line import/no-mutable-exports const selected = elem || editorContext_.getSelectedElements()[0]; // find the rotation transform (if any) and set it const tlist = getTransformList(selected); @@ -1145,7 +1179,7 @@ export let getRotationAngle = function (elem, toRad) { }; /** -* Get the reference element associated with the given attribute value +* Get the reference element associated with the given attribute value. * @function module:utilities.getRefElem * @param {string} attrVal - The attribute value as a string * @returns {Element} Reference element @@ -1158,13 +1192,14 @@ export const getRefElem = function (attrVal) { * Get a DOM element by ID within the SVG root element. * @function module:utilities.getElem * @param {string} id - String with the element's new ID -* @returns {Element} +* @returns {?Element} */ export const getElem = (supportsSelectors()) ? function (id) { // querySelector lookup return svgroot_.querySelector('#' + id); - } : supportsXpath() + } + : supportsXpath() ? function (id) { // xpath lookup return domdoc_.evaluate( @@ -1172,7 +1207,8 @@ export const getElem = (supportsSelectors()) domcontainer_, function () { return NS.SVG; }, 9, - null).singleNodeValue; + null + ).singleNodeValue; } : function (id) { // jQuery lookup: twice as slow as xpath in FF @@ -1205,7 +1241,7 @@ export const assignAttributes = function (elem, attrs, suspendLength, unitCheck) }; /** -* Remove unneeded (default) attributes, makes resulting SVG smaller +* Remove unneeded (default) attributes, making resulting SVG smaller. * @function module:utilities.cleanupElement * @param {Element} element - DOM element to clean up * @returns {undefined} @@ -1231,16 +1267,15 @@ export const cleanupElement = function (element) { delete defaults.ry; } - for (const attr in defaults) { - const val = defaults[attr]; + Object.entries(defaults).forEach(([attr, val]) => { if (element.getAttribute(attr) === String(val)) { element.removeAttribute(attr); } - } + }); }; /** -* Round value to for snapping +* Round value to for snapping. * @function module:utilities.snapToGrid * @param {Float} value * @returns {Integer} @@ -1256,7 +1291,7 @@ export const snapToGrid = function (value) { }; /** -* Escapes special characters in a regular expression +* Escapes special characters in a regular expression. * @function module:utilities.regexEscape * @param {string} str * @returns {string} @@ -1267,7 +1302,7 @@ export const regexEscape = function (str) { }; /** - * Prevents default browser click behaviour on the given element + * Prevents default browser click behaviour on the given element. * @function module:utilities.preventClickDefault * @param {Element} img - The DOM element to prevent the click on * @returns {undefined} @@ -1281,7 +1316,7 @@ export const preventClickDefault = function (img) { * @returns {string} The ID */ /** - * Create a clone of an element, updating its ID and its children's IDs when needed + * Create a clone of an element, updating its ID and its children's IDs when needed. * @function module:utilities.copyElem * @param {Element} el - DOM element to clone * @param {module:utilities.GetNextID} getNextId - The getter of the next unique ID. @@ -1333,8 +1368,18 @@ export const copyElem = function (el, getNextId) { }; /** -* Unit testing + * Whether a value is `null` or `undefined`. + * @param {Any} val + * @returns {boolean} + */ +export const isNullish = (val) => { + return val === null || val === undefined; +}; + +/** +* Overwrite methods for unit testing. * @function module:utilities.mock +* @param {PlainObject} mockMethods * @returns {undefined} */ export const mock = ({ diff --git a/editor/xdomain-svg-editor-es.html b/editor/xdomain-svg-editor-es.html index 397763e1..ee1432ed 100644 --- a/editor/xdomain-svg-editor-es.html +++ b/editor/xdomain-svg-editor-es.html @@ -1,4 +1,5 @@ <!DOCTYPE html> +<!-- AUTO-GENERATED FROM svg-editor-es.html; DO NOT EDIT; use build-html.js to build --> <html> <head> <meta charset="utf-8"/> @@ -15,6 +16,7 @@ <!{else}--> <script src="jquery.min.js"></script> <!--{endif}--> + <script nomodule="" src="redirect-on-no-module-support.js"></script> <!-- We keep this next module external to avoid the need to load further scripts if not supported --> <script type="module" src="redirect-on-lacking-support.js"></script> @@ -25,7 +27,7 @@ <!-- The following could be removed for more modern browsers; currently using for at least `String.prototype.includes`, `Array.prototype.includes`, `String.prototype.startsWith` --> - <script src="external/babel-polyfill/polyfill.min.js"></script> + <script src="external/@babel/polyfill/polyfill.min.js"></script> <!-- If you do not wish to add extensions by URL, you can load them by creating the following file and adding by calls to svgEditor.setConfig --> <script type="module" src="xdomain-svgedit-config-es.js"></script> diff --git a/editor/xdomain-svg-editor.html b/editor/xdomain-svg-editor.html index 5cb18f09..050599ee 100644 --- a/editor/xdomain-svg-editor.html +++ b/editor/xdomain-svg-editor.html @@ -16,6 +16,7 @@ <!{else}--> <script src="jquery.min.js"></script> <!--{endif}--> + <!-- We keep this next module external to avoid the need to load further scripts if not supported --> <script defer="defer" src="../dist/redirect-on-lacking-support.js"></script> @@ -26,7 +27,7 @@ <!-- The following could be removed for more modern browsers; currently using for at least `String.prototype.includes`, `Array.prototype.includes`, `String.prototype.startsWith` --> - <script src="external/babel-polyfill/polyfill.min.js"></script> + <script src="external/@babel/polyfill/polyfill.min.js"></script> <!-- If you do not wish to add extensions by URL, you can load them by creating the following file and adding by calls to svgEditor.setConfig --> <script defer="defer" src="xdomain-svgedit-config-iife.js"></script> diff --git a/editor/xdomain-svgedit-config-es.js b/editor/xdomain-svgedit-config-es.js index 8a311e3a..e8d13a58 100644 --- a/editor/xdomain-svgedit-config-es.js +++ b/editor/xdomain-svgedit-config-es.js @@ -1,4 +1,6 @@ import svgEditor from './svg-editor.js'; + svgEditor.setConfig({ + canvasName: 'xdomain', // Namespace this allowedOrigins: ['*'] }); diff --git a/editor/xdomain-svgedit-config-iife.js b/editor/xdomain-svgedit-config-iife.js index 80374b57..f44144e7 100644 --- a/editor/xdomain-svgedit-config-iife.js +++ b/editor/xdomain-svgedit-config-iife.js @@ -1,20 +1,226 @@ (function () { 'use strict'; + function _typeof(obj) { + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); + } + + function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { + try { + var info = gen[key](arg); + var value = info.value; + } catch (error) { + reject(error); + return; + } + + if (info.done) { + resolve(value); + } else { + Promise.resolve(value).then(_next, _throw); + } + } + + function _asyncToGenerator(fn) { + return function () { + var self = this, + args = arguments; + return new Promise(function (resolve, reject) { + var gen = fn.apply(self, args); + + function _next(value) { + asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); + } + + function _throw(err) { + asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); + } + + _next(undefined); + }); + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } + + function _extends() { + _extends = Object.assign || function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target; + }; + + return _extends.apply(this, arguments); + } + + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf(subClass, superClass); + } + + function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); + } + + function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + return _setPrototypeOf(o, p); + } + + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; + } + + function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } + + return _assertThisInitialized(self); + } + + function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); + } + + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); + } + + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) { + for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; + + return arr2; + } + } + + function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; + } + + function _iterableToArray(iter) { + if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); + } + + function _iterableToArrayLimit(arr, i) { + var _arr = []; + var _n = true; + var _d = false; + var _e = undefined; + + try { + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; + } + } + + return _arr; + } + + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance"); + } + + function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance"); + } + // http://ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript/ + + /** + * + * @param {Event} ev + * @returns {undefined} + */ function touchHandler(ev) { var changedTouches = ev.changedTouches, first = changedTouches[0]; - - var type = ''; + switch (ev.type) { case 'touchstart': - type = 'mousedown';break; + type = 'mousedown'; + break; + case 'touchmove': - type = 'mousemove';break; + type = 'mousemove'; + break; + case 'touchend': - type = 'mouseup';break; + type = 'mouseup'; + break; + default: return; } @@ -22,7 +228,7 @@ var screenX = first.screenX, screenY = first.screenY, clientX = first.clientX, - clientY = first.clientY; + clientY = first.clientY; // eslint-disable-line no-shadow var simulatedEvent = new MouseEvent(type, { // Event interface @@ -30,17 +236,23 @@ cancelable: true, // UIEvent interface view: window, - detail: 1, // click count + detail: 1, + // click count // MouseEvent interface (customized) - screenX: screenX, screenY: screenY, clientX: clientX, clientY: clientY, + screenX: screenX, + screenY: screenY, + clientX: clientX, + clientY: clientY, // MouseEvent interface (defaults) - these could be removed ctrlKey: false, altKey: false, shiftKey: false, metaKey: false, - button: 0, // main button (usually left) + button: 0, + // main button (usually left) relatedTarget: null }); + if (changedTouches.length < 2) { first.target.dispatchEvent(simulatedEvent); ev.preventDefault(); @@ -52,151 +264,6 @@ document.addEventListener('touchend', touchHandler, true); document.addEventListener('touchcancel', touchHandler, true); - var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { - return typeof obj; - } : function (obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; - }; - - var asyncToGenerator = function (fn) { - return function () { - var gen = fn.apply(this, arguments); - return new Promise(function (resolve, reject) { - function step(key, arg) { - try { - var info = gen[key](arg); - var value = info.value; - } catch (error) { - reject(error); - return; - } - - if (info.done) { - resolve(value); - } else { - return Promise.resolve(value).then(function (value) { - step("next", value); - }, function (err) { - step("throw", err); - }); - } - } - - return step("next"); - }); - }; - }; - - var classCallCheck = function (instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } - }; - - var createClass = function () { - function defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } - } - - return function (Constructor, protoProps, staticProps) { - if (protoProps) defineProperties(Constructor.prototype, protoProps); - if (staticProps) defineProperties(Constructor, staticProps); - return Constructor; - }; - }(); - - var _extends = Object.assign || function (target) { - for (var i = 1; i < arguments.length; i++) { - var source = arguments[i]; - - for (var key in source) { - if (Object.prototype.hasOwnProperty.call(source, key)) { - target[key] = source[key]; - } - } - } - - return target; - }; - - var inherits = function (subClass, superClass) { - if (typeof superClass !== "function" && superClass !== null) { - throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); - } - - subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - value: subClass, - enumerable: false, - writable: true, - configurable: true - } - }); - if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; - }; - - var possibleConstructorReturn = function (self, call) { - if (!self) { - throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); - } - - return call && (typeof call === "object" || typeof call === "function") ? call : self; - }; - - var slicedToArray = function () { - function sliceIterator(arr, i) { - var _arr = []; - var _n = true; - var _d = false; - var _e = undefined; - - try { - for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { - _arr.push(_s.value); - - if (i && _arr.length === i) break; - } - } catch (err) { - _d = true; - _e = err; - } finally { - try { - if (!_n && _i["return"]) _i["return"](); - } finally { - if (_d) throw _e; - } - } - - return _arr; - } - - return function (arr, i) { - if (Array.isArray(arr)) { - return arr; - } else if (Symbol.iterator in Object(arr)) { - return sliceIterator(arr, i); - } else { - throw new TypeError("Invalid attempt to destructure non-iterable instance"); - } - }; - }(); - - var toConsumableArray = function (arr) { - if (Array.isArray(arr)) { - for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; - - return arr2; - } else { - return Array.from(arr); - } - }; - /** * Namespaces or tools therefor * @module namespaces @@ -217,16 +284,17 @@ XLINK: 'http://www.w3.org/1999/xlink', XML: 'http://www.w3.org/XML/1998/namespace', XMLNS: 'http://www.w3.org/2000/xmlns/' // see http://www.w3.org/TR/REC-xml-names/#xmlReserved - }; + }; /** * @function module:namespaces.getReverseNS * @returns {string} The NS with key values switched and lowercase */ + var getReverseNS = function getReverseNS() { var reverseNS = {}; Object.entries(NS).forEach(function (_ref) { - var _ref2 = slicedToArray(_ref, 2), + var _ref2 = _slicedToArray(_ref, 2), name = _ref2[0], URI = _ref2[1]; @@ -244,6 +312,7 @@ SVGPathSegCurvetoCubicSmoothAbs, SVGPathSegCurvetoQuadraticRel, SVGPathSegCurvetoQuadraticAbs, SVGPathSegCurvetoQuadraticSmoothRel, SVGPathSegCurvetoQuadraticSmoothAbs, SVGPathSegArcRel, SVGPathSegArcAbs */ + /** * SVGPathSeg API polyfill * https://github.com/progers/pathseg @@ -253,33 +322,39 @@ * including the latest spec changes which were implemented in Firefox 43 and * Chrome 46. */ + + /* eslint-disable no-shadow, class-methods-use-this */ + // Linting: We avoid `no-shadow` as ESLint thinks these are still available globals + // Linting: We avoid `class-methods-use-this` as this is a polyfill that must + // follow the conventions (function () { if (!('SVGPathSeg' in window)) { // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSeg - var _SVGPathSeg = function () { + var _SVGPathSeg = + /*#__PURE__*/ + function () { function _SVGPathSeg(type, typeAsLetter, owningPathSegList) { - classCallCheck(this, _SVGPathSeg); + _classCallCheck(this, _SVGPathSeg); this.pathSegType = type; this.pathSegTypeAsLetter = typeAsLetter; this._owningPathSegList = owningPathSegList; - } - // Notify owning PathSegList on any changes so they can be synchronized back to the path element. + } // Notify owning PathSegList on any changes so they can be synchronized back to the path element. - createClass(_SVGPathSeg, [{ - key: '_segmentChanged', + _createClass(_SVGPathSeg, [{ + key: "_segmentChanged", value: function _segmentChanged() { if (this._owningPathSegList) { this._owningPathSegList.segmentChanged(this); } } }]); + return _SVGPathSeg; }(); _SVGPathSeg.prototype.classname = 'SVGPathSeg'; - _SVGPathSeg.PATHSEG_UNKNOWN = 0; _SVGPathSeg.PATHSEG_CLOSEPATH = 1; _SVGPathSeg.PATHSEG_MOVETO_ABS = 2; @@ -301,247 +376,401 @@ _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18; _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19; - var _SVGPathSegClosePath = function (_SVGPathSeg2) { - inherits(_SVGPathSegClosePath, _SVGPathSeg2); + var _SVGPathSegClosePath = + /*#__PURE__*/ + function (_SVGPathSeg2) { + _inherits(_SVGPathSegClosePath, _SVGPathSeg2); function _SVGPathSegClosePath(owningPathSegList) { - classCallCheck(this, _SVGPathSegClosePath); - return possibleConstructorReturn(this, (_SVGPathSegClosePath.__proto__ || Object.getPrototypeOf(_SVGPathSegClosePath)).call(this, _SVGPathSeg.PATHSEG_CLOSEPATH, 'z', owningPathSegList)); + _classCallCheck(this, _SVGPathSegClosePath); + + return _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegClosePath).call(this, _SVGPathSeg.PATHSEG_CLOSEPATH, 'z', owningPathSegList)); } - createClass(_SVGPathSegClosePath, [{ - key: 'toString', + _createClass(_SVGPathSegClosePath, [{ + key: "toString", value: function toString() { return '[object SVGPathSegClosePath]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegClosePath(undefined); } }]); + return _SVGPathSegClosePath; }(_SVGPathSeg); - var _SVGPathSegMovetoAbs = function (_SVGPathSeg3) { - inherits(_SVGPathSegMovetoAbs, _SVGPathSeg3); + var _SVGPathSegMovetoAbs = + /*#__PURE__*/ + function (_SVGPathSeg3) { + _inherits(_SVGPathSegMovetoAbs, _SVGPathSeg3); function _SVGPathSegMovetoAbs(owningPathSegList, x, y) { - classCallCheck(this, _SVGPathSegMovetoAbs); + var _this; - var _this2 = possibleConstructorReturn(this, (_SVGPathSegMovetoAbs.__proto__ || Object.getPrototypeOf(_SVGPathSegMovetoAbs)).call(this, _SVGPathSeg.PATHSEG_MOVETO_ABS, 'M', owningPathSegList)); + _classCallCheck(this, _SVGPathSegMovetoAbs); - _this2._x = x; - _this2._y = y; - return _this2; + _this = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegMovetoAbs).call(this, _SVGPathSeg.PATHSEG_MOVETO_ABS, 'M', owningPathSegList)); + _this._x = x; + _this._y = y; + return _this; } - createClass(_SVGPathSegMovetoAbs, [{ - key: 'toString', + _createClass(_SVGPathSegMovetoAbs, [{ + key: "toString", value: function toString() { return '[object SVGPathSegMovetoAbs]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegMovetoAbs(undefined, this._x, this._y); } }]); + return _SVGPathSegMovetoAbs; }(_SVGPathSeg); Object.defineProperties(_SVGPathSegMovetoAbs.prototype, { x: { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); + set: function set(x) { + this._x = x; + + this._segmentChanged(); }, enumerable: true }, y: { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); + set: function set(y) { + this._y = y; + + this._segmentChanged(); }, enumerable: true } }); - var _SVGPathSegMovetoRel = function (_SVGPathSeg4) { - inherits(_SVGPathSegMovetoRel, _SVGPathSeg4); + var _SVGPathSegMovetoRel = + /*#__PURE__*/ + function (_SVGPathSeg4) { + _inherits(_SVGPathSegMovetoRel, _SVGPathSeg4); function _SVGPathSegMovetoRel(owningPathSegList, x, y) { - classCallCheck(this, _SVGPathSegMovetoRel); + var _this2; - var _this3 = possibleConstructorReturn(this, (_SVGPathSegMovetoRel.__proto__ || Object.getPrototypeOf(_SVGPathSegMovetoRel)).call(this, _SVGPathSeg.PATHSEG_MOVETO_REL, 'm', owningPathSegList)); + _classCallCheck(this, _SVGPathSegMovetoRel); - _this3._x = x; - _this3._y = y; - return _this3; + _this2 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegMovetoRel).call(this, _SVGPathSeg.PATHSEG_MOVETO_REL, 'm', owningPathSegList)); + _this2._x = x; + _this2._y = y; + return _this2; } - createClass(_SVGPathSegMovetoRel, [{ - key: 'toString', + _createClass(_SVGPathSegMovetoRel, [{ + key: "toString", value: function toString() { return '[object SVGPathSegMovetoRel]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegMovetoRel(undefined, this._x, this._y); } }]); + return _SVGPathSegMovetoRel; }(_SVGPathSeg); Object.defineProperties(_SVGPathSegMovetoRel.prototype, { x: { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); + set: function set(x) { + this._x = x; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y: { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); + set: function set(y) { + this._y = y; + + this._segmentChanged(); }, - enumerable: true } + enumerable: true + } }); - var _SVGPathSegLinetoAbs = function (_SVGPathSeg5) { - inherits(_SVGPathSegLinetoAbs, _SVGPathSeg5); + var _SVGPathSegLinetoAbs = + /*#__PURE__*/ + function (_SVGPathSeg5) { + _inherits(_SVGPathSegLinetoAbs, _SVGPathSeg5); function _SVGPathSegLinetoAbs(owningPathSegList, x, y) { - classCallCheck(this, _SVGPathSegLinetoAbs); + var _this3; - var _this4 = possibleConstructorReturn(this, (_SVGPathSegLinetoAbs.__proto__ || Object.getPrototypeOf(_SVGPathSegLinetoAbs)).call(this, _SVGPathSeg.PATHSEG_LINETO_ABS, 'L', owningPathSegList)); + _classCallCheck(this, _SVGPathSegLinetoAbs); - _this4._x = x; - _this4._y = y; - return _this4; + _this3 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegLinetoAbs).call(this, _SVGPathSeg.PATHSEG_LINETO_ABS, 'L', owningPathSegList)); + _this3._x = x; + _this3._y = y; + return _this3; } - createClass(_SVGPathSegLinetoAbs, [{ - key: 'toString', + _createClass(_SVGPathSegLinetoAbs, [{ + key: "toString", value: function toString() { return '[object SVGPathSegLinetoAbs]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegLinetoAbs(undefined, this._x, this._y); } }]); + return _SVGPathSegLinetoAbs; }(_SVGPathSeg); Object.defineProperties(_SVGPathSegLinetoAbs.prototype, { x: { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); + set: function set(x) { + this._x = x; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y: { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); + set: function set(y) { + this._y = y; + + this._segmentChanged(); }, - enumerable: true } + enumerable: true + } }); - var _SVGPathSegLinetoRel = function (_SVGPathSeg6) { - inherits(_SVGPathSegLinetoRel, _SVGPathSeg6); + var _SVGPathSegLinetoRel = + /*#__PURE__*/ + function (_SVGPathSeg6) { + _inherits(_SVGPathSegLinetoRel, _SVGPathSeg6); function _SVGPathSegLinetoRel(owningPathSegList, x, y) { - classCallCheck(this, _SVGPathSegLinetoRel); + var _this4; - var _this5 = possibleConstructorReturn(this, (_SVGPathSegLinetoRel.__proto__ || Object.getPrototypeOf(_SVGPathSegLinetoRel)).call(this, _SVGPathSeg.PATHSEG_LINETO_REL, 'l', owningPathSegList)); + _classCallCheck(this, _SVGPathSegLinetoRel); - _this5._x = x; - _this5._y = y; - return _this5; + _this4 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegLinetoRel).call(this, _SVGPathSeg.PATHSEG_LINETO_REL, 'l', owningPathSegList)); + _this4._x = x; + _this4._y = y; + return _this4; } - createClass(_SVGPathSegLinetoRel, [{ - key: 'toString', + _createClass(_SVGPathSegLinetoRel, [{ + key: "toString", value: function toString() { return '[object SVGPathSegLinetoRel]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegLinetoRel(undefined, this._x, this._y); } }]); + return _SVGPathSegLinetoRel; }(_SVGPathSeg); Object.defineProperties(_SVGPathSegLinetoRel.prototype, { x: { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); + set: function set(x) { + this._x = x; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y: { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); + set: function set(y) { + this._y = y; + + this._segmentChanged(); }, - enumerable: true } + enumerable: true + } }); - var _SVGPathSegCurvetoCubicAbs = function (_SVGPathSeg7) { - inherits(_SVGPathSegCurvetoCubicAbs, _SVGPathSeg7); + var _SVGPathSegCurvetoCubicAbs = + /*#__PURE__*/ + function (_SVGPathSeg7) { + _inherits(_SVGPathSegCurvetoCubicAbs, _SVGPathSeg7); function _SVGPathSegCurvetoCubicAbs(owningPathSegList, x, y, x1, y1, x2, y2) { - classCallCheck(this, _SVGPathSegCurvetoCubicAbs); + var _this5; - var _this6 = possibleConstructorReturn(this, (_SVGPathSegCurvetoCubicAbs.__proto__ || Object.getPrototypeOf(_SVGPathSegCurvetoCubicAbs)).call(this, _SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS, 'C', owningPathSegList)); + _classCallCheck(this, _SVGPathSegCurvetoCubicAbs); + _this5 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegCurvetoCubicAbs).call(this, _SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS, 'C', owningPathSegList)); + _this5._x = x; + _this5._y = y; + _this5._x1 = x1; + _this5._y1 = y1; + _this5._x2 = x2; + _this5._y2 = y2; + return _this5; + } + + _createClass(_SVGPathSegCurvetoCubicAbs, [{ + key: "toString", + value: function toString() { + return '[object SVGPathSegCurvetoCubicAbs]'; + } + }, { + key: "_asPathString", + value: function _asPathString() { + return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; + } + }, { + key: "clone", + value: function clone() { + return new _SVGPathSegCurvetoCubicAbs(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); + } + }]); + + return _SVGPathSegCurvetoCubicAbs; + }(_SVGPathSeg); + + Object.defineProperties(_SVGPathSegCurvetoCubicAbs.prototype, { + x: { + get: function get() { + return this._x; + }, + set: function set(x) { + this._x = x; + + this._segmentChanged(); + }, + enumerable: true + }, + y: { + get: function get() { + return this._y; + }, + set: function set(y) { + this._y = y; + + this._segmentChanged(); + }, + enumerable: true + }, + x1: { + get: function get() { + return this._x1; + }, + set: function set(x1) { + this._x1 = x1; + + this._segmentChanged(); + }, + enumerable: true + }, + y1: { + get: function get() { + return this._y1; + }, + set: function set(y1) { + this._y1 = y1; + + this._segmentChanged(); + }, + enumerable: true + }, + x2: { + get: function get() { + return this._x2; + }, + set: function set(x2) { + this._x2 = x2; + + this._segmentChanged(); + }, + enumerable: true + }, + y2: { + get: function get() { + return this._y2; + }, + set: function set(y2) { + this._y2 = y2; + + this._segmentChanged(); + }, + enumerable: true + } + }); + + var _SVGPathSegCurvetoCubicRel = + /*#__PURE__*/ + function (_SVGPathSeg8) { + _inherits(_SVGPathSegCurvetoCubicRel, _SVGPathSeg8); + + function _SVGPathSegCurvetoCubicRel(owningPathSegList, x, y, x1, y1, x2, y2) { + var _this6; + + _classCallCheck(this, _SVGPathSegCurvetoCubicRel); + + _this6 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegCurvetoCubicRel).call(this, _SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, 'c', owningPathSegList)); _this6._x = x; _this6._y = y; _this6._x1 = x1; @@ -551,171 +780,191 @@ return _this6; } - createClass(_SVGPathSegCurvetoCubicAbs, [{ - key: 'toString', - value: function toString() { - return '[object SVGPathSegCurvetoCubicAbs]'; - } - }, { - key: '_asPathString', - value: function _asPathString() { - return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; - } - }, { - key: 'clone', - value: function clone() { - return new _SVGPathSegCurvetoCubicAbs(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); - } - }]); - return _SVGPathSegCurvetoCubicAbs; - }(_SVGPathSeg); - - Object.defineProperties(_SVGPathSegCurvetoCubicAbs.prototype, { - x: { - get: function get$$1() { - return this._x; - }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); - }, - enumerable: true }, - y: { - get: function get$$1() { - return this._y; - }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); - }, - enumerable: true }, - x1: { - get: function get$$1() { - return this._x1; - }, - set: function set$$1(x1) { - this._x1 = x1;this._segmentChanged(); - }, - enumerable: true }, - y1: { - get: function get$$1() { - return this._y1; - }, - set: function set$$1(y1) { - this._y1 = y1;this._segmentChanged(); - }, - enumerable: true }, - x2: { - get: function get$$1() { - return this._x2; - }, - set: function set$$1(x2) { - this._x2 = x2;this._segmentChanged(); - }, - enumerable: true }, - y2: { - get: function get$$1() { - return this._y2; - }, - set: function set$$1(y2) { - this._y2 = y2;this._segmentChanged(); - }, - enumerable: true } - }); - - var _SVGPathSegCurvetoCubicRel = function (_SVGPathSeg8) { - inherits(_SVGPathSegCurvetoCubicRel, _SVGPathSeg8); - - function _SVGPathSegCurvetoCubicRel(owningPathSegList, x, y, x1, y1, x2, y2) { - classCallCheck(this, _SVGPathSegCurvetoCubicRel); - - var _this7 = possibleConstructorReturn(this, (_SVGPathSegCurvetoCubicRel.__proto__ || Object.getPrototypeOf(_SVGPathSegCurvetoCubicRel)).call(this, _SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, 'c', owningPathSegList)); - - _this7._x = x; - _this7._y = y; - _this7._x1 = x1; - _this7._y1 = y1; - _this7._x2 = x2; - _this7._y2 = y2; - return _this7; - } - - createClass(_SVGPathSegCurvetoCubicRel, [{ - key: 'toString', + _createClass(_SVGPathSegCurvetoCubicRel, [{ + key: "toString", value: function toString() { return '[object SVGPathSegCurvetoCubicRel]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegCurvetoCubicRel(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); } }]); + return _SVGPathSegCurvetoCubicRel; }(_SVGPathSeg); Object.defineProperties(_SVGPathSegCurvetoCubicRel.prototype, { x: { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); + set: function set(x) { + this._x = x; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y: { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); + set: function set(y) { + this._y = y; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, x1: { - get: function get$$1() { + get: function get() { return this._x1; }, - set: function set$$1(x1) { - this._x1 = x1;this._segmentChanged(); + set: function set(x1) { + this._x1 = x1; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y1: { - get: function get$$1() { + get: function get() { return this._y1; }, - set: function set$$1(y1) { - this._y1 = y1;this._segmentChanged(); + set: function set(y1) { + this._y1 = y1; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, x2: { - get: function get$$1() { + get: function get() { return this._x2; }, - set: function set$$1(x2) { - this._x2 = x2;this._segmentChanged(); + set: function set(x2) { + this._x2 = x2; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y2: { - get: function get$$1() { + get: function get() { return this._y2; }, - set: function set$$1(y2) { - this._y2 = y2;this._segmentChanged(); + set: function set(y2) { + this._y2 = y2; + + this._segmentChanged(); }, - enumerable: true } + enumerable: true + } }); - var _SVGPathSegCurvetoQuadraticAbs = function (_SVGPathSeg9) { - inherits(_SVGPathSegCurvetoQuadraticAbs, _SVGPathSeg9); + var _SVGPathSegCurvetoQuadraticAbs = + /*#__PURE__*/ + function (_SVGPathSeg9) { + _inherits(_SVGPathSegCurvetoQuadraticAbs, _SVGPathSeg9); function _SVGPathSegCurvetoQuadraticAbs(owningPathSegList, x, y, x1, y1) { - classCallCheck(this, _SVGPathSegCurvetoQuadraticAbs); + var _this7; - var _this8 = possibleConstructorReturn(this, (_SVGPathSegCurvetoQuadraticAbs.__proto__ || Object.getPrototypeOf(_SVGPathSegCurvetoQuadraticAbs)).call(this, _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS, 'Q', owningPathSegList)); + _classCallCheck(this, _SVGPathSegCurvetoQuadraticAbs); + _this7 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegCurvetoQuadraticAbs).call(this, _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS, 'Q', owningPathSegList)); + _this7._x = x; + _this7._y = y; + _this7._x1 = x1; + _this7._y1 = y1; + return _this7; + } + + _createClass(_SVGPathSegCurvetoQuadraticAbs, [{ + key: "toString", + value: function toString() { + return '[object SVGPathSegCurvetoQuadraticAbs]'; + } + }, { + key: "_asPathString", + value: function _asPathString() { + return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x + ' ' + this._y; + } + }, { + key: "clone", + value: function clone() { + return new _SVGPathSegCurvetoQuadraticAbs(undefined, this._x, this._y, this._x1, this._y1); + } + }]); + + return _SVGPathSegCurvetoQuadraticAbs; + }(_SVGPathSeg); + + Object.defineProperties(_SVGPathSegCurvetoQuadraticAbs.prototype, { + x: { + get: function get() { + return this._x; + }, + set: function set(x) { + this._x = x; + + this._segmentChanged(); + }, + enumerable: true + }, + y: { + get: function get() { + return this._y; + }, + set: function set(y) { + this._y = y; + + this._segmentChanged(); + }, + enumerable: true + }, + x1: { + get: function get() { + return this._x1; + }, + set: function set(x1) { + this._x1 = x1; + + this._segmentChanged(); + }, + enumerable: true + }, + y1: { + get: function get() { + return this._y1; + }, + set: function set(y1) { + this._y1 = y1; + + this._segmentChanged(); + }, + enumerable: true + } + }); + + var _SVGPathSegCurvetoQuadraticRel = + /*#__PURE__*/ + function (_SVGPathSeg10) { + _inherits(_SVGPathSegCurvetoQuadraticRel, _SVGPathSeg10); + + function _SVGPathSegCurvetoQuadraticRel(owningPathSegList, x, y, x1, y1) { + var _this8; + + _classCallCheck(this, _SVGPathSegCurvetoQuadraticRel); + + _this8 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegCurvetoQuadraticRel).call(this, _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL, 'q', owningPathSegList)); _this8._x = x; _this8._y = y; _this8._x1 = x1; @@ -723,137 +972,205 @@ return _this8; } - createClass(_SVGPathSegCurvetoQuadraticAbs, [{ - key: 'toString', - value: function toString() { - return '[object SVGPathSegCurvetoQuadraticAbs]'; - } - }, { - key: '_asPathString', - value: function _asPathString() { - return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x + ' ' + this._y; - } - }, { - key: 'clone', - value: function clone() { - return new _SVGPathSegCurvetoQuadraticAbs(undefined, this._x, this._y, this._x1, this._y1); - } - }]); - return _SVGPathSegCurvetoQuadraticAbs; - }(_SVGPathSeg); - - Object.defineProperties(_SVGPathSegCurvetoQuadraticAbs.prototype, { - x: { - get: function get$$1() { - return this._x; - }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); - }, - enumerable: true }, - y: { - get: function get$$1() { - return this._y; - }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); - }, - enumerable: true }, - x1: { - get: function get$$1() { - return this._x1; - }, - set: function set$$1(x1) { - this._x1 = x1;this._segmentChanged(); - }, - enumerable: true }, - y1: { - get: function get$$1() { - return this._y1; - }, - set: function set$$1(y1) { - this._y1 = y1;this._segmentChanged(); - }, - enumerable: true } - }); - - var _SVGPathSegCurvetoQuadraticRel = function (_SVGPathSeg10) { - inherits(_SVGPathSegCurvetoQuadraticRel, _SVGPathSeg10); - - function _SVGPathSegCurvetoQuadraticRel(owningPathSegList, x, y, x1, y1) { - classCallCheck(this, _SVGPathSegCurvetoQuadraticRel); - - var _this9 = possibleConstructorReturn(this, (_SVGPathSegCurvetoQuadraticRel.__proto__ || Object.getPrototypeOf(_SVGPathSegCurvetoQuadraticRel)).call(this, _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL, 'q', owningPathSegList)); - - _this9._x = x; - _this9._y = y; - _this9._x1 = x1; - _this9._y1 = y1; - return _this9; - } - - createClass(_SVGPathSegCurvetoQuadraticRel, [{ - key: 'toString', + _createClass(_SVGPathSegCurvetoQuadraticRel, [{ + key: "toString", value: function toString() { return '[object SVGPathSegCurvetoQuadraticRel]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegCurvetoQuadraticRel(undefined, this._x, this._y, this._x1, this._y1); } }]); + return _SVGPathSegCurvetoQuadraticRel; }(_SVGPathSeg); Object.defineProperties(_SVGPathSegCurvetoQuadraticRel.prototype, { x: { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); + set: function set(x) { + this._x = x; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y: { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); + set: function set(y) { + this._y = y; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, x1: { - get: function get$$1() { + get: function get() { return this._x1; }, - set: function set$$1(x1) { - this._x1 = x1;this._segmentChanged(); + set: function set(x1) { + this._x1 = x1; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y1: { - get: function get$$1() { + get: function get() { return this._y1; }, - set: function set$$1(y1) { - this._y1 = y1;this._segmentChanged(); + set: function set(y1) { + this._y1 = y1; + + this._segmentChanged(); }, - enumerable: true } + enumerable: true + } }); - var _SVGPathSegArcAbs = function (_SVGPathSeg11) { - inherits(_SVGPathSegArcAbs, _SVGPathSeg11); + var _SVGPathSegArcAbs = + /*#__PURE__*/ + function (_SVGPathSeg11) { + _inherits(_SVGPathSegArcAbs, _SVGPathSeg11); function _SVGPathSegArcAbs(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) { - classCallCheck(this, _SVGPathSegArcAbs); + var _this9; - var _this10 = possibleConstructorReturn(this, (_SVGPathSegArcAbs.__proto__ || Object.getPrototypeOf(_SVGPathSegArcAbs)).call(this, _SVGPathSeg.PATHSEG_ARC_ABS, 'A', owningPathSegList)); + _classCallCheck(this, _SVGPathSegArcAbs); + _this9 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegArcAbs).call(this, _SVGPathSeg.PATHSEG_ARC_ABS, 'A', owningPathSegList)); + _this9._x = x; + _this9._y = y; + _this9._r1 = r1; + _this9._r2 = r2; + _this9._angle = angle; + _this9._largeArcFlag = largeArcFlag; + _this9._sweepFlag = sweepFlag; + return _this9; + } + + _createClass(_SVGPathSegArcAbs, [{ + key: "toString", + value: function toString() { + return '[object SVGPathSegArcAbs]'; + } + }, { + key: "_asPathString", + value: function _asPathString() { + return this.pathSegTypeAsLetter + ' ' + this._r1 + ' ' + this._r2 + ' ' + this._angle + ' ' + (this._largeArcFlag ? '1' : '0') + ' ' + (this._sweepFlag ? '1' : '0') + ' ' + this._x + ' ' + this._y; + } + }, { + key: "clone", + value: function clone() { + return new _SVGPathSegArcAbs(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); + } + }]); + + return _SVGPathSegArcAbs; + }(_SVGPathSeg); + + Object.defineProperties(_SVGPathSegArcAbs.prototype, { + x: { + get: function get() { + return this._x; + }, + set: function set(x) { + this._x = x; + + this._segmentChanged(); + }, + enumerable: true + }, + y: { + get: function get() { + return this._y; + }, + set: function set(y) { + this._y = y; + + this._segmentChanged(); + }, + enumerable: true + }, + r1: { + get: function get() { + return this._r1; + }, + set: function set(r1) { + this._r1 = r1; + + this._segmentChanged(); + }, + enumerable: true + }, + r2: { + get: function get() { + return this._r2; + }, + set: function set(r2) { + this._r2 = r2; + + this._segmentChanged(); + }, + enumerable: true + }, + angle: { + get: function get() { + return this._angle; + }, + set: function set(angle) { + this._angle = angle; + + this._segmentChanged(); + }, + enumerable: true + }, + largeArcFlag: { + get: function get() { + return this._largeArcFlag; + }, + set: function set(largeArcFlag) { + this._largeArcFlag = largeArcFlag; + + this._segmentChanged(); + }, + enumerable: true + }, + sweepFlag: { + get: function get() { + return this._sweepFlag; + }, + set: function set(sweepFlag) { + this._sweepFlag = sweepFlag; + + this._segmentChanged(); + }, + enumerable: true + } + }); + + var _SVGPathSegArcRel = + /*#__PURE__*/ + function (_SVGPathSeg12) { + _inherits(_SVGPathSegArcRel, _SVGPathSeg12); + + function _SVGPathSegArcRel(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) { + var _this10; + + _classCallCheck(this, _SVGPathSegArcRel); + + _this10 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegArcRel).call(this, _SVGPathSeg.PATHSEG_ARC_REL, 'a', owningPathSegList)); _this10._x = x; _this10._y = y; _this10._r1 = r1; @@ -864,348 +1181,390 @@ return _this10; } - createClass(_SVGPathSegArcAbs, [{ - key: 'toString', - value: function toString() { - return '[object SVGPathSegArcAbs]'; - } - }, { - key: '_asPathString', - value: function _asPathString() { - return this.pathSegTypeAsLetter + ' ' + this._r1 + ' ' + this._r2 + ' ' + this._angle + ' ' + (this._largeArcFlag ? '1' : '0') + ' ' + (this._sweepFlag ? '1' : '0') + ' ' + this._x + ' ' + this._y; - } - }, { - key: 'clone', - value: function clone() { - return new _SVGPathSegArcAbs(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); - } - }]); - return _SVGPathSegArcAbs; - }(_SVGPathSeg); - - Object.defineProperties(_SVGPathSegArcAbs.prototype, { - x: { - get: function get$$1() { - return this._x; - }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); - }, - enumerable: true }, - y: { - get: function get$$1() { - return this._y; - }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); - }, - enumerable: true }, - r1: { - get: function get$$1() { - return this._r1; - }, - set: function set$$1(r1) { - this._r1 = r1;this._segmentChanged(); - }, - enumerable: true }, - r2: { - get: function get$$1() { - return this._r2; - }, - set: function set$$1(r2) { - this._r2 = r2;this._segmentChanged(); - }, - enumerable: true }, - angle: { - get: function get$$1() { - return this._angle; - }, - set: function set$$1(angle) { - this._angle = angle;this._segmentChanged(); - }, - enumerable: true }, - largeArcFlag: { - get: function get$$1() { - return this._largeArcFlag; - }, - set: function set$$1(largeArcFlag) { - this._largeArcFlag = largeArcFlag;this._segmentChanged(); - }, - enumerable: true }, - sweepFlag: { - get: function get$$1() { - return this._sweepFlag; - }, - set: function set$$1(sweepFlag) { - this._sweepFlag = sweepFlag;this._segmentChanged(); - }, - enumerable: true } - }); - - var _SVGPathSegArcRel = function (_SVGPathSeg12) { - inherits(_SVGPathSegArcRel, _SVGPathSeg12); - - function _SVGPathSegArcRel(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) { - classCallCheck(this, _SVGPathSegArcRel); - - var _this11 = possibleConstructorReturn(this, (_SVGPathSegArcRel.__proto__ || Object.getPrototypeOf(_SVGPathSegArcRel)).call(this, _SVGPathSeg.PATHSEG_ARC_REL, 'a', owningPathSegList)); - - _this11._x = x; - _this11._y = y; - _this11._r1 = r1; - _this11._r2 = r2; - _this11._angle = angle; - _this11._largeArcFlag = largeArcFlag; - _this11._sweepFlag = sweepFlag; - return _this11; - } - - createClass(_SVGPathSegArcRel, [{ - key: 'toString', + _createClass(_SVGPathSegArcRel, [{ + key: "toString", value: function toString() { return '[object SVGPathSegArcRel]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._r1 + ' ' + this._r2 + ' ' + this._angle + ' ' + (this._largeArcFlag ? '1' : '0') + ' ' + (this._sweepFlag ? '1' : '0') + ' ' + this._x + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegArcRel(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); } }]); + return _SVGPathSegArcRel; }(_SVGPathSeg); Object.defineProperties(_SVGPathSegArcRel.prototype, { x: { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); + set: function set(x) { + this._x = x; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y: { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); + set: function set(y) { + this._y = y; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, r1: { - get: function get$$1() { + get: function get() { return this._r1; }, - set: function set$$1(r1) { - this._r1 = r1;this._segmentChanged(); + set: function set(r1) { + this._r1 = r1; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, r2: { - get: function get$$1() { + get: function get() { return this._r2; }, - set: function set$$1(r2) { - this._r2 = r2;this._segmentChanged(); + set: function set(r2) { + this._r2 = r2; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, angle: { - get: function get$$1() { + get: function get() { return this._angle; }, - set: function set$$1(angle) { - this._angle = angle;this._segmentChanged(); + set: function set(angle) { + this._angle = angle; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, largeArcFlag: { - get: function get$$1() { + get: function get() { return this._largeArcFlag; }, - set: function set$$1(largeArcFlag) { - this._largeArcFlag = largeArcFlag;this._segmentChanged(); + set: function set(largeArcFlag) { + this._largeArcFlag = largeArcFlag; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, sweepFlag: { - get: function get$$1() { + get: function get() { return this._sweepFlag; }, - set: function set$$1(sweepFlag) { - this._sweepFlag = sweepFlag;this._segmentChanged(); + set: function set(sweepFlag) { + this._sweepFlag = sweepFlag; + + this._segmentChanged(); }, - enumerable: true } + enumerable: true + } }); - var _SVGPathSegLinetoHorizontalAbs = function (_SVGPathSeg13) { - inherits(_SVGPathSegLinetoHorizontalAbs, _SVGPathSeg13); + var _SVGPathSegLinetoHorizontalAbs = + /*#__PURE__*/ + function (_SVGPathSeg13) { + _inherits(_SVGPathSegLinetoHorizontalAbs, _SVGPathSeg13); function _SVGPathSegLinetoHorizontalAbs(owningPathSegList, x) { - classCallCheck(this, _SVGPathSegLinetoHorizontalAbs); + var _this11; - var _this12 = possibleConstructorReturn(this, (_SVGPathSegLinetoHorizontalAbs.__proto__ || Object.getPrototypeOf(_SVGPathSegLinetoHorizontalAbs)).call(this, _SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS, 'H', owningPathSegList)); + _classCallCheck(this, _SVGPathSegLinetoHorizontalAbs); - _this12._x = x; - return _this12; + _this11 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegLinetoHorizontalAbs).call(this, _SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS, 'H', owningPathSegList)); + _this11._x = x; + return _this11; } - createClass(_SVGPathSegLinetoHorizontalAbs, [{ - key: 'toString', + _createClass(_SVGPathSegLinetoHorizontalAbs, [{ + key: "toString", value: function toString() { return '[object SVGPathSegLinetoHorizontalAbs]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegLinetoHorizontalAbs(undefined, this._x); } }]); + return _SVGPathSegLinetoHorizontalAbs; }(_SVGPathSeg); Object.defineProperty(_SVGPathSegLinetoHorizontalAbs.prototype, 'x', { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); - }, - enumerable: true }); + set: function set(x) { + this._x = x; - var _SVGPathSegLinetoHorizontalRel = function (_SVGPathSeg14) { - inherits(_SVGPathSegLinetoHorizontalRel, _SVGPathSeg14); + this._segmentChanged(); + }, + enumerable: true + }); + + var _SVGPathSegLinetoHorizontalRel = + /*#__PURE__*/ + function (_SVGPathSeg14) { + _inherits(_SVGPathSegLinetoHorizontalRel, _SVGPathSeg14); function _SVGPathSegLinetoHorizontalRel(owningPathSegList, x) { - classCallCheck(this, _SVGPathSegLinetoHorizontalRel); + var _this12; - var _this13 = possibleConstructorReturn(this, (_SVGPathSegLinetoHorizontalRel.__proto__ || Object.getPrototypeOf(_SVGPathSegLinetoHorizontalRel)).call(this, _SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL, 'h', owningPathSegList)); + _classCallCheck(this, _SVGPathSegLinetoHorizontalRel); - _this13._x = x; - return _this13; + _this12 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegLinetoHorizontalRel).call(this, _SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL, 'h', owningPathSegList)); + _this12._x = x; + return _this12; } - createClass(_SVGPathSegLinetoHorizontalRel, [{ - key: 'toString', + _createClass(_SVGPathSegLinetoHorizontalRel, [{ + key: "toString", value: function toString() { return '[object SVGPathSegLinetoHorizontalRel]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegLinetoHorizontalRel(undefined, this._x); } }]); + return _SVGPathSegLinetoHorizontalRel; }(_SVGPathSeg); Object.defineProperty(_SVGPathSegLinetoHorizontalRel.prototype, 'x', { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); - }, - enumerable: true }); + set: function set(x) { + this._x = x; - var _SVGPathSegLinetoVerticalAbs = function (_SVGPathSeg15) { - inherits(_SVGPathSegLinetoVerticalAbs, _SVGPathSeg15); + this._segmentChanged(); + }, + enumerable: true + }); + + var _SVGPathSegLinetoVerticalAbs = + /*#__PURE__*/ + function (_SVGPathSeg15) { + _inherits(_SVGPathSegLinetoVerticalAbs, _SVGPathSeg15); function _SVGPathSegLinetoVerticalAbs(owningPathSegList, y) { - classCallCheck(this, _SVGPathSegLinetoVerticalAbs); + var _this13; - var _this14 = possibleConstructorReturn(this, (_SVGPathSegLinetoVerticalAbs.__proto__ || Object.getPrototypeOf(_SVGPathSegLinetoVerticalAbs)).call(this, _SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS, 'V', owningPathSegList)); + _classCallCheck(this, _SVGPathSegLinetoVerticalAbs); - _this14._y = y; - return _this14; + _this13 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegLinetoVerticalAbs).call(this, _SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS, 'V', owningPathSegList)); + _this13._y = y; + return _this13; } - createClass(_SVGPathSegLinetoVerticalAbs, [{ - key: 'toString', + _createClass(_SVGPathSegLinetoVerticalAbs, [{ + key: "toString", value: function toString() { return '[object SVGPathSegLinetoVerticalAbs]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegLinetoVerticalAbs(undefined, this._y); } }]); + return _SVGPathSegLinetoVerticalAbs; }(_SVGPathSeg); Object.defineProperty(_SVGPathSegLinetoVerticalAbs.prototype, 'y', { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); - }, - enumerable: true }); + set: function set(y) { + this._y = y; - var _SVGPathSegLinetoVerticalRel = function (_SVGPathSeg16) { - inherits(_SVGPathSegLinetoVerticalRel, _SVGPathSeg16); + this._segmentChanged(); + }, + enumerable: true + }); + + var _SVGPathSegLinetoVerticalRel = + /*#__PURE__*/ + function (_SVGPathSeg16) { + _inherits(_SVGPathSegLinetoVerticalRel, _SVGPathSeg16); function _SVGPathSegLinetoVerticalRel(owningPathSegList, y) { - classCallCheck(this, _SVGPathSegLinetoVerticalRel); + var _this14; - var _this15 = possibleConstructorReturn(this, (_SVGPathSegLinetoVerticalRel.__proto__ || Object.getPrototypeOf(_SVGPathSegLinetoVerticalRel)).call(this, _SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL, 'v', owningPathSegList)); + _classCallCheck(this, _SVGPathSegLinetoVerticalRel); - _this15._y = y; - return _this15; + _this14 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegLinetoVerticalRel).call(this, _SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL, 'v', owningPathSegList)); + _this14._y = y; + return _this14; } - createClass(_SVGPathSegLinetoVerticalRel, [{ - key: 'toString', + _createClass(_SVGPathSegLinetoVerticalRel, [{ + key: "toString", value: function toString() { return '[object SVGPathSegLinetoVerticalRel]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegLinetoVerticalRel(undefined, this._y); } }]); + return _SVGPathSegLinetoVerticalRel; }(_SVGPathSeg); Object.defineProperty(_SVGPathSegLinetoVerticalRel.prototype, 'y', { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); - }, - enumerable: true }); + set: function set(y) { + this._y = y; - var _SVGPathSegCurvetoCubicSmoothAbs = function (_SVGPathSeg17) { - inherits(_SVGPathSegCurvetoCubicSmoothAbs, _SVGPathSeg17); + this._segmentChanged(); + }, + enumerable: true + }); + + var _SVGPathSegCurvetoCubicSmoothAbs = + /*#__PURE__*/ + function (_SVGPathSeg17) { + _inherits(_SVGPathSegCurvetoCubicSmoothAbs, _SVGPathSeg17); function _SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, x, y, x2, y2) { - classCallCheck(this, _SVGPathSegCurvetoCubicSmoothAbs); + var _this15; - var _this16 = possibleConstructorReturn(this, (_SVGPathSegCurvetoCubicSmoothAbs.__proto__ || Object.getPrototypeOf(_SVGPathSegCurvetoCubicSmoothAbs)).call(this, _SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, 'S', owningPathSegList)); + _classCallCheck(this, _SVGPathSegCurvetoCubicSmoothAbs); + _this15 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegCurvetoCubicSmoothAbs).call(this, _SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, 'S', owningPathSegList)); + _this15._x = x; + _this15._y = y; + _this15._x2 = x2; + _this15._y2 = y2; + return _this15; + } + + _createClass(_SVGPathSegCurvetoCubicSmoothAbs, [{ + key: "toString", + value: function toString() { + return '[object SVGPathSegCurvetoCubicSmoothAbs]'; + } + }, { + key: "_asPathString", + value: function _asPathString() { + return this.pathSegTypeAsLetter + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; + } + }, { + key: "clone", + value: function clone() { + return new _SVGPathSegCurvetoCubicSmoothAbs(undefined, this._x, this._y, this._x2, this._y2); + } + }]); + + return _SVGPathSegCurvetoCubicSmoothAbs; + }(_SVGPathSeg); + + Object.defineProperties(_SVGPathSegCurvetoCubicSmoothAbs.prototype, { + x: { + get: function get() { + return this._x; + }, + set: function set(x) { + this._x = x; + + this._segmentChanged(); + }, + enumerable: true + }, + y: { + get: function get() { + return this._y; + }, + set: function set(y) { + this._y = y; + + this._segmentChanged(); + }, + enumerable: true + }, + x2: { + get: function get() { + return this._x2; + }, + set: function set(x2) { + this._x2 = x2; + + this._segmentChanged(); + }, + enumerable: true + }, + y2: { + get: function get() { + return this._y2; + }, + set: function set(y2) { + this._y2 = y2; + + this._segmentChanged(); + }, + enumerable: true + } + }); + + var _SVGPathSegCurvetoCubicSmoothRel = + /*#__PURE__*/ + function (_SVGPathSeg18) { + _inherits(_SVGPathSegCurvetoCubicSmoothRel, _SVGPathSeg18); + + function _SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, x, y, x2, y2) { + var _this16; + + _classCallCheck(this, _SVGPathSegCurvetoCubicSmoothRel); + + _this16 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegCurvetoCubicSmoothRel).call(this, _SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL, 's', owningPathSegList)); _this16._x = x; _this16._y = y; _this16._x2 = x2; @@ -1213,287 +1572,268 @@ return _this16; } - createClass(_SVGPathSegCurvetoCubicSmoothAbs, [{ - key: 'toString', - value: function toString() { - return '[object SVGPathSegCurvetoCubicSmoothAbs]'; - } - }, { - key: '_asPathString', - value: function _asPathString() { - return this.pathSegTypeAsLetter + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; - } - }, { - key: 'clone', - value: function clone() { - return new _SVGPathSegCurvetoCubicSmoothAbs(undefined, this._x, this._y, this._x2, this._y2); - } - }]); - return _SVGPathSegCurvetoCubicSmoothAbs; - }(_SVGPathSeg); - - Object.defineProperties(_SVGPathSegCurvetoCubicSmoothAbs.prototype, { - x: { - get: function get$$1() { - return this._x; - }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); - }, - enumerable: true }, - y: { - get: function get$$1() { - return this._y; - }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); - }, - enumerable: true }, - x2: { - get: function get$$1() { - return this._x2; - }, - set: function set$$1(x2) { - this._x2 = x2;this._segmentChanged(); - }, - enumerable: true }, - y2: { - get: function get$$1() { - return this._y2; - }, - set: function set$$1(y2) { - this._y2 = y2;this._segmentChanged(); - }, - enumerable: true } - }); - - var _SVGPathSegCurvetoCubicSmoothRel = function (_SVGPathSeg18) { - inherits(_SVGPathSegCurvetoCubicSmoothRel, _SVGPathSeg18); - - function _SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, x, y, x2, y2) { - classCallCheck(this, _SVGPathSegCurvetoCubicSmoothRel); - - var _this17 = possibleConstructorReturn(this, (_SVGPathSegCurvetoCubicSmoothRel.__proto__ || Object.getPrototypeOf(_SVGPathSegCurvetoCubicSmoothRel)).call(this, _SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL, 's', owningPathSegList)); - - _this17._x = x; - _this17._y = y; - _this17._x2 = x2; - _this17._y2 = y2; - return _this17; - } - - createClass(_SVGPathSegCurvetoCubicSmoothRel, [{ - key: 'toString', + _createClass(_SVGPathSegCurvetoCubicSmoothRel, [{ + key: "toString", value: function toString() { return '[object SVGPathSegCurvetoCubicSmoothRel]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegCurvetoCubicSmoothRel(undefined, this._x, this._y, this._x2, this._y2); } }]); + return _SVGPathSegCurvetoCubicSmoothRel; }(_SVGPathSeg); Object.defineProperties(_SVGPathSegCurvetoCubicSmoothRel.prototype, { x: { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); + set: function set(x) { + this._x = x; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y: { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); + set: function set(y) { + this._y = y; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, x2: { - get: function get$$1() { + get: function get() { return this._x2; }, - set: function set$$1(x2) { - this._x2 = x2;this._segmentChanged(); + set: function set(x2) { + this._x2 = x2; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y2: { - get: function get$$1() { + get: function get() { return this._y2; }, - set: function set$$1(y2) { - this._y2 = y2;this._segmentChanged(); + set: function set(y2) { + this._y2 = y2; + + this._segmentChanged(); }, - enumerable: true } + enumerable: true + } }); - var _SVGPathSegCurvetoQuadraticSmoothAbs = function (_SVGPathSeg19) { - inherits(_SVGPathSegCurvetoQuadraticSmoothAbs, _SVGPathSeg19); + var _SVGPathSegCurvetoQuadraticSmoothAbs = + /*#__PURE__*/ + function (_SVGPathSeg19) { + _inherits(_SVGPathSegCurvetoQuadraticSmoothAbs, _SVGPathSeg19); function _SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, x, y) { - classCallCheck(this, _SVGPathSegCurvetoQuadraticSmoothAbs); + var _this17; - var _this18 = possibleConstructorReturn(this, (_SVGPathSegCurvetoQuadraticSmoothAbs.__proto__ || Object.getPrototypeOf(_SVGPathSegCurvetoQuadraticSmoothAbs)).call(this, _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, 'T', owningPathSegList)); + _classCallCheck(this, _SVGPathSegCurvetoQuadraticSmoothAbs); - _this18._x = x; - _this18._y = y; - return _this18; + _this17 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegCurvetoQuadraticSmoothAbs).call(this, _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, 'T', owningPathSegList)); + _this17._x = x; + _this17._y = y; + return _this17; } - createClass(_SVGPathSegCurvetoQuadraticSmoothAbs, [{ - key: 'toString', + _createClass(_SVGPathSegCurvetoQuadraticSmoothAbs, [{ + key: "toString", value: function toString() { return '[object SVGPathSegCurvetoQuadraticSmoothAbs]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegCurvetoQuadraticSmoothAbs(undefined, this._x, this._y); } }]); + return _SVGPathSegCurvetoQuadraticSmoothAbs; }(_SVGPathSeg); Object.defineProperties(_SVGPathSegCurvetoQuadraticSmoothAbs.prototype, { x: { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); + set: function set(x) { + this._x = x; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y: { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); + set: function set(y) { + this._y = y; + + this._segmentChanged(); }, - enumerable: true } + enumerable: true + } }); - var _SVGPathSegCurvetoQuadraticSmoothRel = function (_SVGPathSeg20) { - inherits(_SVGPathSegCurvetoQuadraticSmoothRel, _SVGPathSeg20); + var _SVGPathSegCurvetoQuadraticSmoothRel = + /*#__PURE__*/ + function (_SVGPathSeg20) { + _inherits(_SVGPathSegCurvetoQuadraticSmoothRel, _SVGPathSeg20); function _SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, x, y) { - classCallCheck(this, _SVGPathSegCurvetoQuadraticSmoothRel); + var _this18; - var _this19 = possibleConstructorReturn(this, (_SVGPathSegCurvetoQuadraticSmoothRel.__proto__ || Object.getPrototypeOf(_SVGPathSegCurvetoQuadraticSmoothRel)).call(this, _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, 't', owningPathSegList)); + _classCallCheck(this, _SVGPathSegCurvetoQuadraticSmoothRel); - _this19._x = x; - _this19._y = y; - return _this19; + _this18 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegCurvetoQuadraticSmoothRel).call(this, _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, 't', owningPathSegList)); + _this18._x = x; + _this18._y = y; + return _this18; } - createClass(_SVGPathSegCurvetoQuadraticSmoothRel, [{ - key: 'toString', + _createClass(_SVGPathSegCurvetoQuadraticSmoothRel, [{ + key: "toString", value: function toString() { return '[object SVGPathSegCurvetoQuadraticSmoothRel]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegCurvetoQuadraticSmoothRel(undefined, this._x, this._y); } }]); + return _SVGPathSegCurvetoQuadraticSmoothRel; }(_SVGPathSeg); Object.defineProperties(_SVGPathSegCurvetoQuadraticSmoothRel.prototype, { x: { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); + set: function set(x) { + this._x = x; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y: { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); - }, - enumerable: true } - }); + set: function set(y) { + this._y = y; - // Add createSVGPathSeg* functions to SVGPathElement. + this._segmentChanged(); + }, + enumerable: true + } + }); // Add createSVGPathSeg* functions to SVGPathElement. // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathElement. + SVGPathElement.prototype.createSVGPathSegClosePath = function () { return new _SVGPathSegClosePath(undefined); }; + SVGPathElement.prototype.createSVGPathSegMovetoAbs = function (x, y) { return new _SVGPathSegMovetoAbs(undefined, x, y); }; + SVGPathElement.prototype.createSVGPathSegMovetoRel = function (x, y) { return new _SVGPathSegMovetoRel(undefined, x, y); }; + SVGPathElement.prototype.createSVGPathSegLinetoAbs = function (x, y) { return new _SVGPathSegLinetoAbs(undefined, x, y); }; + SVGPathElement.prototype.createSVGPathSegLinetoRel = function (x, y) { return new _SVGPathSegLinetoRel(undefined, x, y); }; + SVGPathElement.prototype.createSVGPathSegCurvetoCubicAbs = function (x, y, x1, y1, x2, y2) { return new _SVGPathSegCurvetoCubicAbs(undefined, x, y, x1, y1, x2, y2); }; + SVGPathElement.prototype.createSVGPathSegCurvetoCubicRel = function (x, y, x1, y1, x2, y2) { return new _SVGPathSegCurvetoCubicRel(undefined, x, y, x1, y1, x2, y2); }; + SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticAbs = function (x, y, x1, y1) { return new _SVGPathSegCurvetoQuadraticAbs(undefined, x, y, x1, y1); }; + SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticRel = function (x, y, x1, y1) { return new _SVGPathSegCurvetoQuadraticRel(undefined, x, y, x1, y1); }; + SVGPathElement.prototype.createSVGPathSegArcAbs = function (x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new _SVGPathSegArcAbs(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); }; + SVGPathElement.prototype.createSVGPathSegArcRel = function (x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new _SVGPathSegArcRel(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); }; + SVGPathElement.prototype.createSVGPathSegLinetoHorizontalAbs = function (x) { return new _SVGPathSegLinetoHorizontalAbs(undefined, x); }; + SVGPathElement.prototype.createSVGPathSegLinetoHorizontalRel = function (x) { return new _SVGPathSegLinetoHorizontalRel(undefined, x); }; + SVGPathElement.prototype.createSVGPathSegLinetoVerticalAbs = function (y) { return new _SVGPathSegLinetoVerticalAbs(undefined, y); }; + SVGPathElement.prototype.createSVGPathSegLinetoVerticalRel = function (y) { return new _SVGPathSegLinetoVerticalRel(undefined, y); }; + SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothAbs = function (x, y, x2, y2) { return new _SVGPathSegCurvetoCubicSmoothAbs(undefined, x, y, x2, y2); }; + SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothRel = function (x, y, x2, y2) { return new _SVGPathSegCurvetoCubicSmoothRel(undefined, x, y, x2, y2); }; + SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothAbs = function (x, y) { return new _SVGPathSegCurvetoQuadraticSmoothAbs(undefined, x, y); }; + SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothRel = function (x, y) { return new _SVGPathSegCurvetoQuadraticSmoothRel(undefined, x, y); }; @@ -1509,20 +1849,22 @@ var measurementElement = document.createElementNS('http://www.w3.org/2000/svg', 'path'); measurementElement.setAttribute('d', this.getAttribute('d')); - var lastPathSegment = measurementElement.pathSegList.numberOfItems - 1; + var lastPathSegment = measurementElement.pathSegList.numberOfItems - 1; // If the path is empty, return 0. - // If the path is empty, return 0. if (lastPathSegment <= 0) { return 0; } do { measurementElement.pathSegList.removeItem(lastPathSegment); + if (distance > measurementElement.getTotalLength()) { break; } + lastPathSegment--; } while (lastPathSegment > 0); + return lastPathSegment; }; } @@ -1547,127 +1889,141 @@ window.SVGPathSegCurvetoCubicSmoothRel = _SVGPathSegCurvetoCubicSmoothRel; window.SVGPathSegCurvetoQuadraticSmoothAbs = _SVGPathSegCurvetoQuadraticSmoothAbs; window.SVGPathSegCurvetoQuadraticSmoothRel = _SVGPathSegCurvetoQuadraticSmoothRel; - } - - // Checking for SVGPathSegList in window checks for the case of an implementation without the + } // Checking for SVGPathSegList in window checks for the case of an implementation without the // SVGPathSegList API. // The second check for appendItem is specific to Firefox 59+ which removed only parts of the // SVGPathSegList API (e.g., appendItem). In this case we need to re-implement the entire API // so the polyfill data (i.e., _list) is used throughout. + + if (!('SVGPathSegList' in window) || !('appendItem' in window.SVGPathSegList.prototype)) { // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSegList - var SVGPathSegList = function () { + var SVGPathSegList = + /*#__PURE__*/ + function () { function SVGPathSegList(pathElement) { - classCallCheck(this, SVGPathSegList); + _classCallCheck(this, SVGPathSegList); this._pathElement = pathElement; - this._list = this._parsePath(this._pathElement.getAttribute('d')); + this._list = this._parsePath(this._pathElement.getAttribute('d')); // Use a MutationObserver to catch changes to the path's "d" attribute. - // Use a MutationObserver to catch changes to the path's "d" attribute. - this._mutationObserverConfig = { attributes: true, attributeFilter: ['d'] }; + this._mutationObserverConfig = { + attributes: true, + attributeFilter: ['d'] + }; this._pathElementMutationObserver = new MutationObserver(this._updateListFromPathMutations.bind(this)); + this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig); - } - // Process any pending mutations to the path element and update the list as needed. + } // Process any pending mutations to the path element and update the list as needed. // This should be the first call of all public functions and is needed because // MutationObservers are not synchronous so we can have pending asynchronous mutations. - createClass(SVGPathSegList, [{ - key: '_checkPathSynchronizedToList', + _createClass(SVGPathSegList, [{ + key: "_checkPathSynchronizedToList", value: function _checkPathSynchronizedToList() { this._updateListFromPathMutations(this._pathElementMutationObserver.takeRecords()); } }, { - key: '_updateListFromPathMutations', + key: "_updateListFromPathMutations", value: function _updateListFromPathMutations(mutationRecords) { if (!this._pathElement) { return; } + var hasPathMutations = false; mutationRecords.forEach(function (record) { if (record.attributeName === 'd') { hasPathMutations = true; } }); + if (hasPathMutations) { this._list = this._parsePath(this._pathElement.getAttribute('d')); } - } - - // Serialize the list and update the path's 'd' attribute. + } // Serialize the list and update the path's 'd' attribute. }, { - key: '_writeListToPath', + key: "_writeListToPath", value: function _writeListToPath() { this._pathElementMutationObserver.disconnect(); - this._pathElement.setAttribute('d', SVGPathSegList._pathSegArrayAsString(this._list)); - this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig); - } - // When a path segment changes the list needs to be synchronized back to the path element. + this._pathElement.setAttribute('d', SVGPathSegList._pathSegArrayAsString(this._list)); + + this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig); + } // When a path segment changes the list needs to be synchronized back to the path element. }, { - key: 'segmentChanged', + key: "segmentChanged", value: function segmentChanged(pathSeg) { this._writeListToPath(); } }, { - key: 'clear', + key: "clear", value: function clear() { this._checkPathSynchronizedToList(); this._list.forEach(function (pathSeg) { pathSeg._owningPathSegList = null; }); + this._list = []; + this._writeListToPath(); } }, { - key: 'initialize', + key: "initialize", value: function initialize(newItem) { this._checkPathSynchronizedToList(); this._list = [newItem]; newItem._owningPathSegList = this; + this._writeListToPath(); + return newItem; } }, { - key: '_checkValidIndex', + key: "_checkValidIndex", value: function _checkValidIndex(index) { if (isNaN(index) || index < 0 || index >= this.numberOfItems) { throw new Error('INDEX_SIZE_ERR'); } } }, { - key: 'getItem', + key: "getItem", value: function getItem(index) { this._checkPathSynchronizedToList(); this._checkValidIndex(index); + return this._list[index]; } }, { - key: 'insertItemBefore', + key: "insertItemBefore", value: function insertItemBefore(newItem, index) { - this._checkPathSynchronizedToList(); + this._checkPathSynchronizedToList(); // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list. + - // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list. if (index > this.numberOfItems) { index = this.numberOfItems; } + if (newItem._owningPathSegList) { // SVG2 spec says to make a copy. newItem = newItem.clone(); } + this._list.splice(index, 0, newItem); + newItem._owningPathSegList = this; + this._writeListToPath(); + return newItem; } }, { - key: 'replaceItem', + key: "replaceItem", value: function replaceItem(newItem, index) { this._checkPathSynchronizedToList(); @@ -1675,25 +2031,33 @@ // SVG2 spec says to make a copy. newItem = newItem.clone(); } + this._checkValidIndex(index); + this._list[index] = newItem; newItem._owningPathSegList = this; + this._writeListToPath(); + return newItem; } }, { - key: 'removeItem', + key: "removeItem", value: function removeItem(index) { this._checkPathSynchronizedToList(); this._checkValidIndex(index); + var item = this._list[index]; + this._list.splice(index, 1); + this._writeListToPath(); + return item; } }, { - key: 'appendItem', + key: "appendItem", value: function appendItem(newItem) { this._checkPathSynchronizedToList(); @@ -1701,43 +2065,49 @@ // SVG2 spec says to make a copy. newItem = newItem.clone(); } - this._list.push(newItem); - newItem._owningPathSegList = this; - // TODO: Optimize this to just append to the existing attribute. - this._writeListToPath(); - return newItem; - } - // This closely follows SVGPathParser::parsePath from Source/core/svg/SVGPathParser.cpp. + this._list.push(newItem); + + newItem._owningPathSegList = this; // TODO: Optimize this to just append to the existing attribute. + + this._writeListToPath(); + + return newItem; + } // This closely follows SVGPathParser::parsePath from Source/core/svg/SVGPathParser.cpp. }, { - key: '_parsePath', + key: "_parsePath", value: function _parsePath(string) { if (!string || !string.length) { return []; } - var owningPathSegList = this; + var owningPathSegList = this; // eslint-disable-line consistent-this - var Builder = function () { + var Builder = + /*#__PURE__*/ + function () { function Builder() { - classCallCheck(this, Builder); + _classCallCheck(this, Builder); this.pathSegList = []; } - createClass(Builder, [{ - key: 'appendSegment', + _createClass(Builder, [{ + key: "appendSegment", value: function appendSegment(pathSeg) { this.pathSegList.push(pathSeg); } }]); + return Builder; }(); - var Source = function () { + var Source = + /*#__PURE__*/ + function () { function Source(string) { - classCallCheck(this, Source); + _classCallCheck(this, Source); this._string = string; this._currentIndex = 0; @@ -1747,124 +2117,149 @@ this._skipOptionalSpaces(); } - createClass(Source, [{ - key: '_isCurrentSpace', + _createClass(Source, [{ + key: "_isCurrentSpace", value: function _isCurrentSpace() { var character = this._string[this._currentIndex]; return character <= ' ' && (character === ' ' || character === '\n' || character === '\t' || character === '\r' || character === '\f'); } }, { - key: '_skipOptionalSpaces', + key: "_skipOptionalSpaces", value: function _skipOptionalSpaces() { while (this._currentIndex < this._endIndex && this._isCurrentSpace()) { this._currentIndex++; } + return this._currentIndex < this._endIndex; } }, { - key: '_skipOptionalSpacesOrDelimiter', + key: "_skipOptionalSpacesOrDelimiter", value: function _skipOptionalSpacesOrDelimiter() { if (this._currentIndex < this._endIndex && !this._isCurrentSpace() && this._string.charAt(this._currentIndex) !== ',') { return false; } + if (this._skipOptionalSpaces()) { if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) === ',') { this._currentIndex++; + this._skipOptionalSpaces(); } } + return this._currentIndex < this._endIndex; } }, { - key: 'hasMoreData', + key: "hasMoreData", value: function hasMoreData() { return this._currentIndex < this._endIndex; } }, { - key: 'peekSegmentType', + key: "peekSegmentType", value: function peekSegmentType() { var lookahead = this._string[this._currentIndex]; return this._pathSegTypeFromChar(lookahead); } }, { - key: '_pathSegTypeFromChar', + key: "_pathSegTypeFromChar", value: function _pathSegTypeFromChar(lookahead) { switch (lookahead) { case 'Z': case 'z': return SVGPathSeg.PATHSEG_CLOSEPATH; + case 'M': return SVGPathSeg.PATHSEG_MOVETO_ABS; + case 'm': return SVGPathSeg.PATHSEG_MOVETO_REL; + case 'L': return SVGPathSeg.PATHSEG_LINETO_ABS; + case 'l': return SVGPathSeg.PATHSEG_LINETO_REL; + case 'C': return SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS; + case 'c': return SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL; + case 'Q': return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS; + case 'q': return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL; + case 'A': return SVGPathSeg.PATHSEG_ARC_ABS; + case 'a': return SVGPathSeg.PATHSEG_ARC_REL; + case 'H': return SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS; + case 'h': return SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL; + case 'V': return SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS; + case 'v': return SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL; + case 'S': return SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS; + case 's': return SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL; + case 'T': return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS; + case 't': return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL; + default: return SVGPathSeg.PATHSEG_UNKNOWN; } } }, { - key: '_nextCommandHelper', + key: "_nextCommandHelper", value: function _nextCommandHelper(lookahead, previousCommand) { // Check for remaining coordinates in the current command. if ((lookahead === '+' || lookahead === '-' || lookahead === '.' || lookahead >= '0' && lookahead <= '9') && previousCommand !== SVGPathSeg.PATHSEG_CLOSEPATH) { if (previousCommand === SVGPathSeg.PATHSEG_MOVETO_ABS) { return SVGPathSeg.PATHSEG_LINETO_ABS; } + if (previousCommand === SVGPathSeg.PATHSEG_MOVETO_REL) { return SVGPathSeg.PATHSEG_LINETO_REL; } + return previousCommand; } + return SVGPathSeg.PATHSEG_UNKNOWN; } }, { - key: 'initialCommandIsMoveTo', + key: "initialCommandIsMoveTo", value: function initialCommandIsMoveTo() { // If the path is empty it is still valid, so return true. if (!this.hasMoreData()) { return true; } - var command = this.peekSegmentType(); - // Path must start with moveTo. - return command === SVGPathSeg.PATHSEG_MOVETO_ABS || command === SVGPathSeg.PATHSEG_MOVETO_REL; - } - // Parse a number from an SVG path. This very closely follows genericParseNumber(...) from Source/core/svg/SVGParserUtilities.cpp. + var command = this.peekSegmentType(); // Path must start with moveTo. + + return command === SVGPathSeg.PATHSEG_MOVETO_ABS || command === SVGPathSeg.PATHSEG_MOVETO_REL; + } // Parse a number from an SVG path. This very closely follows genericParseNumber(...) from Source/core/svg/SVGParserUtilities.cpp. // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-PathDataBNF }, { - key: '_parseNumber', + key: "_parseNumber", value: function _parseNumber() { var exponent = 0; var integer = 0; @@ -1872,12 +2267,11 @@ var decimal = 0; var sign = 1; var expsign = 1; - var startIndex = this._currentIndex; - this._skipOptionalSpaces(); + this._skipOptionalSpaces(); // Read the sign. + - // Read the sign. if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) === '+') { this._currentIndex++; } else if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) === '-') { @@ -1888,10 +2282,11 @@ if (this._currentIndex === this._endIndex || (this._string.charAt(this._currentIndex) < '0' || this._string.charAt(this._currentIndex) > '9') && this._string.charAt(this._currentIndex) !== '.') { // The first character of a number must be one of [0-9+-.]. return undefined; - } + } // Read the integer part, build right-to-left. + - // Read the integer part, build right-to-left. var startIntPartIndex = this._currentIndex; + while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= '0' && this._string.charAt(this._currentIndex) <= '9') { this._currentIndex++; // Advance to first non-digit. } @@ -1899,40 +2294,40 @@ if (this._currentIndex !== startIntPartIndex) { var scanIntPartIndex = this._currentIndex - 1; var multiplier = 1; + while (scanIntPartIndex >= startIntPartIndex) { integer += multiplier * (this._string.charAt(scanIntPartIndex--) - '0'); multiplier *= 10; } - } + } // Read the decimals. + - // Read the decimals. if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) === '.') { - this._currentIndex++; + this._currentIndex++; // There must be a least one digit following the . - // There must be a least one digit following the . if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < '0' || this._string.charAt(this._currentIndex) > '9') { return undefined; } + while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= '0' && this._string.charAt(this._currentIndex) <= '9') { frac *= 10; decimal += (this._string.charAt(this._currentIndex) - '0') / frac; this._currentIndex += 1; } - } + } // Read the exponent part. + - // Read the exponent part. if (this._currentIndex !== startIndex && this._currentIndex + 1 < this._endIndex && (this._string.charAt(this._currentIndex) === 'e' || this._string.charAt(this._currentIndex) === 'E') && this._string.charAt(this._currentIndex + 1) !== 'x' && this._string.charAt(this._currentIndex + 1) !== 'm') { - this._currentIndex++; + this._currentIndex++; // Read the sign of the exponent. - // Read the sign of the exponent. if (this._string.charAt(this._currentIndex) === '+') { this._currentIndex++; } else if (this._string.charAt(this._currentIndex) === '-') { this._currentIndex++; expsign = -1; - } + } // There must be an exponent. + - // There must be an exponent. if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < '0' || this._string.charAt(this._currentIndex) > '9') { return undefined; } @@ -1960,13 +2355,16 @@ return number; } }, { - key: '_parseArcFlag', + key: "_parseArcFlag", value: function _parseArcFlag() { if (this._currentIndex >= this._endIndex) { return undefined; } + var flag = false; + var flagChar = this._string.charAt(this._currentIndex++); + if (flagChar === '0') { flag = false; } else if (flagChar === '1') { @@ -1976,19 +2374,24 @@ } this._skipOptionalSpacesOrDelimiter(); + return flag; } }, { - key: 'parseSegment', + key: "parseSegment", value: function parseSegment() { var lookahead = this._string[this._currentIndex]; + var command = this._pathSegTypeFromChar(lookahead); + if (command === SVGPathSeg.PATHSEG_UNKNOWN) { // Possibly an implicit command. Not allowed if this is the first command. if (this._previousCommand === SVGPathSeg.PATHSEG_UNKNOWN) { return null; } + command = this._nextCommandHelper(lookahead, this._previousCommand); + if (command === SVGPathSeg.PATHSEG_UNKNOWN) { return null; } @@ -2001,63 +2404,143 @@ switch (command) { case SVGPathSeg.PATHSEG_MOVETO_REL: return new SVGPathSegMovetoRel(owningPathSegList, this._parseNumber(), this._parseNumber()); + case SVGPathSeg.PATHSEG_MOVETO_ABS: return new SVGPathSegMovetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber()); + case SVGPathSeg.PATHSEG_LINETO_REL: return new SVGPathSegLinetoRel(owningPathSegList, this._parseNumber(), this._parseNumber()); + case SVGPathSeg.PATHSEG_LINETO_ABS: return new SVGPathSegLinetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber()); + case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL: return new SVGPathSegLinetoHorizontalRel(owningPathSegList, this._parseNumber()); + case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS: return new SVGPathSegLinetoHorizontalAbs(owningPathSegList, this._parseNumber()); + case SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL: return new SVGPathSegLinetoVerticalRel(owningPathSegList, this._parseNumber()); + case SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS: return new SVGPathSegLinetoVerticalAbs(owningPathSegList, this._parseNumber()); + case SVGPathSeg.PATHSEG_CLOSEPATH: this._skipOptionalSpaces(); + return new SVGPathSegClosePath(owningPathSegList); + case SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL: { - var _points = { x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber() }; - return new SVGPathSegCurvetoCubicRel(owningPathSegList, _points.x, _points.y, _points.x1, _points.y1, _points.x2, _points.y2); - }case SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS: + var points = { + x1: this._parseNumber(), + y1: this._parseNumber(), + x2: this._parseNumber(), + y2: this._parseNumber(), + x: this._parseNumber(), + y: this._parseNumber() + }; + return new SVGPathSegCurvetoCubicRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2); + } + + case SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS: { - var _points2 = { x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber() }; - return new SVGPathSegCurvetoCubicAbs(owningPathSegList, _points2.x, _points2.y, _points2.x1, _points2.y1, _points2.x2, _points2.y2); - }case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL: + var _points = { + x1: this._parseNumber(), + y1: this._parseNumber(), + x2: this._parseNumber(), + y2: this._parseNumber(), + x: this._parseNumber(), + y: this._parseNumber() + }; + return new SVGPathSegCurvetoCubicAbs(owningPathSegList, _points.x, _points.y, _points.x1, _points.y1, _points.x2, _points.y2); + } + + case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL: { - var _points3 = { x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber() }; - return new SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, _points3.x, _points3.y, _points3.x2, _points3.y2); - }case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: + var _points2 = { + x2: this._parseNumber(), + y2: this._parseNumber(), + x: this._parseNumber(), + y: this._parseNumber() + }; + return new SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, _points2.x, _points2.y, _points2.x2, _points2.y2); + } + + case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: { - var _points4 = { x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber() }; - return new SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, _points4.x, _points4.y, _points4.x2, _points4.y2); - }case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL: + var _points3 = { + x2: this._parseNumber(), + y2: this._parseNumber(), + x: this._parseNumber(), + y: this._parseNumber() + }; + return new SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, _points3.x, _points3.y, _points3.x2, _points3.y2); + } + + case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL: { - var _points5 = { x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber() }; - return new SVGPathSegCurvetoQuadraticRel(owningPathSegList, _points5.x, _points5.y, _points5.x1, _points5.y1); - }case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS: - var 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); + var _points4 = { + x1: this._parseNumber(), + y1: this._parseNumber(), + x: this._parseNumber(), + y: this._parseNumber() + }; + return new SVGPathSegCurvetoQuadraticRel(owningPathSegList, _points4.x, _points4.y, _points4.x1, _points4.y1); + } + + case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS: + { + var _points5 = { + x1: this._parseNumber(), + y1: this._parseNumber(), + x: this._parseNumber(), + y: this._parseNumber() + }; + return new SVGPathSegCurvetoQuadraticAbs(owningPathSegList, _points5.x, _points5.y, _points5.x1, _points5.y1); + } + case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL: return new SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, this._parseNumber(), this._parseNumber()); + case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS: return new SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, this._parseNumber(), this._parseNumber()); + case SVGPathSeg.PATHSEG_ARC_REL: { - var _points6 = { x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber() }; + var _points6 = { + x1: this._parseNumber(), + y1: this._parseNumber(), + arcAngle: this._parseNumber(), + arcLarge: this._parseArcFlag(), + arcSweep: this._parseArcFlag(), + x: this._parseNumber(), + y: this._parseNumber() + }; return new SVGPathSegArcRel(owningPathSegList, _points6.x, _points6.y, _points6.x1, _points6.y1, _points6.arcAngle, _points6.arcLarge, _points6.arcSweep); - }case SVGPathSeg.PATHSEG_ARC_ABS: + } + + case SVGPathSeg.PATHSEG_ARC_ABS: { - var _points7 = { x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber() }; + var _points7 = { + x1: this._parseNumber(), + y1: this._parseNumber(), + arcAngle: this._parseNumber(), + arcLarge: this._parseArcFlag(), + arcSweep: this._parseArcFlag(), + x: this._parseNumber(), + y: this._parseNumber() + }; return new SVGPathSegArcAbs(owningPathSegList, _points7.x, _points7.y, _points7.x1, _points7.y1, _points7.arcAngle, _points7.arcLarge, _points7.arcSweep); - }default: + } + + default: throw new Error('Unknown path seg type.'); } } }]); + return Source; }(); @@ -2067,28 +2550,31 @@ if (!source.initialCommandIsMoveTo()) { return []; } + while (source.hasMoreData()) { var pathSeg = source.parseSegment(); + if (!pathSeg) { return []; } + builder.appendSegment(pathSeg); } return builder.pathSegList; } }]); + return SVGPathSegList; }(); SVGPathSegList.prototype.classname = 'SVGPathSegList'; - Object.defineProperty(SVGPathSegList.prototype, 'numberOfItems', { - get: function get$$1() { + get: function get() { this._checkPathSynchronizedToList(); + return this._list.length; }, - enumerable: true }); @@ -2104,57 +2590,55 @@ } }); return string; - }; - - // Add the pathSegList accessors to SVGPathElement. + }; // Add the pathSegList accessors to SVGPathElement. // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGAnimatedPathData + + Object.defineProperties(SVGPathElement.prototype, { pathSegList: { - get: function get$$1() { + get: function get() { if (!this._pathSegList) { this._pathSegList = new SVGPathSegList(this); } + return this._pathSegList; }, - enumerable: true }, // FIXME: The following are not implemented and simply return SVGPathElement.pathSegList. normalizedPathSegList: { - get: function get$$1() { + get: function get() { return this.pathSegList; }, - enumerable: true }, + enumerable: true + }, animatedPathSegList: { - get: function get$$1() { + get: function get() { return this.pathSegList; }, - enumerable: true }, + enumerable: true + }, animatedNormalizedPathSegList: { - get: function get$$1() { + get: function get() { return this.pathSegList; }, - enumerable: true } + enumerable: true + } }); window.SVGPathSegList = SVGPathSegList; } })(); - /* globals jQuery */ - var $ = jQuery; var supportsSVG_ = function () { - return !!document.createElementNS && !!document.createElementNS(NS.SVG, 'svg').createSVGRect; + return Boolean(document.createElementNS && document.createElementNS(NS.SVG, 'svg').createSVGRect); }(); - var _navigator = navigator, userAgent = _navigator.userAgent; + var svg = document.createElementNS(NS.SVG, 'svg'); // Note: Browser sniffing should only be used if no other detection method is possible - var svg = document.createElementNS(NS.SVG, 'svg'); - - // Note: Browser sniffing should only be used if no other detection method is possible - var isOpera_ = !!window.opera; + var isOpera_ = Boolean(window.opera); var isWebkit_ = userAgent.includes('AppleWebKit'); var isGecko_ = userAgent.includes('Gecko/'); var isIE_ = userAgent.includes('MSIE'); @@ -2164,23 +2648,25 @@ var isTouch_ = 'ontouchstart' in window; var supportsSelectors_ = function () { - return !!svg.querySelector; + return Boolean(svg.querySelector); }(); var 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) var supportsPathReplaceItem_ = function () { var path = document.createElementNS(NS.SVG, 'path'); path.setAttribute('d', 'M0,0 10,10'); var seglist = path.pathSegList; var seg = path.createSVGPathSegLinetoAbs(5, 5); + try { seglist.replaceItem(seg, 1); return true; } catch (err) {} + return false; }(); @@ -2189,14 +2675,16 @@ path.setAttribute('d', 'M0,0 10,10'); var seglist = path.pathSegList; var seg = path.createSVGPathSegLinetoAbs(5, 5); + try { seglist.insertItemBefore(seg, 1); return true; } catch (err) {} - return false; - }(); - // text character positioning (for IE9) + return false; + }(); // text character positioning (for IE9 and now Chrome) + + var supportsGoodTextCharPos_ = function () { var svgroot = document.createElementNS(NS.SVG, 'svg'); var svgcontent = document.createElementNS(NS.SVG, 'svg'); @@ -2206,9 +2694,16 @@ var text = document.createElementNS(NS.SVG, 'text'); text.textContent = 'a'; svgcontent.append(text); - var pos = text.getStartPositionOfChar(0).x; - svgroot.remove(); - return pos === 0; + + try { + // Chrome now fails here + var pos = text.getStartPositionOfChar(0).x; + return pos === 0; + } catch (err) { + return false; + } finally { + svgroot.remove(); + } }(); var supportsPathBBox_ = function () { @@ -2220,9 +2715,9 @@ var bbox = path.getBBox(); svgcontent.remove(); return bbox.height > 4 && bbox.height < 5; - }(); + }(); // Support for correct bbox sizing on groups with horizontal/vertical lines + - // Support for correct bbox sizing on groups with horizontal/vertical lines var supportsHVLineContainerBBox_ = function () { var svgcontent = document.createElementNS(NS.SVG, 'svg'); document.documentElement.append(svgcontent); @@ -2234,8 +2729,8 @@ g.append(path, path2); svgcontent.append(g); var bbox = g.getBBox(); - svgcontent.remove(); - // Webkit gives 0, FF gives 10, Opera (correctly) gives 15 + svgcontent.remove(); // Webkit gives 0, FF gives 10, Opera (correctly) gives 15 + return bbox.width === 15; }(); @@ -2245,10 +2740,12 @@ rect.setAttribute('x', 0.1); var crect = rect.cloneNode(false); var retValue = !crect.getAttribute('x').includes(','); + if (!retValue) { // Todo: i18nize or remove $.alert('NOTE: This version of Opera is known to contain bugs in SVG-edit.\n' + 'Please upgrade to the <a href="http://opera.com">latest version</a> in which the problems have been fixed.'); } + return retValue; }(); @@ -2264,16 +2761,21 @@ var t1 = svg.createSVGTransform(); rxform.appendItem(t1); var r1 = rxform.getItem(0); - // Todo: Do frame-independent instance checking - return r1 instanceof SVGTransform && t1 instanceof SVGTransform && r1.type === t1.type && r1.angle === t1.angle && r1.matrix.a === t1.matrix.a && r1.matrix.b === t1.matrix.b && r1.matrix.c === t1.matrix.c && r1.matrix.d === t1.matrix.d && r1.matrix.e === t1.matrix.e && r1.matrix.f === t1.matrix.f; - }(); - // Public API + var isSVGTransform = function isSVGTransform(o) { + // https://developer.mozilla.org/en-US/docs/Web/API/SVGTransform + return o && _typeof(o) === 'object' && typeof o.setMatrix === 'function' && 'angle' in o; + }; + + return isSVGTransform(r1) && isSVGTransform(t1) && r1.type === t1.type && r1.angle === t1.angle && r1.matrix.a === t1.matrix.a && r1.matrix.b === t1.matrix.b && r1.matrix.c === t1.matrix.c && r1.matrix.d === t1.matrix.d && r1.matrix.e === t1.matrix.e && r1.matrix.f === t1.matrix.f; + }(); // Public API /** * @function module:browser.isOpera * @returns {boolean} */ + + var isOpera = function isOpera() { return isOpera_; }; @@ -2281,6 +2783,7 @@ * @function module:browser.isWebkit * @returns {boolean} */ + var isWebkit = function isWebkit() { return isWebkit_; }; @@ -2288,6 +2791,7 @@ * @function module:browser.isGecko * @returns {boolean} */ + var isGecko = function isGecko() { return isGecko_; }; @@ -2295,6 +2799,7 @@ * @function module:browser.isIE * @returns {boolean} */ + var isIE = function isIE() { return isIE_; }; @@ -2302,6 +2807,7 @@ * @function module:browser.isChrome * @returns {boolean} */ + var isChrome = function isChrome() { return isChrome_; }; @@ -2309,6 +2815,7 @@ * @function module:browser.isMac * @returns {boolean} */ + var isMac = function isMac() { return isMac_; }; @@ -2316,78 +2823,79 @@ * @function module:browser.isTouch * @returns {boolean} */ + var isTouch = function isTouch() { return isTouch_; }; - /** * @function module:browser.supportsSelectors * @returns {boolean} */ + var supportsSelectors = function supportsSelectors() { return supportsSelectors_; }; - /** * @function module:browser.supportsXpath * @returns {boolean} */ + var supportsXpath = function supportsXpath() { return supportsXpath_; }; - /** * @function module:browser.supportsPathReplaceItem * @returns {boolean} */ + var supportsPathReplaceItem = function supportsPathReplaceItem() { return supportsPathReplaceItem_; }; - /** * @function module:browser.supportsPathInsertItemBefore * @returns {boolean} */ + var supportsPathInsertItemBefore = function supportsPathInsertItemBefore() { return supportsPathInsertItemBefore_; }; - /** * @function module:browser.supportsPathBBox * @returns {boolean} */ + var supportsPathBBox = function supportsPathBBox() { return supportsPathBBox_; }; - /** * @function module:browser.supportsHVLineContainerBBox * @returns {boolean} */ + var supportsHVLineContainerBBox = function supportsHVLineContainerBBox() { return supportsHVLineContainerBBox_; }; - /** * @function module:browser.supportsGoodTextCharPos * @returns {boolean} */ + var supportsGoodTextCharPos = function supportsGoodTextCharPos() { return supportsGoodTextCharPos_; }; - /** * @function module:browser.supportsNonScalingStroke * @returns {boolean} */ + var supportsNonScalingStroke = function supportsNonScalingStroke() { return supportsNonScalingStroke_; }; - /** * @function module:browser.supportsNativeTransformLists * @returns {boolean} */ + var supportsNativeTransformLists = function supportsNativeTransformLists() { return supportsNativeSVGTransformLists_; }; @@ -2402,36 +2910,40 @@ * This fixes `$(...).attr()` to work as expected with SVG elements. * Does not currently use `*AttributeNS()` since we rarely need that. * Adds {@link external:jQuery.fn.attr}. - * See {@link https://api.jquery.com/attr/} for basic documentation of `.attr()` + * See {@link https://api.jquery.com/attr/} for basic documentation of `.attr()`. * * Additional functionality: * - When getting attributes, a string that's a number is returned as type number. * - If an array is supplied as the first parameter, multiple values are returned - * as an object with values for each given attribute + * as an object with values for each given attribute. * @function module:jQueryAttr.jQueryAttr * @param {external:jQuery} $ The jQuery object to which to add the plug-in * @returns {external:jQuery} */ - function jqPluginSVG ($) { + function jQueryPluginSVG($) { var proxied = $.fn.attr, svgns = 'http://www.w3.org/2000/svg'; /** * @typedef {PlainObject.<string, string|Float>} module:jQueryAttr.Attributes */ + /** * @function external:jQuery.fn.attr * @param {string|string[]|PlainObject.<string, string>} key * @param {string} value * @returns {external:jQuery|module:jQueryAttr.Attributes} */ + $.fn.attr = function (key, value) { var len = this.length; + if (!len) { - return proxied.apply(this, arguments); + return proxied.call(this, key, value); } + for (var i = 0; i < len; ++i) { - var elem = this[i]; - // set/get SVG attribute + var elem = this[i]; // set/get SVG attribute + if (elem.namespaceURI === svgns) { // Setting attribute if (value !== undefined) { @@ -2443,87 +2955,72 @@ while (j--) { var aname = key[j]; - var attr = elem.getAttribute(aname); - // This returns a number when appropriate + var attr = elem.getAttribute(aname); // This returns a number when appropriate + if (attr || attr === '0') { attr = isNaN(attr) ? attr : attr - 0; } + obj[aname] = attr; } + return obj; } - if ((typeof key === 'undefined' ? 'undefined' : _typeof(key)) === 'object') { + + if (_typeof(key) === 'object') { // Setting attributes from object - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; + var _arr = Object.entries(key); - try { - for (var _iterator = Object.entries(key)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var _ref = _step.value; + for (var _i = 0; _i < _arr.length; _i++) { + var _arr$_i = _slicedToArray(_arr[_i], 2), + name = _arr$_i[0], + val = _arr$_i[1]; - var _ref2 = slicedToArray(_ref, 2); + elem.setAttribute(name, val); + } // Getting attribute - var name = _ref2[0]; - var val = _ref2[1]; - - elem.setAttribute(name, val); - } - // Getting attribute - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } } else { var _attr = elem.getAttribute(key); + if (_attr || _attr === '0') { _attr = isNaN(_attr) ? _attr : _attr - 0; } + return _attr; } } else { - return proxied.apply(this, arguments); + return proxied.call(this, key, value); } } + return this; }; + return $; } + var svgroot = document.createElementNS(NS.SVG, 'svg'); /** - * Partial polyfill of `SVGTransformList` - * @module SVGTransformList - * - * @license MIT - * - * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller + * Helper function to convert `SVGTransform` to a string. + * @param {SVGTransform} xform + * @returns {string} */ - var svgroot = document.createElementNS(NS.SVG, 'svg'); - - // Helper function. function transformToString(xform) { var m = xform.matrix; var text = ''; + switch (xform.type) { case 1: // MATRIX text = 'matrix(' + [m.a, m.b, m.c, m.d, m.e, m.f].join(',') + ')'; break; + case 2: // TRANSLATE text = 'translate(' + m.e + ',' + m.f + ')'; break; + case 3: // SCALE if (m.a === m.d) { @@ -2531,49 +3028,57 @@ } else { text = 'scale(' + m.a + ',' + m.d + ')'; } + break; + case 4: { // ROTATE var cx = 0; - var cy = 0; - // this prevents divide by zero + var cy = 0; // this prevents divide by zero + if (xform.angle !== 0) { var K = 1 - m.a; cy = (K * m.f + m.b * m.e) / (K * K + m.b * m.b); cx = (m.e - m.b * cy) / K; } + text = 'rotate(' + xform.angle + ' ' + cx + ',' + cy + ')'; break; } } + return text; } - /** * Map of SVGTransformList objects. */ - var listMap_ = {}; + + var listMap_ = {}; /** * @interface module:SVGTransformList.SVGEditTransformList * @property {Integer} numberOfItems unsigned long */ + /** * @function module:SVGTransformList.SVGEditTransformList#clear * @returns {undefined} */ + /** * @function module:SVGTransformList.SVGEditTransformList#initialize * @param {SVGTransform} newItem * @returns {SVGTransform} */ + /** * (DOES NOT THROW DOMException, INDEX_SIZE_ERR) * @function module:SVGTransformList.SVGEditTransformList#getItem * @param {Integer} index unsigned long * @returns {SVGTransform} */ + /** * (DOES NOT THROW DOMException, INDEX_SIZE_ERR) * @function module:SVGTransformList.SVGEditTransformList#insertItemBefore @@ -2581,6 +3086,7 @@ * @param {Integer} index unsigned long * @returns {SVGTransform} */ + /** * (DOES NOT THROW DOMException, INDEX_SIZE_ERR) * @function module:SVGTransformList.SVGEditTransformList#replaceItem @@ -2588,17 +3094,20 @@ * @param {Integer} index unsigned long * @returns {SVGTransform} */ + /** * (DOES NOT THROW DOMException, INDEX_SIZE_ERR) * @function module:SVGTransformList.SVGEditTransformList#removeItem * @param {Integer} index unsigned long * @returns {SVGTransform} */ + /** * @function module:SVGTransformList.SVGEditTransformList#appendItem * @param {SVGTransform} newItem * @returns {SVGTransform} */ + /** * NOT IMPLEMENTED * @ignore @@ -2606,6 +3115,7 @@ * @param {SVGMatrix} matrix * @returns {SVGTransform} */ + /** * NOT IMPLEMENTED * @ignore @@ -2618,42 +3128,55 @@ * These methods do not currently raise any exceptions. * These methods also do not check that transforms are being inserted. This is basically * implementing as much of SVGTransformList that we need to get the job done. + * @implements {module:SVGTransformList.SVGEditTransformList} */ - var SVGTransformList = function () { + + var SVGTransformList = + /*#__PURE__*/ + function () { + // eslint-disable-line no-shadow + /** * @param {Element} elem */ function SVGTransformList(elem) { - classCallCheck(this, SVGTransformList); + _classCallCheck(this, SVGTransformList); this._elem = elem || null; - this._xforms = []; - // TODO: how do we capture the undo-ability in the changed transform list? + this._xforms = []; // TODO: how do we capture the undo-ability in the changed transform list? + this._update = function () { - var tstr = ''; - /* const concatMatrix = */svgroot.createSVGMatrix(); + var tstr = ''; // /* const concatMatrix = */ svgroot.createSVGMatrix(); + for (var i = 0; i < this.numberOfItems; ++i) { var xform = this._list.getItem(i); + tstr += transformToString(xform) + ' '; } + this._elem.setAttribute('transform', tstr); }; + this._list = this; + this._init = function () { var _this = this; // Transform attribute parser var str = this._elem.getAttribute('transform'); + if (!str) { return; - } + } // TODO: Add skew support in future + - // TODO: Add skew support in future var re = /\s*((scale|matrix|rotate|translate)\s*\(.*?\))\s*,?\s*/; var m = true; + while (m) { m = str.match(re); str = str.replace(re, ''); + if (m && m[1]) { (function () { var x = m[1]; @@ -2666,6 +3189,7 @@ var mtx = svgroot.createSVGMatrix(); Object.values(valArr).forEach(function (item, i) { valArr[i] = parseFloat(item); + if (name === 'matrix') { mtx[letters[i]] = valArr[i]; } @@ -2681,30 +3205,29 @@ } else if (name === 'rotate' && values.length === 1) { values.push(0, 0); } - xform[fname].apply(xform, values); + + xform[fname].apply(xform, _toConsumableArray(values)); + _this._list.appendItem(xform); })(); } } }; + this._removeFromOtherLists = function (item) { if (item) { // Check if this transform is already in a transformlist, and // remove it if so. - var found = false; - for (var id in listMap_) { - var tl = listMap_[id]; + Object.values(listMap_).some(function (tl) { for (var i = 0, len = tl._xforms.length; i < len; ++i) { if (tl._xforms[i] === item) { - found = true; tl.removeItem(i); - break; + return true; } } - if (found) { - break; - } - } + + return false; + }); } }; @@ -2715,26 +3238,26 @@ */ - createClass(SVGTransformList, [{ - key: 'clear', + _createClass(SVGTransformList, [{ + key: "clear", value: function clear() { this.numberOfItems = 0; this._xforms = []; } - /** * @param {SVGTransform} newItem * @returns {SVGTransform} */ }, { - key: 'initialize', + key: "initialize", value: function initialize(newItem) { this.numberOfItems = 1; + this._removeFromOtherLists(newItem); + this._xforms = [newItem]; } - /** * @param {Integer} index unsigned long * @throws {Error} @@ -2742,16 +3265,16 @@ */ }, { - key: 'getItem', + key: "getItem", value: function getItem(index) { if (index < this.numberOfItems && index >= 0) { return this._xforms[index]; } + var err = new Error('DOMException with code=INDEX_SIZE_ERR'); err.code = 1; throw err; } - /** * @param {SVGTransform} newItem * @param {Integer} index unsigned long @@ -2759,33 +3282,40 @@ */ }, { - key: 'insertItemBefore', + key: "insertItemBefore", value: function insertItemBefore(newItem, index) { var retValue = null; + if (index >= 0) { if (index < this.numberOfItems) { this._removeFromOtherLists(newItem); - var newxforms = new Array(this.numberOfItems + 1); - // TODO: use array copying and slicing - var i = void 0; + + var newxforms = new Array(this.numberOfItems + 1); // TODO: use array copying and slicing + + var i; + for (i = 0; i < index; ++i) { newxforms[i] = this._xforms[i]; } + newxforms[i] = newItem; + for (var j = i + 1; i < this.numberOfItems; ++j, ++i) { newxforms[j] = this._xforms[i]; } + this.numberOfItems++; this._xforms = newxforms; retValue = newItem; + this._list._update(); } else { retValue = this._list.appendItem(newItem); } } + return retValue; } - /** * @param {SVGTransform} newItem * @param {Integer} index unsigned long @@ -2793,18 +3323,21 @@ */ }, { - key: 'replaceItem', + key: "replaceItem", value: function replaceItem(newItem, index) { var retValue = null; + if (index < this.numberOfItems && index >= 0) { this._removeFromOtherLists(newItem); + this._xforms[index] = newItem; retValue = newItem; + this._list._update(); } + return retValue; } - /** * @param {Integer} index unsigned long * @throws {Error} @@ -2812,90 +3345,108 @@ */ }, { - key: 'removeItem', + key: "removeItem", value: function removeItem(index) { if (index < this.numberOfItems && index >= 0) { var retValue = this._xforms[index]; var newxforms = new Array(this.numberOfItems - 1); - var i = void 0; + var i; + for (i = 0; i < index; ++i) { newxforms[i] = this._xforms[i]; } + for (var j = i; j < this.numberOfItems - 1; ++j, ++i) { newxforms[j] = this._xforms[i + 1]; } + this.numberOfItems--; this._xforms = newxforms; + this._list._update(); + return retValue; } + var err = new Error('DOMException with code=INDEX_SIZE_ERR'); err.code = 1; throw err; } - /** * @param {SVGTransform} newItem * @returns {SVGTransform} */ }, { - key: 'appendItem', + key: "appendItem", value: function appendItem(newItem) { this._removeFromOtherLists(newItem); + this._xforms.push(newItem); + this.numberOfItems++; + this._list._update(); + return newItem; } }]); + return SVGTransformList; }(); - /** * @function module:SVGTransformList.resetListMap * @returns {undefined} */ + var resetListMap = function resetListMap() { listMap_ = {}; }; - /** * Removes transforms of the given element from the map. * @function module:SVGTransformList.removeElementFromListMap * @param {Element} elem - a DOM Element * @returns {undefined} */ + var removeElementFromListMap = function removeElementFromListMap(elem) { + // eslint-disable-line import/no-mutable-exports if (elem.id && listMap_[elem.id]) { delete listMap_[elem.id]; } }; - /** - * Returns an object that behaves like a `SVGTransformList` for the given DOM element + * Returns an object that behaves like a `SVGTransformList` for the given DOM element. * @function module:SVGTransformList.getTransformList * @param {Element} elem - DOM element to get a transformlist from * @todo The polyfill should have `SVGAnimatedTransformList` and this should use it * @returns {SVGAnimatedTransformList|SVGTransformList} */ + var getTransformList = function getTransformList(elem) { if (!supportsNativeTransformLists()) { var id = elem.id || 'temp'; var t = listMap_[id]; + if (!t || id === 'temp') { listMap_[id] = new SVGTransformList(elem); + listMap_[id]._init(); + t = listMap_[id]; } + return t; } + if (elem.transform) { return elem.transform.baseVal; } + if (elem.gradientTransform) { return elem.gradientTransform.baseVal; } + if (elem.patternTransform) { return elem.patternTransform.baseVal; } @@ -2910,11 +3461,10 @@ * * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller */ - var wAttrs = ['x', 'x1', 'cx', 'rx', 'width']; var hAttrs = ['y', 'y1', 'cy', 'ry', 'height']; - var unitAttrs = ['r', 'radius'].concat(wAttrs, hAttrs); - // unused + var unitAttrs = ['r', 'radius'].concat(wAttrs, hAttrs); // unused + /* const unitNumMap = { '%': 2, @@ -2929,30 +3479,34 @@ }; */ // Container of elements. - var elementContainer_ = void 0; - // Stores mapping of unit type to user coordinates. + var elementContainer_; // Stores mapping of unit type to user coordinates. + var typeMap_ = {}; - /** * @interface module:units.ElementContainer */ + /** * @function module:units.ElementContainer#getBaseUnit * @returns {string} The base unit type of the container ('em') */ + /** * @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 * @returns {Float} The container's height */ + /** * @function module:units.ElementContainer#getWidth * @returns {Float} The container's width */ + /** * @function module:units.ElementContainer#getRoundDigits * @returns {Integer} The number of digits number should be rounded to @@ -2978,10 +3532,10 @@ * @param {module:units.ElementContainer} elementContainer - An object implementing the ElementContainer interface. * @returns {undefined} */ - var init = function init(elementContainer) { - elementContainer_ = elementContainer; - // Get correct em/ex values by creating a temporary SVG. + var init = function init(elementContainer) { + elementContainer_ = elementContainer; // Get correct em/ex values by creating a temporary SVG. + var svg = document.createElementNS(NS.SVG, 'svg'); document.body.append(svg); var rect = document.createElementNS(NS.SVG, 'rect'); @@ -2991,7 +3545,6 @@ svg.append(rect); var bb = rect.getBBox(); svg.remove(); - var inch = bb.x; typeMap_ = { em: bb.width, @@ -3005,7 +3558,6 @@ '%': 0 }; }; - /** * Group: Unit conversion functions */ @@ -3014,10 +3566,10 @@ * @function module:units.getTypeMap * @returns {module:units.TypeMap} The unit object with values for each unit */ + var getTypeMap = function getTypeMap() { return typeMap_; }; - /** * @typedef {GenericArray} module:units.CompareNumbers * @property {Integer} length 2 @@ -3034,31 +3586,35 @@ * @returns {Float|string} If a string/number was given, returns a Float. If an array, return a string * with comma-separated floats */ + var shortFloat = function shortFloat(val) { var digits = elementContainer_.getRoundDigits(); + if (!isNaN(val)) { - // Note that + converts to Number - return +(+val).toFixed(digits); + return Number(Number(val).toFixed(digits)); } + if (Array.isArray(val)) { return shortFloat(val[0]) + ',' + shortFloat(val[1]); } + return parseFloat(val).toFixed(digits) - 0; }; - /** - * Converts the number to given unit or baseUnit + * Converts the number to given unit or baseUnit. * @function module:units.convertUnit + * @param {string|Float} val + * @param {"em"|"ex"|"in"|"cm"|"mm"|"pt"|"pc"|"px"|"%"} [unit] * @returns {Float} */ + var convertUnit = function convertUnit(val, unit) { - unit = unit || elementContainer_.getBaseUnit(); - // baseVal.convertToSpecifiedUnits(unitNumMap[unit]); + unit = unit || elementContainer_.getBaseUnit(); // baseVal.convertToSpecifiedUnits(unitNumMap[unit]); // const val = baseVal.valueInSpecifiedUnits; // baseVal.convertToSpecifiedUnits(1); + return shortFloat(val / typeMap_[unit]); }; - /** * Sets an element's attribute based on the unit in its current value. * @@ -3068,11 +3624,11 @@ * @param {string} val - Attribute value to convert * @returns {undefined} */ + var setUnitAttr = function setUnitAttr(elem, attr, val) { // if (!isNaN(val)) { // New value is a number, so check currently used unit // const oldVal = elem.getAttribute(attr); - // Enable this for alternate mode // if (oldVal !== null && (isNaN(oldVal) || elementContainer_.getBaseUnit() !== 'px')) { // // Old value was a number, so get unit, then convert @@ -3102,109 +3658,112 @@ // } elem.setAttribute(attr, val); }; - /** * Converts given values to numbers. Attributes must be supplied in - * case a percentage is given + * case a percentage is given. * * @function module:units.convertToNum * @param {string} attr - Name of the attribute associated with the value * @param {string} val - Attribute value to convert * @returns {Float} The converted number */ + var convertToNum = function convertToNum(attr, val) { // Return a number if that's what it already is if (!isNaN(val)) { return val - 0; } + if (val.substr(-1) === '%') { // Deal with percentage, depends on attribute var _num = val.substr(0, val.length - 1) / 100; + var width = elementContainer_.getWidth(); var height = elementContainer_.getHeight(); if (wAttrs.includes(attr)) { return _num * width; } + if (hAttrs.includes(attr)) { return _num * height; } + return _num * Math.sqrt(width * width + height * height) / Math.sqrt(2); } + var unit = val.substr(-2); - var num = val.substr(0, val.length - 2); - // Note that this multiplication turns the string into a number + var num = val.substr(0, val.length - 2); // Note that this multiplication turns the string into a number + return num * typeMap_[unit]; }; - /** - * Check if an attribute's value is in a valid format + * Check if an attribute's value is in a valid format. * @function module:units.isValidUnit * @param {string} attr - The name of the attribute associated with the value * @param {string} val - The attribute value to check + * @param {Element} selectedElement * @returns {boolean} Whether the unit is valid */ + var isValidUnit = function isValidUnit(attr, val, selectedElement) { if (unitAttrs.includes(attr)) { // True if it's just a number if (!isNaN(val)) { return true; - } - // Not a number, check if it has a valid unit + } // Not a number, check if it has a valid unit + + val = val.toLowerCase(); return Object.keys(typeMap_).some(function (unit) { var re = new RegExp('^-?[\\d\\.]+' + unit + '$'); return re.test(val); }); } + if (attr === 'id') { // if we're trying to change the id, make sure it's not already present in the doc // and the id value is valid. - - var result = false; - // because getElem() can throw an exception in the case of an invalid id + var result = false; // because getElem() can throw an exception in the case of an invalid id // (according to https://www.w3.org/TR/xml-id/ IDs must be a NCName) // we wrap it in an exception and only return true if the ID was valid and // not already present + try { var elem = elementContainer_.getElement(val); - result = elem == null || elem === selectedElement; + result = isNullish(elem) || elem === selectedElement; } catch (e) {} + return result; } + return true; }; - /** - * For command history tracking and undo functionality - * @module history - * @license MIT - * @copyright 2010 Jeff Schiller - */ - /** * Group: Undo/Redo history management */ + var HistoryEventTypes = { BEFORE_APPLY: 'before_apply', AFTER_APPLY: 'after_apply', BEFORE_UNAPPLY: 'before_unapply', AFTER_UNAPPLY: 'after_unapply' - }; - - // const removedElements = {}; + }; // const removedElements = {}; /** - * Base class for commands + * Base class for commands. */ - var Command = function () { + var Command = + /*#__PURE__*/ + function () { function Command() { - classCallCheck(this, Command); + _classCallCheck(this, Command); } - createClass(Command, [{ - key: 'getText', + _createClass(Command, [{ + key: "getText", /** * @returns {string} @@ -3213,10 +3772,9 @@ return this.text; } }]); - return Command; - }(); - // Todo: Figure out why the interface members aren't showing + return Command; + }(); // Todo: Figure out why the interface members aren't showing // up (with or without modules applied), despite our apparently following // http://usejsdoc.org/tags-interface.html#virtual-comments @@ -3224,6 +3782,7 @@ * An interface that all command objects must implement. * @interface module:history.HistoryCommand */ + /** * Applies * @@ -3232,6 +3791,7 @@ * @fires module:history~Command#event:history * @returns {undefined|true} */ + /** * * Unapplies @@ -3240,21 +3800,25 @@ * @fires module:history~Command#event:history * @returns {undefined|true} */ + /** * Returns the elements * @function module:history.HistoryCommand#elements * @returns {Element[]} */ + /** * Gets the text * @function module:history.HistoryCommand#getText * @returns {string} */ + /** * Gives the type * @function module:history.HistoryCommand.type * @returns {string} */ + /** * Gives the type * @function module:history.HistoryCommand#type @@ -3270,6 +3834,7 @@ * An interface for objects that will handle history events. * @interface module:history.HistoryEventHandler */ + /** * * @function module:history.HistoryEventHandler#handleHistoryEvent @@ -3281,7 +3846,7 @@ */ /** - * History command for an element that had its DOM position changed + * History command for an element that had its DOM position changed. * @implements {module:history.HistoryCommand} * @param {Element} elem - The DOM element that was moved * @param {Element} oldNextSibling - The element's next sibling before it was moved @@ -3290,14 +3855,17 @@ */ - var MoveElementCommand = function (_Command) { - inherits(MoveElementCommand, _Command); + var MoveElementCommand = + /*#__PURE__*/ + function (_Command) { + _inherits(MoveElementCommand, _Command); function MoveElementCommand(elem, oldNextSibling, oldParent, text) { - classCallCheck(this, MoveElementCommand); + var _this; - var _this = possibleConstructorReturn(this, (MoveElementCommand.__proto__ || Object.getPrototypeOf(MoveElementCommand)).call(this)); + _classCallCheck(this, MoveElementCommand); + _this = _possibleConstructorReturn(this, _getPrototypeOf(MoveElementCommand).call(this)); _this.elem = elem; _this.text = text ? 'Move ' + elem.tagName + ' to ' + text : 'Move ' + elem.tagName; _this.oldNextSibling = oldNextSibling; @@ -3307,21 +3875,21 @@ return _this; } - createClass(MoveElementCommand, [{ - key: 'type', + _createClass(MoveElementCommand, [{ + key: "type", value: function type() { + // eslint-disable-line class-methods-use-this return 'svgedit.history.MoveElementCommand'; } - /** - * Re-positions the element + * Re-positions the element. * @param {module:history.HistoryEventHandler} handler * @fires module:history~Command#event:history * @returns {undefined} */ }, { - key: 'apply', + key: "apply", value: function apply(handler) { // TODO(codedread): Refactor this common event code into a base HistoryCommand class. if (handler) { @@ -3334,16 +3902,15 @@ handler.handleHistoryEvent(HistoryEventTypes.AFTER_APPLY, this); } } - /** - * Positions the element back to its original location + * Positions the element back to its original location. * @param {module:history.HistoryEventHandler} handler * @fires module:history~Command#event:history * @returns {undefined} */ }, { - key: 'unapply', + key: "unapply", value: function unapply(handler) { if (handler) { handler.handleHistoryEvent(HistoryEventTypes.BEFORE_UNAPPLY, this); @@ -3355,36 +3922,39 @@ handler.handleHistoryEvent(HistoryEventTypes.AFTER_UNAPPLY, this); } } - /** * @returns {Element[]} Array with element associated with this command */ }, { - key: 'elements', + key: "elements", value: function elements() { return [this.elem]; } }]); + return MoveElementCommand; }(Command); MoveElementCommand.type = MoveElementCommand.prototype.type; - /** - * History command for an element that was added to the DOM + * History command for an element that was added to the DOM. * @implements {module:history.HistoryCommand} * * @param {Element} elem - The newly added DOM element * @param {string} text - An optional string visible to user related to this change */ - var InsertElementCommand = function (_Command2) { - inherits(InsertElementCommand, _Command2); + + var InsertElementCommand = + /*#__PURE__*/ + function (_Command2) { + _inherits(InsertElementCommand, _Command2); function InsertElementCommand(elem, text) { - classCallCheck(this, InsertElementCommand); + var _this2; - var _this2 = possibleConstructorReturn(this, (InsertElementCommand.__proto__ || Object.getPrototypeOf(InsertElementCommand)).call(this)); + _classCallCheck(this, InsertElementCommand); + _this2 = _possibleConstructorReturn(this, _getPrototypeOf(InsertElementCommand).call(this)); _this2.elem = elem; _this2.text = text || 'Create ' + elem.tagName; _this2.parent = elem.parentNode; @@ -3392,21 +3962,21 @@ return _this2; } - createClass(InsertElementCommand, [{ - key: 'type', + _createClass(InsertElementCommand, [{ + key: "type", value: function type() { + // eslint-disable-line class-methods-use-this return 'svgedit.history.InsertElementCommand'; } - /** - * Re-inserts the new element + * Re-inserts the new element. * @param {module:history.HistoryEventHandler} handler * @fires module:history~Command#event:history * @returns {undefined} */ }, { - key: 'apply', + key: "apply", value: function apply(handler) { if (handler) { handler.handleHistoryEvent(HistoryEventTypes.BEFORE_APPLY, this); @@ -3418,16 +3988,15 @@ handler.handleHistoryEvent(HistoryEventTypes.AFTER_APPLY, this); } } - /** - * Removes the element + * Removes the element. * @param {module:history.HistoryEventHandler} handler * @fires module:history~Command#event:history * @returns {undefined} */ }, { - key: 'unapply', + key: "unapply", value: function unapply(handler) { if (handler) { handler.handleHistoryEvent(HistoryEventTypes.BEFORE_UNAPPLY, this); @@ -3440,62 +4009,64 @@ handler.handleHistoryEvent(HistoryEventTypes.AFTER_UNAPPLY, this); } } - /** * @returns {Element[]} Array with element associated with this command */ }, { - key: 'elements', + key: "elements", value: function elements() { return [this.elem]; } }]); + return InsertElementCommand; }(Command); InsertElementCommand.type = InsertElementCommand.prototype.type; - /** - * History command for an element removed from the DOM + * History command for an element removed from the DOM. * @implements {module:history.HistoryCommand} * @param {Element} elem - The removed DOM element * @param {Node} oldNextSibling - The DOM element's nextSibling when it was in the DOM * @param {Element} oldParent - The DOM element's parent * @param {string} [text] - An optional string visible to user related to this change */ - var RemoveElementCommand = function (_Command3) { - inherits(RemoveElementCommand, _Command3); + + var RemoveElementCommand = + /*#__PURE__*/ + function (_Command3) { + _inherits(RemoveElementCommand, _Command3); function RemoveElementCommand(elem, oldNextSibling, oldParent, text) { - classCallCheck(this, RemoveElementCommand); + var _this3; - var _this3 = possibleConstructorReturn(this, (RemoveElementCommand.__proto__ || Object.getPrototypeOf(RemoveElementCommand)).call(this)); + _classCallCheck(this, RemoveElementCommand); + _this3 = _possibleConstructorReturn(this, _getPrototypeOf(RemoveElementCommand).call(this)); _this3.elem = elem; _this3.text = text || 'Delete ' + elem.tagName; _this3.nextSibling = oldNextSibling; - _this3.parent = oldParent; + _this3.parent = oldParent; // special hack for webkit: remove this element's entry in the svgTransformLists map - // special hack for webkit: remove this element's entry in the svgTransformLists map removeElementFromListMap(elem); return _this3; } - createClass(RemoveElementCommand, [{ - key: 'type', + _createClass(RemoveElementCommand, [{ + key: "type", value: function type() { + // eslint-disable-line class-methods-use-this return 'svgedit.history.RemoveElementCommand'; } - /** - * Re-removes the new element + * Re-removes the new element. * @param {module:history.HistoryEventHandler} handler * @fires module:history~Command#event:history * @returns {undefined} */ }, { - key: 'apply', + key: "apply", value: function apply(handler) { if (handler) { handler.handleHistoryEvent(HistoryEventTypes.BEFORE_APPLY, this); @@ -3509,51 +4080,52 @@ handler.handleHistoryEvent(HistoryEventTypes.AFTER_APPLY, this); } } - /** - * Re-adds the new element + * Re-adds the new element. * @param {module:history.HistoryEventHandler} handler * @fires module:history~Command#event:history * @returns {undefined} */ }, { - key: 'unapply', + key: "unapply", value: function unapply(handler) { if (handler) { handler.handleHistoryEvent(HistoryEventTypes.BEFORE_UNAPPLY, this); } removeElementFromListMap(this.elem); - if (this.nextSibling == null) { + + if (isNullish(this.nextSibling)) { if (window.console) { - console.log('Error: reference element was lost'); + console.log('Error: reference element was lost'); // eslint-disable-line no-console } } + this.parent.insertBefore(this.elem, this.nextSibling); // Don't use `before` or `prepend` as `this.nextSibling` may be `null` if (handler) { handler.handleHistoryEvent(HistoryEventTypes.AFTER_UNAPPLY, this); } } - /** * @returns {Element[]} Array with element associated with this command */ }, { - key: 'elements', + key: "elements", value: function elements() { return [this.elem]; } }]); + return RemoveElementCommand; }(Command); RemoveElementCommand.type = RemoveElementCommand.prototype.type; - /** * @typedef {"#text"|"#href"|string} module:history.CommandAttributeName */ + /** * @typedef {PlainObject.<module:history.CommandAttributeName, string>} module:history.CommandAttributes */ @@ -3566,18 +4138,23 @@ * @param {module:history.CommandAttributes} attrs - Attributes to be changed with the values they had *before* the change * @param {string} text - An optional string visible to user related to this change */ - var ChangeElementCommand = function (_Command4) { - inherits(ChangeElementCommand, _Command4); + + var ChangeElementCommand = + /*#__PURE__*/ + function (_Command4) { + _inherits(ChangeElementCommand, _Command4); function ChangeElementCommand(elem, attrs, text) { - classCallCheck(this, ChangeElementCommand); + var _this4; - var _this4 = possibleConstructorReturn(this, (ChangeElementCommand.__proto__ || Object.getPrototypeOf(ChangeElementCommand)).call(this)); + _classCallCheck(this, ChangeElementCommand); + _this4 = _possibleConstructorReturn(this, _getPrototypeOf(ChangeElementCommand).call(this)); _this4.elem = elem; _this4.text = text ? 'Change ' + elem.tagName + ' ' + text : 'Change ' + elem.tagName; _this4.newValues = {}; _this4.oldValues = attrs; + for (var attr in attrs) { if (attr === '#text') { _this4.newValues[attr] = elem.textContent; @@ -3587,61 +4164,68 @@ _this4.newValues[attr] = elem.getAttribute(attr); } } + return _this4; } - createClass(ChangeElementCommand, [{ - key: 'type', + _createClass(ChangeElementCommand, [{ + key: "type", value: function type() { + // eslint-disable-line class-methods-use-this return 'svgedit.history.ChangeElementCommand'; } - /** - * Performs the stored change action + * Performs the stored change action. * @param {module:history.HistoryEventHandler} handler * @fires module:history~Command#event:history * @returns {true} */ }, { - key: 'apply', + key: "apply", value: function apply(handler) { + var _this5 = this; + if (handler) { handler.handleHistoryEvent(HistoryEventTypes.BEFORE_APPLY, this); } var bChangedTransform = false; - for (var attr in this.newValues) { - if (this.newValues[attr]) { + Object.entries(this.newValues).forEach(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + attr = _ref2[0], + value = _ref2[1]; + + if (value) { if (attr === '#text') { - this.elem.textContent = this.newValues[attr]; + _this5.elem.textContent = value; } else if (attr === '#href') { - setHref(this.elem, this.newValues[attr]); + setHref(_this5.elem, value); } else { - this.elem.setAttribute(attr, this.newValues[attr]); + _this5.elem.setAttribute(attr, value); } + } else if (attr === '#text') { + _this5.elem.textContent = ''; } else { - if (attr === '#text') { - this.elem.textContent = ''; - } else { - this.elem.setAttribute(attr, ''); - this.elem.removeAttribute(attr); - } + _this5.elem.setAttribute(attr, ''); + + _this5.elem.removeAttribute(attr); } if (attr === 'transform') { bChangedTransform = true; } - } + }); // relocate rotational transform, if necessary - // relocate rotational transform, if necessary if (!bChangedTransform) { var angle = getRotationAngle(this.elem); + if (angle) { var bbox = this.elem.getBBox(); var cx = bbox.x + bbox.width / 2, cy = bbox.y + bbox.height / 2; var rotate = ['rotate(', angle, ' ', cx, ',', cy, ')'].join(''); + if (rotate !== this.elem.getAttribute('transform')) { this.elem.setAttribute('transform', rotate); } @@ -3654,57 +4238,63 @@ return true; } - /** - * Reverses the stored change action + * Reverses the stored change action. * @param {module:history.HistoryEventHandler} handler * @fires module:history~Command#event:history * @returns {true} */ }, { - key: 'unapply', + key: "unapply", value: function unapply(handler) { + var _this6 = this; + if (handler) { handler.handleHistoryEvent(HistoryEventTypes.BEFORE_UNAPPLY, this); } var bChangedTransform = false; - for (var attr in this.oldValues) { - if (this.oldValues[attr]) { + Object.entries(this.oldValues).forEach(function (_ref3) { + var _ref4 = _slicedToArray(_ref3, 2), + attr = _ref4[0], + value = _ref4[1]; + + if (value) { if (attr === '#text') { - this.elem.textContent = this.oldValues[attr]; + _this6.elem.textContent = value; } else if (attr === '#href') { - setHref(this.elem, this.oldValues[attr]); + setHref(_this6.elem, value); } else { - this.elem.setAttribute(attr, this.oldValues[attr]); + _this6.elem.setAttribute(attr, value); } + } else if (attr === '#text') { + _this6.elem.textContent = ''; } else { - if (attr === '#text') { - this.elem.textContent = ''; - } else { - this.elem.removeAttribute(attr); - } + _this6.elem.removeAttribute(attr); } + if (attr === 'transform') { bChangedTransform = true; } - } - // relocate rotational transform, if necessary + }); // relocate rotational transform, if necessary + if (!bChangedTransform) { var angle = getRotationAngle(this.elem); + if (angle) { var bbox = this.elem.getBBox(); var cx = bbox.x + bbox.width / 2, cy = bbox.y + bbox.height / 2; var rotate = ['rotate(', angle, ' ', cx, ',', cy, ')'].join(''); + if (rotate !== this.elem.getAttribute('transform')) { this.elem.setAttribute('transform', rotate); } } - } + } // Remove transformlist to prevent confusion that causes bugs like 575. + - // Remove transformlist to prevent confusion that causes bugs like 575. removeElementFromListMap(this.elem); if (handler) { @@ -3713,66 +4303,69 @@ return true; } - /** * @returns {Element[]} Array with element associated with this command */ }, { - key: 'elements', + key: "elements", value: function elements() { return [this.elem]; } }]); + return ChangeElementCommand; }(Command); - ChangeElementCommand.type = ChangeElementCommand.prototype.type; - - // TODO: create a 'typing' command object that tracks changes in text + ChangeElementCommand.type = ChangeElementCommand.prototype.type; // TODO: create a 'typing' command object that tracks changes in text // if a new Typing command is created and the top command on the stack is also a Typing // and they both affect the same element, then collapse the two commands into one /** - * History command that can contain/execute multiple other commands + * History command that can contain/execute multiple other commands. * @implements {module:history.HistoryCommand} */ - var BatchCommand = function (_Command5) { - inherits(BatchCommand, _Command5); + + var BatchCommand = + /*#__PURE__*/ + function (_Command5) { + _inherits(BatchCommand, _Command5); /** * @param {string} [text] - An optional string visible to user related to this change */ function BatchCommand(text) { - classCallCheck(this, BatchCommand); + var _this7; - var _this5 = possibleConstructorReturn(this, (BatchCommand.__proto__ || Object.getPrototypeOf(BatchCommand)).call(this)); + _classCallCheck(this, BatchCommand); - _this5.text = text || 'Batch Command'; - _this5.stack = []; - return _this5; + _this7 = _possibleConstructorReturn(this, _getPrototypeOf(BatchCommand).call(this)); + _this7.text = text || 'Batch Command'; + _this7.stack = []; + return _this7; } - createClass(BatchCommand, [{ - key: 'type', + _createClass(BatchCommand, [{ + key: "type", value: function type() { + // eslint-disable-line class-methods-use-this return 'svgedit.history.BatchCommand'; } - /** - * Runs "apply" on all subcommands + * Runs "apply" on all subcommands. * @param {module:history.HistoryEventHandler} handler * @fires module:history~Command#event:history * @returns {undefined} */ }, { - key: 'apply', + key: "apply", value: function apply(handler) { if (handler) { handler.handleHistoryEvent(HistoryEventTypes.BEFORE_APPLY, this); } var len = this.stack.length; + for (var i = 0; i < len; ++i) { this.stack[i].apply(handler); } @@ -3781,16 +4374,15 @@ handler.handleHistoryEvent(HistoryEventTypes.AFTER_APPLY, this); } } - /** - * Runs "unapply" on all subcommands + * Runs "unapply" on all subcommands. * @param {module:history.HistoryEventHandler} handler * @fires module:history~Command#event:history * @returns {undefined} */ }, { - key: 'unapply', + key: "unapply", value: function unapply(handler) { if (handler) { handler.handleHistoryEvent(HistoryEventTypes.BEFORE_UNAPPLY, this); @@ -3804,178 +4396,172 @@ handler.handleHistoryEvent(HistoryEventTypes.AFTER_UNAPPLY, this); } } - /** - * Iterate through all our subcommands + * Iterate through all our subcommands. * @returns {Element[]} All the elements we are changing */ }, { - key: 'elements', + key: "elements", value: function elements() { var elems = []; var cmd = this.stack.length; + while (cmd--) { var thisElems = this.stack[cmd].elements(); var elem = thisElems.length; + while (elem--) { if (!elems.includes(thisElems[elem])) { elems.push(thisElems[elem]); } } } + return elems; } - /** - * Adds a given command to the history stack + * Adds a given command to the history stack. * @param {Command} cmd - The undo command object to add + * @returns {undefined} */ }, { - key: 'addSubCommand', + key: "addSubCommand", value: function addSubCommand(cmd) { this.stack.push(cmd); } - /** * @returns {boolean} Indicates whether or not the batch command is empty */ }, { - key: 'isEmpty', + key: "isEmpty", value: function isEmpty() { return !this.stack.length; } }]); + return BatchCommand; }(Command); BatchCommand.type = BatchCommand.prototype.type; - /** * */ - var UndoManager = function () { + + var UndoManager = + /*#__PURE__*/ + function () { /** * @param {module:history.HistoryEventHandler} historyEventHandler */ function UndoManager(historyEventHandler) { - classCallCheck(this, UndoManager); + _classCallCheck(this, UndoManager); this.handler_ = historyEventHandler || null; this.undoStackPointer = 0; - this.undoStack = []; - - // this is the stack that stores the original values, the elements and + this.undoStack = []; // this is the stack that stores the original values, the elements and // the attribute name for begin/finish + this.undoChangeStackPointer = -1; this.undoableChangeStack = []; } - /** - * Resets the undo stack, effectively clearing the undo/redo history + * Resets the undo stack, effectively clearing the undo/redo history. * @returns {undefined} */ - createClass(UndoManager, [{ - key: 'resetUndoStack', + _createClass(UndoManager, [{ + key: "resetUndoStack", value: function resetUndoStack() { this.undoStack = []; this.undoStackPointer = 0; } - /** * @returns {Integer} Current size of the undo history stack */ }, { - key: 'getUndoStackSize', + key: "getUndoStackSize", value: function getUndoStackSize() { return this.undoStackPointer; } - /** * @returns {Integer} Current size of the redo history stack */ }, { - key: 'getRedoStackSize', + key: "getRedoStackSize", value: function getRedoStackSize() { return this.undoStack.length - this.undoStackPointer; } - /** * @returns {string} String associated with the next undo command */ }, { - key: 'getNextUndoCommandText', + key: "getNextUndoCommandText", value: function getNextUndoCommandText() { return this.undoStackPointer > 0 ? this.undoStack[this.undoStackPointer - 1].getText() : ''; } - /** * @returns {string} String associated with the next redo command */ }, { - key: 'getNextRedoCommandText', + key: "getNextRedoCommandText", value: function getNextRedoCommandText() { return this.undoStackPointer < this.undoStack.length ? this.undoStack[this.undoStackPointer].getText() : ''; } - /** - * Performs an undo step + * Performs an undo step. * @returns {undefined} */ }, { - key: 'undo', + key: "undo", value: function undo() { if (this.undoStackPointer > 0) { var cmd = this.undoStack[--this.undoStackPointer]; cmd.unapply(this.handler_); } } - /** - * Performs a redo step + * Performs a redo step. * @returns {undefined} */ }, { - key: 'redo', + key: "redo", value: function redo() { if (this.undoStackPointer < this.undoStack.length && this.undoStack.length > 0) { var cmd = this.undoStack[this.undoStackPointer++]; cmd.apply(this.handler_); } } - /** - * Adds a command object to the undo history stack + * Adds a command object to the undo history stack. * @param {Command} cmd - The command object to add * @returns {undefined} */ }, { - key: 'addCommandToHistory', + key: "addCommandToHistory", value: function addCommandToHistory(cmd) { // FIXME: we MUST compress consecutive text changes to the same element // (right now each keystroke is saved as a separate command that includes the // entire text contents of the text element) // TODO: consider limiting the history that we store here (need to do some slicing) - // if our stack pointer is not at the end, then we have to remove // all commands after the pointer and insert the new command if (this.undoStackPointer < this.undoStack.length && this.undoStack.length > 0) { this.undoStack = this.undoStack.splice(0, this.undoStackPointer); } + this.undoStack.push(cmd); this.undoStackPointer = this.undoStack.length; } - /** * This function tells the canvas to remember the old values of the * `attrName` attribute for each element sent in. The elements and values @@ -3988,62 +4574,70 @@ */ }, { - key: 'beginUndoableChange', + key: "beginUndoableChange", value: function beginUndoableChange(attrName, elems) { var p = ++this.undoChangeStackPointer; var i = elems.length; var oldValues = new Array(i), elements = new Array(i); + while (i--) { var elem = elems[i]; - if (elem == null) { + + if (isNullish(elem)) { continue; } + elements[i] = elem; oldValues[i] = elem.getAttribute(attrName); } + this.undoableChangeStack[p] = { attrName: attrName, oldValues: oldValues, elements: elements }; } - /** * This function returns a `BatchCommand` object which summarizes the * change since `beginUndoableChange` was called. The command can then - * be added to the command history + * be added to the command history. * @returns {BatchCommand} Batch command object with resulting changes */ }, { - key: 'finishUndoableChange', + key: "finishUndoableChange", value: function finishUndoableChange() { var p = this.undoChangeStackPointer--; var changeset = this.undoableChangeStack[p]; var attrName = changeset.attrName; - var batchCmd = new BatchCommand('Change ' + attrName); var i = changeset.elements.length; + while (i--) { var elem = changeset.elements[i]; - if (elem == null) { + + if (isNullish(elem)) { continue; } + var changes = {}; changes[attrName] = changeset.oldValues[i]; + if (changes[attrName] !== elem.getAttribute(attrName)) { batchCmd.addSubCommand(new ChangeElementCommand(elem, changes, attrName)); } } + this.undoableChangeStack[p] = null; return batchCmd; } }]); + return UndoManager; }(); - var history = /*#__PURE__*/Object.freeze({ + var hstry = /*#__PURE__*/Object.freeze({ HistoryEventTypes: HistoryEventTypes, MoveElementCommand: MoveElementCommand, InsertElementCommand: InsertElementCommand, @@ -4061,45 +4655,46 @@ * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller */ - // Constants - var NEAR_ZERO = 1e-14; + var NEAR_ZERO = 1e-14; // Throw away SVGSVGElement used for creating matrices/transforms. - // Throw away SVGSVGElement used for creating matrices/transforms. var svg$1 = document.createElementNS(NS.SVG, 'svg'); - /** * A (hopefully) quicker function to transform a point by a matrix - * (this function avoids any DOM calls and just does the math) + * (this function avoids any DOM calls and just does the math). * @function module:math.transformPoint * @param {Float} x - Float representing the x coordinate * @param {Float} y - Float representing the y coordinate * @param {SVGMatrix} m - Matrix object to transform the point with * @returns {module:math.XYObject} An x, y object representing the transformed point */ - var transformPoint = function transformPoint(x, y, m) { - return { x: m.a * x + m.c * y + m.e, y: m.b * x + m.d * y + m.f }; - }; + var transformPoint = function transformPoint(x, y, m) { + return { + x: m.a * x + m.c * y + m.e, + y: m.b * x + m.d * y + m.f + }; + }; /** * Helper function to check if the matrix performs no actual transform - * (i.e. exists for identity purposes) + * (i.e. exists for identity purposes). * @function module:math.isIdentity * @param {SVGMatrix} m - The matrix object to check * @returns {boolean} Indicates whether or not the matrix is 1,0,0,1,0,0 */ + var isIdentity = function isIdentity(m) { return m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && m.e === 0 && m.f === 0; }; - /** * This function tries to return a `SVGMatrix` that is the multiplication `m1 * m2`. - * We also round to zero when it's near zero + * We also round to zero when it's near zero. * @function module:math.matrixMultiply * @param {...SVGMatrix} args - Matrix objects to multiply * @returns {SVGMatrix} The matrix object resulting from the calculation */ + var matrixMultiply = function matrixMultiply() { - for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } @@ -4110,45 +4705,46 @@ if (Math.abs(m.a) < NEAR_ZERO) { m.a = 0; } + if (Math.abs(m.b) < NEAR_ZERO) { m.b = 0; } + if (Math.abs(m.c) < NEAR_ZERO) { m.c = 0; } + if (Math.abs(m.d) < NEAR_ZERO) { m.d = 0; } + if (Math.abs(m.e) < NEAR_ZERO) { m.e = 0; } + if (Math.abs(m.f) < NEAR_ZERO) { m.f = 0; } return m; }; - - /** - * See if the given transformlist includes a non-indentity matrix transform - * @function module:math.hasMatrixTransform - * @param {SVGTransformList} [tlist] - The transformlist to check - * @returns {boolean} Whether or not a matrix transform was found - */ var hasMatrixTransform = function hasMatrixTransform(tlist) { if (!tlist) { return false; } + var num = tlist.numberOfItems; + while (num--) { var xform = tlist.getItem(num); + if (xform.type === 1 && !isIdentity(xform.matrix)) { return true; } } + return false; }; - /** * @typedef {PlainObject} module:math.TransformedBox An object with the following values * @property {module:math.XYObject} tl - The top left coordinate @@ -4163,7 +4759,7 @@ */ /** - * Transforms a rectangle based on the given matrix + * Transforms a rectangle based on the given matrix. * @function module:math.transformBox * @param {Float} l - Float with the box's left coordinate * @param {Float} t - Float with the box's top coordinate @@ -4172,6 +4768,7 @@ * @param {SVGMatrix} m - Matrix object to transform the box by * @returns {module:math.TransformedBox} */ + var transformBox = function transformBox(l, t, w, h, m) { var tl = transformPoint(l, t, m), tr = transformPoint(l + w, t, m), @@ -4181,7 +4778,6 @@ maxx = Math.max(tl.x, tr.x, bl.x, br.x), miny = Math.min(tl.y, tr.y, bl.y, br.y), maxy = Math.max(tl.y, tr.y, bl.y, br.y); - return { tl: tl, tr: tr, @@ -4195,12 +4791,11 @@ } }; }; - /** * This returns a single matrix Transform for a given Transform List * (this is the equivalent of `SVGTransformList.consolidate()` but unlike * that method, this one does not modify the actual `SVGTransformList`). - * This function is very liberal with its `min`, `max` arguments + * This function is very liberal with its `min`, `max` arguments. * @function module:math.transformListToTransform * @param {SVGTransformList} tlist - The transformlist object * @param {Integer} [min=0] - Optional integer indicating start transform position @@ -4208,90 +4803,103 @@ * defaults to one less than the tlist's `numberOfItems` * @returns {SVGTransform} A single matrix transform object */ + var transformListToTransform = function transformListToTransform(tlist, min, max) { - if (tlist == null) { + if (isNullish(tlist)) { // Or should tlist = null have been prevented before this? return svg$1.createSVGTransformFromMatrix(svg$1.createSVGMatrix()); } + min = min || 0; max = max || tlist.numberOfItems - 1; - min = parseInt(min, 10); - max = parseInt(max, 10); + min = parseInt(min); + max = parseInt(max); + if (min > max) { - var temp = max;max = min;min = temp; + var temp = max; + max = min; + min = temp; } + var m = svg$1.createSVGMatrix(); + for (var i = min; i <= max; ++i) { // if our indices are out of range, just use a harmless identity matrix var mtom = i >= 0 && i < tlist.numberOfItems ? tlist.getItem(i).matrix : svg$1.createSVGMatrix(); m = matrixMultiply(m, mtom); } + return svg$1.createSVGTransformFromMatrix(m); }; - /** - * Get the matrix object for a given element + * Get the matrix object for a given element. * @function module:math.getMatrix * @param {Element} elem - The DOM element to check * @returns {SVGMatrix} The matrix object associated with the element's transformlist */ + var getMatrix = function getMatrix(elem) { var tlist = getTransformList(elem); return transformListToTransform(tlist).matrix; }; - /** * Returns a 45 degree angle coordinate associated with the two given - * coordinates + * coordinates. * @function module:math.snapToAngle * @param {Integer} x1 - First coordinate's x value - * @param {Integer} x2 - Second coordinate's x value * @param {Integer} y1 - First coordinate's y value + * @param {Integer} x2 - Second coordinate's x value * @param {Integer} y2 - Second coordinate's y value * @returns {module:math.AngleCoord45} */ + var snapToAngle = function snapToAngle(x1, y1, x2, y2) { var snap = Math.PI / 4; // 45 degrees + var dx = x2 - x1; var dy = y2 - y1; var angle = Math.atan2(dy, dx); var dist = Math.sqrt(dx * dx + dy * dy); var snapangle = Math.round(angle / snap) * snap; - return { x: x1 + dist * Math.cos(snapangle), y: y1 + dist * Math.sin(snapangle), a: snapangle }; }; - /** - * Check if two rectangles (BBoxes objects) intersect each other + * Check if two rectangles (BBoxes objects) intersect each other. * @function module:math.rectsIntersect * @param {SVGRect} r1 - The first BBox-like object * @param {SVGRect} r2 - The second BBox-like object * @returns {boolean} True if rectangles intersect */ + var rectsIntersect = function rectsIntersect(r1, r2) { return r2.x < r1.x + r1.width && r2.x + r2.width > r1.x && r2.y < r1.y + r1.height && r2.y + r2.height > r1.y; }; - /* globals jQuery */ - var $$1 = jQuery; - var segData = { - 2: ['x', 'y'], // PATHSEG_MOVETO_ABS - 4: ['x', 'y'], // PATHSEG_LINETO_ABS - 6: ['x', 'y', 'x1', 'y1', 'x2', 'y2'], // PATHSEG_CURVETO_CUBIC_ABS - 8: ['x', 'y', 'x1', 'y1'], // PATHSEG_CURVETO_QUADRATIC_ABS - 10: ['x', 'y', 'r1', 'r2', 'angle', 'largeArcFlag', 'sweepFlag'], // PATHSEG_ARC_ABS - 12: ['x'], // PATHSEG_LINETO_HORIZONTAL_ABS - 14: ['y'], // PATHSEG_LINETO_VERTICAL_ABS - 16: ['x', 'y', 'x2', 'y2'], // PATHSEG_CURVETO_CUBIC_SMOOTH_ABS + 2: ['x', 'y'], + // PATHSEG_MOVETO_ABS + 4: ['x', 'y'], + // PATHSEG_LINETO_ABS + 6: ['x', 'y', 'x1', 'y1', 'x2', 'y2'], + // PATHSEG_CURVETO_CUBIC_ABS + 8: ['x', 'y', 'x1', 'y1'], + // PATHSEG_CURVETO_QUADRATIC_ABS + 10: ['x', 'y', 'r1', 'r2', 'angle', 'largeArcFlag', 'sweepFlag'], + // PATHSEG_ARC_ABS + 12: ['x'], + // PATHSEG_LINETO_HORIZONTAL_ABS + 14: ['y'], + // PATHSEG_LINETO_VERTICAL_ABS + 16: ['x', 'y', 'x2', 'y2'], + // PATHSEG_CURVETO_CUBIC_SMOOTH_ABS 18: ['x', 'y'] // PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS - }; + }; /** * @tutorial LocaleDocs * @typedef {module:locale.LocaleStrings|PlainObject} module:path.uiStrings @@ -4304,36 +4912,33 @@ * @param {module:path.uiStrings} strs * @returns {undefined} */ + var setUiStrings = function setUiStrings(strs) { Object.assign(uiStrings, strs.ui); }; - var pathFuncs = []; - - var linkControlPts = true; - - // Stores references to paths via IDs. + var linkControlPts = true; // Stores references to paths via IDs. // TODO: Make this cross-document happy. - var pathData = {}; + var pathData = {}; /** * @function module:path.setLinkControlPoints * @param {boolean} lcp * @returns {undefined} */ + var setLinkControlPoints = function setLinkControlPoints(lcp) { linkControlPts = lcp; }; - /** * @name module:path.path * @type {null|module:path.Path} * @memberof module:path */ - var path = null; + + var path = null; // eslint-disable-line import/no-mutable-exports var editorContext_ = null; - /** * @external MouseEvent */ @@ -4347,44 +4952,52 @@ * @property {module:path.SVGElementJSON[]} [children] - Data objects to be added recursively as children * @property {string} [namespace="http://www.w3.org/2000/svg"] - Indicate a (non-SVG) namespace */ + /** * @interface module:path.EditorContext * @property {module:select.SelectorManager} selectorManager * @property {module:svgcanvas.SvgCanvas} canvas */ + /** * @function module:path.EditorContext#call * @param {"selected"|"changed"} ev - String with the event name * @param {module:svgcanvas.SvgCanvas#event:selected|module:svgcanvas.SvgCanvas#event:changed} arg - Argument to pass through to the callback function. If the event is "changed", an array of `Element`s is passed; if "selected", a single-item array of `Element` is passed. * @returns {undefined} */ + /** * @function module:path.EditorContext#resetD * @param {SVGPathElement} p * @returns {undefined} */ + /** * Note: This doesn't round to an integer necessarily * @function module:path.EditorContext#round * @param {Float} val * @returns {Float} Rounded value to nearest value based on `currentZoom` */ + /** * @function module:path.EditorContext#clearSelection * @param {boolean} [noCall] - When `true`, does not call the "selected" handler * @returns {undefined} */ + /** * @function module:path.EditorContext#addToSelection * @param {Element[]} elemsToAdd - An array of DOM elements to add to the selection * @param {boolean} showGrips - Indicates whether the resize grips should be shown * @returns {undefined} */ + /** * @function module:path.EditorContext#addCommandToHistory * @param {Command} cmd * @returns {undefined} */ + /** * @function module:path.EditorContext#remapElement * @param {Element} selected - DOM element to be changed @@ -4392,41 +5005,50 @@ * @param {SVGMatrix} m - Matrix object to use for remapping coordinates * @returns {undefined} */ + /** * @function module:path.EditorContext#addSVGElementFromJson * @param {module:path.SVGElementJSON} data * @returns {Element} The new element */ + /** * @function module:path.EditorContext#getGridSnapping * @returns {boolean} */ + /** * @function module:path.EditorContext#getOpacity * @returns {Float} */ + /** * @function module:path.EditorContext#getSelectedElements * @returns {Element[]} the array with selected DOM elements */ + /** * @function module:path.EditorContext#getContainer * @returns {Element} */ + /** * @function module:path.EditorContext#setStarted * @param {boolean} s * @returns {undefined} */ + /** * @function module:path.EditorContext#getRubberBox * @returns {SVGRectElement} */ + /** * @function module:path.EditorContext#setRubberBox * @param {SVGRectElement} rb * @returns {SVGRectElement} Same as parameter passed in */ + /** * @function module:path.EditorContext#addPtsToSelection * @param {PlainObject} cfg @@ -4434,6 +5056,7 @@ * @param {SVGCircleElement[]} cfg.grips * @returns {undefined} */ + /** * @function module:path.EditorContext#endChanges * @param {PlainObject} cfg @@ -4441,44 +5064,53 @@ * @param {Element} cfg.elem * @returns {undefined} */ + /** * @function module:path.EditorContext#getCurrentZoom * @returns {Float} The current zoom level */ + /** * Returns the last created DOM element ID string * @function module:path.EditorContext#getId * @returns {string} */ + /** * Creates and returns a unique ID string for a DOM element * @function module:path.EditorContext#getNextId * @returns {string} */ + /** * Gets the desired element from a mouse event * @function module:path.EditorContext#getMouseTarget * @param {external:MouseEvent} evt - Event object from the mouse event * @returns {Element} DOM element we want */ + /** * @function module:path.EditorContext#getCurrentMode * @returns {string} */ + /** * @function module:path.EditorContext#setCurrentMode * @param {string} cm The mode * @returns {string} The same mode as passed in */ + /** * @function module:path.EditorContext#getDrawnPath * @returns {SVGPathElement|null} */ + /** * @function module:path.EditorContext#setDrawnPath * @param {SVGPathElement|null} dp * @returns {SVGPathElement|null} The same value as passed in */ + /** * @function module:path.EditorContext#getSVGRoot * @returns {SVGSVGElement} @@ -4489,9 +5121,9 @@ * @param {module:path.EditorContext} editorContext * @returns {undefined} */ - var init$1 = function init$$1(editorContext) { - editorContext_ = editorContext; + var init$1 = function init(editorContext) { + editorContext_ = editorContext; pathFuncs = [0, 'ClosePath']; var pathFuncsStrs = ['Moveto', 'Lineto', 'CurvetoCubic', 'CurvetoQuadratic', 'Arc', 'LinetoHorizontal', 'LinetoVertical', 'CurvetoCubicSmooth', 'CurvetoQuadraticSmooth']; $$1.each(pathFuncsStrs, function (i, s) { @@ -4499,7 +5131,6 @@ pathFuncs.push(s + 'Rel'); }); }; - /** * @function module:path.insertItemBefore * @param {Element} elem @@ -4507,6 +5138,7 @@ * @param {Integer} index * @returns {undefined} */ + var insertItemBefore = function insertItemBefore(elem, newseg, index) { // Support insertItemBefore on paths for FF2 var list = elem.pathSegList; @@ -4515,22 +5147,26 @@ list.insertItemBefore(newseg, index); return; } + var len = list.numberOfItems; var arr = []; + for (var i = 0; i < len; i++) { var curSeg = list.getItem(i); arr.push(curSeg); } + list.clear(); + for (var _i = 0; _i < len; _i++) { if (_i === index) { // index + 1 list.appendItem(newseg); } + list.appendItem(arr[_i]); } }; - /** * @function module:path.ptObjToArr * @todo See if this should just live in `replacePathSeg` @@ -4538,53 +5174,52 @@ * @param {SVGPathSegMovetoAbs|SVGPathSegLinetoAbs|SVGPathSegCurvetoCubicAbs|SVGPathSegCurvetoQuadraticAbs|SVGPathSegArcAbs|SVGPathSegLinetoHorizontalAbs|SVGPathSegLinetoVerticalAbs|SVGPathSegCurvetoCubicSmoothAbs|SVGPathSegCurvetoQuadraticSmoothAbs} segItem * @returns {ArgumentsArray} */ + var ptObjToArr = function ptObjToArr(type, segItem) { var props = segData[type]; return props.map(function (prop) { return segItem[prop]; }); }; - /** * @function module:path.getGripPt * @param {Segment} seg * @param {module:math.XYObject} altPt * @returns {module:math.XYObject} */ - var getGripPt = function getGripPt(seg, altPt) { - var path = seg.path; + var getGripPt = function getGripPt(seg, altPt) { + var pth = seg.path; var out = { x: altPt ? altPt.x : seg.item.x, y: altPt ? altPt.y : seg.item.y }; - if (path.matrix) { - var pt = transformPoint(out.x, out.y, path.matrix); + if (pth.matrix) { + var pt = transformPoint(out.x, out.y, pth.matrix); out = pt; } var currentZoom = editorContext_.getCurrentZoom(); out.x *= currentZoom; out.y *= currentZoom; - return out; }; - /** * @function module:path.getPointFromGrip * @param {module:math.XYObject} pt - * @param {module:path.Path} path + * @param {module:path.Path} pth * @returns {module:math.XYObject} */ - var getPointFromGrip = function getPointFromGrip(pt, path) { + + var getPointFromGrip = function getPointFromGrip(pt, pth) { var out = { x: pt.x, y: pt.y }; - if (path.matrix) { - pt = transformPoint(out.x, out.y, path.imatrix); + if (pth.matrix) { + pt = transformPoint(out.x, out.y, pth.imatrix); out.x = pt.x; out.y = pt.y; } @@ -4592,25 +5227,23 @@ var currentZoom = editorContext_.getCurrentZoom(); out.x /= currentZoom; out.y /= currentZoom; - return out; }; - /** * Requires prior call to `setUiStrings` if `xlink:title` - * to be set on the grip + * to be set on the grip. * @function module:path.addPointGrip * @param {Integer} index * @param {Integer} x * @param {Integer} y * @returns {SVGCircleElement} */ + var addPointGrip = function addPointGrip(index, x, y) { // create the container of all the point grips var pointGripContainer = getGripContainer(); + var pointGrip = getElem('pathpointgrip_' + index); // create it - var pointGrip = getElem('pathpointgrip_' + index); - // create it if (!pointGrip) { pointGrip = document.createElementNS(NS.SVG, 'circle'); var atts = { @@ -4623,13 +5256,14 @@ cursor: 'move', style: 'pointer-events:all' }; + if ('pathNodeTooltip' in uiStrings) { // May be empty if running path.js without svg-editor atts['xlink:title'] = uiStrings.pathNodeTooltip; } + assignAttributes(pointGrip, atts); pointGrip = pointGripContainer.appendChild(pointGrip); - var grip = $$1('#pathpointgrip_' + index); grip.dblclick(function () { if (path) { @@ -4637,6 +5271,7 @@ } }); } + if (x && y) { // set up the point grip element and display it assignAttributes(pointGrip, { @@ -4645,32 +5280,36 @@ display: 'inline' }); } + return pointGrip; }; - /** * @function module:path.getGripContainer * @returns {Element} */ + var getGripContainer = function getGripContainer() { var c = getElem('pathpointgrip_container'); + if (!c) { - var parent = getElem('selectorParentGroup'); - c = parent.appendChild(document.createElementNS(NS.SVG, 'g')); + var parentElement = getElem('selectorParentGroup'); + c = parentElement.appendChild(document.createElementNS(NS.SVG, 'g')); c.id = 'pathpointgrip_container'; } + return c; }; - /** * Requires prior call to `setUiStrings` if `xlink:title` - * to be set on the grip + * to be set on the grip. * @function module:path.addCtrlGrip * @param {string} id * @returns {SVGCircleElement} */ + var addCtrlGrip = function addCtrlGrip(id) { var pointGrip = getElem('ctrlpointgrip_' + id); + if (pointGrip) { return pointGrip; } @@ -4686,22 +5325,25 @@ cursor: 'move', style: 'pointer-events:all' }; + if ('pathCtrlPtTooltip' in uiStrings) { // May be empty if running path.js without svg-editor atts['xlink:title'] = uiStrings.pathCtrlPtTooltip; } + assignAttributes(pointGrip, atts); getGripContainer().append(pointGrip); return pointGrip; }; - /** * @function module:path.getCtrlLine * @param {string} id * @returns {SVGLineElement} */ + var getCtrlLine = function getCtrlLine(id) { var ctrlLine = getElem('ctrlLine_' + id); + if (ctrlLine) { return ctrlLine; } @@ -4716,16 +5358,15 @@ getGripContainer().append(ctrlLine); return ctrlLine; }; - /** * @function module:path.getPointGrip * @param {Segment} seg * @param {boolean} update * @returns {SVGCircleElement} */ + var getPointGrip = function getPointGrip(seg, update) { var index = seg.index; - var pointGrip = addPointGrip(index); if (update) { @@ -4739,12 +5380,12 @@ return pointGrip; }; - /** * @function module:path.getControlPoints * @param {Segment} seg * @returns {PlainObject.<string, SVGLineElement|SVGCircleElement>} */ + var getControlPoints = function getControlPoints(seg) { var item = seg.item, index = seg.index; @@ -4752,22 +5393,26 @@ if (!('x1' in item) || !('x2' in item)) { return null; } + var cpt = {}; - /* const pointGripContainer = */getGripContainer(); + /* const pointGripContainer = */ + + getGripContainer(); // Note that this is intentionally not seg.prev.item - // Note that this is intentionally not seg.prev.item var prev = path.segs[index - 1].item; - var segItems = [prev, item]; for (var i = 1; i < 3; i++) { var id = index + 'c' + i; - var ctrlLine = cpt['c' + i + '_line'] = getCtrlLine(id); - - var pt = getGripPt(seg, { x: item['x' + i], y: item['y' + i] }); - var gpt = getGripPt(seg, { x: segItems[i - 1].x, y: segItems[i - 1].y }); - + var pt = getGripPt(seg, { + x: item['x' + i], + y: item['y' + i] + }); + var gpt = getGripPt(seg, { + x: segItems[i - 1].x, + y: segItems[i - 1].y + }); assignAttributes(ctrlLine, { x1: pt.x, y1: pt.y, @@ -4775,12 +5420,9 @@ y2: gpt.y, display: 'inline' }); + cpt['c' + i + '_line'] = ctrlLine; // create it - cpt['c' + i + '_line'] = ctrlLine; - - // create it var pointGrip = cpt['c' + i] = addCtrlGrip(id); - assignAttributes(pointGrip, { cx: pt.x, cy: pt.y, @@ -4788,9 +5430,9 @@ }); cpt['c' + i] = pointGrip; } + return cpt; }; - /** * This replaces the segment at the given index. Type is given as number. * @function module:path.replacePathSeg @@ -4798,12 +5440,13 @@ * @param {Integer} index * @param {ArgumentsArray} pts * @param {SVGPathElement} elem + * @returns {undefined} */ + var replacePathSeg = function replacePathSeg(type, index, pts, elem) { var pth = elem || path.elem; - var func = 'createSVGPathSeg' + pathFuncs[type]; - var seg = pth[func].apply(pth, pts); + var seg = pth[func].apply(pth, _toConsumableArray(pts)); if (supportsPathReplaceItem()) { pth.pathSegList.replaceItem(seg, index); @@ -4811,11 +5454,14 @@ var segList = pth.pathSegList; var len = segList.numberOfItems; var arr = []; + for (var i = 0; i < len; i++) { var curSeg = segList.getItem(i); arr.push(curSeg); } + segList.clear(); + for (var _i2 = 0; _i2 < len; _i2++) { if (_i2 === index) { segList.appendItem(seg); @@ -4825,20 +5471,20 @@ } } }; - /** * @function module:path.getSegSelector * @param {Segment} seg * @param {boolean} update * @returns {SVGPathElement} */ + var getSegSelector = function getSegSelector(seg, update) { var index = seg.index; - var segLine = getElem('segline_' + index); + if (!segLine) { - var pointGripContainer = getGripContainer(); - // create segline + var pointGripContainer = getGripContainer(); // create segline + segLine = document.createElementNS(NS.SVG, 'path'); assignAttributes(segLine, { id: 'segline_' + index, @@ -4860,22 +5506,25 @@ return segLine; } - var pt = getGripPt(prev); - // Set start point - replacePathSeg(2, 0, [pt.x, pt.y], segLine); + var pt = getGripPt(prev); // Set start point + + replacePathSeg(2, 0, [pt.x, pt.y], segLine); + var pts = ptObjToArr(seg.type, seg.item); // , true); - var pts = ptObjToArr(seg.type, seg.item, true); for (var i = 0; i < pts.length; i += 2) { - var _pt = getGripPt(seg, { x: pts[i], y: pts[i + 1] }); - pts[i] = _pt.x; - pts[i + 1] = _pt.y; + var point = getGripPt(seg, { + x: pts[i], + y: pts[i + 1] + }); + pts[i] = point.x; + pts[i + 1] = point.y; } replacePathSeg(seg.type, 1, pts, segLine); } + return segLine; }; - /** * @typedef {PlainObject} Point * @property {Integer} x The x value @@ -4883,13 +5532,14 @@ */ /** - * Takes three points and creates a smoother line based on them + * Takes three points and creates a smoother line based on them. * @function module:path.smoothControlPoints * @param {Point} ct1 - Object with x and y values (first control point) * @param {Point} ct2 - Object with x and y values (second control point) * @param {Point} pt - Object with x and y values (third point) * @returns {Point[]} Array of two "smoothed" point objects */ + var smoothControlPoints = function smoothControlPoints(ct1, ct2, pt) { // each point must not be the origin var x1 = ct1.x - pt.x, @@ -4904,139 +5554,138 @@ nct2 = editorContext_.getSVGRoot().createSVGPoint(); var anglea = Math.atan2(y1, x1), angleb = Math.atan2(y2, x2); + if (anglea < 0) { anglea += 2 * Math.PI; } + if (angleb < 0) { angleb += 2 * Math.PI; } var angleBetween = Math.abs(anglea - angleb), angleDiff = Math.abs(Math.PI - angleBetween) / 2; + var newAnglea, newAngleb; - var newAnglea = void 0, - newAngleb = void 0; if (anglea - angleb > 0) { newAnglea = angleBetween < Math.PI ? anglea + angleDiff : anglea - angleDiff; newAngleb = angleBetween < Math.PI ? angleb - angleDiff : angleb + angleDiff; } else { newAnglea = angleBetween < Math.PI ? anglea - angleDiff : anglea + angleDiff; newAngleb = angleBetween < Math.PI ? angleb + angleDiff : angleb - angleDiff; - } + } // rotate the points + - // rotate the points nct1.x = r1 * Math.cos(newAnglea) + pt.x; nct1.y = r1 * Math.sin(newAnglea) + pt.y; nct2.x = r2 * Math.cos(newAngleb) + pt.x; nct2.y = r2 * Math.sin(newAngleb) + pt.y; - return [nct1, nct2]; } + return undefined; }; - /** * */ - var Segment = function () { + + var Segment = + /*#__PURE__*/ + function () { /** * @param {Integer} index * @param {SVGPathSeg} item * @todo Is `item` be more constrained here? */ function Segment(index, item) { - classCallCheck(this, Segment); + _classCallCheck(this, Segment); this.selected = false; this.index = index; this.item = item; this.type = item.pathSegType; - this.ctrlpts = []; this.ptgrip = null; this.segsel = null; } - /** * @param {boolean} y * @returns {undefined} */ - createClass(Segment, [{ - key: 'showCtrlPts', + _createClass(Segment, [{ + key: "showCtrlPts", value: function showCtrlPts(y) { for (var i in this.ctrlpts) { - if (this.ctrlpts.hasOwnProperty(i)) { + if ({}.hasOwnProperty.call(this.ctrlpts, i)) { this.ctrlpts[i].setAttribute('display', y ? 'inline' : 'none'); } } } - /** * @param {boolean} y * @returns {undefined} */ }, { - key: 'selectCtrls', + key: "selectCtrls", value: function selectCtrls(y) { $$1('#ctrlpointgrip_' + this.index + 'c1, #ctrlpointgrip_' + this.index + 'c2').attr('fill', y ? '#0FF' : '#EEE'); } - /** * @param {boolean} y * @returns {undefined} */ }, { - key: 'show', + key: "show", value: function show(y) { if (this.ptgrip) { this.ptgrip.setAttribute('display', y ? 'inline' : 'none'); - this.segsel.setAttribute('display', y ? 'inline' : 'none'); - // Show/hide all control points if available + this.segsel.setAttribute('display', y ? 'inline' : 'none'); // Show/hide all control points if available + this.showCtrlPts(y); } } - /** * @param {boolean} y * @returns {undefined} */ }, { - key: 'select', + key: "select", value: function select(y) { if (this.ptgrip) { this.ptgrip.setAttribute('stroke', y ? '#0FF' : '#00F'); this.segsel.setAttribute('display', y ? 'inline' : 'none'); + if (this.ctrlpts) { this.selectCtrls(y); } + this.selected = y; } } - /** * @returns {undefined} */ }, { - key: 'addGrip', + key: "addGrip", value: function addGrip() { this.ptgrip = getPointGrip(this, true); - this.ctrlpts = getControlPoints(this, true); + this.ctrlpts = getControlPoints(this); // , true); + this.segsel = getSegSelector(this, true); } - /** * @param {boolean} full * @returns {undefined} */ }, { - key: 'update', + key: "update", value: function update(full) { if (this.ptgrip) { var pt = getGripPt(this); @@ -5044,7 +5693,6 @@ cx: pt.x, cy: pt.y }); - getSegSelector(this, true); if (this.ctrlpts) { @@ -5052,12 +5700,12 @@ this.item = path.elem.pathSegList.getItem(this.index); this.type = this.item.pathSegType; } + getControlPoints(this); - } - // this.segsel.setAttribute('display', y ? 'inline' : 'none'); + } // this.segsel.setAttribute('display', y ? 'inline' : 'none'); + } } - /** * @param {Integer} dx * @param {Integer} dy @@ -5065,13 +5713,10 @@ */ }, { - key: 'move', + key: "move", value: function move(dx, dy) { var item = this.item; - - var curPts = this.ctrlpts ? [item.x += dx, item.y += dy, item.x1, item.y1, item.x2 += dx, item.y2 += dy] : [item.x += dx, item.y += dy]; - replacePathSeg(this.type, this.index, curPts); if (this.next && this.next.ctrlpts) { @@ -5083,58 +5728,55 @@ if (this.mate) { // The last point of a closed subpath has a 'mate', // which is the 'M' segment of the subpath - var _item = this.mate.item; - - var pts = [_item.x += dx, _item.y += dy]; - replacePathSeg(this.mate.type, this.mate.index, pts); - // Has no grip, so does not need 'updating'? + var itm = this.mate.item; + var pts = [itm.x += dx, itm.y += dy]; + replacePathSeg(this.mate.type, this.mate.index, pts); // Has no grip, so does not need 'updating'? } this.update(true); + if (this.next) { this.next.update(true); } } - /** * @param {Integer} num * @returns {undefined} */ }, { - key: 'setLinked', + key: "setLinked", value: function setLinked(num) { - var seg = void 0, - anum = void 0, - pt = void 0; + var seg, anum, pt; + if (num === 2) { anum = 1; seg = this.next; + if (!seg) { return; } + pt = this.item; } else { anum = 2; seg = this.prev; + if (!seg) { return; } + pt = seg.item; } var _seg = seg, item = _seg.item; - item['x' + anum] = pt.x + (pt.x - this.item['x' + num]); item['y' + anum] = pt.y + (pt.y - this.item['y' + num]); - var pts = [item.x, item.y, item.x1, item.y1, item.x2, item.y2]; - replacePathSeg(seg.type, seg.index, pts); seg.update(true); } - /** * @param {Integer} num * @param {Integer} dx @@ -5143,26 +5785,23 @@ */ }, { - key: 'moveCtrl', + key: "moveCtrl", value: function moveCtrl(num, dx, dy) { var item = this.item; - item['x' + num] += dx; item['y' + num] += dy; - var pts = [item.x, item.y, item.x1, item.y1, item.x2, item.y2]; - replacePathSeg(this.type, this.index, pts); this.update(true); } - /** * @param {Integer} newType Possible values set during {@link module:path.init} * @param {ArgumentsArray} pts + * @returns {undefined} */ }, { - key: 'setType', + key: "setType", value: function setType(newType, pts) { replacePathSeg(newType, this.index, pts); this.type = newType; @@ -5172,19 +5811,22 @@ this.update(true); } }]); + return Segment; }(); - /** * */ - var Path = function () { + + var Path = + /*#__PURE__*/ + function () { /** - * @param {SVGPathElement} + * @param {SVGPathElement} elem * @throws {Error} If constructed without a path element */ function Path(elem) { - classCallCheck(this, Path); + _classCallCheck(this, Path); if (!elem || elem.tagName !== 'path') { throw new Error('svgedit.path.Path constructed without a <path> element'); @@ -5193,34 +5835,30 @@ this.elem = elem; this.segs = []; this.selected_pts = []; - path = this; + path = this; // eslint-disable-line consistent-this this.init(); } - /** - * Reset path data + * Reset path data. * @returns {module:path.Path} */ - createClass(Path, [{ - key: 'init', - value: function init$$1() { + _createClass(Path, [{ + key: "init", + value: function init() { // Hide all grips, etc - // fixed, needed to work on all found elements, not just first $$1(getGripContainer()).find('*').each(function () { $$1(this).attr('display', 'none'); }); - var segList = this.elem.pathSegList; var len = segList.numberOfItems; this.segs = []; this.selected_pts = []; - this.first_seg = null; + this.first_seg = null; // Set up segs array - // Set up segs array for (var i = 0; i < len; i++) { var item = segList.getItem(i); var segment = new Segment(i, item); @@ -5229,13 +5867,13 @@ } var segs = this.segs; - - var startI = null; + for (var _i3 = 0; _i3 < len; _i3++) { var seg = segs[_i3]; var nextSeg = _i3 + 1 >= len ? null : segs[_i3 + 1]; var prevSeg = _i3 - 1 < 0 ? null : segs[_i3 - 1]; + if (seg.type === 2) { if (prevSeg && prevSeg.type !== 1) { // New sub-path, last one is open, @@ -5244,19 +5882,20 @@ startSeg.next = segs[startI + 1]; startSeg.next.prev = startSeg; startSeg.addGrip(); - } - // Remember that this is a starter seg + } // Remember that this is a starter seg + + startI = _i3; } else if (nextSeg && nextSeg.type === 1) { // This is the last real segment of a closed sub-path // Next is first seg after "M" - seg.next = segs[startI + 1]; + seg.next = segs[startI + 1]; // First seg after "M"'s prev is this - // First seg after "M"'s prev is this seg.next.prev = seg; seg.mate = segs[startI]; seg.addGrip(); - if (this.first_seg == null) { + + if (isNullish(this.first_seg)) { this.first_seg = seg; } } else if (!nextSeg) { @@ -5266,7 +5905,9 @@ var _startSeg = segs[startI]; _startSeg.next = segs[startI + 1]; _startSeg.next.prev = _startSeg; + _startSeg.addGrip(); + seg.addGrip(); if (!this.first_seg) { @@ -5276,60 +5917,60 @@ } } else if (seg.type !== 1) { // Regular segment, so add grip and its "next" - seg.addGrip(); + seg.addGrip(); // Don't set its "next" if it's an "M" - // Don't set its "next" if it's an "M" if (nextSeg && nextSeg.type !== 2) { seg.next = nextSeg; seg.next.prev = seg; } } } + return this; } - /** * @callback module:path.PathEachSegCallback * @this module:path.Segment * @param {Integer} i The index of the seg being iterated - * @returns {boolean} Will stop execution of `eachSeg` if returns `false` + * @returns {boolean|undefined} Will stop execution of `eachSeg` if returns `false` */ + /** * @param {module:path.PathEachSegCallback} fn * @returns {undefined} */ }, { - key: 'eachSeg', + key: "eachSeg", value: function eachSeg(fn) { var len = this.segs.length; + for (var i = 0; i < len; i++) { var ret = fn.call(this.segs[i], i); + if (ret === false) { break; } } } - /** * @param {Integer} index * @returns {undefined} */ }, { - key: 'addSeg', + key: "addSeg", value: function addSeg(index) { // Adds a new segment var seg = this.segs[index]; + if (!seg.prev) { return; } var prev = seg.prev; + var newseg, newX, newY; - var newseg = void 0, - newX = void 0, - newY = void 0; switch (seg.item.pathSegType) { case 4: { @@ -5337,7 +5978,9 @@ newY = (seg.item.y + prev.item.y) / 2; newseg = this.elem.createSVGPathSegLinetoAbs(newX, newY); break; - }case 6: + } + + case 6: { // make it a curved segment to preserve the shape (WRS) // https://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm#Geometric_interpretation @@ -5362,91 +6005,59 @@ insertItemBefore(this.elem, newseg, index); } - /** * @param {Integer} index * @returns {undefined} */ }, { - key: 'deleteSeg', + key: "deleteSeg", value: function deleteSeg(index) { var seg = this.segs[index]; var list = this.elem.pathSegList; - seg.show(false); var next = seg.next; if (seg.mate) { // Make the next point be the "M" point var pt = [next.item.x, next.item.y]; - replacePathSeg(2, next.index, pt); + replacePathSeg(2, next.index, pt); // Reposition last node - // Reposition last node replacePathSeg(4, seg.index, pt); - list.removeItem(seg.mate.index); } else if (!seg.prev) { // First node of open path, make next point the M // const {item} = seg; - var _pt2 = [next.item.x, next.item.y]; - replacePathSeg(2, seg.next.index, _pt2); + var _pt = [next.item.x, next.item.y]; + replacePathSeg(2, seg.next.index, _pt); list.removeItem(index); } else { list.removeItem(index); } } - - /** - * @param {Integer} index - * @returns {boolean} - */ - - }, { - key: 'subpathIsClosed', - value: function subpathIsClosed(index) { - var closed = false; - // Check if subpath is already open - path.eachSeg(function (i) { - if (i <= index) { - return true; - } - if (this.type === 2) { - // Found M first, so open - return false; - } - if (this.type === 1) { - // Found Z first, so closed - closed = true; - return false; - } - }); - - return closed; - } - /** * @param {Integer} index * @returns {undefined} */ }, { - key: 'removePtFromSelection', + key: "removePtFromSelection", value: function removePtFromSelection(index) { var pos = this.selected_pts.indexOf(index); + if (pos === -1) { return; } + this.segs[index].select(false); this.selected_pts.splice(pos, 1); } - /** * @returns {undefined} */ }, { - key: 'clearSelection', + key: "clearSelection", value: function clearSelection() { this.eachSeg(function () { // 'this' is the segment here @@ -5454,53 +6065,52 @@ }); this.selected_pts = []; } - /** * @returns {undefined} */ }, { - key: 'storeD', + key: "storeD", value: function storeD() { this.last_d = this.elem.getAttribute('d'); } - /** * @param {Integer} y * @returns {undefined} */ }, { - key: 'show', + key: "show", value: function show(y) { // Shows this path's segment grips this.eachSeg(function () { // 'this' is the segment here this.show(y); }); + if (y) { this.selectPt(this.first_seg.index); } + return this; } - /** - * Move selected points + * Move selected points. * @param {Integer} dx * @param {Integer} dy * @returns {undefined} */ }, { - key: 'movePts', + key: "movePts", value: function movePts(dx, dy) { var i = this.selected_pts.length; + while (i--) { var seg = this.segs[this.selected_pts[i]]; seg.move(dx, dy); } } - /** * @param {Integer} dx * @param {Integer} dy @@ -5508,30 +6118,30 @@ */ }, { - key: 'moveCtrl', + key: "moveCtrl", value: function moveCtrl(dx, dy) { var seg = this.segs[this.selected_pts[0]]; seg.moveCtrl(this.dragctrl, dx, dy); + if (linkControlPts) { seg.setLinked(this.dragctrl); } } - /** * @param {?Integer} newType See {@link https://www.w3.org/TR/SVG/single-page.html#paths-InterfaceSVGPathSeg} * @returns {undefined} */ }, { - key: 'setSegType', + key: "setSegType", value: function setSegType(newType) { this.storeD(); var i = this.selected_pts.length; - var text = void 0; - while (i--) { - var selPt = this.selected_pts[i]; + var text; + + while (i--) { + var selPt = this.selected_pts[i]; // Selected seg - // Selected seg var cur = this.segs[selPt]; var prev = cur.prev; @@ -5541,21 +6151,19 @@ if (!newType) { // double-click, so just toggle - text = 'Toggle Path Segment Type'; + text = 'Toggle Path Segment Type'; // Toggle segment to curve/straight line - // Toggle segment to curve/straight line var oldType = cur.type; - newType = oldType === 6 ? 4 : 6; } newType = Number(newType); - var curX = cur.item.x; var curY = cur.item.y; var prevX = prev.item.x; var prevY = prev.item.y; var points = void 0; + switch (newType) { case 6: { @@ -5564,8 +6172,8 @@ points = [curX, curY, old.x1, old.y1, old.x2, old.y2]; } else { var diffX = curX - prevX; - var diffY = curY - prevY; - // get control points from straight line segment + var diffY = curY - prevY; // get control points from straight line segment + /* const ct1x = (prevX + (diffY/2)); const ct1y = (prevY - (diffX/2)); @@ -5573,18 +6181,21 @@ const ct2y = (curY - (diffX/2)); */ // create control points on the line to preserve the shape (WRS) + var ct1x = prevX + diffX / 3; var ct1y = prevY + diffY / 3; var ct2x = curX - diffX / 3; var ct2y = curY - diffY / 3; points = [curX, curY, ct1x, ct1y, ct2x, ct2y]; } - break; - }case 4: - { - points = [curX, curY]; - // Store original prevve segment nums + break; + } + + case 4: + { + points = [curX, curY]; // Store original prevve segment nums + cur.olditem = cur.item; break; } @@ -5592,9 +6203,9 @@ cur.setType(newType, points); } + path.endChanges(text); } - /** * @param {Integer} pt * @param {Integer} ctrlNum @@ -5602,10 +6213,11 @@ */ }, { - key: 'selectPt', + key: "selectPt", value: function selectPt(pt, ctrlNum) { this.clearSelection(); - if (pt == null) { + + if (isNullish(pt)) { this.eachSeg(function (i) { // 'this' is the segment here. if (this.prev) { @@ -5613,7 +6225,9 @@ } }); } + this.addPtsToSelection(pt); + if (ctrlNum) { this.dragctrl = ctrlNum; @@ -5622,14 +6236,13 @@ } } } - /** - * Update position of all points + * Update position of all points. * @returns {Path} */ }, { - key: 'update', + key: "update", value: function update() { var elem = this.elem; @@ -5645,119 +6258,152 @@ this.item = elem.pathSegList.getItem(i); this.update(); }); - return this; } - /** * @param {string} text * @returns {undefined} */ }, { - key: 'endChanges', + key: "endChanges", value: function endChanges(text) { if (isWebkit()) { editorContext_.resetD(this.elem); } - var cmd = new ChangeElementCommand(this.elem, { d: this.last_d }, text); - editorContext_.endChanges({ cmd: cmd, elem: this.elem }); - } + var cmd = new ChangeElementCommand(this.elem, { + d: this.last_d + }, text); + editorContext_.endChanges({ + cmd: cmd, + elem: this.elem + }); + } /** * @param {Integer|Integer[]} indexes * @returns {undefined} */ }, { - key: 'addPtsToSelection', + key: "addPtsToSelection", value: function addPtsToSelection(indexes) { if (!Array.isArray(indexes)) { indexes = [indexes]; } + for (var _i4 = 0; _i4 < indexes.length; _i4++) { var index = indexes[_i4]; var seg = this.segs[index]; + if (seg.ptgrip) { if (!this.selected_pts.includes(index) && index >= 0) { this.selected_pts.push(index); } } } + this.selected_pts.sort(); var i = this.selected_pts.length; var grips = []; - grips.length = i; - // Loop through points to be selected and highlight each + grips.length = i; // Loop through points to be selected and highlight each + while (i--) { var pt = this.selected_pts[i]; var _seg2 = this.segs[pt]; + _seg2.select(true); + grips[i] = _seg2.ptgrip; } - var closedSubpath = this.subpathIsClosed(this.selected_pts[0]); - editorContext_.addPtsToSelection({ grips: grips, closedSubpath: closedSubpath }); + var closedSubpath = Path.subpathIsClosed(this.selected_pts[0]); + editorContext_.addPtsToSelection({ + grips: grips, + closedSubpath: closedSubpath + }); } }]); + return Path; }(); + /** + * @param {Integer} index + * @returns {boolean} + */ + Path.subpathIsClosed = function (index) { + var clsd = false; // Check if subpath is already open + + path.eachSeg(function (i) { + if (i <= index) { + return true; + } + + if (this.type === 2) { + // Found M first, so open + return false; + } + + if (this.type === 1) { + // Found Z first, so closed + clsd = true; + return false; + } + + return true; + }); + return clsd; + }; /** * @function module:path.getPath_ * @param {SVGPathElement} elem * @returns {module:path.Path} */ + + var getPath_ = function getPath_(elem) { var p = pathData[elem.id]; + if (!p) { p = pathData[elem.id] = new Path(elem); } + return p; }; - /** * @function module:path.removePath_ * @param {string} id * @returns {undefined} */ + var removePath_ = function removePath_(id) { if (id in pathData) { delete pathData[id]; } }; - - var newcx = void 0, - newcy = void 0, - oldcx = void 0, - oldcy = void 0, - angle = void 0; + var newcx, newcy, oldcx, oldcy, angle; var getRotVals = function getRotVals(x, y) { var dx = x - oldcx; - var dy = y - oldcy; + var dy = y - oldcy; // rotate the point around the old center - // rotate the point around the old center var r = Math.sqrt(dx * dx + dy * dy); var theta = Math.atan2(dy, dx) + angle; dx = r * Math.cos(theta) + oldcx; - dy = r * Math.sin(theta) + oldcy; - - // dx,dy should now hold the actual coordinates of each + dy = r * Math.sin(theta) + oldcy; // dx,dy should now hold the actual coordinates of each // point after being rotated - // now we want to rotate them around the new center in the reverse direction + dx -= newcx; dy -= newcy; - r = Math.sqrt(dx * dx + dy * dy); theta = Math.atan2(dy, dx) - angle; - - return { x: r * Math.cos(theta) + newcx, - y: r * Math.sin(theta) + newcy }; - }; - - // If the path was rotated, we must now pay the piper: + return { + x: r * Math.cos(theta) + newcx, + y: r * Math.sin(theta) + newcy + }; + }; // If the path was rotated, we must now pay the piper: // Every path point must be rotated into the rotated coordinate system of // its old center, then determine the new center, then rotate it back // This is because we want the path to remember its rotation @@ -5768,113 +6414,116 @@ * be optimized or even taken care of by `recalculateDimensions` * @returns {undefined} */ + + var recalcRotatedPath = function recalcRotatedPath() { var currentPath = path.elem; angle = getRotationAngle(currentPath, true); + if (!angle) { return; - } - // selectedBBoxes[0] = path.oldbbox; + } // selectedBBoxes[0] = path.oldbbox; + + var oldbox = path.oldbbox; // selectedBBoxes[0], + oldcx = oldbox.x + oldbox.width / 2; oldcy = oldbox.y + oldbox.height / 2; var box = getBBox(currentPath); newcx = box.x + box.width / 2; - newcy = box.y + box.height / 2; + newcy = box.y + box.height / 2; // un-rotate the new center to the proper position - // un-rotate the new center to the proper position var dx = newcx - oldcx, dy = newcy - oldcy, r = Math.sqrt(dx * dx + dy * dy), theta = Math.atan2(dy, dx) + angle; - newcx = r * Math.cos(theta) + oldcx; newcy = r * Math.sin(theta) + oldcy; - var list = currentPath.pathSegList; - var i = list.numberOfItems; + while (i) { i -= 1; var seg = list.getItem(i), type = seg.pathSegType; + if (type === 1) { continue; } var rvals = getRotVals(seg.x, seg.y), points = [rvals.x, rvals.y]; - if (seg.x1 != null && seg.x2 != null) { + + if (!isNullish(seg.x1) && !isNullish(seg.x2)) { var cVals1 = getRotVals(seg.x1, seg.y1); var cVals2 = getRotVals(seg.x2, seg.y2); points.splice(points.length, 0, cVals1.x, cVals1.y, cVals2.x, cVals2.y); } + replacePathSeg(type, i, points); } // loop for each point - box = getBBox(currentPath); - // selectedBBoxes[0].x = box.x; selectedBBoxes[0].y = box.y; - // selectedBBoxes[0].width = box.width; selectedBBoxes[0].height = box.height; + /* box = */ + + getBBox(currentPath); // selectedBBoxes[0].x = box.x; selectedBBoxes[0].y = box.y; + // selectedBBoxes[0].width = box.width; selectedBBoxes[0].height = box.height; // now we must set the new transform to be rotated around the new center + var Rnc = editorContext_.getSVGRoot().createSVGTransform(), tlist = getTransformList(currentPath); Rnc.setRotate(angle * 180.0 / Math.PI, newcx, newcy); tlist.replaceItem(Rnc, 0); - }; - - // ==================================== + }; // ==================================== // Public API starts here /** * @function module:path.clearData * @returns {undefined} */ + var clearData = function clearData() { pathData = {}; - }; + }; // Making public for mocking - // Making public for mocking /** * @function module:path.reorientGrads * @param {Element} elem * @param {SVGMatrix} m * @returns {undefined} */ + var reorientGrads = function reorientGrads(elem, m) { var bb = getBBox(elem); + for (var i = 0; i < 2; i++) { var type = i === 0 ? 'fill' : 'stroke'; var attrVal = elem.getAttribute(type); + if (attrVal && attrVal.startsWith('url(')) { var grad = getRefElem(attrVal); + if (grad.tagName === 'linearGradient') { var x1 = grad.getAttribute('x1') || 0; var y1 = grad.getAttribute('y1') || 0; var x2 = grad.getAttribute('x2') || 1; - var y2 = grad.getAttribute('y2') || 0; + var y2 = grad.getAttribute('y2') || 0; // Convert to USOU points - // Convert to USOU points x1 = bb.width * x1 + bb.x; y1 = bb.height * y1 + bb.y; x2 = bb.width * x2 + bb.x; - y2 = bb.height * y2 + bb.y; + y2 = bb.height * y2 + bb.y; // Transform those points - // Transform those points var pt1 = transformPoint(x1, y1, m); - var pt2 = transformPoint(x2, y2, m); + var pt2 = transformPoint(x2, y2, m); // Convert back to BB points - // Convert back to BB points var gCoords = {}; - gCoords.x1 = (pt1.x - bb.x) / bb.width; gCoords.y1 = (pt1.y - bb.y) / bb.height; gCoords.x2 = (pt2.x - bb.x) / bb.width; gCoords.y2 = (pt2.y - bb.y) / bb.height; - var newgrad = grad.cloneNode(true); $$1(newgrad).attr(gCoords); - newgrad.id = editorContext_.getNextId(); findDefs().append(newgrad); elem.setAttribute(type, 'url(#' + newgrad.id + ')'); @@ -5882,40 +6531,39 @@ } } }; - /** * This is how we map paths to our preferred relative segment types * @name module:path.pathMap * @type {GenericArray} */ - var pathMap = [0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a', 'H', 'h', 'V', 'v', 'S', 's', 'T', 't']; + var pathMap = [0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a', 'H', 'h', 'V', 'v', 'S', 's', 'T', 't']; /** - * Convert a path to one with only absolute or relative values + * Convert a path to one with only absolute or relative values. * @todo move to pathActions.js * @function module:path.convertPath - * @param {SVGPathElement} path - the path to convert + * @param {SVGPathElement} pth - the path to convert * @param {boolean} toRel - true of convert to relative * @returns {string} */ - var convertPath = function convertPath(path, toRel) { - var segList = path.pathSegList; - var len = segList.numberOfItems; + + var convertPath = function convertPath(pth, toRel) { + var pathSegList = pth.pathSegList; + var len = pathSegList.numberOfItems; var curx = 0, cury = 0; var d = ''; var lastM = null; for (var i = 0; i < len; ++i) { - var seg = segList.getItem(i); - // if these properties are not in the segment, set them to zero + var seg = pathSegList.getItem(i); // if these properties are not in the segment, set them to zero + var x = seg.x || 0, y = seg.y || 0, x1 = seg.x1 || 0, y1 = seg.y1 || 0, x2 = seg.x2 || 0, y2 = seg.y2 || 0; - var type = seg.pathSegType; var letter = pathMap[type]['to' + (toRel ? 'Lower' : 'Upper') + 'Case'](); @@ -5923,15 +6571,19 @@ case 1: // z,Z closepath (Z/z) d += 'z'; + if (lastM && !toRel) { curx = lastM[0]; cury = lastM[1]; } + break; + case 12: // absolute horizontal line (H) x -= curx; // Fallthrough + case 13: // relative horizontal line (h) if (toRel) { @@ -5941,14 +6593,17 @@ x += curx; curx = x; letter = 'L'; - } - // Convert to "line" for easier editing + } // Convert to "line" for easier editing + + d += pathDSegment(letter, [[x, cury]]); break; + case 14: // absolute vertical line (V) y -= cury; // Fallthrough + case 15: // relative vertical line (v) if (toRel) { @@ -5958,19 +6613,26 @@ y += cury; cury = y; letter = 'L'; - } - // Convert to "line" for easier editing + } // Convert to "line" for easier editing + + d += pathDSegment(letter, [[curx, y]]); break; + case 2: // absolute move (M) + case 4: // absolute line (L) + case 18: // absolute smooth quad (T) x -= curx; y -= cury; // Fallthrough + case 5: // relative line (l) + case 3: // relative move (m) + case 19: // relative smooth quad (t) if (toRel) { @@ -5982,53 +6644,74 @@ curx = x; cury = y; } + if (type === 2 || type === 3) { lastM = [curx, cury]; } d += pathDSegment(letter, [[x, y]]); break; + case 6: // absolute cubic (C) - x -= curx;x1 -= curx;x2 -= curx; - y -= cury;y1 -= cury;y2 -= cury; + x -= curx; + x1 -= curx; + x2 -= curx; + y -= cury; + y1 -= cury; + y2 -= cury; // Fallthrough + case 7: // relative cubic (c) if (toRel) { curx += x; cury += y; } else { - x += curx;x1 += curx;x2 += curx; - y += cury;y1 += cury;y2 += cury; + x += curx; + x1 += curx; + x2 += curx; + y += cury; + y1 += cury; + y2 += cury; curx = x; cury = y; } + d += pathDSegment(letter, [[x1, y1], [x2, y2], [x, y]]); break; + case 8: // absolute quad (Q) - x -= curx;x1 -= curx; - y -= cury;y1 -= cury; + x -= curx; + x1 -= curx; + y -= cury; + y1 -= cury; // Fallthrough + case 9: // relative quad (q) if (toRel) { curx += x; cury += y; } else { - x += curx;x1 += curx; - y += cury;y1 += cury; + x += curx; + x1 += curx; + y += cury; + y1 += cury; curx = x; cury = y; } + d += pathDSegment(letter, [[x1, y1], [x, y]]); break; + case 10: // absolute elliptical arc (A) x -= curx; y -= cury; // Fallthrough + case 11: // relative elliptical arc (a) if (toRel) { @@ -6040,84 +6723,97 @@ curx = x; cury = y; } + d += pathDSegment(letter, [[seg.r1, seg.r2]], [seg.angle, seg.largeArcFlag ? 1 : 0, seg.sweepFlag ? 1 : 0], [x, y]); break; + case 16: // absolute smooth cubic (S) - x -= curx;x2 -= curx; - y -= cury;y2 -= cury; + x -= curx; + x2 -= curx; + y -= cury; + y2 -= cury; // Fallthrough + case 17: // relative smooth cubic (s) if (toRel) { curx += x; cury += y; } else { - x += curx;x2 += curx; - y += cury;y2 += cury; + x += curx; + x2 += curx; + y += cury; + y2 += cury; curx = x; cury = y; } + d += pathDSegment(letter, [[x2, y2], [x, y]]); break; } // switch on path segment type + } // for each segment + + return d; }; - /** - * TODO: refactor callers in convertPath to use getPathDFromSegments instead of this function. - * Legacy code refactored from svgcanvas.pathActions.convertPath + * TODO: refactor callers in `convertPath` to use `getPathDFromSegments` instead of this function. + * Legacy code refactored from `svgcanvas.pathActions.convertPath`. * @param {string} letter - path segment command (letter in potentially either case from {@link module:path.pathMap}; see [SVGPathSeg#pathSegTypeAsLetter]{@link https://www.w3.org/TR/SVG/single-page.html#paths-__svg__SVGPathSeg__pathSegTypeAsLetter}) - * @param {Integer[][]} points - x,y points - * @param {Integer[][]} [morePoints] - x,y points + * @param {GenericArray<GenericArray<Integer>>} points - x,y points + * @param {GenericArray<GenericArray<Integer>>} [morePoints] - x,y points * @param {Integer[]} [lastPoint] - x,y point * @returns {string} */ + function pathDSegment(letter, points, morePoints, lastPoint) { $$1.each(points, function (i, pnt) { points[i] = shortFloat(pnt); }); var segment = letter + points.join(' '); + if (morePoints) { segment += ' ' + morePoints.join(' '); } + if (lastPoint) { segment += ' ' + shortFloat(lastPoint); } + return segment; } - /** * Group: Path edit functions * Functions relating to editing path elements * @namespace {PlainObject} pathActions * @memberof module:path */ + + var pathActions = function () { var subpath = false; - var newPoint = void 0, - firstCtrl = void 0; - + var newPoint, firstCtrl; var currentPath = null; - var hasMoved = false; - // No `editorContext_` yet but should be ok as is `null` by default + var hasMoved = false; // No `editorContext_` yet but should be ok as is `null` by default // editorContext_.setDrawnPath(null); /** * This function converts a polyline (created by the fh_path tool) into * a path element and coverts every three line segments into a single bezier - * curve in an attempt to smooth out the free-hand + * curve in an attempt to smooth out the free-hand. * @function smoothPolylineIntoPath * @param {Element} element * @returns {Element} */ + var smoothPolylineIntoPath = function smoothPolylineIntoPath(element) { - var i = void 0; + var i; var _element = element, points = _element.points; - var N = points.numberOfItems; + if (N >= 4) { // loop through every 3 points and convert to a cubic bezier curve segment // @@ -6136,15 +6832,16 @@ prevCtlPt = null; var d = []; d.push(['M', curpos.x, ',', curpos.y, ' C'].join('')); + for (i = 1; i <= N - 4; i += 3) { var ct1 = points.getItem(i); var ct2 = points.getItem(i + 1); - var end = points.getItem(i + 2); - - // if the previous segment had a control point, we want to smooth out + var end = points.getItem(i + 2); // if the previous segment had a control point, we want to smooth out // the control points on both sides + if (prevCtlPt) { var newpts = smoothControlPoints(prevCtlPt, ct1, curpos); + if (newpts && newpts.length === 2) { var prevArr = d[d.length - 1].split(','); prevArr[2] = newpts[0].x; @@ -6155,20 +6852,21 @@ } d.push([ct1.x, ct1.y, ct2.x, ct2.y, end.x, end.y].join(',')); - curpos = end; prevCtlPt = ct2; - } - // handle remaining line segments + } // handle remaining line segments + + d.push('L'); + while (i < N) { var pt = points.getItem(i); d.push([pt.x, pt.y].join(',')); i++; } - d = d.join(' '); - // create new path element + d = d.join(' '); // create new path element + element = editorContext_.addSVGElementFromJson({ element: 'path', curStyles: true, @@ -6177,24 +6875,28 @@ d: d, fill: 'none' } - }); - // No need to call "changed", as this is already done under mouseUp + }); // No need to call "changed", as this is already done under mouseUp } + return element; }; - return (/** @lends module:path.pathActions */{ + return ( + /** @lends module:path.pathActions */ + { /** * @param {MouseEvent} evt * @param {Element} mouseTarget * @param {Float} startX * @param {Float} startY - * @returns {undefined} + * @returns {boolean|undefined} */ mouseDown: function mouseDown(evt, mouseTarget, startX, startY) { - var id = void 0; + var id; + if (editorContext_.getCurrentMode() === 'path') { var mouseX = startX; // Was this meant to work with the other `mouseX`? (was defined globally so adding `let` to at least avoid a global) + var mouseY = startY; // Was this meant to work with the other `mouseY`? (was defined globally so adding `let` to at least avoid a global) var currentZoom = editorContext_.getCurrentZoom(); @@ -6220,15 +6922,19 @@ }); stretchy = getElem('selectorParentGroup').appendChild(stretchy); } - stretchy.setAttribute('display', 'inline'); + stretchy.setAttribute('display', 'inline'); var keep = null; - var index = void 0; - // if pts array is empty, create path element with M at current point + var index; // if pts array is empty, create path element with M at current point + var drawnPath = editorContext_.getDrawnPath(); + if (!drawnPath) { var dAttr = 'M' + x + ',' + y + ' '; // Was this meant to work with the other `dAttr`? (was defined globally so adding `var` to at least avoid a global) - drawnPath = editorContext_.setDrawnPath(editorContext_.addSVGElementFromJson({ + + /* drawnPath = */ + + editorContext_.setDrawnPath(editorContext_.addSVGElementFromJson({ element: 'path', curStyles: true, attr: { @@ -6236,8 +6942,8 @@ id: editorContext_.getNextId(), opacity: editorContext_.getOpacity() / 2 } - })); - // set stretchy line to first point + })); // set stretchy line to first point + stretchy.setAttribute('d', ['M', mouseX, mouseY, mouseX, mouseY].join(' ')); index = subpath ? path.segs.length : 0; addPointGrip(index, mouseX, mouseY); @@ -6247,30 +6953,29 @@ var i = seglist.numberOfItems; var FUZZ = 6 / currentZoom; var clickOnPoint = false; + while (i) { i--; var item = seglist.getItem(i); var px = item.x, - py = item.y; - // found a matching point + py = item.y; // found a matching point + if (x >= px - FUZZ && x <= px + FUZZ && y >= py - FUZZ && y <= py + FUZZ) { clickOnPoint = true; break; } - } + } // get path element that we are in the process of creating - // get path element that we are in the process of creating - id = editorContext_.getId(); - // Remove previous path object if previously created + id = editorContext_.getId(); // Remove previous path object if previously created + removePath_(id); - var newpath = getElem(id); - var newseg = void 0; - var sSeg = void 0; - var len = seglist.numberOfItems; - // if we clicked on an existing point, then we are done this path, commit it + var newseg; + var sSeg; + var len = seglist.numberOfItems; // if we clicked on an existing point, then we are done this path, commit it // (i, i+1) are the x,y that were clicked on + if (clickOnPoint) { // if clicked on any other point but the first OR // the first point was clicked on and there are less than 3 points @@ -6280,8 +6985,8 @@ // Create end segment var absX = seglist.getItem(0).x; var absY = seglist.getItem(0).y; - sSeg = stretchy.pathSegList.getItem(1); + if (sSeg.pathSegType === 4) { newseg = drawnPath.createSVGPathSegLinetoAbs(absX, absY); } else { @@ -6295,11 +7000,13 @@ keep = false; return keep; } - $$1(stretchy).remove(); - // This will signal to commit the path + $$1(stretchy).remove(); // This will signal to commit the path // const element = newpath; // Other event handlers define own `element`, so this was probably not meant to interact with them or one which shares state (as there were none); I therefore adding a missing `var` to avoid a global - drawnPath = editorContext_.setDrawnPath(null); + + /* drawnPath = */ + + editorContext_.setDrawnPath(null); editorContext_.setStarted(false); if (subpath) { @@ -6311,20 +7018,22 @@ var origD = $$1(path.elem).attr('d'); $$1(path.elem).attr('d', origD + newD); $$1(newpath).remove(); + if (path.matrix) { recalcRotatedPath(); } + init$1(); pathActions.toEditMode(path.elem); path.selectPt(); return false; - } - // else, create a new point, update path element + } // else, create a new point, update path element + } else { // Checks if current target or parents are #svgcontent if (!$$1.contains(editorContext_.getContainer(), editorContext_.getMouseTarget(evt))) { // Clicked outside canvas, so don't make point - console.log('Clicked outside canvas'); + // console.log('Clicked outside canvas'); return false; } @@ -6337,10 +7046,11 @@ var xya = snapToAngle(lastx, lasty, x, y); x = xya.x; y = xya.y; - } + } // Use the segment defined by stretchy + - // Use the segment defined by stretchy sSeg = stretchy.pathSegList.getItem(1); + if (sSeg.pathSegType === 4) { newseg = drawnPath.createSVGPathSegLinetoAbs(editorContext_.round(x), editorContext_.round(y)); } else { @@ -6348,46 +7058,45 @@ } drawnPath.pathSegList.appendItem(newseg); - x *= currentZoom; - y *= currentZoom; + y *= currentZoom; // set stretchy line to latest point - // set stretchy line to latest point stretchy.setAttribute('d', ['M', x, y, x, y].join(' ')); index = num; + if (subpath) { index += path.segs.length; } + addPointGrip(index, x, y); - } - // 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; + return undefined; } path.storeD(); - id = evt.target.id; + var curPt; - var curPt = void 0; if (id.substr(0, 14) === 'pathpointgrip_') { // Select this point - curPt = path.cur_pt = parseInt(id.substr(14), 10); + curPt = path.cur_pt = parseInt(id.substr(14)); path.dragging = [startX, startY]; - var seg = path.segs[curPt]; - - // only clear selection if shift is not pressed (otherwise, add + var seg = path.segs[curPt]; // only clear selection if shift is not pressed (otherwise, add // node to selection) + if (!evt.shiftKey) { if (path.selected_pts.length <= 1 || !seg.selected) { path.clearSelection(); } + path.addPtsToSelection(curPt); } else if (seg.selected) { path.removePtFromSelection(curPt); @@ -6396,20 +7105,22 @@ } } else if (id.startsWith('ctrlpointgrip_')) { path.dragging = [startX, startY]; - var parts = id.split('_')[1].split('c'); curPt = Number(parts[0]); var ctrlNum = Number(parts[1]); path.selectPt(curPt, ctrlNum); - } + } // Start selection box + - // Start selection box if (!path.dragging) { var rubberBox = editorContext_.getRubberBox(); - if (rubberBox == null) { + + if (isNullish(rubberBox)) { rubberBox = editorContext_.setRubberBox(editorContext_.selectorManager.getRubberBandBox()); } + var _currentZoom = editorContext_.getCurrentZoom(); + assignAttributes(rubberBox, { x: startX * _currentZoom, y: startY * _currentZoom, @@ -6418,6 +7129,8 @@ display: 'inline' }, 100); } + + return undefined; }, /** @@ -6429,40 +7142,36 @@ var currentZoom = editorContext_.getCurrentZoom(); hasMoved = true; var drawnPath = editorContext_.getDrawnPath(); + if (editorContext_.getCurrentMode() === 'path') { if (!drawnPath) { return; } + var seglist = drawnPath.pathSegList; var index = seglist.numberOfItems - 1; if (newPoint) { // First point // if (!index) { return; } - // Set control points var pointGrip1 = addCtrlGrip('1c1'); - var pointGrip2 = addCtrlGrip('0c2'); + var pointGrip2 = addCtrlGrip('0c2'); // dragging pointGrip1 - // dragging pointGrip1 pointGrip1.setAttribute('cx', mouseX); pointGrip1.setAttribute('cy', mouseY); pointGrip1.setAttribute('display', 'inline'); - var ptX = newPoint[0]; - var ptY = newPoint[1]; - - // set curve + var ptY = newPoint[1]; // set curve // const seg = seglist.getItem(index); + var curX = mouseX / currentZoom; var curY = mouseY / currentZoom; var altX = ptX + (ptX - curX); var altY = ptY + (ptY - curY); - pointGrip2.setAttribute('cx', altX * currentZoom); pointGrip2.setAttribute('cy', altY * currentZoom); pointGrip2.setAttribute('display', 'inline'); - var ctrlLine = getCtrlLine(1); assignAttributes(ctrlLine, { x1: mouseX, @@ -6486,12 +7195,15 @@ lastX = firstCtrl[0] / currentZoom; lastY = firstCtrl[1] / currentZoom; } + replacePathSeg(6, index, [ptX, ptY, lastX, lastY, altX, altY], drawnPath); } } else { var stretchy = getElem('path_stretch_line'); + if (stretchy) { var prev = seglist.getItem(index); + if (prev.pathSegType === 6) { var prevX = prev.x + (prev.x - prev.x2); var prevY = prev.y + (prev.y - prev.y2); @@ -6503,9 +7215,11 @@ } } } + return; - } - // if we are dragging a point, let's move it + } // if we are dragging a point, let's move it + + if (path.dragging) { var pt = getPointFromGrip({ x: path.dragging[0], @@ -6527,15 +7241,15 @@ } else { path.selected_pts = []; path.eachSeg(function (i) { - var seg = this; + var seg = this; // eslint-disable-line consistent-this + if (!seg.next && !seg.prev) { return; - } + } // const {item} = seg; + - // const {item} = seg; var rubberBox = editorContext_.getRubberBox(); var rbb = rubberBox.getBBox(); - var pt = getGripPt(seg); var ptBb = { x: pt.x, @@ -6543,11 +7257,9 @@ width: 0, height: 0 }; - var sel = rectsIntersect(rbb, ptBb); + this.select(sel); // Note that addPtsToSelection is not being run - this.select(sel); - // Note that addPtsToSelection is not being run if (sel) { path.selected_pts.push(seg.index); } @@ -6555,18 +7267,26 @@ } }, + /** + * @typedef module:path.keepElement + * @type {PlainObject} + * @property {boolean} keep + * @property {Element} element + */ + /** * @param {Event} evt * @param {Element} element * @param {Float} mouseX * @param {Float} mouseY - * @returns {undefined} + * @returns {module:path.keepElement|undefined} */ mouseUp: function mouseUp(evt, element, mouseX, mouseY) { - var drawnPath = editorContext_.getDrawnPath(); - // Create mode + var drawnPath = editorContext_.getDrawnPath(); // Create mode + if (editorContext_.getCurrentMode() === 'path') { newPoint = null; + if (!drawnPath) { element = getElem(editorContext_.getId()); editorContext_.setStarted(false); @@ -6577,13 +7297,13 @@ keep: true, element: element }; - } + } // Edit mode + - // Edit mode var rubberBox = editorContext_.getRubberBox(); + if (path.dragging) { var lastPt = path.cur_pt; - path.dragging = false; path.dragctrl = false; path.update(); @@ -6601,13 +7321,14 @@ if (rubberBox.getAttribute('width') <= 2 && rubberBox.getAttribute('height') <= 2) { pathActions.toSelectMode(evt.target); - } + } // else, move back to select mode - // else, move back to select mode } else { pathActions.toSelectMode(evt.target); } + hasMoved = false; + return undefined; }, /** @@ -6624,7 +7345,7 @@ }, /** - * @param {Element} element + * @param {Element} elem * @fires module:svgcanvas.SvgCanvas#event:selected * @returns {undefined} */ @@ -6669,8 +7390,7 @@ select: function select(target) { if (currentPath === target) { pathActions.toEditMode(target); - editorContext_.setCurrentMode('pathedit'); - // going into pathedit mode + editorContext_.setCurrentMode('pathedit'); // going into pathedit mode } else { currentPath = target; } @@ -6682,11 +7402,14 @@ */ reorient: function reorient() { var elem = editorContext_.getSelectedElements()[0]; + if (!elem) { return; } - var angle = getRotationAngle(elem); - if (angle === 0) { + + var angl = getRotationAngle(elem); + + if (angl === 0) { return; } @@ -6698,19 +7421,14 @@ batchCmd.addSubCommand(new ChangeElementCommand(elem, changes)); editorContext_.clearSelection(); this.resetOrientation(elem); + editorContext_.addCommandToHistory(batchCmd); // Set matrix to null - editorContext_.addCommandToHistory(batchCmd); - - // Set matrix to null getPath_(elem).show(false).matrix = null; - this.clear(); - editorContext_.addToSelection([elem], true); editorContext_.call('changed', editorContext_.getSelectedElements()); }, - /** * @param {boolean} remove Not in use * @returns {undefined} @@ -6718,6 +7436,7 @@ clear: function clear(remove) { var drawnPath = editorContext_.getDrawnPath(); currentPath = null; + if (drawnPath) { var elem = getElem(editorContext_.getId()); $$1(getElem('path_stretch_line')).remove(); @@ -6729,6 +7448,7 @@ } else if (editorContext_.getCurrentMode() === 'pathedit') { this.toSelectMode(); } + if (path) { path.init().show(false); } @@ -6739,22 +7459,20 @@ * @returns {false|undefined} */ resetOrientation: function resetOrientation(pth) { - if (pth == null || pth.nodeName !== 'path') { + if (isNullish(pth) || pth.nodeName !== 'path') { return false; } + var tlist = getTransformList(pth); var m = transformListToTransform(tlist).matrix; tlist.clear(); pth.removeAttribute('transform'); - var segList = pth.pathSegList; - - // Opera/win/non-EN throws an error here. + var segList = pth.pathSegList; // Opera/win/non-EN throws an error here. // TODO: Find out why! // Presumed fixed in Opera 10.5, so commented out for now - // try { - var len = segList.numberOfItems; - // } catch(err) { + + var len = segList.numberOfItems; // } catch(err) { // const fixed_d = pathActions.convertPath(pth); // pth.setAttribute('d', fixed_d); // segList = pth.pathSegList; @@ -6765,13 +7483,16 @@ var _loop = function _loop(i) { var seg = segList.getItem(i); var type = seg.pathSegType; + if (type === 1) { - return 'continue'; + return "continue"; } + var pts = []; $$1.each(['', 1, 2], function (j, n) { var x = seg['x' + n], y = seg['y' + n]; + if (x !== undefined && y !== undefined) { var pt = transformPoint(x, y, m); pts.splice(pts.length, 0, pt.x, pt.y); @@ -6783,10 +7504,11 @@ for (var i = 0; i < len; ++i) { var _ret = _loop(i); - if (_ret === 'continue') continue; + if (_ret === "continue") continue; } reorientGrads(pth, m); + return undefined; }, /** @@ -6804,12 +7526,12 @@ * @property {Float} y * @property {Integer} type */ + /** * @returns {module:path.NodePoint} */ getNodePoint: function getNodePoint() { var selPt = path.selected_pts.length ? path.selected_pts[0] : 1; - var seg = path.segs[selPt]; return { x: seg.item.x, @@ -6831,9 +7553,7 @@ */ clonePathNode: function clonePathNode() { path.storeD(); - - var selPts = path.selected_pts; - // const {segs} = path; + var selPts = path.selected_pts; // const {segs} = path; var i = selPts.length; var nums = []; @@ -6841,12 +7561,11 @@ while (i--) { var pt = selPts[i]; path.addSeg(pt); - nums.push(pt + i); nums.push(pt + i + 1); } - path.init().addPtsToSelection(nums); + path.init().addPtsToSelection(nums); path.endChanges('Clone path node(s)'); }, @@ -6854,56 +7573,55 @@ * @returns {undefined} */ opencloseSubPath: function opencloseSubPath() { - var selPts = path.selected_pts; - // Only allow one selected node for now + var selPts = path.selected_pts; // Only allow one selected node for now + if (selPts.length !== 1) { return; } var _path = path, elem = _path.elem; - - var list = elem.pathSegList; - - // const len = list.numberOfItems; + var list = elem.pathSegList; // const len = list.numberOfItems; var index = selPts[0]; - var openPt = null; - var startItem = null; + var startItem = null; // Check if subpath is already open - // Check if subpath is already open path.eachSeg(function (i) { if (this.type === 2 && i <= index) { startItem = this.item; } + if (i <= index) { return true; } + if (this.type === 2) { // Found M first, so open openPt = i; return false; } + if (this.type === 1) { // Found Z first, so closed openPt = false; return false; } + + return true; }); - if (openPt == null) { + if (isNullish(openPt)) { // Single path, so close last seg openPt = path.segs.length - 1; } if (openPt !== false) { // Close this path - // Create a line going to the previous "M" var newseg = elem.createSVGPathSegLinetoAbs(startItem.x, startItem.y); - var closer = elem.createSVGPathSegClosePath(); + if (openPt === path.segs.length - 1) { list.appendItem(newseg); list.appendItem(closer); @@ -6914,27 +7632,25 @@ path.init().selectPt(openPt + 1); return; - } - - // M 1,1 L 2,2 L 3,3 L 1,1 z // open at 2,2 + } // M 1,1 L 2,2 L 3,3 L 1,1 z // open at 2,2 // M 2,2 L 3,3 L 1,1 - // M 1,1 L 2,2 L 1,1 z M 4,4 L 5,5 L6,6 L 5,5 z // M 1,1 L 2,2 L 1,1 z [M 4,4] L 5,5 L(M)6,6 L 5,5 z + var seg = path.segs[index]; if (seg.mate) { list.removeItem(index); // Removes last "L" + list.removeItem(index); // Removes the "Z" + path.init().selectPt(index - 1); return; } - var lastM = void 0, - zSeg = void 0; + var lastM, zSeg; // Find this sub-path's closing point and remove - // Find this sub-path's closing point and remove for (var i = 0; i < list.numberOfItems; i++) { var item = list.getItem(i); @@ -6943,8 +7659,7 @@ lastM = i; } else if (i === index) { // Remove it - list.removeItem(lastM); - // index--; + list.removeItem(lastM); // index--; } else if (item.pathSegType === 1 && index < i) { // Remove the closing seg of this subpath zSeg = i - 1; @@ -6959,12 +7674,9 @@ insertItemBefore(elem, list.getItem(lastM), zSeg); } - var pt = list.getItem(lastM); + var pt = list.getItem(lastM); // Make this point the new "M" - // Make this point the new "M" - replacePathSeg(2, lastM, [pt.x, pt.y]); - - // i = index; // i is local here, so has no effect; what was the intent for this? + replacePathSeg(2, lastM, [pt.x, pt.y]); // i = index; // i is local here, so has no effect; what was the intent for this? path.init().selectPt(0); }, @@ -6976,17 +7688,17 @@ if (!pathActions.canDeleteNodes) { return; } + path.storeD(); - var selPts = path.selected_pts; - var i = selPts.length; + while (i--) { var pt = selPts[i]; path.deleteSeg(pt); - } + } // Cleanup + - // Cleanup var cleanup = function cleanup() { var segList = path.elem.pathSegList; var len = segList.numberOfItems; @@ -7003,9 +7715,11 @@ while (len--) { var item = segList.getItem(len); + if (item.pathSegType === 1) { var prev = segList.getItem(len - 1); var nprev = segList.getItem(len - 2); + if (prev.pathSegType === 2) { remItems(len - 1, 2); cleanup(); @@ -7017,13 +7731,12 @@ } } else if (item.pathSegType === 2) { if (len > 0) { - var prevType = segList.getItem(len - 1).pathSegType; - // Path has M M + var prevType = segList.getItem(len - 1).pathSegType; // Path has M M + if (prevType === 2) { remItems(len - 1, 1); cleanup(); - break; - // Entire path ends with Z M + break; // Entire path ends with Z M } else if (prevType === 1 && segList.numberOfItems - 1 === len) { remItems(len, 1); cleanup(); @@ -7032,12 +7745,12 @@ } } } + return false; }; - cleanup(); + cleanup(); // Completely delete a path with 1 or 0 segments - // Completely delete a path with 1 or 0 segments if (path.elem.pathSegList.numberOfItems <= 1) { pathActions.toSelectMode(path.elem); editorContext_.canvas.deleteSelectedElements(); @@ -7045,26 +7758,28 @@ } path.init(); - path.clearSelection(); - - // TODO: Find right way to select point now + path.clearSelection(); // TODO: Find right way to select point now // path.selectPt(selPt); + if (window.opera) { // Opera repaints incorrectly var cp = $$1(path.elem); cp.attr('d', cp.attr('d')); } + path.endChanges('Delete path node(s)'); }, - // Can't seem to use `@borrows` here, so using `@see` + /** * Smooth polyline into path * @function module:path.pathActions.smoothPolylineIntoPath * @see module:path~smoothPolylineIntoPath */ smoothPolylineIntoPath: smoothPolylineIntoPath, + /** + * @param {?Integer} v See {@link https://www.w3.org/TR/SVG/single-page.html#paths-InterfaceSVGPathSeg} * @returns {undefined} */ setSegType: function setSegType(v) { @@ -7078,17 +7793,19 @@ */ moveNode: function moveNode(attr, newValue) { var selPts = path.selected_pts; + if (!selPts.length) { return; } - path.storeD(); + path.storeD(); // Get first selected point - // Get first selected point var seg = path.segs[selPts[0]]; - var diff = { x: 0, y: 0 }; + var diff = { + x: 0, + y: 0 + }; diff[attr] = newValue - seg.item[attr]; - seg.move(diff.x, diff.y); path.endChanges('Move path point'); }, @@ -7103,31 +7820,35 @@ // M0,0 L0,100 L100,100 z var segList = elem.pathSegList; var len = segList.numberOfItems; - var lastM = void 0; + var lastM; + for (var i = 0; i < len; ++i) { var item = segList.getItem(i); + if (item.pathSegType === 2) { lastM = item; } if (item.pathSegType === 1) { var prev = segList.getItem(i - 1); + if (prev.x !== lastM.x || prev.y !== lastM.y) { // Add an L segment here var newseg = elem.createSVGPathSegLinetoAbs(lastM.x, lastM.y); - insertItemBefore(elem, newseg, i); - // Can this be done better? + insertItemBefore(elem, newseg, i); // Can this be done better? + pathActions.fixEnd(elem); break; } } } + if (isWebkit()) { editorContext_.resetD(elem); } }, - // Can't seem to use `@borrows` here, so using `@see` + /** * Convert a path to one with only absolute or relative values * @function module:path.pathActions.convertPath @@ -7136,26 +7857,19 @@ convertPath: convertPath } ); - }(); + }(); // end pathActions - /* globals jQuery */ + var $$2 = jQueryPluginSVG(jQuery); // String used to encode base64. - // Constants - var $$2 = jqPluginSVG(jQuery); + var KEYSTR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; // Much faster than running getBBox() every time - // String used to encode base64. - var KEYSTR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; - - // Much faster than running getBBox() every time var visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use'; - var visElemsArr = visElems.split(','); - // const hidElems = 'clipPath,defs,desc,feGaussianBlur,filter,linearGradient,marker,mask,metadata,pattern,radialGradient,stop,switch,symbol,title,textPath'; + var visElemsArr = visElems.split(','); // const hidElems = 'clipPath,defs,desc,feGaussianBlur,filter,linearGradient,marker,mask,metadata,pattern,radialGradient,stop,switch,symbol,title,textPath'; var editorContext_$1 = null; var domdoc_ = null; var domcontainer_ = null; var svgroot_ = null; - /** * Object with the following keys/values * @typedef {PlainObject} module:utilities.SVGElementJSON @@ -7172,10 +7886,12 @@ * @interface module:utilities.EditorContext * @property {module:path.pathActions} pathActions */ + /** * @function module:utilities.EditorContext#getSVGContent * @returns {SVGSVGElement} */ + /** * Create a new SVG element based on the given object keys/values and add it * to the current layer. @@ -7184,26 +7900,32 @@ * @param {module:utilities.SVGElementJSON} data * @returns {Element} The new element */ + /** * @function module:utilities.EditorContext#getSelectedElements * @returns {Element[]} the array with selected DOM elements */ + /** * @function module:utilities.EditorContext#getDOMDocument * @returns {HTMLDocument} */ + /** * @function module:utilities.EditorContext#getDOMContainer * @returns {HTMLElement} */ + /** * @function module:utilities.EditorContext#getSVGRoot * @returns {SVGSVGElement} */ + /** * @function module:utilities.EditorContext#getBaseUnit * @returns {string} */ + /** * @function module:utilities.EditorContext#getSnappingStep * @returns {Float|string} @@ -7214,13 +7936,24 @@ * @param {module:utilities.EditorContext} editorContext * @returns {undefined} */ - var init$2 = function init$$1(editorContext) { + + var init$2 = function init(editorContext) { editorContext_$1 = editorContext; domdoc_ = editorContext.getDOMDocument(); domcontainer_ = editorContext.getDOMContainer(); svgroot_ = editorContext.getSVGRoot(); }; + /** + * Used to prevent the [Billion laughs attack]{@link https://en.wikipedia.org/wiki/Billion_laughs_attack}. + * @function module:utilities.dropXMLInteralSubset + * @param {string} str String to be processed + * @returns {string} The string with entity declarations in the internal subset removed + * @todo This might be needed in other places `parseFromString` is used even without LGTM flagging + */ + var dropXMLInteralSubset = function dropXMLInteralSubset(str) { + return str.replace(/(<!DOCTYPE\s+\w*\s*\[).*(\?\]>)/, '$1$2'); + }; /** * Converts characters in a string to XML-friendly entities. * @function module:utilities.toXml @@ -7228,50 +7961,52 @@ * @param {string} str - The string to be converted * @returns {string} The converted string */ + var toXml = function toXml(str) { // ' is ok in XML, but not HTML // > does not normally need escaping, though it can if within a CDATA expression (and preceded by "]]") - return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/, '''); + return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, '''); // Note: `'` is XML only }; - - // 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. // Base64 code from Tyler Akins -- http://rumkin.com - // schiller: Removed string concatenation in favour of Array.join() optimization, // also precalculate the size of the array needed. /** - * Converts a string to base64 + * Converts a string to base64. * @function module:utilities.encode64 * @param {string} input * @returns {string} Base64 output */ - var encode64 = function encode64(input) { + + function encode64(input) { // base64 strings are 4/3 larger than the original string input = encodeUTF8(input); // convert non-ASCII characters // input = convertToXMLReferences(input); + if (window.btoa) { return window.btoa(input); // Use native if available } - var output = []; - output.length = Math.floor((input.length + 2) / 3) * 4; + var output = new Array(Math.floor((input.length + 2) / 3) * 4); var i = 0, p = 0; + do { var chr1 = input.charCodeAt(i++); var chr2 = input.charCodeAt(i++); var chr3 = input.charCodeAt(i++); + /* eslint-disable no-bitwise */ var enc1 = chr1 >> 2; var enc2 = (chr1 & 3) << 4 | chr2 >> 4; - var enc3 = (chr2 & 15) << 2 | chr3 >> 6; var enc4 = chr3 & 63; + /* eslint-enable no-bitwise */ if (isNaN(chr2)) { - enc3 = enc4 = 64; + enc3 = 64; + enc4 = 64; } else if (isNaN(chr3)) { enc4 = 64; } @@ -7283,22 +8018,21 @@ } while (i < input.length); return output.join(''); - }; - + } /** - * Converts a string from base64 + * Converts a string from base64. * @function module:utilities.decode64 * @param {string} input Base64-encoded input * @returns {string} Decoded output */ - var decode64 = function decode64(input) { + + function decode64(input) { if (window.atob) { return decodeUTF8(window.atob(input)); - } + } // remove all characters that are not A-Z, a-z, 0-9, +, /, or = + - // remove all characters that are not A-Z, a-z, 0-9, +, /, or = input = input.replace(/[^A-Za-z0-9+/=]/g, ''); - var output = ''; var i = 0; @@ -7307,109 +8041,123 @@ var enc2 = KEYSTR.indexOf(input.charAt(i++)); var enc3 = KEYSTR.indexOf(input.charAt(i++)); var enc4 = KEYSTR.indexOf(input.charAt(i++)); + /* eslint-disable no-bitwise */ var chr1 = enc1 << 2 | enc2 >> 4; var chr2 = (enc2 & 15) << 4 | enc3 >> 2; var chr3 = (enc3 & 3) << 6 | enc4; + /* eslint-enable no-bitwise */ output += String.fromCharCode(chr1); if (enc3 !== 64) { - output = output + String.fromCharCode(chr2); + output += String.fromCharCode(chr2); } + if (enc4 !== 64) { - output = output + String.fromCharCode(chr3); + output += String.fromCharCode(chr3); } } while (i < input.length); - return decodeUTF8(output); - }; + return decodeUTF8(output); + } /** * @function module:utilities.decodeUTF8 * @param {string} argString * @returns {string} */ - var decodeUTF8 = function decodeUTF8(argString) { - return decodeURIComponent(escape(argString)); - }; - // codedread:does not seem to work with webkit-based browsers on OSX // Brettz9: please test again as function upgraded + function decodeUTF8(argString) { + return decodeURIComponent(escape(argString)); + } // codedread:does not seem to work with webkit-based browsers on OSX // Brettz9: please test again as function upgraded + /** * @function module:utilities.encodeUTF8 * @param {string} argString * @returns {string} */ + var encodeUTF8 = function encodeUTF8(argString) { return unescape(encodeURIComponent(argString)); }; - /** - * convert dataURL to object URL + * Convert dataURL to object URL. * @function module:utilities.dataURLToObjectURL * @param {string} dataurl * @returns {string} object URL or empty string */ + var dataURLToObjectURL = function dataURLToObjectURL(dataurl) { if (typeof Uint8Array === 'undefined' || typeof Blob === 'undefined' || typeof URL === 'undefined' || !URL.createObjectURL) { return ''; } + var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]); var n = bstr.length; var u8arr = new Uint8Array(n); + while (n--) { u8arr[n] = bstr.charCodeAt(n); } - var blob = new Blob([u8arr], { type: mime }); + + var blob = new Blob([u8arr], { + type: mime + }); return URL.createObjectURL(blob); }; - /** - * get object URL for a blob object + * Get object URL for a blob object. * @function module:utilities.createObjectURL * @param {Blob} blob A Blob object or File object * @returns {string} object URL or empty string */ + var createObjectURL = function createObjectURL(blob) { if (!blob || typeof URL === 'undefined' || !URL.createObjectURL) { return ''; } + return URL.createObjectURL(blob); }; - /** * @property {string} blankPageObjectURL */ + var blankPageObjectURL = function () { if (typeof Blob === 'undefined') { return ''; } - var blob = new Blob(['<html><head><title>SVG-edit '], { type: 'text/html' }); + + var blob = new Blob(['SVG-edit '], { + type: 'text/html' + }); return createObjectURL(blob); }(); - /** - * Cross-browser compatible method of converting a string to an XML tree - * found this function [here]{@link http://groups.google.com/group/jquery-dev/browse_thread/thread/c6d11387c580a77f} + * Cross-browser compatible method of converting a string to an XML tree. + * Found this function [here]{@link http://groups.google.com/group/jquery-dev/browse_thread/thread/c6d11387c580a77f}. * @function module:utilities.text2xml * @param {string} sXML * @throws {Error} * @returns {XMLDocument} */ + var text2xml = function text2xml(sXML) { if (sXML.includes('` element, creating it first if necessary */ + var findDefs = function findDefs() { var svgElement = editorContext_$1.getSVGContent(); var defs = svgElement.getElementsByTagNameNS(NS.SVG, 'defs'); + if (defs.length > 0) { defs = defs[0]; } else { defs = svgElement.ownerDocument.createElementNS(NS.SVG, 'defs'); + if (svgElement.firstChild) { // first child is a comment, so call nextSibling - svgElement.insertBefore(defs, svgElement.firstChild.nextSibling); - // svgElement.firstChild.nextSibling.before(defs); // Not safe + svgElement.insertBefore(defs, svgElement.firstChild.nextSibling); // svgElement.firstChild.nextSibling.before(defs); // Not safe } else { svgElement.append(defs); } } - return defs; - }; - // TODO(codedread): Consider moving the next to functions to bbox.js + return defs; + }; // TODO(codedread): Consider moving the next to functions to bbox.js /** * Get correct BBox for a path in Webkit. - * Converted from code found [here]{@link http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html} + * Converted from code found [here]{@link http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html}. * @function module:utilities.getPathBBox * @param {SVGPathElement} path - The path DOM element to get the BBox for * @returns {module:utilities.BBoxObject} A BBox-like object */ - var getPathBBox = function getPathBBox(path$$1) { - var seglist = path$$1.pathSegList; - var tot = seglist.numberOfItems; + var getPathBBox = function getPathBBox(path) { + var seglist = path.pathSegList; + var tot = seglist.numberOfItems; var bounds = [[], []]; var start = seglist.getItem(0); var P0 = [start.x, start.y]; + var getCalc = function getCalc(j, P1, P2, P3) { + return function (t) { + return 1 - Math.pow(t, 3) * P0[j] + 3 * 1 - Math.pow(t, 2) * t * P1[j] + 3 * (1 - t) * Math.pow(t, 2) * P2[j] + Math.pow(t, 3) * P3[j]; + }; + }; + for (var i = 0; i < tot; i++) { var seg = seglist.getItem(i); if (seg.x === undefined) { continue; - } + } // Add actual points to limits + - // Add actual points to limits bounds[0].push(P0[0]); bounds[1].push(P0[1]); if (seg.x1) { - (function () { - var P1 = [seg.x1, seg.y1], - P2 = [seg.x2, seg.y2], - P3 = [seg.x, seg.y]; + var P1 = [seg.x1, seg.y1], + P2 = [seg.x2, seg.y2], + P3 = [seg.x, seg.y]; - var _loop = function _loop(j) { - var calc = function calc(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 (var j = 0; j < 2; j++) { + var calc = getCalc(j, P1, P2, P3); + var b = 6 * P0[j] - 12 * P1[j] + 6 * P2[j]; + var a = -3 * P0[j] + 9 * P1[j] - 9 * P2[j] + 3 * P3[j]; + var c = 3 * P1[j] - 3 * P0[j]; - var b = 6 * P0[j] - 12 * P1[j] + 6 * P2[j]; - var a = -3 * P0[j] + 9 * P1[j] - 9 * P2[j] + 3 * P3[j]; - var c = 3 * P1[j] - 3 * P0[j]; - - if (a === 0) { - if (b === 0) { - return 'continue'; - } - var t = -c / b; - if (t > 0 && t < 1) { - bounds[j].push(calc(t)); - } - return 'continue'; + if (a === 0) { + if (b === 0) { + continue; } - var b2ac = Math.pow(b, 2) - 4 * c * a; - if (b2ac < 0) { - return 'continue'; - } - var t1 = (-b + Math.sqrt(b2ac)) / (2 * a); - if (t1 > 0 && t1 < 1) { - bounds[j].push(calc(t1)); - } - var t2 = (-b - Math.sqrt(b2ac)) / (2 * a); - if (t2 > 0 && t2 < 1) { - bounds[j].push(calc(t2)); - } - }; - for (var j = 0; j < 2; j++) { - var _ret2 = _loop(j); + var t = -c / b; - if (_ret2 === 'continue') continue; + if (t > 0 && t < 1) { + bounds[j].push(calc(t)); + } + + continue; } - P0 = P3; - })(); + + var b2ac = Math.pow(b, 2) - 4 * c * a; + + if (b2ac < 0) { + continue; + } + + var t1 = (-b + Math.sqrt(b2ac)) / (2 * a); + + if (t1 > 0 && t1 < 1) { + bounds[j].push(calc(t1)); + } + + var t2 = (-b - Math.sqrt(b2ac)) / (2 * a); + + if (t2 > 0 && t2 < 1) { + bounds[j].push(calc(t2)); + } + } + + P0 = P3; } else { bounds[0].push(seg.x); bounds[1].push(seg.y); @@ -7646,7 +8412,6 @@ height: h }; }; - /** * Get the given/selected element's bounding box object, checking for * horizontal/vertical lines (see issue 717) @@ -7655,16 +8420,17 @@ * @param {Element} selected - Container or `` DOM element * @returns {DOMRect} Bounding box object */ + function groupBBFix(selected) { if (supportsHVLineContainerBBox()) { try { return selected.getBBox(); } catch (e) {} } + var ref = $$2.data(selected, 'ref'); var matched = null; - var ret = void 0, - copy = void 0; + var ret, copy; if (ref) { copy = $$2(ref).children().clone().attr('visibility', 'hidden'); @@ -7675,13 +8441,16 @@ } var issue = false; + if (matched.length) { matched.each(function () { var bb = this.getBBox(); + if (!bb.width || !bb.height) { issue = true; } }); + if (issue) { var elems = ref ? copy : $$2(selected).children(); ret = getStrokedBBox(elems); @@ -7691,64 +8460,72 @@ } else { ret = selected.getBBox(); } + if (ref) { copy.remove(); } + return ret; } - /** * Get the given/selected element's bounding box object, convert it to be more - * usable when necessary + * usable when necessary. * @function module:utilities.getBBox * @param {Element} elem - Optional DOM element to get the BBox for * @returns {module:utilities.BBoxObject} Bounding box object */ + + var getBBox = function getBBox(elem) { var selected = elem || editorContext_$1.geSelectedElements()[0]; + if (elem.nodeType !== 1) { return null; } - var elname = selected.nodeName; + var elname = selected.nodeName; var ret = null; + switch (elname) { case 'text': if (selected.textContent === '') { selected.textContent = 'a'; // Some character needed for the selector to use. + ret = selected.getBBox(); selected.textContent = ''; - } else { - if (selected.getBBox) { - ret = selected.getBBox(); - } + } else if (selected.getBBox) { + ret = selected.getBBox(); } + break; + case 'path': if (!supportsPathBBox()) { ret = getPathBBox(selected); - } else { - if (selected.getBBox) { - ret = selected.getBBox(); - } + } else if (selected.getBBox) { + ret = selected.getBBox(); } + break; + case 'g': case 'a': ret = groupBBFix(selected); break; - default: + default: if (elname === 'use') { - ret = groupBBFix(selected, true); + ret = groupBBFix(selected); // , true); } + if (elname === 'use' || elname === 'foreignObject' && isWebkit()) { if (!ret) { ret = selected.getBBox(); - } - // This is resolved in later versions of webkit, perhaps we should + } // This is resolved in later versions of webkit, perhaps we should // have a featured detection for correct 'use' behavior? // —————————— + + if (!isWebkit()) { var bb = {}; bb.width = ret.width; @@ -7765,7 +8542,9 @@ // tspan (and textPath apparently) have no `getBBox` in Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=937268 // Re: Chrome returning bbox for containing text element, see: https://bugs.chromium.org/p/chromium/issues/detail?id=349835 var extent = selected.getExtentOfChar(0); // pos+dimensions of the first glyph + var width = selected.getComputedTextLength(); // width of the tspan + ret = { x: extent.x, y: extent.y, @@ -7776,6 +8555,7 @@ } else { // Check if element is child of a foreignObject var fo = $$2(selected).closest('foreignObject'); + if (fo.length) { if (fo[0].getBBox) { ret = fo[0].getBBox(); @@ -7783,15 +8563,16 @@ } } } + } + if (ret) { ret = bboxToObj(ret); - } + } // get the bounding box from the DOM (which is in that element's coordinate system) + - // get the bounding box from the DOM (which is in that element's coordinate system) return ret; }; - /** * @typedef {GenericArray} module:utilities.PathSegmentArray * @property {Integer} length 2 @@ -7806,157 +8587,168 @@ * @param {module:utilities.PathSegmentArray[]} pathSegments - An array of path segments to be converted * @returns {string} The converted path d attribute. */ + var getPathDFromSegments = function getPathDFromSegments(pathSegments) { var d = ''; - $$2.each(pathSegments, function (j, _ref2) { - var _ref3 = slicedToArray(_ref2, 2), + var _ref3 = _slicedToArray(_ref2, 2), singleChar = _ref3[0], pts = _ref3[1]; d += singleChar; + for (var i = 0; i < pts.length; i += 2) { d += pts[i] + ',' + pts[i + 1] + ' '; } }); - return d; }; - /** * Make a path 'd' attribute from a simple SVG element shape. * @function module:utilities.getPathDFromElement * @param {Element} elem - The element to be converted * @returns {string} The path d attribute or `undefined` if the element type is unknown. */ + var getPathDFromElement = function getPathDFromElement(elem) { // Possibly the cubed root of 6, but 1.81 works best var num = 1.81; - var d = void 0, - a = void 0, - rx = void 0, - ry = void 0; + var d, a, rx, ry; + switch (elem.tagName) { case 'ellipse': case 'circle': - a = $$2(elem).attr(['rx', 'ry', 'cx', 'cy']); - var _a = a, - cx = _a.cx, - cy = _a.cy; - var _a2 = a; - rx = _a2.rx; - ry = _a2.ry; + { + a = $$2(elem).attr(['rx', 'ry', 'cx', 'cy']); + var _a = a, + cx = _a.cx, + cy = _a.cy; + var _a2 = a; + rx = _a2.rx; + ry = _a2.ry; - if (elem.tagName === 'circle') { - rx = ry = $$2(elem).attr('r'); + if (elem.tagName === 'circle') { + ry = $$2(elem).attr('r'); + rx = ry; + } + + d = getPathDFromSegments([['M', [cx - rx, cy]], ['C', [cx - rx, cy - ry / num, cx - rx / num, cy - ry, cx, cy - ry]], ['C', [cx + rx / num, cy - ry, cx + rx, cy - ry / num, cx + rx, cy]], ['C', [cx + rx, cy + ry / num, cx + rx / num, cy + ry, cx, cy + ry]], ['C', [cx - rx / num, cy + ry, cx - rx, cy + ry / num, cx - rx, cy]], ['Z', []]]); + break; } - d = getPathDFromSegments([['M', [cx - rx, cy]], ['C', [cx - rx, cy - ry / num, cx - rx / num, cy - ry, cx, cy - ry]], ['C', [cx + rx / num, cy - ry, cx + rx, cy - ry / num, cx + rx, cy]], ['C', [cx + rx, cy + ry / num, cx + rx / num, cy + ry, cx, cy + ry]], ['C', [cx - rx / num, cy + ry, cx - rx, cy + ry / num, cx - rx, cy]], ['Z', []]]); - break; case 'path': d = elem.getAttribute('d'); break; + case 'line': a = $$2(elem).attr(['x1', 'y1', 'x2', 'y2']); d = 'M' + a.x1 + ',' + a.y1 + 'L' + a.x2 + ',' + a.y2; break; + case 'polyline': d = 'M' + elem.getAttribute('points'); break; + case 'polygon': d = 'M' + elem.getAttribute('points') + ' Z'; break; + case 'rect': - var r = $$2(elem).attr(['rx', 'ry']); - rx = r.rx; - ry = r.ry; + { + var r = $$2(elem).attr(['rx', 'ry']); + rx = r.rx; + ry = r.ry; + var b = elem.getBBox(); + var x = b.x, + y = b.y, + w = b.width, + h = b.height; + num = 4 - num; // Why? Because! - var _b = elem.getBBox(); - var x = _b.x, - y = _b.y, - w = _b.width, - h = _b.height; + if (!rx && !ry) { + // Regular rect + d = getPathDFromSegments([['M', [x, y]], ['L', [x + w, y]], ['L', [x + w, y + h]], ['L', [x, y + h]], ['L', [x, y]], ['Z', []]]); + } else { + d = getPathDFromSegments([['M', [x, y + ry]], ['C', [x, y + ry / num, x + rx / num, y, x + rx, y]], ['L', [x + w - rx, y]], ['C', [x + w - rx / num, y, x + w, y + ry / num, x + w, y + ry]], ['L', [x + w, y + h - ry]], ['C', [x + w, y + h - ry / num, x + w - rx / num, y + h, x + w - rx, y + h]], ['L', [x + rx, y + h]], ['C', [x + rx / num, y + h, x, y + h - ry / num, x, y + h - ry]], ['L', [x, y + ry]], ['Z', []]]); + } - num = 4 - num; // Why? Because! - - if (!rx && !ry) { - // Regular rect - d = getPathDFromSegments([['M', [x, y]], ['L', [x + w, y]], ['L', [x + w, y + h]], ['L', [x, y + h]], ['L', [x, y]], ['Z', []]]); - } else { - d = getPathDFromSegments([['M', [x, y + ry]], ['C', [x, y + ry / num, x + rx / num, y, x + rx, y]], ['L', [x + w - rx, y]], ['C', [x + w - rx / num, y, x + w, y + ry / num, x + w, y + ry]], ['L', [x + w, y + h - ry]], ['C', [x + w, y + h - ry / num, x + w - rx / num, y + h, x + w - rx, y + h]], ['L', [x + rx, y + h]], ['C', [x + rx / num, y + h, x, y + h - ry / num, x, y + h - ry]], ['L', [x, y + ry]], ['Z', []]]); + break; } - break; + default: break; } return d; }; - /** * Get a set of attributes from an element that is useful for convertToPath. * @function module:utilities.getExtraAttributesForConvertToPath * @param {Element} elem - The element to be probed * @returns {PlainObject.<"marker-start"|"marker-end"|"marker-mid"|"filter"|"clip-path", string>} An object with attributes. */ + var getExtraAttributesForConvertToPath = function getExtraAttributesForConvertToPath(elem) { - var attrs = {}; - // TODO: make this list global so that we can properly maintain it + var attrs = {}; // TODO: make this list global so that we can properly maintain it // TODO: what about @transform, @clip-rule, @fill-rule, etc? + $$2.each(['marker-start', 'marker-end', 'marker-mid', 'filter', 'clip-path'], function () { var a = elem.getAttribute(this); + if (a) { attrs[this] = a; } }); return attrs; }; - /** - * Get the BBox of an element-as-path + * Get the BBox of an element-as-path. * @function module:utilities.getBBoxOfElementAsPath * @param {Element} elem - The DOM element to be probed * @param {module:utilities.EditorContext#addSVGElementFromJson} addSVGElementFromJson - Function to add the path element to the current layer. See canvas.addSVGElementFromJson * @param {module:path.pathActions} pathActions - If a transform exists, `pathActions.resetOrientation()` is used. See: canvas.pathActions. * @returns {DOMRect|false} The resulting path's bounding box object. */ - var getBBoxOfElementAsPath = function getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions$$1) { - var path$$1 = addSVGElementFromJson({ + + var getBBoxOfElementAsPath = function getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions) { + var path = addSVGElementFromJson({ element: 'path', attr: getExtraAttributesForConvertToPath(elem) }); - var eltrans = elem.getAttribute('transform'); + if (eltrans) { - path$$1.setAttribute('transform', eltrans); + path.setAttribute('transform', eltrans); } - var parent = elem.parentNode; + var parentNode = elem.parentNode; + if (elem.nextSibling) { - elem.before(path$$1); + elem.before(path); } else { - parent.append(path$$1); + parentNode.append(path); } var d = getPathDFromElement(elem); + if (d) { - path$$1.setAttribute('d', d); + path.setAttribute('d', d); } else { - path$$1.remove(); + path.remove(); + } // Get the correct BBox of the new path, then discard it + + + pathActions.resetOrientation(path); + var bb = false; + + try { + bb = path.getBBox(); + } catch (e) {// Firefox fails } - // Get the correct BBox of the new path, then discard it - pathActions$$1.resetOrientation(path$$1); - var bb = false; - try { - bb = path$$1.getBBox(); - } catch (e) { - // Firefox fails - } - path$$1.remove(); + path.remove(); return bb; }; - /** * Convert selected element to a path. * @function module:utilities.convertToPath @@ -7966,69 +8758,64 @@ * @param {module:path.pathActions} pathActions - If a transform exists, pathActions.resetOrientation() is used. See: canvas.pathActions. * @param {module:draw.DrawCanvasInit#clearSelection|module:path.EditorContext#clearSelection} clearSelection - see [canvas.clearSelection]{@link module:svgcanvas.SvgCanvas#clearSelection} * @param {module:path.EditorContext#addToSelection} addToSelection - see [canvas.addToSelection]{@link module:svgcanvas.SvgCanvas#addToSelection} - * @param {module:history} history - see history module + * @param {module:history} hstry - see history module * @param {module:path.EditorContext#addCommandToHistory|module:draw.DrawCanvasInit#addCommandToHistory} addCommandToHistory - see [canvas.addCommandToHistory]{@link module:svgcanvas~addCommandToHistory} * @returns {SVGPathElement|null} The converted path element or null if the DOM element was not recognized. */ - var convertToPath = function convertToPath(elem, attrs, addSVGElementFromJson, pathActions$$1, clearSelection, addToSelection, history, addCommandToHistory) { - var batchCmd = new history.BatchCommand('Convert element to Path'); - // Any attribute on the element not covered by the passed-in attributes + var convertToPath = function convertToPath(elem, attrs, addSVGElementFromJson, pathActions, clearSelection, addToSelection, hstry, addCommandToHistory) { + var batchCmd = new hstry.BatchCommand('Convert element to Path'); // Any attribute on the element not covered by the passed-in attributes + attrs = $$2.extend({}, attrs, getExtraAttributesForConvertToPath(elem)); - - var path$$1 = addSVGElementFromJson({ + var path = addSVGElementFromJson({ element: 'path', attr: attrs }); - var eltrans = elem.getAttribute('transform'); + if (eltrans) { - path$$1.setAttribute('transform', eltrans); + path.setAttribute('transform', eltrans); } var id = elem.id; + var parentNode = elem.parentNode; - var parent = elem.parentNode; if (elem.nextSibling) { - elem.before(path$$1); + elem.before(path); } else { - parent.append(path$$1); + parentNode.append(path); } var d = getPathDFromElement(elem); + if (d) { - path$$1.setAttribute('d', d); - - // Replace the current element with the converted one - + path.setAttribute('d', d); // Replace the current element with the converted one // Reorient if it has a matrix + if (eltrans) { - var tlist = getTransformList(path$$1); + var tlist = getTransformList(path); + if (hasMatrixTransform(tlist)) { - pathActions$$1.resetOrientation(path$$1); + pathActions.resetOrientation(path); } } var nextSibling = elem.nextSibling; - - batchCmd.addSubCommand(new history.RemoveElementCommand(elem, nextSibling, parent)); - batchCmd.addSubCommand(new history.InsertElementCommand(path$$1)); - + batchCmd.addSubCommand(new hstry.RemoveElementCommand(elem, nextSibling, parent)); + batchCmd.addSubCommand(new hstry.InsertElementCommand(path)); clearSelection(); elem.remove(); - path$$1.setAttribute('id', id); - path$$1.removeAttribute('visibility'); - addToSelection([path$$1], true); - + path.setAttribute('id', id); + path.removeAttribute('visibility'); + addToSelection([path], true); addCommandToHistory(batchCmd); + return path; + } // the elem.tagName was not recognized, so no "d" attribute. Remove it, so we've haven't changed anything. - return path$$1; - } - // the elem.tagName was not recognized, so no "d" attribute. Remove it, so we've haven't changed anything. - path$$1.remove(); + + path.remove(); return null; }; - /** * Can the bbox be optimized over the native getBBox? The optimized bbox is the same as the native getBBox when * the rotation angle is a multiple of 90 degrees and there are no complex transforms. @@ -8046,16 +8833,16 @@ * getBBox then apply the angle and any transforms. * * @param {Float} angle - The rotation angle in degrees - * @param {boolean} hasMatrixTransform - True if there is a matrix transform + * @param {boolean} hasAMatrixTransform - True if there is a matrix transform * @returns {boolean} True if the bbox can be optimized. */ - function bBoxCanBeOptimizedOverNativeGetBBox(angle, hasMatrixTransform$$1) { + + function bBoxCanBeOptimizedOverNativeGetBBox(angle, hasAMatrixTransform) { var angleModulo90 = angle % 90; var closeTo90 = angleModulo90 < -89.99 || angleModulo90 > 89.99; var closeTo0 = angleModulo90 > -0.001 && angleModulo90 < 0.001; - return hasMatrixTransform$$1 || !(closeTo0 || closeTo90); + return hasAMatrixTransform || !(closeTo0 || closeTo90); } - /** * Get bounding box that includes any transforms. * @function module:utilities.getBBoxWithTransform @@ -8064,11 +8851,12 @@ * @param {module:path.pathActions} pathActions - If a transform exists, pathActions.resetOrientation() is used. See: canvas.pathActions. * @returns {module:utilities.BBoxObject|module:math.TransformedBox|DOMRect} A single bounding box object */ - var getBBoxWithTransform = function getBBoxWithTransform(elem, addSVGElementFromJson, pathActions$$1) { + + + var getBBoxWithTransform = function getBBoxWithTransform(elem, addSVGElementFromJson, pathActions) { // TODO: Fix issue with rotated groups. Currently they work // fine in FF, but not in other browsers (same problem mentioned // in Issue 339 comment #2). - var bb = getBBox(elem); if (!bb) { @@ -8081,18 +8869,23 @@ if (angle || hasMatrixXForm) { var goodBb = false; + if (bBoxCanBeOptimizedOverNativeGetBBox(angle, hasMatrixXForm)) { // Get the BBox from the raw path for these elements // TODO: why ellipse and not circle var elemNames = ['ellipse', 'path', 'line', 'polyline', 'polygon']; + if (elemNames.includes(elem.tagName)) { - bb = goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions$$1); + goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions); + bb = goodBb; } else if (elem.tagName === 'rect') { // Look for radius var rx = elem.getAttribute('rx'); var ry = elem.getAttribute('ry'); + if (rx || ry) { - bb = goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions$$1); + goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions); + bb = goodBb; } } } @@ -8101,9 +8894,7 @@ var _transformListToTrans = transformListToTransform(tlist), matrix = _transformListToTrans.matrix; - bb = transformBox(bb.x, bb.y, bb.width, bb.height, matrix).aabox; - - // Old technique that was exceedingly slow with large documents. + bb = transformBox(bb.x, bb.y, bb.width, bb.height, matrix).aabox; // Old technique that was exceedingly slow with large documents. // // Accurate way to get BBox of rotated element in Firefox: // Put element in group and get its BBox @@ -8118,15 +8909,20 @@ // g.remove(); } } + return bb; }; + /** + * @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. + */ - // 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) { var sw = elem.getAttribute('stroke-width'); return !isNaN(sw) && elem.getAttribute('stroke') !== 'none' ? sw / 2 : 0; } - /** * @typedef {PlainObject} BBox * @property {Integer} x The x value @@ -8136,43 +8932,44 @@ */ /** - * Get the bounding box for one or more stroked and/or transformed elements + * Get the bounding box for one or more stroked and/or transformed elements. * @function module:utilities.getStrokedBBox * @param {Element[]} elems - Array with DOM elements to check * @param {module:utilities.EditorContext#addSVGElementFromJson} addSVGElementFromJson - Function to add the path element to the current layer. See canvas.addSVGElementFromJson * @param {module:path.pathActions} pathActions - If a transform exists, pathActions.resetOrientation() is used. See: canvas.pathActions. * @returns {module:utilities.BBoxObject|module:math.TransformedBox|DOMRect} A single bounding box object */ - var getStrokedBBox = function getStrokedBBox(elems, addSVGElementFromJson, pathActions$$1) { + + + var getStrokedBBox = function getStrokedBBox(elems, addSVGElementFromJson, pathActions) { if (!elems || !elems.length) { return false; } - var fullBb = void 0; + var fullBb; $$2.each(elems, function () { if (fullBb) { return; } + if (!this.parentNode) { return; } - fullBb = getBBoxWithTransform(this, addSVGElementFromJson, pathActions$$1); - }); - // This shouldn't ever happen... + fullBb = getBBoxWithTransform(this, addSVGElementFromJson, pathActions); + }); // This shouldn't ever happen... + if (fullBb === undefined) { return null; - } - - // fullBb doesn't include the stoke, so this does no good! + } // fullBb doesn't include the stoke, so this does no good! // if (elems.length == 1) return fullBb; + var maxX = fullBb.x + fullBb.width; var maxY = fullBb.y + fullBb.height; var minX = fullBb.x; - var minY = fullBb.y; + var minY = fullBb.y; // If only one elem, don't call the potentially slow getBBoxWithTransform method again. - // If only one elem, don't call the potentially slow getBBoxWithTransform method again. if (elems.length === 1) { var offset = getStrokeOffsetForBBox(elems[0]); minX -= offset; @@ -8181,12 +8978,14 @@ maxY += offset; } else { $$2.each(elems, function (i, elem) { - var curBb = getBBoxWithTransform(elem, addSVGElementFromJson, pathActions$$1); + var curBb = getBBoxWithTransform(elem, addSVGElementFromJson, pathActions); + if (curBb) { var _offset = getStrokeOffsetForBBox(elem); + minX = Math.min(minX, curBb.x - _offset); - minY = Math.min(minY, curBb.y - _offset); - // TODO: The old code had this test for max, but not min. I suspect this test should be for both min and max + minY = Math.min(minY, curBb.y - _offset); // TODO: The old code had this test for max, but not min. I suspect this test should be for both min and max + if (elem.nodeType === 1) { maxX = Math.max(maxX, curBb.x + curBb.width + _offset); maxY = Math.max(maxY, curBb.y + curBb.height + _offset); @@ -8201,42 +9000,42 @@ fullBb.height = maxY - minY; return fullBb; }; - /** * Get all elements that have a BBox (excludes ``, ``, etc). * Note that 0-opacity, off-screen etc elements are still considered "visible" - * for this function + * for this function. * @function module:utilities.getVisibleElements - * @param {Element} parent - The parent DOM element to search within + * @param {Element} parentElement - The parent DOM element to search within * @returns {Element[]} All "visible" elements. */ - var getVisibleElements = function getVisibleElements(parent) { - if (!parent) { - parent = $$2(editorContext_$1.getSVGContent()).children(); // Prevent layers from being included + + var getVisibleElements = function getVisibleElements(parentElement) { + if (!parentElement) { + parentElement = $$2(editorContext_$1.getSVGContent()).children(); // Prevent layers from being included } var contentElems = []; - $$2(parent).children().each(function (i, elem) { + $$2(parentElement).children().each(function (i, elem) { if (elem.getBBox) { contentElems.push(elem); } }); return contentElems.reverse(); }; - /** - * Get the bounding box for one or more stroked and/or transformed elements + * Get the bounding box for one or more stroked and/or transformed elements. * @function module:utilities.getStrokedBBoxDefaultVisible * @param {Element[]} elems - Array with DOM elements to check * @returns {module:utilities.BBoxObject} A single bounding box object */ + var getStrokedBBoxDefaultVisible = function getStrokedBBoxDefaultVisible(elems) { if (!elems) { elems = getVisibleElements(); } + return getStrokedBBox(elems, editorContext_$1.addSVGElementFromJson, editorContext_$1.pathActions); }; - /** * Get the rotation angle of the given transform list. * @function module:utilities.getRotationAngleFromTransformList @@ -8244,50 +9043,57 @@ * @param {boolean} toRad - When true returns the value in radians rather than degrees * @returns {Float} The angle in degrees or radians */ + var getRotationAngleFromTransformList = function getRotationAngleFromTransformList(tlist, toRad) { if (!tlist) { return 0; } // <svg> elements have no tlist + + var N = tlist.numberOfItems; + for (var i = 0; i < N; ++i) { var xform = tlist.getItem(i); + if (xform.type === 4) { return toRad ? xform.angle * Math.PI / 180.0 : xform.angle; } } + return 0.0; }; - /** - * Get the rotation angle of the given/selected DOM element + * Get the rotation angle of the given/selected DOM element. * @function module:utilities.getRotationAngle * @param {Element} [elem] - DOM element to get the angle for. Default to first of selected elements. * @param {boolean} [toRad=false] - When true returns the value in radians rather than degrees * @returns {Float} The angle in degrees or radians */ + var getRotationAngle = function getRotationAngle(elem, toRad) { - var selected = elem || editorContext_$1.getSelectedElements()[0]; - // find the rotation transform (if any) and set it + // eslint-disable-line import/no-mutable-exports + var selected = elem || editorContext_$1.getSelectedElements()[0]; // find the rotation transform (if any) and set it + var tlist = getTransformList(selected); return getRotationAngleFromTransformList(tlist, toRad); }; - /** - * Get the reference element associated with the given attribute value + * Get the reference element associated with the given attribute value. * @function module:utilities.getRefElem * @param {string} attrVal - The attribute value as a string * @returns {Element} Reference element */ + var getRefElem = function getRefElem(attrVal) { return getElem(getUrlFromAttr(attrVal).substr(1)); }; - /** * Get a DOM element by ID within the SVG root element. * @function module:utilities.getElem * @param {string} id - String with the element's new ID - * @returns {Element} + * @returns {?Element} */ + var getElem = supportsSelectors() ? function (id) { // querySelector lookup return svgroot_.querySelector('#' + id); @@ -8300,7 +9106,6 @@ // jQuery lookup: twice as slow as xpath in FF return $$2(svgroot_).find('[id=' + id + ']')[0]; }; - /** * Assigns multiple attributes to an element. * @function module:utilities.assignAttributes @@ -8310,54 +9115,35 @@ * @param {boolean} [unitCheck=false] - Boolean to indicate the need to use units.setUnitAttr * @returns {undefined} */ + var assignAttributes = function assignAttributes(elem, attrs, suspendLength, unitCheck) { - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; + var _arr = Object.entries(attrs); - try { - for (var _iterator = Object.entries(attrs)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var _ref4 = _step.value; + for (var _i = 0; _i < _arr.length; _i++) { + var _arr$_i = _slicedToArray(_arr[_i], 2), + key = _arr$_i[0], + value = _arr$_i[1]; - var _ref5 = slicedToArray(_ref4, 2); + var ns = key.substr(0, 4) === 'xml:' ? NS.XML : key.substr(0, 6) === 'xlink:' ? NS.XLINK : null; - var key = _ref5[0]; - var value = _ref5[1]; - - var ns = key.substr(0, 4) === 'xml:' ? NS.XML : key.substr(0, 6) === 'xlink:' ? NS.XLINK : null; - - if (ns) { - elem.setAttributeNS(ns, key, value); - } else if (!unitCheck) { - elem.setAttribute(key, value); - } else { - setUnitAttr(elem, key, value); - } - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } + if (ns) { + elem.setAttributeNS(ns, key, value); + } else if (!unitCheck) { + elem.setAttribute(key, value); + } else { + setUnitAttr(elem, key, value); } } }; - /** - * Remove unneeded (default) attributes, makes resulting SVG smaller + * Remove unneeded (default) attributes, making resulting SVG smaller. * @function module:utilities.cleanupElement * @param {Element} element - DOM element to clean up * @returns {undefined} */ + var cleanupElement = function cleanupElement(element) { - var defaults$$1 = { + var defaults = { 'fill-opacity': 1, 'stop-opacity': 1, opacity: 1, @@ -8373,68 +9159,74 @@ if (element.nodeName === 'ellipse') { // Ellipse elements require rx and ry attributes - delete defaults$$1.rx; - delete defaults$$1.ry; + delete defaults.rx; + delete defaults.ry; } - for (var attr in defaults$$1) { - var val = defaults$$1[attr]; + Object.entries(defaults).forEach(function (_ref4) { + var _ref5 = _slicedToArray(_ref4, 2), + attr = _ref5[0], + val = _ref5[1]; + if (element.getAttribute(attr) === String(val)) { element.removeAttribute(attr); } - } + }); }; - /** - * Round value to for snapping + * Round value to for snapping. * @function module:utilities.snapToGrid * @param {Float} value * @returns {Integer} */ + var snapToGrid = function snapToGrid(value) { var unit = editorContext_$1.getBaseUnit(); var stepSize = editorContext_$1.getSnappingStep(); + if (unit !== 'px') { stepSize *= getTypeMap()[unit]; } + value = Math.round(value / stepSize) * stepSize; return value; }; - /** - * Escapes special characters in a regular expression + * Escapes special characters in a regular expression. * @function module:utilities.regexEscape * @param {string} str * @returns {string} */ + var regexEscape = function regexEscape(str) { // From: http://phpjs.org/functions return String(str).replace(new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\-]', 'g'), '\\$&'); }; - /** - * Prevents default browser click behaviour on the given element + * Prevents default browser click behaviour on the given element. * @function module:utilities.preventClickDefault * @param {Element} img - The DOM element to prevent the click on * @returns {undefined} */ + var preventClickDefault = function preventClickDefault(img) { $$2(img).click(function (e) { e.preventDefault(); }); }; - /** * @callback module:utilities.GetNextID * @returns {string} The ID */ + /** - * Create a clone of an element, updating its ID and its children's IDs when needed + * Create a clone of an element, updating its ID and its children's IDs when needed. * @function module:utilities.copyElem * @param {Element} el - DOM element to clone * @param {module:utilities.GetNextID} getNextId - The getter of the next unique ID. * @returns {Element} The cloned element */ + var copyElem = function copyElem(el, getNextId) { // manually create a copy of the element var newEl = document.createElementNS(el.namespaceURI, el.nodeName); @@ -8442,29 +9234,30 @@ if (attr.localName !== '-moz-math-font-style') { newEl.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value); } - }); - // set the copied element's new id - newEl.removeAttribute('id'); - newEl.id = getNextId(); + }); // set the copied element's new id - // Opera's "d" value needs to be reset for Opera/Win/non-EN + newEl.removeAttribute('id'); + newEl.id = getNextId(); // Opera's "d" value needs to be reset for Opera/Win/non-EN // Also needed for webkit (else does not keep curved segments on clone) + if (isWebkit() && el.nodeName === 'path') { var fixedD = convertPath(el); newEl.setAttribute('d', fixedD); - } + } // now create copies of all children + - // now create copies of all children $$2.each(el.childNodes, function (i, child) { switch (child.nodeType) { case 1: // element node newEl.append(copyElem(child, getNextId)); break; + case 3: // text node newEl.textContent = child.nodeValue; break; + default: break; } @@ -8481,8 +9274,18 @@ return newEl; }; + /** + * Whether a value is `null` or `undefined`. + * @param {Any} val + * @returns {boolean} + */ + + var isNullish = function isNullish(val) { + return val === null || val === undefined; + }; /* globals jQuery */ + /** * Adds context menu functionality * @module contextmenu @@ -8491,51 +9294,51 @@ */ // Dependencies: // 1) jQuery (for dom injection of context menus) - var $$3 = jQuery; - var contextMenuExtensions = {}; - /** * @function module:contextmenu.hasCustomHandler * @param {string} handlerKey * @returns {boolean} */ + var hasCustomHandler = function hasCustomHandler(handlerKey) { return Boolean(contextMenuExtensions[handlerKey]); }; - /** * @function module:contextmenu.getCustomHandler * @param {string} handlerKey * @returns {module:contextmenu.MenuItemAction} */ + var getCustomHandler = function getCustomHandler(handlerKey) { return contextMenuExtensions[handlerKey].action; }; - /** * @param {module:contextmenu.MenuItem} menuItem * @returns {undefined} */ + var injectExtendedContextMenuItemIntoDom = function injectExtendedContextMenuItemIntoDom(menuItem) { if (!Object.keys(contextMenuExtensions).length) { // all menuItems appear at the bottom of the menu in their own container. // if this is the first extension menu we need to add the separator. $$3('#cmenu_canvas').append("<li class='separator'>"); } + var shortcut = menuItem.shortcut || ''; $$3('#cmenu_canvas').append("<li class='disabled'><a href='#" + menuItem.id + "'>" + menuItem.label + "<span class='shortcut'>" + shortcut + '</span></a></li>'); }; - /** * @function module:contextmenu.injectExtendedContextMenuItemsIntoDom * @returns {undefined} */ + + var injectExtendedContextMenuItemsIntoDom = function injectExtendedContextMenuItemsIntoDom() { - for (var menuItem in contextMenuExtensions) { - injectExtendedContextMenuItemIntoDom(contextMenuExtensions[menuItem]); - } + Object.values(contextMenuExtensions).forEach(function (menuItem) { + injectExtendedContextMenuItemIntoDom(menuItem); + }); }; // MIT License @@ -8545,11 +9348,24 @@ * @module importModule */ + /** + * Converts a possible relative URL into an absolute one. + * @param {string} url + * @returns {string} + */ function toAbsoluteURL(url) { var a = document.createElement('a'); a.setAttribute('href', url); // <a href="hoge.html"> + return a.cloneNode(false).href; // -> "http://example.com/hoge.html" } + /** + * Add any of the whitelisted attributes to the script tag. + * @param {HTMLScriptElement} script + * @param {PlainObject.<string, string>} atts + * @returns {undefined} + */ + function addScriptAtts(script, atts) { ['id', 'class', 'type'].forEach(function (prop) { @@ -8557,85 +9373,86 @@ script[prop] = atts[prop]; } }); - } + } // Additions by Brett - // Additions by Brett /** * @typedef {PlainObject} module:importModule.ImportConfig * @property {string} global The variable name to set on `window` (when not using the modular version) * @property {boolean} [returnDefault=false] */ + /** * @function module:importModule.importSetGlobalDefault - * @param {string} url + * @param {string|string[]} url * @param {module:importModule.ImportConfig} config - * @returns {*} The return depends on the export of the targeted module. + * @returns {Promise} The value to which it resolves depends on the export of the targeted module. */ - var importSetGlobalDefault = function () { - var _ref = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(url, config) { + + + function importSetGlobalDefault(url, config) { + return importSetGlobal(url, _extends({}, config, { + returnDefault: true + })); + } + /** + * @function module:importModule.importSetGlobal + * @param {string|string[]} url + * @param {module:importModule.ImportConfig} config + * @returns {Promise} The promise resolves to either an `ArbitraryModule` or + * any other value depends on the export of the targeted module. + */ + + function importSetGlobal(_x, _x2) { + return _importSetGlobal.apply(this, arguments); + } + /** + * + * @author Brett Zamir (other items are from `dynamic-import-polyfill`) + * @param {string|string[]} url + * @param {PlainObject} [atts={}] + * @returns {Promise} Resolves to `undefined` or rejects with an `Error` upon a + * script loading error + */ + + function _importSetGlobal() { + _importSetGlobal = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee(url, _ref) { + var glob, returnDefault, modularVersion; return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: - return _context.abrupt('return', importSetGlobal(url, _extends({}, config, { returnDefault: true }))); + glob = _ref.global, returnDefault = _ref.returnDefault; + // Todo: Replace calls to this function with `import()` when supported + modularVersion = !('svgEditor' in window) || !window.svgEditor || window.svgEditor.modules !== false; - case 1: - case 'end': + if (!modularVersion) { + _context.next = 4; + break; + } + + return _context.abrupt("return", importModule(url, undefined, { + returnDefault: returnDefault + })); + + case 4: + _context.next = 6; + return importScript(url); + + case 6: + return _context.abrupt("return", window[glob]); + + case 7: + case "end": return _context.stop(); } } }, _callee, this); })); + return _importSetGlobal.apply(this, arguments); + } - return function importSetGlobalDefault(_x, _x2) { - return _ref.apply(this, arguments); - }; - }(); - /** - * @function module:importModule.importSetGlobal - * @param {string} url - * @param {module:importModule.ImportConfig} config - * @returns {ArbitraryModule|*} The return depends on the export of the targeted module. - */ - var importSetGlobal = function () { - var _ref3 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(url, _ref2) { - var global = _ref2.global, - returnDefault = _ref2.returnDefault; - var modularVersion; - return regeneratorRuntime.wrap(function _callee2$(_context2) { - while (1) { - switch (_context2.prev = _context2.next) { - case 0: - // Todo: Replace calls to this function with `import()` when supported - modularVersion = !('svgEditor' in window) || !window.svgEditor || window.svgEditor.modules !== false; - - if (!modularVersion) { - _context2.next = 3; - break; - } - - return _context2.abrupt('return', importModule(url, undefined, { returnDefault: returnDefault })); - - case 3: - _context2.next = 5; - return importScript(url); - - case 5: - return _context2.abrupt('return', window[global]); - - case 6: - case 'end': - return _context2.stop(); - } - } - }, _callee2, this); - })); - - return function importSetGlobal(_x3, _x4) { - return _ref3.apply(this, arguments); - }; - }(); - // Addition by Brett function importScript(url) { var atts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; @@ -8644,77 +9461,314 @@ return importScript(u, atts); })); } + return new Promise(function (resolve, reject) { + // eslint-disable-line promise/avoid-new var script = document.createElement('script'); + /** + * + * @returns {undefined} + */ + + function scriptOnError() { + reject(new Error("Failed to import: ".concat(url))); + destructor(); + } + /** + * + * @returns {undefined} + */ + + + function scriptOnLoad() { + resolve(); + destructor(); + } + var destructor = function destructor() { - script.onerror = null; - script.onload = null; + script.removeEventListener('error', scriptOnError); + script.removeEventListener('load', scriptOnLoad); script.remove(); script.src = ''; }; + script.defer = 'defer'; addScriptAtts(script, atts); - script.onerror = function () { - reject(new Error('Failed to import: ' + url)); - destructor(); - }; - script.onload = function () { - resolve(); - destructor(); - }; + script.addEventListener('error', scriptOnError); + script.addEventListener('load', scriptOnLoad); script.src = url; - document.head.append(script); }); } + /** + * + * @param {string|string[]} url + * @param {PlainObject} [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. + */ function importModule(url) { var atts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - var _ref4 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, - _ref4$returnDefault = _ref4.returnDefault, - returnDefault = _ref4$returnDefault === undefined ? false : _ref4$returnDefault; + var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, + _ref2$returnDefault = _ref2.returnDefault, + returnDefault = _ref2$returnDefault === void 0 ? false : _ref2$returnDefault; if (Array.isArray(url)) { return Promise.all(url.map(function (u) { return importModule(u, atts); })); } + return new Promise(function (resolve, reject) { + // eslint-disable-line promise/avoid-new var vector = '$importModule$' + Math.random().toString(32).slice(2); var script = document.createElement('script'); + /** + * + * @returns {undefined} + */ + + function scriptOnError() { + reject(new Error("Failed to import: ".concat(url))); + destructor(); + } + /** + * + * @returns {undefined} + */ + + + function scriptOnLoad() { + resolve(window[vector]); + destructor(); + } + var destructor = function destructor() { delete window[vector]; - script.onerror = null; - script.onload = null; + script.removeEventListener('error', scriptOnError); + script.removeEventListener('load', scriptOnLoad); script.remove(); URL.revokeObjectURL(script.src); script.src = ''; }; + addScriptAtts(script, atts); script.defer = 'defer'; script.type = 'module'; - script.onerror = function () { - reject(new Error('Failed to import: ' + url)); - destructor(); - }; - script.onload = function () { - resolve(window[vector]); - destructor(); - }; + script.addEventListener('error', scriptOnError); + script.addEventListener('load', scriptOnLoad); var absURL = toAbsoluteURL(url); - var loader = 'import * as m from \'' + absURL.replace(/'/g, "\\'") + '\'; window.' + vector + ' = ' + (returnDefault ? 'm.default || ' : '') + 'm;'; // export Module - var blob = new Blob([loader], { type: 'text/javascript' }); - script.src = URL.createObjectURL(blob); + var loader = "import * as m from '".concat(absURL.replace(/'/g, "\\'"), "'; window.").concat(vector, " = ").concat(returnDefault ? 'm.default || ' : '', "m;"); // export Module + var blob = new Blob([loader], { + type: 'text/javascript' + }); + script.src = URL.createObjectURL(blob); document.head.append(script); }); } - /* globals jQuery */ + /** + * @module jQueryPluginDBox + */ + + /** + * @param {external:jQuery} $ + * @param {PlainObject} [strings] + * @param {PlainObject} [strings.ok] + * @param {PlainObject} [strings.cancel] + * @returns {external:jQuery} + */ + function jQueryPluginDBox($) { + var strings = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { + ok: 'Ok', + cancel: 'Cancel' + }; + // This sets up alternative dialog boxes. They mostly work the same way as + // their UI counterparts, expect instead of returning the result, a callback + // needs to be included that returns the result as its first parameter. + // In the future we may want to add additional types of dialog boxes, since + // they should be easy to handle this way. + $('#dialog_container').draggable({ + cancel: '#dialog_content, #dialog_buttons *', + containment: 'window' + }).css('position', 'absolute'); + var box = $('#dialog_box'), + btnHolder = $('#dialog_buttons'), + dialogContent = $('#dialog_content'); + /** + * Resolves to `false` (if cancelled), for prompts and selects + * without checkboxes, it resolves to the value of the form control. For other + * types without checkboxes, it resolves to `true`. For checkboxes, it resolves + * to an object with the `response` key containing the same value as the previous + * mentioned (string or `true`) and a `checked` (boolean) property. + * @typedef {Promise} module:jQueryPluginDBox.PromiseResult + */ + + /** + * @typedef {PlainObject} module:jQueryPluginDBox.SelectOption + * @property {string} text + * @property {string} value + */ + + /** + * @typedef {PlainObject} module:jQueryPluginDBox.CheckboxInfo + * @property {string} label Label for the checkbox + * @property {string} value Value of the checkbox + * @property {string} tooltip Tooltip on the checkbox label + * @property {boolean} checked Whether the checkbox is checked by default + */ + + /** + * Triggered upon a change of value for the select pull-down. + * @callback module:jQueryPluginDBox.SelectChangeListener + * @returns {undefined} + */ + + /** + * @param {"alert"|"prompt"|"select"|"process"} type + * @param {string} msg + * @param {string} [defaultVal] + * @param {module:jQueryPluginDBox.SelectOption[]} [opts] + * @param {module:jQueryPluginDBox.SelectChangeListener} [changeListener] + * @param {module:jQueryPluginDBox.CheckboxInfo} [checkbox] + * @returns {jQueryPluginDBox.PromiseResult} + */ + + function dbox(type, msg, defaultVal, opts, changeListener, checkbox) { + dialogContent.html('<p>' + msg.replace(/\n/g, '</p><p>') + '</p>').toggleClass('prompt', type === 'prompt'); + btnHolder.empty(); + var ok = $('<input type="button" value="' + strings.ok + '">').appendTo(btnHolder); + return new Promise(function (resolve, reject) { + // eslint-disable-line promise/avoid-new + if (type !== 'alert') { + $('<input type="button" value="' + strings.cancel + '">').appendTo(btnHolder).click(function () { + box.hide(); + resolve(false); + }); + } + + var ctrl, chkbx; + + if (type === 'prompt') { + ctrl = $('<input type="text">').prependTo(btnHolder); + ctrl.val(defaultVal || ''); + ctrl.bind('keydown', 'return', function () { + ok.click(); + }); + } else if (type === 'select') { + var div = $('<div style="text-align:center;">'); + ctrl = $('<select>').appendTo(div); + + if (checkbox) { + var label = $('<label>').text(checkbox.label); + chkbx = $('<input type="checkbox">').appendTo(label); + chkbx.val(checkbox.value); + + if (checkbox.tooltip) { + label.attr('title', checkbox.tooltip); + } + + chkbx.prop('checked', Boolean(checkbox.checked)); + div.append($('<div>').append(label)); + } + + $.each(opts || [], function (opt, val) { + if (_typeof(val) === 'object') { + ctrl.append($('<option>').val(val.value).html(val.text)); + } else { + ctrl.append($('<option>').html(val)); + } + }); + dialogContent.append(div); + + if (defaultVal) { + ctrl.val(defaultVal); + } + + if (changeListener) { + ctrl.bind('change', 'return', changeListener); + } + + ctrl.bind('keydown', 'return', function () { + ok.click(); + }); + } else if (type === 'process') { + ok.hide(); + } + + box.show(); + ok.click(function () { + box.hide(); + var response = type === 'prompt' || type === 'select' ? ctrl.val() : true; + + if (chkbx) { + resolve({ + response: response, + checked: chkbx.prop('checked') + }); + return; + } + + resolve(response); + }).focus(); + + if (type === 'prompt' || type === 'select') { + ctrl.focus(); + } + }); + } + /** + * @param {string} msg Message to alert + * @returns {jQueryPluginDBox.PromiseResult} + */ + + + $.alert = function (msg) { + return dbox('alert', msg); + }; + /** + * @param {string} msg Message for which to ask confirmation + * @returns {jQueryPluginDBox.PromiseResult} + */ + + + $.confirm = function (msg) { + return dbox('confirm', msg); + }; + /** + * @param {string} msg Message to indicate upon cancelable indicator + * @returns {jQueryPluginDBox.PromiseResult} + */ + + + $.process_cancel = function (msg) { + return dbox('process', msg); + }; + /** + * @param {string} msg Message to accompany the prompt + * @param {string} [defaultText=''] The default text to show for the prompt + * @returns {jQueryPluginDBox.PromiseResult} + */ + + + $.prompt = function (msg) { + var defaultText = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + return dbox('prompt', msg, defaultText); + }; + + $.select = function (msg, opts, changeListener, txt, checkbox) { + return dbox('select', msg, txt, opts, changeListener, checkbox); + }; + + return $; + } var $$4 = jQuery; - /** * This class encapsulates the concept of a layer in the drawing. It can be constructed with * an existing group element or, with three parameters, will create a new layer group element. @@ -8726,7 +9780,9 @@ * @memberof module:layer */ - var Layer = function () { + var Layer = + /*#__PURE__*/ + function () { /** * @param {string} name - Layer name * @param {SVGGElement|null} group - An existing SVG group element or null. @@ -8737,7 +9793,7 @@ * a new layer to the document. */ function Layer(name, group, svgElem) { - classCallCheck(this, Layer); + _classCallCheck(this, Layer); this.name_ = name; this.group_ = svgElem ? null : group; @@ -8749,6 +9805,7 @@ var layerTitle = svgdoc.createElementNS(NS.SVG, 'title'); layerTitle.textContent = name; this.group_.append(layerTitle); + if (group) { $$4(group).after(this.group_); } else { @@ -8760,55 +9817,49 @@ walkTree(this.group_, function (e) { e.setAttribute('style', 'pointer-events:inherit'); }); - this.group_.setAttribute('style', svgElem ? 'pointer-events:all' : 'pointer-events:none'); } - /** * Get the layer's name. * @returns {string} The layer name */ - createClass(Layer, [{ - key: 'getName', + _createClass(Layer, [{ + key: "getName", value: function getName() { return this.name_; } - /** * Get the group element for this layer. * @returns {SVGGElement} The layer SVG group */ }, { - key: 'getGroup', + key: "getGroup", value: function getGroup() { return this.group_; } - /** * Active this layer so it takes pointer events. * @returns {undefined} */ }, { - key: 'activate', + key: "activate", value: function activate() { this.group_.setAttribute('style', 'pointer-events:all'); } - /** * Deactive this layer so it does NOT take pointer events. * @returns {undefined} */ }, { - key: 'deactivate', + key: "deactivate", value: function deactivate() { this.group_.setAttribute('style', 'pointer-events:none'); } - /** * Set this layer visible or hidden based on 'visible' parameter. * @param {boolean} visible - If true, make visible; otherwise, hide it. @@ -8816,41 +9867,41 @@ */ }, { - key: 'setVisible', + key: "setVisible", value: function setVisible(visible) { var expected = visible === undefined || visible ? 'inline' : 'none'; var oldDisplay = this.group_.getAttribute('display'); + if (oldDisplay !== expected) { this.group_.setAttribute('display', expected); } } - /** * Is this layer visible? * @returns {boolean} True if visible. */ }, { - key: 'isVisible', + key: "isVisible", value: function isVisible() { return this.group_.getAttribute('display') !== 'none'; } - /** * Get layer opacity. * @returns {Float} Opacity value. */ }, { - key: 'getOpacity', + key: "getOpacity", value: function getOpacity() { var opacity = this.group_.getAttribute('opacity'); - if (opacity === null || opacity === undefined) { + + if (isNullish(opacity)) { return 1; } + return parseFloat(opacity); } - /** * Sets the opacity of this layer. If opacity is not a value between 0.0 and 1.0, * nothing happens. @@ -8859,13 +9910,12 @@ */ }, { - key: 'setOpacity', + key: "setOpacity", value: function setOpacity(opacity) { if (typeof opacity === 'number' && opacity >= 0.0 && opacity <= 1.0) { this.group_.setAttribute('opacity', opacity); } } - /** * Append children to this layer. * @param {SVGGElement} children - The children to append to this layer. @@ -8873,30 +9923,31 @@ */ }, { - key: 'appendChildren', + key: "appendChildren", value: function appendChildren(children) { for (var i = 0; i < children.length; ++i) { this.group_.append(children[i]); } } - /** * @returns {SVGTitleElement|null} */ }, { - key: 'getTitleElement', + key: "getTitleElement", value: function getTitleElement() { var len = this.group_.childNodes.length; + for (var i = 0; i < len; ++i) { var child = this.group_.childNodes.item(i); + if (child && child.tagName === 'title') { return child; } } + return null; } - /** * Set the name of this layer. * @param {string} name - The new name. @@ -8905,32 +9956,36 @@ */ }, { - key: 'setName', + key: "setName", value: function setName(name, hrService) { var previousName = this.name_; - name = toXml(name); - // now change the underlying title element contents + name = toXml(name); // now change the underlying title element contents + var title = this.getTitleElement(); + if (title) { $$4(title).empty(); title.textContent = name; this.name_ = name; + if (hrService) { - hrService.changeElement(title, { '#text': previousName }); + hrService.changeElement(title, { + '#text': previousName + }); } + return this.name_; } + return null; } - /** * Remove this layer's group from the DOM. No more functions on group can be called after this. - * @param {SVGGElement} children - The children to append to this layer. * @returns {SVGGElement} The layer SVG group that was just removed. */ }, { - key: 'removeGroup', + key: "removeGroup", value: function removeGroup() { var parent = this.group_.parentNode; var group = parent.removeChild(this.group_); @@ -8938,6 +9993,7 @@ return group; } }]); + return Layer; }(); /** @@ -8946,34 +10002,28 @@ Layer.CLASS_NAME = 'layer'; - /** * @property {RegExp} CLASS_REGEX - Used to test presence of class Layer.CLASS_NAME */ - Layer.CLASS_REGEX = new RegExp('(\\s|^)' + Layer.CLASS_NAME + '(\\s|$)'); + Layer.CLASS_REGEX = new RegExp('(\\s|^)' + Layer.CLASS_NAME + '(\\s|$)'); /** * Add class `Layer.CLASS_NAME` to the element (usually `class='layer'`). * * @param {SVGGElement} elem - The SVG element to update * @returns {undefined} */ + function addLayerClass(elem) { var classes = elem.getAttribute('class'); - if (classes === null || classes === undefined || !classes.length) { + + if (isNullish(classes) || !classes.length) { elem.setAttribute('class', Layer.CLASS_NAME); } else if (!Layer.CLASS_REGEX.test(classes)) { elem.setAttribute('class', classes + ' ' + Layer.CLASS_NAME); } } - /** - * HistoryRecordingService component of history - * @module history - * @license MIT - * @copyright 2016 Flint O'Brien - */ - /** * History recording service. * @@ -9007,20 +10057,21 @@ * @memberof module:history */ - var HistoryRecordingService = function () { + var HistoryRecordingService = + /*#__PURE__*/ + function () { /** * @param {history.UndoManager|null} undoManager - The undo manager. * A value of `null` is valid for cases where no history recording is required. * See singleton: {@link module:history.HistoryRecordingService.HistoryRecordingService.NO_HISTORY} */ function HistoryRecordingService(undoManager) { - classCallCheck(this, HistoryRecordingService); + _classCallCheck(this, HistoryRecordingService); this.undoManager_ = undoManager; this.currentBatchCommand_ = null; this.batchCommandStack_ = []; } - /** * Start a batch command so multiple commands can recorded as a single history command. * Requires a corresponding call to endBatchCommand. Start and end commands can be nested. @@ -9030,41 +10081,41 @@ */ - createClass(HistoryRecordingService, [{ - key: 'startBatchCommand', + _createClass(HistoryRecordingService, [{ + key: "startBatchCommand", value: function startBatchCommand(text) { if (!this.undoManager_) { return this; } + this.currentBatchCommand_ = new BatchCommand(text); this.batchCommandStack_.push(this.currentBatchCommand_); return this; } - /** * End a batch command and add it to the history or a parent batch command. * @returns {module:history.HistoryRecordingService} */ }, { - key: 'endBatchCommand', + key: "endBatchCommand", value: function endBatchCommand() { if (!this.undoManager_) { return this; } + if (this.currentBatchCommand_) { var batchCommand = this.currentBatchCommand_; this.batchCommandStack_.pop(); - var length = this.batchCommandStack_.length; - - this.currentBatchCommand_ = length ? this.batchCommandStack_[length - 1] : null; + var len = this.batchCommandStack_.length; + this.currentBatchCommand_ = len ? this.batchCommandStack_[len - 1] : null; this.addCommand_(batchCommand); } + return this; } - /** - * Add a MoveElementCommand to the history or current batch command + * Add a `MoveElementCommand` to the history or current batch command. * @param {Element} elem - The DOM element that was moved * @param {Element} oldNextSibling - The element's next sibling before it was moved * @param {Element} oldParent - The element's parent before it was moved @@ -9073,34 +10124,34 @@ */ }, { - key: 'moveElement', + key: "moveElement", value: function moveElement(elem, oldNextSibling, oldParent, text) { if (!this.undoManager_) { return this; } + this.addCommand_(new MoveElementCommand(elem, oldNextSibling, oldParent, text)); return this; } - /** - * Add an InsertElementCommand to the history or current batch command + * Add an `InsertElementCommand` to the history or current batch command. * @param {Element} elem - The DOM element that was added * @param {string} [text] - An optional string visible to user related to this change * @returns {module:history.HistoryRecordingService} */ }, { - key: 'insertElement', + key: "insertElement", value: function insertElement(elem, text) { if (!this.undoManager_) { return this; } + this.addCommand_(new InsertElementCommand(elem, text)); return this; } - /** - * Add a RemoveElementCommand to the history or current batch command + * Add a `RemoveElementCommand` to the history or current batch command. * @param {Element} elem - The DOM element that was removed * @param {Element} oldNextSibling - The element's next sibling before it was removed * @param {Element} oldParent - The element's parent before it was removed @@ -9109,17 +10160,17 @@ */ }, { - key: 'removeElement', + key: "removeElement", value: function removeElement(elem, oldNextSibling, oldParent, text) { if (!this.undoManager_) { return this; } + this.addCommand_(new RemoveElementCommand(elem, oldNextSibling, oldParent, text)); return this; } - /** - * Add a ChangeElementCommand to the history or current batch command + * Add a `ChangeElementCommand` to the history or current batch command. * @param {Element} elem - The DOM element that was changed * @param {module:history.CommandAttributes} attrs - An object with the attributes to be changed and the values they had *before* the change * @param {string} [text] - An optional string visible to user related to this change @@ -9127,35 +10178,39 @@ */ }, { - key: 'changeElement', + key: "changeElement", value: function changeElement(elem, attrs, text) { if (!this.undoManager_) { return this; } + this.addCommand_(new ChangeElementCommand(elem, attrs, text)); return this; } - /** * Private function to add a command to the history or current batch command. * @private * @param {Command} cmd - * @returns {module:history.HistoryRecordingService} + * @returns {module:history.HistoryRecordingService|undefined} */ }, { - key: 'addCommand_', + key: "addCommand_", value: function addCommand_(cmd) { if (!this.undoManager_) { return this; } + if (this.currentBatchCommand_) { this.currentBatchCommand_.addSubCommand(cmd); } else { this.undoManager_.addCommandToHistory(cmd); } + + return undefined; } }]); + return HistoryRecordingService; }(); /** @@ -9166,59 +10221,60 @@ HistoryRecordingService.NO_HISTORY = new HistoryRecordingService(); - /* globals jQuery */ - var $$5 = jQuery; - var visElems$1 = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use'.split(','); - var RandomizeModes = { LET_DOCUMENT_DECIDE: 0, ALWAYS_RANDOMIZE: 1, NEVER_RANDOMIZE: 2 }; - var randIds = RandomizeModes.LET_DOCUMENT_DECIDE; - // Array with current disabled elements (for in-group editing) - var disabledElems = []; + var randIds = RandomizeModes.LET_DOCUMENT_DECIDE; // Array with current disabled elements (for in-group editing) + var disabledElems = []; /** * Get a HistoryRecordingService. * @param {module:history.HistoryRecordingService} [hrService] - if exists, return it instead of creating a new service. * @returns {module:history.HistoryRecordingService} */ + function historyRecordingService(hrService) { return hrService || new HistoryRecordingService(canvas_.undoMgr); } - /** * Find the layer name in a group element. * @param {Element} group The group element to search in. * @returns {string} The layer name or empty string. */ + + function findLayerNameInGroup(group) { - return $$5('title', group).text() || (isOpera() && group.querySelectorAll - // Hack for Opera 10.60 + return $$5('title', group).text() || (isOpera() && group.querySelectorAll // Hack for Opera 10.60 ? $$5(group.querySelectorAll('title')).text() : ''); } - /** * Given a set of names, return a new unique name. * @param {string[]} existingLayerNames - Existing layer names. * @returns {string} - The new name. */ + + function getNewLayerName(existingLayerNames) { - var i = 1; - // TODO(codedread): What about internationalization of "Layer"? + var i = 1; // TODO(codedread): What about internationalization of "Layer"? + while (existingLayerNames.includes('Layer ' + i)) { i++; } + return 'Layer ' + i; } - /** - * This class encapsulates the concept of a SVG-edit drawing + * This class encapsulates the concept of a SVG-edit drawing. */ - var Drawing = function () { + + + var Drawing = + /*#__PURE__*/ + function () { /** * @param {SVGSVGElement} svgElem - The SVG DOM Element that this JS object * encapsulates. If the svgElem has a se:nonce attribute on it, then @@ -9227,44 +10283,44 @@ * @throws {Error} If not initialized with an SVG element */ function Drawing(svgElem, optIdPrefix) { - classCallCheck(this, Drawing); + _classCallCheck(this, Drawing); if (!svgElem || !svgElem.tagName || !svgElem.namespaceURI || svgElem.tagName !== 'svg' || svgElem.namespaceURI !== NS.SVG) { throw new Error('Error: svgedit.draw.Drawing instance initialized without a <svg> element'); } - /** * The SVG DOM Element that represents this drawing. * @type {SVGSVGElement} */ - this.svgElem_ = svgElem; + + this.svgElem_ = svgElem; /** * The latest object number used in this drawing. * @type {Integer} */ - this.obj_num = 0; + this.obj_num = 0; /** * The prefix to prepend to each element id in the drawing. * @type {string} */ - this.idPrefix = optIdPrefix || 'svg_'; + this.idPrefix = optIdPrefix || 'svg_'; /** * An array of released element ids to immediately reuse. * @type {Integer[]} */ - this.releasedNums = []; + this.releasedNums = []; /** * The z-ordered array of Layer objects. Each layer has a name * and group element. * The first layer is the one at the bottom of the rendering. * @type {Layer[]} */ - this.all_layers = []; + this.all_layers = []; /** * Map of all_layers by name. * @@ -9273,142 +10329,139 @@ * * @type {PlainObject.<string, Layer>} */ - this.layer_map = {}; + this.layer_map = {}; /** * The current layer being used. * @type {Layer} */ - this.current_layer = null; + this.current_layer = null; /** * The nonce to use to uniquely identify elements across drawings. * @type {!String} */ + this.nonce_ = ''; - var n = this.svgElem_.getAttributeNS(NS.SE, 'nonce'); - // If already set in the DOM, use the nonce throughout the document + var n = this.svgElem_.getAttributeNS(NS.SE, 'nonce'); // If already set in the DOM, use the nonce throughout the document // else, if randomizeIds(true) has been called, create and set the nonce. - if (!!n && randIds !== RandomizeModes.NEVER_RANDOMIZE) { + + if (n && randIds !== RandomizeModes.NEVER_RANDOMIZE) { this.nonce_ = n; } else if (randIds === RandomizeModes.ALWAYS_RANDOMIZE) { this.setNonce(Math.floor(Math.random() * 100001)); } } - /** * @param {string} id Element ID to retrieve * @returns {Element} SVG element within the root SVGSVGElement */ - createClass(Drawing, [{ - key: 'getElem_', + _createClass(Drawing, [{ + key: "getElem_", value: function getElem_(id) { if (this.svgElem_.querySelector) { // querySelector lookup return this.svgElem_.querySelector('#' + id); - } - // jQuery lookup: twice as slow as xpath in FF + } // jQuery lookup: twice as slow as xpath in FF + + return $$5(this.svgElem_).find('[id=' + id + ']')[0]; } - /** * @returns {SVGSVGElement} */ }, { - key: 'getSvgElem', + key: "getSvgElem", value: function getSvgElem() { return this.svgElem_; } - /** * @returns {!(string|Integer)} The previously set nonce */ }, { - key: 'getNonce', + key: "getNonce", value: function getNonce() { return this.nonce_; } - /** * @param {!(string|Integer)} n The nonce to set * @returns {undefined} */ }, { - key: 'setNonce', + key: "setNonce", value: function setNonce(n) { this.svgElem_.setAttributeNS(NS.XMLNS, 'xmlns:se', NS.SE); this.svgElem_.setAttributeNS(NS.SE, 'se:nonce', n); this.nonce_ = n; } - /** - * Clears any previously set nonce + * Clears any previously set nonce. * @returns {undefined} */ }, { - key: 'clearNonce', + key: "clearNonce", value: function clearNonce() { // We deliberately leave any se:nonce attributes alone, // we just don't use it to randomize ids. this.nonce_ = ''; } - /** * Returns the latest object id as a string. * @returns {string} The latest object Id. */ }, { - key: 'getId', + key: "getId", value: function getId() { return this.nonce_ ? this.idPrefix + this.nonce_ + '_' + this.obj_num : this.idPrefix + this.obj_num; } - /** * Returns the next object Id as a string. * @returns {string} The next object Id to use. */ }, { - key: 'getNextId', + key: "getNextId", value: function getNextId() { var oldObjNum = this.obj_num; - var restoreOldObjNum = false; - - // If there are any released numbers in the release stack, + var restoreOldObjNum = false; // If there are any released numbers in the release stack, // use the last one instead of the next obj_num. // We need to temporarily use obj_num as that is what getId() depends on. + if (this.releasedNums.length > 0) { this.obj_num = this.releasedNums.pop(); restoreOldObjNum = true; } else { // If we are not using a released id, then increment the obj_num. this.obj_num++; - } + } // Ensure the ID does not exist. + - // Ensure the ID does not exist. var id = this.getId(); + while (this.getElem_(id)) { if (restoreOldObjNum) { this.obj_num = oldObjNum; restoreOldObjNum = false; } + this.obj_num++; id = this.getId(); - } - // Restore the old object number if required. + } // Restore the old object number if required. + + if (restoreOldObjNum) { this.obj_num = oldObjNum; } + return id; } - /** * Releases the object Id, letting it be used as the next id in getNextId(). * This method DOES NOT remove any elements from the DOM, it is expected @@ -9418,51 +10471,48 @@ */ }, { - key: 'releaseId', + key: "releaseId", value: function releaseId(id) { // confirm if this is a valid id for this Document, else return false var front = this.idPrefix + (this.nonce_ ? this.nonce_ + '_' : ''); + if (typeof id !== 'string' || !id.startsWith(front)) { return false; - } - // extract the obj_num of this id - var num = parseInt(id.substr(front.length), 10); + } // extract the obj_num of this id - // if we didn't get a positive number or we already released this number + + var num = parseInt(id.substr(front.length)); // if we didn't get a positive number or we already released this number // then return false. + if (typeof num !== 'number' || num <= 0 || this.releasedNums.includes(num)) { return false; - } + } // push the released number into the released queue + - // push the released number into the released queue this.releasedNums.push(num); - return true; } - /** * Returns the number of layers in the current drawing. * @returns {Integer} The number of layers in the current drawing. */ }, { - key: 'getNumLayers', + key: "getNumLayers", value: function getNumLayers() { return this.all_layers.length; } - /** - * Check if layer with given name already exists + * Check if layer with given name already exists. * @param {string} name - The layer name to check * @returns {boolean} */ }, { - key: 'hasLayer', + key: "hasLayer", value: function hasLayer(name) { return this.layer_map[name] !== undefined; } - /** * Returns the name of the ith layer. If the index is out of range, an empty string is returned. * @param {Integer} i - The zero-based index of the layer you are querying. @@ -9470,33 +10520,31 @@ */ }, { - key: 'getLayerName', + key: "getLayerName", value: function getLayerName(i) { return i >= 0 && i < this.getNumLayers() ? this.all_layers[i].getName() : ''; } - /** * @returns {SVGGElement|null} The SVGGElement representing the current layer. */ }, { - key: 'getCurrentLayer', + key: "getCurrentLayer", value: function getCurrentLayer() { return this.current_layer ? this.current_layer.getGroup() : null; } - /** * Get a layer by name. + * @param {string} name * @returns {SVGGElement} The SVGGElement representing the named layer or null. */ }, { - key: 'getLayerByName', + key: "getLayerByName", value: function getLayerByName(name) { var layer = this.layer_map[name]; return layer ? layer.getGroup() : null; } - /** * Returns the name of the currently selected layer. If an error occurs, an empty string * is returned. @@ -9504,11 +10552,10 @@ */ }, { - key: 'getCurrentLayerName', + key: "getCurrentLayerName", value: function getCurrentLayerName() { return this.current_layer ? this.current_layer.getName() : ''; } - /** * Set the current layer's name. * @param {string} name - The new name. @@ -9517,20 +10564,22 @@ */ }, { - key: 'setCurrentLayerName', + key: "setCurrentLayerName", value: function setCurrentLayerName(name, hrService) { var finalName = null; + if (this.current_layer) { var oldName = this.current_layer.getName(); finalName = this.current_layer.setName(name, hrService); + if (finalName) { delete this.layer_map[oldName]; this.layer_map[finalName] = this.current_layer; } } + return finalName; } - /** * Set the current layer's position. * @param {Integer} newpos - The zero-based index of the new position of the layer. Range should be 0 to layers-1 @@ -9538,20 +10587,23 @@ */ }, { - key: 'setCurrentLayerPosition', + key: "setCurrentLayerPosition", value: function setCurrentLayerPosition(newpos) { var layerCount = this.getNumLayers(); + if (!this.current_layer || newpos < 0 || newpos >= layerCount) { return null; } - var oldpos = void 0; + var oldpos; + for (oldpos = 0; oldpos < layerCount; ++oldpos) { if (this.all_layers[oldpos] === this.current_layer) { break; } - } - // some unknown error condition (current_layer not in all_layers) + } // some unknown error condition (current_layer not in all_layers) + + if (oldpos === layerCount) { return null; } @@ -9560,66 +10612,70 @@ // if our new position is below us, we need to insert before the node after newpos var currentGroup = this.current_layer.getGroup(); var oldNextSibling = currentGroup.nextSibling; - var refGroup = null; + if (newpos > oldpos) { if (newpos < layerCount - 1) { refGroup = this.all_layers[newpos + 1].getGroup(); - } - // if our new position is above us, we need to insert before the node at newpos + } // if our new position is above us, we need to insert before the node at newpos + } else { refGroup = this.all_layers[newpos].getGroup(); } + this.svgElem_.insertBefore(currentGroup, refGroup); // Ok to replace with `refGroup.before(currentGroup);`? this.identifyLayers(); this.setCurrentLayer(this.getLayerName(newpos)); - return { currentGroup: currentGroup, oldNextSibling: oldNextSibling }; } + return null; } - /** * @param {module:history.HistoryRecordingService} hrService * @returns {undefined} */ }, { - key: 'mergeLayer', + key: "mergeLayer", value: function mergeLayer(hrService) { var currentGroup = this.current_layer.getGroup(); var prevGroup = $$5(currentGroup).prev()[0]; + if (!prevGroup) { return; } hrService.startBatchCommand('Merge Layer'); - var layerNextSibling = currentGroup.nextSibling; hrService.removeElement(currentGroup, layerNextSibling, this.svgElem_); while (currentGroup.firstChild) { var child = currentGroup.firstChild; + if (child.localName === 'title') { hrService.removeElement(child, child.nextSibling, currentGroup); child.remove(); continue; } + var oldNextSibling = child.nextSibling; prevGroup.append(child); hrService.moveElement(child, oldNextSibling, currentGroup); - } + } // Remove current layer's group + + + this.current_layer.removeGroup(); // Remove the current layer and set the previous layer as the new current layer - // Remove current layer's group - this.current_layer.removeGroup(); - // Remove the current layer and set the previous layer as the new current layer var index = this.all_layers.indexOf(this.current_layer); + if (index > 0) { var _name = this.current_layer.getName(); + this.current_layer = this.all_layers[index - 1]; this.all_layers.splice(index, 1); delete this.layer_map[_name]; @@ -9627,25 +10683,24 @@ hrService.endBatchCommand(); } - /** * @param {module:history.HistoryRecordingService} hrService * @returns {undefined} */ }, { - key: 'mergeAllLayers', + key: "mergeAllLayers", value: function mergeAllLayers(hrService) { // Set the current layer to the last layer. this.current_layer = this.all_layers[this.all_layers.length - 1]; - hrService.startBatchCommand('Merge all Layers'); + while (this.all_layers.length > 1) { this.mergeLayer(hrService); } + hrService.endBatchCommand(); } - /** * Sets the current layer. If the name is not a valid layer name, then this * function returns `false`. Otherwise it returns `true`. This is not an @@ -9655,20 +10710,22 @@ */ }, { - key: 'setCurrentLayer', + key: "setCurrentLayer", value: function setCurrentLayer(name) { var layer = this.layer_map[name]; + if (layer) { if (this.current_layer) { this.current_layer.deactivate(); } + this.current_layer = layer; this.current_layer.activate(); return true; } + return false; } - /** * Deletes the current layer from the drawing and then clears the selection. * This function then calls the 'changed' handler. This is an undoable action. @@ -9677,16 +10734,16 @@ */ }, { - key: 'deleteCurrentLayer', + key: "deleteCurrentLayer", value: function deleteCurrentLayer() { if (this.current_layer && this.getNumLayers() > 1) { var oldLayerGroup = this.current_layer.removeGroup(); this.identifyLayers(); return oldLayerGroup; } + return null; } - /** * Updates layer system and sets the current layer to the * top-most layer (last `<g>` child of this drawing). @@ -9694,23 +10751,26 @@ */ }, { - key: 'identifyLayers', + key: "identifyLayers", value: function identifyLayers() { this.all_layers = []; this.layer_map = {}; - var numchildren = this.svgElem_.childNodes.length; - // loop through all children of SVG element + var numchildren = this.svgElem_.childNodes.length; // loop through all children of SVG element + var orphans = [], layernames = []; var layer = null; var childgroups = false; + for (var i = 0; i < numchildren; ++i) { - var child = this.svgElem_.childNodes.item(i); - // for each g, find its layer name + var child = this.svgElem_.childNodes.item(i); // for each g, find its layer name + if (child && child.nodeType === 1) { if (child.tagName === 'g') { childgroups = true; + var _name2 = findLayerNameInGroup(child); + if (_name2) { layernames.push(_name2); layer = new Layer(_name2, child); @@ -9725,9 +10785,9 @@ orphans.push(child); } } - } + } // If orphans or no layers found, create a new layer and add all the orphans to it + - // If orphans or no layers found, create a new layer and add all the orphans to it if (orphans.length > 0 || !childgroups) { layer = new Layer(getNewLayerName(layernames), null, this.svgElem_); layer.appendChildren(orphans); @@ -9736,9 +10796,9 @@ } else { layer.activate(); } + this.current_layer = layer; } - /** * Creates a new top-level layer in the drawing with the given name and * makes it the current layer. @@ -9749,19 +10809,20 @@ */ }, { - key: 'createLayer', + key: "createLayer", value: function createLayer(name, hrService) { if (this.current_layer) { this.current_layer.deactivate(); - } - // Check for duplicate name. + } // Check for duplicate name. + + if (name === undefined || name === null || name === '' || this.layer_map[name]) { name = getNewLayerName(Object.keys(this.layer_map)); - } + } // Crate new layer and add to DOM as last layer + + + var layer = new Layer(name, null, this.svgElem_); // Like to assume hrService exists, but this is backwards compatible with old version of createLayer. - // Crate new layer and add to DOM as last layer - var layer = new Layer(name, null, this.svgElem_); - // Like to assume hrService exists, but this is backwards compatible with old version of createLayer. if (hrService) { hrService.startBatchCommand('Create Layer'); hrService.insertElement(layer.getGroup()); @@ -9773,7 +10834,6 @@ this.current_layer = layer; return layer.getGroup(); } - /** * Creates a copy of the current layer with the given name and makes it the current layer. * @param {string} name - The given name. If the layer name exists, a new name will be generated. @@ -9783,29 +10843,32 @@ */ }, { - key: 'cloneLayer', + key: "cloneLayer", value: function cloneLayer(name, hrService) { if (!this.current_layer) { return null; } - this.current_layer.deactivate(); - // Check for duplicate name. + + this.current_layer.deactivate(); // Check for duplicate name. + if (name === undefined || name === null || name === '' || this.layer_map[name]) { name = getNewLayerName(Object.keys(this.layer_map)); - } + } // Create new group and add to DOM just after current_layer + - // Create new group and add to DOM just after current_layer var currentGroup = this.current_layer.getGroup(); var layer = new Layer(name, currentGroup, this.svgElem_); - var group = layer.getGroup(); + var group = layer.getGroup(); // Clone children - // Clone children var children = currentGroup.childNodes; + for (var _index = 0; _index < children.length; _index++) { var ch = children[_index]; + if (ch.localName === 'title') { continue; } + group.append(this.copyElem(ch)); } @@ -9813,20 +10876,21 @@ hrService.startBatchCommand('Duplicate Layer'); hrService.insertElement(group); hrService.endBatchCommand(); - } + } // Update layer containers and current_layer. + - // Update layer containers and current_layer. var index = this.all_layers.indexOf(this.current_layer); + if (index >= 0) { this.all_layers.splice(index + 1, 0, layer); } else { this.all_layers.push(layer); } + this.layer_map[name] = layer; this.current_layer = layer; return group; } - /** * Returns whether the layer is visible. If the layer name is not valid, * then this function returns `false`. @@ -9835,12 +10899,11 @@ */ }, { - key: 'getLayerVisibility', + key: "getLayerVisibility", value: function getLayerVisibility(layerName) { var layer = this.layer_map[layerName]; return layer ? layer.isVisible() : false; } - /** * Sets the visibility of the layer. If the layer name is not valid, this * function returns `null`, otherwise it returns the `SVGElement` representing @@ -9852,19 +10915,21 @@ */ }, { - key: 'setLayerVisibility', + key: "setLayerVisibility", value: function setLayerVisibility(layerName, bVisible) { if (typeof bVisible !== 'boolean') { return null; } + var layer = this.layer_map[layerName]; + if (!layer) { return null; } + layer.setVisible(bVisible); return layer.getGroup(); } - /** * Returns the opacity of the given layer. If the input name is not a layer, `null` is returned. * @param {string} layerName - name of the layer on which to get the opacity @@ -9873,15 +10938,16 @@ */ }, { - key: 'getLayerOpacity', + key: "getLayerOpacity", value: function getLayerOpacity(layerName) { var layer = this.layer_map[layerName]; + if (!layer) { return null; } + return layer.getOpacity(); } - /** * Sets the opacity of the given layer. If the input name is not a layer, * nothing happens. If opacity is not a value between 0.0 and 1.0, then @@ -9896,36 +10962,39 @@ */ }, { - key: 'setLayerOpacity', + key: "setLayerOpacity", value: function setLayerOpacity(layerName, opacity) { if (typeof opacity !== 'number' || opacity < 0.0 || opacity > 1.0) { return; } + var layer = this.layer_map[layerName]; + if (layer) { layer.setOpacity(opacity); } } - /** - * Create a clone of an element, updating its ID and its children's IDs when needed + * Create a clone of an element, updating its ID and its children's IDs when needed. * @param {Element} el - DOM element to clone * @returns {Element} */ }, { - key: 'copyElem', - value: function copyElem$$1(el) { - var self = this; + key: "copyElem", + value: function copyElem$1(el) { + var that = this; + var getNextIdClosure = function getNextIdClosure() { - return self.getNextId(); + return that.getNextId(); }; + return copyElem(el, getNextIdClosure); } }]); + return Drawing; }(); - /** * Called to ensure that drawings will or will not have randomized ids. * The currentDrawing will have its nonce set if it doesn't already. @@ -9934,6 +11003,7 @@ * @param {draw.Drawing} currentDrawing * @returns {undefined} */ + var randomizeIds = function randomizeIds(enableRandomization, currentDrawing) { randIds = enableRandomization === false ? RandomizeModes.NEVER_RANDOMIZE : RandomizeModes.ALWAYS_RANDOMIZE; @@ -9942,9 +11012,7 @@ } else if (randIds === RandomizeModes.NEVER_RANDOMIZE && currentDrawing.getNonce()) { currentDrawing.clearNonce(); } - }; - - // Layer API Functions + }; // Layer API Functions /** * Group: Layers @@ -9961,32 +11029,39 @@ * @property {external:jQuery.data} elData * @property {module:history.UndoManager} undoMgr */ + /** * @function module:draw.DrawCanvasInit#getCurrentGroup * @returns {Element} */ + /** * @function module:draw.DrawCanvasInit#setCurrentGroup * @param {Element} cg * @returns {undefined} */ + /** * @function module:draw.DrawCanvasInit#getSelectedElements * @returns {Element[]} the array with selected DOM elements */ + /** * @function module:draw.DrawCanvasInit#getSVGContent * @returns {SVGSVGElement} */ + /** * @function module:draw.DrawCanvasInit#getCurrentDrawing * @returns {module:draw.Drawing} */ + /** * @function module:draw.DrawCanvasInit#clearSelection * @param {boolean} [noCall] - When `true`, does not call the "selected" handler * @returns {undefined} */ + /** * Run the callback function associated with the given event * @function module:draw.DrawCanvasInit#call @@ -9996,36 +11071,38 @@ * passed. If the event is "contextset", the arg is `null` or `Element`. * @returns {undefined} */ + /** * @function module:draw.DrawCanvasInit#addCommandToHistory * @param {Command} cmd * @returns {undefined} */ + /** * @function module:draw.DrawCanvasInit#changeSVGContent * @returns {undefined} */ - var canvas_ = void 0; + var canvas_; /** * @function module:draw.init * @param {module:draw.DrawCanvasInit} canvas * @returns {undefined} */ + var init$3 = function init(canvas) { canvas_ = canvas; }; - /** - * Updates layer system + * Updates layer system. * @function module:draw.identifyLayers * @returns {undefined} */ + var identifyLayers = function identifyLayers() { leaveContext(); canvas_.getCurrentDrawing().identifyLayers(); }; - /** * Creates a new top-level layer in the drawing with the given name, sets the current layer * to it, and then clears the selection. This function then calls the 'changed' handler. @@ -10036,12 +11113,12 @@ * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + var createLayer = function createLayer(name, hrService) { var newLayer = canvas_.getCurrentDrawing().createLayer(name, historyRecordingService(hrService)); canvas_.clearSelection(); canvas_.call('changed', [newLayer]); }; - /** * Creates a new top-level layer in the drawing with the given name, copies all the current layer's contents * to it, and then clears the selection. This function then calls the 'changed' handler. @@ -10052,15 +11129,14 @@ * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + var cloneLayer = function cloneLayer(name, hrService) { // Clone the current layer and make the cloned layer the new current layer var newLayer = canvas_.getCurrentDrawing().cloneLayer(name, historyRecordingService(hrService)); - canvas_.clearSelection(); leaveContext(); canvas_.call('changed', [newLayer]); }; - /** * Deletes the current layer from the drawing and then clears the selection. This function * then calls the 'changed' handler. This is an undoable action. @@ -10068,25 +11144,26 @@ * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {boolean} `true` if an old layer group was found to delete */ + var deleteCurrentLayer = function deleteCurrentLayer() { var currentLayer = canvas_.getCurrentDrawing().getCurrentLayer(); var _currentLayer = currentLayer, nextSibling = _currentLayer.nextSibling; - var parent = currentLayer.parentNode; currentLayer = canvas_.getCurrentDrawing().deleteCurrentLayer(); + if (currentLayer) { - var batchCmd = new BatchCommand('Delete Layer'); - // store in our Undo History + var batchCmd = new BatchCommand('Delete Layer'); // store in our Undo History + batchCmd.addSubCommand(new RemoveElementCommand(currentLayer, nextSibling, parent)); canvas_.addCommandToHistory(batchCmd); canvas_.clearSelection(); canvas_.call('changed', [parent]); return true; } + return false; }; - /** * Sets the current layer. If the name is not a valid layer name, then this function returns * false. Otherwise it returns true. This is not an undo-able action. @@ -10094,14 +11171,16 @@ * @param {string} name - The name of the layer you want to switch to. * @returns {boolean} true if the current layer was switched, otherwise false */ + var setCurrentLayer = function setCurrentLayer(name) { var result = canvas_.getCurrentDrawing().setCurrentLayer(toXml(name)); + if (result) { canvas_.clearSelection(); } + return result; }; - /** * Renames the current layer. If the layer name is not valid (i.e. unique), then this function * does nothing and returns `false`, otherwise it returns `true`. This is an undo-able action. @@ -10111,19 +11190,22 @@ * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {boolean} Whether the rename succeeded */ + var renameCurrentLayer = function renameCurrentLayer(newName) { var drawing = canvas_.getCurrentDrawing(); var layer = drawing.getCurrentLayer(); + if (layer) { var result = drawing.setCurrentLayerName(newName, historyRecordingService()); + if (result) { canvas_.call('changed', [layer]); return true; } } + return false; }; - /** * Changes the position of the current layer to the new value. If the new index is not valid, * this function does nothing and returns false, otherwise it returns true. This is an @@ -10133,16 +11215,18 @@ * 0 and (number of layers - 1) * @returns {boolean} `true` if the current layer position was changed, `false` otherwise. */ + var setCurrentLayerPosition = function setCurrentLayerPosition(newPos) { var drawing = canvas_.getCurrentDrawing(); var result = drawing.setCurrentLayerPosition(newPos); + if (result) { canvas_.addCommandToHistory(new MoveElementCommand(result.currentGroup, result.oldNextSibling, canvas_.getSVGContent())); return true; } + return false; }; - /** * Sets the visibility of the layer. If the layer name is not valid, this function return * `false`, otherwise it returns `true`. This is an undo-able action. @@ -10151,13 +11235,17 @@ * @param {boolean} bVisible - Whether the layer should be visible * @returns {boolean} true if the layer's visibility was set, false otherwise */ + var setLayerVisibility = function setLayerVisibility(layerName, bVisible) { var drawing = canvas_.getCurrentDrawing(); var prevVisibility = drawing.getLayerVisibility(layerName); var layer = drawing.setLayerVisibility(layerName, bVisible); + if (layer) { var oldDisplay = prevVisibility ? 'inline' : 'none'; - canvas_.addCommandToHistory(new ChangeElementCommand(layer, { display: oldDisplay }, 'Layer Visibility')); + canvas_.addCommandToHistory(new ChangeElementCommand(layer, { + display: oldDisplay + }, 'Layer Visibility')); } else { return false; } @@ -10165,11 +11253,11 @@ if (layer === drawing.getCurrentLayer()) { canvas_.clearSelection(); canvas_.pathActions.clear(); - } - // call('changed', [selected]); + } // call('changed', [selected]); + + return true; }; - /** * Moves the selected elements to layerName. If the name is not a valid layer name, then `false` * is returned. Otherwise it returns `true`. This is an undo-able action. @@ -10177,148 +11265,132 @@ * @param {string} layerName - The name of the layer you want to which you want to move the selected elements * @returns {boolean} Whether the selected elements were moved to the layer. */ + var moveSelectedToLayer = function moveSelectedToLayer(layerName) { // find the layer var drawing = canvas_.getCurrentDrawing(); var layer = drawing.getLayerByName(layerName); + if (!layer) { return false; } - var batchCmd = new BatchCommand('Move Elements to Layer'); + var batchCmd = new BatchCommand('Move Elements to Layer'); // loop for each selected element and move it - // loop for each selected element and move it var selElems = canvas_.getSelectedElements(); var i = selElems.length; + while (i--) { var elem = selElems[i]; + if (!elem) { continue; } - var oldNextSibling = elem.nextSibling; - // TODO: this is pretty brittle! + + var oldNextSibling = elem.nextSibling; // TODO: this is pretty brittle! + var oldLayer = elem.parentNode; layer.append(elem); batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldLayer)); } canvas_.addCommandToHistory(batchCmd); - return true; }; - /** * @function module:draw.mergeLayer * @param {module:history.HistoryRecordingService} hrService * @returns {undefined} */ + var mergeLayer = function mergeLayer(hrService) { canvas_.getCurrentDrawing().mergeLayer(historyRecordingService(hrService)); canvas_.clearSelection(); leaveContext(); canvas_.changeSVGContent(); }; - /** * @function module:draw.mergeAllLayers * @param {module:history.HistoryRecordingService} hrService * @returns {undefined} */ + var mergeAllLayers = function mergeAllLayers(hrService) { canvas_.getCurrentDrawing().mergeAllLayers(historyRecordingService(hrService)); canvas_.clearSelection(); leaveContext(); canvas_.changeSVGContent(); }; - /** * Return from a group context to the regular kind, make any previously - * disabled elements enabled again + * disabled elements enabled again. * @function module:draw.leaveContext * @fires module:svgcanvas.SvgCanvas#event:contextset * @returns {undefined} */ + var leaveContext = function leaveContext() { var len = disabledElems.length; + if (len) { for (var i = 0; i < len; i++) { var elem = disabledElems[i]; var orig = canvas_.elData(elem, 'orig_opac'); + if (orig !== 1) { elem.setAttribute('opacity', orig); } else { elem.removeAttribute('opacity'); } + elem.setAttribute('style', 'pointer-events: inherit'); } + disabledElems = []; canvas_.clearSelection(true); canvas_.call('contextset', null); } + canvas_.setCurrentGroup(null); }; - /** - * Set the current context (for in-group editing) + * Set the current context (for in-group editing). * @function module:draw.setContext * @param {Element} elem * @fires module:svgcanvas.SvgCanvas#event:contextset * @returns {undefined} */ + var setContext = function setContext(elem) { leaveContext(); + if (typeof elem === 'string') { elem = getElem(elem); - } + } // Edit inside this group - // Edit inside this group - canvas_.setCurrentGroup(elem); - // Disable other elements + canvas_.setCurrentGroup(elem); // Disable other elements + $$5(elem).parentsUntil('#svgcontent').andSelf().siblings().each(function () { - var opac = this.getAttribute('opacity') || 1; - // Store the original's opacity + var opac = this.getAttribute('opacity') || 1; // Store the original's opacity + canvas_.elData(this, 'orig_opac', opac); this.setAttribute('opacity', opac * 0.33); this.setAttribute('style', 'pointer-events: none'); disabledElems.push(this); }); - canvas_.clearSelection(); canvas_.call('contextset', canvas_.getCurrentGroup()); }; - var draw = /*#__PURE__*/Object.freeze({ - Drawing: Drawing, - randomizeIds: randomizeIds, - init: init$3, - identifyLayers: identifyLayers, - createLayer: createLayer, - cloneLayer: cloneLayer, - deleteCurrentLayer: deleteCurrentLayer, - setCurrentLayer: setCurrentLayer, - renameCurrentLayer: renameCurrentLayer, - setCurrentLayerPosition: setCurrentLayerPosition, - setLayerVisibility: setLayerVisibility, - moveSelectedToLayer: moveSelectedToLayer, - mergeLayer: mergeLayer, - mergeAllLayers: mergeAllLayers, - leaveContext: leaveContext, - setContext: setContext, - Layer: Layer - }); + var REVERSE_NS = getReverseNS(); // Todo: Split out into core attributes, presentation attributes, etc. so consistent /** - * Tools for SVG sanitization - * @module sanitize - * @license MIT - * - * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller + * This defines which elements and attributes that we support (or at least + * don't remove) + * @type {PlainObject} */ - var REVERSE_NS = getReverseNS(); - - // this defines which elements and attributes that we support var svgWhiteList_ = { // SVG Elements a: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'xlink:href', 'xlink:title'], @@ -10329,6 +11401,7 @@ desc: [], ellipse: ['class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'], feGaussianBlur: ['class', 'color-interpolation-filters', 'id', 'requiredFeatures', 'stdDeviation'], + feMorphology: ['class', 'in', 'operator', 'radius'], filter: ['class', 'color-interpolation-filters', 'filterRes', 'filterUnits', 'height', 'id', 'primitiveUnits', 'requiredFeatures', 'width', 'x', 'xlink:href', 'y'], foreignObject: ['class', 'font-size', 'height', 'id', 'opacity', 'requiredFeatures', 'style', 'transform', 'width', 'x', 'y'], g: ['class', 'clip-path', 'clip-rule', 'id', 'display', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'font-family', 'font-size', 'font-style', 'font-weight', 'text-anchor'], @@ -10353,7 +11426,6 @@ title: [], tspan: ['class', 'clip-path', 'clip-rule', 'dx', 'dy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'rotate', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'textLength', 'transform', 'x', 'xml:space', 'y'], use: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'transform', 'width', 'x', 'xlink:href', 'y'], - // MathML Elements annotation: ['encoding'], 'annotation-xml': ['encoding'], @@ -10386,18 +11458,17 @@ munderover: [], none: [], semantics: [] - }; + }; // Produce a Namespace-aware version of svgWhitelist - // Produce a Namespace-aware version of svgWhitelist var svgWhiteListNS_ = {}; Object.entries(svgWhiteList_).forEach(function (_ref) { - var _ref2 = slicedToArray(_ref, 2), + var _ref2 = _slicedToArray(_ref, 2), elt = _ref2[0], atts = _ref2[1]; var attNS = {}; Object.entries(atts).forEach(function (_ref3) { - var _ref4 = slicedToArray(_ref3, 2), + var _ref4 = _slicedToArray(_ref3, 2), i = _ref4[0], att = _ref4[1]; @@ -10410,7 +11481,6 @@ }); svgWhiteListNS_[elt] = attNS; }); - /** * Sanitizes the input node and its children. * It only keeps what is allowed from our whitelist defined above. @@ -10418,101 +11488,110 @@ * @param {Text|Element} node - The DOM element to be checked (we'll also check its children) or text node to be cleaned up * @returns {undefined} */ + var sanitizeSvg = function sanitizeSvg(node) { // Cleanup text nodes if (node.nodeType === 3) { // 3 === TEXT_NODE // Trim whitespace - node.nodeValue = node.nodeValue.replace(/^\s+|\s+$/g, ''); - // Remove if empty + node.nodeValue = node.nodeValue.replace(/^\s+|\s+$/g, ''); // Remove if empty + if (!node.nodeValue.length) { node.remove(); } - } - - // We only care about element nodes. + } // We only care about element nodes. // Automatically return for all non-element nodes, such as comments, etc. + + if (node.nodeType !== 1) { // 1 == ELEMENT_NODE return; } var doc = node.ownerDocument; - var parent = node.parentNode; - // can parent ever be null here? I think the root node's parent is the document... + var parent = node.parentNode; // can parent ever be null here? I think the root node's parent is the document... + if (!doc || !parent) { return; } var allowedAttrs = svgWhiteList_[node.nodeName]; - var allowedAttrsNS = svgWhiteListNS_[node.nodeName]; - // if this element is supported, sanitize it + var allowedAttrsNS = svgWhiteListNS_[node.nodeName]; // if this element is supported, sanitize it + if (typeof allowedAttrs !== 'undefined') { var seAttrs = []; var i = node.attributes.length; + while (i--) { // if the attribute is not in our whitelist, then remove it // could use jQuery's inArray(), but I don't know if that's any better var attr = node.attributes.item(i); var attrName = attr.nodeName; var attrLocalName = attr.localName; - var attrNsURI = attr.namespaceURI; - // Check that an attribute with the correct localName in the correct namespace is on + var attrNsURI = attr.namespaceURI; // Check that an attribute with the correct localName in the correct namespace is on // our whitelist or is a namespace declaration for one of our allowed namespaces - if (!(allowedAttrsNS.hasOwnProperty(attrLocalName) && attrNsURI === allowedAttrsNS[attrLocalName] && attrNsURI !== NS.XMLNS) && !(attrNsURI === NS.XMLNS && REVERSE_NS[attr.value])) { + + if (!({}.hasOwnProperty.call(allowedAttrsNS, attrLocalName) && attrNsURI === allowedAttrsNS[attrLocalName] && attrNsURI !== NS.XMLNS) && !(attrNsURI === NS.XMLNS && REVERSE_NS[attr.value])) { // TODO(codedread): Programmatically add the se: attributes to the NS-aware whitelist. // Bypassing the whitelist to allow se: prefixes. // Is there a more appropriate way to do this? if (attrName.startsWith('se:') || attrName.startsWith('data-')) { seAttrs.push([attrName, attr.value]); } - node.removeAttributeNS(attrNsURI, attrLocalName); - } - // Add spaces before negative signs where necessary + node.removeAttributeNS(attrNsURI, attrLocalName); + } // Add spaces before negative signs where necessary + + if (isGecko()) { switch (attrName) { case 'transform': case 'gradientTransform': case 'patternTransform': - var val = attr.value.replace(/(\d)-/g, '$1 -'); - node.setAttribute(attrName, val); - break; + { + var val = attr.value.replace(/(\d)-/g, '$1 -'); + node.setAttribute(attrName, val); + 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 if (attrName === 'style') { var props = attr.value.split(';'); var p = props.length; + while (p--) { var _props$p$split = props[p].split(':'), - _props$p$split2 = slicedToArray(_props$p$split, 2), + _props$p$split2 = _slicedToArray(_props$p$split, 2), name = _props$p$split2[0], _val = _props$p$split2[1]; var styleAttrName = (name || '').trim(); - var styleAttrVal = (_val || '').trim(); - // Now check that this attribute is supported + + var styleAttrVal = (_val || '').trim(); // Now check that this attribute is supported + + if (allowedAttrs.includes(styleAttrName)) { node.setAttribute(styleAttrName, styleAttrVal); } } + node.removeAttribute('style'); } } Object.values(seAttrs).forEach(function (_ref5) { - var _ref6 = slicedToArray(_ref5, 2), + var _ref6 = _slicedToArray(_ref5, 2), att = _ref6[0], val = _ref6[1]; node.setAttributeNS(NS.SE, att, val); - }); - - // for some elements that have a xlink:href, ensure the URI refers to a local element + }); // for some elements that have a xlink:href, ensure the URI refers to a local element // (but not for links) + var href = getHref(node); + if (href && ['filter', 'linearGradient', 'pattern', 'radialGradient', 'textPath', 'use'].includes(node.nodeName)) { // TODO: we simply check if the first character is a #, is this bullet-proof? if (href[0] !== '#') { @@ -10520,90 +11599,93 @@ setHref(node, ''); node.removeAttributeNS(NS.XLINK, 'href'); } - } + } // Safari crashes on a <use> without a xlink:href, so we just remove the node here + - // Safari crashes on a <use> without a xlink:href, so we just remove the node here if (node.nodeName === 'use' && !getHref(node)) { node.remove(); return; - } - // if the element has attributes pointing to a non-local reference, + } // if the element has attributes pointing to a non-local reference, // need to remove the attribute + + Object.values(['clip-path', 'fill', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'stroke'], function (attr) { var val = node.getAttribute(attr); + if (val) { - val = getUrlFromAttr(val); - // simply check for first character being a '#' + val = getUrlFromAttr(val); // simply check for first character being a '#' + if (val && val[0] !== '#') { node.setAttribute(attr, ''); node.removeAttribute(attr); } } - }); + }); // recurse to children - // recurse to children i = node.childNodes.length; + while (i--) { sanitizeSvg(node.childNodes.item(i)); - } - // else (element not supported), remove it + } // else (element not supported), remove it + } else { // remove all children from this node and insert them before this node // FIXME: in the case of animation elements this will hardly ever be correct var children = []; + while (node.hasChildNodes()) { children.push(parent.insertBefore(node.firstChild, node)); - } + } // remove this node from the document altogether - // remove this node from the document altogether - node.remove(); - // call sanitizeSvg on each of those children + node.remove(); // call sanitizeSvg on each of those children + var _i = children.length; + while (_i--) { sanitizeSvg(children[_i]); } } }; - /* globals jQuery */ + var $$6 = jQuery; // this is how we map paths to our preferred relative segment types - var $$6 = jQuery; - - // this is how we map paths to our preferred relative segment types var pathMap$1 = [0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a', 'H', 'h', 'V', 'v', 'S', 's', 'T', 't']; - /** * @interface module:coords.EditorContext */ + /** * @function module:coords.EditorContext#getGridSnapping * @returns {boolean} */ + /** * @function module:coords.EditorContext#getDrawing * @returns {module:draw.Drawing} */ + /** * @function module:coords.EditorContext#getSVGRoot * @returns {SVGSVGElement} */ var editorContext_$2 = null; - /** * @function module:coords.init * @param {module:coords.EditorContext} editorContext + * @returns {undefined} */ + var init$4 = function init(editorContext) { editorContext_$2 = editorContext; }; - /** - * Applies coordinate changes to an element based on the given matrix + * Applies coordinate changes to an element based on the given matrix. * @function module:coords.remapElement * @implements {module:path.EditorContext#remapElement} */ + var remapElement = function remapElement(selected, changes, m) { var remap = function remap(x, y) { return transformPoint(x, y, m); @@ -10617,10 +11699,15 @@ doSnapping = editorContext_$2.getGridSnapping() && selected.parentNode.parentNode.localName === 'svg', finishUp = function finishUp() { if (doSnapping) { - for (var o in changes) { - changes[o] = snapToGrid(changes[o]); - } + Object.entries(changes).forEach(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + o = _ref2[0], + value = _ref2[1]; + + changes[o] = snapToGrid(value); + }); } + assignAttributes(selected, changes, 1000, true); }, box = getBBox(selected); @@ -10628,10 +11715,12 @@ for (var i = 0; i < 2; i++) { var type = i === 0 ? 'fill' : 'stroke'; var attrVal = selected.getAttribute(type); + if (attrVal && attrVal.startsWith('url(')) { if (m.a < 0 || m.d < 0) { var grad = getRefElem(attrVal); var newgrad = grad.cloneNode(true); + if (m.a < 0) { // flip x var x1 = newgrad.getAttribute('x1'); @@ -10647,19 +11736,20 @@ newgrad.setAttribute('y1', -(y1 - 1)); newgrad.setAttribute('y2', -(y2 - 1)); } + newgrad.id = editorContext_$2.getDrawing().getNextId(); findDefs().append(newgrad); selected.setAttribute(type, 'url(#' + newgrad.id + ')'); - } - - // Not really working :( + } // Not really working :( // if (selected.tagName === 'path') { // reorientGrads(selected, m); // } + } } var elName = selected.tagName; + if (elName === 'g' || elName === 'text' || elName === 'tspan' || elName === 'use') { // if it was a translate, then just update x,y if (m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && (m.e !== 0 || m.f !== 0)) { @@ -10677,10 +11767,10 @@ chlist.clear(); chlist.appendItem(mt); } - } - - // now we have a set of changes and an applied reduced transform list + } // now we have a set of changes and an applied reduced transform list // we apply the changes directly to the DOM + + switch (elName) { case 'foreignObject': case 'rect': @@ -10690,9 +11780,13 @@ if (elName === 'image' && (m.a < 0 || m.d < 0)) { // Convert to matrix var _chlist = getTransformList(selected); + var _mt = editorContext_$2.getSVGRoot().createSVGTransform(); + _mt.setMatrix(matrixMultiply(transformListToTransform(_chlist).matrix, m)); + _chlist.clear(); + _chlist.appendItem(_mt); } else { var pt1 = remap(changes.x, changes.y); @@ -10703,9 +11797,12 @@ changes.width = Math.abs(changes.width); changes.height = Math.abs(changes.height); } + finishUp(); break; - }case 'ellipse': + } + + case 'ellipse': { var c = remap(changes.cx, changes.cy); changes.cx = c.x; @@ -10716,12 +11813,15 @@ changes.ry = Math.abs(changes.ry); finishUp(); break; - }case 'circle': + } + + case 'circle': { var _c = remap(changes.cx, changes.cy); + changes.cx = _c.x; - changes.cy = _c.y; - // take the minimum of the new selected box's dimensions for the new circle radius + changes.cy = _c.y; // take the minimum of the new selected box's dimensions for the new circle radius + var tbox = transformBox(box.x, box.y, box.width, box.height, m); var w = tbox.tr.x - tbox.tl.x, h = tbox.bl.y - tbox.tl.y; @@ -10730,34 +11830,47 @@ if (changes.r) { changes.r = Math.abs(changes.r); } + finishUp(); break; - }case 'line': + } + + case 'line': { var _pt = remap(changes.x1, changes.y1); + var pt2 = remap(changes.x2, changes.y2); changes.x1 = _pt.x; changes.y1 = _pt.y; changes.x2 = pt2.x; changes.y2 = pt2.y; - } // Fallthrough + } + // Fallthrough + case 'text': case 'tspan': case 'use': { finishUp(); break; - }case 'g': + } + + case 'g': { var gsvg = $$6(selected).data('gsvg'); + if (gsvg) { assignAttributes(gsvg, changes, 1000, true); } + break; - }case 'polyline': + } + + case 'polyline': case 'polygon': { var len = changes.points.length; + for (var _i = 0; _i < len; ++_i) { var pt = changes.points[_i]; @@ -10767,21 +11880,26 @@ changes.points[_i].x = x; changes.points[_i].y = y; - } + } // const len = changes.points.length; + - // const len = changes.points.length; var pstr = ''; + for (var _i2 = 0; _i2 < len; ++_i2) { var _pt2 = changes.points[_i2]; pstr += _pt2.x + ',' + _pt2.y + ' '; } + selected.setAttribute('points', pstr); break; - }case 'path': + } + + case 'path': { var segList = selected.pathSegList; var _len = segList.numberOfItems; changes.d = []; + for (var _i3 = 0; _i3 < _len; ++_i3) { var seg = segList.getItem(_i3); changes.d[_i3] = { @@ -10805,10 +11923,10 @@ currentpt = remap(firstseg.x, firstseg.y); changes.d[0].x = currentpt.x; changes.d[0].y = currentpt.y; + for (var _i4 = 1; _i4 < _len; ++_i4) { var _seg = changes.d[_i4]; - var _type = _seg.type; - // if absolute or first segment, we want to remap x, y, x1, y1, x2, y2 + var _type = _seg.type; // if absolute or first segment, we want to remap x, y, x1, y1, x2, y2 // if relative, we want to scalew, scaleh if (_type % 2 === 0) { @@ -10816,9 +11934,13 @@ var thisx = _seg.x !== undefined ? _seg.x : currentpt.x, // for V commands thisy = _seg.y !== undefined ? _seg.y : currentpt.y; // for H commands + var _pt3 = remap(thisx, thisy); + var _pt4 = remap(_seg.x1, _seg.y1); + var _pt5 = remap(_seg.x2, _seg.y2); + _seg.x = _pt3.x; _seg.y = _pt3.y; _seg.x1 = _pt4.x; @@ -10840,49 +11962,68 @@ } } // for each segment + var dstr = ''; _len = changes.d.length; + for (var _i5 = 0; _i5 < _len; ++_i5) { var _seg2 = changes.d[_i5]; var _type2 = _seg2.type; - dstr += pathMap$1[_type2]; + switch (_type2) { case 13: // relative horizontal line (h) + case 12: // absolute horizontal line (H) dstr += _seg2.x + ' '; break; + case 15: // relative vertical line (v) + case 14: // absolute vertical line (V) dstr += _seg2.y + ' '; break; + case 3: // relative move (m) + case 5: // relative line (l) + case 19: // relative smooth quad (t) + case 2: // absolute move (M) + case 4: // absolute line (L) + case 18: // absolute smooth quad (T) dstr += _seg2.x + ',' + _seg2.y + ' '; break; + case 7: // relative cubic (c) + case 6: // absolute cubic (C) dstr += _seg2.x1 + ',' + _seg2.y1 + ' ' + _seg2.x2 + ',' + _seg2.y2 + ' ' + _seg2.x + ',' + _seg2.y + ' '; break; + case 9: // relative quad (q) + case 8: // absolute quad (Q) dstr += _seg2.x1 + ',' + _seg2.y1 + ' ' + _seg2.x + ',' + _seg2.y + ' '; break; + case 11: // relative elliptical arc (a) + case 10: // absolute elliptical arc (A) - dstr += _seg2.r1 + ',' + _seg2.r2 + ' ' + _seg2.angle + ' ' + +_seg2.largeArcFlag + ' ' + +_seg2.sweepFlag + ' ' + _seg2.x + ',' + _seg2.y + ' '; + dstr += _seg2.r1 + ',' + _seg2.r2 + ' ' + _seg2.angle + ' ' + Number(_seg2.largeArcFlag) + ' ' + Number(_seg2.sweepFlag) + ' ' + _seg2.x + ',' + _seg2.y + ' '; break; + case 17: // relative smooth cubic (s) + case 16: // absolute smooth cubic (S) dstr += _seg2.x2 + ',' + _seg2.y2 + ' ' + _seg2.x + ',' + _seg2.y + ' '; @@ -10897,22 +12038,22 @@ }; /* globals jQuery */ - - var $$7 = jqPluginSVG(jQuery); - - var context_ = void 0; - + var $$7 = jQueryPluginSVG(jQuery); + var context_; /** * @interface module:recalculate.EditorContext */ + /** * @function module:recalculate.EditorContext#getSVGRoot * @returns {SVGSVGElement} The root DOM element */ + /** * @function module:recalculate.EditorContext#getStartTransform * @returns {string} */ + /** * @function module:recalculate.EditorContext#setStartTransform * @param {string} transform @@ -10924,58 +12065,57 @@ * @param {module:recalculate.EditorContext} editorContext * @returns {undefined} */ - var init$5 = function init$$1(editorContext) { + + var init$5 = function init(editorContext) { context_ = editorContext; }; - /** - * Updates a `<clipPath>`s values based on the given translation of an element + * Updates a `<clipPath>`s values based on the given translation of an element. * @function module:recalculate.updateClipPath * @param {string} attr - The clip-path attribute value with the clipPath's ID * @param {Float} tx - The translation's x value * @param {Float} ty - The translation's y value * @returns {undefined} */ + var updateClipPath = function updateClipPath(attr, tx, ty) { var path = getRefElem(attr).firstChild; var cpXform = getTransformList(path); var newxlate = context_.getSVGRoot().createSVGTransform(); newxlate.setTranslate(tx, ty); + cpXform.appendItem(newxlate); // Update clipPath's dimensions - cpXform.appendItem(newxlate); - - // Update clipPath's dimensions recalculateDimensions(path); }; - /** - * Decides the course of action based on the element's transform list + * Decides the course of action based on the element's transform list. * @function module:recalculate.recalculateDimensions * @param {Element} selected - The DOM element to recalculate * @returns {Command} Undo command object with the resulting change */ - var recalculateDimensions = function recalculateDimensions(selected) { - if (selected == null) { - return null; - } - // Firefox Issue - 1081 + var recalculateDimensions = function recalculateDimensions(selected) { + if (isNullish(selected)) { + return null; + } // Firefox Issue - 1081 + + if (selected.nodeName === 'svg' && navigator.userAgent.includes('Firefox/20')) { return null; } var svgroot = context_.getSVGRoot(); - var tlist = getTransformList(selected); + var tlist = getTransformList(selected); // remove any unnecessary transforms - // remove any unnecessary transforms if (tlist && tlist.numberOfItems > 0) { var k = tlist.numberOfItems; var noi = k; + while (k--) { var xform = tlist.getItem(k); + if (xform.type === 0) { - tlist.removeItem(k); - // remove identity matrices + tlist.removeItem(k); // remove identity matrices } else if (xform.type === 1) { if (isIdentity(xform.matrix)) { if (noi === 1) { @@ -10986,64 +12126,69 @@ selected.removeAttribute('transform'); return null; } + tlist.removeItem(k); - } - // remove zero-degree rotations + } // remove zero-degree rotations + } else if (xform.type === 4) { if (xform.angle === 0) { tlist.removeItem(k); } } - } - // End here if all it has is a rotation + } // End here if all it has is a rotation + + if (tlist.numberOfItems === 1 && getRotationAngle(selected)) { return null; } - } + } // if this element had no transforms, we are done + - // if this element had no transforms, we are done if (!tlist || tlist.numberOfItems === 0) { // Chrome apparently had a bug that requires clearing the attribute first. - selected.setAttribute('transform', ''); - // However, this still next line currently doesn't work at all in Chrome - selected.removeAttribute('transform'); - // selected.transform.baseVal.clear(); // Didn't help for Chrome bug - return null; - } + selected.setAttribute('transform', ''); // However, this still next line currently doesn't work at all in Chrome + + selected.removeAttribute('transform'); // selected.transform.baseVal.clear(); // Didn't help for Chrome bug + + return null; + } // TODO: Make this work for more than 2 + - // TODO: Make this work for more than 2 if (tlist) { var mxs = []; var _k = tlist.numberOfItems; + while (_k--) { var _xform = tlist.getItem(_k); + if (_xform.type === 1) { mxs.push([_xform.matrix, _k]); } else if (mxs.length) { mxs = []; } } + if (mxs.length === 2) { var mNew = svgroot.createSVGTransformFromMatrix(matrixMultiply(mxs[1][0], mxs[0][0])); tlist.removeItem(mxs[0][1]); tlist.removeItem(mxs[1][1]); tlist.insertItemBefore(mNew, mxs[1][1]); - } + } // combine matrix + translate + - // combine matrix + translate _k = tlist.numberOfItems; + if (_k >= 2 && tlist.getItem(_k - 2).type === 1 && tlist.getItem(_k - 1).type === 2) { var mt = svgroot.createSVGTransform(); - var m = matrixMultiply(tlist.getItem(_k - 2).matrix, tlist.getItem(_k - 1).matrix); mt.setMatrix(m); tlist.removeItem(_k - 2); tlist.removeItem(_k - 2); tlist.appendItem(mt); } - } + } // If it still has a single [M] or [R][M], return null too (prevents BatchCommand from being returned). + - // If it still has a single [M] or [R][M], return null too (prevents BatchCommand from being returned). switch (selected.tagName) { // Ignore these elements, as they can absorb the [M] case 'line': @@ -11051,42 +12196,48 @@ case 'polygon': case 'path': break; + default: if (tlist.numberOfItems === 1 && tlist.getItem(0).type === 1 || tlist.numberOfItems === 2 && tlist.getItem(0).type === 1 && tlist.getItem(0).type === 4) { return null; } - } - // Grouped SVG element - var gsvg = $$7(selected).data('gsvg'); + } // Grouped SVG element - // we know we have some transforms, so set up return variable - var batchCmd = new BatchCommand('Transform'); - // store initial values that will be affected by reducing the transform list + var gsvg = $$7(selected).data('gsvg'); // we know we have some transforms, so set up return variable + + var batchCmd = new BatchCommand('Transform'); // store initial values that will be affected by reducing the transform list + var changes = {}; var initial = null; var attrs = []; + switch (selected.tagName) { case 'line': attrs = ['x1', 'y1', 'x2', 'y2']; break; + case 'circle': attrs = ['cx', 'cy', 'r']; break; + case 'ellipse': attrs = ['cx', 'cy', 'rx', 'ry']; break; + case 'foreignObject': case 'rect': case 'image': attrs = ['width', 'height', 'x', 'y']; break; + case 'use': case 'text': case 'tspan': attrs = ['x', 'y']; break; + case 'polygon': case 'polyline': { @@ -11095,18 +12246,26 @@ var list = selected.points; var len = list.numberOfItems; changes.points = new Array(len); + for (var i = 0; i < len; ++i) { var pt = list.getItem(i); - changes.points[i] = { x: pt.x, y: pt.y }; + changes.points[i] = { + x: pt.x, + y: pt.y + }; } + break; - }case 'path': + } + + case 'path': initial = {}; initial.d = selected.getAttribute('d'); changes.d = selected.getAttribute('d'); break; } // switch on element type to get initial values + if (attrs.length) { changes = $$7(selected).attr(attrs); $$7.each(changes, function (attr, val) { @@ -11118,43 +12277,46 @@ x: $$7(gsvg).attr('x') || 0, y: $$7(gsvg).attr('y') || 0 }; - } - - // 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 - if (initial == null) { + + + if (isNullish(initial)) { initial = $$7.extend(true, {}, changes); $$7.each(initial, function (attr, val) { initial[attr] = convertToNum(attr, val); }); - } - // save the start transform value too + } // save the start transform value too + + initial.transform = context_.getStartTransform() || ''; + var oldcenter, newcenter; // if it's a regular group, we have special processing to flatten transforms - var oldcenter = void 0, - newcenter = void 0; - - // if it's a regular group, we have special processing to flatten transforms if (selected.tagName === 'g' && !gsvg || selected.tagName === 'a') { var box = getBBox(selected); - - oldcenter = { x: box.x + box.width / 2, y: box.y + box.height / 2 }; - newcenter = transformPoint(box.x + box.width / 2, box.y + box.height / 2, transformListToTransform(tlist).matrix); - var _m = svgroot.createSVGMatrix(); - + oldcenter = { + x: box.x + box.width / 2, + y: box.y + box.height / 2 + }; + newcenter = transformPoint(box.x + box.width / 2, box.y + box.height / 2, transformListToTransform(tlist).matrix); // let m = svgroot.createSVGMatrix(); // temporarily strip off the rotate and save the old center + var gangle = getRotationAngle(selected); + if (gangle) { var a = gangle * Math.PI / 180; - var s = void 0; + var s; + if (Math.abs(a) > 1.0e-10) { s = Math.sin(a) / (1 - Math.cos(a)); } else { // FIXME: This blows up if the angle is exactly 0! s = 2 / a; } + for (var _i = 0; _i < tlist.numberOfItems; ++_i) { var _xform2 = tlist.getItem(_i); + if (_xform2.type === 4) { // extract old center through mystical arts var rm = _xform2.matrix; @@ -11165,44 +12327,43 @@ } } } + var N = tlist.numberOfItems; var tx = 0, ty = 0, operation = 0; + var firstM; - var firstM = void 0; if (N) { firstM = tlist.getItem(0).matrix; } - var oldStartTransform = void 0; - // first, if it was a scale then the second-last transform will be it + var oldStartTransform; // first, if it was a scale then the second-last transform will be it + if (N >= 3 && tlist.getItem(N - 2).type === 3 && tlist.getItem(N - 3).type === 2 && tlist.getItem(N - 1).type === 2) { operation = 3; // scale - // if the children are unrotated, pass the scale down directly // otherwise pass the equivalent matrix() down directly + var tm = tlist.getItem(N - 3).matrix, sm = tlist.getItem(N - 2).matrix, tmn = tlist.getItem(N - 1).matrix; - var children = selected.childNodes; var c = children.length; + while (c--) { var child = children.item(c); tx = 0; ty = 0; - if (child.nodeType === 1) { - var childTlist = getTransformList(child); - // some children might not have a transform (<metadata>, <defs>, etc) + if (child.nodeType === 1) { + var childTlist = getTransformList(child); // some children might not have a transform (<metadata>, <defs>, etc) + if (!childTlist) { continue; } - var _m2 = transformListToTransform(childTlist).matrix; - - // Convert a matrix to a scale if applicable + var _m = transformListToTransform(childTlist).matrix; // Convert a matrix to a scale if applicable // if (hasMatrixTransform(childTlist) && childTlist.numberOfItems == 1) { // if (m.b==0 && m.c==0 && m.e==0 && m.f==0) { // childTlist.removeItem(0); @@ -11220,32 +12381,30 @@ var angle = getRotationAngle(child); oldStartTransform = context_.getStartTransform(); + var childxforms = []; context_.setStartTransform(child.getAttribute('transform')); + if (angle || hasMatrixTransform(childTlist)) { var e2t = svgroot.createSVGTransform(); - e2t.setMatrix(matrixMultiply(tm, sm, tmn, _m2)); + e2t.setMatrix(matrixMultiply(tm, sm, tmn, _m)); childTlist.clear(); childTlist.appendItem(e2t); - // if not rotated or skewed, push the [T][S][-T] down to the child + childxforms.push(e2t); // if not rotated or skewed, push the [T][S][-T] down to the child } else { // update the transform list with translate,scale,translate - // slide the [T][S][-T] from the front to the back // [T][S][-T][M] = [M][T2][S2][-T2] - // (only bringing [-T] to the right of [M]) // [T][S][-T][M] = [T][S][M][-T2] // [-T2] = [M_inv][-T][M] - var t2n = matrixMultiply(_m2.inverse(), tmn, _m2); - // [T2] is always negative translation of [-T2] + var t2n = matrixMultiply(_m.inverse(), tmn, _m); // [T2] is always negative translation of [-T2] + var t2 = svgroot.createSVGMatrix(); t2.e = -t2n.e; - t2.f = -t2n.f; - - // [T][S][-T][M] = [M][T2][S2][-T2] + t2.f = -t2n.f; // [T][S][-T][M] = [M][T2][S2][-T2] // [S2] = [T2_inv][M_inv][T][S][-T][M][-T2_inv] - var s2 = matrixMultiply(t2.inverse(), _m2.inverse(), tm, sm, tmn, _m2, t2n.inverse()); + var s2 = matrixMultiply(t2.inverse(), _m.inverse(), tm, sm, tmn, _m, t2n.inverse()); var translateOrigin = svgroot.createSVGTransform(), scale = svgroot.createSVGTransform(), translateBack = svgroot.createSVGTransform(); @@ -11255,11 +12414,14 @@ childTlist.appendItem(translateBack); childTlist.appendItem(scale); childTlist.appendItem(translateOrigin); - // logMatrix(translateBack.matrix); + childxforms.push(translateBack); + childxforms.push(scale); + childxforms.push(translateOrigin); // logMatrix(translateBack.matrix); // logMatrix(scale.matrix); } // not rotated - batchCmd.addSubCommand(recalculateDimensions(child)); - // TODO: If any <use> have this group as a parent and are + + + batchCmd.addSubCommand(recalculateDimensions(child)); // TODO: If any <use> have this group as a parent and are // referencing this child, then we need to impose a reverse // scale on it so that when it won't get double-translated // const uses = selected.getElementsByTagNameNS(NS.SVG, 'use'); @@ -11274,30 +12436,37 @@ // batchCmd.addSubCommand( recalculateDimensions(useElem) ); // } // } + context_.setStartTransform(oldStartTransform); } // element + } // for each child // Remove these transforms from group + + tlist.removeItem(N - 1); tlist.removeItem(N - 2); tlist.removeItem(N - 3); } else if (N >= 3 && tlist.getItem(N - 1).type === 1) { operation = 3; // scale - _m = transformListToTransform(tlist).matrix; + + var _m2 = transformListToTransform(tlist).matrix; + var _e2t = svgroot.createSVGTransform(); - _e2t.setMatrix(_m); + + _e2t.setMatrix(_m2); + tlist.clear(); - tlist.appendItem(_e2t); - // next, check if the first transform was a translate + tlist.appendItem(_e2t); // next, check if the first transform was a translate // if we had [ T1 ] [ M ] we want to transform this into [ M ] [ T2 ] // therefore [ T2 ] = [ M_inv ] [ T1 ] [ M ] } else if ((N === 1 || N > 1 && tlist.getItem(1).type !== 3) && tlist.getItem(0).type === 2) { operation = 2; // translate + var T_M = transformListToTransform(tlist).matrix; tlist.removeItem(0); var mInv = transformListToTransform(tlist).matrix.inverse(); var M2 = matrixMultiply(mInv, T_M); - tx = M2.e; ty = M2.f; @@ -11305,16 +12474,17 @@ // we pass the translates down to the individual children var _children = selected.childNodes; var _c = _children.length; - var clipPathsDone = []; while (_c--) { var _child = _children.item(_c); + if (_child.nodeType === 1) { // Check if child has clip-path if (_child.getAttribute('clip-path')) { // tx, ty var attr = _child.getAttribute('clip-path'); + if (!clipPathsDone.includes(attr)) { updateClipPath(attr, tx, ty); clipPathsDone.push(attr); @@ -11324,25 +12494,30 @@ oldStartTransform = context_.getStartTransform(); context_.setStartTransform(_child.getAttribute('transform')); - var _childTlist = getTransformList(_child); - // some children might not have a transform (<metadata>, <defs>, etc) + var _childTlist = getTransformList(_child); // some children might not have a transform (<metadata>, <defs>, etc) + + if (_childTlist) { var newxlate = svgroot.createSVGTransform(); newxlate.setTranslate(tx, ty); + if (_childTlist.numberOfItems) { _childTlist.insertItemBefore(newxlate, 0); } else { _childTlist.appendItem(newxlate); } - batchCmd.addSubCommand(recalculateDimensions(_child)); - // If any <use> have this group as a parent and are + + batchCmd.addSubCommand(recalculateDimensions(_child)); // If any <use> have this group as a parent and are // referencing this child, then impose a reverse translate on it // so that when it won't get double-translated + var uses = selected.getElementsByTagNameNS(NS.SVG, 'use'); var href = '#' + _child.id; var u = uses.length; + while (u--) { var useElem = uses.item(u); + if (href === getHref(useElem)) { var usexlate = svgroot.createSVGTransform(); usexlate.setTranslate(-tx, -ty); @@ -11350,26 +12525,29 @@ batchCmd.addSubCommand(recalculateDimensions(useElem)); } } + context_.setStartTransform(oldStartTransform); } } } - clipPathsDone = []; context_.setStartTransform(oldStartTransform); - } - // else, a matrix imposition from a parent group + } // else, a matrix imposition from a parent group // keep pushing it down to the children + } else if (N === 1 && tlist.getItem(0).type === 1 && !gangle) { operation = 1; var _m3 = tlist.getItem(0).matrix, _children2 = selected.childNodes; var _c2 = _children2.length; + while (_c2--) { var _child2 = _children2.item(_c2); + if (_child2.nodeType === 1) { oldStartTransform = context_.getStartTransform(); context_.setStartTransform(_child2.getAttribute('transform')); + var _childTlist2 = getTransformList(_child2); if (!_childTlist2) { @@ -11379,40 +12557,46 @@ var em = matrixMultiply(_m3, transformListToTransform(_childTlist2).matrix); var e2m = svgroot.createSVGTransform(); e2m.setMatrix(em); + _childTlist2.clear(); + _childTlist2.appendItem(e2m, 0); batchCmd.addSubCommand(recalculateDimensions(_child2)); - context_.setStartTransform(oldStartTransform); - - // Convert stroke + context_.setStartTransform(oldStartTransform); // Convert stroke // TODO: Find out if this should actually happen somewhere else + var sw = _child2.getAttribute('stroke-width'); + if (_child2.getAttribute('stroke') !== 'none' && !isNaN(sw)) { var avg = (Math.abs(em.a) + Math.abs(em.d)) / 2; + _child2.setAttribute('stroke-width', sw * avg); } } } - tlist.clear(); - // else it was just a rotate + + tlist.clear(); // else it was just a rotate } else { if (gangle) { var newRot = svgroot.createSVGTransform(); newRot.setRotate(gangle, newcenter.x, newcenter.y); + if (tlist.numberOfItems) { tlist.insertItemBefore(newRot, 0); } else { tlist.appendItem(newRot); } } + if (tlist.numberOfItems === 0) { selected.removeAttribute('transform'); } - return null; - } - // if it was a translate, put back the rotate at the new center + return null; + } // if it was a translate, put back the rotate at the new center + + if (operation === 2) { if (gangle) { newcenter = { @@ -11421,14 +12605,16 @@ }; var _newRot = svgroot.createSVGTransform(); + _newRot.setRotate(gangle, newcenter.x, newcenter.y); + if (tlist.numberOfItems) { tlist.insertItemBefore(_newRot, 0); } else { tlist.appendItem(_newRot); } - } - // if it was a resize + } // if it was a resize + } else if (operation === 3) { var _m4 = transformListToTransform(tlist).matrix; var roldt = svgroot.createSVGTransform(); @@ -11436,6 +12622,7 @@ var rold = roldt.matrix; var rnew = svgroot.createSVGTransform(); rnew.setRotate(gangle, newcenter.x, newcenter.y); + var rnewInv = rnew.matrix.inverse(), _mInv = _m4.inverse(), extrat = matrixMultiply(_mInv, rnewInv, rold, _m4); @@ -11448,14 +12635,20 @@ // we pass the translates down to the individual children var _children3 = selected.childNodes; var _c3 = _children3.length; + while (_c3--) { var _child3 = _children3.item(_c3); + if (_child3.nodeType === 1) { oldStartTransform = context_.getStartTransform(); context_.setStartTransform(_child3.getAttribute('transform')); + var _childTlist3 = getTransformList(_child3); + var _newxlate = svgroot.createSVGTransform(); + _newxlate.setTranslate(tx, ty); + if (_childTlist3.numberOfItems) { _childTlist3.insertItemBefore(_newxlate, 0); } else { @@ -11475,33 +12668,39 @@ tlist.appendItem(rnew); } } - } - // else, it's a non-group + } // else, it's a non-group + } else { // FIXME: box might be null for some elements (<metadata> etc), need to handle this - var _box = getBBox(selected); - - // Paths (and possbly other shapes) will have no BBox while still in <defs>, + var _box = getBBox(selected); // Paths (and possbly other shapes) will have no BBox while still in <defs>, // but we still may need to recalculate them (see issue 595). // TODO: Figure out how to get BBox from these elements in case they // have a rotation transform + if (!_box && selected.tagName !== 'path') return null; - var _m5 = svgroot.createSVGMatrix(); + var _m5; // = svgroot.createSVGMatrix(); // temporarily strip off the rotate and save the old center + + var _angle = getRotationAngle(selected); + if (_angle) { - oldcenter = { x: _box.x + _box.width / 2, y: _box.y + _box.height / 2 }; + oldcenter = { + x: _box.x + _box.width / 2, + y: _box.y + _box.height / 2 + }; newcenter = transformPoint(_box.x + _box.width / 2, _box.y + _box.height / 2, transformListToTransform(tlist).matrix); var _a = _angle * Math.PI / 180; - var _s = Math.abs(_a) > 1.0e-10 ? Math.sin(_a) / (1 - Math.cos(_a)) - // FIXME: This blows up if the angle is exactly 0! + + var _s = Math.abs(_a) > 1.0e-10 ? Math.sin(_a) / (1 - Math.cos(_a)) // FIXME: This blows up if the angle is exactly 0! : 2 / _a; for (var _i2 = 0; _i2 < tlist.numberOfItems; ++_i2) { var _xform3 = tlist.getItem(_i2); + if (_xform3.type === 4) { // extract old center through mystical arts var _rm = _xform3.matrix; @@ -11511,22 +12710,23 @@ break; } } - } + } // 2 = translate, 3 = scale, 4 = rotate, 1 = matrix imposition + - // 2 = translate, 3 = scale, 4 = rotate, 1 = matrix imposition var _operation = 0; - var _N = tlist.numberOfItems; - - // Check if it has a gradient with userSpaceOnUse, in which case + var _N = tlist.numberOfItems; // Check if it has a gradient with userSpaceOnUse, in which case // adjust it by recalculating the matrix transform. // TODO: Make this work in Webkit using transformlist.SVGTransformList + if (!isWebkit()) { var fill = selected.getAttribute('fill'); + if (fill && fill.startsWith('url(')) { var paint = getRefElem(fill); var type = 'pattern'; if (paint.tagName !== type) type = 'gradient'; var attrVal = paint.getAttribute(type + 'Units'); + if (attrVal === 'userSpaceOnUse') { // Update the userSpaceOnUse element _m5 = transformListToTransform(tlist).matrix; @@ -11537,79 +12737,94 @@ paint.setAttribute(type + 'Transform', mStr); } } - } - - // first, if it was a scale of a non-skewed element, then the second-last + } // first, if it was a scale of a non-skewed element, then the second-last // transform will be the [S] // if we had [M][T][S][T] we want to extract the matrix equivalent of // [T][S][T] and push it down to the element + + if (_N >= 3 && tlist.getItem(_N - 2).type === 3 && tlist.getItem(_N - 3).type === 2 && tlist.getItem(_N - 1).type === 2) { // Removed this so a <use> with a given [T][S][T] would convert to a matrix. // Is that bad? // && selected.nodeName != 'use' _operation = 3; // scale + _m5 = transformListToTransform(tlist, _N - 3, _N - 1).matrix; tlist.removeItem(_N - 1); tlist.removeItem(_N - 2); - tlist.removeItem(_N - 3); - // if we had [T][S][-T][M], then this was a skewed element being resized + tlist.removeItem(_N - 3); // if we had [T][S][-T][M], then this was a skewed element being resized // Thus, we simply combine it all into one matrix } else if (_N === 4 && tlist.getItem(_N - 1).type === 1) { _operation = 3; // scale + _m5 = transformListToTransform(tlist).matrix; + var _e2t2 = svgroot.createSVGTransform(); + _e2t2.setMatrix(_m5); + tlist.clear(); - tlist.appendItem(_e2t2); - // reset the matrix so that the element is not re-mapped - _m5 = svgroot.createSVGMatrix(); - // if we had [R][T][S][-T][M], then this was a rotated matrix-element + tlist.appendItem(_e2t2); // reset the matrix so that the element is not re-mapped + + _m5 = svgroot.createSVGMatrix(); // if we had [R][T][S][-T][M], then this was a rotated matrix-element // if we had [T1][M] we want to transform this into [M][T2] // therefore [ T2 ] = [ M_inv ] [ T1 ] [ M ] and we can push [T2] // down to the element } else if ((_N === 1 || _N > 1 && tlist.getItem(1).type !== 3) && tlist.getItem(0).type === 2) { _operation = 2; // translate + var oldxlate = tlist.getItem(0).matrix, meq = transformListToTransform(tlist, 1).matrix, meqInv = meq.inverse(); _m5 = matrixMultiply(meqInv, oldxlate, meq); - tlist.removeItem(0); - // else if this child now has a matrix imposition (from a parent group) + tlist.removeItem(0); // else if this child now has a matrix imposition (from a parent group) // we might be able to simplify } else if (_N === 1 && tlist.getItem(0).type === 1 && !_angle) { // Remap all point-based elements _m5 = transformListToTransform(tlist).matrix; + switch (selected.tagName) { case 'line': changes = $$7(selected).attr(['x1', 'y1', 'x2', 'y2']); // Fallthrough + case 'polyline': case 'polygon': changes.points = selected.getAttribute('points'); + if (changes.points) { var _list = selected.points; var _len = _list.numberOfItems; changes.points = new Array(_len); + for (var _i3 = 0; _i3 < _len; ++_i3) { var _pt = _list.getItem(_i3); - changes.points[_i3] = { x: _pt.x, y: _pt.y }; + + changes.points[_i3] = { + x: _pt.x, + y: _pt.y + }; } } + // Fallthrough + case 'path': changes.d = selected.getAttribute('d'); _operation = 1; tlist.clear(); break; + default: break; - } - // if it was a rotation, put the rotate back and return without a command + } // if it was a rotation, put the rotate back and return without a command // (this function has zero work to do for a rotate()) + } else { - _operation = 4; // rotation + // operation = 4; // rotation if (_angle) { var _newRot2 = svgroot.createSVGTransform(); + _newRot2.setRotate(_angle, newcenter.x, newcenter.y); if (tlist.numberOfItems) { @@ -11618,18 +12833,21 @@ tlist.appendItem(_newRot2); } } + if (tlist.numberOfItems === 0) { selected.removeAttribute('transform'); } - return null; - } - // if it was a translate or resize, we need to remap the element and absorb the xform + return null; + } // if it was a translate or resize, we need to remap the element and absorb the xform + + if (_operation === 1 || _operation === 2 || _operation === 3) { remapElement(selected, changes, _m5); } // if we are remapping - // if it was a translate, put back the rotate at the new center + + if (_operation === 2) { if (_angle) { if (!hasMatrixTransform(tlist)) { @@ -11638,22 +12856,28 @@ y: oldcenter.y + _m5.f }; } + var _newRot3 = svgroot.createSVGTransform(); + _newRot3.setRotate(_angle, newcenter.x, newcenter.y); + if (tlist.numberOfItems) { tlist.insertItemBefore(_newRot3, 0); } else { tlist.appendItem(_newRot3); } - } - // We have special processing for tspans: Tspans are not transformable + } // We have special processing for tspans: Tspans are not transformable // but they can have x,y coordinates (sigh). Thus, if this was a translate, // on a text element, also translate any tspan children. + + if (selected.tagName === 'text') { var _children4 = selected.childNodes; var _c4 = _children4.length; + while (_c4--) { var _child4 = _children4.item(_c4); + if (_child4.tagName === 'tspan') { var tspanChanges = { x: $$7(_child4).attr('x') || 0, @@ -11662,23 +12886,33 @@ remapElement(_child4, tspanChanges, _m5); } } - } - // [Rold][M][T][S][-T] became [Rold][M] + } // [Rold][M][T][S][-T] became [Rold][M] // we want it to be [Rnew][M][Tr] where Tr is the // translation required to re-center it // Therefore, [Tr] = [M_inv][Rnew_inv][Rold][M] + } else if (_operation === 3 && _angle) { - var _m6 = transformListToTransform(tlist).matrix; + var _transformListToTrans = transformListToTransform(tlist), + matrix = _transformListToTrans.matrix; + var _roldt = svgroot.createSVGTransform(); + _roldt.setRotate(_angle, oldcenter.x, oldcenter.y); + var _rold = _roldt.matrix; + var _rnew = svgroot.createSVGTransform(); + _rnew.setRotate(_angle, newcenter.x, newcenter.y); + var _rnewInv = _rnew.matrix.inverse(); - var _mInv2 = _m6.inverse(); - var _extrat = matrixMultiply(_mInv2, _rnewInv, _rold, _m6); + + var _mInv2 = matrix.inverse(); + + var _extrat = matrixMultiply(_mInv2, _rnewInv, _rold, matrix); remapElement(selected, changes, _extrat); + if (_angle) { if (tlist.numberOfItems) { tlist.insertItemBefore(_rnew, 0); @@ -11688,54 +12922,52 @@ } } } // a non-group - // if the transform list has been emptied, remove it + + if (tlist.numberOfItems === 0) { selected.removeAttribute('transform'); } batchCmd.addSubCommand(new ChangeElementCommand(selected, initial)); - return batchCmd; }; - /* globals jQuery */ - var $$8 = jQuery; + var svgFactory_; + var config_; + var selectorManager_; // A Singleton - var svgFactory_ = void 0; - var config_ = void 0; - var selectorManager_ = void 0; // A Singleton var gripRadius = isTouch() ? 10 : 4; - /** - * Private class for DOM element selection boxes + * Private class for DOM element selection boxes. */ - var Selector = function () { + + var Selector = + /*#__PURE__*/ + function () { /** * @param {Integer} id - Internally identify the selector * @param {Element} elem - DOM element associated with this selector * @param {module:utilities.BBoxObject} [bbox] - Optional bbox to use for initialization (prevents duplicate `getBBox` call). */ function Selector(id, elem, bbox) { - classCallCheck(this, Selector); + _classCallCheck(this, Selector); // this is the selector's unique number - this.id = id; + this.id = id; // this holds a reference to the element for which this selector is being used - // this holds a reference to the element for which this selector is being used - this.selectedElement = elem; + this.selectedElement = elem; // this is a flag used internally to track whether the selector is being used or not - // this is a flag used internally to track whether the selector is being used or not - this.locked = true; + this.locked = true; // this holds a reference to the <g> element that holds all visual elements of the selector - // this holds a reference to the <g> element that holds all visual elements of the selector this.selectorGroup = svgFactory_.createSVGElement({ element: 'g', - attr: { id: 'selectorGroup' + this.id } - }); + attr: { + id: 'selectorGroup' + this.id + } + }); // this holds a reference to the path rect - // this holds a reference to the path rect this.selectorRect = this.selectorGroup.appendChild(svgFactory_.createSVGElement({ element: 'path', attr: { @@ -11747,9 +12979,8 @@ // need to specify this so that the rect is not selectable style: 'pointer-events:none' } - })); + })); // this holds a reference to the grip coordinates for this selector - // this holds a reference to the grip coordinates for this selector this.gripCoords = { nw: null, n: null, @@ -11760,80 +12991,51 @@ sw: null, w: null }; - this.reset(this.selectedElement, bbox); } - /** - * Used to reset the id and element that the selector is attached to + * Used to reset the id and element that the selector is attached to. * @param {Element} e - DOM element associated with this selector * @param {module:utilities.BBoxObject} bbox - Optional bbox to use for reset (prevents duplicate getBBox call). + * @returns {undefined} */ - createClass(Selector, [{ - key: 'reset', + _createClass(Selector, [{ + key: "reset", value: function reset(e, bbox) { this.locked = true; this.selectedElement = e; this.resize(bbox); 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 - */ - - }, { - key: 'updateGripCursors', - value: function updateGripCursors(angle) { - var dir = void 0; - var dirArr = []; - var 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--; - } - var 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 + * @returns {undefined} */ }, { - key: 'showGrips', + key: "showGrips", value: function showGrips(show) { var bShow = show ? 'inline' : 'none'; selectorManager_.selectorGripsGroup.setAttribute('display', bShow); var elem = this.selectedElement; this.hasGrips = show; + if (elem && show) { this.selectorGroup.append(selectorManager_.selectorGripsGroup); - this.updateGripCursors(getRotationAngle(elem)); + Selector.updateGripCursors(getRotationAngle(elem)); } } - /** - * Updates the selector to match the element's size + * Updates the selector to match the element's size. * @param {module:utilities.BBoxObject} [bbox] - BBox to use for resize (prevents duplicate getBBox call). + * @returns {undefined} */ }, { - key: 'resize', + key: "resize", value: function resize(bbox) { var selectedBox = this.selectorRect, mgr = selectorManager_, @@ -11842,6 +13044,7 @@ sw = selected.getAttribute('stroke-width'), currentZoom = svgFactory_.getCurrentZoom(); var offset = 1 / currentZoom; + if (selected.getAttribute('stroke') !== 'none' && !isNaN(sw)) { offset += sw / 2; } @@ -11850,57 +13053,53 @@ if (tagName === 'text') { offset += 2 / currentZoom; - } + } // loop and transform our bounding box until we reach our first rotation + - // loop and transform our bounding box until we reach our first rotation var tlist = getTransformList(selected); - var m = transformListToTransform(tlist).matrix; - - // This should probably be handled somewhere else, but for now + var m = transformListToTransform(tlist).matrix; // This should probably be handled somewhere else, but for now // it keeps the selection box correctly positioned when zoomed + m.e *= currentZoom; m.f *= currentZoom; if (!bbox) { bbox = getBBox(selected); - } - // TODO: getBBox (previous line) already knows to call getStrokedBBox when tagName === 'g'. Remove this? + } // TODO: getBBox (previous line) already knows to call getStrokedBBox when tagName === 'g'. Remove this? // TODO: getBBox doesn't exclude 'gsvg' and calls getStrokedBBox for any 'g'. Should getBBox be updated? + + if (tagName === 'g' && !$$8.data(selected, 'gsvg')) { // The bbox for a group does not include stroke vals, so we // get the bbox based on its children. var strokedBbox = getStrokedBBox([selected.childNodes]); + if (strokedBbox) { bbox = strokedBbox; } - } + } // apply the transforms + - // apply the transforms var l = bbox.x, t = bbox.y, w = bbox.width, - h = bbox.height; - bbox = { x: l, y: t, width: w, height: h }; - + h = bbox.height; // bbox = {x: l, y: t, width: w, height: h}; // Not in use // we need to handle temporary transforms too // if skewed, get its transformed box, then find its axis-aligned bbox - // * - offset *= currentZoom; + offset *= currentZoom; var nbox = transformBox(l * currentZoom, t * currentZoom, w * currentZoom, h * currentZoom, m), aabox = nbox.aabox; - var nbax = aabox.x - offset, nbay = aabox.y - offset, nbaw = aabox.width + offset * 2, - nbah = aabox.height + offset * 2; + nbah = aabox.height + offset * 2; // now if the shape is rotated, un-rotate it - // now if the shape is rotated, un-rotate it var cx = nbax + nbaw / 2, cy = nbay + nbah / 2; - var angle = getRotationAngle(selected); + if (angle) { var rot = svgFactory_.svgRoot().createSVGTransform(); rot.setRotate(-angle, cx, cy); @@ -11908,25 +13107,19 @@ nbox.tl = transformPoint(nbox.tl.x, nbox.tl.y, rotm); nbox.tr = transformPoint(nbox.tr.x, nbox.tr.y, rotm); nbox.bl = transformPoint(nbox.bl.x, nbox.bl.y, rotm); - nbox.br = transformPoint(nbox.br.x, nbox.br.y, rotm); + nbox.br = transformPoint(nbox.br.x, nbox.br.y, rotm); // calculate the axis-aligned bbox - // calculate the axis-aligned bbox var tl = nbox.tl; - var minx = tl.x, miny = tl.y, maxx = tl.x, maxy = tl.y; - var min = Math.min, max = Math.max; - - minx = min(minx, min(nbox.tr.x, min(nbox.bl.x, nbox.br.x))) - offset; miny = min(miny, min(nbox.tr.y, min(nbox.bl.y, nbox.br.y))) - offset; maxx = max(maxx, max(nbox.tr.x, max(nbox.bl.x, nbox.br.x))) + offset; maxy = max(maxy, max(nbox.tr.y, max(nbox.bl.y, nbox.br.y))) + offset; - nbax = minx; nbay = miny; nbaw = maxx - minx; @@ -11935,12 +13128,10 @@ var dstr = 'M' + nbax + ',' + nbay + ' L' + (nbax + nbaw) + ',' + nbay + ' ' + (nbax + nbaw) + ',' + (nbay + nbah) + ' ' + nbax + ',' + (nbay + nbah) + 'z'; selectedBox.setAttribute('d', dstr); - var xform = angle ? 'rotate(' + [angle, cx, cy].join(',') + ')' : ''; - this.selectorGroup.setAttribute('transform', xform); - - // TODO(codedread): Is this needed? + this.selectorGroup.setAttribute('transform', xform); // TODO(codedread): Is this needed? // if (selected === selectedElements[0]) { + this.gripCoords = { nw: [nbax, nbay], ne: [nbax + nbaw, nbay], @@ -11951,46 +13142,69 @@ e: [nbax + nbaw, nbay + nbah / 2], s: [nbax + nbaw / 2, nbay + nbah] }; - for (var dir in this.gripCoords) { - var coords = this.gripCoords[dir]; + Object.entries(this.gripCoords).forEach(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + dir = _ref2[0], + coords = _ref2[1]; + selectedGrips[dir].setAttribute('cx', coords[0]); selectedGrips[dir].setAttribute('cy', coords[1]); - } + }); // we want to go 20 pixels in the negative transformed y direction, ignoring scale - // we want to go 20 pixels in the negative transformed y direction, ignoring scale mgr.rotateGripConnector.setAttribute('x1', nbax + nbaw / 2); mgr.rotateGripConnector.setAttribute('y1', nbay); mgr.rotateGripConnector.setAttribute('x2', nbax + nbaw / 2); mgr.rotateGripConnector.setAttribute('y2', nbay - gripRadius * 5); - mgr.rotateGrip.setAttribute('cx', nbax + nbaw / 2); - mgr.rotateGrip.setAttribute('cy', nbay - gripRadius * 5); - // } + mgr.rotateGrip.setAttribute('cy', nbay - gripRadius * 5); // } } }]); + return Selector; }(); - /** - * Manage all selector objects (selection boxes) + * Updates cursors for corner grips on rotation so arrows point the right way. + * @param {Float} angle - Current rotation angle in degrees + * @returns {undefined} */ - var SelectorManager = function () { + + Selector.updateGripCursors = function (angle) { + var dirArr = Object.keys(selectorManager_.selectorGrips); + var steps = Math.round(angle / 45); + + if (steps < 0) { + steps += 8; + } + + while (steps > 0) { + dirArr.push(dirArr.shift()); + steps--; + } + + Object.values(selectorManager_.selectorGrips).forEach(function (gripElement, i) { + gripElement.setAttribute('style', 'cursor:' + dirArr[i] + '-resize'); + }); + }; + /** + * Manage all selector objects (selection boxes). + */ + + + var SelectorManager = + /*#__PURE__*/ + function () { function SelectorManager() { - classCallCheck(this, SelectorManager); + _classCallCheck(this, SelectorManager); // this will hold the <g> element that contains all selector rects/grips - this.selectorParentGroup = null; + this.selectorParentGroup = null; // this is a special rect that is used for multi-select - // this is a special rect that is used for multi-select - this.rubberBandBox = null; + this.rubberBandBox = null; // this will hold objects of type Selector (see above) - // this will hold objects of type Selector (see above) - this.selectors = []; + this.selectors = []; // this holds a map of SVG elements to their Selector object - // this holds a map of SVG elements to their Selector object - this.selectorMap = {}; + this.selectorMap = {}; // this holds a reference to the grip elements - // this holds a reference to the grip elements this.selectorGrips = { nw: null, n: null, @@ -12001,45 +13215,47 @@ sw: null, w: null }; - this.selectorGripsGroup = null; this.rotateGripConnector = null; this.rotateGrip = null; - this.initGroup(); } - /** - * Resets the parent selector group element + * Resets the parent selector group element. + * @returns {undefined} */ - createClass(SelectorManager, [{ - key: 'initGroup', + _createClass(SelectorManager, [{ + key: "initGroup", value: function initGroup() { + var _this = this; + // remove old selector parent group if it existed if (this.selectorParentGroup && this.selectorParentGroup.parentNode) { this.selectorParentGroup.remove(); - } + } // create parent selector group and add it to svgroot + - // create parent selector group and add it to svgroot this.selectorParentGroup = svgFactory_.createSVGElement({ element: 'g', - attr: { id: 'selectorParentGroup' } + attr: { + id: 'selectorParentGroup' + } }); this.selectorGripsGroup = svgFactory_.createSVGElement({ element: 'g', - attr: { display: 'none' } + attr: { + display: 'none' + } }); this.selectorParentGroup.append(this.selectorGripsGroup); svgFactory_.svgRoot().append(this.selectorParentGroup); - this.selectorMap = {}; this.selectors = []; - this.rubberBandBox = null; + this.rubberBandBox = null; // add the corner grips - // add the corner grips - for (var dir in this.selectorGrips) { + Object.keys(this.selectorGrips).forEach(function (dir) { var grip = svgFactory_.createSVGElement({ element: 'circle', attr: { @@ -12055,13 +13271,11 @@ 'pointer-events': 'all' } }); - $$8.data(grip, 'dir', dir); $$8.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(svgFactory_.createSVGElement({ element: 'line', attr: { @@ -12070,7 +13284,6 @@ 'stroke-width': '1' } })); - this.rotateGrip = this.selectorGripsGroup.appendChild(svgFactory_.createSVGElement({ element: 'circle', attr: { @@ -12088,7 +13301,7 @@ return; } - var _config_$dimensions = slicedToArray(config_.dimensions, 2), + var _config_$dimensions = _slicedToArray(config_.dimensions, 2), width = _config_$dimensions[0], height = _config_$dimensions[1]; @@ -12100,11 +13313,11 @@ height: height, x: 0, y: 0, - overflow: isWebkit() ? 'none' : 'visible', // Chrome 7 has a problem with this when zooming out + overflow: isWebkit() ? 'none' : 'visible', + // Chrome 7 has a problem with this when zooming out style: 'pointer-events:none' } }); - var rect = svgFactory_.createSVGElement({ element: 'rect', attr: { @@ -12117,16 +13330,13 @@ fill: '#FFF', style: 'pointer-events:none' } - }); - - // Both Firefox and WebKit are too slow with this filter region (especially at higher + }); // Both Firefox and WebKit are too slow with this filter region (especially at higher // zoom levels) and Opera has at least one bug // if (!isOpera()) rect.setAttribute('filter', 'url(#canvashadow)'); - canvasbg.append(rect); - svgFactory_.svgRoot().insertBefore(canvasbg, svgFactory_.svgContent()); - // Ok to replace above with `svgFactory_.svgContent().before(canvasbg);`? - } + canvasbg.append(rect); + svgFactory_.svgRoot().insertBefore(canvasbg, svgFactory_.svgContent()); // Ok to replace above with `svgFactory_.svgContent().before(canvasbg);`? + } /** * * @param {Element} elem - DOM element to get the selector for @@ -12135,18 +13345,19 @@ */ }, { - key: 'requestSelector', + key: "requestSelector", value: function requestSelector(elem, bbox) { - if (elem == null) { + if (isNullish(elem)) { return null; } - var N = this.selectors.length; - // If we've already acquired one for this element, return it. + var N = this.selectors.length; // If we've already acquired one for this element, return it. + if (_typeof(this.selectorMap[elem.id]) === 'object') { this.selectorMap[elem.id].locked = true; return this.selectorMap[elem.id]; } + for (var i = 0; i < N; ++i) { if (this.selectors[i] && !this.selectors[i].locked) { this.selectors[i].locked = true; @@ -12154,40 +13365,43 @@ this.selectorMap[elem.id] = this.selectors[i]; return this.selectors[i]; } - } - // if we reached here, no available selectors were found, we create one + } // if we reached here, no available selectors were found, we create one + + this.selectors[N] = new Selector(N, elem, bbox); this.selectorParentGroup.append(this.selectors[N].selectorGroup); this.selectorMap[elem.id] = this.selectors[N]; return this.selectors[N]; } - /** - * Removes the selector of the given element (hides selection box) + * Removes the selector of the given element (hides selection box). * * @param {Element} elem - DOM element to remove the selector for + * @returns {undefined} */ }, { - key: 'releaseSelector', + key: "releaseSelector", value: function releaseSelector(elem) { - if (elem == null) { + if (isNullish(elem)) { return; } + var N = this.selectors.length, sel = this.selectorMap[elem.id]; + if (!sel.locked) { // TODO(codedread): Ensure this exists in this module. - console.log('WARNING! selector was released but was already unlocked'); + console.log('WARNING! selector was released but was already unlocked'); // eslint-disable-line no-console } + for (var i = 0; i < N; ++i) { if (this.selectors[i] && this.selectors[i] === sel) { delete this.selectorMap[elem.id]; sel.locked = false; sel.selectedElement = null; - sel.showGrips(false); + sel.showGrips(false); // remove from DOM and store reference in JS but only if it exists in the DOM - // remove from DOM and store reference in JS but only if it exists in the DOM try { sel.selectorGroup.setAttribute('display', 'none'); } catch (e) {} @@ -12196,14 +13410,13 @@ } } } - /** * @returns {SVGRectElement} The rubberBandBox DOM element. This is the rectangle drawn by * the user for selecting/zooming */ }, { - key: 'getRubberBandBox', + key: "getRubberBandBox", value: function getRubberBandBox() { if (!this.rubberBandBox) { this.rubberBandBox = this.selectorParentGroup.appendChild(svgFactory_.createSVGElement({ @@ -12219,30 +13432,35 @@ } })); } + return this.rubberBandBox; } }]); + return SelectorManager; }(); - /** * An object that creates SVG elements for the canvas. * * @interface module:select.SVGFactory */ + /** * @function module:select.SVGFactory#createSVGElement * @param {module:utilities.EditorContext#addSVGElementFromJson} jsonMap * @returns {SVGElement} */ + /** * @function module:select.SVGFactory#svgRoot * @returns {SVGSVGElement} */ + /** * @function module:select.SVGFactory#svgContent * @returns {SVGSVGElement} */ + /** * @function module:select.SVGFactory#getCurrentZoom * @returns {Float} @@ -12254,6 +13472,7 @@ * @property {Float} 0 Width * @property {Float} 1 Height */ + /** * @typedef {PlainObject} module:select.Config * @property {string} imgPath @@ -12267,23 +13486,22 @@ * @param {module:select.SVGFactory} svgFactory - An object implementing the SVGFactory interface. * @returns {undefined} */ + var init$6 = function init(config, svgFactory) { config_ = config; svgFactory_ = svgFactory; selectorManager_ = new SelectorManager(); }; - /** * @function module:select.getSelectorManager * @returns {module:select.SelectorManager} The SelectorManager instance. */ + var getSelectorManager = function getSelectorManager() { return selectorManager_; }; - /* eslint-disable indent */ - - var $$9 = jqPluginSVG(jQuery); + var $$9 = jQueryPluginSVG(jQuery); var MoveElementCommand$1 = MoveElementCommand, InsertElementCommand$1 = InsertElementCommand, RemoveElementCommand$1 = RemoveElementCommand, @@ -12292,22 +13510,29 @@ UndoManager$1 = UndoManager, HistoryEventTypes$1 = HistoryEventTypes; - if (!window.console) { window.console = {}; - window.console.log = function (str) {}; - window.console.dir = function (str) {}; + + window.console.log = function (str) { + /* */ + }; + + window.console.dir = function (str) { + /* */ + }; } if (window.opera) { window.console.log = function (str) { window.opera.postError(str); }; - window.console.dir = function (str) {}; - } + window.console.dir = function (str) { + /* */ + }; + } /** - * The main SvgCanvas class that manages all SVG-related functions + * The main SvgCanvas class that manages all SVG-related functions. * @memberof module:svgcanvas * * @borrows module:coords.remapElement as #remapElement @@ -12335,62 +13560,58 @@ * @borrows module:path.pathActions.linkControlPoints as #linkControlPoints */ + var SvgCanvas = /** * @param {HTMLElement} container - The container HTML element that should hold the SVG root element * @param {module:SVGEditor.curConfig} config - An object that contains configuration data */ function SvgCanvas(container, config) { - classCallCheck(this, SvgCanvas); + _classCallCheck(this, SvgCanvas); // Alias Namespace constants - // Default configuration options var curConfig = { show_outside_canvas: true, selectNew: true, dimensions: [640, 480] - }; + }; // Update config with new one if given - // Update config with new one if given if (config) { $$9.extend(curConfig, config); - } + } // Array with width/height of canvas + - // Array with width/height of canvas var dimensions = curConfig.dimensions; - - - var canvas = this; - + var canvas = this; // eslint-disable-line consistent-this // "document" element associated with the container (same as window.document using default svg-editor.js) // NOTE: This is not actually a SVG document, but an HTML document. - var svgdoc = container.ownerDocument; - // This is a container for the document being edited, not the document itself. + var svgdoc = container.ownerDocument; // This is a container for the document being edited, not the document itself. + /** * @name module:svgcanvas~svgroot * @type {SVGSVGElement} */ + var svgroot = svgdoc.importNode(text2xml('<svg id="svgroot" xmlns="' + NS.SVG + '" xlinkns="' + NS.XLINK + '" ' + 'width="' + dimensions[0] + '" height="' + dimensions[1] + '" x="' + dimensions[0] + '" y="' + dimensions[1] + '" overflow="visible">' + '<defs>' + '<filter id="canvashadow" filterUnits="objectBoundingBox">' + '<feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur"/>' + '<feOffset in="blur" dx="5" dy="5" result="offsetBlur"/>' + '<feMerge>' + '<feMergeNode in="offsetBlur"/>' + '<feMergeNode in="SourceGraphic"/>' + '</feMerge>' + '</filter>' + '</defs>' + '</svg>').documentElement, true); container.append(svgroot); - /** * The actual element that represents the final output SVG element * @name module:svgcanvas~svgcontent * @type {SVGSVGElement} */ - var svgcontent = svgdoc.createElementNS(NS.SVG, 'svg'); + var svgcontent = svgdoc.createElementNS(NS.SVG, 'svg'); /** * This function resets the svgcontent element while keeping it in the DOM. * @function module:svgcanvas.SvgCanvas#clearSvgContentElement * @returns {undefined} */ - var clearSvgContentElement = canvas.clearSvgContentElement = function () { - $$9(svgcontent).empty(); - // TODO: Clear out all other attributes first? + var clearSvgContentElement = canvas.clearSvgContentElement = function () { + $$9(svgcontent).empty(); // TODO: Clear out all other attributes first? + $$9(svgcontent).attr({ id: 'svgcontent', width: dimensions[0], @@ -12401,53 +13622,52 @@ xmlns: NS.SVG, 'xmlns:se': NS.SE, 'xmlns:xlink': NS.XLINK - }).appendTo(svgroot); + }).appendTo(svgroot); // TODO: make this string optional and set by the client - // TODO: make this string optional and set by the client var comment = svgdoc.createComment(' Created with SVG-edit - https://github.com/SVG-Edit/svgedit'); svgcontent.append(comment); }; - clearSvgContentElement(); - // Prefix string for element IDs + clearSvgContentElement(); // Prefix string for element IDs + var idprefix = 'svg_'; - /** - * Changes the ID prefix to the given value + * Changes the ID prefix to the given value. * @function module:svgcanvas.SvgCanvas#setIdPrefix * @param {string} p - String with the new prefix * @returns {undefined} */ + canvas.setIdPrefix = function (p) { idprefix = p; }; - /** * Current draw.Drawing object * @type {module:draw.Drawing} * @name module:svgcanvas.SvgCanvas#current_drawing_ */ - canvas.current_drawing_ = new Drawing(svgcontent, idprefix); + + canvas.current_drawing_ = new Drawing(svgcontent, idprefix); /** * Returns the current Drawing. * @function module:svgcanvas.SvgCanvas#getCurrentDrawing * @implements {module:draw.DrawCanvasInit#getCurrentDrawing} */ + var getCurrentDrawing = canvas.getCurrentDrawing = function () { return canvas.current_drawing_; }; - /** * Float displaying the current zoom level (1 = 100%, .5 = 50%, etc) * @type {Float} */ - var currentZoom = 1; - // pointer to current group (for in-group editing) - var currentGroup = null; - // Object containing data for the currently selected styles + var currentZoom = 1; // pointer to current group (for in-group editing) + + var currentGroup = null; // Object containing data for the currently selected styles + var allProperties = { shape: { fill: (curConfig.initFill.color === 'none' ? '' : '#') + curConfig.initFill.color, @@ -12463,22 +13683,18 @@ opacity: curConfig.initOpacity } }; - allProperties.text = $$9.extend(true, {}, allProperties.shape); $$9.extend(allProperties.text, { fill: '#000000', stroke_width: curConfig.text && curConfig.text.stroke_width, font_size: curConfig.text && curConfig.text.font_size, font_family: curConfig.text && curConfig.text.font_family - }); + }); // Current shape style properties - // Current shape style properties - var curShape = allProperties.shape; - - // Array with all the currently selected elements + var curShape = allProperties.shape; // Array with all the currently selected elements // default size of 1 until it needs to grow bigger - var selectedElements = []; + var selectedElements = []; /** * @typedef {PlainObject} module:svgcanvas.SVGAsJSON * @property {string} element @@ -12491,52 +13707,55 @@ * @param {Text|Element} data * @returns {module:svgcanvas.SVGAsJSON} */ + var getJsonFromSvgElement = this.getJsonFromSvgElement = function (data) { // Text node if (data.nodeType === 3) return data.nodeValue; - var retval = { element: data.tagName, // namespace: nsMap[data.namespaceURI], attr: {}, children: [] - }; + }; // Iterate attributes - // Iterate attributes for (var i = 0, attr; attr = data.attributes[i]; i++) { retval.attr[attr.name] = attr.value; - } + } // Iterate children + - // Iterate children for (var _i = 0, node; node = data.childNodes[_i]; _i++) { retval.children[_i] = getJsonFromSvgElement(node); } return retval; }; - /** - * This should really be an intersection implementing all rather than a union + * This should really be an intersection implementing all rather than a union. * @function module:svgcanvas.SvgCanvas#addSVGElementFromJson * @implements {module:utilities.EditorContext#addSVGElementFromJson|module:path.EditorContext#addSVGElementFromJson} */ + + var addSVGElementFromJson = this.addSVGElementFromJson = function (data) { if (typeof data === 'string') return svgdoc.createTextNode(data); + var shape = getElem(data.attr.id); // if shape is a path but we need to create a rect/ellipse, then remove the path - var shape = getElem(data.attr.id); - // if shape is a path but we need to create a rect/ellipse, then remove the path var currentLayer = getCurrentDrawing().getCurrentLayer(); + if (shape && data.element !== shape.tagName) { shape.remove(); shape = null; } + if (!shape) { var ns = data.namespace || NS.SVG; shape = svgdoc.createElementNS(ns, data.element); + if (currentLayer) { (currentGroup || currentLayer).append(shape); } } + if (data.curStyles) { assignAttributes(shape, { fill: curShape.fill, @@ -12551,10 +13770,10 @@ style: 'pointer-events:inherit' }, 100); } - assignAttributes(shape, data.attr, 100); - cleanupElement(shape); - // Children + assignAttributes(shape, data.attr, 100); + cleanupElement(shape); // Children + if (data.children) { data.children.forEach(function (child) { shape.append(addSVGElementFromJson(child)); @@ -12565,22 +13784,22 @@ }; canvas.getTransformList = getTransformList; - canvas.matrixMultiply = matrixMultiply; canvas.hasMatrixTransform = hasMatrixTransform; canvas.transformListToTransform = transformListToTransform; - /** * @implements {module:utilities.EditorContext#getBaseUnit} */ + var getBaseUnit = function getBaseUnit() { return curConfig.baseUnit; }; - /** * initialize from units.js. * Send in an object implementing the ElementContainer interface (see units.js) */ + + init( /** * @implements {module:units.ElementContainer} @@ -12598,32 +13817,32 @@ return saveOptions.round_digits; } }); - canvas.convertToNum = convertToNum; - /** - * This should really be an intersection implementing all rather than a union + * This should really be an intersection implementing all rather than a union. * @implements {module:draw.DrawCanvasInit#getSVGContent|module:utilities.EditorContext#getSVGContent} */ + var getSVGContent = function getSVGContent() { return svgcontent; }; - /** - * Should really be an intersection with all needing to apply rather than a union + * Should really be an intersection with all needing to apply rather than a union. * @function module:svgcanvas.SvgCanvas#getSelectedElements * @implements {module:utilities.EditorContext#getSelectedElements|module:draw.DrawCanvasInit#getSelectedElements|module:path.EditorContext#getSelectedElements} */ + + var getSelectedElements = this.getSelectedElems = function () { return selectedElements; }; - var pathActions$$1 = pathActions; - + var pathActions$1 = pathActions; /** - * This should actually be an intersection as all interfaces should be met + * This should actually be an intersection as all interfaces should be met. * @implements {module:utilities.EditorContext#getSVGRoot|module:recalculate.EditorContext#getSVGRoot|module:coords.EditorContext#getSVGRoot|module:path.EditorContext#getSVGRoot} */ + var getSVGRoot = function getSVGRoot() { return svgroot; }; @@ -12633,7 +13852,8 @@ * @implements {module:utilities.EditorContext} */ { - pathActions: pathActions$$1, // Ok since not modifying + pathActions: pathActions$1, + // Ok since not modifying getSVGContent: getSVGContent, addSVGElementFromJson: addSVGElementFromJson, getSelectedElements: getSelectedElements, @@ -12643,7 +13863,6 @@ getDOMContainer: function getDOMContainer() { return container; }, - getSVGRoot: getSVGRoot, // TODO: replace this mostly with a way to get the current drawing. getBaseUnit: getBaseUnit, @@ -12651,23 +13870,23 @@ return curConfig.snappingStep; } }); - canvas.findDefs = findDefs; canvas.getUrlFromAttr = getUrlFromAttr; canvas.getHref = getHref; canvas.setHref = setHref; - /* const getBBox = */canvas.getBBox = getBBox; + /* const getBBox = */ + + canvas.getBBox = getBBox; canvas.getRotationAngle = getRotationAngle; canvas.getElem = getElem; canvas.getRefElem = getRefElem; canvas.assignAttributes = assignAttributes; - this.cleanupElement = cleanupElement; - /** - * This should actually be an intersection not a union as all should apply + * This should actually be an intersection not a union as all should apply. * @implements {module:coords.EditorContext|module:path.EditorContext} */ + var getGridSnapping = function getGridSnapping() { return curConfig.gridSnapping; }; @@ -12680,12 +13899,10 @@ getDrawing: function getDrawing() { return getCurrentDrawing(); }, - getSVGRoot: getSVGRoot, getGridSnapping: getGridSnapping }); this.remapElement = remapElement; - init$5( /** * @implements {module:recalculate.EditorContext} @@ -12699,17 +13916,16 @@ startTransform = transform; } }); - this.recalculateDimensions = recalculateDimensions; + this.recalculateDimensions = recalculateDimensions; // import from sanitize.js - // import from sanitize.js var nsMap = getReverseNS(); canvas.sanitizeSvg = sanitizeSvg; - /** * @name undoMgr * @memberof module:svgcanvas.SvgCanvas# * @type {module:history.HistoryEventHandler} */ + var undoMgr = canvas.undoMgr = new UndoManager$1({ /** * @param {string} eventType One of the HistoryEvent types @@ -12718,8 +13934,8 @@ * @returns {undefined} */ handleHistoryEvent: function handleHistoryEvent(eventType, cmd) { - var EventTypes = HistoryEventTypes$1; - // TODO: handle setBlurOffsets. + var EventTypes = HistoryEventTypes$1; // TODO: handle setBlurOffsets. + if (eventType === EventTypes.BEFORE_UNAPPLY || eventType === EventTypes.BEFORE_APPLY) { canvas.clearSelection(); } else if (eventType === EventTypes.AFTER_APPLY || eventType === EventTypes.AFTER_UNAPPLY) { @@ -12728,8 +13944,10 @@ call('changed', elems); var cmdType = cmd.type(); var isApply = eventType === EventTypes.AFTER_APPLY; + if (cmdType === MoveElementCommand$1.type()) { var parent = isApply ? cmd.newParent : cmd.oldParent; + if (parent === svgcontent) { identifyLayers(); } @@ -12737,15 +13955,15 @@ if (cmd.parent === svgcontent) { identifyLayers(); } + if (cmdType === InsertElementCommand$1.type()) { if (isApply) { restoreRefElems(cmd.elem); } - } else { - if (!isApply) { - restoreRefElems(cmd.elem); - } + } else if (!isApply) { + restoreRefElems(cmd.elem); } + if (cmd.elem.tagName === 'use') { setUseData(cmd.elem); } @@ -12754,12 +13972,12 @@ if (cmd.elem.tagName === 'title' && cmd.elem.parentNode.parentNode === svgcontent) { identifyLayers(); } - var values = isApply ? cmd.newValues : cmd.oldValues; - // If stdDeviation was changed, update the blur. + + var values = isApply ? cmd.newValues : cmd.oldValues; // If stdDeviation was changed, update the blur. + if (values.stdDeviation) { canvas.setBlurOffsets(cmd.elem.parentNode, values.stdDeviation); - } - // This is resolved in later versions of webkit, perhaps we should + } // This is resolved in later versions of webkit, perhaps we should // have a featured detection for correct 'use' behavior? // —————————— // Remove & Re-add hack for Webkit (issue 775) @@ -12773,36 +13991,39 @@ // // Ok to replace above with this? `sib.before(elem);` // } // } + } } } }); - /** - * This should really be an intersection applying to all types rather than a union + * This should really be an intersection applying to all types rather than a union. * @function module:svgcanvas~addCommandToHistory * @implements {module:path.EditorContext#addCommandToHistory|module:draw.DrawCanvasInit#addCommandToHistory} */ + var addCommandToHistory = function addCommandToHistory(cmd) { canvas.undoMgr.addCommandToHistory(cmd); }; - /** - * This should really be an intersection applying to all types rather than a union + * This should really be an intersection applying to all types rather than a union. * @function module:svgcanvas.SvgCanvas#getZoom * @implements {module:path.EditorContext#getCurrentZoom|module:select.SVGFactory#getCurrentZoom} */ + + var getCurrentZoom = this.getZoom = function () { return currentZoom; }; - /** * This method rounds the incoming value to the nearest value based on the `currentZoom` * @function module:svgcanvas.SvgCanvas#round * @implements {module:path.EditorContext#round} */ + + var round = this.round = function (val) { - return parseInt(val * currentZoom, 10) / currentZoom; + return parseInt(val * currentZoom) / currentZoom; }; init$6(curConfig, @@ -12820,7 +14041,6 @@ svgContent: function svgContent() { return svgcontent; }, - getCurrentZoom: getCurrentZoom }); /** @@ -12828,50 +14048,57 @@ * @name module:svgcanvas.SvgCanvas#selectorManager * @type {module:select.SelectorManager} */ - var selectorManager = this.selectorManager = getSelectorManager(); + var selectorManager = this.selectorManager = getSelectorManager(); /** * @function module:svgcanvas.SvgCanvas#getNextId * @implements {module:path.EditorContext#getNextId} */ + var getNextId = canvas.getNextId = function () { return getCurrentDrawing().getNextId(); }; - /** * @function module:svgcanvas.SvgCanvas#getId * @implements {module:path.EditorContext#getId} */ + + var getId = canvas.getId = function () { return getCurrentDrawing().getId(); }; - /** - * The "implements" should really be an intersection applying to all types rather than a union + * The "implements" should really be an intersection applying to all types rather than a union. * @function module:svgcanvas.SvgCanvas#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 {module:svgcanvas.SvgCanvas#event:GenericCanvasEvent} arg - Argument to pass through to the callback function. - * @returns {undefined} + * @returns {module:svgcanvas.EventHandlerReturn|undefined} */ + + var call = function call(ev, arg) { if (events[ev]) { return events[ev](window, arg); } - }; + return undefined; + }; /** * Clears the selection. The 'selected' handler is then optionally called. - * This should really be an intersection applying to all types rather than a union + * This should really be an intersection applying to all types rather than a union. * @function module:svgcanvas.SvgCanvas#clearSelection * @implements {module:draw.DrawCanvasInit#clearSelection|module:path.EditorContext#clearSelection} * @fires module:svgcanvas.SvgCanvas#event:selected */ + + var clearSelection = this.clearSelection = function (noCall) { selectedElements.forEach(function (elem) { - if (elem == null) { + if (isNullish(elem)) { return; } + selectorManager.releaseSelector(elem); }); selectedElements = []; @@ -12880,35 +14107,42 @@ call('selected', selectedElements); } }; - /** * Adds a list of elements to the selection. The 'selected' handler is then called. * @function module:svgcanvas.SvgCanvas#addToSelection * @implements {module:path.EditorContext#addToSelection} * @fires module:svgcanvas.SvgCanvas#event:selected */ + + var addToSelection = this.addToSelection = function (elemsToAdd, showGrips) { if (!elemsToAdd.length) { return; - } - // find the first null in our selectedElements array + } // find the first null in our selectedElements array + var j = 0; + while (j < selectedElements.length) { - if (selectedElements[j] == null) { + if (isNullish(selectedElements[j])) { break; } - ++j; - } - // now add each element consecutively + ++j; + } // now add each element consecutively + + var i = elemsToAdd.length; + while (i--) { var elem = elemsToAdd[i]; + if (!elem) { continue; } + var bbox = getBBox(elem); + if (!bbox) { continue; } @@ -12916,14 +14150,13 @@ if (elem.tagName === 'a' && elem.childNodes.length === 1) { // Make "a" element's child be the selected element elem = elem.firstChild; - } + } // if it's not already there, add it + - // if it's not already there, add it if (!selectedElements.includes(elem)) { - selectedElements[j] = elem; - - // only the first selectedBBoxes element is ever used in the codebase these days + selectedElements[j] = elem; // only the first selectedBBoxes element is ever used in the codebase these days // if (j === 0) selectedBBoxes[0] = utilsGetBBox(elem); + j++; var sel = selectorManager.requestSelector(elem, bbox); @@ -12932,75 +14165,80 @@ } } } + call('selected', selectedElements); if (showGrips || selectedElements.length === 1) { selectorManager.requestSelector(selectedElements[0]).showGrips(true); } else { selectorManager.requestSelector(selectedElements[0]).showGrips(false); - } - - // make sure the elements are in the correct order + } // make sure the elements are in the correct order // See: https://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-compareDocumentPosition + selectedElements.sort(function (a, b) { if (a && b && a.compareDocumentPosition) { - return 3 - (b.compareDocumentPosition(a) & 6); + return 3 - (b.compareDocumentPosition(a) & 6); // eslint-disable-line no-bitwise } - if (a == null) { + + if (isNullish(a)) { return 1; } - }); - // Make sure first elements are not null - while (selectedElements[0] == null) { + return 0; + }); // Make sure first elements are not null + + while (isNullish(selectedElements[0])) { selectedElements.shift(0); } }; - /** * @implements {module:path.EditorContext#getOpacity} */ + + var getOpacity = function getOpacity() { return curShape.opacity; }; - /** * @function module:svgcanvas.SvgCanvas#getMouseTarget * @implements {module:path.EditorContext#getMouseTarget} */ + + var getMouseTarget = this.getMouseTarget = function (evt) { - if (evt == null) { + if (isNullish(evt)) { return null; } - var mouseTarget = evt.target; - // if it was a <use>, Opera and WebKit return the SVGElementInstance + var mouseTarget = evt.target; // if it was a <use>, Opera and WebKit return the SVGElementInstance + if (mouseTarget.correspondingUseElement) { mouseTarget = mouseTarget.correspondingUseElement; - } - - // for foreign content, go up until we find the foreignObject + } // for foreign content, go up until we find the foreignObject // WebKit browsers set the mouse target to the svgcanvas div + + if ([NS.MATH, NS.HTML].includes(mouseTarget.namespaceURI) && mouseTarget.id !== 'svgcanvas') { while (mouseTarget.nodeName !== 'foreignObject') { mouseTarget = mouseTarget.parentNode; + if (!mouseTarget) { return svgroot; } } - } - - // Get the desired mouseTarget with jQuery selector-fu + } // Get the desired mouseTarget with jQuery selector-fu // If it's root-like, select the root + + var currentLayer = getCurrentDrawing().getCurrentLayer(); + if ([svgroot, container, svgcontent, currentLayer].includes(mouseTarget)) { return svgroot; } - var $target = $$9(mouseTarget); + var $target = $$9(mouseTarget); // If it's a selection grip, return the grip parent - // If it's a selection grip, return the grip parent if ($target.closest('#selectorParentGroup').length) { // While we could instead have just returned mouseTarget, // this makes it easier to indentify as being a selector grip @@ -13009,9 +14247,7 @@ while (mouseTarget.parentNode !== (currentGroup || currentLayer)) { mouseTarget = mouseTarget.parentNode; - } - - // + } // // // go up until we hit a child of a layer // while (mouseTarget.parentNode.parentNode.tagName == 'g') { // mouseTarget = mouseTarget.parentNode; @@ -13022,28 +14258,34 @@ // mouseTarget = svgroot; // } + return mouseTarget; }; - /** * @namespace {module:path.pathActions} pathActions * @memberof module:svgcanvas.SvgCanvas# * @see module:path.pathActions */ - canvas.pathActions = pathActions$$1; + + + canvas.pathActions = pathActions$1; /** * @implements {module:path.EditorContext#resetD} */ + function resetD(p) { - p.setAttribute('d', pathActions$$1.convertPath(p)); + p.setAttribute('d', pathActions$1.convertPath(p)); } + init$1( /** * @implements {module:path.EditorContext} */ { - selectorManager: selectorManager, // Ok since not changing - canvas: canvas, // Ok since not changing + selectorManager: selectorManager, + // Ok since not changing + canvas: canvas, + // Ok since not changing call: call, resetD: resetD, round: round, @@ -13070,36 +14312,39 @@ }, /** - * @param {boolean} closedSubpath - * @param {SVGCircleElement[]} grips + * @param {PlainObject} ptsInfo + * @param {boolean} ptsInfo.closedSubpath + * @param {SVGCircleElement[]} ptsInfo.grips * @fires module:svgcanvas.SvgCanvas#event:pointsAdded * @fires module:svgcanvas.SvgCanvas#event:selected + * @returns {undefined} */ addPtsToSelection: function addPtsToSelection(_ref) { var closedSubpath = _ref.closedSubpath, grips = _ref.grips; - // TODO: Correct this: - pathActions$$1.canDeleteNodes = true; - pathActions$$1.closed_subpath = closedSubpath; - call('pointsAdded', { closedSubpath: closedSubpath, grips: grips }); + pathActions$1.canDeleteNodes = true; + pathActions$1.closed_subpath = closedSubpath; + call('pointsAdded', { + closedSubpath: closedSubpath, + grips: grips + }); call('selected', grips); }, /** - * @param {ChangeElementCommand} cmd - * @param {SVGPathElement} elem + * @param {PlainObject} changes + * @param {ChangeElementCommand} changes.cmd + * @param {SVGPathElement} changes.elem * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ endChanges: function endChanges(_ref2) { var cmd = _ref2.cmd, elem = _ref2.elem; - addCommandToHistory(cmd); call('changed', [elem]); }, - getCurrentZoom: getCurrentZoom, getId: getId, getNextId: getNextId, @@ -13118,19 +14363,14 @@ drawnPath = dp; return drawnPath; }, - getSVGRoot: getSVGRoot - }); + }); // Interface strings, usually for title elements - // Interface strings, usually for title elements var uiStrings = {}; - var visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use'; var refAttrs = ['clip-path', 'fill', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'stroke']; + var elData = $$9.data; // Animation element to change the opacity of any newly created element - var elData = $$9.data; - - // Animation element to change the opacity of any newly created element var opacAni = document.createElementNS(NS.SVG, 'animate'); $$9(opacAni).attr({ attributeName: 'opacity', @@ -13142,18 +14382,17 @@ var restoreRefElems = function restoreRefElems(elem) { // Look for missing reference elements, restore any found var attrs = $$9(elem).attr(refAttrs); - for (var o in attrs) { - var val = attrs[o]; + Object.values(attrs).forEach(function (val) { if (val && val.startsWith('url(')) { var id = getUrlFromAttr(val).substr(1); var ref = getElem(id); + if (!ref) { findDefs().append(removedElements[id]); delete removedElements[id]; } } - } - + }); var childs = elem.getElementsByTagName('*'); if (childs.length) { @@ -13161,9 +14400,7 @@ restoreRefElems(childs[i]); } } - }; - - // (function () { + }; // (function () { // TODO For Issue 208: this is a start on a thumbnail // const svgthumb = svgdoc.createElementNS(NS.SVG, 'use'); // svgthumb.setAttribute('width', '100'); @@ -13178,84 +14415,71 @@ * @property {"embed"} [image] * @property {Integer} round_digits */ - // Object to contain image data for raster images that were found encodable + + var encodableImages = {}, + // Object with save options - - // Object with save options /** * @type {module:svgcanvas.SaveOptions} */ - saveOptions = { round_digits: 5 }, - - - // Object with IDs for imported files, to see if one was already added + saveOptions = { + round_digits: 5 + }, + // Object with IDs for imported files, to see if one was already added importIds = {}, - - - // Current text style properties + // Current text style properties curText = allProperties.text, - - - // Object to contain all included extensions + // Object to contain all included extensions extensions = {}, - - - // Map of deleted reference elements + // Map of deleted reference elements removedElements = {}; - - var - // String with image URL of last loadable image + var // String with image URL of last loadable image lastGoodImgUrl = curConfig.imgPath + 'logo.png', - - - // Boolean indicating whether or not a draw action has been started + // Boolean indicating whether or not a draw action has been started started = false, - - - // String with an element's initial transform attribute value + // String with an element's initial transform attribute value startTransform = null, - - - // String indicating the current editor mode + // String indicating the current editor mode currentMode = 'select', - - - // String with the current direction in which an element is being resized + // String with the current direction in which an element is being resized currentResizeMode = 'none', - - - // Current general properties + // Current general properties curProperties = curShape, - - - // Array with selected elements' Bounding box object + // Array with selected elements' Bounding box object // selectedBBoxes = new Array(1), - // The DOM element that was just selected justSelected = null, - - - // DOM element for selection rectangle drawn by the user + // DOM element for selection rectangle drawn by the user rubberBox = null, - - - // Array of current BBoxes, used in getIntersectionList(). + // Array of current BBoxes, used in getIntersectionList(). curBBoxes = [], - - - // Canvas point for the most recent right click + // Canvas point for the most recent right click lastClickPoint = null; + this.runExtension = function (name, action, vars) { + return this.runExtensions(action, vars, false, function (n) { + return n === name; + }); + }; /** * @typedef {module:svgcanvas.ExtensionMouseDownStatus|module:svgcanvas.ExtensionMouseUpStatus|module:svgcanvas.ExtensionIDsUpdatedStatus|module:locale.ExtensionLocaleData[]|undefined} module:svgcanvas.ExtensionStatus * @tutorial ExtensionDocs */ + /** * @callback module:svgcanvas.ExtensionVarBuilder * @param {string} name The name of the extension + * @returns {module:svgcanvas.SvgCanvas#event:ext-addLangData} */ + + /** + * @callback module:svgcanvas.ExtensionNameFilter + * @param {string} name + * @returns {boolean} + */ + /** * @todo Consider: Should this return an array by default, so extension results aren't overwritten? * @todo Would be easier to document if passing in object with key of action and vars as value; could then define an interface which tied both together @@ -13263,15 +14487,23 @@ * @param {"mouseDown"|"mouseMove"|"mouseUp"|"zoomChanged"|"IDsUpdated"|"canvasUpdated"|"toolButtonStateUpdate"|"selectedChanged"|"elementTransition"|"elementChanged"|"langReady"|"langChanged"|"addLangData"|"onNewDocument"|"workareaResized"} action * @param {module:svgcanvas.SvgCanvas#event:ext-mouseDown|module:svgcanvas.SvgCanvas#event:ext-mouseMove|module:svgcanvas.SvgCanvas#event:ext-mouseUp|module:svgcanvas.SvgCanvas#event:ext-zoomChanged|module:svgcanvas.SvgCanvas#event:ext-IDsUpdated|module:svgcanvas.SvgCanvas#event:ext-canvasUpdated|module:svgcanvas.SvgCanvas#event:ext-toolButtonStateUpdate|module:svgcanvas.SvgCanvas#event:ext-selectedChanged|module:svgcanvas.SvgCanvas#event:ext-elementTransition|module:svgcanvas.SvgCanvas#event:ext-elementChanged|module:svgcanvas.SvgCanvas#event:ext-langReady|module:svgcanvas.SvgCanvas#event:ext-langChanged|module:svgcanvas.SvgCanvas#event:ext-addLangData|module:svgcanvas.SvgCanvas#event:ext-onNewDocument|module:svgcanvas.SvgCanvas#event:ext-workareaResized|module:svgcanvas.ExtensionVarBuilder} [vars] * @param {boolean} [returnArray] + * @param {module:svgcanvas.ExtensionNameFilter} nameFilter * @returns {GenericArray.<module:svgcanvas.ExtensionStatus>|module:svgcanvas.ExtensionStatus|false} See {@tutorial ExtensionDocs} on the ExtensionStatus. */ - var runExtensions = this.runExtensions = function (action, vars, returnArray) { + + + var runExtensions = this.runExtensions = function (action, vars, returnArray, nameFilter) { var result = returnArray ? [] : false; $$9.each(extensions, function (name, ext) { + if (nameFilter && !nameFilter(name)) { + return; + } + if (ext && action in ext) { if (typeof vars === 'function') { vars = vars(name); // ext, action } + if (returnArray) { result.push(ext[action](vars)); } else { @@ -13281,17 +14513,18 @@ }); return result; }; - /** * @typedef {PlainObject} module:svgcanvas.ExtensionMouseDownStatus * @property {boolean} started Indicates that creating/editing has started */ + /** * @typedef {PlainObject} module:svgcanvas.ExtensionMouseUpStatus * @property {boolean} keep Indicates if the current element should be kept * @property {boolean} started Indicates if editing should still be considered as "started" * @property {Element} element The element being affected */ + /** * @typedef {PlainObject} module:svgcanvas.ExtensionIDsUpdatedStatus * @property {string[]} remove Contains string IDs (used by `ext-connector.js`) @@ -13303,83 +14536,100 @@ * @property {module:SVGEditor.Button[]|PlainObject.<Integer, module:SVGEditor.Button>} [buttons] * @property {string} [svgicons] The location of a local SVG or SVGz file */ + /** * @function module:svgcanvas.ExtensionInitResponse#mouseDown * @param {module:svgcanvas.SvgCanvas#event:ext-mouseDown} arg * @returns {undefined|module:svgcanvas.ExtensionMouseDownStatus} */ + /** * @function module:svgcanvas.ExtensionInitResponse#mouseMove * @param {module:svgcanvas.SvgCanvas#event:ext-mouseMove} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#mouseUp * @param {module:svgcanvas.SvgCanvas#event:ext-mouseUp} arg * @returns {module:svgcanvas.ExtensionMouseUpStatus} */ + /** * @function module:svgcanvas.ExtensionInitResponse#zoomChanged * @param {module:svgcanvas.SvgCanvas#event:ext-zoomChanged} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#IDsUpdated * @param {module:svgcanvas.SvgCanvas#event:ext-IDsUpdated} arg * @returns {module:svgcanvas.ExtensionIDsUpdatedStatus} */ + /** * @function module:svgcanvas.ExtensionInitResponse#canvasUpdated * @param {module:svgcanvas.SvgCanvas#event:ext-canvasUpdated} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#toolButtonStateUpdate * @param {module:svgcanvas.SvgCanvas#event:ext-toolButtonStateUpdate} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#selectedChanged * @param {module:svgcanvas.SvgCanvas#event:ext-selectedChanged} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#elementTransition * @param {module:svgcanvas.SvgCanvas#event:ext-elementTransition} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#elementChanged * @param {module:svgcanvas.SvgCanvas#event:ext-elementChanged} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#langReady * @param {module:svgcanvas.SvgCanvas#event:ext-langReady} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#langChanged * @param {module:svgcanvas.SvgCanvas#event:ext-langChanged} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#addLangData * @param {module:svgcanvas.SvgCanvas#event:ext-addLangData} arg * @returns {Promise} Resolves to {@link module:locale.ExtensionLocaleData} */ + /** * @function module:svgcanvas.ExtensionInitResponse#onNewDocument * @param {module:svgcanvas.SvgCanvas#event:ext-onNewDocument} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#workareaResized * @param {module:svgcanvas.SvgCanvas#event:ext-workareaResized} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#callback + * @this module:SVGEditor * @param {module:svgcanvas.SvgCanvas#event:ext-callback} arg * @returns {undefined} */ @@ -13390,39 +14640,57 @@ * @param {module:svgcanvas.ExtensionArgumentObject} arg * @returns {Promise} Resolves to [ExtensionInitResponse]{@link module:svgcanvas.ExtensionInitResponse} or `undefined` */ + /** - * Add an extension to the editor + * @typedef {PlainObject} module:svgcanvas.ExtensionInitArgs + * @param {external:jQuery} initArgs.$ + * @param {module:SVGEditor~ImportLocale} initArgs.importLocale + */ + + /** + * Add an extension to the editor. * @function module:svgcanvas.SvgCanvas#addExtension * @param {string} name - String with the ID of the extension. Used internally; no need for i18n. * @param {module:svgcanvas.ExtensionInitCallback} [extInitFunc] - Function supplied by the extension with its data - * @param {module:SVGEditor~ImportLocale} importLocale + * @param {module:svgcanvas.ExtensionInitArgs} initArgs * @fires module:svgcanvas.SvgCanvas#event:extension_added - * @throws {TypeError} If `extInitFunc` is not a function + * @throws {TypeError|Error} `TypeError` if `extInitFunc` is not a function, `Error` + * if extension of supplied name already exists * @returns {Promise} Resolves to `undefined` */ - this.addExtension = function () { - var _ref3 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(name, extInitFunc, importLocale) { - var extObj, argObj; + + + this.addExtension = + /*#__PURE__*/ + function () { + var _ref4 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee(name, extInitFunc, _ref3) { + var jq, importLocale, argObj, extObj; return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: + jq = _ref3.$, importLocale = _ref3.importLocale; + if (!(typeof extInitFunc !== 'function')) { - _context.next = 2; + _context.next = 3; break; } throw new TypeError('Function argument expected for `svgcanvas.addExtension`'); - case 2: - extObj = {}; - - if (name in extensions) { - _context.next = 14; + case 3: + if (!(name in extensions)) { + _context.next = 5; break; } + throw new Error('Cannot add extension "' + name + '", an extension by that name already exists.'); + + case 5: // Provide private vars/funcs here. Is there a better way to do this? + /** * @typedef {module:svgcanvas.PrivateMethods} module:svgcanvas.ExtensionArgumentObject * @property {SVGSVGElement} svgroot See {@link module:svgcanvas~svgroot} @@ -13431,42 +14699,34 @@ * @property {module:select.SelectorManager} selectorManager * @property {module:SVGEditor~ImportLocale} importLocale */ + /** * @type {module:svgcanvas.ExtensionArgumentObject} * @see {@link module:svgcanvas.PrivateMethods} source for the other methods/properties */ argObj = $$9.extend(canvas.getPrivateMethods(), { + $: jq, importLocale: importLocale, svgroot: svgroot, svgcontent: svgcontent, nonce: getCurrentDrawing().getNonce(), selectorManager: selectorManager }); - - if (!extInitFunc) { - _context.next = 9; - break; - } - _context.next = 8; return extInitFunc(argObj); case 8: extObj = _context.sent; - case 9: if (extObj) { extObj.name = name; } extensions[name] = extObj; - return _context.abrupt('return', call('extension_added', extObj)); + return _context.abrupt("return", call('extension_added', extObj)); - case 14: - console.log('Cannot add extension "' + name + '", an extension by that name already exists.'); - - case 15: - case 'end': + case 12: + case "end": return _context.stop(); } } @@ -13474,10 +14734,9 @@ })); return function (_x, _x2, _x3) { - return _ref3.apply(this, arguments); + return _ref4.apply(this, arguments); }; }(); - /** * This method sends back an array or a NodeList full of elements that * intersect the multi-select rubber-band-box on the currentLayer only. @@ -13485,26 +14744,27 @@ * We brute-force `getIntersectionList` for browsers that do not support it (Firefox). * * Reference: - * Firefox does not implement `getIntersectionList()`, see {@link https://bugzilla.mozilla.org/show_bug.cgi?id=501421} + * Firefox does not implement `getIntersectionList()`, see {@link https://bugzilla.mozilla.org/show_bug.cgi?id=501421}. * @function module:svgcanvas.SvgCanvas#getIntersectionList * @param {SVGRect} rect * @returns {Element[]|NodeList} Bbox elements */ + + var getIntersectionList = this.getIntersectionList = function (rect) { - if (rubberBox == null) { + if (isNullish(rubberBox)) { return null; } var parent = currentGroup || getCurrentDrawing().getCurrentLayer(); + var rubberBBox; - var rubberBBox = void 0; if (!rect) { rubberBBox = rubberBox.getBBox(); var bb = svgcontent.createSVGRect(); - - for (var o in rubberBBox) { + ['x', 'y', 'width', 'height', 'top', 'right', 'bottom', 'left'].forEach(function (o) { bb[o] = rubberBBox[o] / currentZoom; - } + }); rubberBBox = bb; } else { rubberBBox = svgcontent.createSVGRect(); @@ -13515,44 +14775,45 @@ } var resultList = null; - if (!isIE) { + + if (!isIE()) { if (typeof svgroot.getIntersectionList === 'function') { // Offset the bbox of the rubber box by the offset of the svgcontent element. - rubberBBox.x += parseInt(svgcontent.getAttribute('x'), 10); - rubberBBox.y += parseInt(svgcontent.getAttribute('y'), 10); - + rubberBBox.x += parseInt(svgcontent.getAttribute('x')); + rubberBBox.y += parseInt(svgcontent.getAttribute('y')); resultList = svgroot.getIntersectionList(rubberBBox, parent); } } - if (resultList == null || typeof resultList.item !== 'function') { + if (isNullish(resultList) || typeof resultList.item !== 'function') { resultList = []; if (!curBBoxes.length) { // Cache all bboxes curBBoxes = getVisibleElementsAndBBoxes(parent); } + var i = curBBoxes.length; + while (i--) { if (!rubberBBox.width) { continue; } + if (rectsIntersect(rubberBBox, curBBoxes[i].bbox)) { resultList.push(curBBoxes[i].elem); } } - } - - // addToSelection expects an array, but it's ok to pass a NodeList + } // addToSelection expects an array, but it's ok to pass a NodeList // because using square-bracket notation is allowed: // https://www.w3.org/TR/DOM-Level-2-Core/ecma-script-binding.html + + return resultList; }; this.getStrokedBBox = getStrokedBBoxDefaultVisible; - this.getVisibleElements = getVisibleElements; - /** * @typedef {PlainObject} ElementAndBBox * @property {Element} elem - The element @@ -13562,63 +14823,71 @@ /** * Get all elements that have a BBox (excludes `<defs>`, `<title>`, etc). * Note that 0-opacity, off-screen etc elements are still considered "visible" - * for this function + * for this function. * @function module:svgcanvas.SvgCanvas#getVisibleElementsAndBBoxes * @param {Element} parent - The parent DOM element to search within * @returns {ElementAndBBox[]} An array with objects that include: */ + var getVisibleElementsAndBBoxes = this.getVisibleElementsAndBBoxes = function (parent) { if (!parent) { parent = $$9(svgcontent).children(); // Prevent layers from being included } + var contentElems = []; $$9(parent).children().each(function (i, elem) { if (elem.getBBox) { - contentElems.push({ elem: elem, bbox: getStrokedBBoxDefaultVisible([elem]) }); + contentElems.push({ + elem: elem, + bbox: getStrokedBBoxDefaultVisible([elem]) + }); } }); return contentElems.reverse(); }; - /** - * Wrap an SVG element into a group element, mark the group as 'gsvg' + * Wrap an SVG element into a group element, mark the group as 'gsvg'. * @function module:svgcanvas.SvgCanvas#groupSvgElem * @param {Element} elem - SVG element to wrap * @returns {undefined} */ + + var groupSvgElem = this.groupSvgElem = function (elem) { var g = document.createElementNS(NS.SVG, 'g'); elem.replaceWith(g); $$9(g).append(elem).data('gsvg', elem)[0].id = getNextId(); - }; - - // Set scope for these functions - + }; // Set scope for these functions // Object to contain editor event names and callback functions - var events = {}; + + var events = {}; canvas.call = call; /** * Array of what was changed (elements, layers) * @event module:svgcanvas.SvgCanvas#event:changed * @type {Element[]} */ + /** * Array of selected elements * @event module:svgcanvas.SvgCanvas#event:selected * @type {Element[]} */ + /** * Array of selected elements * @event module:svgcanvas.SvgCanvas#event:transition * @type {Element[]} */ + /** * The Element is always `SVGGElement`? * If not `null`, will be the set current group element * @event module:svgcanvas.SvgCanvas#event:contextset * @type {null|Element} */ + /** * @event module:svgcanvas.SvgCanvas#event:pointsAdded * @type {PlainObject} @@ -13636,17 +14905,20 @@ * @property {0.5|2} factor * @see module:SVGEditor.BBoxObjectWithFactor */ + /** * @event module:svgcanvas.SvgCanvas#event:updateCanvas * @type {PlainObject} * @property {false} center * @property {module:math.XYObject} newCtr */ + /** * @typedef {PlainObject} module:svgcanvas.ExtensionInitResponsePlusName * @implements {module:svgcanvas.ExtensionInitResponse} * @property {string} name The extension's resolved ID (whether explicit or based on file name) */ + /** * Generalized extension object response of * [`init()`]{@link module:svgcanvas.ExtensionInitCallback} @@ -13654,36 +14926,44 @@ * @event module:svgcanvas.SvgCanvas#event:extension_added * @type {module:svgcanvas.ExtensionInitResponsePlusName|undefined} */ + /** * @event module:svgcanvas.SvgCanvas#event:extensions_added * @type {undefined} */ + /** * @typedef {PlainObject} module:svgcanvas.Message * @property {Any} data The data * @property {string} origin The origin */ + /** * @event module:svgcanvas.SvgCanvas#event:message * @type {module:svgcanvas.Message} */ + /** * SVG canvas converted to string * @event module:svgcanvas.SvgCanvas#event:saved * @type {string} */ + /** * @event module:svgcanvas.SvgCanvas#event:setnonce * @type {!(string|Integer)} */ + /** * @event module:svgcanvas.SvgCanvas#event:unsetnonce * @type {undefined} */ + /** * @event module:svgcanvas.SvgCanvas#event:zoomDone * @type {undefined} */ + /** * @event module:svgcanvas.SvgCanvas#event:cleared * @type {undefined} @@ -13693,10 +14973,12 @@ * @event module:svgcanvas.SvgCanvas#event:exported * @type {module:svgcanvas.ImageExportedResults} */ + /** * @event module:svgcanvas.SvgCanvas#event:exportedPDF * @type {module:svgcanvas.PDFExportedResults} */ + /** * Creating a cover-all class until {@link https://github.com/jsdoc3/jsdoc/issues/1545} may be supported. * `undefined` may be returned by {@link module:svgcanvas.SvgCanvas#event:extension_added} if the extension's `init` returns `undefined` It is also the type for the following events "zoomDone", "unsetnonce", "cleared", and "extensions_added". @@ -13704,43 +14986,51 @@ * @type {module:svgcanvas.SvgCanvas#event:selected|module:svgcanvas.SvgCanvas#event:changed|module:svgcanvas.SvgCanvas#event:contextset|module:svgcanvas.SvgCanvas#event:pointsAdded|module:svgcanvas.SvgCanvas#event:extension_added|module:svgcanvas.SvgCanvas#event:extensions_added|module:svgcanvas.SvgCanvas#event:message|module:svgcanvas.SvgCanvas#event:transition|module:svgcanvas.SvgCanvas#event:zoomed|module:svgcanvas.SvgCanvas#event:updateCanvas|module:svgcanvas.SvgCanvas#event:saved|module:svgcanvas.SvgCanvas#event:exported|module:svgcanvas.SvgCanvas#event:exportedPDF|module:svgcanvas.SvgCanvas#event:setnonce|module:svgcanvas.SvgCanvas#event:unsetnonce|undefined} */ + /** + * The promise return, if present, resolves to `undefined` + * (`extension_added`, `exported`, `saved`) + * @typedef {Promise|undefined} module:svgcanvas.EventHandlerReturn + */ + /** * @callback module:svgcanvas.EventHandler * @param {external:Window} win * @param {module:svgcanvas.SvgCanvas#event:GenericCanvasEvent} arg * @listens module:svgcanvas.SvgCanvas#event:GenericCanvasEvent + * @returns {module:svgcanvas.EventHandlerReturn} */ /** - * Attaches a callback function to an event + * Attaches a callback function to an event. * @function module:svgcanvas.SvgCanvas#bind * @param {"changed"|"contextset"|"selected"|"pointsAdded"|"extension_added"|"extensions_added"|"message"|"transition"|"zoomed"|"updateCanvas"|"zoomDone"|"saved"|"exported"|"exportedPDF"|"setnonce"|"unsetnonce"|"cleared"} ev - String indicating the name of the event * @param {module:svgcanvas.EventHandler} f - The callback function to bind to the event * @returns {module:svgcanvas.EventHandler} The previous event */ + canvas.bind = function (ev, f) { var old = events[ev]; events[ev] = f; return old; }; - /** * Runs the SVG Document through the sanitizer and then updates its paths. * @function module:svgcanvas.SvgCanvas#prepareSvg * @param {XMLDocument} newDoc - The SVG DOM document * @returns {undefined} */ - this.prepareSvg = function (newDoc) { - this.sanitizeSvg(newDoc.documentElement); - // convert paths into absolute commands - var paths = [].concat(toConsumableArray(newDoc.getElementsByTagNameNS(NS.SVG, 'path'))); - paths.forEach(function (path$$1) { - path$$1.setAttribute('d', pathActions$$1.convertPath(path$$1)); - pathActions$$1.fixEnd(path$$1); + + this.prepareSvg = function (newDoc) { + this.sanitizeSvg(newDoc.documentElement); // convert paths into absolute commands + + var paths = _toConsumableArray(newDoc.getElementsByTagNameNS(NS.SVG, 'path')); + + paths.forEach(function (path) { + path.setAttribute('d', pathActions$1.convertPath(path)); + pathActions$1.fixEnd(path); }); }; - /** * Hack for Firefox bugs where text element features aren't updated or get * messed up. See issue 136 and issue 137. @@ -13751,10 +15041,13 @@ * @param {Element} elem - The (text) DOM element to clone * @returns {Element} Cloned element */ + + var ffClone = function ffClone(elem) { if (!isGecko()) { return elem; } + var clone = elem.cloneNode(true); elem.before(clone); elem.remove(); @@ -13762,9 +15055,7 @@ selectedElements[0] = clone; selectorManager.requestSelector(clone).showGrips(true); return clone; - }; - - // `this.each` is deprecated, if any extension used this it can be recreated by doing this: + }; // `this.each` is deprecated, if any extension used this it can be recreated by doing this: // * @example $(canvas.getRootElem()).children().each(...) // * @function module:svgcanvas.SvgCanvas#each // this.each = function (cb) { @@ -13773,13 +15064,15 @@ /** * Removes any old rotations if present, prepends a new rotation at the - * transformed center + * transformed center. * @function module:svgcanvas.SvgCanvas#setRotationAngle * @param {string|Float} val - The new rotation angle in degrees * @param {boolean} preventUndo - Indicates whether the action should be undoable or not * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + this.setRotationAngle = function (val, preventUndo) { // ensure val is the proper type val = parseFloat(val); @@ -13788,20 +15081,22 @@ var bbox = getBBox(elem); var cx = bbox.x + bbox.width / 2, cy = bbox.y + bbox.height / 2; - var tlist = getTransformList(elem); + var tlist = getTransformList(elem); // only remove the real rotational transform if present (i.e. at index=0) - // only remove the real rotational transform if present (i.e. at index=0) if (tlist.numberOfItems > 0) { var xform = tlist.getItem(0); + if (xform.type === 4) { tlist.removeItem(0); } - } - // find Rnc and insert it + } // find Rnc and insert it + + if (val !== 0) { var center = transformPoint(cx, cy, transformListToTransform(tlist).matrix); var Rnc = svgroot.createSVGTransform(); Rnc.setRotate(val, center.x, center.y); + if (tlist.numberOfItems) { tlist.insertItemBefore(Rnc, 0); } else { @@ -13818,32 +15113,35 @@ elem.setAttribute('transform', oldTransform); changeSelectedAttribute('transform', newTransform, selectedElements); call('changed', selectedElements); - } - // const pointGripContainer = getElem('pathpointgrip_container'); + } // const pointGripContainer = getElem('pathpointgrip_container'); // if (elem.nodeName === 'path' && pointGripContainer) { // pathActions.setPointContainerTransform(elem.getAttribute('transform')); // } + + var selector = selectorManager.requestSelector(selectedElements[0]); selector.resize(); - selector.updateGripCursors(val); + Selector.updateGripCursors(val); }; - /** * Runs `recalculateDimensions` on the selected elements, - * adding the changes to a single batch command + * adding the changes to a single batch command. * @function module:svgcanvas.SvgCanvas#recalculateAllSelectedDimensions * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + var recalculateAllSelectedDimensions = this.recalculateAllSelectedDimensions = function () { var text = currentResizeMode === 'none' ? 'position' : 'size'; var batchCmd = new BatchCommand$1(text); - var i = selectedElements.length; + while (i--) { - var elem = selectedElements[i]; - // if (getRotationAngle(elem) && !hasMatrixTransform(getTransformList(elem))) { continue; } + var elem = selectedElements[i]; // if (getRotationAngle(elem) && !hasMatrixTransform(getTransformList(elem))) { continue; } + var cmd = recalculateDimensions(elem); + if (cmd) { batchCmd.addSubCommand(cmd); } @@ -13854,39 +15152,37 @@ call('changed', selectedElements); } }; - /** - * Debug tool to easily see the current matrix in the browser's console + * Debug tool to easily see the current matrix in the browser's console. * @function module:svgcanvas~logMatrix * @param {SVGMatrix} m The matrix * @returns {undefined} */ + + var logMatrix = function logMatrix(m) { - console.log([m.a, m.b, m.c, m.d, m.e, m.f]); - }; + console.log([m.a, m.b, m.c, m.d, m.e, m.f]); // eslint-disable-line no-console + }; // Root Current Transformation Matrix in user units + - // Root Current Transformation Matrix in user units var rootSctm = null; - /** * Group: Selection */ - // TODO: do we need to worry about selectedBBoxes here? /** - * Selects only the given elements, shortcut for clearSelection(); addToSelection() + * Selects only the given elements, shortcut for `clearSelection(); addToSelection()`. * @function module:svgcanvas.SvgCanvas#selectOnly * @param {Element[]} elems - an array of DOM elements to be selected * @param {boolean} showGrips - Indicates whether the resize grips should be shown * @returns {undefined} */ + var selectOnly = this.selectOnly = function (elems, showGrips) { clearSelection(true); addToSelection(elems, showGrips); - }; - - // TODO: could use slice here to make this faster? + }; // TODO: could use slice here to make this faster? // TODO: should the 'selected' handler /** @@ -13895,19 +15191,26 @@ * @param {Element[]} elemsToRemove - An array of elements to remove from selection * @returns {undefined} */ - /* const removeFromSelection = */this.removeFromSelection = function (elemsToRemove) { - if (selectedElements[0] == null) { - return; - } - if (!elemsToRemove.length) { + + /* const removeFromSelection = */ + + + this.removeFromSelection = function (elemsToRemove) { + if (isNullish(selectedElements[0])) { return; } - // find every element and remove it from our array copy + if (!elemsToRemove.length) { + return; + } // find every element and remove it from our array copy + + var newSelectedItems = [], len = selectedElements.length; + for (var i = 0; i < len; ++i) { var elem = selectedElements[i]; + if (elem) { // keep the item if (!elemsToRemove.includes(elem)) { @@ -13917,27 +15220,29 @@ selectorManager.releaseSelector(elem); } } - } - // the copy becomes the master now + } // the copy becomes the master now + + selectedElements = newSelectedItems; }; - /** * Clears the selection, then adds all elements in the current layer to the selection. * @function module:svgcanvas.SvgCanvas#selectAllInCurrentLayer * @returns {undefined} */ + + this.selectAllInCurrentLayer = function () { var currentLayer = getCurrentDrawing().getCurrentLayer(); + if (currentLayer) { currentMode = 'select'; selectOnly($$9(currentGroup || currentLayer).children()); } }; - var drawnPath = null; + var drawnPath = null; // Mouse events - // Mouse events (function () { var freehand = { minx: null, @@ -13954,17 +15259,38 @@ rStartY = null, initBbox = {}, sumDistance = 0, - controllPoint2 = { x: 0, y: 0 }, - controllPoint1 = { x: 0, y: 0 }, - start = { x: 0, y: 0 }, - end = { x: 0, y: 0 }, - bSpline = { x: 0, y: 0 }, - nextPos = { x: 0, y: 0 }, - parameter = void 0, - nextParameter = void 0; + controllPoint2 = { + x: 0, + y: 0 + }, + controllPoint1 = { + x: 0, + y: 0 + }, + start = { + x: 0, + y: 0 + }, + end = { + x: 0, + y: 0 + }, + bSpline = { + x: 0, + y: 0 + }, + nextPos = { + x: 0, + y: 0 + }, + parameter, + nextParameter; var getBsplinePoint = function getBsplinePoint(t) { - var spline = { x: 0, y: 0 }, + var spline = { + x: 0, + y: 0 + }, p0 = controllPoint2, p1 = controllPoint1, p2 = start, @@ -13972,26 +15298,26 @@ S = 1.0 / 6.0, t2 = t * t, t3 = t2 * t; - var m = [[-1, 3, -3, 1], [3, -6, 3, 0], [-3, 0, 3, 0], [1, 4, 1, 0]]; - spline.x = S * ((p0.x * m[0][0] + p1.x * m[0][1] + p2.x * m[0][2] + p3.x * m[0][3]) * t3 + (p0.x * m[1][0] + p1.x * m[1][1] + p2.x * m[1][2] + p3.x * m[1][3]) * t2 + (p0.x * m[2][0] + p1.x * m[2][1] + p2.x * m[2][2] + p3.x * m[2][3]) * t + (p0.x * m[3][0] + p1.x * m[3][1] + p2.x * m[3][2] + p3.x * m[3][3])); spline.y = S * ((p0.y * m[0][0] + p1.y * m[0][1] + p2.y * m[0][2] + p3.y * m[0][3]) * t3 + (p0.y * m[1][0] + p1.y * m[1][1] + p2.y * m[1][2] + p3.y * m[1][3]) * t2 + (p0.y * m[2][0] + p1.y * m[2][1] + p2.y * m[2][2] + p3.y * m[2][3]) * t + (p0.y * m[3][0] + p1.y * m[3][1] + p2.y * m[3][2] + p3.y * m[3][3])); - return { x: spline.x, y: spline.y }; }; /** + * Follows these conditions: * - When we are in a create mode, the element is added to the canvas but the * action is not recorded until mousing up. * - When we are in select mode, select the element, remember the position - * and do nothing else + * and do nothing else. * @param {MouseEvent} evt * @fires module:svgcanvas.SvgCanvas#event:ext-mouseDown * @returns {undefined} */ + + var mouseDown = function mouseDown(evt) { if (canvas.spaceKey || evt.button === 1) { return; @@ -14005,32 +15331,29 @@ } rootSctm = $$9('#svgcontent g')[0].getScreenCTM().inverse(); - var pt = transformPoint(evt.pageX, evt.pageY, rootSctm), mouseX = pt.x * currentZoom, mouseY = pt.y * currentZoom; - evt.preventDefault(); if (rightClick) { currentMode = 'select'; lastClickPoint = pt; - } - - // This would seem to be unnecessary... + } // This would seem to be unnecessary... // if (!['select', 'resize'].includes(currentMode)) { // setGradient(); // } + var x = mouseX / currentZoom, y = mouseY / currentZoom; var mouseTarget = getMouseTarget(evt); if (mouseTarget.tagName === 'a' && mouseTarget.childNodes.length === 1) { mouseTarget = mouseTarget.firstChild; - } + } // realX/y ignores grid-snap value + - // realX/y ignores grid-snap value var realX = x; rStartX = startX = x; var realY = y; @@ -14041,33 +15364,32 @@ y = snapToGrid(y); startX = snapToGrid(startX); startY = snapToGrid(startY); - } - - // 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 - if (mouseTarget === selectorManager.selectorParentGroup && selectedElements[0] != null) { + + if (mouseTarget === selectorManager.selectorParentGroup && !isNullish(selectedElements[0])) { var grip = evt.target; - var griptype = elData(grip, 'type'); - // rotating + var griptype = elData(grip, 'type'); // rotating + if (griptype === 'rotate') { - currentMode = 'rotate'; - // resizing + currentMode = 'rotate'; // resizing } else if (griptype === 'resize') { currentMode = 'resize'; currentResizeMode = elData(grip, 'dir'); } + mouseTarget = selectedElements[0]; } startTransform = mouseTarget.getAttribute('transform'); - var i = void 0, - strokeW = void 0; var tlist = getTransformList(mouseTarget); + switch (currentMode) { case 'select': started = true; currentResizeMode = 'none'; + if (rightClick) { started = false; } @@ -14081,20 +15403,23 @@ // No need to do the call here as it will be done on addToSelection clearSelection(true); } + addToSelection([mouseTarget]); justSelected = mouseTarget; - pathActions$$1.clear(); - } - // else if it's a path, go into pathedit mode in mouseup + pathActions$1.clear(); + } // else if it's a path, go into pathedit mode in mouseup + if (!rightClick) { // insert a dummy transform so if the element(s) are moved it will have // a transform to use for its translate - for (i = 0; i < selectedElements.length; ++i) { - if (selectedElements[i] == null) { + for (var i = 0; i < selectedElements.length; ++i) { + if (isNullish(selectedElements[i])) { continue; } + var slist = getTransformList(selectedElements[i]); + if (slist.numberOfItems) { slist.insertItemBefore(svgroot.createSVGTransform(), 0); } else { @@ -14105,12 +15430,13 @@ } else if (!rightClick) { clearSelection(); currentMode = 'multiselect'; - if (rubberBox == null) { + + if (isNullish(rubberBox)) { rubberBox = selectorManager.getRubberBandBox(); } + rStartX *= currentZoom; - rStartY *= currentZoom; - // console.log('p',[evt.pageX, evt.pageY]); + rStartY *= currentZoom; // console.log('p',[evt.pageX, evt.pageY]); // console.log('c',[evt.clientX, evt.clientY]); // console.log('o',[evt.offsetX, evt.offsetY]); // console.log('s',[startX, startY]); @@ -14123,12 +15449,16 @@ display: 'inline' }, 100); } + break; + case 'zoom': started = true; - if (rubberBox == null) { + + if (isNullish(rubberBox)) { rubberBox = selectorManager.getRubberBandBox(); } + assignAttributes(rubberBox, { x: realX * currentZoom, y: realX * currentZoom, @@ -14137,79 +15467,88 @@ display: 'inline' }, 100); break; + case 'resize': - started = true; - startX = x; - startY = y; + { + started = true; + startX = x; + startY = y; // Getting the BBox from the selection box, since we know we + // want to orient around it - // Getting the BBox from the selection box, since we know we - // want to orient around it - initBbox = getBBox($$9('#selectedBox0')[0]); - var bb = {}; - $$9.each(initBbox, function (key, val) { - bb[key] = val / currentZoom; - }); - initBbox = bb; + initBbox = getBBox($$9('#selectedBox0')[0]); + var bb = {}; + $$9.each(initBbox, function (key, val) { + bb[key] = val / currentZoom; + }); + initBbox = bb; // append three dummy transforms to the tlist so that + // we can translate,scale,translate in mousemove - // append three dummy transforms to the tlist so that - // we can translate,scale,translate in mousemove - var pos = getRotationAngle(mouseTarget) ? 1 : 0; + var pos = getRotationAngle(mouseTarget) ? 1 : 0; - if (hasMatrixTransform(tlist)) { - tlist.insertItemBefore(svgroot.createSVGTransform(), pos); - tlist.insertItemBefore(svgroot.createSVGTransform(), pos); - tlist.insertItemBefore(svgroot.createSVGTransform(), pos); - } else { - tlist.appendItem(svgroot.createSVGTransform()); - tlist.appendItem(svgroot.createSVGTransform()); - tlist.appendItem(svgroot.createSVGTransform()); + if (hasMatrixTransform(tlist)) { + tlist.insertItemBefore(svgroot.createSVGTransform(), pos); + tlist.insertItemBefore(svgroot.createSVGTransform(), pos); + tlist.insertItemBefore(svgroot.createSVGTransform(), pos); + } else { + tlist.appendItem(svgroot.createSVGTransform()); + tlist.appendItem(svgroot.createSVGTransform()); + tlist.appendItem(svgroot.createSVGTransform()); - if (supportsNonScalingStroke()) { - // Handle crash for newer Chrome and Safari 6 (Mobile and Desktop): - // https://code.google.com/p/svg-edit/issues/detail?id=904 - // Chromium issue: https://code.google.com/p/chromium/issues/detail?id=114625 - // TODO: Remove this workaround once vendor fixes the issue - var iswebkit = isWebkit(); + if (supportsNonScalingStroke()) { + // Handle crash for newer Chrome and Safari 6 (Mobile and Desktop): + // https://code.google.com/p/svg-edit/issues/detail?id=904 + // Chromium issue: https://code.google.com/p/chromium/issues/detail?id=114625 + // TODO: Remove this workaround once vendor fixes the issue + var iswebkit = isWebkit(); + var delayedStroke; - var delayedStroke = void 0; - if (iswebkit) { - delayedStroke = function delayedStroke(ele) { - var _stroke = ele.getAttributeNS(null, 'stroke'); - ele.removeAttributeNS(null, 'stroke'); - // Re-apply stroke after delay. Anything higher than 1 seems to cause flicker - if (_stroke !== null) setTimeout(function () { - ele.setAttributeNS(null, 'stroke', _stroke); - }, 0); - }; - } - mouseTarget.style.vectorEffect = 'non-scaling-stroke'; - if (iswebkit) { - delayedStroke(mouseTarget); - } - - var all = mouseTarget.getElementsByTagName('*'), - len = all.length; - for (i = 0; i < len; i++) { - if (!all[i].style) { - // mathML - continue; - } - all[i].style.vectorEffect = 'non-scaling-stroke'; if (iswebkit) { - delayedStroke(all[i]); + delayedStroke = function delayedStroke(ele) { + var stroke_ = ele.getAttribute('stroke'); + ele.removeAttribute('stroke'); // Re-apply stroke after delay. Anything higher than 1 seems to cause flicker + + if (stroke_ !== null) setTimeout(function () { + ele.setAttribute('stroke', stroke_); + }, 0); + }; + } + + mouseTarget.style.vectorEffect = 'non-scaling-stroke'; + + if (iswebkit) { + delayedStroke(mouseTarget); + } + + var all = mouseTarget.getElementsByTagName('*'), + len = all.length; + + for (var _i2 = 0; _i2 < len; _i2++) { + if (!all[_i2].style) { + // mathML + continue; + } + + all[_i2].style.vectorEffect = 'non-scaling-stroke'; + + if (iswebkit) { + delayedStroke(all[_i2]); + } } } } + + break; } - break; + case 'fhellipse': case 'fhrect': case 'fhpath': start.x = realX; start.y = realY; started = true; - dAttr = realX + ',' + realY + ' '; - strokeW = parseFloat(curShape.stroke_width) === 0 ? 1 : curShape.stroke_width; + dAttr = realX + ',' + realY + ' '; // Commented out as doing nothing now: + // strokeW = parseFloat(curShape.stroke_width) === 0 ? 1 : curShape.stroke_width; + addSVGElementFromJson({ element: 'polyline', curStyles: true, @@ -14227,27 +15566,31 @@ freehand.miny = realY; freehand.maxy = realY; break; + case 'image': - started = true; - var newImage = addSVGElementFromJson({ - element: 'image', - attr: { - x: x, - y: y, - width: 0, - height: 0, - id: getNextId(), - opacity: curShape.opacity / 2, - style: 'pointer-events:inherit' - } - }); - setHref(newImage, lastGoodImgUrl); - preventClickDefault(newImage); - break; - case 'square': - // FIXME: once we create the rect, we lose information that this was a square + { + started = true; + var newImage = addSVGElementFromJson({ + element: 'image', + attr: { + x: x, + y: y, + width: 0, + height: 0, + id: getNextId(), + opacity: curShape.opacity / 2, + style: 'pointer-events:inherit' + } + }); + setHref(newImage, lastGoodImgUrl); + preventClickDefault(newImage); + break; + } + + case 'square': // FIXME: once we create the rect, we lose information that this was a square // (for resizing purposes this could be important) // Fallthrough + case 'rect': started = true; startX = x; @@ -14265,30 +15608,34 @@ } }); break; + case 'line': - started = true; - strokeW = Number(curShape.stroke_width) === 0 ? 1 : curShape.stroke_width; - addSVGElementFromJson({ - element: 'line', - curStyles: true, - attr: { - x1: x, - y1: y, - x2: x, - y2: y, - id: getNextId(), - stroke: curShape.stroke, - 'stroke-width': strokeW, - 'stroke-dasharray': curShape.stroke_dasharray, - 'stroke-linejoin': curShape.stroke_linejoin, - 'stroke-linecap': curShape.stroke_linecap, - 'stroke-opacity': curShape.stroke_opacity, - fill: 'none', - opacity: curShape.opacity / 2, - style: 'pointer-events:none' - } - }); - break; + { + started = true; + var strokeW = Number(curShape.stroke_width) === 0 ? 1 : curShape.stroke_width; + addSVGElementFromJson({ + element: 'line', + curStyles: true, + attr: { + x1: x, + y1: y, + x2: x, + y2: y, + id: getNextId(), + stroke: curShape.stroke, + 'stroke-width': strokeW, + 'stroke-dasharray': curShape.stroke_dasharray, + 'stroke-linejoin': curShape.stroke_linejoin, + 'stroke-linecap': curShape.stroke_linecap, + 'stroke-opacity': curShape.stroke_opacity, + fill: 'none', + opacity: curShape.opacity / 2, + style: 'pointer-events:none' + } + }); + break; + } + case 'circle': started = true; addSVGElementFromJson({ @@ -14303,6 +15650,7 @@ } }); break; + case 'ellipse': started = true; addSVGElementFromJson({ @@ -14318,9 +15666,12 @@ } }); break; + case 'text': started = true; - /* const newText = */addSVGElementFromJson({ + /* const newText = */ + + addSVGElementFromJson({ element: 'text', curStyles: true, attr: { @@ -14335,33 +15686,36 @@ 'xml:space': 'preserve', opacity: curShape.opacity } - }); - // newText.textContent = 'text'; + }); // newText.textContent = 'text'; + break; - case 'path': - // Fall through + + case 'path': // Fall through + case 'pathedit': startX *= currentZoom; startY *= currentZoom; - pathActions$$1.mouseDown(evt, mouseTarget, startX, startY); + pathActions$1.mouseDown(evt, mouseTarget, startX, startY); started = true; break; + case 'textedit': startX *= currentZoom; startY *= currentZoom; textActions.mouseDown(evt, mouseTarget, startX, startY); started = true; break; + case 'rotate': - started = true; - // we are starting an undoable change (a drag-rotation) + started = true; // we are starting an undoable change (a drag-rotation) + canvas.undoMgr.beginUndoableChange('transform', selectedElements); break; + default: // This could occur in an extension break; } - /** * The main (left) mouse button is held down on the canvas area * @event module:svgcanvas.SvgCanvas#event:ext-mouseDown @@ -14371,22 +15725,24 @@ * @property {Float} start_y y coordinate on canvas * @property {Element[]} selectedElements An array of the selected Elements */ - var extResult = runExtensions('mouseDown', /** @type {module:svgcanvas.SvgCanvas#event:ext-mouseDown} */{ + + + var extResult = runExtensions('mouseDown', + /** @type {module:svgcanvas.SvgCanvas#event:ext-mouseDown} */ + { event: evt, start_x: startX, start_y: startY, selectedElements: selectedElements }, true); - $$9.each(extResult, function (i, r) { if (r && r.started) { started = true; } }); - }; - - // in this function we do not record any state changes yet (but we do update + }; // in this function we do not record any state changes yet (but we do update // any elements that are still being created, moved or resized on the canvas) + /** * * @param {MouseEvent} evt @@ -14394,30 +15750,32 @@ * @fires module:svgcanvas.SvgCanvas#event:ext-mouseMove * @returns {undefined} */ + + var mouseMove = function mouseMove(evt) { if (!started) { return; } + if (evt.button === 1 || canvas.spaceKey) { return; } - var i = void 0, - xya = void 0, - c = void 0, - cx = void 0, - cy = void 0, - dx = void 0, - dy = void 0, - len = void 0, - angle = void 0, - box = void 0, + var i, + xya, + c, + cx, + cy, + dx, + dy, + len, + angle, + box, selected = selectedElements[0]; var pt = transformPoint(evt.pageX, evt.pageY, rootSctm), mouseX = pt.x * currentZoom, mouseY = pt.y * currentZoom, shape = getElem(getId()); - var realX = mouseX / currentZoom; var x = realX; var realY = mouseY / currentZoom; @@ -14429,7 +15787,8 @@ } evt.preventDefault(); - var tlist = void 0; + var tlist; + switch (currentMode) { case 'select': { @@ -14444,51 +15803,57 @@ dx = snapToGrid(dx); dy = snapToGrid(dy); } - + /* + // Commenting out as currently has no effect if (evt.shiftKey) { xya = snapToAngle(startX, startY, x, y); - var _xya = xya; - x = _xya.x; - y = _xya.y; + ({x, y} = xya); } + */ + if (dx !== 0 || dy !== 0) { len = selectedElements.length; + for (i = 0; i < len; ++i) { selected = selectedElements[i]; - if (selected == null) { + + if (isNullish(selected)) { break; - } - // if (i === 0) { + } // if (i === 0) { // const box = utilsGetBBox(selected); // selectedBBoxes[i].x = box.x + dx; // selectedBBoxes[i].y = box.y + dy; // } - // update the dummy transform in our transform list // to be a translate + + var xform = svgroot.createSVGTransform(); - tlist = getTransformList(selected); - // Note that if Webkit and there's no ID for this + tlist = getTransformList(selected); // Note that if Webkit and there's no ID for this // element, the dummy transform may have gotten lost. // This results in unexpected behaviour xform.setTranslate(dx, dy); + if (tlist.numberOfItems) { tlist.replaceItem(xform, 0); } else { tlist.appendItem(xform); - } + } // update our internal bbox that we're tracking while dragging + - // update our internal bbox that we're tracking while dragging selectorManager.requestSelector(selected).resize(); } call('transition', selectedElements); } } + break; - }case 'multiselect': + } + + case 'multiselect': { realX *= currentZoom; realY *= currentZoom; @@ -14497,26 +15862,27 @@ y: Math.min(rStartY, realY), width: Math.abs(realX - rStartX), height: Math.abs(realY - rStartY) - }, 100); - - // for each selected: + }, 100); // for each selected: // - if newList contains selected, do nothing // - if newList doesn't contain selected, remove it from selected // - for any newList that was not in selectedElements, add it to selected + var elemsToRemove = selectedElements.slice(), elemsToAdd = [], - newList = getIntersectionList(); + newList = getIntersectionList(); // For every element in the intersection, add if not present in selectedElements. - // For every element in the intersection, add if not present in selectedElements. len = newList.length; + for (i = 0; i < len; ++i) { - var intElem = newList[i]; - // Found an element that was not selected before, so we should add it. + var intElem = newList[i]; // Found an element that was not selected before, so we should add it. + if (!selectedElements.includes(intElem)) { elemsToAdd.push(intElem); - } - // Found an element that was already selected, so we shouldn't remove it. + } // Found an element that was already selected, so we shouldn't remove it. + + var foundInd = elemsToRemove.indexOf(intElem); + if (foundInd !== -1) { elemsToRemove.splice(foundInd, 1); } @@ -14531,7 +15897,9 @@ } break; - }case 'resize': + } + + case 'resize': { // we track the resize bounding box and translate/scale the selected element // while the mouse is down, when mouse goes up, we use this to recalculate @@ -14544,7 +15912,6 @@ _box = box, width = _box.width, height = _box.height; - dx = x - startX; dy = y - startY; @@ -14553,22 +15920,24 @@ dy = snapToGrid(dy); height = snapToGrid(height); width = snapToGrid(width); - } + } // if rotated, adjust the dx,dy values + - // if rotated, adjust the dx,dy values angle = getRotationAngle(selected); + if (angle) { var r = Math.sqrt(dx * dx + dy * dy), theta = Math.atan2(dy, dx) - angle * Math.PI / 180.0; dx = r * Math.cos(theta); dy = r * Math.sin(theta); - } - - // if not stretching in y direction, set dy to 0 + } // if not stretching in y direction, set dy to 0 // if not stretching in x direction, set dx to 0 + + if (!currentResizeMode.includes('n') && !currentResizeMode.includes('s')) { dy = 0; } + if (!currentResizeMode.includes('e') && !currentResizeMode.includes('w')) { dx = 0; } @@ -14577,20 +15946,20 @@ tx = 0, ty = 0, sy = height ? (height + dy) / height : 1, - sx = width ? (width + dx) / width : 1; - // if we are dragging on the north side, then adjust the scale factor and ty + sx = width ? (width + dx) / width : 1; // if we are dragging on the north side, then adjust the scale factor and ty + if (currentResizeMode.includes('n')) { sy = height ? (height - dy) / height : 1; ty = height; - } + } // if we dragging on the east side, then adjust the scale factor and tx + - // if we dragging on the east side, then adjust the scale factor and tx if (currentResizeMode.includes('w')) { sx = width ? (width - dx) / width : 1; tx = width; - } + } // update the transform list with translate,scale,translate + - // update the transform list with translate,scale,translate var translateOrigin = svgroot.createSVGTransform(), scale = svgroot.createSVGTransform(), translateBack = svgroot.createSVGTransform(); @@ -14603,6 +15972,7 @@ } translateOrigin.setTranslate(-(left + tx), -(top + ty)); + if (evt.shiftKey) { if (sx === 1) { sx = sy; @@ -14610,9 +15980,10 @@ sy = sx; } } - scale.setScale(sx, sy); + scale.setScale(sx, sy); translateBack.setTranslate(left + tx, top + ty); + if (hasMatrix) { var diff = angle ? 1 : 0; tlist.replaceItem(translateOrigin, 2 + diff); @@ -14626,11 +15997,11 @@ } selectorManager.requestSelector(selected).resize(); - call('transition', selectedElements); - break; - }case 'zoom': + } + + case 'zoom': { realX *= currentZoom; realY *= currentZoom; @@ -14641,14 +16012,18 @@ height: Math.abs(realY - rStartY * currentZoom) }, 100); break; - }case 'text': + } + + case 'text': { assignAttributes(shape, { x: x, y: y }, 1000); break; - }case 'line': + } + + case 'line': { if (curConfig.gridSnapping) { x = snapToGrid(x); @@ -14664,22 +16039,24 @@ y2 = xya.y; } - shape.setAttributeNS(null, 'x2', x2); - shape.setAttributeNS(null, 'y2', y2); + shape.setAttribute('x2', x2); + shape.setAttribute('y2', y2); break; - }case 'foreignObject': - // fall through - case 'square': - // fall through - case 'rect': - // fall through + } + + case 'foreignObject': // fall through + + case 'square': // fall through + + case 'rect': // fall through + case 'image': { var square = currentMode === 'square' || evt.shiftKey; var w = Math.abs(x - startX), h = Math.abs(y - startY); - var newX = void 0, - newY = void 0; + var newX, newY; + if (square) { w = h = Math.max(w, h); newX = startX < x ? startX : startX - w; @@ -14702,22 +16079,26 @@ x: newX, y: newY }, 1000); - break; - }case 'circle': + } + + case 'circle': { c = $$9(shape).attr(['cx', 'cy']); var _c = c; cx = _c.cx; cy = _c.cy; - var rad = Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy)); + if (curConfig.gridSnapping) { rad = snapToGrid(rad); } - shape.setAttributeNS(null, 'r', rad); + + shape.setAttribute('r', rad); break; - }case 'ellipse': + } + + case 'ellipse': { c = $$9(shape).attr(['cx', 'cy']); var _c2 = c; @@ -14730,11 +16111,13 @@ y = snapToGrid(y); cy = snapToGrid(cy); } - shape.setAttributeNS(null, 'rx', Math.abs(x - cx)); + + shape.setAttribute('rx', Math.abs(x - cx)); var ry = Math.abs(evt.shiftKey ? x - cx : y - cy); - shape.setAttributeNS(null, 'ry', ry); + shape.setAttribute('ry', ry); break; } + case 'fhellipse': case 'fhrect': { @@ -14744,11 +16127,14 @@ freehand.maxy = Math.max(realY, freehand.maxy); } // Fallthrough + case 'fhpath': { // dAttr += + realX + ',' + realY + ' '; - // shape.setAttributeNS(null, 'points', dAttr); - end.x = realX;end.y = realY; + // shape.setAttribute('points', dAttr); + end.x = realX; + end.y = realY; + if (controllPoint2.x && controllPoint2.y) { for (i = 0; i < STEP_COUNT - 1; i++) { parameter = i / STEP_COUNT; @@ -14757,10 +16143,10 @@ nextPos = bSpline; bSpline = getBsplinePoint(parameter); sumDistance += Math.sqrt((nextPos.x - bSpline.x) * (nextPos.x - bSpline.x) + (nextPos.y - bSpline.y) * (nextPos.y - bSpline.y)); - if (sumDistance > THRESHOLD_DIST) { - sumDistance -= THRESHOLD_DIST; - // Faster than completely re-writing the points attribute. + if (sumDistance > THRESHOLD_DIST) { + sumDistance -= THRESHOLD_DIST; // Faster than completely re-writing the points attribute. + var point = svgcontent.createSVGPoint(); point.x = bSpline.x; point.y = bSpline.y; @@ -14768,14 +16154,24 @@ } } } - controllPoint2 = { x: controllPoint1.x, y: controllPoint1.y }; - controllPoint1 = { x: start.x, y: start.y }; - start = { x: end.x, y: end.y }; - break; - // update path stretch line coordinates - }case 'path': - // fall through + controllPoint2 = { + x: controllPoint1.x, + y: controllPoint1.y + }; + controllPoint1 = { + x: start.x, + y: start.y + }; + start = { + x: end.x, + y: end.y + }; + break; // update path stretch line coordinates + } + + case 'path': // fall through + case 'pathedit': { x *= currentZoom; @@ -14787,22 +16183,23 @@ startX = snapToGrid(startX); startY = snapToGrid(startY); } - if (evt.shiftKey) { - var path$$1 = path; - var x1 = void 0, - y1 = void 0; - if (path$$1) { - x1 = path$$1.dragging ? path$$1.dragging[0] : startX; - y1 = path$$1.dragging ? path$$1.dragging[1] : startY; + if (evt.shiftKey) { + var path$1 = path; + var x1, y1; + + if (path$1) { + x1 = path$1.dragging ? path$1.dragging[0] : startX; + y1 = path$1.dragging ? path$1.dragging[1] : startY; } else { x1 = startX; y1 = startY; } + xya = snapToAngle(x1, y1, x, y); - var _xya2 = xya; - x = _xya2.x; - y = _xya2.y; + var _xya = xya; + x = _xya.x; + y = _xya.y; } if (rubberBox && rubberBox.getAttribute('display') !== 'none') { @@ -14815,14 +16212,15 @@ height: Math.abs(realY - rStartY * currentZoom) }, 100); } - pathActions$$1.mouseMove(x, y); + pathActions$1.mouseMove(x, y); break; - }case 'textedit': + } + + case 'textedit': { x *= currentZoom; - y *= currentZoom; - // if (rubberBox && rubberBox.getAttribute('display') !== 'none') { + y *= currentZoom; // if (rubberBox && rubberBox.getAttribute('display') !== 'none') { // assignAttributes(rubberBox, { // x: Math.min(startX, x), // y: Math.min(startY, y), @@ -14832,9 +16230,10 @@ // } textActions.mouseMove(mouseX, mouseY); - break; - }case 'rotate': + } + + case 'rotate': { box = getBBox(selected); cx = box.x + box.width / 2; @@ -14844,9 +16243,11 @@ cx = center.x; cy = center.y; angle = (Math.atan2(cy - y, cx - x) * (180 / Math.PI) - 90) % 360; + if (curConfig.gridSnapping) { angle = snapToGrid(angle); } + if (evt.shiftKey) { // restrict rotations to nice angles (WRS) var snap = 45; @@ -14856,10 +16257,11 @@ canvas.setRotationAngle(angle < -180 ? 360 + angle : angle, true); call('transition', selectedElements); break; - }default: + } + + default: break; } - /** * The mouse has moved on the canvas area * @event module:svgcanvas.SvgCanvas#event:ext-mouseMove @@ -14869,19 +16271,23 @@ * @property {Float} mouse_y y coordinate on canvas * @property {Element} selected Refers to the first selected element */ - runExtensions('mouseMove', /** @type {module:svgcanvas.SvgCanvas#event:ext-mouseMove} */{ + + + runExtensions('mouseMove', + /** @type {module:svgcanvas.SvgCanvas#event:ext-mouseMove} */ + { event: evt, mouse_x: mouseX, mouse_y: mouseY, selected: selected }); }; // mouseMove() - // - in create mode, the element's opacity is set properly, we create an InsertElementCommand // and store it on the Undo stack // - in move/resize mode, the element's attributes which were affected by the move/resize are // identified, a ChangeElementCommand is created and stored on the stack for those attrs // this is done in when we recalculate the selected dimensions() + /** * * @param {MouseEvent} evt @@ -14890,51 +16296,59 @@ * @fires module:svgcanvas.SvgCanvas#event:ext-mouseUp * @returns {undefined} */ + + var mouseUp = function mouseUp(evt) { if (evt.button === 2) { return; } + var tempJustSelected = justSelected; justSelected = null; + if (!started) { return; } + var pt = transformPoint(evt.pageX, evt.pageY, rootSctm), mouseX = pt.x * currentZoom, mouseY = pt.y * currentZoom, x = mouseX / currentZoom, y = mouseY / currentZoom; - var element = getElem(getId()); var keep = false; - var realX = x; - var realY = y; + var realY = y; // TODO: Make true when in multi-unit mode + started = false; - var attrs = void 0, - t = void 0; + var attrs, t; + switch (currentMode) { // intentionally fall-through to select here case 'resize': case 'multiselect': - if (rubberBox != null) { + if (!isNullish(rubberBox)) { rubberBox.setAttribute('display', 'none'); curBBoxes = []; } + currentMode = 'select'; // Fallthrough + case 'select': - if (selectedElements[0] != null) { + if (!isNullish(selectedElements[0])) { // if we only have one selected element - if (selectedElements[1] == null) { + if (isNullish(selectedElements[1])) { // set our current stroke/fill properties to the element's var selected = selectedElements[0]; + switch (selected.tagName) { case 'g': case 'use': case 'image': case 'foreignObject': break; + default: curProperties.fill = selected.getAttribute('fill'); curProperties.fill_opacity = selected.getAttribute('fill-opacity'); @@ -14950,31 +16364,33 @@ curText.font_size = selected.getAttribute('font-size'); curText.font_family = selected.getAttribute('font-family'); } - selectorManager.requestSelector(selected).showGrips(true); - // This shouldn't be necessary as it was done on mouseDown... + selectorManager.requestSelector(selected).showGrips(true); // This shouldn't be necessary as it was done on mouseDown... // call('selected', [selected]); - } - // always recalculate dimensions to strip off stray identity transforms - recalculateAllSelectedDimensions(); - // if it was being dragged/resized + } // always recalculate dimensions to strip off stray identity transforms + + + recalculateAllSelectedDimensions(); // if it was being dragged/resized + if (realX !== rStartX || realY !== rStartY) { var len = selectedElements.length; + for (var i = 0; i < len; ++i) { - if (selectedElements[i] == null) { + if (isNullish(selectedElements[i])) { break; } + if (!selectedElements[i].firstChild) { // Not needed for groups (incorrectly resizes elems), possibly not needed at all? selectorManager.requestSelector(selectedElements[i]).resize(); } - } - // 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 { t = evt.target; - if (selectedElements[0].nodeName === 'path' && selectedElements[1] == null) { - pathActions$$1.select(selectedElements[0]); - // if it was a path + + if (selectedElements[0].nodeName === 'path' && isNullish(selectedElements[1])) { + pathActions$1.select(selectedElements[0]); // if it was a path // else, if it was selected and this is a shift-click, remove it from selection } else if (evt.shiftKey) { if (tempJustSelected !== t) { @@ -14982,72 +16398,102 @@ } } } // no change in mouse position - // Remove non-scaling stroke + + if (supportsNonScalingStroke()) { var elem = selectedElements[0]; + if (elem) { elem.removeAttribute('style'); - walkTree(elem, function (elem) { - elem.removeAttribute('style'); + walkTree(elem, function (el) { + el.removeAttribute('style'); }); } } } + return; + case 'zoom': - if (rubberBox != null) { - rubberBox.setAttribute('display', 'none'); + { + if (!isNullish(rubberBox)) { + rubberBox.setAttribute('display', 'none'); + } + + var factor = evt.shiftKey ? 0.5 : 2; + call('zoomed', { + x: Math.min(rStartX, realX), + y: Math.min(rStartY, realY), + width: Math.abs(realX - rStartX), + height: Math.abs(realY - rStartY), + factor: factor + }); + return; } - var factor = evt.shiftKey ? 0.5 : 2; - call('zoomed', { - x: Math.min(rStartX, realX), - y: Math.min(rStartY, realY), - width: Math.abs(realX - rStartX), - height: Math.abs(realY - rStartY), - factor: factor - }); - return; + case 'fhpath': - // Check that the path contains at least 2 points; a degenerate one-point path - // causes problems. - // Webkit ignores how we set the points attribute with commas and uses space - // to separate all coordinates, see https://bugs.webkit.org/show_bug.cgi?id=29870 - sumDistance = 0; - controllPoint2 = { x: 0, y: 0 }; - controllPoint1 = { x: 0, y: 0 }; - start = { x: 0, y: 0 }; - end = { x: 0, y: 0 }; - var coords = element.getAttribute('points'); - var commaIndex = coords.indexOf(','); - if (commaIndex >= 0) { - keep = coords.indexOf(',', commaIndex + 1) >= 0; - } else { - keep = coords.indexOf(' ', coords.indexOf(' ') + 1) >= 0; + { + // Check that the path contains at least 2 points; a degenerate one-point path + // causes problems. + // Webkit ignores how we set the points attribute with commas and uses space + // to separate all coordinates, see https://bugs.webkit.org/show_bug.cgi?id=29870 + sumDistance = 0; + controllPoint2 = { + x: 0, + y: 0 + }; + controllPoint1 = { + x: 0, + y: 0 + }; + start = { + x: 0, + y: 0 + }; + end = { + x: 0, + y: 0 + }; + var coords = element.getAttribute('points'); + var commaIndex = coords.indexOf(','); + + if (commaIndex >= 0) { + keep = coords.indexOf(',', commaIndex + 1) >= 0; + } else { + keep = coords.indexOf(' ', coords.indexOf(' ') + 1) >= 0; + } + + if (keep) { + element = pathActions$1.smoothPolylineIntoPath(element); + } + + break; } - if (keep) { - element = pathActions$$1.smoothPolylineIntoPath(element); - } - break; + case 'line': attrs = $$9(element).attr(['x1', 'x2', 'y1', 'y2']); keep = attrs.x1 !== attrs.x2 || attrs.y1 !== attrs.y2; break; + case 'foreignObject': case 'square': case 'rect': case 'image': - attrs = $$9(element).attr(['width', 'height']); - // Image should be kept regardless of size (use inherit dimensions later) + attrs = $$9(element).attr(['width', 'height']); // Image should be kept regardless of size (use inherit dimensions later) + keep = attrs.width || attrs.height || currentMode === 'image'; break; + case 'circle': keep = element.getAttribute('r') !== '0'; break; + case 'ellipse': attrs = $$9(element).attr(['rx', 'ry']); keep = attrs.rx || attrs.ry; break; + case 'fhellipse': if (freehand.maxx - freehand.minx > 0 && freehand.maxy - freehand.miny > 0) { element = addSVGElementFromJson({ @@ -15064,7 +16510,9 @@ call('changed', [element]); keep = true; } + break; + case 'fhrect': if (freehand.maxx - freehand.minx > 0 && freehand.maxy - freehand.miny > 0) { element = addSVGElementFromJson({ @@ -15081,50 +16529,60 @@ call('changed', [element]); keep = true; } + break; + case 'text': keep = true; selectOnly([element]); textActions.start(element); break; + case 'path': - // set element to null here so that it is not removed nor finalized - element = null; - // continue to be set to true so that mouseMove happens - started = true; + { + // set element to null here so that it is not removed nor finalized + element = null; // continue to be set to true so that mouseMove happens - var res = pathActions$$1.mouseUp(evt, element, mouseX, mouseY); - element = res.element; - keep = res.keep; + started = true; + var res = pathActions$1.mouseUp(evt, element, mouseX, mouseY); + element = res.element; + keep = res.keep; + break; + } - break; case 'pathedit': keep = true; element = null; - pathActions$$1.mouseUp(evt); + pathActions$1.mouseUp(evt); break; + case 'textedit': keep = false; element = null; textActions.mouseUp(evt, mouseX, mouseY); break; + case 'rotate': - keep = true; - element = null; - currentMode = 'select'; - var batchCmd = canvas.undoMgr.finishUndoableChange(); - if (!batchCmd.isEmpty()) { - addCommandToHistory(batchCmd); + { + keep = true; + element = null; + currentMode = 'select'; + var batchCmd = canvas.undoMgr.finishUndoableChange(); + + if (!batchCmd.isEmpty()) { + addCommandToHistory(batchCmd); + } // perform recalculation to weed out any stray identity transforms that might get stuck + + + recalculateAllSelectedDimensions(); + call('changed', selectedElements); + break; } - // perform recalculation to weed out any stray identity transforms that might get stuck - recalculateAllSelectedDimensions(); - call('changed', selectedElements); - break; + default: // This could occur in an extension break; } - /** * The main (left) mouse button is released (anywhere) * @event module:svgcanvas.SvgCanvas#event:ext-mouseUp @@ -15133,43 +16591,44 @@ * @property {Float} mouse_x x coordinate on canvas * @property {Float} mouse_y y coordinate on canvas */ - var extResult = runExtensions('mouseUp', /** @type {module:svgcanvas.SvgCanvas#event:ext-mouseUp} */{ + + + var extResult = runExtensions('mouseUp', + /** @type {module:svgcanvas.SvgCanvas#event:ext-mouseUp} */ + { event: evt, mouse_x: mouseX, mouse_y: mouseY }, true); - $$9.each(extResult, function (i, r) { if (r) { keep = r.keep || keep; element = r.element; - started = r.started || started; } }); - if (!keep && element != null) { + if (!keep && !isNullish(element)) { getCurrentDrawing().releaseId(getId()); element.remove(); element = null; - - t = evt.target; - - // if this element is in a group, go up until we reach the top-level group + t = evt.target; // if this element is in a group, go up until we reach the top-level group // just below the layer groups // TODO: once we implement links, we also would have to check for <a> elements + while (t && t.parentNode && t.parentNode.parentNode && t.parentNode.parentNode.tagName === 'g') { t = t.parentNode; - } - // if we are not in the middle of creating a path, and we've clicked on some shape, + } // if we are not in the middle of creating a path, and we've clicked on some shape, // then go to Select mode. // WebKit returns <div> when the canvas is clicked, Firefox/Opera return <svg> + + if ((currentMode !== 'path' || !drawnPath) && t && t.parentNode && t.parentNode.id !== 'selectorParentGroup' && t.id !== 'svgcanvas' && t.id !== 'svgroot') { // switch into "select" mode if we've clicked on an element canvas.setMode('select'); selectOnly([t], true); } - } else if (element != null) { + } else if (!isNullish(element)) { /** * @name module:svgcanvas.SvgCanvas#addedNew * @type {boolean} @@ -15177,38 +16636,42 @@ canvas.addedNew = true; var aniDur = 0.2; - var cAni = void 0; + var cAni; + if (opacAni.beginElement && parseFloat(element.getAttribute('opacity')) !== curShape.opacity) { cAni = $$9(opacAni).clone().attr({ to: curShape.opacity, dur: aniDur }).appendTo(element); + try { // Fails in FF4 on foreignObject cAni[0].beginElement(); } catch (e) {} } else { aniDur = 0; - } - - // Ideally this would be done on the endEvent of the animation, + } // Ideally this would be done on the endEvent of the animation, // but that doesn't seem to be supported in Webkit + + setTimeout(function () { if (cAni) { cAni.remove(); } + element.setAttribute('opacity', curShape.opacity); element.setAttribute('style', 'pointer-events:inherit'); cleanupElement(element); + if (currentMode === 'path') { - pathActions$$1.toEditMode(element); + pathActions$1.toEditMode(element); } else if (curConfig.selectNew) { selectOnly([element], true); - } - // we create the insert command that is stored on the stack + } // we create the insert command that is stored on the stack // undo means to call cmd.unapply(), redo means to call cmd.apply() - addCommandToHistory(new InsertElementCommand$1(element)); + + addCommandToHistory(new InsertElementCommand$1(element)); call('changed', [element]); }, aniDur * 1000); } @@ -15218,9 +16681,8 @@ var dblClick = function dblClick(evt) { var evtTarget = evt.target; - var parent = evtTarget.parentNode; + var parent = evtTarget.parentNode; // Do nothing if already in current group - // Do nothing if already in current group if (parent === currentGroup) { return; } @@ -15229,7 +16691,6 @@ var _mouseTarget = mouseTarget, tagName = _mouseTarget.tagName; - if (tagName === 'text' && currentMode !== 'textedit') { var pt = transformPoint(evt.pageX, evt.pageY, rootSctm); textActions.select(mouseTarget, pt.x, pt.y); @@ -15238,13 +16699,13 @@ if ((tagName === 'g' || tagName === 'a') && getRotationAngle(mouseTarget)) { // TODO: Allow method of in-group editing without having to do // this (similar to editing rotated paths) - // Ungroup and regroup pushGroupProperties(mouseTarget); mouseTarget = selectedElements[0]; clearSelection(true); - } - // Reset context + } // Reset context + + if (currentGroup) { leaveContext(); } @@ -15253,21 +16714,21 @@ // Escape from in-group edit return; } - setContext(mouseTarget); - }; - // prevent links from being followed in the canvas + setContext(mouseTarget); + }; // prevent links from being followed in the canvas + + var handleLinkInCanvas = function handleLinkInCanvas(e) { e.preventDefault(); return false; - }; - - // Added mouseup to the container here. + }; // Added mouseup to the container here. // TODO(codedread): Figure out why after the Closure compiler, the window mouseup is ignored. - $$9(container).mousedown(mouseDown).mousemove(mouseMove).click(handleLinkInCanvas).dblclick(dblClick).mouseup(mouseUp); - // $(window).mouseup(mouseUp); + + $$9(container).mousedown(mouseDown).mousemove(mouseMove).click(handleLinkInCanvas).dblclick(dblClick).mouseup(mouseUp); // $(window).mouseup(mouseUp); // TODO(rafaelcastrocouto): User preference for shift key and zoom factor + $$9(container).bind('mousewheel DOMMouseScroll', /** * @param {Event} e @@ -15282,42 +16743,34 @@ e.preventDefault(); var evt = e.originalEvent; - rootSctm = $$9('#svgcontent g')[0].getScreenCTM().inverse(); - var workarea = $$9('#workarea'); var scrbar = 15; - var rulerwidth = curConfig.showRulers ? 16 : 0; + var rulerwidth = curConfig.showRulers ? 16 : 0; // mouse relative to content area in content pixels - // mouse relative to content area in content pixels - var pt = transformPoint(evt.pageX, evt.pageY, rootSctm); + var pt = transformPoint(evt.pageX, evt.pageY, rootSctm); // full work area width in screen pixels - // full work area width in screen pixels var editorFullW = workarea.width(); - var editorFullH = workarea.height(); + var editorFullH = workarea.height(); // work area width minus scroll and ruler in screen pixels - // work area width minus scroll and ruler in screen pixels var editorW = editorFullW - scrbar - rulerwidth; - var editorH = editorFullH - scrbar - rulerwidth; + var editorH = editorFullH - scrbar - rulerwidth; // work area width in content pixels - // work area width in content pixels var workareaViewW = editorW * rootSctm.a; - var workareaViewH = editorH * rootSctm.d; + var workareaViewH = editorH * rootSctm.d; // content offset from canvas in screen pixels - // content offset from canvas in screen pixels var wOffset = workarea.offset(); - var wOffsetLeft = wOffset['left'] + rulerwidth; - var wOffsetTop = wOffset['top'] + rulerwidth; - + var wOffsetLeft = wOffset.left + rulerwidth; + var wOffsetTop = wOffset.top + rulerwidth; var delta = evt.wheelDelta ? evt.wheelDelta : evt.detail ? -evt.detail : 0; + if (!delta) { return; } var factor = Math.max(3 / 4, Math.min(4 / 3, delta)); + var wZoom, hZoom; - var wZoom = void 0, - hZoom = void 0; if (factor > 1) { wZoom = Math.ceil(editorW / workareaViewW * factor * 100) / 100; hZoom = Math.ceil(editorH / workareaViewH * factor * 100) / 100; @@ -15325,60 +16778,66 @@ wZoom = Math.floor(editorW / workareaViewW * factor * 100) / 100; hZoom = Math.floor(editorH / workareaViewH * factor * 100) / 100; } + var zoomlevel = Math.min(wZoom, hZoom); zoomlevel = Math.min(10, Math.max(0.01, zoomlevel)); + if (zoomlevel === currentZoom) { return; } - factor = zoomlevel / currentZoom; - // top left of workarea in content pixels before zoom - var topLeftOld = transformPoint(wOffsetLeft, wOffsetTop, rootSctm); + factor = zoomlevel / currentZoom; // top left of workarea in content pixels before zoom + + var topLeftOld = transformPoint(wOffsetLeft, wOffsetTop, rootSctm); // top left of workarea in content pixels after zoom - // top left of workarea in content pixels after zoom var topLeftNew = { x: pt.x - (pt.x - topLeftOld.x) / factor, y: pt.y - (pt.y - topLeftOld.y) / factor - }; + }; // top left of workarea in canvas pixels relative to content after zoom - // top left of workarea in canvas pixels relative to content after zoom var topLeftNewCanvas = { x: topLeftNew.x * zoomlevel, y: topLeftNew.y * zoomlevel - }; + }; // new center in canvas pixels - // new center in canvas pixels var newCtr = { x: topLeftNewCanvas.x - rulerwidth + editorFullW / 2, y: topLeftNewCanvas.y - rulerwidth + editorFullH / 2 }; - canvas.setZoom(zoomlevel); $$9('#zoom').val((zoomlevel * 100).toFixed(1)); - - call('updateCanvas', { center: false, newCtr: newCtr }); + call('updateCanvas', { + center: false, + newCtr: newCtr + }); call('zoomDone'); }); })(); - /** * Group: Text edit functions * Functions relating to editing text elements * @namespace {PlainObject} textActions * @memberof module:svgcanvas.SvgCanvas# */ + + var textActions = canvas.textActions = function () { - var curtext = void 0; - var textinput = void 0; - var cursor = void 0; - var selblock = void 0; - var blinker = void 0; + var curtext; + var textinput; + var cursor; + var selblock; + var blinker; var chardata = []; - var textbb = void 0; // , transbb; - var matrix = void 0; - var lastX = void 0, - lastY = void 0; - var allowDbl = void 0; + var textbb; // , transbb; + + var matrix; + var lastX, lastY; + var allowDbl; + /** + * + * @param {Integer} index + * @returns {undefined} + */ function setCursor(index) { var empty = textinput.value === ''; @@ -15391,15 +16850,19 @@ if (textinput.selectionEnd !== textinput.selectionStart) { return; } + index = textinput.selectionEnd; } } var charbb = chardata[index]; + if (!empty) { textinput.setSelectionRange(index, index); } + cursor = getElem('text_cursor'); + if (!cursor) { cursor = document.createElementNS(NS.SVG, 'line'); assignAttributes(cursor, { @@ -15419,7 +16882,6 @@ var startPt = ptToScreen(charbb.x, textbb.y); var endPt = ptToScreen(charbb.x, textbb.y + textbb.height); - assignAttributes(cursor, { x1: startPt.x, y1: startPt.y, @@ -15433,6 +16895,14 @@ selblock.setAttribute('d', ''); } } + /** + * + * @param {Integer} start + * @param {Integer} end + * @param {boolean} skipInput + * @returns {undefined} + */ + function setSelection(start, end, skipInput) { if (start === end) { @@ -15445,6 +16915,7 @@ } selblock = getElem('text_selectblock'); + if (!selblock) { selblock = document.createElementNS(NS.SVG, 'path'); assignAttributes(selblock, { @@ -15458,70 +16929,98 @@ var startbb = chardata[start]; var endbb = chardata[end]; - cursor.setAttribute('visibility', 'hidden'); - var tl = ptToScreen(startbb.x, textbb.y), tr = ptToScreen(startbb.x + (endbb.x - startbb.x), textbb.y), bl = ptToScreen(startbb.x, textbb.y + textbb.height), br = ptToScreen(startbb.x + (endbb.x - startbb.x), textbb.y + textbb.height); - var dstr = 'M' + tl.x + ',' + tl.y + ' L' + tr.x + ',' + tr.y + ' ' + br.x + ',' + br.y + ' ' + bl.x + ',' + bl.y + 'z'; - assignAttributes(selblock, { d: dstr, display: 'inline' }); } + /** + * + * @param {Float} mouseX + * @param {Float} mouseY + * @returns {Integer} + */ + function getIndexFromPoint(mouseX, mouseY) { // Position cursor here var pt = svgroot.createSVGPoint(); pt.x = mouseX; - pt.y = mouseY; + pt.y = mouseY; // No content, so return 0 - // No content, so return 0 if (chardata.length === 1) { return 0; - } - // Determine if cursor should be on left or right of character + } // Determine if cursor should be on left or right of character + + var charpos = curtext.getCharNumAtPosition(pt); + if (charpos < 0) { // Out of text range, look at mouse coords charpos = chardata.length - 2; + if (mouseX <= chardata[0].x) { charpos = 0; } } else if (charpos >= chardata.length - 2) { charpos = chardata.length - 2; } + var charbb = chardata[charpos]; var mid = charbb.x + charbb.width / 2; + if (mouseX > mid) { charpos++; } + return charpos; } + /** + * + * @param {Float} mouseX + * @param {Float} mouseY + * @returns {undefined} + */ + function setCursorFromPoint(mouseX, mouseY) { setCursor(getIndexFromPoint(mouseX, mouseY)); } + /** + * + * @param {Float} x + * @param {Float} y + * @param {boolean} apply + * @returns {undefined} + */ + function setEndSelectionFromPoint(x, y, apply) { var i1 = textinput.selectionStart; var i2 = getIndexFromPoint(x, y); - var start = Math.min(i1, i2); var end = Math.max(i1, i2); setSelection(start, end, !apply); } + /** + * + * @param {Float} xIn + * @param {Float} yIn + * @returns {module:math.XYObject} + */ + function screenToPt(xIn, yIn) { var out = { x: xIn, y: yIn }; - out.x /= currentZoom; out.y /= currentZoom; @@ -15533,6 +17032,13 @@ return out; } + /** + * + * @param {Float} xIn + * @param {Float} yIn + * @returns {module:math.XYObject} + */ + function ptToScreen(xIn, yIn) { var out = { @@ -15548,10 +17054,8 @@ out.x *= currentZoom; out.y *= currentZoom; - return out; } - /* // Not currently in use function hideCursor () { @@ -15561,10 +17065,23 @@ } */ + /** + * + * @param {Event} evt + * @returns {undefined} + */ + + function selectAll(evt) { setSelection(0, curtext.textContent.length); $$9(this).unbind(evt); } + /** + * + * @param {Event} evt + * @returns {undefined} + */ + function selectWord(evt) { if (!allowDbl || !curtext) { @@ -15575,22 +17092,22 @@ mouseX = ept.x * currentZoom, mouseY = ept.y * currentZoom; var pt = screenToPt(mouseX, mouseY); - var index = getIndexFromPoint(pt.x, pt.y); var str = curtext.textContent; var first = str.substr(0, index).replace(/[a-z0-9]+$/i, '').length; var m = str.substr(index).match(/^[a-z0-9]+/i); var last = (m ? m[0].length : 0) + index; - setSelection(first, last); + setSelection(first, last); // Set tripleclick - // Set tripleclick $$9(evt.target).click(selectAll); setTimeout(function () { $$9(evt.target).unbind('click', selectAll); }, 300); } - return (/** @lends module:svgcanvas.SvgCanvas#textActions */{ + return ( + /** @lends module:svgcanvas.SvgCanvas#textActions */ + { /** * @param {Element} target * @param {Float} x @@ -15620,13 +17137,10 @@ */ mouseDown: function mouseDown(evt, mouseTarget, startX, startY) { var pt = screenToPt(startX, startY); - textinput.focus(); setCursorFromPoint(pt.x, pt.y); lastX = startX; - lastY = startY; - - // TODO: Find way to block native selection + lastY = startY; // TODO: Find way to block native selection }, /** @@ -15640,17 +17154,14 @@ }, /** - * @param {external:MouseEvent} + * @param {external:MouseEvent} evt * @param {Float} mouseX * @param {Float} mouseY * @returns {undefined} */ mouseUp: function mouseUp(evt, mouseX, mouseY) { var pt = screenToPt(mouseX, mouseY); - - setEndSelectionFromPoint(pt.x, pt.y, true); - - // TODO: Find a way to make this work: Use transformed BBox instead of evt.target + setEndSelectionFromPoint(pt.x, pt.y, true); // TODO: Find a way to make this work: Use transformed BBox instead of evt.target // if (lastX === mouseX && lastY === mouseY // && !rectsIntersect(transbb, {x: pt.x, y: pt.y, width: 0, height: 0})) { // textActions.toSelectMode(true); @@ -15667,6 +17178,7 @@ * @returns {undefined} */ setCursor: setCursor, + /** * @param {Float} x * @param {Float} y @@ -15675,16 +17187,15 @@ toEditMode: function toEditMode(x, y) { allowDbl = false; currentMode = 'textedit'; - selectorManager.requestSelector(curtext).showGrips(false); - // Make selector group accept clicks - /* const selector = */selectorManager.requestSelector(curtext); // Do we need this? Has side effect of setting lock, so keeping for now, but next line wasn't being used + selectorManager.requestSelector(curtext).showGrips(false); // Make selector group accept clicks + + /* const selector = */ + + selectorManager.requestSelector(curtext); // Do we need this? Has side effect of setting lock, so keeping for now, but next line wasn't being used // const sel = selector.selectorRect; textActions.init(); - - $$9(curtext).css('cursor', 'text'); - - // if (supportsEditableText()) { + $$9(curtext).css('cursor', 'text'); // if (supportsEditableText()) { // curtext.setAttribute('editable', 'simple'); // return; // } @@ -15710,31 +17221,31 @@ currentMode = 'select'; clearInterval(blinker); blinker = null; + if (selblock) { $$9(selblock).attr('display', 'none'); } + if (cursor) { $$9(cursor).attr('visibility', 'hidden'); } + $$9(curtext).css('cursor', 'move'); if (selectElem) { clearSelection(); $$9(curtext).css('cursor', 'move'); - call('selected', [curtext]); addToSelection([curtext], true); } + if (curtext && !curtext.textContent.length) { // No content, so delete canvas.deleteSelectedElements(); } $$9(textinput).blur(); - - curtext = false; - - // if (supportsEditableText()) { + curtext = false; // if (supportsEditableText()) { // curtext.removeAttribute('editable'); // } }, @@ -15744,8 +17255,7 @@ * @returns {undefined} */ setInputElem: function setInputElem(elem) { - textinput = elem; - // $(textinput).blur(hideCursor); + textinput = elem; // $(textinput).blur(hideCursor); }, /** @@ -15761,13 +17271,12 @@ * @param {Element} inputElem Not in use * @returns {undefined} */ - init: function init$$1(inputElem) { + init: function init(inputElem) { if (!curtext) { return; } - var i = void 0, - end = void 0; - // if (supportsEditableText()) { + + var i, end; // if (supportsEditableText()) { // curtext.select(); // return; // } @@ -15780,21 +17289,19 @@ var str = curtext.textContent; var len = str.length; - var xform = curtext.getAttribute('transform'); - textbb = getBBox(curtext); - matrix = xform ? getMatrix(curtext) : null; - chardata = []; chardata.length = len; textinput.focus(); - $$9(curtext).unbind('dblclick', selectWord).dblclick(selectWord); if (!len) { - end = { x: textbb.x + textbb.width / 2, width: 0 }; + end = { + x: textbb.x + textbb.width / 2, + width: 0 + }; } for (i = 0; i < len; i++) { @@ -15805,24 +17312,23 @@ var offset = canvas.contentW * currentZoom; start.x -= offset; end.x -= offset; - start.x /= currentZoom; end.x /= currentZoom; - } - - // Get a "bbox" equivalent for each character. Uses the + } // Get a "bbox" equivalent for each character. Uses the // bbox data of the actual text for y, height purposes - // TODO: Decide if y, width and height are actually necessary + + chardata[i] = { x: start.x, - y: textbb.y, // start.y? + y: textbb.y, + // start.y? width: end.x - start.x, height: textbb.height }; - } + } // Add a last bbox for cursor at end of text + - // Add a last bbox for cursor at end of text chardata.push({ x: end.x, width: 0 @@ -15832,7 +17338,6 @@ } ); }(); - /** * Group: Serialization */ @@ -15843,35 +17348,38 @@ * @function module:svgcanvas.SvgCanvas#removeUnusedDefElems * @returns {Integer} The number of elements that were removed */ + + var removeUnusedDefElems = this.removeUnusedDefElems = function () { var defs = svgcontent.getElementsByTagNameNS(NS.SVG, 'defs'); + if (!defs || !defs.length) { return 0; - } + } // if (!defs.firstChild) { return; } - // if (!defs.firstChild) { return; } var defelemUses = []; var numRemoved = 0; var attrs = ['fill', 'stroke', 'filter', 'marker-start', 'marker-mid', 'marker-end']; var alen = attrs.length; - var allEls = svgcontent.getElementsByTagNameNS(NS.SVG, '*'); var allLen = allEls.length; + var i, j; - var i = void 0, - j = void 0; for (i = 0; i < allLen; i++) { var el = allEls[i]; + for (j = 0; j < alen; j++) { var ref = getUrlFromAttr(el.getAttribute(attrs[j])); + if (ref) { defelemUses.push(ref.substr(1)); } - } + } // gradients can refer to other gradients + - // gradients can refer to other gradients var href = getHref(el); + if (href && href.startsWith('#')) { defelemUses.push(href.substr(1)); } @@ -15879,6 +17387,7 @@ var defelems = $$9(defs).find('linearGradient, radialGradient, filter, marker, svg, symbol'); i = defelems.length; + while (i--) { var defelem = defelems[i]; var id = defelem.id; @@ -15893,52 +17402,52 @@ return numRemoved; }; - /** - * Main function to set up the SVG content for output + * Main function to set up the SVG content for output. * @function module:svgcanvas.SvgCanvas#svgCanvasToString * @returns {string} The SVG image for output */ + + this.svgCanvasToString = function () { // keep calling it until there are none to remove - while (removeUnusedDefElems() > 0) {} + while (removeUnusedDefElems() > 0) {} // eslint-disable-line no-empty - pathActions$$1.clear(true); - // Keep SVG-Edit comment on top + pathActions$1.clear(true); // Keep SVG-Edit comment on top + $$9.each(svgcontent.childNodes, function (i, node) { if (i && node.nodeType === 8 && node.data.includes('Created with')) { svgcontent.firstChild.before(node); } - }); + }); // Move out of in-group editing mode - // Move out of in-group editing mode if (currentGroup) { leaveContext(); selectOnly([currentGroup]); } - var nakedSvgs = []; + var nakedSvgs = []; // Unwrap gsvg if it has no special attributes (only id and style) - // Unwrap gsvg if it has no special attributes (only id and style) $$9(svgcontent).find('g:data(gsvg)').each(function () { var attrs = this.attributes; var len = attrs.length; + for (var i = 0; i < len; i++) { if (attrs[i].nodeName === 'id' || attrs[i].nodeName === 'style') { len--; } - } - // No significant attributes, so ungroup + } // No significant attributes, so ungroup + + if (len <= 0) { var svg = this.firstChild; nakedSvgs.push(svg); $$9(this).replaceWith(svg); } }); - var output = this.svgToString(svgcontent, 0); + var output = this.svgToString(svgcontent, 0); // Rewrap gsvg - // Rewrap gsvg if (nakedSvgs.length) { $$9(nakedSvgs).each(function () { groupSvgElem(this); @@ -15947,14 +17456,15 @@ return output; }; - /** - * Sub function ran on each SVG element to convert it to a string as desired + * Sub function ran on each SVG element to convert it to a string as desired. * @function module:svgcanvas.SvgCanvas#svgToString * @param {Element} elem - The SVG element to convert * @param {Integer} indent - Number of spaces to indent this tag * @returns {string} The given element as an SVG tag */ + + this.svgToString = function (elem, indent) { var out = []; var unit = curConfig.baseUnit; @@ -15962,23 +17472,25 @@ if (elem) { cleanupElement(elem); - var attrs = Array.from(elem.attributes); - var i = void 0; + + var attrs = _toConsumableArray(elem.attributes); + var childs = elem.childNodes; attrs.sort(function (a, b) { return a.name > b.name ? -1 : 1; }); - for (i = 0; i < indent; i++) { + for (var i = 0; i < indent; i++) { out.push(' '); } - out.push('<');out.push(elem.nodeName); + + out.push('<'); + out.push(elem.nodeName); + if (elem.id === 'svgcontent') { // Process root element separately var res = getResolution(); - - var vb = ''; - // TODO: Allow this by dividing all values by current baseVal + var vb = ''; // TODO: Allow this by dividing all values by current baseVal // Note that this also means we should properly deal with this on import // if (curConfig.baseUnit !== 'px') { // const unit = curConfig.baseUnit; @@ -15996,92 +17508,104 @@ } out.push(' width="' + res.w + '" height="' + res.h + '"' + vb + ' xmlns="' + NS.SVG + '"'); + var nsuris = {}; // Check elements for namespaces, add if found - var nsuris = {}; - - // Check elements for namespaces, add if found $$9(elem).find('*').andSelf().each(function () { // const el = this; // for some elements have no attribute var uri = this.namespaceURI; + if (uri && !nsuris[uri] && nsMap[uri] && nsMap[uri] !== 'xmlns' && nsMap[uri] !== 'xml') { nsuris[uri] = true; out.push(' xmlns:' + nsMap[uri] + '="' + uri + '"'); } $$9.each(this.attributes, function (i, attr) { - var uri = attr.namespaceURI; - if (uri && !nsuris[uri] && nsMap[uri] !== 'xmlns' && nsMap[uri] !== 'xml') { - nsuris[uri] = true; - out.push(' xmlns:' + nsMap[uri] + '="' + uri + '"'); + var u = attr.namespaceURI; + + if (u && !nsuris[u] && nsMap[u] !== 'xmlns' && nsMap[u] !== 'xml') { + nsuris[u] = true; + out.push(' xmlns:' + nsMap[u] + '="' + u + '"'); } }); }); - - i = attrs.length; + var _i3 = attrs.length; var attrNames = ['width', 'height', 'xmlns', 'x', 'y', 'viewBox', 'id', 'overflow']; - while (i--) { - var attr = attrs[i]; - var attrVal = toXml(attr.value); - // Namespaces have already been dealt with, so skip + while (_i3--) { + var attr = attrs[_i3]; + var attrVal = toXml(attr.value); // Namespaces have already been dealt with, so skip + if (attr.nodeName.startsWith('xmlns:')) { continue; - } + } // only serialize attributes we don't use internally + - // only serialize attributes we don't use internally if (attrVal !== '' && !attrNames.includes(attr.localName)) { if (!attr.namespaceURI || nsMap[attr.namespaceURI]) { out.push(' '); - out.push(attr.nodeName);out.push('="'); - out.push(attrVal);out.push('"'); + out.push(attr.nodeName); + out.push('="'); + out.push(attrVal); + out.push('"'); } } } } else { // Skip empty defs if (elem.nodeName === 'defs' && !elem.firstChild) { - return; + return ''; } var mozAttrs = ['-moz-math-font-style', '_moz-math-font-style']; - for (i = attrs.length - 1; i >= 0; i--) { - var _attr = attrs[i]; - var _attrVal = toXml(_attr.value); - // remove bogus attributes added by Gecko + + for (var _i4 = attrs.length - 1; _i4 >= 0; _i4--) { + var _attr = attrs[_i4]; + + var _attrVal = toXml(_attr.value); // remove bogus attributes added by Gecko + + if (mozAttrs.includes(_attr.localName)) { continue; } + if (_attrVal !== '') { if (_attrVal.startsWith('pointer-events')) { continue; } + if (_attr.localName === 'class' && _attrVal.startsWith('se_')) { continue; } + out.push(' '); + if (_attr.localName === 'd') { - _attrVal = pathActions$$1.convertPath(elem, true); + _attrVal = pathActions$1.convertPath(elem, true); } + if (!isNaN(_attrVal)) { _attrVal = shortFloat(_attrVal); } else if (unitRe.test(_attrVal)) { _attrVal = shortFloat(_attrVal) + unit; - } + } // Embed images when saving + - // Embed images when saving if (saveOptions.apply && elem.nodeName === 'image' && _attr.localName === 'href' && saveOptions.images && saveOptions.images === 'embed') { var img = encodableImages[_attrVal]; + if (img) { _attrVal = img; } - } - - // map various namespaces to our fixed namespace prefixes + } // map various namespaces to our fixed namespace prefixes // (the default xmlns attribute itself does not get a prefix) + + if (!_attr.namespaceURI || _attr.namespaceURI === NS.SVG || nsMap[_attr.namespaceURI]) { - out.push(_attr.nodeName);out.push('="'); - out.push(_attrVal);out.push('"'); + out.push(_attr.nodeName); + out.push('="'); + out.push(_attrVal); + out.push('"'); } } } @@ -16092,22 +17616,29 @@ indent++; var bOneLine = false; - for (i = 0; i < childs.length; i++) { - var child = childs.item(i); + for (var _i5 = 0; _i5 < childs.length; _i5++) { + var child = childs.item(_i5); + switch (child.nodeType) { case 1: // element node out.push('\n'); - out.push(this.svgToString(childs.item(i), indent)); + out.push(this.svgToString(childs.item(_i5), indent)); break; + case 3: - // text node - var str = child.nodeValue.replace(/^\s+|\s+$/g, ''); - if (str !== '') { - bOneLine = true; - out.push(String(toXml(str))); + { + // text node + var str = child.nodeValue.replace(/^\s+|\s+$/g, ''); + + if (str !== '') { + bOneLine = true; + out.push(String(toXml(str))); + } + + break; } - break; + case 4: // cdata node out.push('\n'); @@ -16116,6 +17647,7 @@ out.push(child.nodeValue); out.push(']]>'); break; + case 8: // comment out.push('\n'); @@ -16125,19 +17657,27 @@ out.push('-->'); break; } // switch on node type + } + indent--; + if (!bOneLine) { out.push('\n'); - for (i = 0; i < indent; i++) { + + for (var _i6 = 0; _i6 < indent; _i6++) { out.push(' '); } } - out.push('</');out.push(elem.nodeName);out.push('>'); + + out.push('</'); + out.push(elem.nodeName); + out.push('>'); } else { out.push('/>'); } } + return out.join(''); }; // end svgToString() @@ -16147,28 +17687,33 @@ * @param {string|false} result Data URL * @returns {undefined} */ + /** - * Converts a given image file to a data URL when possible, then runs a given callback + * Converts a given image file to a data URL when possible, then runs a given callback. * @function module:svgcanvas.SvgCanvas#embedImage * @param {string} src - The path/URL of the image - * @param {module:svgcanvas.ImageEmbeddedCallback} [callback] - Function to run when image data is found * @returns {Promise} Resolves to Data URL (string|false) */ - this.embedImage = function (src, callback) { + + + this.embedImage = function (src) { + // Todo: Remove this Promise in favor of making an async/await `Image.load` utility return new Promise(function (resolve, reject) { + // eslint-disable-line promise/avoid-new // load in the image and once it's loaded, get the dimensions $$9(new Image()).load(function (response, status, xhr) { if (status === 'error') { reject(new Error('Error loading image: ' + xhr.status + ' ' + xhr.statusText)); return; - } - // create a canvas the same size as the raster image + } // create a canvas the same size as the raster image + + var cvs = document.createElement('canvas'); cvs.width = this.width; - cvs.height = this.height; - // load the raster image into the canvas - cvs.getContext('2d').drawImage(this, 0, 0); - // retrieve the data: URL + cvs.height = this.height; // load the raster image into the canvas + + cvs.getContext('2d').drawImage(this, 0, 0); // retrieve the data: URL + try { var urldata = ';svgedit_url=' + encodeURIComponent(src); urldata = cvs.toDataURL().replace(';base64', urldata + ';base64'); @@ -16176,32 +17721,33 @@ } catch (e) { encodableImages[src] = false; } + lastGoodImgUrl = src; - if (callback) { - callback(encodableImages[src]); - } resolve(encodableImages[src]); }).attr('src', src); }); }; - /** - * Sets a given URL to be a "last good image" URL + * Sets a given URL to be a "last good image" URL. * @function module:svgcanvas.SvgCanvas#setGoodImage * @param {string} val * @returns {undefined} */ + + this.setGoodImage = function (val) { lastGoodImgUrl = val; }; - /** - * Does nothing by default, handled by optional widget/extension + * Does nothing by default, handled by optional widget/extension. * @function module:svgcanvas.SvgCanvas#open * @returns {undefined} */ - this.open = function () {}; + + this.open = function () { + /* */ + }; /** * Serializes the current drawing into SVG XML text and passes it to the 'saved' handler. * This function also includes the XML prolog. Clients of the `SvgCanvas` bind their save @@ -16211,40 +17757,47 @@ * @fires module:svgcanvas.SvgCanvas#event:saved * @returns {undefined} */ + + this.save = function (opts) { // remove the selected outline before serializing - clearSelection(); - // Update save options if provided + clearSelection(); // Update save options if provided + if (opts) { $$9.extend(saveOptions, opts); } - saveOptions.apply = true; - // no need for doctype, see https://jwatt.org/svg/authoring/#doctype-declaration + saveOptions.apply = true; // no need for doctype, see https://jwatt.org/svg/authoring/#doctype-declaration + var str = this.svgCanvasToString(); call('saved', str); }; + /** + * @typedef {PlainObject} module:svgcanvas.IssuesAndCodes + * @property {string[]} issueCodes The locale-independent code names + * @property {string[]} issues The localized descriptions + */ /** - * Codes only is useful for locale-independent detection + * Codes only is useful for locale-independent detection. + * @returns {module:svgcanvas.IssuesAndCodes} */ + + function getIssues() { // remove the selected outline before serializing - clearSelection(); + clearSelection(); // Check for known CanVG issues - // Check for known CanVG issues var issues = []; - var issueCodes = []; + var issueCodes = []; // Selector and notice - // Selector and notice var issueList = { feGaussianBlur: uiStrings.exportNoBlur, foreignObject: uiStrings.exportNoforeignObject, '[stroke-dasharray]': uiStrings.exportNoDashArray }; - var content = $$9(svgcontent); + var content = $$9(svgcontent); // Add font/text check if Canvas Text API is not implemented - // Add font/text check if Canvas Text API is not implemented if (!('font' in $$9('<canvas>')[0].getContext('2d'))) { issueList.text = uiStrings.exportNoText; } @@ -16255,13 +17808,17 @@ issues.push(descr); } }); - return { issues: issues, issueCodes: issueCodes }; + return { + issues: issues, + issueCodes: issueCodes + }; } - var canvg = void 0; + var canvg; /** * @typedef {"feGaussianBlur"|"foreignObject"|"[stroke-dasharray]"|"text"} module:svgcanvas.IssueCode */ + /** * @typedef {PlainObject} module:svgcanvas.ImageExportedResults * @property {string} datauri Contents as a Data URL @@ -16275,123 +17832,139 @@ * @property {string} exportWindowName A convenience for passing along a `window.name` to target a window on which the export could be added */ - /** - * Function to run when image data is found - * @callback module:svgcanvas.ImageExportedCallback - * @param {module:svgcanvas.ImageExportedResults} obj - * @returns {undefined} - */ /** * Generates a PNG (or JPG, BMP, WEBP) Data URL based on the current image, * then calls "exported" with an object including the string, image - * information, and any issues found + * information, and any issues found. * @function module:svgcanvas.SvgCanvas#rasterExport * @param {"PNG"|"JPEG"|"BMP"|"WEBP"|"ICO"} [imgType="PNG"] * @param {Float} [quality] Between 0 and 1 * @param {string} [exportWindowName] - * @param {module:svgcanvas.ImageExportedCallback} [cb] + * @param {PlainObject} [opts] + * @param {boolean} [opts.avoidEvent] * @fires module:svgcanvas.SvgCanvas#event:exported * @todo Confirm/fix ICO type * @returns {Promise} Resolves to {@link module:svgcanvas.ImageExportedResults} */ - this.rasterExport = function (imgType, quality, exportWindowName, cb) { - var _this = this; - var type = imgType === 'ICO' ? 'BMP' : imgType || 'PNG'; - var mimeType = 'image/' + type.toLowerCase(); + this.rasterExport = + /*#__PURE__*/ + function () { + var _ref5 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee2(imgType, quality, exportWindowName) { + var opts, + type, + mimeType, + _getIssues, + issues, + issueCodes, + svg, + _ref6, + c, + _args2 = arguments; - var _getIssues = getIssues(), - issues = _getIssues.issues, - issueCodes = _getIssues.issueCodes; + return regeneratorRuntime.wrap(function _callee2$(_context2) { + while (1) { + switch (_context2.prev = _context2.next) { + case 0: + opts = _args2.length > 3 && _args2[3] !== undefined ? _args2[3] : {}; + type = imgType === 'ICO' ? 'BMP' : imgType || 'PNG'; + mimeType = 'image/' + type.toLowerCase(); + _getIssues = getIssues(), issues = _getIssues.issues, issueCodes = _getIssues.issueCodes; + svg = this.svgCanvasToString(); - var svg = this.svgCanvasToString(); + if (canvg) { + _context2.next = 10; + break; + } - return new Promise(function () { - var _ref4 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(resolve, reject) { - var _ref5, c, dataURLType, datauri, bloburl, done; + _context2.next = 8; + return importSetGlobal(curConfig.canvgPath + 'canvg.js', { + global: 'canvg' + }); - return regeneratorRuntime.wrap(function _callee2$(_context2) { - while (1) { - switch (_context2.prev = _context2.next) { - case 0: - done = function done() { + case 8: + _ref6 = _context2.sent; + canvg = _ref6.canvg; + + case 10: + if (!$$9('#export_canvas').length) { + $$9('<canvas>', { + id: 'export_canvas' + }).hide().appendTo('body'); + } + + c = $$9('#export_canvas')[0]; + c.width = canvas.contentW; + c.height = canvas.contentH; + _context2.next = 16; + return canvg(c, svg); + + case 16: + return _context2.abrupt("return", new Promise(function (resolve, reject) { + // eslint-disable-line promise/avoid-new + var dataURLType = type.toLowerCase(); + var datauri = quality ? c.toDataURL('image/' + dataURLType, quality) : c.toDataURL('image/' + dataURLType); + var bloburl; + /** + * Called when `bloburl` is available for export. + * @returns {undefined} + */ + + function done() { var obj = { - datauri: datauri, bloburl: bloburl, svg: svg, issues: issues, issueCodes: issueCodes, type: imgType, - mimeType: mimeType, quality: quality, exportWindowName: exportWindowName + datauri: datauri, + bloburl: bloburl, + svg: svg, + issues: issues, + issueCodes: issueCodes, + type: imgType, + mimeType: mimeType, + quality: quality, + exportWindowName: exportWindowName }; - call('exported', obj); - if (cb) { - cb(obj); + + if (!opts.avoidEvent) { + call('exported', obj); } + resolve(obj); - }; - - if (canvg) { - _context2.next = 6; - break; } - _context2.next = 4; - return importSetGlobal(curConfig.canvgPath + 'canvg.js', { - global: 'canvg' - }); - - case 4: - _ref5 = _context2.sent; - canvg = _ref5.canvg; - - case 6: - if (!$$9('#export_canvas').length) { - $$9('<canvas>', { id: 'export_canvas' }).hide().appendTo('body'); - } - c = $$9('#export_canvas')[0]; - - c.width = canvas.contentW; - c.height = canvas.contentH; - - _context2.next = 12; - return canvg(c, svg); - - case 12: - dataURLType = type.toLowerCase(); - datauri = quality ? c.toDataURL('image/' + dataURLType, quality) : c.toDataURL('image/' + dataURLType); - bloburl = void 0; - - if (!c.toBlob) { - _context2.next = 18; - break; + if (c.toBlob) { + c.toBlob(function (blob) { + bloburl = createObjectURL(blob); + done(); + }, mimeType, quality); + return; } - c.toBlob(function (blob) { - bloburl = createObjectURL(blob); - done(); - }, mimeType, quality); - return _context2.abrupt('return'); - - case 18: bloburl = dataURLToObjectURL(datauri); done(); + })); - case 20: - case 'end': - return _context2.stop(); - } + case 17: + case "end": + return _context2.stop(); } - }, _callee2, _this); - })); + } + }, _callee2, this); + })); - return function (_x4, _x5) { - return _ref4.apply(this, arguments); - }; - }()); - }; + return function (_x4, _x5, _x6) { + return _ref5.apply(this, arguments); + }; + }(); /** * @external jsPDF */ + /** * @typedef {undefined|"save"|"arraybuffer"|"blob"|"datauristring"|"dataurlstring"|"dataurlnewwindow"|"datauri"|"dataurl"} external:jsPDF.OutputType * @todo Newer version to add also allows these `outputType` values "bloburi"|"bloburl" which return strings, so document here and for `outputType` of `module:svgcanvas.PDFExportedResults` below if added */ + /** * @typedef {PlainObject} module:svgcanvas.PDFExportedResults * @property {string} svg The SVG PDF output @@ -16411,129 +17984,137 @@ * @property {string} exportWindowName */ - /** - * Function to run when PDF data is found - * @callback module:svgcanvas.PDFExportedCallback - * @param {module:svgcanvas.PDFExportedResults} obj - * @returns {undefined} - */ /** * Generates a PDF based on the current image, then calls "exportedPDF" with - * an object including the string, the data URL, and any issues found + * an object including the string, the data URL, and any issues found. * @function module:svgcanvas.SvgCanvas#exportPDF - * @param {string} exportWindowName Will also be used for the download file name here + * @param {string} [exportWindowName] Will also be used for the download file name here * @param {external:jsPDF.OutputType} [outputType="dataurlstring"] - * @param {module:svgcanvas.PDFExportedCallback} cb * @fires module:svgcanvas.SvgCanvas#event:exportedPDF * @returns {Promise} Resolves to {@link module:svgcanvas.PDFExportedResults} */ - this.exportPDF = function (exportWindowName, outputType, cb) { - var _this2 = this; - var that = this; - return new Promise(function () { - var _ref6 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(resolve, reject) { - var modularVersion, res, orientation, unit, doc, docTitle, _getIssues2, issues, issueCodes, svg, obj; - return regeneratorRuntime.wrap(function _callee3$(_context3) { - while (1) { - switch (_context3.prev = _context3.next) { - case 0: - if (window.jsPDF) { - _context3.next = 6; - break; - } + this.exportPDF = + /*#__PURE__*/ + function () { + var _ref7 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee3(exportWindowName) { + var outputType, + modularVersion, + res, + orientation, + unit, + doc, + docTitle, + _getIssues2, + issues, + issueCodes, + svg, + obj, + _args3 = arguments; - _context3.next = 3; - return importScript([ - // We do not currently have these paths configurable as they are - // currently global-only, so not Rolled-up - 'jspdf/underscore-min.js', 'jspdf/jspdf.min.js']); + return regeneratorRuntime.wrap(function _callee3$(_context3) { + while (1) { + switch (_context3.prev = _context3.next) { + case 0: + outputType = _args3.length > 1 && _args3[1] !== undefined ? _args3[1] : isChrome() ? 'save' : undefined; - case 3: - modularVersion = !('svgEditor' in window) || !window.svgEditor || window.svgEditor.modules !== false; - // Todo: Switch to `import()` when widely supported and available (also allow customization of path) + if (window.jsPDF) { + _context3.next = 7; + break; + } - _context3.next = 6; - return importScript(curConfig.jspdfPath + 'jspdf.plugin.svgToPdf.js', { - type: modularVersion ? 'module' : 'text/javascript' - }); + _context3.next = 4; + return importScript([// We do not currently have these paths configurable as they are + // currently global-only, so not Rolled-up + 'jspdf/underscore-min.js', 'jspdf/jspdf.min.js']); - case 6: - res = getResolution(); - orientation = res.w > res.h ? 'landscape' : 'portrait'; - unit = 'pt'; // curConfig.baseUnit; // We could use baseUnit, but that is presumably not intended for export purposes + case 4: + modularVersion = !('svgEditor' in window) || !window.svgEditor || window.svgEditor.modules !== false; // Todo: Switch to `import()` when widely supported and available (also allow customization of path) - // Todo: Give options to use predefined jsPDF formats like "a4", etc. from pull-down (with option to keep customizable) + _context3.next = 7; + return importScript(curConfig.jspdfPath + 'jspdf.plugin.svgToPdf.js', { + type: modularVersion ? 'module' : 'text/javascript' + }); - doc = jsPDF({ - orientation: orientation, - unit: unit, - format: [res.w, res.h] - // , compressPdf: true - }); - docTitle = getDocumentTitle(); + case 7: + res = getResolution(); + orientation = res.w > res.h ? 'landscape' : 'portrait'; + unit = 'pt'; // curConfig.baseUnit; // We could use baseUnit, but that is presumably not intended for export purposes + // Todo: Give options to use predefined jsPDF formats like "a4", etc. from pull-down (with option to keep customizable) - doc.setProperties({ - title: docTitle /* , - subject: '', - author: '', - keywords: '', - creator: '' */ - }); - _getIssues2 = getIssues(), issues = _getIssues2.issues, issueCodes = _getIssues2.issueCodes; - svg = that.svgCanvasToString(); + doc = jsPDF({ + orientation: orientation, + unit: unit, + format: [res.w, res.h] // , compressPdf: true - doc.addSVG(svg, 0, 0); + }); + docTitle = getDocumentTitle(); + doc.setProperties({ + title: docTitle + /* , + subject: '', + author: '', + keywords: '', + creator: '' */ - // doc.output('save'); // Works to open in a new - // window; todo: configure this and other export - // options to optionally work in this manner as - // opposed to opening a new tab - outputType = outputType || 'dataurlstring'; - obj = { svg: svg, issues: issues, issueCodes: issueCodes, exportWindowName: exportWindowName, outputType: outputType }; + }); + _getIssues2 = getIssues(), issues = _getIssues2.issues, issueCodes = _getIssues2.issueCodes; + svg = this.svgCanvasToString(); + doc.addSVG(svg, 0, 0); // doc.output('save'); // Works to open in a new + // window; todo: configure this and other export + // options to optionally work in this manner as + // opposed to opening a new tab - obj.output = doc.output(outputType, outputType === 'save' ? exportWindowName || 'svg.pdf' : undefined); - if (cb) { - cb(obj); - } - resolve(obj); - call('exportedPDF', obj); + outputType = outputType || 'dataurlstring'; + obj = { + svg: svg, + issues: issues, + issueCodes: issueCodes, + exportWindowName: exportWindowName, + outputType: outputType + }; + obj.output = doc.output(outputType, outputType === 'save' ? exportWindowName || 'svg.pdf' : undefined); + call('exportedPDF', obj); + return _context3.abrupt("return", obj); - case 21: - case 'end': - return _context3.stop(); - } + case 21: + case "end": + return _context3.stop(); } - }, _callee3, _this2); - })); - - return function (_x6, _x7) { - return _ref6.apply(this, arguments); - }; - }()); - }; + } + }, _callee3, this); + })); + return function (_x7) { + return _ref7.apply(this, arguments); + }; + }(); /** * Returns the current drawing as raw SVG XML text. * @function module:svgcanvas.SvgCanvas#getSvgString * @returns {string} The current drawing as raw SVG XML text. */ + + this.getSvgString = function () { saveOptions.apply = false; return this.svgCanvasToString(); }; - /** * This function determines whether to use a nonce in the prefix, when * generating IDs for future documents in SVG-Edit. * If you're controlling SVG-Edit externally, and want randomized IDs, call - * this BEFORE calling svgCanvas.setSvgString + * this BEFORE calling `svgCanvas.setSvgString`. * @function module:svgcanvas.SvgCanvas#randomizeIds * @param {boolean} [enableRandomization] If true, adds a nonce to the prefix. Thus * `svgCanvas.randomizeIds() <==> svgCanvas.randomizeIds(true)` * @returns {undefined} */ + + this.randomizeIds = function (enableRandomization) { if (arguments.length > 0 && enableRandomization === false) { randomizeIds(false, getCurrentDrawing()); @@ -16541,16 +18122,16 @@ randomizeIds(true, getCurrentDrawing()); } }; - /** - * Ensure each element has a unique ID + * Ensure each element has a unique ID. * @function module:svgcanvas.SvgCanvas#uniquifyElems * @param {Element} g - The parent element of the tree to give unique IDs * @returns {undefined} */ + + var uniquifyElems = this.uniquifyElems = function (g) { - var ids = {}; - // TODO: Handle markers and connectors. These are not yet re-identified properly + var ids = {}; // TODO: Handle markers and connectors. These are not yet re-identified properly // as their referring elements do not get remapped. // // <marker id='se_marker_end_svg_7'/> @@ -16558,8 +18139,8 @@ // // Problem #1: if svg_1 gets renamed, we do not update the polyline's se:connector attribute // Problem #2: if the polyline svg_7 gets renamed, we do not update the marker id nor the polyline's marker-end attribute - var refElems = ['filter', 'linearGradient', 'pattern', 'radialGradient', 'symbol', 'textPath', 'use']; + var refElems = ['filter', 'linearGradient', 'pattern', 'radialGradient', 'symbol', 'textPath', 'use']; walkTree(g, function (n) { // if it's an element node if (n.nodeType === 1) { @@ -16568,70 +18149,86 @@ // and we haven't tracked this ID yet if (!(n.id in ids)) { // add this id to our map - ids[n.id] = { elem: null, attrs: [], hrefs: [] }; + ids[n.id] = { + elem: null, + attrs: [], + hrefs: [] + }; } - ids[n.id].elem = n; - } - // now search for all attributes on this element that might refer + ids[n.id].elem = n; + } // now search for all attributes on this element that might refer // to other elements + + $$9.each(refAttrs, function (i, attr) { var attrnode = n.getAttributeNode(attr); + if (attrnode) { // the incoming file has been sanitized, so we should be able to safely just strip off the leading # var url = getUrlFromAttr(attrnode.value), refid = url ? url.substr(1) : null; + if (refid) { if (!(refid in ids)) { // add this id to our map - ids[refid] = { elem: null, attrs: [], hrefs: [] }; + ids[refid] = { + elem: null, + attrs: [], + hrefs: [] + }; } + ids[refid].attrs.push(attrnode); } } - }); + }); // check xlink:href now + + var href = getHref(n); // TODO: what if an <image> or <a> element refers to an element internally? - // check xlink:href now - var href = getHref(n); - // TODO: what if an <image> or <a> element refers to an element internally? if (href && refElems.includes(n.nodeName)) { var refid = href.substr(1); + if (refid) { if (!(refid in ids)) { // add this id to our map - ids[refid] = { elem: null, attrs: [], hrefs: [] }; + ids[refid] = { + elem: null, + attrs: [], + hrefs: [] + }; } + ids[refid].hrefs.push(n); } } } - }); + }); // in ids, we now have a map of ids, elements and attributes, let's re-identify - // in ids, we now have a map of ids, elements and attributes, let's re-identify for (var oldid in ids) { if (!oldid) { continue; } + var elem = ids[oldid].elem; if (elem) { - var newid = getNextId(); + var newid = getNextId(); // assign element its new id - // assign element its new id - elem.id = newid; + elem.id = newid; // remap all url() attributes - // remap all url() attributes var attrs = ids[oldid].attrs; - var j = attrs.length; + while (j--) { var attr = attrs[j]; attr.ownerElement.setAttribute(attr.name, 'url(#' + newid + ')'); - } + } // remap all href attributes + - // remap all href attributes var hreffers = ids[oldid].hrefs; var k = hreffers.length; + while (k--) { var hreffer = hreffers[k]; setHref(hreffer, '#' + newid); @@ -16639,13 +18236,14 @@ } } }; - /** - * Assigns reference data for each use element + * Assigns reference data for each use element. * @function module:svgcanvas.SvgCanvas#setUseData * @param {Element} parent * @returns {undefined} */ + + var setUseData = this.setUseData = function (parent) { var elems = $$9(parent); @@ -16656,24 +18254,29 @@ elems.each(function () { var id = getHref(this).substr(1); var refElem = getElem(id); + if (!refElem) { return; } + $$9(this).data('ref', refElem); + if (refElem.tagName === 'symbol' || refElem.tagName === 'svg') { $$9(this).data('symbol', refElem).data('ref', refElem); } }); }; - /** - * Converts gradients from userSpaceOnUse to objectBoundingBox + * Converts gradients from userSpaceOnUse to objectBoundingBox. * @function module:svgcanvas.SvgCanvas#convertGradients * @param {Element} elem * @returns {undefined} */ + + var convertGradients = this.convertGradients = function (elem) { var elems = $$9(elem).find('linearGradient, radialGradient'); + if (!elems.length && isWebkit()) { // Bug in webkit prevents regular *Gradient selector search elems = $$9(elem).find('*').filter(function () { @@ -16682,33 +18285,33 @@ } elems.each(function () { - var grad = this; + var grad = this; // eslint-disable-line consistent-this + if ($$9(grad).attr('gradientUnits') === 'userSpaceOnUse') { // TODO: Support more than one element with this ref by duplicating parent grad - var _elems = $$9(svgcontent).find('[fill="url(#' + grad.id + ')"],[stroke="url(#' + grad.id + ')"]'); - if (!_elems.length) { + var fillStrokeElems = $$9(svgcontent).find('[fill="url(#' + grad.id + ')"],[stroke="url(#' + grad.id + ')"]'); + + if (!fillStrokeElems.length) { return; - } + } // get object's bounding box - // get object's bounding box - var bb = getBBox(_elems[0]); - // This will occur if the element is inside a <defs> or a <symbol>, + var bb = getBBox(fillStrokeElems[0]); // This will occur if the element is inside a <defs> or a <symbol>, // in which we shouldn't need to convert anyway. + if (!bb) { return; } if (grad.tagName === 'linearGradient') { - var gCoords = $$9(grad).attr(['x1', 'y1', 'x2', 'y2']); + var gCoords = $$9(grad).attr(['x1', 'y1', 'x2', 'y2']); // If has transform, convert - // If has transform, convert var tlist = grad.gradientTransform.baseVal; + if (tlist && tlist.numberOfItems > 0) { var m = transformListToTransform(tlist).matrix; var pt1 = transformPoint(gCoords.x1, gCoords.y1, m); var pt2 = transformPoint(gCoords.x2, gCoords.y2, m); - gCoords.x1 = pt1.x; gCoords.y1 = pt1.y; gCoords.x2 = pt2.x; @@ -16723,8 +18326,7 @@ y2: (gCoords.y2 - bb.y) / bb.height }); grad.removeAttribute('gradientUnits'); - } - // else { + } // else { // Note: radialGradient elements cannot be easily converted // because userSpaceOnUse will keep circular gradients, while // objectBoundingBox will x/y scale the gradient according to @@ -16744,33 +18346,34 @@ // // grad.removeAttribute('gradientUnits'); // } + } }); }; - /** - * Converts selected/given `<use>` or child SVG element to a group + * Converts selected/given `<use>` or child SVG element to a group. * @function module:svgcanvas.SvgCanvas#convertToGroup * @param {Element} elem * @fires module:svgcanvas.SvgCanvas#event:selected * @returns {undefined} */ + + var convertToGroup = this.convertToGroup = function (elem) { if (!elem) { elem = selectedElements[0]; } + var $elem = $$9(elem); var batchCmd = new BatchCommand$1(); - var ts = void 0; + var ts; if ($elem.data('gsvg')) { // Use the gsvg as the new group var svg = elem.firstChild; var pt = $$9(svg).attr(['x', 'y']); - $$9(elem.firstChild.firstChild).unwrap(); $$9(elem).removeData('gsvg'); - var tlist = getTransformList(elem); var xform = svgroot.createSVGTransform(); xform.setTranslate(pt.x, pt.y); @@ -16779,39 +18382,33 @@ call('selected', [elem]); } else if ($elem.data('symbol')) { elem = $elem.data('symbol'); - ts = $elem.attr('transform'); var pos = $elem.attr(['x', 'y']); - var vb = elem.getAttribute('viewBox'); if (vb) { var nums = vb.split(' '); - pos.x -= +nums[0]; - pos.y -= +nums[1]; - } + pos.x -= Number(nums[0]); + pos.y -= Number(nums[1]); + } // Not ideal, but works + - // Not ideal, but works ts += ' translate(' + (pos.x || 0) + ',' + (pos.y || 0) + ')'; + var prev = $elem.prev(); // Remove <use> element - var prev = $elem.prev(); - - // Remove <use> element batchCmd.addSubCommand(new RemoveElementCommand$1($elem[0], $elem[0].nextSibling, $elem[0].parentNode)); - $elem.remove(); + $elem.remove(); // See if other elements reference this symbol - // See if other elements reference this symbol var hasMore = $$9(svgcontent).find('use:data(symbol)').length; - var g = svgdoc.createElementNS(NS.SVG, 'g'); var childs = elem.childNodes; + var i; - var i = void 0; for (i = 0; i < childs.length; i++) { g.append(childs[i].cloneNode(true)); - } + } // Duplicate the gradients for Gecko, since they weren't included in the <symbol> + - // Duplicate the gradients for Gecko, since they weren't included in the <symbol> if (isGecko()) { var dupeGrads = $$9(findDefs()).children('linearGradient,radialGradient,pattern').clone(); $$9(g).append(dupeGrads); @@ -16822,17 +18419,14 @@ } var parent = elem.parentNode; + uniquifyElems(g); // Put the dupe gradients back into <defs> (after uniquifying them) - uniquifyElems(g); - - // Put the dupe gradients back into <defs> (after uniquifying them) if (isGecko()) { $$9(findDefs()).append($$9(g).find('linearGradient,radialGradient,pattern')); - } + } // now give the g itself a new id + - // now give the g itself a new id g.id = getNextId(); - prev.after(g); if (parent) { @@ -16840,10 +18434,10 @@ // remove symbol/svg element var _elem = elem, nextSibling = _elem.nextSibling; - elem.remove(); batchCmd.addSubCommand(new RemoveElementCommand$1(elem, nextSibling, parent)); } + batchCmd.addSubCommand(new InsertElementCommand$1(g)); } @@ -16853,38 +18447,35 @@ convertGradients(findDefs()); } else { convertGradients(g); - } - - // recalculate dimensions on the top-level children so that unnecessary transforms + } // recalculate dimensions on the top-level children so that unnecessary transforms // are removed + + walkTreePost(g, function (n) { try { recalculateDimensions(n); } catch (e) { - console.log(e); + console.log(e); // eslint-disable-line no-console } - }); + }); // Give ID for any visible element missing one - // Give ID for any visible element missing one $$9(g).find(visElems).each(function () { if (!this.id) { this.id = getNextId(); } }); - selectOnly([g]); - var cm = pushGroupProperties(g, true); + if (cm) { batchCmd.addSubCommand(cm); } addCommandToHistory(batchCmd); } else { - console.log('Unexpected element to ungroup:', elem); + console.log('Unexpected element to ungroup:', elem); // eslint-disable-line no-console } }; - /** * This function sets the current drawing as the input SVG XML. * @function module:svgcanvas.SvgCanvas#setSvgString @@ -16898,27 +18489,26 @@ * @returns {boolean} This function returns `false` if the set was * unsuccessful, `true` otherwise. */ + + this.setSvgString = function (xmlString, preventUndo) { try { // convert string into XML document var newDoc = text2xml(xmlString); + if (newDoc.firstElementChild && newDoc.firstElementChild.namespaceURI !== NS.SVG) { return false; } this.prepareSvg(newDoc); + var batchCmd = new BatchCommand$1('Change Source'); // remove old svg document - var batchCmd = new BatchCommand$1('Change Source'); - - // remove old svg document var _svgcontent = svgcontent, nextSibling = _svgcontent.nextSibling; - var oldzoom = svgroot.removeChild(svgcontent); - batchCmd.addSubCommand(new RemoveElementCommand$1(oldzoom, nextSibling, svgroot)); - - // set new svg document + batchCmd.addSubCommand(new RemoveElementCommand$1(oldzoom, nextSibling, svgroot)); // set new svg document // If DOM3 adoptNode() available, use it. Otherwise fall back to DOM2 importNode() + if (svgdoc.adoptNode) { svgcontent = svgdoc.adoptNode(newDoc.documentElement); } else { @@ -16927,82 +18517,77 @@ svgroot.append(svgcontent); var content = $$9(svgcontent); + canvas.current_drawing_ = new Drawing(svgcontent, idprefix); // retrieve or set the nonce - canvas.current_drawing_ = new Drawing(svgcontent, idprefix); - - // retrieve or set the nonce var nonce = getCurrentDrawing().getNonce(); + if (nonce) { call('setnonce', nonce); } else { call('unsetnonce'); - } + } // change image href vals if possible + - // change image href vals if possible content.find('image').each(function () { - var image = this; + var image = this; // eslint-disable-line consistent-this + preventClickDefault(image); var val = getHref(this); + if (val) { if (val.startsWith('data:')) { // Check if an SVG-edit data URI var m = val.match(/svgedit_url=(.*?);/); + if (m) { var url = decodeURIComponent(m[1]); $$9(new Image()).load(function () { image.setAttributeNS(NS.XLINK, 'xlink:href', url); }).attr('src', url); } - } - // Add to encodableImages if it loads + } // Add to encodableImages if it loads + + canvas.embedImage(val); } - }); + }); // Wrap child SVGs in group elements - // Wrap child SVGs in group elements content.find('svg').each(function () { // Skip if it's in a <defs> if ($$9(this).closest('defs').length) { return; } - uniquifyElems(this); + uniquifyElems(this); // Check if it already has a gsvg group - // Check if it already has a gsvg group var pa = this.parentNode; + if (pa.childNodes.length === 1 && pa.nodeName === 'g') { $$9(pa).data('gsvg', this); pa.id = pa.id || getNextId(); } else { groupSvgElem(this); } - }); + }); // For Firefox: Put all paint elems in defs - // For Firefox: Put all paint elems in defs if (isGecko()) { content.find('linearGradient, radialGradient, pattern').appendTo(findDefs()); - } - - // Set ref element for <use> elements - + } // Set ref element for <use> elements // TODO: This should also be done if the object is re-added through "redo" + + setUseData(content); - convertGradients(content[0]); - var attrs = { id: 'svgcontent', overflow: curConfig.show_outside_canvas ? 'visible' : 'hidden' }; + var percs = false; // determine proper size - var percs = false; - - // determine proper size if (content.attr('viewBox')) { var vb = content.attr('viewBox').split(' '); attrs.width = vb[2]; - attrs.height = vb[3]; - // handle content that doesn't have a viewBox + attrs.height = vb[3]; // handle content that doesn't have a viewBox } else { $$9.each(['width', 'height'], function (i, dim) { // Set to 100 if not given @@ -17015,30 +18600,29 @@ attrs[dim] = convertToNum(dim, val); } }); - } + } // identify layers - // identify layers - identifyLayers(); - // Give ID for any visible layer children missing one + identifyLayers(); // Give ID for any visible layer children missing one + content.children().find(visElems).each(function () { if (!this.id) { this.id = getNextId(); } - }); + }); // Percentage width/height, so let's base it on visible elements - // Percentage width/height, so let's base it on visible elements if (percs) { var bb = getStrokedBBoxDefaultVisible(); attrs.width = bb.width + bb.x; attrs.height = bb.height + bb.y; - } - - // Just in case negative numbers are given or + } // Just in case negative numbers are given or // result from the percs calculation + + if (attrs.width <= 0) { attrs.width = 100; } + if (attrs.height <= 0) { attrs.height = 100; } @@ -17046,31 +18630,27 @@ content.attr(attrs); this.contentW = attrs.width; this.contentH = attrs.height; + batchCmd.addSubCommand(new InsertElementCommand$1(svgcontent)); // update root to the correct size - batchCmd.addSubCommand(new InsertElementCommand$1(svgcontent)); - // update root to the correct size var changes = content.attr(['width', 'height']); - batchCmd.addSubCommand(new ChangeElementCommand$1(svgroot, changes)); + batchCmd.addSubCommand(new ChangeElementCommand$1(svgroot, changes)); // reset zoom - // reset zoom - currentZoom = 1; + currentZoom = 1; // reset transform lists - // reset transform lists resetListMap(); clearSelection(); clearData(); svgroot.append(selectorManager.selectorParentGroup); - if (!preventUndo) addCommandToHistory(batchCmd); call('changed', [svgcontent]); } catch (e) { - console.log(e); + console.log(e); // eslint-disable-line no-console + return false; } return true; }; - /** * This function imports the input SVG XML as a `<symbol>` in the `<defs>`, then adds a * `<use>` to the current layer. @@ -17085,16 +18665,16 @@ * arbitrary transform lists, but makes some assumptions about how the transform list * was obtained */ + + this.importSvgString = function (xmlString) { - var j = void 0, - ts = void 0, - useEl = void 0; + var j, ts, useEl; + try { // Get unique ID var uid = encode64(xmlString.length + xmlString).substr(0, 32); + var useExisting = false; // Look for symbol and make sure symbol exists in image - var useExisting = false; - // Look for symbol and make sure symbol exists in image if (importIds[uid]) { if ($$9(importIds[uid].symbol).parents('#svgroot').length) { useExisting = true; @@ -17102,20 +18682,18 @@ } var batchCmd = new BatchCommand$1('Import Image'); - var symbol = void 0; + var symbol; + if (useExisting) { symbol = importIds[uid].symbol; - ts = importIds[uid].xform; } else { // convert string into XML document var newDoc = text2xml(xmlString); + this.prepareSvg(newDoc); // import new svg document into our document - this.prepareSvg(newDoc); + var svg; // If DOM3 adoptNode() available, use it. Otherwise fall back to DOM2 importNode() - // import new svg document into our document - var svg = void 0; - // If DOM3 adoptNode() available, use it. Otherwise fall back to DOM2 importNode() if (svgdoc.adoptNode) { svg = svgdoc.adoptNode(newDoc.documentElement); } else { @@ -17123,31 +18701,28 @@ } uniquifyElems(svg); - var innerw = convertToNum('width', svg.getAttribute('width')), innerh = convertToNum('height', svg.getAttribute('height')), innervb = svg.getAttribute('viewBox'), - - // 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]; - for (j = 0; j < 4; ++j) { - vb[j] = +vb[j]; - } - // TODO: properly handle preserveAspectRatio + for (j = 0; j < 4; ++j) { + vb[j] = Number(vb[j]); + } // TODO: properly handle preserveAspectRatio + + var // canvasw = +svgcontent.getAttribute('width'), - canvash = +svgcontent.getAttribute('height'); - // imported content should be 1/3 of the canvas on its largest dimension + canvash = Number(svgcontent.getAttribute('height')); // imported content should be 1/3 of the canvas on its largest dimension if (innerh > innerw) { ts = 'scale(' + canvash / 3 / vb[3] + ')'; } else { ts = 'scale(' + canvash / 3 / vb[2] + ')'; - } + } // Hack to make recalculateDimensions understand how to scale + - // Hack to make recalculateDimensions understand how to scale ts = 'translate(0) ' + ts + ' translate(0)'; - symbol = svgdoc.createElementNS(NS.SVG, 'symbol'); var defs = findDefs(); @@ -17162,19 +18737,20 @@ var first = svg.firstChild; symbol.append(first); } + var attrs = svg.attributes; + for (var i = 0; i < attrs.length; i++) { var attr = attrs[i]; symbol.setAttribute(attr.nodeName, attr.value); } - symbol.id = getNextId(); - // Store data + symbol.id = getNextId(); // Store data + importIds[uid] = { symbol: symbol, xform: ts }; - findDefs().append(symbol); batchCmd.addSubCommand(new InsertElementCommand$1(symbol)); } @@ -17182,49 +18758,65 @@ useEl = svgdoc.createElementNS(NS.SVG, 'use'); useEl.id = getNextId(); setHref(useEl, '#' + symbol.id); - (currentGroup || getCurrentDrawing().getCurrentLayer()).append(useEl); batchCmd.addSubCommand(new InsertElementCommand$1(useEl)); clearSelection(); - useEl.setAttribute('transform', ts); recalculateDimensions(useEl); $$9(useEl).data('symbol', symbol).data('ref', symbol); - addToSelection([useEl]); - - // TODO: Find way to add this in a recalculateDimensions-parsable way + addToSelection([useEl]); // TODO: Find way to add this in a recalculateDimensions-parsable way // if (vb[0] !== 0 || vb[1] !== 0) { // ts = 'translate(' + (-vb[0]) + ',' + (-vb[1]) + ') ' + ts; // } + addCommandToHistory(batchCmd); call('changed', [svgcontent]); } catch (e) { - console.log(e); + console.log(e); // eslint-disable-line no-console + return null; - } + } // we want to return the element so we can automatically select it + - // we want to return the element so we can automatically select it return useEl; - }; - - // Could deprecate, but besides external uses, their usage makes clear that + }; // Could deprecate, but besides external uses, their usage makes clear that // canvas is a dependency for all of these - ['identifyLayers', 'createLayer', 'cloneLayer', 'deleteCurrentLayer', 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', 'setLayerVisibility', 'moveSelectedToLayer', 'mergeLayer', 'mergeAllLayers', 'leaveContext', 'setContext'].forEach(function (prop) { - canvas[prop] = draw[prop]; + + + var dr = { + identifyLayers: identifyLayers, + createLayer: createLayer, + cloneLayer: cloneLayer, + deleteCurrentLayer: deleteCurrentLayer, + setCurrentLayer: setCurrentLayer, + renameCurrentLayer: renameCurrentLayer, + setCurrentLayerPosition: setCurrentLayerPosition, + setLayerVisibility: setLayerVisibility, + moveSelectedToLayer: moveSelectedToLayer, + mergeLayer: mergeLayer, + mergeAllLayers: mergeAllLayers, + leaveContext: leaveContext, + setContext: setContext + }; + Object.entries(dr).forEach(function (_ref8) { + var _ref9 = _slicedToArray(_ref8, 2), + prop = _ref9[0], + propVal = _ref9[1]; + + canvas[prop] = propVal; }); init$3( /** * @implements {module:draw.DrawCanvasInit} */ { - pathActions: pathActions$$1, + pathActions: pathActions$1, getCurrentGroup: function getCurrentGroup() { return currentGroup; }, setCurrentGroup: function setCurrentGroup(cg) { currentGroup = cg; }, - getSelectedElements: getSelectedElements, getSVGContent: getSVGContent, undoMgr: undoMgr, @@ -17233,6 +18825,7 @@ clearSelection: clearSelection, call: call, addCommandToHistory: addCommandToHistory, + /** * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} @@ -17241,7 +18834,6 @@ call('changed', [svgcontent]); } }); - /** * Group: Document functions */ @@ -17252,51 +18844,44 @@ * @fires module:svgcanvas.SvgCanvas#event:cleared * @returns {undefined} */ + this.clear = function () { - pathActions$$1.clear(); + pathActions$1.clear(); + clearSelection(); // clear the svgcontent node - clearSelection(); + canvas.clearSvgContentElement(); // create new document - // clear the svgcontent node - canvas.clearSvgContentElement(); + canvas.current_drawing_ = new Drawing(svgcontent); // create empty first layer - // create new document - canvas.current_drawing_ = new Drawing(svgcontent); + canvas.createLayer('Layer 1'); // clear the undo stack - // create empty first layer - canvas.createLayer('Layer 1'); + canvas.undoMgr.resetUndoStack(); // reset the selector manager - // clear the undo stack - canvas.undoMgr.resetUndoStack(); + selectorManager.initGroup(); // reset the rubber band box - // reset the selector manager - selectorManager.initGroup(); - - // reset the rubber band box rubberBox = selectorManager.getRubberBandBox(); - call('cleared'); - }; + }; // Alias function - // Alias function - this.linkControlPoints = pathActions$$1.linkControlPoints; + this.linkControlPoints = pathActions$1.linkControlPoints; /** * @function module:svgcanvas.SvgCanvas#getContentElem * @returns {Element} The content DOM element */ + this.getContentElem = function () { return svgcontent; }; - /** * @function module:svgcanvas.SvgCanvas#getRootElem * @returns {SVGSVGElement} The root DOM element */ + + this.getRootElem = function () { return svgroot; }; - /** * @typedef {PlainObject} DimensionsAndZoom * @property {Float} w Width @@ -17308,93 +18893,103 @@ * @function module:svgcanvas.SvgCanvas#getResolution * @returns {DimensionsAndZoom} The current dimensions and zoom level in an object */ + + var getResolution = this.getResolution = function () { // const vb = svgcontent.getAttribute('viewBox').split(' '); // return {w:vb[2], h:vb[3], zoom: currentZoom}; - var w = svgcontent.getAttribute('width') / currentZoom; var h = svgcontent.getAttribute('height') / currentZoom; - return { w: w, h: h, zoom: currentZoom }; }; - /** * @function module:svgcanvas.SvgCanvas#getSnapToGrid * @returns {boolean} The current snap to grid setting */ + + this.getSnapToGrid = function () { return curConfig.gridSnapping; }; - /** * @function module:svgcanvas.SvgCanvas#getVersion * @returns {string} A string which describes the revision number of SvgCanvas. */ + + this.getVersion = function () { return 'svgcanvas.js ($Rev$)'; }; - /** - * Update interface strings with given values + * Update interface strings with given values. * @function module:svgcanvas.SvgCanvas#setUiStrings * @param {module:path.uiStrings} strs - Object with strings (see the [locales API]{@link module:locale.LocaleStrings} and the [tutorial]{@tutorial LocaleDocs}) * @returns {undefined} */ + + this.setUiStrings = function (strs) { Object.assign(uiStrings, strs.notification); + $$9 = jQueryPluginDBox($$9, strs.common); setUiStrings(strs); }; - /** - * Update configuration options with given values + * Update configuration options with given values. * @function module:svgcanvas.SvgCanvas#setConfig * @param {module:SVGEditor.Config} opts - Object with options * @returns {undefined} */ + + this.setConfig = function (opts) { Object.assign(curConfig, opts); }; - /** * @function module:svgcanvas.SvgCanvas#getTitle - * @param {Element} elem - * @returns {string|undefined} the current group/SVG's title contents + * @param {Element} [elem] + * @returns {string|undefined} the current group/SVG's title contents or + * `undefined` if no element is passed nd there are no selected elements. */ + + this.getTitle = function (elem) { elem = elem || selectedElements[0]; + if (!elem) { - return; + return undefined; } + elem = $$9(elem).data('gsvg') || $$9(elem).data('symbol') || elem; var childs = elem.childNodes; + for (var i = 0; i < childs.length; i++) { if (childs[i].nodeName === 'title') { return childs[i].textContent; } } + return ''; }; - /** - * Sets the group/SVG's title content + * Sets the group/SVG's title content. * @function module:svgcanvas.SvgCanvas#setGroupTitle * @param {string} val * @todo Combine this with `setDocumentTitle` * @returns {undefined} */ + + this.setGroupTitle = function (val) { var elem = selectedElements[0]; elem = $$9(elem).data('gsvg') || elem; - var ts = $$9(elem).children('title'); - var batchCmd = new BatchCommand$1('Set Label'); + var title; - var title = void 0; if (!val.length) { // Remove title element var tsNextSibling = ts.nextSibling; @@ -17403,7 +18998,9 @@ } else if (ts.length) { // Change title contents title = ts[0]; - batchCmd.addSubCommand(new ChangeElementCommand$1(title, { '#text': title.textContent })); + batchCmd.addSubCommand(new ChangeElementCommand$1(title, { + '#text': title.textContent + })); title.textContent = val; } else { // Add title element @@ -17415,27 +19012,28 @@ addCommandToHistory(batchCmd); }; - /** * @function module:svgcanvas.SvgCanvas#getDocumentTitle * @returns {string|undefined} The current document title or an empty string if not found */ + + var getDocumentTitle = this.getDocumentTitle = function () { return canvas.getTitle(svgcontent); }; - /** * Adds/updates a title element for the document with the given name. - * This is an undoable action + * This is an undoable action. * @function module:svgcanvas.SvgCanvas#setDocumentTitle * @param {string} newTitle - String with the new title * @returns {undefined} */ + + this.setDocumentTitle = function (newTitle) { var childs = svgcontent.childNodes; var docTitle = false, oldTitle = ''; - var batchCmd = new BatchCommand$1('Change Image Title'); for (var i = 0; i < childs.length; i++) { @@ -17445,10 +19043,10 @@ break; } } + if (!docTitle) { docTitle = svgdoc.createElementNS(NS.SVG, 'title'); - svgcontent.insertBefore(docTitle, svgcontent.firstChild); - // svgcontent.firstChild.before(docTitle); // Ok to replace above with this? + svgcontent.insertBefore(docTitle, svgcontent.firstChild); // svgcontent.firstChild.before(docTitle); // Ok to replace above with this? } if (newTitle.length) { @@ -17457,39 +19055,44 @@ // No title given, so element is not necessary docTitle.remove(); } - batchCmd.addSubCommand(new ChangeElementCommand$1(docTitle, { '#text': oldTitle })); + + batchCmd.addSubCommand(new ChangeElementCommand$1(docTitle, { + '#text': oldTitle + })); addCommandToHistory(batchCmd); }; - /** - * Returns the editor's namespace URL, optionally adding it to the root element + * Returns the editor's namespace URL, optionally adding it to the root element. * @function module:svgcanvas.SvgCanvas#getEditorNS * @param {boolean} [add] - Indicates whether or not to add the namespace value * @returns {string} The editor's namespace URL */ + + this.getEditorNS = function (add) { if (add) { svgcontent.setAttribute('xmlns:se', NS.SE); } + return NS.SE; }; - /** - * Changes the document's dimensions to the given size + * Changes the document's dimensions to the given size. * @function module:svgcanvas.SvgCanvas#setResolution * @param {Float|"fit"} x - Number with the width of the new dimensions in user units. - * Can also be the string "fit" to indicate "fit to content" + * Can also be the string "fit" to indicate "fit to content". * @param {Float} y - Number with the height of the new dimensions in user units. * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {boolean} Indicates if resolution change was successful. * It will fail on "fit to content" option with no content to fit to. */ + + this.setResolution = function (x, y) { var res = getResolution(); var w = res.w, h = res.h; - - var batchCmd = void 0; + var batchCmd; if (x === 'fit') { // Get bounding box @@ -17505,17 +19108,16 @@ dx.push(bbox.x * -1); dy.push(bbox.y * -1); }); - var cmd = canvas.moveSelectedElements(dx, dy, true); batchCmd.addSubCommand(cmd); clearSelection(); - x = Math.round(bbox.width); y = Math.round(bbox.height); } else { return false; } } + if (x !== w || y !== h) { if (!batchCmd) { batchCmd = new BatchCommand$1('Change Image Dimensions'); @@ -17523,23 +19125,24 @@ x = convertToNum('width', x); y = convertToNum('height', y); - svgcontent.setAttribute('width', x); svgcontent.setAttribute('height', y); - this.contentW = x; this.contentH = y; - batchCmd.addSubCommand(new ChangeElementCommand$1(svgcontent, { width: w, height: h })); - + batchCmd.addSubCommand(new ChangeElementCommand$1(svgcontent, { + width: w, + height: h + })); svgcontent.setAttribute('viewBox', [0, 0, x / currentZoom, y / currentZoom].join(' ')); - batchCmd.addSubCommand(new ChangeElementCommand$1(svgcontent, { viewBox: ['0 0', w, h].join(' ') })); - + batchCmd.addSubCommand(new ChangeElementCommand$1(svgcontent, { + viewBox: ['0 0', w, h].join(' ') + })); addCommandToHistory(batchCmd); call('changed', [svgcontent]); } + return true; }; - /** * @typedef {module:jQueryAttr.Attributes} module:svgcanvas.ElementPositionInCanvas * @property {Float} x @@ -17551,81 +19154,113 @@ * @returns {module:svgcanvas.ElementPositionInCanvas} An object with `x`, `y` values indicating the svgcontent element's * position in the editor's canvas. */ + + this.getOffset = function () { return $$9(svgcontent).attr(['x', 'y']); }; - /** * @typedef {PlainObject} module:svgcanvas.ZoomAndBBox * @property {Float} zoom * @property {module:utilities.BBoxObject} bbox */ + /** - * Sets the zoom level on the canvas-side based on the given value + * Sets the zoom level on the canvas-side based on the given value. * @function module:svgcanvas.SvgCanvas#setBBoxZoom * @param {"selection"|"canvas"|"content"|"layer"|module:SVGEditor.BBoxObjectWithFactor} val - Bounding box object to zoom to or string indicating zoom option. Note: the object value type is defined in `svg-editor.js` * @param {Integer} editorW - The editor's workarea box's width * @param {Integer} editorH - The editor's workarea box's height * @returns {module:svgcanvas.ZoomAndBBox|undefined} */ + + this.setBBoxZoom = function (val, editorW, editorH) { var spacer = 0.85; - var bb = void 0; + var bb; + var calcZoom = function calcZoom(bb) { + // eslint-disable-line no-shadow if (!bb) { return false; } + var wZoom = Math.round(editorW / bb.width * 100 * spacer) / 100; var hZoom = Math.round(editorH / bb.height * 100 * spacer) / 100; var zoom = Math.min(wZoom, hZoom); canvas.setZoom(zoom); - return { zoom: zoom, bbox: bb }; + return { + zoom: zoom, + bbox: bb + }; }; - if ((typeof val === 'undefined' ? 'undefined' : _typeof(val)) === 'object') { + if (_typeof(val) === 'object') { bb = val; + if (bb.width === 0 || bb.height === 0) { var newzoom = bb.zoom ? bb.zoom : currentZoom * bb.factor; canvas.setZoom(newzoom); - return { zoom: currentZoom, bbox: bb }; + return { + zoom: currentZoom, + bbox: bb + }; } + return calcZoom(bb); } switch (val) { case 'selection': - if (!selectedElements[0]) { - return; - } - var selectedElems = $$9.map(selectedElements, function (n) { - if (n) { - return n; + { + if (!selectedElements[0]) { + return undefined; } - }); - bb = getStrokedBBoxDefaultVisible(selectedElems); - break; + + var selectedElems = $$9.map(selectedElements, function (n) { + if (n) { + return n; + } + + return undefined; + }); + bb = getStrokedBBoxDefaultVisible(selectedElems); + break; + } + case 'canvas': - var res = getResolution(); - spacer = 0.95; - bb = { width: res.w, height: res.h, x: 0, y: 0 }; - break; + { + var res = getResolution(); + spacer = 0.95; + bb = { + width: res.w, + height: res.h, + x: 0, + y: 0 + }; + break; + } + case 'content': bb = getStrokedBBoxDefaultVisible(); break; + case 'layer': bb = getStrokedBBoxDefaultVisible(getVisibleElements(getCurrentDrawing().getCurrentLayer())); break; + default: - return; + return undefined; } + return calcZoom(bb); }; - /** * The zoom level has changed. Supplies the new zoom level as a number (not percentage). * @event module:svgcanvas.SvgCanvas#event:ext-zoomChanged * @type {Float} */ + /** * The bottom panel was updated * @event module:svgcanvas.SvgCanvas#event:ext-toolButtonStateUpdate @@ -17633,6 +19268,7 @@ * @property {boolean} nofill Indicates fill is disabled * @property {boolean} nostroke Indicates stroke is disabled */ + /** * The element selection has changed (elements were added/removed from selection) * @event module:svgcanvas.SvgCanvas#event:ext-selectedChanged @@ -17641,6 +19277,7 @@ * @property {Element|null} selectedElement The single selected element * @property {boolean} multiselected Indicates whether one or more elements were selected */ + /** * Called when part of element is in process of changing, generally on * mousemove actions like rotate, move, etc. @@ -17648,12 +19285,14 @@ * @type {PlainObject} * @property {Element[]} elems Array of transitioning elements */ + /** * One or more elements were changed * @event module:svgcanvas.SvgCanvas#event:ext-elementChanged * @type {PlainObject} * @property {Element[]} elems Array of the affected elements */ + /** * Invoked as soon as the locale is ready * @event module:svgcanvas.SvgCanvas#event:ext-langReady @@ -17662,11 +19301,13 @@ * @property {module:SVGEditor.uiStrings} uiStrings * @property {module:SVGEditor~ImportLocale} importLocale */ + /** * The language was changed. Two-letter code of the new language. * @event module:svgcanvas.SvgCanvas#event:ext-langChanged * @type {string} */ + /** * Means for an extension to add locale data. The two-letter language code. * @event module:svgcanvas.SvgCanvas#event:ext-addLangData @@ -17674,16 +19315,19 @@ * @property {string} lang * @property {module:SVGEditor~ImportLocale} importLocale */ + /** * Called when new image is created * @event module:svgcanvas.SvgCanvas#event:ext-onNewDocument * @type {undefined} */ + /** * Called when sidepanel is resized or toggled * @event module:svgcanvas.SvgCanvas#event:ext-workareaResized * @type {undefined} */ + /** * Called upon addition of the extension, or, if svgicons are set, * after the icons are ready when extension SVG icons have loaded. @@ -17692,12 +19336,14 @@ */ /** - * Sets the zoom to the given level + * Sets the zoom to the given level. * @function module:svgcanvas.SvgCanvas#setZoom * @param {Float} zoomLevel - Float indicating the zoom level to change to * @fires module:svgcanvas.SvgCanvas#event:ext-zoomChanged * @returns {undefined} */ + + this.setZoom = function (zoomLevel) { var res = getResolution(); svgcontent.setAttribute('viewBox', '0 0 ' + res.w / zoomLevel + ' ' + res.h / zoomLevel); @@ -17706,33 +19352,37 @@ if (!elem) { return; } + selectorManager.requestSelector(elem).resize(); }); - pathActions$$1.zoomChange(); - runExtensions('zoomChanged', /** @type {module:svgcanvas.SvgCanvas#event:ext-zoomChanged} */zoomLevel); + pathActions$1.zoomChange(); + runExtensions('zoomChanged', + /** @type {module:svgcanvas.SvgCanvas#event:ext-zoomChanged} */ + zoomLevel); }; - /** * @function module:svgcanvas.SvgCanvas#getMode * @returns {string} The current editor mode string */ + + this.getMode = function () { return currentMode; }; - /** - * Sets the editor's mode to the given string + * Sets the editor's mode to the given string. * @function module:svgcanvas.SvgCanvas#setMode * @param {string} name - String with the new mode to change to * @returns {undefined} */ + + this.setMode = function (name) { - pathActions$$1.clear(true); + pathActions$1.clear(true); textActions.clear(); curProperties = selectedElements[0] && selectedElements[0].nodeName === 'text' ? curText : curShape; currentMode = name; }; - /** * Group: Element Styling */ @@ -17747,12 +19397,13 @@ * @param {string} type * @returns {string|module:svgcanvas.PaintOptions|Float|module:jGraduate~Paint} The current fill/stroke option */ + + this.getColor = function (type) { return curProperties[type]; }; - /** - * Change the current stroke/fill color/gradient value + * Change the current stroke/fill color/gradient value. * @function module:svgcanvas.SvgCanvas#setColor * @param {string} type - String indicating fill or stroke * @param {string} val - The value to set the stroke attribute to @@ -17760,32 +19411,44 @@ * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + this.setColor = function (type, val, preventUndo) { curShape[type] = val; - curProperties[type + '_paint'] = { type: 'solidColor' }; + curProperties[type + '_paint'] = { + type: 'solidColor' + }; var elems = []; + /** + * + * @param {Element} e + * @returns {undefined} + */ + function addNonG(e) { if (e.nodeName !== 'g') { elems.push(e); } } + var i = selectedElements.length; + while (i--) { var elem = selectedElements[i]; + if (elem) { if (elem.tagName === 'g') { walkTree(elem, addNonG); - } else { - if (type === 'fill') { - if (elem.tagName !== 'polyline' && elem.tagName !== 'line') { - elems.push(elem); - } - } else { + } else if (type === 'fill') { + if (elem.tagName !== 'polyline' && elem.tagName !== 'line') { elems.push(elem); } + } else { + elems.push(elem); } } } + if (elems.length > 0) { if (!preventUndo) { changeSelectedAttribute(type, val, elems); @@ -17795,47 +19458,53 @@ } } }; - /** - * Apply the current gradient to selected element's fill or stroke + * Apply the current gradient to selected element's fill or stroke. * @function module:svgcanvas.SvgCanvas#setGradient * @param {"fill"|"stroke"} type - String indicating "fill" or "stroke" to apply to an element * @returns {undefined} */ + + var setGradient = this.setGradient = function (type) { if (!curProperties[type + '_paint'] || curProperties[type + '_paint'].type === 'solidColor') { return; } - var grad = canvas[type + 'Grad']; - // find out if there is a duplicate gradient already in the defs + + var grad = canvas[type + 'Grad']; // find out if there is a duplicate gradient already in the defs + var duplicateGrad = findDuplicateGradient(grad); - var defs = findDefs(); - // no duplicate found, so import gradient into defs + var defs = findDefs(); // no duplicate found, so import gradient into defs + if (!duplicateGrad) { // const origGrad = grad; - grad = defs.appendChild(svgdoc.importNode(grad, true)); - // get next id and set it on the grad + grad = defs.appendChild(svgdoc.importNode(grad, true)); // get next id and set it on the grad + grad.id = getNextId(); } else { // use existing gradient grad = duplicateGrad; } + canvas.setColor(type, 'url(#' + grad.id + ')'); }; - /** - * Check if exact gradient already exists + * Check if exact gradient already exists. * @function module:svgcanvas~findDuplicateGradient * @param {SVGGradientElement} grad - The gradient DOM element to compare to others * @returns {SVGGradientElement} The existing gradient if found, `null` if not */ + + var findDuplicateGradient = function findDuplicateGradient(grad) { var defs = findDefs(); var existingGrads = $$9(defs).find('linearGradient, radialGradient'); var i = existingGrads.length; var radAttrs = ['r', 'cx', 'cy', 'fx', 'fy']; + while (i--) { var og = existingGrads[i]; + if (grad.tagName === 'linearGradient') { if (grad.getAttribute('x1') !== og.getAttribute('x1') || grad.getAttribute('y1') !== og.getAttribute('y1') || grad.getAttribute('x2') !== og.getAttribute('x2') || grad.getAttribute('y2') !== og.getAttribute('y2')) { continue; @@ -17844,23 +19513,22 @@ var _ret = function () { var gradAttrs = $$9(grad).attr(radAttrs); var ogAttrs = $$9(og).attr(radAttrs); - var diff = false; - $$9.each(radAttrs, function (i, attr) { + $$9.each(radAttrs, function (j, attr) { if (gradAttrs[attr] !== ogAttrs[attr]) { diff = true; } }); if (diff) { - return 'continue'; + return "continue"; } }(); - if (_ret === 'continue') continue; - } + if (_ret === "continue") continue; + } // else could be a duplicate, iterate through stops + - // else could be a duplicate, iterate through stops var stops = grad.getElementsByTagNameNS(NS.SVG, 'stop'); var ostops = og.getElementsByTagNameNS(NS.SVG, 'stop'); @@ -17869,6 +19537,7 @@ } var j = stops.length; + while (j--) { var stop = stops[j]; var ostop = ostops[j]; @@ -17883,27 +19552,30 @@ } } // for each gradient in defs + return null; }; - /** - * Set a color/gradient to a fill/stroke + * Set a color/gradient to a fill/stroke. * @function module:svgcanvas.SvgCanvas#setPaint * @param {"fill"|"stroke"} type - String with "fill" or "stroke" * @param {module:jGraduate.jGraduatePaintOptions} paint - The jGraduate paint object to apply * @returns {undefined} */ + + this.setPaint = function (type, paint) { // make a copy var p = new $$9.jGraduate.Paint(paint); - this.setPaintOpacity(type, p.alpha / 100, true); + this.setPaintOpacity(type, p.alpha / 100, true); // now set the current paint object - // now set the current paint object curProperties[type + '_paint'] = p; + switch (p.type) { case 'solidColor': this.setColor(type, p.solidColor !== 'none' ? '#' + p.solidColor : 'none'); break; + case 'linearGradient': case 'radialGradient': canvas[type + 'Grad'] = p[p.type]; @@ -17911,57 +19583,70 @@ break; } }; - /** * @function module:svgcanvas.SvgCanvas#setStrokePaint * @param {module:jGraduate~Paint} paint * @returns {undefined} */ + + this.setStrokePaint = function (paint) { this.setPaint('stroke', paint); }; - /** * @function module:svgcanvas.SvgCanvas#setFillPaint * @param {module:jGraduate~Paint} paint * @returns {undefined} */ + + this.setFillPaint = function (paint) { this.setPaint('fill', paint); }; - /** * @function module:svgcanvas.SvgCanvas#getStrokeWidth * @returns {Float|string} The current stroke-width value */ + + this.getStrokeWidth = function () { return curProperties.stroke_width; }; - /** * Sets the stroke width for the current selected elements. - * When attempting to set a line's width to 0, this changes it to 1 instead + * When attempting to set a line's width to 0, this changes it to 1 instead. * @function module:svgcanvas.SvgCanvas#setStrokeWidth * @param {Float} val - A Float indicating the new stroke width value * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + this.setStrokeWidth = function (val) { if (val === 0 && ['line', 'path'].includes(currentMode)) { canvas.setStrokeWidth(1); return; } - curProperties.stroke_width = val; + curProperties.stroke_width = val; var elems = []; + /** + * + * @param {Element} e + * @returns {undefined} + */ + function addNonG(e) { if (e.nodeName !== 'g') { elems.push(e); } } + var i = selectedElements.length; + while (i--) { var elem = selectedElements[i]; + if (elem) { if (elem.tagName === 'g') { walkTree(elem, addNonG); @@ -17970,27 +19655,30 @@ } } } + if (elems.length > 0) { changeSelectedAttribute('stroke-width', val, elems); call('changed', selectedElements); } }; - /** - * Set the given stroke-related attribute the given value for selected elements + * Set the given stroke-related attribute the given value for selected elements. * @function module:svgcanvas.SvgCanvas#setStrokeAttr * @param {string} attr - String with the attribute name * @param {string|Float} val - String or number with the attribute value * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + this.setStrokeAttr = function (attr, val) { curShape[attr.replace('-', '_')] = val; var elems = []; - var i = selectedElements.length; + while (i--) { var elem = selectedElements[i]; + if (elem) { if (elem.tagName === 'g') { walkTree(elem, function (e) { @@ -18003,12 +19691,12 @@ } } } + if (elems.length > 0) { changeSelectedAttribute(attr, val, elems); call('changed', selectedElements); } }; - /** * @typedef {PlainObject} module:svgcanvas.StyleOptions * @property {string} fill @@ -18026,89 +19714,100 @@ * @function module:svgcanvas.SvgCanvas#getStyle * @returns {module:svgcanvas.StyleOptions} current style options */ + + this.getStyle = function () { return curShape; }; - /** * @function module:svgcanvas.SvgCanvas#getOpacity * @returns {Float} the current opacity */ - this.getOpacity = getOpacity; + + this.getOpacity = getOpacity; /** - * Sets the given opacity to the current selected elements + * Sets the given opacity on the current selected elements. * @function module:svgcanvas.SvgCanvas#setOpacity * @param {string} val * @returns {undefined} */ + this.setOpacity = function (val) { curShape.opacity = val; changeSelectedAttribute('opacity', val); }; - /** * @function module:svgcanvas.SvgCanvas#getFillOpacity * @returns {Float} the current fill opacity */ + + this.getFillOpacity = function () { return curShape.fill_opacity; }; - /** * @function module:svgcanvas.SvgCanvas#getStrokeOpacity * @returns {string} the current stroke opacity */ + + this.getStrokeOpacity = function () { return curShape.stroke_opacity; }; - /** - * Sets the current fill/stroke opacity + * Sets the current fill/stroke opacity. * @function module:svgcanvas.SvgCanvas#setPaintOpacity * @param {string} type - String with "fill" or "stroke" * @param {Float} val - Float with the new opacity value * @param {boolean} preventUndo - Indicates whether or not this should be an undoable action * @returns {undefined} */ + + this.setPaintOpacity = function (type, val, preventUndo) { curShape[type + '_opacity'] = val; + if (!preventUndo) { changeSelectedAttribute(type + '-opacity', val); } else { changeSelectedAttributeNoUndo(type + '-opacity', val); } }; - /** - * Gets the current fill/stroke opacity + * Gets the current fill/stroke opacity. * @function module:svgcanvas.SvgCanvas#getPaintOpacity * @param {"fill"|"stroke"} type - String with "fill" or "stroke" * @returns {Float} Fill/stroke opacity */ + + this.getPaintOpacity = function (type) { return type === 'fill' ? this.getFillOpacity() : this.getStrokeOpacity(); }; - /** - * Gets the `stdDeviation` blur value of the given element + * Gets the `stdDeviation` blur value of the given element. * @function module:svgcanvas.SvgCanvas#getBlur * @param {Element} elem - The element to check the blur value for * @returns {string} stdDeviation blur attribute value */ + + this.getBlur = function (elem) { - var val = 0; - // const elem = selectedElements[0]; + var val = 0; // const elem = selectedElements[0]; if (elem) { var filterUrl = elem.getAttribute('filter'); + if (filterUrl) { var blur = getElem(elem.id + '_blur'); + if (blur) { val = blur.firstChild.getAttribute('stdDeviation'); } } } + return val; }; @@ -18116,18 +19815,19 @@ var curCommand = null; var filter = null; var filterHidden = false; - /** - * Sets the `stdDeviation` blur value on the selected element without being undoable + * Sets the `stdDeviation` blur value on the selected element without being undoable. * @function module:svgcanvas.SvgCanvas#setBlurNoUndo * @param {Float} val - The new `stdDeviation` value * @returns {undefined} */ + canvas.setBlurNoUndo = function (val) { if (!filter) { canvas.setBlur(val); return; } + if (val === 0) { // Don't change the StdDev, as that will hide the element. // Instead, just remove the value for "filter" @@ -18135,18 +19835,26 @@ filterHidden = true; } else { var elem = selectedElements[0]; + if (filterHidden) { changeSelectedAttributeNoUndo('filter', 'url(#' + elem.id + '_blur)'); } + if (isWebkit()) { - console.log('e', elem); + // console.log('e', elem); // eslint-disable-line no-console elem.removeAttribute('filter'); elem.setAttribute('filter', 'url(#' + elem.id + '_blur)'); } + changeSelectedAttributeNoUndo('stdDeviation', val, [filter.firstChild]); canvas.setBlurOffsets(filter, val); } }; + /** + * + * @returns {undefined} + */ + function finishChange() { var bCmd = canvas.undoMgr.finishUndoableChange(); @@ -18155,84 +19863,81 @@ curCommand = null; filter = null; } - /** * Sets the `x`, `y`, `width`, `height` values of the filter element in order to - * make the blur not be clipped. Removes them if not neeeded + * make the blur not be clipped. Removes them if not neeeded. * @function module:svgcanvas.SvgCanvas#setBlurOffsets - * @param {Element} filter - The filter DOM element to update + * @param {Element} filterElem - The filter DOM element to update * @param {Float} stdDev - The standard deviation value on which to base the offset size * @returns {undefined} */ - canvas.setBlurOffsets = function (filter, stdDev) { + + + canvas.setBlurOffsets = function (filterElem, stdDev) { if (stdDev > 3) { // TODO: Create algorithm here where size is based on expected blur - assignAttributes(filter, { + assignAttributes(filterElem, { x: '-50%', y: '-50%', width: '200%', height: '200%' - }, 100); - } else { - // Removing these attributes hides text in Chrome (see Issue 579) - if (!isWebkit()) { - filter.removeAttribute('x'); - filter.removeAttribute('y'); - filter.removeAttribute('width'); - filter.removeAttribute('height'); - } + }, 100); // Removing these attributes hides text in Chrome (see Issue 579) + } else if (!isWebkit()) { + filterElem.removeAttribute('x'); + filterElem.removeAttribute('y'); + filterElem.removeAttribute('width'); + filterElem.removeAttribute('height'); } }; - /** - * Adds/updates the blur filter to the selected element + * Adds/updates the blur filter to the selected element. * @function module:svgcanvas.SvgCanvas#setBlur * @param {Float} val - Float with the new `stdDeviation` blur value * @param {boolean} complete - Whether or not the action should be completed (to add to the undo manager) * @returns {undefined} */ + + canvas.setBlur = function (val, complete) { if (curCommand) { finishChange(); return; - } + } // Looks for associated blur, creates one if not found + - // Looks for associated blur, creates one if not found var elem = selectedElements[0]; var elemId = elem.id; filter = getElem(elemId + '_blur'); - val -= 0; + var batchCmd = new BatchCommand$1(); // Blur found! - var batchCmd = new BatchCommand$1(); - - // Blur found! if (filter) { if (val === 0) { filter = null; } } else { // Not found, so create - var newblur = addSVGElementFromJson({ element: 'feGaussianBlur', + var newblur = addSVGElementFromJson({ + element: 'feGaussianBlur', attr: { in: 'SourceGraphic', stdDeviation: val } }); - - filter = addSVGElementFromJson({ element: 'filter', + filter = addSVGElementFromJson({ + element: 'filter', attr: { id: elemId + '_blur' } }); - filter.append(newblur); findDefs().append(filter); - batchCmd.addSubCommand(new InsertElementCommand$1(filter)); } - var changes = { filter: elem.getAttribute('filter') }; + var changes = { + filter: elem.getAttribute('filter') + }; if (val === 0) { elem.removeAttribute('filter'); @@ -18243,229 +19948,246 @@ changeSelectedAttribute('filter', 'url(#' + elemId + '_blur)'); batchCmd.addSubCommand(new ChangeElementCommand$1(elem, changes)); canvas.setBlurOffsets(filter, val); - curCommand = batchCmd; canvas.undoMgr.beginUndoableChange('stdDeviation', [filter ? filter.firstChild : null]); + if (complete) { canvas.setBlurNoUndo(val); finishChange(); } }; })(); - /** - * Check whether selected element is bold or not + * Check whether selected element is bold or not. * @function module:svgcanvas.SvgCanvas#getBold * @returns {boolean} Indicates whether or not element is bold */ + + this.getBold = function () { // should only have one element selected var selected = selectedElements[0]; - if (selected != null && selected.tagName === 'text' && selectedElements[1] == null) { + + if (!isNullish(selected) && selected.tagName === 'text' && isNullish(selectedElements[1])) { return selected.getAttribute('font-weight') === 'bold'; } + return false; }; - /** - * Make the selected element bold or normal + * Make the selected element bold or normal. * @function module:svgcanvas.SvgCanvas#setBold * @param {boolean} b - Indicates bold (`true`) or normal (`false`) * @returns {undefined} */ + + this.setBold = function (b) { var selected = selectedElements[0]; - if (selected != null && selected.tagName === 'text' && selectedElements[1] == null) { + + if (!isNullish(selected) && selected.tagName === 'text' && isNullish(selectedElements[1])) { changeSelectedAttribute('font-weight', b ? 'bold' : 'normal'); } + if (!selectedElements[0].textContent) { textActions.setCursor(); } }; - /** - * Check whether selected element is italic or not + * Check whether selected element is in italics or not. * @function module:svgcanvas.SvgCanvas#getItalic * @returns {boolean} Indicates whether or not element is italic */ + + this.getItalic = function () { var selected = selectedElements[0]; - if (selected != null && selected.tagName === 'text' && selectedElements[1] == null) { + + if (!isNullish(selected) && selected.tagName === 'text' && isNullish(selectedElements[1])) { return selected.getAttribute('font-style') === 'italic'; } + return false; }; - /** - * Make the selected element italic or normal + * Make the selected element italic or normal. * @function module:svgcanvas.SvgCanvas#setItalic - * @param {boolean} b - Indicates italic (`true`) or normal (`false`) + * @param {boolean} i - Indicates italic (`true`) or normal (`false`) * @returns {undefined} */ + + this.setItalic = function (i) { var selected = selectedElements[0]; - if (selected != null && selected.tagName === 'text' && selectedElements[1] == null) { + + if (!isNullish(selected) && selected.tagName === 'text' && isNullish(selectedElements[1])) { changeSelectedAttribute('font-style', i ? 'italic' : 'normal'); } + if (!selectedElements[0].textContent) { textActions.setCursor(); } }; - /** * @function module:svgcanvas.SvgCanvas#getFontFamily * @returns {string} The current font family */ + + this.getFontFamily = function () { return curText.font_family; }; - /** - * Set the new font family + * Set the new font family. * @function module:svgcanvas.SvgCanvas#setFontFamily * @param {string} val - String with the new font family * @returns {undefined} */ + + this.setFontFamily = function (val) { curText.font_family = val; changeSelectedAttribute('font-family', val); + if (selectedElements[0] && !selectedElements[0].textContent) { textActions.setCursor(); } }; - /** - * Set the new font color + * Set the new font color. * @function module:svgcanvas.SvgCanvas#setFontColor * @param {string} val - String with the new font color * @returns {undefined} */ + + this.setFontColor = function (val) { curText.fill = val; changeSelectedAttribute('fill', val); }; - /** * @function module:svgcanvas.SvgCanvas#getFontColor * @returns {string} The current font color */ + + this.getFontColor = function () { return curText.fill; }; - /** * @function module:svgcanvas.SvgCanvas#getFontSize * @returns {Float} The current font size */ + + this.getFontSize = function () { return curText.font_size; }; - /** - * Applies the given font size to the selected element + * Applies the given font size to the selected element. * @function module:svgcanvas.SvgCanvas#setFontSize * @param {Float} val - Float with the new font size * @returns {undefined} */ + + this.setFontSize = function (val) { curText.font_size = val; changeSelectedAttribute('font-size', val); + if (!selectedElements[0].textContent) { textActions.setCursor(); } }; - /** * @function module:svgcanvas.SvgCanvas#getText * @returns {string} The current text (`textContent`) of the selected element */ + + this.getText = function () { var selected = selectedElements[0]; - if (selected == null) { + + if (isNullish(selected)) { return ''; } + return selected.textContent; }; - /** - * Updates the text element with the given string + * Updates the text element with the given string. * @function module:svgcanvas.SvgCanvas#setTextContent * @param {string} val - String with the new text * @returns {undefined} */ + + this.setTextContent = function (val) { changeSelectedAttribute('#text', val); textActions.init(val); textActions.setCursor(); }; - /** * Sets the new image URL for the selected image element. Updates its size if - * a new URL is given + * a new URL is given. * @function module:svgcanvas.SvgCanvas#setImageURL * @param {string} val - String with the image URL/path * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + this.setImageURL = function (val) { var elem = selectedElements[0]; + if (!elem) { return; } var attrs = $$9(elem).attr(['width', 'height']); var setsize = !attrs.width || !attrs.height; + var curHref = getHref(elem); // Do nothing if no URL change or size change - var curHref = getHref(elem); - - // Do nothing if no URL change or size change - if (curHref !== val) { - setsize = true; - } else if (!setsize) { + if (curHref === val && !setsize) { return; } var batchCmd = new BatchCommand$1('Change Image URL'); - setHref(elem, val); batchCmd.addSubCommand(new ChangeElementCommand$1(elem, { '#href': curHref })); - - if (setsize) { - $$9(new Image()).load(function () { - var changes = $$9(elem).attr(['width', 'height']); - - $$9(elem).attr({ - width: this.width, - height: this.height - }); - - selectorManager.requestSelector(elem).resize(); - - batchCmd.addSubCommand(new ChangeElementCommand$1(elem, changes)); - addCommandToHistory(batchCmd); - call('changed', [elem]); - }).attr('src', val); - } else { + $$9(new Image()).load(function () { + var changes = $$9(elem).attr(['width', 'height']); + $$9(elem).attr({ + width: this.width, + height: this.height + }); + selectorManager.requestSelector(elem).resize(); + batchCmd.addSubCommand(new ChangeElementCommand$1(elem, changes)); addCommandToHistory(batchCmd); - } + call('changed', [elem]); + }).attr('src', val); }; - /** * Sets the new link URL for the selected anchor element. * @function module:svgcanvas.SvgCanvas#setLinkURL * @param {string} val - String with the link URL/path * @returns {undefined} */ + + this.setLinkURL = function (val) { var elem = selectedElements[0]; + if (!elem) { return; } + if (elem.tagName !== 'a') { // See if parent is an anchor var parentsA = $$9(elem).parents('a'); + if (parentsA.length) { elem = parentsA[0]; } else { @@ -18480,56 +20202,60 @@ } var batchCmd = new BatchCommand$1('Change Link URL'); - setHref(elem, val); batchCmd.addSubCommand(new ChangeElementCommand$1(elem, { '#href': curHref })); - addCommandToHistory(batchCmd); }; - /** - * Sets the `rx` and `ry` values to the selected `rect` element to change its corner radius + * Sets the `rx` and `ry` values to the selected `rect` element + * to change its corner radius. * @function module:svgcanvas.SvgCanvas#setRectRadius * @param {string|Float} val - The new radius * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + this.setRectRadius = function (val) { var selected = selectedElements[0]; - if (selected != null && selected.tagName === 'rect') { + + if (!isNullish(selected) && selected.tagName === 'rect') { var r = selected.getAttribute('rx'); + if (r !== String(val)) { selected.setAttribute('rx', val); selected.setAttribute('ry', val); - addCommandToHistory(new ChangeElementCommand$1(selected, { rx: r, ry: r }, 'Radius')); + addCommandToHistory(new ChangeElementCommand$1(selected, { + rx: r, + ry: r + }, 'Radius')); call('changed', [selected]); } } }; - /** - * Wraps the selected element(s) in an anchor element or converts group to one + * Wraps the selected element(s) in an anchor element or converts group to one. * @function module:svgcanvas.SvgCanvas#makeHyperlink * @param {string} url * @returns {undefined} */ - this.makeHyperlink = function (url) { - canvas.groupSelectedElements('a', url); - // TODO: If element is a single "g", convert to "a" + + this.makeHyperlink = function (url) { + canvas.groupSelectedElements('a', url); // TODO: If element is a single "g", convert to "a" // if (selectedElements.length > 1 && selectedElements[1]) { }; - /** * @function module:svgcanvas.SvgCanvas#removeHyperlink * @returns {undefined} */ + + this.removeHyperlink = function () { canvas.ungroupSelectedElement(); }; - /** * Group: Element manipulation */ @@ -18540,12 +20266,13 @@ * @param {Integer} newType - New segment type. See {@link https://www.w3.org/TR/SVG/paths.html#InterfaceSVGPathSeg} for list * @returns {undefined} */ - this.setSegType = function (newType) { - pathActions$$1.setSegType(newType); - }; + + this.setSegType = function (newType) { + pathActions$1.setSegType(newType); + }; /** - * Convert selected element to a path, or get the BBox of an element-as-path + * Convert selected element to a path, or get the BBox of an element-as-path. * @function module:svgcanvas.SvgCanvas#convertToPath * @todo (codedread): Remove the getBBox argument and split this function into two. * @param {Element} elem - The DOM element to be converted @@ -18553,21 +20280,25 @@ * @returns {undefined|DOMRect|false|SVGPathElement|null} If the getBBox flag is true, the resulting path's bounding box object. * Otherwise the resulting path element is returned. */ - this.convertToPath = function (elem, getBBox$$1) { - if (elem == null) { + + + this.convertToPath = function (elem, getBBox) { + if (isNullish(elem)) { var elems = selectedElements; - $$9.each(elems, function (i, elem) { - if (elem) { - canvas.convertToPath(elem); + $$9.each(elems, function (i, el) { + if (el) { + canvas.convertToPath(el); } }); - return; + return undefined; } - if (getBBox$$1) { - return getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions$$1); - } - // TODO: Why is this applying attributes from curShape, then inside utilities.convertToPath it's pulling addition attributes from elem? + + if (getBBox) { + return getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions$1); + } // TODO: Why is this applying attributes from curShape, then inside utilities.convertToPath it's pulling addition attributes from elem? // TODO: If convertToPath is called with one elem, curShape and elem are probably the same; but calling with multiple is a bug or cool feature. + + var attrs = { fill: curShape.fill, 'fill-opacity': curShape.fill_opacity, @@ -18580,9 +20311,8 @@ opacity: curShape.opacity, visibility: 'hidden' }; - return convertToPath(elem, attrs, addSVGElementFromJson, pathActions$$1, clearSelection, addToSelection, history, addCommandToHistory); + return convertToPath(elem, attrs, addSVGElementFromJson, pathActions$1, clearSelection, addToSelection, hstry, addCommandToHistory); }; - /** * This function makes the changes to the elements. It does not add the change * to the history stack. @@ -18591,48 +20321,51 @@ * @param {Element[]} elems - The DOM elements to apply the change to * @returns {undefined} */ + + var changeSelectedAttributeNoUndo = function changeSelectedAttributeNoUndo(attr, newValue, elems) { if (currentMode === 'pathedit') { // Editing node - pathActions$$1.moveNode(attr, newValue); + pathActions$1.moveNode(attr, newValue); } + elems = elems || selectedElements; var i = elems.length; - var noXYElems = ['g', 'polyline', 'path']; - var goodGAttrs = ['transform', 'opacity', 'filter']; + var noXYElems = ['g', 'polyline', 'path']; // const goodGAttrs = ['transform', 'opacity', 'filter']; var _loop = function _loop() { var elem = elems[i]; - if (elem == null) { - return 'continue'; - } - // Set x,y vals on elements that don't have them + if (isNullish(elem)) { + return "continue"; + } // Set x,y vals on elements that don't have them + + if ((attr === 'x' || attr === 'y') && noXYElems.includes(elem.tagName)) { var bbox = getStrokedBBoxDefaultVisible([elem]); var diffX = attr === 'x' ? newValue - bbox.x : 0; var diffY = attr === 'y' ? newValue - bbox.y : 0; canvas.moveSelectedElements(diffX * currentZoom, diffY * currentZoom, true); - return 'continue'; - } + return "continue"; + } // only allow the transform/opacity/filter attribute to change on <g> elements, slightly hacky + // TODO: FIXME: Missing statement body + // if (elem.tagName === 'g' && goodGAttrs.includes(attr)) {} + - // only allow the transform/opacity/filter attribute to change on <g> elements, slightly hacky - // TODO: FIXME: This doesn't seem right. Where's the body of this if statement? - if (elem.tagName === 'g' && goodGAttrs.includes(attr)) ; var oldval = attr === '#text' ? elem.textContent : elem.getAttribute(attr); - if (oldval == null) { + + if (isNullish(oldval)) { oldval = ''; } + if (oldval !== String(newValue)) { if (attr === '#text') { // const oldW = utilsGetBBox(elem).width; - elem.textContent = newValue; + elem.textContent = newValue; // FF bug occurs on on rotated elements - // FF bug occurs on on rotated elements if (/rotate/.test(elem.getAttribute('transform'))) { elem = ffClone(elem); - } - // Hoped to solve the issue of moving text with text-anchor="start", + } // Hoped to solve the issue of moving text with text-anchor="start", // but this doesn't actually fix it. Hopefully on the right track, though. -Fyrd // const box = getBBox(elem), left = box.x, top = box.y, {width, height} = box, // dx = width - oldW, dy = 0; @@ -18646,35 +20379,36 @@ // elem.setAttribute('x', elem.getAttribute('x') - dx); // elem.setAttribute('y', elem.getAttribute('y') - dy); // } + } else if (attr === '#href') { setHref(elem, newValue); } else { elem.setAttribute(attr, newValue); - } - - // Go into "select" mode for text changes + } // Go into "select" mode for text changes // NOTE: Important that this happens AFTER elem.setAttribute() or else attributes like // font-size can get reset to their old value, ultimately by svgEditor.updateContextPanel(), // after calling textActions.toSelectMode() below + + if (currentMode === 'textedit' && attr !== '#text' && elem.textContent.length) { textActions.toSelectMode(elem); - } - - // if (i === 0) { + } // if (i === 0) { // selectedBBoxes[0] = utilsGetBBox(elem); // } - // Use the Firefox ffClone hack for text elements with gradients or // where other text attributes are changed. + + if (isGecko() && elem.nodeName === 'text' && /rotate/.test(elem.getAttribute('transform'))) { if (String(newValue).startsWith('url') || ['font-size', 'font-family', 'x', 'y'].includes(attr) && elem.textContent) { elem = ffClone(elem); } - } - // Timeout needed for Opera & Firefox + } // Timeout needed for Opera & Firefox // codedread: it is now possible for this function to be called with elements // that are not in the selectedElements array, we need to only request a // selector if the element is in that array + + if (selectedElements.includes(elem)) { setTimeout(function () { // Due to element replacement, this element may no longer @@ -18682,21 +20416,25 @@ if (!elem.parentNode) { return; } + selectorManager.requestSelector(elem).resize(); }, 0); - } - // if this element was rotated, and we changed the position of this element + } // if this element was rotated, and we changed the position of this element // we need to update the rotational transform attribute + + var angle = getRotationAngle(elem); + if (angle !== 0 && attr !== 'transform') { var tlist = getTransformList(elem); var n = tlist.numberOfItems; + while (n--) { var xform = tlist.getItem(n); + if (xform.type === 4) { // remove old rotate tlist.removeItem(n); - var box = getBBox(elem); var center = transformPoint(box.x + box.width / 2, box.y + box.height / 2, transformListToTransform(tlist).matrix); var cx = center.x, @@ -18709,15 +20447,16 @@ } } } // if oldValue != newValue + }; while (i--) { var _ret2 = _loop(); - if (_ret2 === 'continue') continue; + if (_ret2 === "continue") continue; } // for each elem - }; + }; /** * Change the given/selected element and add the original value to the history stack. * If you want to change all `selectedElements`, ignore the `elems` argument. @@ -18725,30 +20464,32 @@ * subset to this function in the `elems` argument. * @function module:svgcanvas.SvgCanvas#changeSelectedAttribute * @param {string} attr - String with the attribute name - * @param {string|Float} newValue - String or number with the new attribute value + * @param {string|Float} val - String or number with the new attribute value * @param {Element[]} elems - The DOM elements to apply the change to * @returns {undefined} */ + + var changeSelectedAttribute = this.changeSelectedAttribute = function (attr, val, elems) { elems = elems || selectedElements; - canvas.undoMgr.beginUndoableChange(attr, elems); - // const i = elems.length; + canvas.undoMgr.beginUndoableChange(attr, elems); // const i = elems.length; changeSelectedAttributeNoUndo(attr, val, elems); - var batchCmd = canvas.undoMgr.finishUndoableChange(); + if (!batchCmd.isEmpty()) { addCommandToHistory(batchCmd); } }; - /** * Removes all selected elements from the DOM and adds the change to the - * history stack + * history stack. * @function module:svgcanvas.SvgCanvas#deleteSelectedElements * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + this.deleteSelectedElements = function () { var batchCmd = new BatchCommand$1('Delete Elements'); var len = selectedElements.length; @@ -18756,20 +20497,18 @@ for (var i = 0; i < len; ++i) { var selected = selectedElements[i]; - if (selected == null) { + + if (isNullish(selected)) { break; } var parent = selected.parentNode; - var t = selected; + var t = selected; // this will unselect the element and remove the selectedOutline - // this will unselect the element and remove the selectedOutline - selectorManager.releaseSelector(t); + selectorManager.releaseSelector(t); // Remove the path if present. - // Remove the path if present. - removePath_(t.id); + removePath_(t.id); // Get the parent if it's a single-child anchor - // Get the parent if it's a single-child anchor if (parent.tagName === 'a' && parent.childNodes.length === 1) { t = parent; parent = parent.parentNode; @@ -18777,44 +20516,46 @@ var _t = t, nextSibling = _t.nextSibling; - - var _elem2 = parent.removeChild(t); + var elem = parent.removeChild(t); selectedCopy.push(selected); // for the copy - batchCmd.addSubCommand(new RemoveElementCommand$1(_elem2, nextSibling, parent)); + + batchCmd.addSubCommand(new RemoveElementCommand$1(elem, nextSibling, parent)); } + selectedElements = []; if (!batchCmd.isEmpty()) { addCommandToHistory(batchCmd); } + call('changed', selectedCopy); clearSelection(); }; - /** * Removes all selected elements from the DOM and adds the change to the - * history stack. Remembers removed elements on the clipboard + * history stack. Remembers removed elements on the clipboard. * @function module:svgcanvas.SvgCanvas#cutSelectedElements * @returns {undefined} */ + + this.cutSelectedElements = function () { canvas.copySelectedElements(); canvas.deleteSelectedElements(); }; - /** - * Remembers the current selected elements on the clipboard + * Remembers the current selected elements on the clipboard. * @function module:svgcanvas.SvgCanvas#copySelectedElements * @returns {undefined} */ + + this.copySelectedElements = function () { localStorage.setItem('svgedit_clipboard', JSON.stringify(selectedElements.map(function (x) { return getJsonFromSvgElement(x); }))); - $$9('#cmenu_canvas').enableContextMenuItems('#paste,#paste_in_place'); }; - /** * @function module:svgcanvas.SvgCanvas#pasteElements * @param {"in_place"|"point"|undefined} type @@ -18824,35 +20565,46 @@ * @fires module:svgcanvas.SvgCanvas#event:ext-IDsUpdated * @returns {undefined} */ + + this.pasteElements = function (type, x, y) { var clipb = JSON.parse(localStorage.getItem('svgedit_clipboard')); var len = clipb.length; + if (!len) { return; } var pasted = []; - var batchCmd = new BatchCommand$1('Paste elements'); - // const drawing = getCurrentDrawing(); + var batchCmd = new BatchCommand$1('Paste elements'); // const drawing = getCurrentDrawing(); + /** * @typedef {PlainObject.<string, string>} module:svgcanvas.ChangedIDs */ + /** * @type {module:svgcanvas.ChangedIDs} */ - var changedIDs = {}; - // Recursively replace IDs and record the changes + var changedIDs = {}; // Recursively replace IDs and record the changes + + /** + * + * @param {module:svgcanvas.SVGAsJSON} elem + * @returns {undefined} + */ + function checkIDs(elem) { if (elem.attr && elem.attr.id) { changedIDs[elem.attr.id] = getNextId(); elem.attr.id = changedIDs[elem.attr.id]; } + if (elem.children) elem.children.forEach(checkIDs); } - clipb.forEach(checkIDs); - // Give extensions like the connector extension a chance to reflect new IDs and remove invalid elements + clipb.forEach(checkIDs); // Give extensions like the connector extension a chance to reflect new IDs and remove invalid elements + /** * Triggered when `pasteElements` is called from a paste action (context menu or key) * @event module:svgcanvas.SvgCanvas#event:ext-IDsUpdated @@ -18860,37 +20612,38 @@ * @property {module:svgcanvas.SVGAsJSON[]} elems * @property {module:svgcanvas.ChangedIDs} changes Maps past ID (on attribute) to current ID */ + runExtensions('IDsUpdated', /** @type {module:svgcanvas.SvgCanvas#event:ext-IDsUpdated} */ - { elems: clipb, changes: changedIDs }, true).forEach(function (extChanges) { + { + elems: clipb, + changes: changedIDs + }, true).forEach(function (extChanges) { if (!extChanges || !('remove' in extChanges)) return; - extChanges.remove.forEach(function (removeID) { clipb = clipb.filter(function (clipBoardItem) { return clipBoardItem.attr.id !== removeID; }); }); - }); + }); // Move elements to lastClickPoint - // Move elements to lastClickPoint while (len--) { - var _elem3 = clipb[len]; - if (!_elem3) { + var elem = clipb[len]; + + if (!elem) { continue; } - var copy = addSVGElementFromJson(_elem3); + var copy = addSVGElementFromJson(elem); pasted.push(copy); batchCmd.addSubCommand(new InsertElementCommand$1(copy)); - restoreRefElems(copy); } selectOnly(pasted); if (type !== 'in_place') { - var ctrX = void 0, - ctrY = void 0; + var ctrX, ctrY; if (!type) { ctrX = lastClickPoint.x; @@ -18905,12 +20658,10 @@ cy = ctrY - (bbox.y + bbox.height / 2), dx = [], dy = []; - $$9.each(pasted, function (i, item) { dx.push(cx); dy.push(cy); }); - var cmd = canvas.moveSelectedElements(dx, dy, false); if (cmd) batchCmd.addSubCommand(cmd); } @@ -18918,20 +20669,22 @@ addCommandToHistory(batchCmd); call('changed', pasted); }; - /** - * Wraps all the selected elements in a group (`g`) element + * Wraps all the selected elements in a group (`g`) element. * @function module:svgcanvas.SvgCanvas#groupSelectedElements * @param {"a"|"g"} [type="g"] - type of element to group into, defaults to `<g>` * @param {string} [urlArg] * @returns {undefined} */ + + this.groupSelectedElements = function (type, urlArg) { if (!type) { type = 'g'; } + var cmdStr = ''; - var url = void 0; + var url; switch (type) { case 'a': @@ -18939,7 +20692,9 @@ cmdStr = 'Make hyperlink'; url = urlArg || ''; break; - }default: + } + + default: { type = 'g'; cmdStr = 'Group Elements'; @@ -18947,64 +20702,64 @@ } } - var batchCmd = new BatchCommand$1(cmdStr); + var batchCmd = new BatchCommand$1(cmdStr); // create and insert the group element - // create and insert the group element var g = addSVGElementFromJson({ element: type, attr: { id: getNextId() } }); + if (type === 'a') { setHref(g, url); } - batchCmd.addSubCommand(new InsertElementCommand$1(g)); - // now move all children into the group + batchCmd.addSubCommand(new InsertElementCommand$1(g)); // now move all children into the group + var i = selectedElements.length; + while (i--) { - var _elem4 = selectedElements[i]; - if (_elem4 == null) { + var elem = selectedElements[i]; + + if (isNullish(elem)) { continue; } - if (_elem4.parentNode.tagName === 'a' && _elem4.parentNode.childNodes.length === 1) { - _elem4 = _elem4.parentNode; + if (elem.parentNode.tagName === 'a' && elem.parentNode.childNodes.length === 1) { + elem = elem.parentNode; } - var oldNextSibling = _elem4.nextSibling; - var oldParent = _elem4.parentNode; - g.append(_elem4); - batchCmd.addSubCommand(new MoveElementCommand$1(_elem4, oldNextSibling, oldParent)); + var oldNextSibling = elem.nextSibling; + var oldParent = elem.parentNode; + g.append(elem); + batchCmd.addSubCommand(new MoveElementCommand$1(elem, oldNextSibling, oldParent)); } + if (!batchCmd.isEmpty()) { addCommandToHistory(batchCmd); - } + } // update selection + - // update selection selectOnly([g], true); }; - /** * Pushes all appropriate parent group properties down to its children, then - * removes them from the group + * removes them from the group. * @function module:svgcanvas.SvgCanvas#pushGroupProperties * @param {SVGAElement|SVGGElement} g * @param {boolean} undoable - * @returns {undefined} + * @returns {BatchCommand|undefined} */ + + var pushGroupProperties = this.pushGroupProperties = function (g, undoable) { var children = g.childNodes; var len = children.length; var xform = g.getAttribute('transform'); - var glist = getTransformList(g); var m = transformListToTransform(glist).matrix; - - var batchCmd = new BatchCommand$1('Push group properties'); - - // TODO: get all fill/stroke properties from the group that we are about to destroy + var batchCmd = new BatchCommand$1('Push group properties'); // TODO: get all fill/stroke properties from the group that we are about to destroy // "fill", "fill-opacity", "fill-rule", "stroke", "stroke-dasharray", "stroke-dashoffset", // "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", // "stroke-width" @@ -19012,40 +20767,39 @@ // then set the child's attribute var gangle = getRotationAngle(g); - var gattrs = $$9(g).attr(['filter', 'opacity']); - var gfilter = void 0, - gblur = void 0, - changes = void 0; + var gfilter, gblur, changes; var drawing = getCurrentDrawing(); for (var i = 0; i < len; i++) { - var _elem5 = children[i]; + var elem = children[i]; - if (_elem5.nodeType !== 1) { + if (elem.nodeType !== 1) { continue; } if (gattrs.opacity !== null && gattrs.opacity !== 1) { // const c_opac = elem.getAttribute('opacity') || 1; - var newOpac = Math.round((_elem5.getAttribute('opacity') || 1) * gattrs.opacity * 100) / 100; - changeSelectedAttribute('opacity', newOpac, [_elem5]); + var newOpac = Math.round((elem.getAttribute('opacity') || 1) * gattrs.opacity * 100) / 100; + changeSelectedAttribute('opacity', newOpac, [elem]); } if (gattrs.filter) { - var cblur = this.getBlur(_elem5); + var cblur = this.getBlur(elem); var origCblur = cblur; + if (!gblur) { gblur = this.getBlur(g); } + if (cblur) { // Is this formula correct? cblur = Number(gblur) + Number(cblur); } else if (cblur === 0) { cblur = gblur; - } + } // If child has no current filter, get group's filter or clone it. + - // If child has no current filter, get group's filter or clone it. if (!origCblur) { // Set group's filter to use first child's ID if (!gfilter) { @@ -19056,35 +20810,33 @@ findDefs().append(gfilter); } } else { - gfilter = getRefElem(_elem5.getAttribute('filter')); - } + gfilter = getRefElem(elem.getAttribute('filter')); + } // Change this in future for different filters + - // Change this in future for different filters var suffix = gfilter.firstChild.tagName === 'feGaussianBlur' ? 'blur' : 'filter'; - gfilter.id = _elem5.id + '_' + suffix; - changeSelectedAttribute('filter', 'url(#' + gfilter.id + ')', [_elem5]); + gfilter.id = elem.id + '_' + suffix; + changeSelectedAttribute('filter', 'url(#' + gfilter.id + ')', [elem]); // Update blur value - // Update blur value if (cblur) { changeSelectedAttribute('stdDeviation', cblur, [gfilter.firstChild]); canvas.setBlurOffsets(gfilter, cblur); } } - var chtlist = getTransformList(_elem5); + var chtlist = getTransformList(elem); // Don't process gradient transforms - // Don't process gradient transforms - if (_elem5.tagName.includes('Gradient')) { + if (elem.tagName.includes('Gradient')) { chtlist = null; - } + } // Hopefully not a problem to add this. Necessary for elements like <desc/> + - // Hopefully not a problem to add this. Necessary for elements like <desc/> if (!chtlist) { continue; - } + } // Apparently <defs> can get get a transformlist, but we don't want it to have one! - // Apparently <defs> can get get a transformlist, but we don't want it to have one! - if (_elem5.tagName === 'defs') { + + if (elem.tagName === 'defs') { continue; } @@ -19099,35 +20851,29 @@ // sum of the group and child's rotation angles // - [Tr] is the equivalent translation that this child // undergoes if the group wasn't there - // [Tr] = [Rg] [Rc] [Rc2_inv] - // get group's rotation matrix (Rg) - var rgm = glist.getItem(0).matrix; + var rgm = glist.getItem(0).matrix; // get child's rotation matrix (Rc) - // get child's rotation matrix (Rc) var rcm = svgroot.createSVGMatrix(); - var cangle = getRotationAngle(_elem5); + var cangle = getRotationAngle(elem); + if (cangle) { rcm = chtlist.getItem(0).matrix; - } + } // get child's old center of rotation - // get child's old center of rotation - var cbox = getBBox(_elem5); + + var cbox = getBBox(elem); var ceqm = transformListToTransform(chtlist).matrix; - var coldc = transformPoint(cbox.x + cbox.width / 2, cbox.y + cbox.height / 2, ceqm); + var coldc = transformPoint(cbox.x + cbox.width / 2, cbox.y + cbox.height / 2, ceqm); // sum group and child's angles - // sum group and child's angles - var sangle = gangle + cangle; + var sangle = gangle + cangle; // get child's rotation at the old center (Rc2_inv) - // get child's rotation at the old center (Rc2_inv) var r2 = svgroot.createSVGTransform(); - r2.setRotate(sangle, coldc.x, coldc.y); + r2.setRotate(sangle, coldc.x, coldc.y); // calculate equivalent translate - // calculate equivalent translate - var trm = matrixMultiply(rgm, rcm, r2.matrix.inverse()); + var trm = matrixMultiply(rgm, rcm, r2.matrix.inverse()); // set up tlist - // set up tlist if (cangle) { chtlist.removeItem(0); } @@ -19143,6 +20889,7 @@ if (trm.e || trm.f) { var tr = svgroot.createSVGTransform(); tr.setTranslate(trm.e, trm.f); + if (chtlist.numberOfItems) { chtlist.insertItemBefore(tr, 0); } else { @@ -19153,28 +20900,28 @@ // more complicated than just a rotate // transfer the group's transform down to each child and then // call recalculateDimensions() - var oldxform = _elem5.getAttribute('transform'); + var oldxform = elem.getAttribute('transform'); changes = {}; changes.transform = oldxform || ''; - - var newxform = svgroot.createSVGTransform(); - - // [ gm ] [ chm ] = [ chm ] [ gm' ] + var newxform = svgroot.createSVGTransform(); // [ gm ] [ chm ] = [ chm ] [ gm' ] // [ gm' ] = [ chmInv ] [ gm ] [ chm ] + var chm = transformListToTransform(chtlist).matrix, chmInv = chm.inverse(); var gm = matrixMultiply(chmInv, m, chm); newxform.setMatrix(gm); chtlist.appendItem(newxform); } - var cmd = recalculateDimensions(_elem5); + + var cmd = recalculateDimensions(elem); + if (cmd) { batchCmd.addSubCommand(cmd); } } - } + } // remove transform and make it undo-able + - // remove transform and make it undo-able if (xform) { changes = {}; changes.transform = xform; @@ -19186,24 +20933,30 @@ if (undoable && !batchCmd.isEmpty()) { return batchCmd; } - }; + return undefined; + }; /** * Unwraps all the elements in a selected group (`g`) element. This requires - * significant recalculations to apply group's transforms, etc. to its children + * significant recalculations to apply group's transforms, etc. to its children. * @function module:svgcanvas.SvgCanvas#ungroupSelectedElement * @returns {undefined} */ + + this.ungroupSelectedElement = function () { var g = selectedElements[0]; + if (!g) { return; } + if ($$9(g).data('gsvg') || $$9(g).data('symbol')) { // Is svg, so actually convert to group convertToGroup(g); return; } + if (g.tagName === 'use') { // Somehow doesn't have data set, so retrieve var symbol = getElem(getHref(g).substr(1)); @@ -19211,15 +20964,18 @@ convertToGroup(g); return; } + var parentsA = $$9(g).parents('a'); + if (parentsA.length) { g = parentsA[0]; - } + } // Look for parent "a" + - // Look for parent "a" if (g.tagName === 'g' || g.tagName === 'a') { var batchCmd = new BatchCommand$1('Ungroup Elements'); var cmd = pushGroupProperties(g, true); + if (cmd) { batchCmd.addSubCommand(cmd); } @@ -19227,83 +20983,82 @@ var parent = g.parentNode; var anchor = g.nextSibling; var children = new Array(g.childNodes.length); - var i = 0; + while (g.firstChild) { - var _elem6 = g.firstChild; - var oldNextSibling = _elem6.nextSibling; - var oldParent = _elem6.parentNode; + var elem = g.firstChild; + var oldNextSibling = elem.nextSibling; + var oldParent = elem.parentNode; // Remove child title elements - // Remove child title elements - if (_elem6.tagName === 'title') { - var _elem7 = _elem6, - nextSibling = _elem7.nextSibling; - - batchCmd.addSubCommand(new RemoveElementCommand$1(_elem6, nextSibling, oldParent)); - _elem6.remove(); + if (elem.tagName === 'title') { + var _elem2 = elem, + nextSibling = _elem2.nextSibling; + batchCmd.addSubCommand(new RemoveElementCommand$1(elem, nextSibling, oldParent)); + elem.remove(); continue; } - children[i++] = _elem6 = parent.insertBefore(_elem6, anchor); - batchCmd.addSubCommand(new MoveElementCommand$1(_elem6, oldNextSibling, oldParent)); - } + children[i++] = elem = parent.insertBefore(elem, anchor); + batchCmd.addSubCommand(new MoveElementCommand$1(elem, oldNextSibling, oldParent)); + } // remove the group from the selection - // remove the group from the selection - clearSelection(); - // delete the group element (but make undo-able) + clearSelection(); // delete the group element (but make undo-able) + var gNextSibling = g.nextSibling; g = parent.removeChild(g); batchCmd.addSubCommand(new RemoveElementCommand$1(g, gNextSibling, parent)); if (!batchCmd.isEmpty()) { addCommandToHistory(batchCmd); - } + } // update selection + - // update selection addToSelection(children); } }; - /** * Repositions the selected element to the bottom in the DOM to appear on top of - * other elements + * other elements. * @function module:svgcanvas.SvgCanvas#moveToTopSelectedElement * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + this.moveToTopSelectedElement = function () { var _selectedElements = selectedElements, - _selectedElements2 = slicedToArray(_selectedElements, 1), + _selectedElements2 = _slicedToArray(_selectedElements, 1), selected = _selectedElements2[0]; - if (selected != null) { + if (!isNullish(selected)) { var t = selected; var oldParent = t.parentNode; var oldNextSibling = t.nextSibling; - t = t.parentNode.appendChild(t); - // If the element actually moved position, add the command and fire the changed + t = t.parentNode.appendChild(t); // If the element actually moved position, add the command and fire the changed // event handler. + if (oldNextSibling !== t.nextSibling) { addCommandToHistory(new MoveElementCommand$1(t, oldNextSibling, oldParent, 'top')); call('changed', [t]); } } }; - /** * Repositions the selected element to the top in the DOM to appear under - * other elements + * other elements. * @function module:svgcanvas.SvgCanvas#moveToBottomSelectedElement * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + this.moveToBottomSelectedElement = function () { var _selectedElements3 = selectedElements, - _selectedElements4 = slicedToArray(_selectedElements3, 1), + _selectedElements4 = _slicedToArray(_selectedElements3, 1), selected = _selectedElements4[0]; - if (selected != null) { + if (!isNullish(selected)) { var t = selected; var oldParent = t.parentNode; var oldNextSibling = t.nextSibling; @@ -19311,41 +21066,45 @@ if (firstChild.tagName === 'title') { firstChild = firstChild.nextSibling; - } - // This can probably be removed, as the defs should not ever apppear + } // This can probably be removed, as the defs should not ever apppear // inside a layer group + + if (firstChild.tagName === 'defs') { firstChild = firstChild.nextSibling; } - t = t.parentNode.insertBefore(t, firstChild); - // If the element actually moved position, add the command and fire the changed + + t = t.parentNode.insertBefore(t, firstChild); // If the element actually moved position, add the command and fire the changed // event handler. + if (oldNextSibling !== t.nextSibling) { addCommandToHistory(new MoveElementCommand$1(t, oldNextSibling, oldParent, 'bottom')); call('changed', [t]); } } }; - /** * Moves the select element up or down the stack, based on the visibly - * intersecting elements + * intersecting elements. * @function module:svgcanvas.SvgCanvas#moveUpDownSelected * @param {"Up"|"Down"} dir - String that's either 'Up' or 'Down' * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + this.moveUpDownSelected = function (dir) { var selected = selectedElements[0]; + if (!selected) { return; } curBBoxes = []; - var closest = void 0, - foundCur = void 0; - // jQuery sorts this list + var closest, foundCur; // jQuery sorts this list + var list = $$9(getIntersectionList(getStrokedBBoxDefaultVisible([selected]))).toArray(); + if (dir === 'Down') { list.reverse(); } @@ -19355,11 +21114,15 @@ if (this === selected) { foundCur = true; } - return; + + return true; } - closest = this; + + closest = this; // eslint-disable-line consistent-this + return false; }); + if (!closest) { return; } @@ -19367,24 +21130,25 @@ var t = selected; var oldParent = t.parentNode; var oldNextSibling = t.nextSibling; - $$9(closest)[dir === 'Down' ? 'before' : 'after'](t); - // If the element actually moved position, add the command and fire the changed + $$9(closest)[dir === 'Down' ? 'before' : 'after'](t); // If the element actually moved position, add the command and fire the changed // event handler. + if (oldNextSibling !== t.nextSibling) { addCommandToHistory(new MoveElementCommand$1(t, oldNextSibling, oldParent, 'Move ' + dir)); call('changed', [t]); } }; - /** - * Moves selected elements on the X/Y axis + * Moves selected elements on the X/Y axis. * @function module:svgcanvas.SvgCanvas#moveSelectedElements * @param {Float} dx - Float with the distance to move on the x-axis * @param {Float} dy - Float with the distance to move on the y-axis * @param {boolean} undoable - Boolean indicating whether or not the action should be undoable * @fires module:svgcanvas.SvgCanvas#event:changed - * @returns {BatchCommand} Batch command for the move + * @returns {BatchCommand|undefined} Batch command for the move */ + + this.moveSelectedElements = function (dx, dy, undoable) { // if undoable is not sent, default to true // if single values, scale them to the zoom @@ -19392,23 +21156,24 @@ dx /= currentZoom; dy /= currentZoom; } + undoable = undoable || true; var batchCmd = new BatchCommand$1('position'); var i = selectedElements.length; + while (i--) { var selected = selectedElements[i]; - if (selected != null) { + + if (!isNullish(selected)) { // if (i === 0) { // selectedBBoxes[0] = utilsGetBBox(selected); // } // const b = {}; // for (const j in selectedBBoxes[i]) b[j] = selectedBBoxes[i][j]; // selectedBBoxes[i] = b; - var xform = svgroot.createSVGTransform(); - var tlist = getTransformList(selected); + var tlist = getTransformList(selected); // dx and dy could be arrays - // dx and dy could be arrays if (dx.constructor === Array) { // if (i === 0) { // selectedBBoxes[0].x += dx[0]; @@ -19430,6 +21195,7 @@ } var cmd = recalculateDimensions(selected); + if (cmd) { batchCmd.addSubCommand(cmd); } @@ -19437,46 +21203,62 @@ selectorManager.requestSelector(selected).resize(); } } + if (!batchCmd.isEmpty()) { if (undoable) { addCommandToHistory(batchCmd); } + call('changed', selectedElements); return batchCmd; } - }; + return undefined; + }; /** * Create deep DOM copies (clones) of all selected elements and move them slightly - * from their originals + * from their originals. * @function module:svgcanvas.SvgCanvas#cloneSelectedElements * @param {Float} x Float with the distance to move on the x-axis * @param {Float} y Float with the distance to move on the y-axis * @returns {undefined} */ + + this.cloneSelectedElements = function (x, y) { - var i = void 0, - elem = void 0; - var batchCmd = new BatchCommand$1('Clone Elements'); - // find all the elements selected (stop at first null) + var i, elem; + var batchCmd = new BatchCommand$1('Clone Elements'); // find all the elements selected (stop at first null) + var len = selectedElements.length; + /** + * Sorts an array numerically and ascending. + * @param {Element} a + * @param {Element} b + * @returns {Integer} + */ + function sortfunction(a, b) { - return $$9(b).index() - $$9(a).index(); // causes an array to be sorted numerically and ascending + return $$9(b).index() - $$9(a).index(); } + selectedElements.sort(sortfunction); + for (i = 0; i < len; ++i) { elem = selectedElements[i]; - if (elem == null) { + + 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 + + var copiedElements = selectedElements.slice(0, i); - this.clearSelection(true); - // note that we loop in the reverse way because of the way elements are added + this.clearSelection(true); // note that we loop in the reverse way because of the way elements are added // to the selectedElements array (top-first) + var drawing = getCurrentDrawing(); i = copiedElements.length; + while (i--) { // clone each element and replace it within copiedElements elem = copiedElements[i] = drawing.copyElem(copiedElements[i]); @@ -19486,38 +21268,44 @@ if (!batchCmd.isEmpty()) { addToSelection(copiedElements.reverse()); // Need to reverse for correct selection-adding + this.moveSelectedElements(x, y, false); addCommandToHistory(batchCmd); } }; - /** - * Aligns selected elements + * Aligns selected elements. * @function module:svgcanvas.SvgCanvas#alignSelectedElements * @param {string} type - String with single character indicating the alignment type * @param {"selected"|"largest"|"smallest"|"page"} relativeTo * @returns {undefined} */ + + this.alignSelectedElements = function (type, relativeTo) { var bboxes = []; // angles = []; + var len = selectedElements.length; + if (!len) { return; } + var minx = Number.MAX_VALUE, maxx = Number.MIN_VALUE, miny = Number.MAX_VALUE, maxy = Number.MIN_VALUE; var curwidth = Number.MIN_VALUE, curheight = Number.MIN_VALUE; + for (var i = 0; i < len; ++i) { - if (selectedElements[i] == null) { + if (isNullish(selectedElements[i])) { break; } - var _elem8 = selectedElements[i]; - bboxes[i] = getStrokedBBoxDefaultVisible([_elem8]); - // now bbox is axis-aligned and handles rotation + var elem = selectedElements[i]; + bboxes[i] = getStrokedBBoxDefaultVisible([elem]); // now bbox is axis-aligned and handles rotation + switch (relativeTo) { case 'smallest': if ((type === 'l' || type === 'c' || type === 'r') && (curwidth === Number.MIN_VALUE || curwidth > bboxes[i].width) || (type === 't' || type === 'm' || type === 'b') && (curheight === Number.MIN_VALUE || curheight > bboxes[i].height)) { @@ -19528,7 +21316,9 @@ curwidth = bboxes[i].width; curheight = bboxes[i].height; } + break; + case 'largest': if ((type === 'l' || type === 'c' || type === 'r') && (curwidth === Number.MIN_VALUE || curwidth < bboxes[i].width) || (type === 't' || type === 'm' || type === 'b') && (curheight === Number.MIN_VALUE || curheight < bboxes[i].height)) { minx = bboxes[i].x; @@ -19538,25 +21328,32 @@ curwidth = bboxes[i].width; curheight = bboxes[i].height; } + break; + default: // 'selected' if (bboxes[i].x < minx) { minx = bboxes[i].x; } + if (bboxes[i].y < miny) { miny = bboxes[i].y; } + if (bboxes[i].x + bboxes[i].width > maxx) { maxx = bboxes[i].x + bboxes[i].width; } + if (bboxes[i].y + bboxes[i].height > maxy) { maxy = bboxes[i].y + bboxes[i].height; } + break; } } // loop for each element to find the bbox and adjust min/max + if (relativeTo === 'page') { minx = 0; miny = 0; @@ -19566,44 +21363,52 @@ var dx = new Array(len); var dy = new Array(len); - for (var _i2 = 0; _i2 < len; ++_i2) { - if (selectedElements[_i2] == null) { + + for (var _i7 = 0; _i7 < len; ++_i7) { + if (isNullish(selectedElements[_i7])) { break; - } - // const elem = selectedElements[i]; - var bbox = bboxes[_i2]; - dx[_i2] = 0; - dy[_i2] = 0; + } // const elem = selectedElements[i]; + + + var bbox = bboxes[_i7]; + dx[_i7] = 0; + dy[_i7] = 0; + switch (type) { case 'l': // left (horizontal) - dx[_i2] = minx - bbox.x; + dx[_i7] = minx - bbox.x; break; + case 'c': // center (horizontal) - dx[_i2] = (minx + maxx) / 2 - (bbox.x + bbox.width / 2); + dx[_i7] = (minx + maxx) / 2 - (bbox.x + bbox.width / 2); break; + case 'r': // right (horizontal) - dx[_i2] = maxx - (bbox.x + bbox.width); + dx[_i7] = maxx - (bbox.x + bbox.width); break; + case 't': // top (vertical) - dy[_i2] = miny - bbox.y; + dy[_i7] = miny - bbox.y; break; + case 'm': // middle (vertical) - dy[_i2] = (miny + maxy) / 2 - (bbox.y + bbox.height / 2); + dy[_i7] = (miny + maxy) / 2 - (bbox.y + bbox.height / 2); break; + case 'b': // bottom (vertical) - dy[_i2] = maxy - (bbox.y + bbox.height); + dy[_i7] = maxy - (bbox.y + bbox.height); break; } } + this.moveSelectedElements(dx, dy); }; - /** * Group: Additional editor tools */ @@ -19612,13 +21417,15 @@ * @name module:svgcanvas.SvgCanvas#contentW * @type {Float} */ + + this.contentW = getResolution().w; /** * @name module:svgcanvas.SvgCanvas#contentH * @type {Float} */ - this.contentH = getResolution().h; + this.contentH = getResolution().h; /** * @typedef {PlainObject} module:svgcanvas.CanvasInfo * @property {Float} x - The canvas' new x coordinate @@ -19630,22 +21437,22 @@ */ /** - * Updates the editor canvas width/height/position after a zoom has occurred + * Updates the editor canvas width/height/position after a zoom has occurred. * @function module:svgcanvas.SvgCanvas#updateCanvas * @param {Float} w - Float with the new width * @param {Float} h - Float with the new height * @fires module:svgcanvas.SvgCanvas#event:ext-canvasUpdated * @returns {module:svgcanvas.CanvasInfo} */ + this.updateCanvas = function (w, h) { svgroot.setAttribute('width', w); svgroot.setAttribute('height', h); var bg = $$9('#canvasBackground')[0]; var oldX = svgcontent.getAttribute('x'); var oldY = svgcontent.getAttribute('y'); - var x = w / 2 - this.contentW * currentZoom / 2; - var y = h / 2 - this.contentH * currentZoom / 2; - + var x = (w - this.contentW * currentZoom) / 2; + var y = (h - this.contentH * currentZoom) / 2; assignAttributes(svgcontent, { width: this.contentW * currentZoom, height: this.contentH * currentZoom, @@ -19653,15 +21460,14 @@ y: y, viewBox: '0 0 ' + this.contentW + ' ' + this.contentH }); - assignAttributes(bg, { width: svgcontent.getAttribute('width'), height: svgcontent.getAttribute('height'), x: x, y: y }); - var bgImg = getElem('background_image'); + if (bgImg) { assignAttributes(bgImg, { width: '100%', @@ -19681,26 +21487,43 @@ * @property {Integer} d_x * @property {Integer} d_y */ + runExtensions('canvasUpdated', /** * @type {module:svgcanvas.SvgCanvas#event:ext-canvasUpdated} */ - { new_x: x, new_y: y, old_x: oldX, old_y: oldY, d_x: x - oldX, d_y: y - oldY }); - return { x: x, y: y, old_x: oldX, old_y: oldY, d_x: x - oldX, d_y: y - oldY }; + { + new_x: x, + new_y: y, + old_x: oldX, + old_y: oldY, + d_x: x - oldX, + d_y: y - oldY + }); + return { + x: x, + y: y, + old_x: oldX, + old_y: oldY, + d_x: x - oldX, + d_y: y - oldY + }; }; - /** - * Set the background of the editor (NOT the actual document) + * Set the background of the editor (NOT the actual document). * @function module:svgcanvas.SvgCanvas#setBackground * @param {string} color - String with fill color to apply * @param {string} url - URL or path to image to use * @returns {undefined} */ + + this.setBackground = function (color, url) { var bg = getElem('canvasBackground'); var border = $$9(bg).find('rect')[0]; var bgImg = getElem('background_image'); border.setAttribute('fill', color); + if (url) { if (!bgImg) { bgImg = svgdoc.createElementNS(NS.SVG, 'image'); @@ -19712,52 +21535,59 @@ style: 'pointer-events:none' }); } + setHref(bgImg, url); bg.append(bgImg); } else if (bgImg) { bgImg.remove(); } }; - /** - * Select the next/previous element within the current layer + * Select the next/previous element within the current layer. * @function module:svgcanvas.SvgCanvas#cycleElement * @param {boolean} next - true = next and false = previous element * @fires module:svgcanvas.SvgCanvas#event:selected * @returns {undefined} */ + + this.cycleElement = function (next) { - var num = void 0; + var num; var curElem = selectedElements[0]; var elem = false; var allElems = getVisibleElements(currentGroup || getCurrentDrawing().getCurrentLayer()); + if (!allElems.length) { return; } - if (curElem == null) { + + if (isNullish(curElem)) { num = next ? allElems.length - 1 : 0; elem = allElems[num]; } else { var i = allElems.length; + while (i--) { if (allElems[i] === curElem) { num = next ? i - 1 : i + 1; + if (num >= allElems.length) { num = 0; } else if (num < 0) { num = allElems.length - 1; } + elem = allElems[num]; break; } } } + selectOnly([elem], true); call('selected', selectedElements); }; this.clear(); - /** * @interface module:svgcanvas.PrivateMethods * @type {PlainObject} @@ -19765,6 +21595,7 @@ * @property {module:history.HistoryCommand} BatchCommand * @property {module:history.HistoryCommand} ChangeElementCommand * @property {module:utilities.decode64} decode64 + * @property {module:utilities.dropXMLInteralSubset} dropXMLInteralSubset * @property {module:utilities.encode64} encode64 * @property {module:svgcanvas~ffClone} ffClone * @property {module:svgcanvas~findDuplicateGradient} findDuplicateGradient @@ -19786,6 +21617,7 @@ * @property {module:math.transformPoint} transformPoint * @property {module:utilities.walkTree} walkTree */ + /** * @deprecated getPrivateMethods * Since all methods are/should be public somehow, this function should be removed; @@ -19798,12 +21630,14 @@ * @function module:svgcanvas.SvgCanvas#getPrivateMethods * @returns {module:svgcanvas.PrivateMethods} */ + this.getPrivateMethods = function () { var obj = { addCommandToHistory: addCommandToHistory, BatchCommand: BatchCommand$1, ChangeElementCommand: ChangeElementCommand$1, decode64: decode64, + dropXMLInteralSubset: dropXMLInteralSubset, encode64: encode64, ffClone: ffClone, findDefs: findDefs, @@ -19834,6 +21668,7 @@ ; // End class // Todo: Update: https://github.com/jeresig/jquery.hotkeys + /* * jQuery Hotkeys Plugin * Copyright 2010, John Resig @@ -19847,42 +21682,146 @@ * Original idea by: * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/ */ + // We *do* want to allow the escape key within textareas (and possibly tab too), so add the condition `n.which !== 27` + function jQueryPluginJSHotkeys (b) { + b.hotkeys = { + version: "0.8", + specialKeys: { + 8: "backspace", + 9: "tab", + 13: "return", + 16: "shift", + 17: "ctrl", + 18: "alt", + 19: "pause", + 20: "capslock", + 27: "esc", + 32: "space", + 33: "pageup", + 34: "pagedown", + 35: "end", + 36: "home", + 37: "left", + 38: "up", + 39: "right", + 40: "down", + 45: "insert", + 46: "del", + 96: "0", + 97: "1", + 98: "2", + 99: "3", + 100: "4", + 101: "5", + 102: "6", + 103: "7", + 104: "8", + 105: "9", + 106: "*", + 107: "+", + 109: "-", + 110: ".", + 111: "/", + 112: "f1", + 113: "f2", + 114: "f3", + 115: "f4", + 116: "f5", + 117: "f6", + 118: "f7", + 119: "f8", + 120: "f9", + 121: "f10", + 122: "f11", + 123: "f12", + 144: "numlock", + 145: "scroll", + 191: "/", + 224: "meta", + 219: "[", + 221: "]" + }, + shiftNums: { + "`": "~", + "1": "!", + "2": "@", + "3": "#", + "4": "$", + "5": "%", + "6": "^", + "7": "&", + "8": "*", + "9": "(", + "0": ")", + "-": "_", + "=": "+", + ";": ": ", + "'": '"', + ",": "<", + ".": ">", + "/": "?", + "\\": "|" + } + }; - function jqPluginJSHotkeys (b) { - b.hotkeys = { version: "0.8", specialKeys: { 8: "backspace", 9: "tab", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause", 20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home", 37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del", 96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7", 104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111: "/", 112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8", 120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 191: "/", 224: "meta", 219: "[", 221: "]" }, shiftNums: { "`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&", "8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": '"', ",": "<", ".": ">", "/": "?", "\\": "|" } };function a(d) { + function a(d) { if (typeof d.data !== "string") { return; - }var c = d.handler, - e = d.data.toLowerCase().split(" ");d.handler = function (n) { - if (this !== n.target && (/textarea|select/i.test(n.target.nodeName) || n.target.type === "text")) { + } + + var c = d.handler, + e = d.data.toLowerCase().split(" "); + + d.handler = function (n) { + if (this !== n.target && n.which !== 27 && (/textarea|select/i.test(n.target.nodeName) || n.target.type === "text")) { return; - }var h = n.type !== "keypress" && b.hotkeys.specialKeys[n.which], + } + + var h = n.type !== "keypress" && b.hotkeys.specialKeys[n.which], o = String.fromCharCode(n.which).toLowerCase(), m = "", - g = {};if (n.altKey && h !== "alt") { + g = {}; + + if (n.altKey && h !== "alt") { m += "alt+"; - }if (n.ctrlKey && h !== "ctrl") { + } + + if (n.ctrlKey && h !== "ctrl") { m += "ctrl+"; - }if (n.metaKey && !n.ctrlKey && h !== "meta") { + } + + if (n.metaKey && !n.ctrlKey && h !== "meta") { m += "meta+"; - }if (n.shiftKey && h !== "shift") { + } + + if (n.shiftKey && h !== "shift") { m += "shift+"; - }if (h) { + } + + if (h) { g[m + h] = true; } else { - g[m + o] = true;g[m + b.hotkeys.shiftNums[o]] = true;if (m === "shift+") { + g[m + o] = true; + g[m + b.hotkeys.shiftNums[o]] = true; + + if (m === "shift+") { g[b.hotkeys.shiftNums[o]] = true; } - }for (var j = 0, f = e.length; j < f; j++) { + } + + for (var j = 0, f = e.length; j < f; j++) { if (g[e[j]]) { return c.apply(this, arguments); } } }; - }b.each(["keydown", "keyup", "keypress"], function () { - b.event.special[this] = { add: a }; - }); + } + b.each(["keydown", "keyup", "keypress"], function () { + b.event.special[this] = { + add: a + }; + }); return b; } @@ -19895,10 +21834,8 @@ * Dual licensed under the MIT and GPL licenses. * http://benalman.com/about/license/ */ - // For sake of modules, added this wrapping export and changed `this` to `window` - function jqPluginBBQ (jQuery) { - + function jQueryPluginBBQ (jQuery) { (function ($, p) { var i, m = Array.prototype.slice, @@ -19922,49 +21859,101 @@ x = /^.*\?|#.*$/g, w = /^.*\#/, h, - C = {};function E(F) { + C = {}; + + function E(F) { return typeof F === "string"; - }function B(G) { - var F = m.call(arguments, 1);return function () { + } + + function B(G) { + var F = m.call(arguments, 1); + return function () { return G.apply(this, F.concat(m.call(arguments))); }; - }function n(F) { + } + + function n(F) { return F.replace(/^[^#]*#?(.*)$/, "$1"); - }function o(F) { + } + + function o(F) { return F.replace(/(?:^[^?#]*\?([^#]*).*$)?.*/, "$1"); - }function f(H, M, F, I, G) { - var O, L, K, N, J;if (I !== i) { - K = F.match(H ? /^([^#]*)\#?(.*)$/ : /^([^#?]*)\??([^#]*)(#?.*)/);J = K[3] || "";if (G === 2 && E(I)) { + } + + function f(H, M, F, I, G) { + var O, L, K, N, J; + + if (I !== i) { + K = F.match(H ? /^([^#]*)\#?(.*)$/ : /^([^#?]*)\??([^#]*)(#?.*)/); + J = K[3] || ""; + + if (G === 2 && E(I)) { L = I.replace(H ? w : x, ""); } else { - N = l(K[2]);I = E(I) ? l[H ? D : A](I) : I;L = G === 2 ? I : G === 1 ? $.extend({}, I, N) : $.extend({}, N, I);L = a(L);if (H) { + N = l(K[2]); + I = E(I) ? l[H ? D : A](I) : I; + L = G === 2 ? I : G === 1 ? $.extend({}, I, N) : $.extend({}, N, I); + L = a(L); + + if (H) { L = L.replace(h, r); } - }O = K[1] + (H ? "#" : L || !K[1] ? "?" : "") + L + J; + } + + O = K[1] + (H ? "#" : L || !K[1] ? "?" : "") + L + J; } else { O = M(F !== i ? F : p[g][k]); - }return O; - }a[A] = B(f, 0, o);a[D] = c = B(f, 1, n);c.noEscape = function (G) { - G = G || "";var F = $.map(G.split(""), encodeURIComponent);h = new RegExp(F.join("|"), "g"); - };c.noEscape(",/");$.deparam = l = function l(I, F) { + } + + return O; + } + + a[A] = B(f, 0, o); + a[D] = c = B(f, 1, n); + + c.noEscape = function (G) { + G = G || ""; + var F = $.map(G.split(""), encodeURIComponent); + h = new RegExp(F.join("|"), "g"); + }; + + c.noEscape(",/"); + + $.deparam = l = function l(I, F) { var H = {}, - G = { "true": !0, "false": !1, "null": null };$.each(I.replace(/\+/g, " ").split("&"), function (L, Q) { + G = { + "true": !0, + "false": !1, + "null": null + }; + $.each(I.replace(/\+/g, " ").split("&"), function (L, Q) { var K = Q.split("="), P = r(K[0]), J, O = H, M = 0, R = P.split("]["), - N = R.length - 1;if (/\[/.test(R[0]) && /\]$/.test(R[N])) { - R[N] = R[N].replace(/\]$/, "");R = R.shift().split("[").concat(R);N = R.length - 1; + N = R.length - 1; + + if (/\[/.test(R[0]) && /\]$/.test(R[N])) { + R[N] = R[N].replace(/\]$/, ""); + R = R.shift().split("[").concat(R); + N = R.length - 1; } else { N = 0; - }if (K.length === 2) { - J = r(K[1]);if (F) { + } + + if (K.length === 2) { + J = r(K[1]); + + if (F) { J = J && !isNaN(J) ? +J : J === "undefined" ? i : G[J] !== i ? G[J] : J; - }if (N) { + } + + if (N) { for (; M <= N; M++) { - P = R[M] === "" ? O.length : R[M];O = O[P] = M < N ? O[P] || (R[M + 1] && isNaN(R[M + 1]) ? {} : []) : J; + P = R[M] === "" ? O.length : R[M]; + O = O[P] = M < N ? O[P] || (R[M + 1] && isNaN(R[M + 1]) ? {} : []) : J; } } else { if ($.isArray(H[P])) { @@ -19982,47 +21971,105 @@ H[P] = F ? i : ""; } } - });return H; - };function z(H, F, G) { + }); + return H; + }; + + function z(H, F, G) { if (F === i || typeof F === "boolean") { - G = F;F = a[H ? D : A](); + G = F; + F = a[H ? D : A](); } else { F = E(F) ? F.replace(H ? w : x, "") : F; - }return l(F, G); - }l[A] = B(z, 0);l[D] = v = B(z, 1);$[y] || ($[y] = function (F) { + } + + return l(F, G); + } + + l[A] = B(z, 0); + l[D] = v = B(z, 1); + $[y] || ($[y] = function (F) { return $.extend(C, F); - })({ a: k, base: k, iframe: t, img: t, input: t, form: "action", link: k, script: t });j = $[y];function s(I, G, H, F) { - if (!E(H) && (typeof H === "undefined" ? "undefined" : _typeof(H)) !== "object") { - F = H;H = G;G = i; - }return this.each(function () { + })({ + a: k, + base: k, + iframe: t, + img: t, + input: t, + form: "action", + link: k, + script: t + }); + j = $[y]; + + function s(I, G, H, F) { + if (!E(H) && _typeof(H) !== "object") { + F = H; + H = G; + G = i; + } + + return this.each(function () { var L = $(this), J = G || j()[(this.nodeName || "").toLowerCase()] || "", - K = J && L.attr(J) || "";L.attr(J, a[I](K, H, F)); + K = J && L.attr(J) || ""; + L.attr(J, a[I](K, H, F)); }); - }$.fn[A] = B(s, A);$.fn[D] = B(s, D);b.pushState = q = function q(I, F) { + } + + $.fn[A] = B(s, A); + $.fn[D] = B(s, D); + + b.pushState = q = function q(I, F) { if (E(I) && /^#/.test(I) && F === i) { F = 2; - }var H = I !== i, - G = c(p[g][k], H ? I : {}, H ? F : 2);p[g][k] = G + (/#/.test(G) ? "" : "#"); - };b.getState = u = function u(F, G) { + } + + var H = I !== i, + G = c(p[g][k], H ? I : {}, H ? F : 2); + p[g][k] = G + (/#/.test(G) ? "" : "#"); + }; + + b.getState = u = function u(F, G) { return F === i || typeof F === "boolean" ? v(F) : v(G)[F]; - };b.removeState = function (F) { - var G = {};if (F !== i) { - G = u();$.each($.isArray(F) ? F : arguments, function (I, H) { + }; + + b.removeState = function (F) { + var G = {}; + + if (F !== i) { + G = u(); + $.each($.isArray(F) ? F : arguments, function (I, H) { delete G[H]; }); - }q(G, 2); - };e[d] = $.extend(e[d], { add: function add(F) { - var H;function G(J) { - var I = J[D] = c();J.getState = function (K, L) { + } + + q(G, 2); + }; + + e[d] = $.extend(e[d], { + add: function add(F) { + var H; + + function G(J) { + var I = J[D] = c(); + + J.getState = function (K, L) { return K === i || typeof K === "boolean" ? l(I, K) : l(I, L)[K]; - };H.apply(this, arguments); - }if ($.isFunction(F)) { - H = F;return G; - } else { - H = F.handler;F.handler = G; + }; + + H.apply(this, arguments); } - } }); + + if ($.isFunction(F)) { + H = F; + return G; + } else { + H = F.handler; + F.handler = G; + } + } + }); })(jQuery, window); /* * jQuery hashchange event - v1.2 - 2/11/2010 @@ -20032,6 +22079,8 @@ * Dual licensed under the MIT and GPL licenses. * http://benalman.com/about/license/ */ + + (function ($, i, b) { var j, k = $.event.special, @@ -20041,57 +22090,102 @@ f = $.browser, g = document.documentMode, h = f.msie && (g === b || g < 8), - e = "on" + d in i && !h;function a(m) { - m = m || i[c][l];return m.replace(/^[^#]*#?(.*)$/, "$1"); - }$[d + "Delay"] = 100;k[d] = $.extend(k[d], { setup: function setup() { + e = "on" + d in i && !h; + + function a(m) { + m = m || i[c][l]; + return m.replace(/^[^#]*#?(.*)$/, "$1"); + } + + $[d + "Delay"] = 100; + k[d] = $.extend(k[d], { + setup: function setup() { if (e) { return false; - }$(j.start); - }, teardown: function teardown() { + } + + $(j.start); + }, + teardown: function teardown() { if (e) { return false; - }$(j.stop); - } });j = function () { + } + + $(j.stop); + } + }); + + j = function () { var m = {}, r, n, o, - q;function p() { + q; + + function p() { o = q = function q(s) { return s; - };if (h) { - n = $('<iframe src="javascript:0"/>').hide().insertAfter("body")[0].contentWindow;q = function q() { + }; + + if (h) { + n = $('<iframe src="javascript:0"/>').hide().insertAfter("body")[0].contentWindow; + + q = function q() { return a(n.document[c][l]); - };o = function o(u, s) { + }; + + o = function o(u, s) { if (u !== s) { - var t = n.document;t.open().close();t[c].hash = "#" + u; + var t = n.document; + t.open().close(); + t[c].hash = "#" + u; } - };o(a()); + }; + + o(a()); } - }m.start = function () { + } + + m.start = function () { if (r) { return; - }var t = a();o || p();(function s() { + } + + var t = a(); + o || p(); + + (function s() { var v = a(), - u = q(t);if (v !== t) { - o(t = v, u);$(i).trigger(d); + u = q(t); + + if (v !== t) { + o(t = v, u); + $(i).trigger(d); } else { if (u !== t) { i[c][l] = i[c][l].replace(/#.*/, "") + "#" + u; } - }r = setTimeout(s, $[d + "Delay"]); + } + + r = setTimeout(s, $[d + "Delay"]); })(); - };m.stop = function () { + }; + + m.stop = function () { if (!n) { - r && clearTimeout(r);r = 0; + r && clearTimeout(r); + r = 0; } - };return m; + }; + + return m; }(); })(jQuery, window); return jQuery; } + // Todo: Move to own module (and have it import a modular base64 encoder) /** * SVG Icon Loader 2.0 * @@ -20188,58 +22282,65 @@ /** * @function module:jQuerySVGIcons.jQuerySVGIcons * @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 */ - function jqPluginSVGIcons ($) { - var svgIcons = {}; - var fixIDs = void 0; + function jQueryPluginSVGIcons($) { + var svgIcons = {}; + var fixIDs; + /** + * List of raster images with each + * key being the SVG icon ID to replace, and the value the image file name + * @typedef {PlainObject.<string, string>} external:jQuery.svgIcons.Fallback + */ + /** * @function external:jQuery.svgIcons * @param {string} file The location of a local SVG or SVGz file - * @param {PlainObject} [options] - * @param {Float} [options.w] The icon widths - * @param {Float} [options.h] The icon heights - * @param {PlainObject.<string, string>} [options.fallback] List of raster images with each - key being the SVG icon ID to replace, and the value the image file name - * @param {string} [options.fallback_path] The path to use for all images + * @param {PlainObject} [opts] + * @param {Float} [opts.w] The icon widths + * @param {Float} [opts.h] The icon heights + * @param {external:jQuery.svgIcons.Fallback} [opts.fallback] + * @param {string} [opts.fallback_path] The path to use for all images listed under "fallback" - * @param {boolean} [options.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, rather than include the SVG icon. - * @param {PlainObject.<string, string>} [options.placement] List with selectors for keys and SVG icon ids + * @param {PlainObject.<string, string>} [opts.placement] List with selectors for keys and SVG icon ids as values. This provides a custom method of adding icons. - * @param {PlainObject.<string, module:jQuerySVGIcons.Size>} [options.resize] List with selectors for keys and numbers + * @param {PlainObject.<string, module:jQuerySVGIcons.Size>} [opts.resize] List with selectors for keys and numbers as values. This allows an easy way to resize specific icons. - * @param {module:jQuerySVGIcons.SVGIconsLoadedCallback} [options.callback] A function to call when all icons have been loaded. - * @param {boolean} [options.id_match=true] Automatically attempt to match SVG icon ids with + * @param {module:jQuerySVGIcons.SVGIconsLoadedCallback} [opts.callback] A function to call when all icons have been loaded. + * @param {boolean} [opts.id_match=true] Automatically attempt to match SVG icon ids with corresponding HTML id - * @param {boolean} [options.no_img] Prevent attempting to convert the icon into an `<img>` + * @param {boolean} [opts.no_img] Prevent attempting to convert the icon into an `<img>` element (may be faster, help for browser consistency) - * @param {boolean} [options.svgz] Indicate that the file is an SVGZ file, and thus not to + * @param {boolean} [opts.svgz] Indicate that the file is an SVGZ file, and thus not to parse as XML. SVGZ files add compression benefits, but getting data from them fails in Firefox 2 and older. + * @returns {undefined} */ + $.svgIcons = function (file) { var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - var svgns = 'http://www.w3.org/2000/svg', xlinkns = 'http://www.w3.org/1999/xlink', iconW = opts.w || 24, iconH = opts.h || 24; - var elems = void 0, - svgdoc = void 0, - testImg = void 0, + var elems, + svgdoc, + testImg, iconsMade = false, dataLoaded = false, loadAttempts = 0; - var isOpera = !!window.opera, - - // ua = navigator.userAgent, + var isOpera = Boolean(window.opera), + // ua = navigator.userAgent, // isSafari = (ua.includes('Safari/') && !ua.includes('Chrome/')), dataPre = 'data:image/svg+xml;charset=utf-8;base64,'; + var dataEl; - var dataEl = void 0; if (opts.svgz) { dataEl = $('<object data="' + file + '" type=image/svg+xml>').appendTo('body').hide(); + try { svgdoc = dataEl[0].contentDocument; dataEl.load(getIcons); @@ -20257,6 +22358,7 @@ $(useFallback); return; } + svgdoc = parser.parseFromString(data, 'text/xml'); $(function () { getIcons('ajax'); @@ -20268,42 +22370,53 @@ $(function () { useFallback(); }); - } else { - if (err.responseText) { - svgdoc = parser.parseFromString(err.responseText, 'text/xml'); + } else if (err.responseText) { + svgdoc = parser.parseFromString(err.responseText, 'text/xml'); - if (!svgdoc.childNodes.length) { - $(useFallback); - } - $(function () { - getIcons('ajax'); - }); - } else { + if (!svgdoc.childNodes.length) { $(useFallback); } + + $(function () { + getIcons('ajax'); + }); + } else { + $(useFallback); } } }); } + /** + * + * @param {"ajax"|0|undefined} evt + * @param {boolean} [noWait] + * @returns {undefined} + */ + function getIcons(evt, noWait) { if (evt !== 'ajax') { - if (dataLoaded) return; - // Webkit sometimes says svgdoc is undefined, other times + if (dataLoaded) return; // Webkit sometimes says svgdoc is undefined, other times // it fails to load all nodes. Thus we must make sure the "eof" // element is loaded. + svgdoc = dataEl[0].contentDocument; // Needed again for Webkit + var isReady = svgdoc && svgdoc.getElementById('svg_eof'); + if (!isReady && !(noWait && isReady)) { loadAttempts++; + if (loadAttempts < 50) { setTimeout(getIcons, 20); } else { useFallback(); dataLoaded = true; } + return; } + dataLoaded = true; } @@ -20311,7 +22424,6 @@ if (!opts.no_img) { var testSrc = dataPre + 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNzUiIGhlaWdodD0iMjc1Ij48L3N2Zz4%3D'; - testImg = $(new Image()).attr({ src: testSrc, width: 0, @@ -20328,9 +22440,19 @@ }, 500); } } + /** + * + * @param {external:jQuery} target + * @param {external:jQuery} icon A wrapped `defs` or Image + * @param {string} id SVG icon ID + * @param {string} setID + * @returns {undefined} + */ + function setIcon(target, icon, id, setID) { if (isOpera) icon.css('visibility', 'hidden'); + if (opts.replace) { if (setID) icon.attr('id', id); var cl = target.attr('class'); @@ -20339,6 +22461,7 @@ } else { target.append(icon); } + if (isOpera) { setTimeout(function () { icon.removeAttr('style'); @@ -20346,23 +22469,40 @@ } } - var holder = void 0; + var holder; + /** + * @param {external:jQuery} icon A wrapped `defs` or Image + * @param {string} id SVG icon ID + * @returns {undefined} + */ + function addIcon(icon, id) { if (opts.id_match === undefined || opts.id_match !== false) { setIcon(holder, icon, id, true); } + svgIcons[id] = icon; } + /** + * + * @param {boolean} [toImage] + * @param {external:jQuery.svgIcons.Fallback} [fallback] + * @returns {undefined} + */ - function makeIcons(toImage, fallback) { + + function makeIcons() { + var toImage = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var fallback = arguments.length > 1 ? arguments[1] : undefined; if (iconsMade) return; if (opts.no_img) toImage = false; + var tempHolder; - var tempHolder = void 0; if (toImage) { tempHolder = $(document.createElement('div')); tempHolder.hide().appendTo('body'); } + if (fallback) { var path = opts.fallback_path || ''; $.each(fallback, function (id, imgsrc) { @@ -20374,56 +22514,55 @@ height: iconH, alt: 'icon' }); - addIcon(icon, id); }); } else { var len = elems.length; + for (var i = 0; i < len; i++) { var elem = elems[i]; var id = elem.id; - if (id === 'svg_eof') break; holder = $('#' + id); - var svgroot = document.createElementNS(svgns, 'svg'); - // Per https://www.w3.org/TR/xml-names11/#defaulting, the namespace for + var svgroot = document.createElementNS(svgns, 'svg'); // Per https://www.w3.org/TR/xml-names11/#defaulting, the namespace for // attributes should have no value. - svgroot.setAttributeNS(null, 'viewBox', [0, 0, iconW, iconH].join(' ')); - var svg = elem.getElementsByTagNameNS(svgns, 'svg')[0]; + svgroot.setAttribute('viewBox', [0, 0, iconW, iconH].join(' ')); + var svg = elem.getElementsByTagNameNS(svgns, 'svg')[0]; // Make flexible by converting width/height to viewBox - // Make flexible by converting width/height to viewBox var w = svg.getAttribute('width'); var h = svg.getAttribute('height'); svg.removeAttribute('width'); svg.removeAttribute('height'); - var vb = svg.getAttribute('viewBox'); + if (!vb) { svg.setAttribute('viewBox', [0, 0, w, h].join(' ')); - } + } // Not using jQuery to be a bit faster + - // Not using jQuery to be a bit faster svgroot.setAttribute('xmlns', svgns); svgroot.setAttribute('width', iconW); svgroot.setAttribute('height', iconH); svgroot.setAttribute('xmlns:xlink', xlinkns); - svgroot.setAttribute('class', 'svg_icon'); - - // Without cloning, Firefox will make another GET request. + svgroot.setAttribute('class', 'svg_icon'); // Without cloning, Firefox will make another GET request. // With cloning, causes issue in Opera/Win/Non-EN + if (!isOpera) svg = svg.cloneNode(true); - svgroot.append(svg); - var icon = void 0; + if (toImage) { tempHolder.empty().append(svgroot); var str = dataPre + encode64(unescape(encodeURIComponent(new XMLSerializer().serializeToString(svgroot)))); - icon = $(new Image()).attr({ class: 'svg_icon', src: str }); + icon = $(new Image()).attr({ + class: 'svg_icon', + src: str + }); } else { icon = fixIDs($(svgroot), i); } + addIcon(icon, id); } } @@ -20438,25 +22577,26 @@ }); }); } + if (!fallback) { if (toImage) tempHolder.remove(); if (dataEl) dataEl.remove(); if (testImg) testImg.remove(); } + if (opts.resize) $.resizeSvgIcons(opts.resize); iconsMade = true; - if (opts.callback) opts.callback(svgIcons); } fixIDs = function fixIDs(svgEl, svgNum, force) { var defs = svgEl.find('defs'); if (!defs.length) return svgEl; + var idElems; - var idElems = void 0; if (isOpera) { idElems = defs.find('*').filter(function () { - return !!this.id; + return Boolean(this.id); }); } else { idElems = defs.find('[id]'); @@ -20464,7 +22604,6 @@ var allElems = svgEl[0].getElementsByTagName('*'), len = allElems.length; - idElems.each(function (i) { var id = this.id; /* @@ -20475,11 +22614,8 @@ var newId = 'x' + id + svgNum + i; this.id = newId; - var oldVal = 'url(#' + id + ')'; - var newVal = 'url(#' + newId + ')'; - - // Selector method, possibly faster but fails in Opera / jQuery 1.4.3 + var newVal = 'url(#' + newId + ')'; // Selector method, possibly faster but fails in Opera / jQuery 1.4.3 // svgEl.find('[fill="url(#' + id + ')"]').each(function() { // this.setAttribute('fill', 'url(#' + newId + ')'); // }).end().find('[stroke="url(#' + id + ')"]').each(function() { @@ -20494,12 +22630,15 @@ for (i = 0; i < len; i++) { var elem = allElems[i]; + if (elem.getAttribute('fill') === oldVal) { elem.setAttribute('fill', newVal); } + if (elem.getAttribute('stroke') === oldVal) { elem.setAttribute('stroke', newVal); } + if (elem.getAttribute('filter') === oldVal) { elem.setAttribute('filter', newVal); } @@ -20507,67 +22646,42 @@ }); return svgEl; }; + /** + * @returns {undefined} + */ + function useFallback() { if (file.includes('.svgz')) { var regFile = file.replace('.svgz', '.svg'); + if (window.console) { - console.log('.svgz failed, trying with .svg'); + console.log('.svgz failed, trying with .svg'); // eslint-disable-line no-console } + $.svgIcons(regFile, opts); } else if (opts.fallback) { makeIcons(false, opts.fallback); } } - - function encode64(input) { - // base64 strings are 4/3 larger than the original string - if (window.btoa) return window.btoa(input); - var _keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; - var output = new Array(Math.floor((input.length + 2) / 3) * 4); - - var i = 0, - p = 0; - do { - var chr1 = input.charCodeAt(i++); - var chr2 = input.charCodeAt(i++); - var chr3 = input.charCodeAt(i++); - - var enc1 = chr1 >> 2; - var enc2 = (chr1 & 3) << 4 | chr2 >> 4; - - var enc3 = (chr2 & 15) << 2 | chr3 >> 6; - var 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(''); - } }; - /** * @function external:jQuery.getSvgIcon * @param {string} id * @param {boolean} uniqueClone Whether to clone * @returns {external:jQuery} The icon (optionally cloned) */ + + $.getSvgIcon = function (id, uniqueClone) { var icon = svgIcons[id]; + if (uniqueClone && icon) { icon = fixIDs(icon, 0, true).clone(true); } + return icon; }; - /** * @typedef {GenericArray} module:jQuerySVGIcons.Dimensions * @property {Integer} length 2 @@ -20585,6 +22699,8 @@ * @param {PlainObject.<string, module:jQuerySVGIcons.Size>} obj Object with selectors as keys. The values are sizes. * @returns {undefined} */ + + $.resizeSvgIcons = function (obj) { // FF2 and older don't detect .svg_icon, so we change it detect svg elems instead var changeSel = !$('.svg_icon:first').length; @@ -20592,12 +22708,15 @@ var arr = Array.isArray(size); var w = arr ? size[0] : size, h = arr ? size[1] : size; + if (changeSel) { sel = sel.replace(/\.svg_icon/g, 'svg'); } + $(sel).each(function () { this.setAttribute('width', w); this.setAttribute('height', h); + if (window.opera && window.widget) { this.parentNode.style.width = w + 'px'; this.parentNode.style.height = h + 'px'; @@ -20605,6 +22724,7 @@ }); }); }; + return $; } @@ -20632,13 +22752,13 @@ * The jQuery namespace. * @external jQuery */ + /** * The jQuery plugin namespace. * @namespace {PlainObject} fn * @memberof external:jQuery * @see {@link http://learn.jquery.com/plugins/|jQuery Plugins} */ - var ns = { svg: 'http://www.w3.org/2000/svg', xlink: 'http://www.w3.org/1999/xlink' @@ -20646,26 +22766,34 @@ if (!window.console) { window.console = { - log: function log(str) {}, - dir: function dir(str) {} + log: function log(str) { + /* */ + }, + dir: function dir(str) { + /* */ + } }; } - /** - * Adds {@link external:jQuery.jGraduate.Paint}, {@link external:jQuery.fn.jGraduateDefaults}, {@link external:jQuery.fn.jGraduate} + * Adds {@link external:jQuery.jGraduate.Paint}, + * {@link external:jQuery.fn.jGraduateDefaults}, + * {@link external:jQuery.fn.jGraduate}. * @function module:jGraduate.jGraduate * @param {external:jQuery} $ The jQuery instance to wrap * @returns {external:jQuery} */ - function jqPluginJGraduate ($) { + + + function jQueryPluginJGraduate($) { if (!$.loadingStylesheets) { $.loadingStylesheets = []; } + var stylesheet = 'jgraduate/css/jGraduate.css'; + if (!$.loadingStylesheets.includes(stylesheet)) { $.loadingStylesheets.push(stylesheet); } - /** * @typedef {PlainObject} module:jGraduate.jGraduatePaintOptions * @param {Float} [alpha] @@ -20679,16 +22807,17 @@ * @memberof module:jGraduate~ */ + var Paint = /** * @param {module:jGraduate.jGraduatePaintOptions} [opt] */ function Paint(opt) { - classCallCheck(this, Paint); + _classCallCheck(this, Paint); var options = opt || {}; - this.alpha = isNaN(options.alpha) ? 100 : options.alpha; - // copy paint object + this.alpha = isNaN(options.alpha) ? 100 : options.alpha; // copy paint object + if (options.copy) { /** * @name module:jGraduate~Paint#type @@ -20700,54 +22829,58 @@ * @name module:jGraduate~Paint#alpha * @type {Float} */ + this.alpha = options.copy.alpha; /** * Represents #RRGGBB hex of color * @name module:jGraduate~Paint#solidColor * @type {string} */ + this.solidColor = null; /** * @name module:jGraduate~Paint#linearGradient * @type {SVGLinearGradientElement} */ + this.linearGradient = null; /** * @name module:jGraduate~Paint#radialGradient * @type {SVGRadialGradientElement} */ + this.radialGradient = null; switch (this.type) { case 'none': break; + case 'solidColor': this.solidColor = options.copy.solidColor; break; + case 'linearGradient': this.linearGradient = options.copy.linearGradient.cloneNode(true); break; + case 'radialGradient': this.radialGradient = options.copy.radialGradient.cloneNode(true); break; - } - // create linear gradient paint + } // create linear gradient paint + } else if (options.linearGradient) { this.type = 'linearGradient'; this.solidColor = null; this.radialGradient = null; - this.linearGradient = options.linearGradient.cloneNode(true); - // create linear gradient paint + this.linearGradient = options.linearGradient.cloneNode(true); // create linear gradient paint } else if (options.radialGradient) { this.type = 'radialGradient'; this.solidColor = null; this.linearGradient = null; - this.radialGradient = options.radialGradient.cloneNode(true); - // create solid color paint + this.radialGradient = options.radialGradient.cloneNode(true); // create solid color paint } else if (options.solidColor) { this.type = 'solidColor'; - this.solidColor = options.solidColor; - // create empty paint + this.solidColor = options.solidColor; // create empty paint } else { this.type = 'none'; this.solidColor = null; @@ -20761,27 +22894,32 @@ */ - $.jGraduate = /** @lends external:jQuery.jGraduate */{ + $.jGraduate = + /** @lends external:jQuery.jGraduate */ + { /** * @class external:jQuery.jGraduate.Paint * @see module:jGraduate~Paint */ Paint: Paint - }; - - // JSDoc doesn't show this as belonging to our `module:jGraduate.Options` type, + }; // JSDoc doesn't show this as belonging to our `module:jGraduate.Options` type, // so we use `@see` + /** * @namespace {module:jGraduate.Options} jGraduateDefaults * @memberof external:jQuery.fn */ - $.fn.jGraduateDefaults = /** @lends external:jQuery.fn.jGraduateDefaults */{ + + $.fn.jGraduateDefaults = + /** @lends external:jQuery.fn.jGraduateDefaults */ + { /** * Creates an object with a 'none' color * @type {external:jQuery.jGraduate.Paint} * @see module:jGraduate.Options */ paint: new $.jGraduate.Paint(), + /** * @namespace */ @@ -20792,6 +22930,7 @@ */ pickerTitle: 'Drag markers to pick a paint' }, + /** * @namespace */ @@ -20802,47 +22941,74 @@ */ clientPath: 'images/' }, + /** * @type {string} * @see module:jGraduate.Options */ newstop: 'inverse' // same, inverse, black, white - }; + }; var isGecko = navigator.userAgent.includes('Gecko/'); + /** + * @typedef {PlainObject.<string, string>} module:jGraduate.Attrs + */ + + /** + * @param {SVGElement} elem + * @param {module:jGraduate.Attrs} attrs + * @returns {undefined} + */ function setAttrs(elem, attrs) { if (isGecko) { - for (var aname in attrs) { - elem.setAttribute(aname, attrs[aname]); - } + Object.entries(attrs).forEach(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + aname = _ref2[0], + val = _ref2[1]; + + elem.setAttribute(aname, val); + }); } else { - for (var _aname in attrs) { - var val = attrs[_aname], - prop = elem[_aname]; + Object.entries(attrs).forEach(function (_ref3) { + var _ref4 = _slicedToArray(_ref3, 2), + aname = _ref4[0], + val = _ref4[1]; + + var prop = elem[aname]; + if (prop && prop.constructor === 'SVGLength') { prop.baseVal.value = val; } else { - elem.setAttribute(_aname, val); + elem.setAttribute(aname, val); } - } + }); } } + /** + * @param {string} name + * @param {module:jGraduate.Attrs} attrs + * @param {Element} newparent + * @returns {SVGElement} + */ + function mkElem(name, attrs, newparent) { var elem = document.createElementNS(ns.svg, name); setAttrs(elem, attrs); + if (newparent) { newparent.append(elem); } + return elem; } - /** * @typedef {PlainObject} module:jGraduate.ColorOpac Object may have one or both values * @property {string} [color] #Hex color * @property {Float} [opac] 0-1 */ + /** * @typedef {PlainObject} module:jGraduate.Options * @property {module:jGraduate~Paint} [paint] A Paint object object describing the paint to display initially; defaults to a new instance without options (defaults to opaque white) @@ -20858,6 +23024,7 @@ * @param {external:jQuery.jGraduate.Paint} paint * @returns {undefined} */ + /** * @callback external:jQuery.fn.jGraduate.CancelCallback * @returns {undefined} @@ -20870,6 +23037,8 @@ * @param {external:jQuery.fn.jGraduate.CancelCallback} [cancelCallback] Called with no arguments when Cancel is pressed * @returns {external:jQuery} */ + + $.fn.jGraduate = function (options, okCallback, cancelCallback) { return this.each(function () { var $this = $(this), @@ -20878,7 +23047,8 @@ idref = '#' + $this.attr('id') + ' '; if (!idref) { - alert('Container element must have an id attribute to maintain unique id strings for sub-elements.'); + /* await */ + $.alert('Container element must have an id attribute to maintain unique id strings for sub-elements.'); return; } @@ -20887,108 +23057,109 @@ case 'radialGradient': $this.paint.linearGradient = null; break; + case 'linearGradient': $this.paint.radialGradient = null; break; + case 'solidColor': $this.paint.radialGradient = $this.paint.linearGradient = null; break; } + typeof $this.okCallback === 'function' && $this.okCallback($this.paint); $this.hide(); }; + var cancelClicked = function cancelClicked() { typeof $this.cancelCallback === 'function' && $this.cancelCallback(); $this.hide(); }; - $.extend(true, $this, { // public properties, methods, and callbacks + $.extend(true, $this, { + // public properties, methods, and callbacks // make a copy of the incoming paint - paint: new $.jGraduate.Paint({ copy: $settings.paint }), + paint: new $.jGraduate.Paint({ + copy: $settings.paint + }), okCallback: typeof okCallback === 'function' ? okCallback : null, cancelCallback: typeof cancelCallback === 'function' ? cancelCallback : null }); - var // pos = $this.position(), color = null; var $win = $(window); if ($this.paint.type === 'none') { - $this.paint = new $.jGraduate.Paint({ solidColor: 'ffffff' }); + $this.paint = new $.jGraduate.Paint({ + solidColor: 'ffffff' + }); } $this.addClass('jGraduate_Picker'); $this.html('<ul class="jGraduate_tabs">' + '<li class="jGraduate_tab_color jGraduate_tab_current" data-type="col">Solid Color</li>' + '<li class="jGraduate_tab_lingrad" data-type="lg">Linear Gradient</li>' + '<li class="jGraduate_tab_radgrad" data-type="rg">Radial Gradient</li>' + '</ul>' + '<div class="jGraduate_colPick"></div>' + '<div class="jGraduate_gradPick"></div>' + '<div class="jGraduate_LightBox"></div>' + '<div id="' + id + '_jGraduate_stopPicker" class="jGraduate_stopPicker"></div>'); var colPicker = $(idref + '> .jGraduate_colPick'); var gradPicker = $(idref + '> .jGraduate_gradPick'); - - gradPicker.html('<div id="' + id + '_jGraduate_Swatch" class="jGraduate_Swatch">' + '<h2 class="jGraduate_Title">' + $settings.window.pickerTitle + '</h2>' + '<div id="' + id + '_jGraduate_GradContainer" class="jGraduate_GradContainer"></div>' + '<div id="' + id + '_jGraduate_StopSlider" class="jGraduate_StopSlider"></div>' + '</div>' + '<div class="jGraduate_Form jGraduate_Points jGraduate_lg_field">' + '<div class="jGraduate_StopSection">' + '<label class="jGraduate_Form_Heading">Begin Point</label>' + '<div class="jGraduate_Form_Section">' + '<label>x:</label>' + '<input type="text" id="' + id + '_jGraduate_x1" size="3" title="Enter starting x value between 0.0 and 1.0"/>' + '<label>y:</label>' + '<input type="text" id="' + id + '_jGraduate_y1" size="3" title="Enter starting y value between 0.0 and 1.0"/>' + '</div>' + '</div>' + '<div class="jGraduate_StopSection">' + '<label class="jGraduate_Form_Heading">End Point</label>' + '<div class="jGraduate_Form_Section">' + '<label>x:</label>' + '<input type="text" id="' + id + '_jGraduate_x2" size="3" title="Enter ending x value between 0.0 and 1.0"/>' + '<label>y:</label>' + '<input type="text" id="' + id + '_jGraduate_y2" size="3" title="Enter ending y value between 0.0 and 1.0"/>' + '</div>' + '</div>' + '</div>' + '<div class="jGraduate_Form jGraduate_Points jGraduate_rg_field">' + '<div class="jGraduate_StopSection">' + '<label class="jGraduate_Form_Heading">Center Point</label>' + '<div class="jGraduate_Form_Section">' + '<label>x:</label>' + '<input type="text" id="' + id + '_jGraduate_cx" size="3" title="Enter x value between 0.0 and 1.0"/>' + '<label>y:</label>' + '<input type="text" id="' + id + '_jGraduate_cy" size="3" title="Enter y value between 0.0 and 1.0"/>' + '</div>' + '</div>' + '<div class="jGraduate_StopSection">' + '<label class="jGraduate_Form_Heading">Focal Point</label>' + '<div class="jGraduate_Form_Section">' + '<label>Match center: <input type="checkbox" checked="checked" id="' + id + '_jGraduate_match_ctr"/></label><br/>' + '<label>x:</label>' + '<input type="text" id="' + id + '_jGraduate_fx" size="3" title="Enter x value between 0.0 and 1.0"/>' + '<label>y:</label>' + '<input type="text" id="' + id + '_jGraduate_fy" size="3" title="Enter y value between 0.0 and 1.0"/>' + '</div>' + '</div>' + '</div>' + '<div class="jGraduate_StopSection jGraduate_SpreadMethod">' + '<label class="jGraduate_Form_Heading">Spread method</label>' + '<div class="jGraduate_Form_Section">' + '<select class="jGraduate_spreadMethod">' + '<option value=pad selected>Pad</option>' + '<option value=reflect>Reflect</option>' + '<option value=repeat>Repeat</option>' + '</select>' + '</div>' + '</div>' + '<div class="jGraduate_Form">' + '<div class="jGraduate_Slider jGraduate_RadiusField jGraduate_rg_field">' + '<label class="prelabel">Radius:</label>' + '<div id="' + id + '_jGraduate_Radius" class="jGraduate_SliderBar jGraduate_Radius" title="Click to set radius">' + '<img id="' + id + '_jGraduate_RadiusArrows" class="jGraduate_RadiusArrows" src="' + $settings.images.clientPath + 'rangearrows2.gif">' + '</div>' + '<label><input type="text" id="' + id + '_jGraduate_RadiusInput" size="3" value="100"/>%</label>' + '</div>' + '<div class="jGraduate_Slider jGraduate_EllipField jGraduate_rg_field">' + '<label class="prelabel">Ellip:</label>' + '<div id="' + id + '_jGraduate_Ellip" class="jGraduate_SliderBar jGraduate_Ellip" title="Click to set Ellip">' + '<img id="' + id + '_jGraduate_EllipArrows" class="jGraduate_EllipArrows" src="' + $settings.images.clientPath + 'rangearrows2.gif">' + '</div>' + '<label><input type="text" id="' + id + '_jGraduate_EllipInput" size="3" value="0"/>%</label>' + '</div>' + '<div class="jGraduate_Slider jGraduate_AngleField jGraduate_rg_field">' + '<label class="prelabel">Angle:</label>' + '<div id="' + id + '_jGraduate_Angle" class="jGraduate_SliderBar jGraduate_Angle" title="Click to set Angle">' + '<img id="' + id + '_jGraduate_AngleArrows" class="jGraduate_AngleArrows" src="' + $settings.images.clientPath + 'rangearrows2.gif">' + '</div>' + '<label><input type="text" id="' + id + '_jGraduate_AngleInput" size="3" value="0"/>deg</label>' + '</div>' + '<div class="jGraduate_Slider jGraduate_OpacField">' + '<label class="prelabel">Opac:</label>' + '<div id="' + id + '_jGraduate_Opac" class="jGraduate_SliderBar jGraduate_Opac" title="Click to set Opac">' + '<img id="' + id + '_jGraduate_OpacArrows" class="jGraduate_OpacArrows" src="' + $settings.images.clientPath + 'rangearrows2.gif">' + '</div>' + '<label><input type="text" id="' + id + '_jGraduate_OpacInput" size="3" value="100"/>%</label>' + '</div>' + '</div>' + '<div class="jGraduate_OkCancel">' + '<input type="button" id="' + id + '_jGraduate_Ok" class="jGraduate_Ok" value="OK"/>' + '<input type="button" id="' + id + '_jGraduate_Cancel" class="jGraduate_Cancel" value="Cancel"/>' + '</div>'); - - // -------------- + gradPicker.html('<div id="' + id + '_jGraduate_Swatch" class="jGraduate_Swatch">' + '<h2 class="jGraduate_Title">' + $settings.window.pickerTitle + '</h2>' + '<div id="' + id + '_jGraduate_GradContainer" class="jGraduate_GradContainer"></div>' + '<div id="' + id + '_jGraduate_StopSlider" class="jGraduate_StopSlider"></div>' + '</div>' + '<div class="jGraduate_Form jGraduate_Points jGraduate_lg_field">' + '<div class="jGraduate_StopSection">' + '<label class="jGraduate_Form_Heading">Begin Point</label>' + '<div class="jGraduate_Form_Section">' + '<label>x:</label>' + '<input type="text" id="' + id + '_jGraduate_x1" size="3" title="Enter starting x value between 0.0 and 1.0"/>' + '<label>y:</label>' + '<input type="text" id="' + id + '_jGraduate_y1" size="3" title="Enter starting y value between 0.0 and 1.0"/>' + '</div>' + '</div>' + '<div class="jGraduate_StopSection">' + '<label class="jGraduate_Form_Heading">End Point</label>' + '<div class="jGraduate_Form_Section">' + '<label>x:</label>' + '<input type="text" id="' + id + '_jGraduate_x2" size="3" title="Enter ending x value between 0.0 and 1.0"/>' + '<label>y:</label>' + '<input type="text" id="' + id + '_jGraduate_y2" size="3" title="Enter ending y value between 0.0 and 1.0"/>' + '</div>' + '</div>' + '</div>' + '<div class="jGraduate_Form jGraduate_Points jGraduate_rg_field">' + '<div class="jGraduate_StopSection">' + '<label class="jGraduate_Form_Heading">Center Point</label>' + '<div class="jGraduate_Form_Section">' + '<label>x:</label>' + '<input type="text" id="' + id + '_jGraduate_cx" size="3" title="Enter x value between 0.0 and 1.0"/>' + '<label>y:</label>' + '<input type="text" id="' + id + '_jGraduate_cy" size="3" title="Enter y value between 0.0 and 1.0"/>' + '</div>' + '</div>' + '<div class="jGraduate_StopSection">' + '<label class="jGraduate_Form_Heading">Focal Point</label>' + '<div class="jGraduate_Form_Section">' + '<label>Match center: <input type="checkbox" checked="checked" id="' + id + '_jGraduate_match_ctr"/></label><br/>' + '<label>x:</label>' + '<input type="text" id="' + id + '_jGraduate_fx" size="3" title="Enter x value between 0.0 and 1.0"/>' + '<label>y:</label>' + '<input type="text" id="' + id + '_jGraduate_fy" size="3" title="Enter y value between 0.0 and 1.0"/>' + '</div>' + '</div>' + '</div>' + '<div class="jGraduate_StopSection jGraduate_SpreadMethod">' + '<label class="jGraduate_Form_Heading">Spread method</label>' + '<div class="jGraduate_Form_Section">' + '<select class="jGraduate_spreadMethod">' + '<option value=pad selected>Pad</option>' + '<option value=reflect>Reflect</option>' + '<option value=repeat>Repeat</option>' + '</select>' + '</div>' + '</div>' + '<div class="jGraduate_Form">' + '<div class="jGraduate_Slider jGraduate_RadiusField jGraduate_rg_field">' + '<label class="prelabel">Radius:</label>' + '<div id="' + id + '_jGraduate_Radius" class="jGraduate_SliderBar jGraduate_Radius" title="Click to set radius">' + '<img id="' + id + '_jGraduate_RadiusArrows" class="jGraduate_RadiusArrows" src="' + $settings.images.clientPath + 'rangearrows2.gif">' + '</div>' + '<label><input type="text" id="' + id + '_jGraduate_RadiusInput" size="3" value="100"/>%</label>' + '</div>' + '<div class="jGraduate_Slider jGraduate_EllipField jGraduate_rg_field">' + '<label class="prelabel">Ellip:</label>' + '<div id="' + id + '_jGraduate_Ellip" class="jGraduate_SliderBar jGraduate_Ellip" title="Click to set Ellip">' + '<img id="' + id + '_jGraduate_EllipArrows" class="jGraduate_EllipArrows" src="' + $settings.images.clientPath + 'rangearrows2.gif">' + '</div>' + '<label><input type="text" id="' + id + '_jGraduate_EllipInput" size="3" value="0"/>%</label>' + '</div>' + '<div class="jGraduate_Slider jGraduate_AngleField jGraduate_rg_field">' + '<label class="prelabel">Angle:</label>' + '<div id="' + id + '_jGraduate_Angle" class="jGraduate_SliderBar jGraduate_Angle" title="Click to set Angle">' + '<img id="' + id + '_jGraduate_AngleArrows" class="jGraduate_AngleArrows" src="' + $settings.images.clientPath + 'rangearrows2.gif">' + '</div>' + '<label><input type="text" id="' + id + '_jGraduate_AngleInput" size="3" value="0"/>deg</label>' + '</div>' + '<div class="jGraduate_Slider jGraduate_OpacField">' + '<label class="prelabel">Opac:</label>' + '<div id="' + id + '_jGraduate_Opac" class="jGraduate_SliderBar jGraduate_Opac" title="Click to set Opac">' + '<img id="' + id + '_jGraduate_OpacArrows" class="jGraduate_OpacArrows" src="' + $settings.images.clientPath + 'rangearrows2.gif">' + '</div>' + '<label><input type="text" id="' + id + '_jGraduate_OpacInput" size="3" value="100"/>%</label>' + '</div>' + '</div>' + '<div class="jGraduate_OkCancel">' + '<input type="button" id="' + id + '_jGraduate_Ok" class="jGraduate_Ok" value="OK"/>' + '<input type="button" id="' + id + '_jGraduate_Cancel" class="jGraduate_Cancel" value="Cancel"/>' + '</div>'); // -------------- // Set up all the SVG elements (the gradient, stops and rectangle) + var MAX = 256, MARGINX = 0, MARGINY = 0, - - // STOP_RADIUS = 15 / 2, + // STOP_RADIUS = 15 / 2, SIZEX = MAX - 2 * MARGINX, SIZEY = MAX - 2 * MARGINY; - var attrInput = {}; - var SLIDERW = 145; $('.jGraduate_SliderBar').width(SLIDERW); - var container = $('#' + id + '_jGraduate_GradContainer')[0]; - var svg = mkElem('svg', { id: id + '_jgraduate_svg', width: MAX, height: MAX, xmlns: ns.svg - }, container); - - // This wasn't working as designed + }, container); // This wasn't working as designed // let curType; // curType = curType || $this.paint.type; - // if we are sent a gradient, import it - var curType = $this.paint.type; + var curType = $this.paint.type; var grad = $this.paint[curType]; var curGradient = grad; - var gradalpha = $this.paint.alpha; + var isSolid = curType === 'solidColor'; // Make any missing gradients - var isSolid = curType === 'solidColor'; - - // Make any missing gradients switch (curType) { - case 'solidColor': - // fall through + case 'solidColor': // fall through + case 'linearGradient': if (!isSolid) { curGradient.id = id + '_lg_jgraduate_grad'; grad = curGradient = svg.appendChild(curGradient); // .cloneNode(true)); } + mkElem('radialGradient', { id: id + '_rg_jgraduate_grad' }, svg); + if (curType === 'linearGradient') { break; } + // fall through + case 'radialGradient': if (!isSolid) { curGradient.id = id + '_rg_jgraduate_grad'; grad = curGradient = svg.appendChild(curGradient); // .cloneNode(true)); } + mkElem('linearGradient', { id: id + '_lg_jgraduate_grad' }, svg); } - var stopGroup = void 0; // eslint-disable-line prefer-const + var stopGroup; // eslint-disable-line prefer-const + if (isSolid) { grad = curGradient = $('#' + id + '_lg_jgraduate_grad')[0]; color = $this.paint[curType]; @@ -21003,16 +23174,20 @@ break; case 'inverse': - // Invert current color for second stop - var inverted = ''; - for (var i = 0; i < 6; i += 2) { - // const ch = color.substr(i, 2); - var inv = (255 - parseInt(color.substr(i, 2), 16)).toString(16); - if (inv.length < 2) inv = 0 + inv; - inverted += inv; + { + // Invert current color for second stop + var inverted = ''; + + for (var i = 0; i < 6; i += 2) { + // const ch = color.substr(i, 2); + var inv = (255 - parseInt(color.substr(i, 2), 16)).toString(16); + if (inv.length < 2) inv = 0 + inv; + inverted += inv; + } + + mkStop(1, '#' + inverted, 1); + break; } - mkStop(1, '#' + inverted, 1); - break; case 'white': mkStop(1, '#ffffff', 1); @@ -21032,12 +23207,10 @@ y1 = parseFloat(grad.getAttribute('y1') || 0.0), x2 = parseFloat(grad.getAttribute('x2') || 1.0), y2 = parseFloat(grad.getAttribute('y2') || 0.0); - var cx = parseFloat(grad.getAttribute('cx') || 0.5), cy = parseFloat(grad.getAttribute('cy') || 0.5), fx = parseFloat(grad.getAttribute('fx') || cx), fy = parseFloat(grad.getAttribute('fy') || cy); - var previewRect = mkElem('rect', { id: id + '_jgraduate_rect', x: MARGINX, @@ -21046,9 +23219,8 @@ height: SIZEY, fill: 'url(#' + id + '_jgraduate_grad)', 'fill-opacity': gradalpha / 100 - }, svg); + }, svg); // stop visuals created here - // stop visuals created here var beginCoord = $('<div/>').attr({ class: 'grad_coord jGraduate_lg_field', title: 'Begin Stop' @@ -21056,12 +23228,10 @@ top: y1 * MAX, left: x1 * MAX }).data('coord', 'start').appendTo(container); - var endCoord = beginCoord.clone().text(2).css({ top: y2 * MAX, left: x2 * MAX }).attr('title', 'End stop').data('coord', 'end').appendTo(container); - var centerCoord = $('<div/>').attr({ class: 'grad_coord jGraduate_rg_field', title: 'Center stop' @@ -21069,17 +23239,12 @@ top: cy * MAX, left: cx * MAX }).data('coord', 'center').appendTo(container); - var focusCoord = centerCoord.clone().text('F').css({ top: fy * MAX, left: fx * MAX, display: 'none' }).attr('title', 'Focus point').data('coord', 'focus').appendTo(container); - - focusCoord[0].id = id + '_jGraduate_focusCoord'; - - // const coords = $(idref + ' .grad_coord'); - + focusCoord[0].id = id + '_jGraduate_focusCoord'; // const coords = $(idref + ' .grad_coord'); // $(container).hover(function () { // coords.animate({ // opacity: 1 @@ -21090,11 +23255,11 @@ // }, 500); // }); - var showFocus = void 0; + var showFocus; $.each(['x1', 'y1', 'x2', 'y2', 'cx', 'cy', 'fx', 'fy'], function (i, attr) { var isRadial = isNaN(attr[1]); - var attrval = curGradient.getAttribute(attr); + if (!attrval) { // Set defaults if (isRadial) { @@ -21121,41 +23286,50 @@ } var $elem = isRadial ? attr[0] === 'c' ? centerCoord : focusCoord : attr[1] === '1' ? beginCoord : endCoord; - var cssName = attr.includes('x') ? 'left' : 'top'; - $elem.css(cssName, this.value * MAX); }).change(); }); + /** + * + * @param {Float} n + * @param {Float|string} colr + * @param {Float} opac + * @param {boolean} [sel] + * @param {SVGStopElement} [stopElem] + * @returns {SVGStopElement} + */ + + function mkStop(n, colr, opac, sel, stopElem) { + var stop = stopElem || mkElem('stop', { + 'stop-color': colr, + 'stop-opacity': opac, + offset: n + }, curGradient); - function mkStop(n, color, opac, sel, stopElem) { - var stop = stopElem || mkElem('stop', { 'stop-color': color, 'stop-opacity': opac, offset: n }, curGradient); if (stopElem) { - color = stopElem.getAttribute('stop-color'); + colr = stopElem.getAttribute('stop-color'); opac = stopElem.getAttribute('stop-opacity'); n = stopElem.getAttribute('offset'); } else { curGradient.append(stop); } + if (opac === null) opac = 1; - var pickerD = 'M-6.2,0.9c3.6-4,6.7-4.3,6.7-12.4c-0.2,7.9,3.1,8.8,6.5,12.4c3.5,3.8,2.9,9.6,0,12.3c-3.1,2.8-10.4,2.7-13.2,0C-9.6,9.9-9.4,4.4-6.2,0.9z'; - var pathbg = mkElem('path', { d: pickerD, fill: 'url(#jGraduate_trans)', transform: 'translate(' + (10 + n * MAX) + ', 26)' }, stopGroup); - var path = mkElem('path', { d: pickerD, - fill: color, + fill: colr, 'fill-opacity': opac, transform: 'translate(' + (10 + n * MAX) + ', 26)', stroke: '#000', 'stroke-width': 1.5 }, stopGroup); - $(path).mousedown(function (e) { selectStop(this); drag = curStop; @@ -21165,21 +23339,34 @@ return false; }).data('stop', stop).data('bg', pathbg).dblclick(function () { $('div.jGraduate_LightBox').show(); - var colorhandle = this; - var stopOpacity = +stop.getAttribute('stop-opacity') || 1; + var colorhandle = this; // eslint-disable-line consistent-this + + var stopOpacity = Number(stop.getAttribute('stop-opacity')) || 1; var stopColor = stop.getAttribute('stop-color') || 1; var thisAlpha = (parseFloat(stopOpacity) * 255).toString(16); + while (thisAlpha.length < 2) { thisAlpha = '0' + thisAlpha; } - color = stopColor.substr(1) + thisAlpha; - $('#' + id + '_jGraduate_stopPicker').css({ left: 100, bottom: 15 }).jPicker({ - window: { title: 'Pick the start color and opacity for the gradient' }, - images: { clientPath: $settings.images.clientPath }, - color: { active: color, alphaSupport: true } - }, function (color, arg2) { - stopColor = color.val('hex') ? '#' + color.val('hex') : 'none'; - stopOpacity = color.val('a') !== null ? color.val('a') / 256 : 1; + + colr = stopColor.substr(1) + thisAlpha; + $('#' + id + '_jGraduate_stopPicker').css({ + left: 100, + bottom: 15 + }).jPicker({ + window: { + title: 'Pick the start color and opacity for the gradient' + }, + images: { + clientPath: $settings.images.clientPath + }, + color: { + active: colr, + alphaSupport: true + } + }, function (clr, arg2) { + stopColor = clr.val('hex') ? '#' + clr.val('hex') : 'none'; + stopOpacity = clr.val('a') !== null ? clr.val('a') / 256 : 1; colorhandle.setAttribute('fill', stopColor); colorhandle.setAttribute('fill-opacity', stopOpacity); stop.setAttribute('stop-color', stopColor); @@ -21191,11 +23378,11 @@ $('#' + id + '_jGraduate_stopPicker').hide(); }); }); - $(curGradient).find('stop').each(function () { var curS = $(this); - if (+this.getAttribute('offset') > n) { - if (!color) { + + if (Number(this.getAttribute('offset')) > n) { + if (!colr) { var newcolor = this.getAttribute('stop-color'); var newopac = this.getAttribute('stop-opacity'); stop.setAttribute('stop-color', newcolor); @@ -21203,13 +23390,21 @@ stop.setAttribute('stop-opacity', newopac === null ? 1 : newopac); path.setAttribute('fill-opacity', newopac === null ? 1 : newopac); } + curS.before(stop); return false; } + + return true; }); if (sel) selectStop(path); return stop; } + /** + * + * @returns {undefined} + */ + function remStop() { delStop.setAttribute('display', 'none'); @@ -21220,11 +23415,7 @@ } var stopMakerDiv = $('#' + id + '_jGraduate_StopSlider'); - - var stops = void 0, - curStop = void 0, - drag = void 0; - + var stops, curStop, drag; var delStop = mkElem('path', { d: 'm9.75,-6l-19.5,19.5m0,-19.5l19.5,19.5', fill: 'none', @@ -21233,51 +23424,69 @@ display: 'none' }, undefined); // stopMakerSVG); + /** + * @param {Element} item + * @returns {undefined} + */ + function selectStop(item) { if (curStop) curStop.setAttribute('stroke', '#000'); item.setAttribute('stroke', 'blue'); curStop = item; - curStop.parentNode.append(curStop); - // stops = $('stop'); + curStop.parentNode.append(curStop); // stops = $('stop'); // opac_select.val(curStop.attr('fill-opacity') || 1); // root.append(delStop); } - var stopOffset = void 0; + var stopOffset; + /** + * + * @returns {undefined} + */ function remDrags() { $win.unbind('mousemove', dragColor); + if (delStop.getAttribute('display') !== 'none') { remStop(); } + drag = null; } var scaleX = 1, scaleY = 1, angle = 0; - var cX = cx; var cY = cy; + /** + * + * @returns {undefined} + */ + function xform() { var rot = angle ? 'rotate(' + angle + ',' + cX + ',' + cY + ') ' : ''; + if (scaleX === 1 && scaleY === 1) { - curGradient.removeAttribute('gradientTransform'); - // $('#ang').addClass('dis'); + curGradient.removeAttribute('gradientTransform'); // $('#ang').addClass('dis'); } else { var x = -cX * (scaleX - 1); var y = -cY * (scaleY - 1); - curGradient.setAttribute('gradientTransform', rot + 'translate(' + x + ',' + y + ') scale(' + scaleX + ',' + scaleY + ')'); - // $('#ang').removeClass('dis'); + curGradient.setAttribute('gradientTransform', rot + 'translate(' + x + ',' + y + ') scale(' + scaleX + ',' + scaleY + ')'); // $('#ang').removeClass('dis'); } } + /** + * @param {Event} evt + * @returns {undefined} + */ + function dragColor(evt) { var x = evt.pageX - stopOffset.left; var y = evt.pageY - stopOffset.top; x = x < 10 ? 10 : x > MAX + 10 ? MAX + 10 : x; - var xfStr = 'translate(' + x + ', 26)'; + if (y < -60 || y > 130) { delStop.setAttribute('display', 'block'); delStop.setAttribute('transform', xfStr); @@ -21289,17 +23498,17 @@ $.data(drag, 'bg').setAttribute('transform', xfStr); var stop = $.data(drag, 'stop'); var sX = (x - 10) / MAX; - stop.setAttribute('offset', sX); - var last = 0; $(curGradient).find('stop').each(function (i) { var cur = this.getAttribute('offset'); var t = $(this); + if (cur < last) { t.prev().before(t); stops = $(curGradient).find('stop'); } + last = cur; }); } @@ -21308,40 +23517,31 @@ width: '100%', height: 45 }, stopMakerDiv[0]); - var transPattern = mkElem('pattern', { width: 16, height: 16, patternUnits: 'userSpaceOnUse', id: 'jGraduate_trans' }, stopMakerSVG); - var transImg = mkElem('image', { width: 16, height: 16 }, transPattern); - var bgImage = $settings.images.clientPath + 'map-opacity.png'; - transImg.setAttributeNS(ns.xlink, 'xlink:href', bgImage); - $(stopMakerSVG).click(function (evt) { stopOffset = stopMakerDiv.offset(); var target = evt.target; - if (target.tagName === 'path') return; var x = evt.pageX - stopOffset.left - 8; x = x < 10 ? 10 : x > MAX + 10 ? MAX + 10 : x; mkStop(x / MAX, 0, 0, true); evt.stopPropagation(); }); - $(stopMakerSVG).mouseover(function () { stopMakerSVG.append(delStop); }); - stopGroup = mkElem('g', {}, stopMakerSVG); - mkElem('line', { x1: 10, y1: 15, @@ -21350,58 +23550,55 @@ 'stroke-width': 2, stroke: '#000' }, stopMakerSVG); - var spreadMethodOpt = gradPicker.find('.jGraduate_spreadMethod').change(function () { curGradient.setAttribute('spreadMethod', $(this).val()); - }); + }); // handle dragging the stop around the swatch - // handle dragging the stop around the swatch var draggingCoord = null; var onCoordDrag = function onCoordDrag(evt) { var x = evt.pageX - offset.left; - var y = evt.pageY - offset.top; + var y = evt.pageY - offset.top; // clamp stop to the swatch - // clamp stop to the swatch x = x < 0 ? 0 : x > MAX ? MAX : x; y = y < 0 ? 0 : y > MAX ? MAX : y; + draggingCoord.css('left', x).css('top', y); // calculate stop offset - draggingCoord.css('left', x).css('top', y); - - // calculate stop offset var fracx = x / SIZEX; var fracy = y / SIZEY; - var type = draggingCoord.data('coord'); - var grad = curGradient; + var grd = curGradient; switch (type) { case 'start': attrInput.x1.val(fracx); attrInput.y1.val(fracy); - grad.setAttribute('x1', fracx); - grad.setAttribute('y1', fracy); + grd.setAttribute('x1', fracx); + grd.setAttribute('y1', fracy); break; + case 'end': attrInput.x2.val(fracx); attrInput.y2.val(fracy); - grad.setAttribute('x2', fracx); - grad.setAttribute('y2', fracy); + grd.setAttribute('x2', fracx); + grd.setAttribute('y2', fracy); break; + case 'center': attrInput.cx.val(fracx); attrInput.cy.val(fracy); - grad.setAttribute('cx', fracx); - grad.setAttribute('cy', fracy); + grd.setAttribute('cx', fracx); + grd.setAttribute('cy', fracy); cX = fracx; cY = fracy; xform(); break; + case 'focus': attrInput.fx.val(fracx); attrInput.fy.val(fracy); - grad.setAttribute('fx', fracx); - grad.setAttribute('fy', fracy); + grd.setAttribute('fx', fracx); + grd.setAttribute('fy', fracy); xform(); } @@ -21411,20 +23608,19 @@ var onCoordUp = function onCoordUp() { draggingCoord = null; $win.unbind('mousemove', onCoordDrag).unbind('mouseup', onCoordUp); - }; - - // Linear gradient + }; // Linear gradient // (function () { - stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); - var numstops = stops.length; - // if there are not at least two stops, then + stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); + var numstops = stops.length; // if there are not at least two stops, then + if (numstops < 2) { while (numstops < 2) { curGradient.append(document.createElementNS(ns.svg, 'stop')); ++numstops; } + stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); } @@ -21433,23 +23629,18 @@ } spreadMethodOpt.val(curGradient.getAttribute('spreadMethod') || 'pad'); + var offset; // No match, so show focus point - var offset = void 0; - - // No match, so show focus point showFocus = false; - previewRect.setAttribute('fill-opacity', gradalpha / 100); - $('#' + id + ' div.grad_coord').mousedown(function (evt) { evt.preventDefault(); - draggingCoord = $(this); - // const sPos = draggingCoord.offset(); + draggingCoord = $(this); // const sPos = draggingCoord.offset(); + offset = draggingCoord.parent().offset(); $win.mousemove(onCoordDrag).mouseup(onCoordUp); - }); + }); // bind GUI elements - // bind GUI elements $('#' + id + '_jGraduate_Ok').bind('click', function () { $this.paint.type = curType; $this.paint[curType] = curGradient.cloneNode(true); @@ -21471,50 +23662,47 @@ } $('#' + id + '_jGraduate_match_ctr')[0].checked = !showFocus; - - var lastfx = void 0, - lastfy = void 0; - + var lastfx, lastfy; $('#' + id + '_jGraduate_match_ctr').change(function () { showFocus = !this.checked; focusCoord.toggle(showFocus); attrInput.fx.val(''); attrInput.fy.val(''); - var grad = curGradient; + var grd = curGradient; + if (!showFocus) { - lastfx = grad.getAttribute('fx'); - lastfy = grad.getAttribute('fy'); - grad.removeAttribute('fx'); - grad.removeAttribute('fy'); + lastfx = grd.getAttribute('fx'); + lastfy = grd.getAttribute('fy'); + grd.removeAttribute('fx'); + grd.removeAttribute('fy'); } else { - var _fx = lastfx || 0.5; - var _fy = lastfy || 0.5; - grad.setAttribute('fx', _fx); - grad.setAttribute('fy', _fy); - attrInput.fx.val(_fx); - attrInput.fy.val(_fy); + var fX = lastfx || 0.5; + var fY = lastfy || 0.5; + grd.setAttribute('fx', fX); + grd.setAttribute('fy', fY); + attrInput.fx.val(fX); + attrInput.fy.val(fY); } }); - stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); - numstops = stops.length; - // if there are not at least two stops, then + numstops = stops.length; // if there are not at least two stops, then + if (numstops < 2) { while (numstops < 2) { curGradient.append(document.createElementNS(ns.svg, 'stop')); ++numstops; } + stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); } - var slider = void 0; + var slider; var setSlider = function setSlider(e) { var _slider = slider, - offset = _slider.offset; - + left = _slider.offset.left; var div = slider.parent; - var x = e.pageX - offset.left - parseInt(div.css('border-left-width')); + var x = e.pageX - left - parseInt(div.css('border-left-width')); if (x > SLIDERW) x = SLIDERW; if (x <= 0) x = 0; var posx = x - 5; @@ -21527,35 +23715,47 @@ if (x <= 0.01) x = 0.01; curGradient.setAttribute('r', x); break; + case 'opacity': $this.paint.alpha = parseInt(x * 100); previewRect.setAttribute('fill-opacity', x); break; + case 'ellip': scaleX = 1; scaleY = 1; + if (x < 0.5) { x /= 0.5; // 0.001 + scaleX = x <= 0 ? 0.01 : x; } else if (x > 0.5) { x /= 0.5; // 2 + x = 2 - x; scaleY = x <= 0 ? 0.01 : x; } + xform(); x -= 1; + if (scaleY === x + 1) { x = Math.abs(x); } + break; + case 'angle': - x = x - 0.5; + x -= 0.5; angle = x *= 180; xform(); x /= 100; break; } - slider.elem.css({ 'margin-left': posx }); + + slider.elem.css({ + 'margin-left': posx + }); x = Math.round(x * 100); slider.input.val(x); }; @@ -21565,11 +23765,14 @@ if (curType === 'radialGradient') { var tlist = curGradient.gradientTransform.baseVal; + if (tlist.numberOfItems === 2) { var t = tlist.getItem(0); var s = tlist.getItem(1); + if (t.type === 2 && s.type === 3) { var m = s.matrix; + if (m.a !== 1) { ellipVal = Math.round(-(1 - m.a) * 100); } else if (m.d !== 1) { @@ -21579,12 +23782,15 @@ } else if (tlist.numberOfItems === 3) { // Assume [R][T][S] var r = tlist.getItem(0); + var _t = tlist.getItem(1); + var _s = tlist.getItem(2); if (r.type === 4 && _t.type === 2 && _s.type === 3) { angleVal = Math.round(r.angle); var _m = _s.matrix; + if (_m.a !== 1) { ellipVal = Math.round(-(1 - _m.a) * 100); } else if (_m.d !== 1) { @@ -21616,7 +23822,6 @@ val: angleVal } }; - $.each(sliders, function (type, data) { var handle = $(data.handle); handle.mousedown(function (evt) { @@ -21631,11 +23836,11 @@ $win.mousemove(dragSlider).mouseup(stopSlider); evt.preventDefault(); }); - $(data.input).val(data.val).change(function () { var isRad = curType === 'radialGradient'; - var val = +this.value; + var val = Number(this.value); var xpos = 0; + switch (type) { case 'radius': if (isRad) curGradient.setAttribute('r', val / 100); @@ -21650,11 +23855,14 @@ case 'ellip': scaleX = scaleY = 1; + if (val === 0) { xpos = SLIDERW * 0.5; break; } + if (val > 99.5) val = 99.5; + if (val > 0) { scaleY = 1 - val / 100; } else { @@ -21672,12 +23880,16 @@ xpos *= SLIDERW; if (isRad) xform(); } + if (xpos > SLIDERW) { xpos = SLIDERW; } else if (xpos < 0) { xpos = 0; } - handle.css({ 'margin-left': xpos - 5 }); + + handle.css({ + 'margin-left': xpos - 5 + }); }).change(); }); @@ -21689,59 +23901,68 @@ var stopSlider = function stopSlider(evt) { $win.unbind('mousemove', dragSlider).unbind('mouseup', stopSlider); slider = null; - }; + }; // -------------- + - // -------------- var thisAlpha = ($this.paint.alpha * 255 / 100).toString(16); + while (thisAlpha.length < 2) { thisAlpha = '0' + thisAlpha; } + thisAlpha = thisAlpha.split('.')[0]; color = $this.paint.solidColor === 'none' ? '' : $this.paint.solidColor + thisAlpha; if (!isSolid) { color = stops[0].getAttribute('stop-color'); - } + } // This should be done somewhere else, probably + - // This should be done somewhere else, probably $.extend($.fn.jPicker.defaults.window, { - alphaSupport: true, effects: { type: 'show', speed: 0 } + alphaSupport: true, + effects: { + type: 'show', + speed: 0 + } }); - colPicker.jPicker({ - window: { title: $settings.window.pickerTitle }, - images: { clientPath: $settings.images.clientPath }, - color: { active: color, alphaSupport: true } - }, function (color) { + window: { + title: $settings.window.pickerTitle + }, + images: { + clientPath: $settings.images.clientPath + }, + color: { + active: color, + alphaSupport: true + } + }, function (clr) { $this.paint.type = 'solidColor'; - $this.paint.alpha = color.val('ahex') ? Math.round(color.val('a') / 255 * 100) : 100; - $this.paint.solidColor = color.val('hex') ? color.val('hex') : 'none'; + $this.paint.alpha = clr.val('ahex') ? Math.round(clr.val('a') / 255 * 100) : 100; + $this.paint.solidColor = clr.val('hex') ? clr.val('hex') : 'none'; $this.paint.radialGradient = null; okClicked(); }, null, function () { cancelClicked(); }); - var tabs = $(idref + ' .jGraduate_tabs li'); tabs.click(function () { tabs.removeClass('jGraduate_tab_current'); $(this).addClass('jGraduate_tab_current'); $(idref + ' > div').hide(); var type = $(this).attr('data-type'); - /* const container = */$(idref + ' .jGraduate_gradPick').show(); + /* const container = */ + + $(idref + ' .jGraduate_gradPick').show(); + if (type === 'rg' || type === 'lg') { // Show/hide appropriate fields $('.jGraduate_' + type + '_field').show(); $('.jGraduate_' + (type === 'lg' ? 'rg' : 'lg') + '_field').hide(); - - $('#' + id + '_jgraduate_rect')[0].setAttribute('fill', 'url(#' + id + '_' + type + '_jgraduate_grad)'); - - // Copy stops + $('#' + id + '_jgraduate_rect')[0].setAttribute('fill', 'url(#' + id + '_' + type + '_jgraduate_grad)'); // Copy stops curType = type === 'lg' ? 'linearGradient' : 'radialGradient'; - $('#' + id + '_jGraduate_OpacInput').val($this.paint.alpha).change(); - var newGrad = $('#' + id + '_' + type + '_jgraduate_grad')[0]; if (curGradient !== newGrad) { @@ -21751,8 +23972,10 @@ var sm = spreadMethodOpt.val(); curGradient.setAttribute('spreadMethod', sm); } - showFocus = type === 'rg' && curGradient.getAttribute('fx') != null && !(cx === fx && cy === fy); + + showFocus = type === 'rg' && curGradient.getAttribute('fx') !== null && !(cx === fx && cy === fy); $('#' + id + '_jGraduate_focusCoord').toggle(showFocus); + if (showFocus) { $('#' + id + '_jGraduate_match_ctr')[0].checked = false; } @@ -21763,26 +23986,30 @@ }); $(idref + ' > div').hide(); tabs.removeClass('jGraduate_tab_current'); - var tab = void 0; + var tab; + switch ($this.paint.type) { case 'linearGradient': tab = $(idref + ' .jGraduate_tab_lingrad'); break; + case 'radialGradient': tab = $(idref + ' .jGraduate_tab_radgrad'); break; + default: tab = $(idref + ' .jGraduate_tab_color'); break; } - $this.show(); - // jPicker will try to show after a 0ms timeout, so need to fire this after that + $this.show(); // jPicker will try to show after a 0ms timeout, so need to fire this after that + setTimeout(function () { tab.addClass('jGraduate_tab_current').click(); }, 10); }); }; + return $; } @@ -21856,34 +24083,41 @@ $("#myInputElement").SpinButton(myOptions); }); */ + /** * @function module:jQuerySpinButton.jQuerySpinButton * @param {external:jQuery} $ The jQuery object to which to add the plug-in * @returns {external:jQuery} */ - function jqPluginSpinBtn ($) { + function jQueryPluginSpinButton($) { if (!$.loadingStylesheets) { $.loadingStylesheets = []; } + var stylesheet = 'spinbtn/jQuery.SpinButton.css'; + if (!$.loadingStylesheets.includes(stylesheet)) { $.loadingStylesheets.push(stylesheet); } /** * @callback module:jQuerySpinButton.StepCallback * @param {external:jQuery} thisArg Value of `this` + * @param {Float} i Value to adjust + * @returns {Float} */ + /** * @callback module:jQuerySpinButton.ValueCallback - * @param {external:jQuery} thisArg Value of `this` - * @param {Float} value Value that was changed + * @param {external:jQuery.fn.SpinButton} thisArg Spin Button; check its `value` to see how it was changed. + * @returns {undefined} */ + /** * @typedef {PlainObject} module:jQuerySpinButton.SpinButtonConfig * @property {Float} min Set lower limit * @property {Float} max Set upper limit. * @property {Float} step Set increment size. - * @property {module:jQuerySpinButton.StepCallback} stepfunc Custom function to run when changing a value; called with `this` of object and the value to adjust + * @property {module:jQuerySpinButton.StepCallback} stepfunc Custom function to run when changing a value; called with `this` of object and the value to adjust and returns a float. * @property {module:jQuerySpinButton.ValueCallback} callback Called after value adjusted (with `this` of object) * @property {Float} smallStep Set shift-click increment size. * @property {PlainObject} stateObj Object to allow passing in live-updating scale @@ -21896,17 +24130,27 @@ * @property {Float} delay Millisecond delay * @property {Float} interval Millisecond interval */ + /** * @function external:jQuery.fn.SpinButton * @param {module:jQuerySpinButton.SpinButtonConfig} cfg * @returns {external:jQuery} */ + + $.fn.SpinButton = function (cfg) { cfg = cfg || {}; + /** + * + * @param {Element} el + * @param {"offsetLeft"|"offsetTop"} prop + * @returns {Integer} + */ + function coord(el, prop) { var b = document.body; - var c = el[prop]; + while ((el = el.offsetParent) && el !== b) { if (!$.browser.msie || el.currentStyle.position !== 'relative') { c += el[prop]; @@ -21917,14 +24161,14 @@ } return this.each(function () { - this.repeating = false; - - // Apply specified options or defaults: + this.repeating = false; // Apply specified options or defaults: // (Ought to refactor this some day to use $.extend() instead) + this.spinCfg = { // min: cfg.min ? Number(cfg.min) : null, // max: cfg.max ? Number(cfg.max) : null, - min: !isNaN(parseFloat(cfg.min)) ? Number(cfg.min) : null, // Fixes bug with min:0 + min: !isNaN(parseFloat(cfg.min)) ? Number(cfg.min) : null, + // Fixes bug with min:0 max: !isNaN(parseFloat(cfg.max)) ? Number(cfg.max) : null, step: cfg.step ? Number(cfg.step) : 1, stepfunc: cfg.stepfunc || false, @@ -21939,13 +24183,13 @@ _delay: null, _repeat: null, callback: cfg.callback || null - }; + }; // if a smallStep isn't supplied, use half the regular step - // if a smallStep isn't supplied, use half the regular step this.spinCfg.smallStep = cfg.smallStep || this.spinCfg.step / 2; this.adjustValue = function (i) { - var v = void 0; + var v; + if (isNaN(this.value)) { v = this.spinCfg.reset; } else if (typeof this.spinCfg.stepfunc === 'function') { @@ -21954,13 +24198,17 @@ // weirdest JavaScript bug ever: 5.1 + 0.1 = 5.199999999 v = Number((Number(this.value) + Number(i)).toFixed(5)); } + if (this.spinCfg.min !== null) { v = Math.max(v, this.spinCfg.min); } + if (this.spinCfg.max !== null) { v = Math.min(v, this.spinCfg.max); } + this.value = v; + if (typeof this.spinCfg.callback === 'function') { this.spinCfg.callback(this); } @@ -21973,7 +24221,6 @@ var el = e.target; var scale = cfg.stateObj.tool_scale || 1; var height = $(el).height() / 2; - var direction = x > coord(el, 'offsetLeft') + el.offsetWidth * scale - this.spinCfg._btn_width ? y < coord(el, 'offsetTop') + height * scale ? 1 : -1 : 0; if (direction !== this.spinCfg._direction) { @@ -21983,16 +24230,18 @@ // Up arrow: $(this).removeClass(this.spinCfg.downClass).addClass(this.spinCfg.upClass); break; + case -1: // Down arrow: $(this).removeClass(this.spinCfg.upClass).addClass(this.spinCfg.downClass); break; + default: // Mouse is elsewhere in the textbox $(this).removeClass(this.spinCfg.upClass).removeClass(this.spinCfg.downClass); - } + } // Set spin direction: + - // Set spin direction: this.spinCfg._direction = direction; } }).mouseout(function () { @@ -22012,12 +24261,11 @@ _this.adjustValue(_this.spinCfg._direction * stepSize); }; - adjust(); + adjust(); // Initial delay before repeating adjustment - // Initial delay before repeating adjustment this.spinCfg._delay = window.setTimeout(function () { - adjust(); - // Repeat adjust at regular intervals + adjust(); // Repeat adjust at regular intervals + _this.spinCfg._repeat = window.setInterval(adjust, _this.spinCfg.interval); }, this.spinCfg.delay); } @@ -22033,16 +24281,26 @@ // Respond to up/down arrow keys. switch (e.keyCode) { case 38: - this.adjustValue(this.spinCfg.step);break; // Up + this.adjustValue(this.spinCfg.step); + break; + // Up + case 40: - this.adjustValue(-this.spinCfg.step);break; // Down + this.adjustValue(-this.spinCfg.step); + break; + // Down + case 33: - this.adjustValue(this.spinCfg.page);break; // PageUp + this.adjustValue(this.spinCfg.page); + break; + // PageUp + case 34: - this.adjustValue(-this.spinCfg.page);break; // PageDown + this.adjustValue(-this.spinCfg.page); + break; + // PageDown } }) - /* http://unixpapa.com/js/key.html describes the current state-of-affairs for key repeat events: @@ -22054,30 +24312,46 @@ // Respond to up/down arrow keys. switch (e.keyCode) { case 38: - this.adjustValue(this.spinCfg.step);break; // Up + this.adjustValue(this.spinCfg.step); + break; + // Up + case 40: - this.adjustValue(-this.spinCfg.step);break; // Down + this.adjustValue(-this.spinCfg.step); + break; + // Down + case 33: - this.adjustValue(this.spinCfg.page);break; // PageUp + this.adjustValue(this.spinCfg.page); + break; + // PageUp + case 34: - this.adjustValue(-this.spinCfg.page);break; // PageDown - } - // we always ignore the first keypress event (use the keydown instead) + this.adjustValue(-this.spinCfg.page); + break; + // PageDown + } // we always ignore the first keypress event (use the keydown instead) + } else { this.repeating = true; } - }) - - // clear the 'repeating' flag + }) // clear the 'repeating' flag .keyup(function (e) { this.repeating = false; + switch (e.keyCode) { case 38: // Up + case 40: // Down + case 33: // PageUp + case 34: // PageDown + case 13: - this.adjustValue(0);break; // Enter/Return + this.adjustValue(0); + break; + // Enter/Return } }).bind('mousewheel', function (e) { // Respond to mouse wheel in IE. (It returns up/dn motion in multiples of 120) @@ -22102,10 +24376,11 @@ } e.preventDefault(); - }, false); + }); } }); }; + return $; } @@ -22128,9 +24403,8 @@ * and the MIT License and is copyright A Beautiful Site, LLC. * */ - /** - * @callback module:jQueryContextMenu.jQueryContextMenuCallback + * @callback module:jQueryContextMenu.jQueryContextMenuListener * @param {string} href The `href` value after the first character (for bypassing an initial `#`) * @param {external:jQuery} srcElement The wrapped jQuery srcElement * @param {{x: Float, y: Float, docX: Float, docY: Float}} coords @@ -22145,135 +24419,149 @@ */ /** - * Adds {@link external:jQuery.fn.contextMenu}, {@link external:jQuery.fn.disableContextMenuItems}, {@link external:jQuery.fn.enableContextMenuItems}, {@link external:jQuery.fn.disableContextMenu}, {@link external:jQuery.fn.enableContextMenu}, {@link external:jQuery.fn.destroyContextMenu} + * Adds {@link external:jQuery.fn.contextMenu}, + * {@link external:jQuery.fn.disableContextMenuItems}, + * {@link external:jQuery.fn.enableContextMenuItems}, + * {@link external:jQuery.fn.disableContextMenu}, + * {@link external:jQuery.fn.enableContextMenu}, + * {@link external:jQuery.fn.destroyContextMenu}. * @function module:jQueryContextMenu.jQueryContextMenu * @param {external:jQuery} $ The jQuery object to wrap (with `contextMenu`, `disableContextMenuItems`, `enableContextMenuItems`, `disableContextMenu`, `enableContextMenu`, `destroyContextMenu`) * @returns {external:jQuery} */ + function jQueryContextMenu($) { var win = $(window); var doc = $(document); - $.extend($.fn, { /** * @memberof external:jQuery.fn * @param {module:jQueryContextMenu.jQueryContextMenuConfig} o - * @param {module:jQueryContextMenu.jQueryContextMenuCallback} callback + * @param {module:jQueryContextMenu.jQueryContextMenuListener} listener * @returns {external:jQuery} */ - contextMenu: function contextMenu(o, callback) { + contextMenu: function contextMenu(o, listener) { // Defaults if (o.menu === undefined) return false; if (o.inSpeed === undefined) o.inSpeed = 150; - if (o.outSpeed === undefined) o.outSpeed = 75; - // 0 needs to be -1 for expected results (no fade) + if (o.outSpeed === undefined) o.outSpeed = 75; // 0 needs to be -1 for expected results (no fade) + if (o.inSpeed === 0) o.inSpeed = -1; - if (o.outSpeed === 0) o.outSpeed = -1; - // Loop each context menu + if (o.outSpeed === 0) o.outSpeed = -1; // Loop each context menu + $(this).each(function () { var el = $(this); var offset = $(el).offset(); + var menu = $('#' + o.menu); // Add contextMenu class - var menu = $('#' + o.menu); + menu.addClass('contextMenu'); // Simulate a true right click - // Add contextMenu class - menu.addClass('contextMenu'); - // Simulate a true right click - $(this).bind('mousedown', function (e) { - var evt = e; + $(this).bind('mousedown', function (evt) { $(this).mouseup(function (e) { var srcElement = $(this); srcElement.unbind('mouseup'); - if (evt.button === 2 || o.allowLeft || evt.ctrlKey && isMac()) { - e.stopPropagation(); - // Hide context menus that may be showing + + if (!(evt.button === 2 || o.allowLeft || evt.ctrlKey && isMac())) { + return undefined; + } + + e.stopPropagation(); // Hide context menus that may be showing + + $('.contextMenu').hide(); // Get this context menu + + if (el.hasClass('disabled')) return false; // Detect mouse position + + var x = e.pageX, + y = e.pageY; + var xOff = win.width() - menu.width(), + yOff = win.height() - menu.height(); + if (x > xOff - 15) x = xOff - 15; + if (y > yOff - 30) y = yOff - 30; // 30 is needed to prevent scrollbars in FF + // Show the menu + + doc.unbind('click'); + menu.css({ + top: y, + left: x + }).fadeIn(o.inSpeed); // Hover events + + menu.find('A').mouseover(function () { + menu.find('LI.hover').removeClass('hover'); + $(this).parent().addClass('hover'); + }).mouseout(function () { + menu.find('LI.hover').removeClass('hover'); + }); // Keyboard + + doc.keypress(function (ev) { + switch (ev.keyCode) { + case 38: + // up + if (!menu.find('LI.hover').length) { + menu.find('LI:last').addClass('hover'); + } else { + menu.find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover'); + if (!menu.find('LI.hover').length) menu.find('LI:last').addClass('hover'); + } + + break; + + case 40: + // down + if (!menu.find('LI.hover').length) { + menu.find('LI:first').addClass('hover'); + } else { + menu.find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover'); + if (!menu.find('LI.hover').length) menu.find('LI:first').addClass('hover'); + } + + break; + + case 13: + // enter + menu.find('LI.hover A').trigger('click'); + break; + + case 27: + // esc + doc.trigger('click'); + break; + } + }); // When items are selected + + menu.find('A').unbind('mouseup'); + menu.find('LI:not(.disabled) A').mouseup(function () { + doc.unbind('click').unbind('keypress'); $('.contextMenu').hide(); - // Get this context menu - if (el.hasClass('disabled')) return false; + if (listener) { + listener($(this).attr('href').substr(1), $(srcElement), { + x: x - offset.left, + y: y - offset.top, + docX: x, + docY: y + }); + } - // Detect mouse position - var x = e.pageX, - y = e.pageY; + return false; + }); // Hide bindings - var xOff = win.width() - menu.width(), - yOff = win.height() - menu.height(); - - if (x > xOff - 15) x = xOff - 15; - if (y > yOff - 30) y = yOff - 30; // 30 is needed to prevent scrollbars in FF - - // Show the menu - doc.unbind('click'); - menu.css({ top: y, left: x }).fadeIn(o.inSpeed); - // Hover events - menu.find('A').mouseover(function () { - menu.find('LI.hover').removeClass('hover'); - $(this).parent().addClass('hover'); - }).mouseout(function () { - menu.find('LI.hover').removeClass('hover'); - }); - - // Keyboard - doc.keypress(function (e) { - switch (e.keyCode) { - case 38: - // up - if (!menu.find('LI.hover').length) { - menu.find('LI:last').addClass('hover'); - } else { - menu.find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover'); - if (!menu.find('LI.hover').length) menu.find('LI:last').addClass('hover'); - } - break; - case 40: - // down - if (!menu.find('LI.hover').length) { - menu.find('LI:first').addClass('hover'); - } else { - menu.find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover'); - if (!menu.find('LI.hover').length) menu.find('LI:first').addClass('hover'); - } - break; - case 13: - // enter - menu.find('LI.hover A').trigger('click'); - break; - case 27: - // esc - doc.trigger('click'); - break; - } - }); - - // When items are selected - menu.find('A').unbind('mouseup'); - menu.find('LI:not(.disabled) A').mouseup(function () { + setTimeout(function () { + // Delay for Mozilla + doc.click(function () { doc.unbind('click').unbind('keypress'); - $('.contextMenu').hide(); - // Callback - if (callback) { - callback($(this).attr('href').substr(1), $(srcElement), { x: x - offset.left, y: y - offset.top, docX: x, docY: y }); - } + menu.fadeOut(o.outSpeed); return false; }); - - // Hide bindings - setTimeout(function () { - // Delay for Mozilla - doc.click(function () { - doc.unbind('click').unbind('keypress'); - menu.fadeOut(o.outSpeed); - return false; - }); - }, 0); - } + }, 0); + return undefined; }); - }); + }); // Disable text selection - // Disable text selection if ($.browser.mozilla) { $('#' + o.menu).each(function () { - $(this).css({ MozUserSelect: 'none' }); + $(this).css({ + MozUserSelect: 'none' + }); }); } else if ($.browser.msie) { $('#' + o.menu).each(function () { @@ -22287,8 +24575,9 @@ return false; }); }); - } - // Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome) + } // Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome) + + $(el).add($('UL.contextMenu')).bind('contextmenu', function () { return false; }); @@ -22296,9 +24585,8 @@ return $(this); }, - /** - * Disable context menu items on the fly + * Disable context menu items on the fly. * @memberof external:jQuery.fn * @param {undefined|string} o Comma-separated * @returns {external:jQuery} @@ -22309,9 +24597,11 @@ $(this).find('LI').addClass('disabled'); return $(this); } + $(this).each(function () { if (o !== undefined) { var d = o.split(','); + for (var i = 0; i < d.length; i++) { $(this).find('A[href="' + d[i] + '"]').parent().addClass('disabled'); } @@ -22320,9 +24610,8 @@ return $(this); }, - /** - * Enable context menu items on the fly + * Enable context menu items on the fly. * @memberof external:jQuery.fn * @param {undefined|string} o Comma-separated * @returns {external:jQuery} @@ -22333,9 +24622,11 @@ $(this).find('LI.disabled').removeClass('disabled'); return $(this); } + $(this).each(function () { if (o !== undefined) { var d = o.split(','); + for (var i = 0; i < d.length; i++) { $(this).find('A[href="' + d[i] + '"]').parent().removeClass('disabled'); } @@ -22344,9 +24635,8 @@ return $(this); }, - /** - * Disable context menu(s) + * Disable context menu(s). * @memberof external:jQuery.fn * @returns {external:jQuery} */ @@ -22357,9 +24647,8 @@ return $(this); }, - /** - * Enable context menu(s) + * Enable context menu(s). * @memberof external:jQuery.fn * @returns {external:jQuery} */ @@ -22370,9 +24659,8 @@ return $(this); }, - /** - * Destroy context menu(s) + * Destroy context menu(s). * @memberof external:jQuery.fn * @returns {external:jQuery} */ @@ -22388,6 +24676,8 @@ return $; } + /* eslint-disable no-bitwise */ + /** * jPicker (Adapted from version 1.1.6) * @@ -22408,22 +24698,34 @@ /** * @external Math */ + /** * @memberof external:Math * @param {Float} value * @param {Float} precision * @returns {Float} */ - Math.precision = function (value, precision) { + function toFixedNumeric(value, precision) { if (precision === undefined) precision = 0; return Math.round(value * Math.pow(10, precision)) / Math.pow(10, precision); - }; + } + /** + * Whether a value is `null` or `undefined`. + * @param {Any} val + * @returns {boolean} + */ + + var isNullish$1 = function isNullish(val) { + return val === null || val === undefined; + }; /** * @function module:jPicker.jPicker * @param {external:jQuery} $ The jQuery object to wrap (with {@link external:jQuery.loadingStylesheets}, {@link external:jQuery.fn.$.fn.jPicker}, {@link external:jQuery.fn.$.fn.jPicker.defaults}) * @returns {external:jQuery} */ + + var jPicker = function jPicker($) { if (!$.loadingStylesheets) { /** @@ -22433,7 +24735,9 @@ */ $.loadingStylesheets = []; } + var stylesheet = 'jgraduate/css/jPicker.css'; + if (!$.loadingStylesheets.includes(stylesheet)) { $.loadingStylesheets.push(stylesheet); } @@ -22450,59 +24754,107 @@ /** * Encapsulate slider functionality for the ColorMap and ColorBar - - * could be useful to use a jQuery UI draggable for this with certain extensions + * could be useful to use a jQuery UI draggable for this with certain extensions. + * @memberof module:jPicker * @param {external:jQuery} bar * @param {module:jPicker.SliderOptions} options + * @returns {undefined} */ - function Slider(bar, options) { - var $this = this; + + + var Slider = function Slider(bar, options) { + _classCallCheck(this, Slider); + + var that = this; + /** + * Fire events on the supplied `context` + * @param {module:jPicker.JPickerInit} context + * @returns {undefined} + */ + function fireChangeEvents(context) { - for (var i = 0; i < changeEvents.length; i++) { - changeEvents[i].call($this, $this, context); - } + changeEvents.forEach(function (changeEvent) { + changeEvent.call(that, that, context); + }); } - // bind the mousedown to the bar not the arrow for quick snapping to the clicked location + /** + * Bind the mousedown to the bar not the arrow for quick snapping to the clicked location. + * @param {external:jQuery.Event} e + * @returns {undefined} + */ + + function mouseDown(e) { var off = bar.offset(); - offset = { l: off.left | 0, t: off.top | 0 }; - clearTimeout(timeout); - // using setTimeout for visual updates - once the style is updated the browser will re-render internally allowing the next Javascript to run + offset = { + l: off.left | 0, + t: off.top | 0 + }; + clearTimeout(timeout); // using setTimeout for visual updates - once the style is updated the browser will re-render internally allowing the next Javascript to run + timeout = setTimeout(function () { - setValuesFromMousePosition.call($this, e); - }, 0); - // Bind mousemove and mouseup event to the document so it responds when dragged of of the bar - we will unbind these when on mouseup to save processing + setValuesFromMousePosition.call(that, e); + }, 0); // Bind mousemove and mouseup event to the document so it responds when dragged of of the bar - we will unbind these when on mouseup to save processing + $(document).bind('mousemove', mouseMove).bind('mouseup', mouseUp); e.preventDefault(); // don't try to select anything or drag the image to the desktop } - // set the values as the mouse moves + /** + * Set the values as the mouse moves. + * @param {external:jQuery.Event} e + * @returns {false} + */ + + function mouseMove(e) { clearTimeout(timeout); timeout = setTimeout(function () { - setValuesFromMousePosition.call($this, e); + setValuesFromMousePosition.call(that, e); }, 0); e.stopPropagation(); e.preventDefault(); return false; } - // unbind the document events - they aren't needed when not dragging + /** + * Unbind the document events - they aren't needed when not dragging. + * @param {external:jQuery.Event} e + * @returns {false} + */ + + function mouseUp(e) { $(document).unbind('mouseup', mouseUp).unbind('mousemove', mouseMove); e.stopPropagation(); e.preventDefault(); return false; } - // calculate mouse position and set value within the current range + /** + * Calculate mouse position and set value within the current range. + * @param {Event} e + * @returns {undefined} + */ + + function setValuesFromMousePosition(e) { var barW = bar.w, // local copies for YUI compressor barH = bar.h; var locX = e.pageX - offset.l, - locY = e.pageY - offset.t; - // keep the arrow within the bounds of the bar + locY = e.pageY - offset.t; // keep the arrow within the bounds of the bar + if (locX < 0) locX = 0;else if (locX > barW) locX = barW; if (locY < 0) locY = 0;else if (locY > barH) locY = barH; - val.call($this, 'xy', { x: locX / barW * rangeX + minX, y: locY / barH * rangeY + minY }); + val.call(that, 'xy', { + x: locX / barW * rangeX + minX, + y: locY / barH * rangeY + minY + }); } + /** + * + * @returns {undefined} + */ + + function draw() { var barW = bar.w, barH = bar.h, @@ -22516,118 +24868,201 @@ // constrain to bounds if (x === maxX) arrowOffsetX = barW;else arrowOffsetX = x / rangeX * barW | 0; } + if (rangeY > 0) { // range is greater than zero // constrain to bounds if (y === maxY) arrowOffsetY = barH;else arrowOffsetY = y / rangeY * barH | 0; - } - // if arrow width is greater than bar width, center arrow and prevent horizontal dragging + } // if arrow width is greater than bar width, center arrow and prevent horizontal dragging + + if (arrowW >= barW) arrowOffsetX = (barW >> 1) - (arrowW >> 1); // number >> 1 - superfast bitwise divide by two and truncate (move bits over one bit discarding lowest) - else arrowOffsetX -= arrowW >> 1; - // if arrow height is greater than bar height, center arrow and prevent vertical dragging - if (arrowH >= barH) arrowOffsetY = (barH >> 1) - (arrowH >> 1);else arrowOffsetY -= arrowH >> 1; - // set the arrow position based on these offsets - arrow.css({ left: arrowOffsetX + 'px', top: arrowOffsetY + 'px' }); - }, 0); + else arrowOffsetX -= arrowW >> 1; // if arrow height is greater than bar height, center arrow and prevent vertical dragging + + if (arrowH >= barH) arrowOffsetY = (barH >> 1) - (arrowH >> 1);else arrowOffsetY -= arrowH >> 1; // set the arrow position based on these offsets + + arrow.css({ + left: arrowOffsetX + 'px', + top: arrowOffsetY + 'px' + }); + }); } + /** + * Get or set a value. + * @param {?("xy"|"x"|"y")} name + * @param {module:math.XYObject} value + * @param {module:jPicker.Slider} context + * @returns {module:math.XYObject|Float|undefined} + */ + + function val(name, value, context) { - var set$$1 = value !== undefined; - if (!set$$1) { - if (name === undefined || name == null) name = 'xy'; + var set = value !== undefined; + + if (!set) { + if (isNullish$1(name)) name = 'xy'; + switch (name.toLowerCase()) { case 'x': return x; + case 'y': return y; + case 'xy': default: - return { x: x, y: y }; + return { + x: x, + y: y + }; } } - if (context != null && context === $this) return; - var changed = false; - var newX = void 0, - newY = void 0; - if (name == null) name = 'xy'; + if (!isNullish$1(context) && context === that) return undefined; + var changed = false; + var newX, newY; + if (isNullish$1(name)) name = 'xy'; + switch (name.toLowerCase()) { case 'x': newX = value && (value.x && value.x | 0 || value | 0) || 0; break; + case 'y': newY = value && (value.y && value.y | 0 || value | 0) || 0; break; + case 'xy': default: newX = value && value.x && value.x | 0 || 0; newY = value && value.y && value.y | 0 || 0; break; } - if (newX != null) { + + if (!isNullish$1(newX)) { if (newX < minX) newX = minX;else if (newX > maxX) newX = maxX; + if (x !== newX) { x = newX; changed = true; } } - if (newY != null) { + + if (!isNullish$1(newY)) { if (newY < minY) newY = minY;else if (newY > maxY) newY = maxY; + if (y !== newY) { y = newY; changed = true; } } - changed && fireChangeEvents.call($this, context || $this); + + changed && fireChangeEvents.call(that, context || that); + return undefined; } + /** + * @typedef {PlainObject} module:jPicker.MinMaxRangeX + * @property {Float} minX + * @property {Float} maxX + * @property {Float} rangeX + */ + + /** + * @typedef {PlainObject} module:jPicker.MinMaxRangeY + * @property {Float} minY + * @property {Float} maxY + * @property {Float} rangeY + */ + + /** + * @typedef {module:jPicker.MinMaxRangeY|module:jPicker.MinMaxRangeX} module:jPicker.MinMaxRangeXY + */ + + /** + * + * @param {"minx"|"maxx"|"rangex"|"miny"|"maxy"|"rangey"|"all"} name + * @param {module:jPicker.MinMaxRangeXY} value + * @returns {module:jPicker.MinMaxRangeXY|module:jPicker.MinMaxRangeX|module:jPicker.MinMaxRangeY|undefined} + */ + + function range(name, value) { - var set$$1 = value !== undefined; - if (!set$$1) { - if (name === undefined || name == null) name = 'all'; + var set = value !== undefined; + + if (!set) { + if (isNullish$1(name)) name = 'all'; + switch (name.toLowerCase()) { case 'minx': return minX; + case 'maxx': return maxX; + case 'rangex': - return { minX: minX, maxX: maxX, rangeX: rangeX }; + return { + minX: minX, + maxX: maxX, + rangeX: rangeX + }; + case 'miny': return minY; + case 'maxy': return maxY; + case 'rangey': - return { minY: minY, maxY: maxY, rangeY: rangeY }; + return { + minY: minY, + maxY: maxY, + rangeY: rangeY + }; + case 'all': default: - return { minX: minX, maxX: maxX, rangeX: rangeX, minY: minY, maxY: maxY, rangeY: rangeY }; + return { + minX: minX, + maxX: maxX, + rangeX: rangeX, + minY: minY, + maxY: maxY, + rangeY: rangeY + }; } } + var // changed = false, - newMinX = void 0, - newMaxX = void 0, - newMinY = void 0, - newMaxY = void 0; - if (name == null) name = 'all'; + newMinX, newMaxX, newMinY, newMaxY; + if (isNullish$1(name)) name = 'all'; + switch (name.toLowerCase()) { case 'minx': newMinX = value && (value.minX && value.minX | 0 || value | 0) || 0; break; + case 'maxx': newMaxX = value && (value.maxX && value.maxX | 0 || value | 0) || 0; break; + case 'rangex': newMinX = value && value.minX && value.minX | 0 || 0; newMaxX = value && value.maxX && value.maxX | 0 || 0; break; + case 'miny': newMinY = value && (value.minY && value.minY | 0 || value | 0) || 0; break; + case 'maxy': newMaxY = value && (value.maxY && value.maxY | 0 || value | 0) || 0; break; + case 'rangey': newMinY = value && value.minY && value.minY | 0 || 0; newMaxY = value && value.maxY && value.maxY | 0 || 0; break; + case 'all': default: newMinX = value && value.minX && value.minX | 0 || 0; @@ -22636,33 +25071,60 @@ newMaxY = value && value.maxY && value.maxY | 0 || 0; break; } - if (newMinX != null && minX !== newMinX) { + + if (!isNullish$1(newMinX) && minX !== newMinX) { minX = newMinX; rangeX = maxX - minX; } - if (newMaxX != null && maxX !== newMaxX) { + + if (!isNullish$1(newMaxX) && maxX !== newMaxX) { maxX = newMaxX; rangeX = maxX - minX; } - if (newMinY != null && minY !== newMinY) { + + if (!isNullish$1(newMinY) && minY !== newMinY) { minY = newMinY; rangeY = maxY - minY; } - if (newMaxY != null && maxY !== newMaxY) { + + if (!isNullish$1(newMaxY) && maxY !== newMaxY) { maxY = newMaxY; rangeY = maxY - minY; } + + return undefined; } + /** + * @param {GenericCallback} callback + * @returns {undefined} + */ + + function bind(callback) { + // eslint-disable-line promise/prefer-await-to-callbacks if (typeof callback === 'function') changeEvents.push(callback); } + /** + * @param {GenericCallback} callback + * @returns {undefined} + */ + + function unbind(callback) { + // eslint-disable-line promise/prefer-await-to-callbacks if (typeof callback !== 'function') return; - var i = void 0; + var i; + while (i = changeEvents.includes(callback)) { changeEvents.splice(i, 1); } } + /** + * + * @returns {undefined} + */ + + function destroy() { // unbind all possible events and null objects $(document).unbind('mouseup', mouseUp).unbind('mousemove', mouseMove); @@ -22671,8 +25133,9 @@ arrow = null; changeEvents = null; } - var offset = void 0, - timeout = void 0, + + var offset, + timeout, x = 0, y = 0, minX = 0, @@ -22684,197 +25147,285 @@ arrow = bar.find('img:first'), // the arrow image to drag changeEvents = []; - - $.extend(true, $this, // public properties, methods, and event bindings - these we need to access from other controls - { + $.extend(true, // public properties, methods, and event bindings - these we need + // to access from other controls + that, { val: val, range: range, bind: bind, unbind: unbind, destroy: destroy - }); - // initialize this control + }); // initialize this control + arrow.src = options.arrow && options.arrow.image; arrow.w = options.arrow && options.arrow.width || arrow.width(); arrow.h = options.arrow && options.arrow.height || arrow.height(); bar.w = options.map && options.map.width || bar.width(); - bar.h = options.map && options.map.height || bar.height(); - // bind mousedown event + bar.h = options.map && options.map.height || bar.height(); // bind mousedown event + bar.bind('mousedown', mouseDown); - bind.call($this, draw); - } - // controls for all the input elements for the typing in color values - function ColorValuePicker(picker, color, bindedHex, alphaPrecision) { - var $this = this; // private properties and methods - var inputs = picker.find('td.Text input'); - // input box key down - use arrows to alter color + bind.call(that, draw); + }; + /** + * Controls for all the input elements for the typing in color values. + * @param {external:jQuery} picker + * @param {external:jQuery.jPicker.Color} color + * @param {external:jQuery.fn.$.fn.jPicker} bindedHex + * @param {Float} alphaPrecision + * @constructor + */ + + + var ColorValuePicker = function ColorValuePicker(picker, color, bindedHex, alphaPrecision) { + _classCallCheck(this, ColorValuePicker); + + var that = this; // private properties and methods + + var inputs = picker.find('td.Text input'); // input box key down - use arrows to alter color + + /** + * + * @param {Event} e + * @returns {Event|false|undefined} + */ + function keyDown(e) { - if (e.target.value === '' && e.target !== hex.get(0) && (bindedHex != null && e.target !== bindedHex.get(0) || bindedHex == null)) return; + if (e.target.value === '' && e.target !== hex.get(0) && (!isNullish$1(bindedHex) && e.target !== bindedHex.get(0) || isNullish$1(bindedHex))) return undefined; if (!validateKey(e)) return e; + switch (e.target) { case red.get(0): switch (e.keyCode) { case 38: - red.val(setValueInRange.call($this, (red.val() << 0) + 1, 0, 255)); + red.val(setValueInRange.call(that, (red.val() << 0) + 1, 0, 255)); color.val('r', red.val(), e.target); return false; + case 40: - red.val(setValueInRange.call($this, (red.val() << 0) - 1, 0, 255)); + red.val(setValueInRange.call(that, (red.val() << 0) - 1, 0, 255)); color.val('r', red.val(), e.target); return false; } + break; + case green.get(0): switch (e.keyCode) { case 38: - green.val(setValueInRange.call($this, (green.val() << 0) + 1, 0, 255)); + green.val(setValueInRange.call(that, (green.val() << 0) + 1, 0, 255)); color.val('g', green.val(), e.target); return false; + case 40: - green.val(setValueInRange.call($this, (green.val() << 0) - 1, 0, 255)); + green.val(setValueInRange.call(that, (green.val() << 0) - 1, 0, 255)); color.val('g', green.val(), e.target); return false; } + break; + case blue.get(0): switch (e.keyCode) { case 38: - blue.val(setValueInRange.call($this, (blue.val() << 0) + 1, 0, 255)); + blue.val(setValueInRange.call(that, (blue.val() << 0) + 1, 0, 255)); color.val('b', blue.val(), e.target); return false; + case 40: - blue.val(setValueInRange.call($this, (blue.val() << 0) - 1, 0, 255)); + blue.val(setValueInRange.call(that, (blue.val() << 0) - 1, 0, 255)); color.val('b', blue.val(), e.target); return false; } + break; + case alpha && alpha.get(0): switch (e.keyCode) { case 38: - alpha.val(setValueInRange.call($this, parseFloat(alpha.val()) + 1, 0, 100)); - color.val('a', Math.precision(alpha.val() * 255 / 100, alphaPrecision), e.target); + alpha.val(setValueInRange.call(that, parseFloat(alpha.val()) + 1, 0, 100)); + color.val('a', toFixedNumeric(alpha.val() * 255 / 100, alphaPrecision), e.target); return false; + case 40: - alpha.val(setValueInRange.call($this, parseFloat(alpha.val()) - 1, 0, 100)); - color.val('a', Math.precision(alpha.val() * 255 / 100, alphaPrecision), e.target); + alpha.val(setValueInRange.call(that, parseFloat(alpha.val()) - 1, 0, 100)); + color.val('a', toFixedNumeric(alpha.val() * 255 / 100, alphaPrecision), e.target); return false; } + break; + case hue.get(0): switch (e.keyCode) { case 38: - hue.val(setValueInRange.call($this, (hue.val() << 0) + 1, 0, 360)); + hue.val(setValueInRange.call(that, (hue.val() << 0) + 1, 0, 360)); color.val('h', hue.val(), e.target); return false; + case 40: - hue.val(setValueInRange.call($this, (hue.val() << 0) - 1, 0, 360)); + hue.val(setValueInRange.call(that, (hue.val() << 0) - 1, 0, 360)); color.val('h', hue.val(), e.target); return false; } + break; + case saturation.get(0): switch (e.keyCode) { case 38: - saturation.val(setValueInRange.call($this, (saturation.val() << 0) + 1, 0, 100)); + saturation.val(setValueInRange.call(that, (saturation.val() << 0) + 1, 0, 100)); color.val('s', saturation.val(), e.target); return false; + case 40: - saturation.val(setValueInRange.call($this, (saturation.val() << 0) - 1, 0, 100)); + saturation.val(setValueInRange.call(that, (saturation.val() << 0) - 1, 0, 100)); color.val('s', saturation.val(), e.target); return false; } + break; + case value.get(0): switch (e.keyCode) { case 38: - value.val(setValueInRange.call($this, (value.val() << 0) + 1, 0, 100)); + value.val(setValueInRange.call(that, (value.val() << 0) + 1, 0, 100)); color.val('v', value.val(), e.target); return false; + case 40: - value.val(setValueInRange.call($this, (value.val() << 0) - 1, 0, 100)); + value.val(setValueInRange.call(that, (value.val() << 0) - 1, 0, 100)); color.val('v', value.val(), e.target); return false; } + break; } - } - // input box key up - validate value and set color + + return undefined; + } // input box key up - validate value and set color + + /** + * @param {Event} e + * @returns {Event|undefined} + * @todo Why is this returning an event? + */ + + function keyUp(e) { - if (e.target.value === '' && e.target !== hex.get(0) && (bindedHex != null && e.target !== bindedHex.get(0) || bindedHex == null)) return; + if (e.target.value === '' && e.target !== hex.get(0) && (!isNullish$1(bindedHex) && e.target !== bindedHex.get(0) || isNullish$1(bindedHex))) return undefined; if (!validateKey(e)) return e; + switch (e.target) { case red.get(0): - red.val(setValueInRange.call($this, red.val(), 0, 255)); + red.val(setValueInRange.call(that, red.val(), 0, 255)); color.val('r', red.val(), e.target); break; + case green.get(0): - green.val(setValueInRange.call($this, green.val(), 0, 255)); + green.val(setValueInRange.call(that, green.val(), 0, 255)); color.val('g', green.val(), e.target); break; + case blue.get(0): - blue.val(setValueInRange.call($this, blue.val(), 0, 255)); + blue.val(setValueInRange.call(that, blue.val(), 0, 255)); color.val('b', blue.val(), e.target); break; + case alpha && alpha.get(0): - alpha.val(setValueInRange.call($this, alpha.val(), 0, 100)); - color.val('a', Math.precision(alpha.val() * 255 / 100, alphaPrecision), e.target); + alpha.val(setValueInRange.call(that, alpha.val(), 0, 100)); + color.val('a', toFixedNumeric(alpha.val() * 255 / 100, alphaPrecision), e.target); break; + case hue.get(0): - hue.val(setValueInRange.call($this, hue.val(), 0, 360)); + hue.val(setValueInRange.call(that, hue.val(), 0, 360)); color.val('h', hue.val(), e.target); break; + case saturation.get(0): - saturation.val(setValueInRange.call($this, saturation.val(), 0, 100)); + saturation.val(setValueInRange.call(that, saturation.val(), 0, 100)); color.val('s', saturation.val(), e.target); break; + case value.get(0): - value.val(setValueInRange.call($this, value.val(), 0, 100)); + value.val(setValueInRange.call(that, value.val(), 0, 100)); color.val('v', value.val(), e.target); break; + case hex.get(0): hex.val(hex.val().replace(/[^a-fA-F0-9]/g, '').toLowerCase().substring(0, 6)); bindedHex && bindedHex.val(hex.val()); color.val('hex', hex.val() !== '' ? hex.val() : null, e.target); break; + case bindedHex && bindedHex.get(0): bindedHex.val(bindedHex.val().replace(/[^a-fA-F0-9]/g, '').toLowerCase().substring(0, 6)); hex.val(bindedHex.val()); color.val('hex', bindedHex.val() !== '' ? bindedHex.val() : null, e.target); break; + case ahex && ahex.get(0): ahex.val(ahex.val().replace(/[^a-fA-F0-9]/g, '').toLowerCase().substring(0, 2)); - color.val('a', ahex.val() != null ? parseInt(ahex.val(), 16) : null, e.target); + color.val('a', !isNullish$1(ahex.val()) ? parseInt(ahex.val(), 16) : null, e.target); break; } - } - // input box blur - reset to original if value empty + + return undefined; + } // input box blur - reset to original if value empty + + /** + * @param {Event} e + * @returns {undefined} + */ + + function blur(e) { - if (color.val() != null) { + if (!isNullish$1(color.val())) { switch (e.target) { case red.get(0): - red.val(color.val('r'));break; + red.val(color.val('r')); + break; + case green.get(0): - green.val(color.val('g'));break; + green.val(color.val('g')); + break; + case blue.get(0): - blue.val(color.val('b'));break; + blue.val(color.val('b')); + break; + case alpha && alpha.get(0): - alpha.val(Math.precision(color.val('a') * 100 / 255, alphaPrecision));break; + alpha.val(toFixedNumeric(color.val('a') * 100 / 255, alphaPrecision)); + break; + case hue.get(0): - hue.val(color.val('h'));break; + hue.val(color.val('h')); + break; + case saturation.get(0): - saturation.val(color.val('s'));break; + saturation.val(color.val('s')); + break; + case value.get(0): - value.val(color.val('v'));break; + value.val(color.val('v')); + break; + case hex.get(0): case bindedHex && bindedHex.get(0): hex.val(color.val('hex')); bindedHex && bindedHex.val(color.val('hex')); break; + case ahex && ahex.get(0): - ahex.val(color.val('ahex').substring(6));break; + ahex.val(color.val('ahex').substring(6)); + break; } } } + /** + * @param {Event} e + * @returns {boolean} + */ + + function validateKey(e) { switch (e.keyCode) { case 9: @@ -22883,34 +25434,56 @@ case 37: case 39: return false; + case 'c'.charCodeAt(): case 'v'.charCodeAt(): if (e.ctrlKey) return false; } + return true; } - // constrain value within range + /** + * Constrain value within range. + * @param {Float|string} value + * @param {Float} min + * @param {Float} max + * @returns {Float|string} Returns a number or numeric string + */ + + function setValueInRange(value, min, max) { if (value === '' || isNaN(value)) return min; if (value > max) return max; if (value < min) return min; return value; } + /** + * @param {external:jQuery} ui + * @param {Element} context + * @returns {undefined} + */ + + function colorChanged(ui, context) { var all = ui.val('all'); - if (context !== red.get(0)) red.val(all != null ? all.r : ''); - if (context !== green.get(0)) green.val(all != null ? all.g : ''); - if (context !== blue.get(0)) blue.val(all != null ? all.b : ''); - if (alpha && context !== alpha.get(0)) alpha.val(all != null ? Math.precision(all.a * 100 / 255, alphaPrecision) : ''); - if (context !== hue.get(0)) hue.val(all != null ? all.h : ''); - if (context !== saturation.get(0)) saturation.val(all != null ? all.s : ''); - if (context !== value.get(0)) value.val(all != null ? all.v : ''); - if (context !== hex.get(0) && (bindedHex && context !== bindedHex.get(0) || !bindedHex)) hex.val(all != null ? all.hex : ''); - if (bindedHex && context !== bindedHex.get(0) && context !== hex.get(0)) bindedHex.val(all != null ? all.hex : ''); - if (ahex && context !== ahex.get(0)) ahex.val(all != null ? all.ahex.substring(6) : ''); + if (context !== red.get(0)) red.val(!isNullish$1(all) ? all.r : ''); + if (context !== green.get(0)) green.val(!isNullish$1(all) ? all.g : ''); + if (context !== blue.get(0)) blue.val(!isNullish$1(all) ? all.b : ''); + if (alpha && context !== alpha.get(0)) alpha.val(!isNullish$1(all) ? toFixedNumeric(all.a * 100 / 255, alphaPrecision) : ''); + if (context !== hue.get(0)) hue.val(!isNullish$1(all) ? all.h : ''); + if (context !== saturation.get(0)) saturation.val(!isNullish$1(all) ? all.s : ''); + if (context !== value.get(0)) value.val(!isNullish$1(all) ? all.v : ''); + if (context !== hex.get(0) && (bindedHex && context !== bindedHex.get(0) || !bindedHex)) hex.val(!isNullish$1(all) ? all.hex : ''); + if (bindedHex && context !== bindedHex.get(0) && context !== hex.get(0)) bindedHex.val(!isNullish$1(all) ? all.hex : ''); + if (ahex && context !== ahex.get(0)) ahex.val(!isNullish$1(all) ? all.ahex.substring(6) : ''); } + /** + * Unbind all events and null objects. + * @returns {undefined} + */ + + function destroy() { - // unbind all events and null objects red.add(green).add(blue).add(alpha).add(hue).add(saturation).add(value).add(hex).add(bindedHex).add(ahex).unbind('keyup', keyUp).unbind('blur', blur); red.add(green).add(blue).add(alpha).add(hue).add(saturation).add(value).unbind('keydown', keyDown); color.unbind(colorChanged); @@ -22924,6 +25497,7 @@ hex = null; ahex = null; } + var red = inputs.eq(3), green = inputs.eq(4), blue = inputs.eq(5), @@ -22933,38 +25507,42 @@ value = inputs.eq(2), hex = inputs.eq(inputs.length > 7 ? 7 : 6), ahex = inputs.length > 7 ? inputs.eq(8) : null; - $.extend(true, $this, { + $.extend(true, that, { // public properties and methods destroy: destroy }); red.add(green).add(blue).add(alpha).add(hue).add(saturation).add(value).add(hex).add(bindedHex).add(ahex).bind('keyup', keyUp).bind('blur', blur); red.add(green).add(blue).add(alpha).add(hue).add(saturation).add(value).bind('keydown', keyDown); color.bind(colorChanged); - } - + }; /** * @typedef {PlainObject} module:jPicker.JPickerInit - * @property {Integer} a - * @property {Integer} b - * @property {Integer} g - * @property {Integer} h - * @property {Integer} r - * @property {Integer} s - * @property {Integer} v - * @property {string} hex - * @property {string} ahex + * @property {Integer} [a] + * @property {Integer} [b] + * @property {Integer} [g] + * @property {Integer} [h] + * @property {Integer} [r] + * @property {Integer} [s] + * @property {Integer} [v] + * @property {string} [hex] + * @property {string} [ahex] */ /** * @namespace {PlainObject} jPicker * @memberof external:jQuery */ - $.jPicker = /** @lends external:jQuery.jPicker */{ + + + $.jPicker = + /** @lends external:jQuery.jPicker */ + { /** * Array holding references to each active instance of the jPicker control * @type {external:jQuery.fn.$.fn.jPicker[]} */ List: [], + /** * Color object - we will be able to assign by any color space type or * retrieve any color space info. @@ -22977,257 +25555,381 @@ * @param {module:jPicker.JPickerInit} init */ Color: function Color(init) { - var $this = this; + // eslint-disable-line object-shorthand + var that = this; + /** + * + * @param {module:jPicker.Slider} context + * @returns {undefined} + */ + function fireChangeEvents(context) { for (var i = 0; i < changeEvents.length; i++) { - changeEvents[i].call($this, $this, context); + changeEvents[i].call(that, that, context); } } + /** + * @param {string|"ahex"|"hex"|"all"|""|null|undefined} name String composed of letters "r", "g", "b", "a", "h", "s", and/or "v" + * @param {module:jPicker.RGBA|module:jPicker.JPickerInit|string} [value] + * @param {external:jQuery.jPicker.Color} context + * @returns {module:jPicker.JPickerInit|string|null|undefined} + */ + + function val(name, value, context) { // Kind of ugly - var set$$1 = Boolean(value); - if (set$$1 && value.ahex === '') value.ahex = '00000000'; - if (!set$$1) { - if (name === undefined || name == null || name === '') name = 'all'; - if (r == null) return null; + var set = Boolean(value); + if (set && value.ahex === '') value.ahex = '00000000'; + + if (!set) { + var ret; + if (isNullish$1(name) || name === '') name = 'all'; + if (isNullish$1(r)) return null; + switch (name.toLowerCase()) { case 'ahex': - return ColorMethods.rgbaToHex({ r: r, g: g, b: b, a: a }); + return ColorMethods.rgbaToHex({ + r: r, + g: g, + b: b, + a: a + }); + case 'hex': return val('ahex').substring(0, 6); - case 'all': - return { r: r, g: g, b: b, a: a, h: h, s: s, v: v, hex: val.call($this, 'hex'), ahex: val.call($this, 'ahex') }; - default: - var ret = {}; - for (var i = 0; i < name.length; i++) { - switch (name.charAt(i)) { - case 'r': - if (name.length === 1) ret = r;else ret.r = r; - break; - case 'g': - if (name.length === 1) ret = g;else ret.g = g; - break; - case 'b': - if (name.length === 1) ret = b;else ret.b = b; - break; - case 'a': - if (name.length === 1) ret = a;else ret.a = a; - break; - case 'h': - if (name.length === 1) ret = h;else ret.h = h; - break; - case 's': - if (name.length === 1) ret = s;else ret.s = s; - break; - case 'v': - if (name.length === 1) ret = v;else ret.v = v; - break; - } - } - return !name.length ? val.call($this, 'all') : ret; - } - } - if (context != null && context === $this) return; - if (name == null) name = ''; + case 'all': + return { + r: r, + g: g, + b: b, + a: a, + h: h, + s: s, + v: v, + hex: val.call(that, 'hex'), + ahex: val.call(that, 'ahex') + }; + + default: + { + ret = {}; + var nameLength = name.length; + + _toConsumableArray(name).forEach(function (ch) { + switch (ch) { + case 'r': + if (nameLength === 1) ret = r;else ret.r = r; + break; + + case 'g': + if (nameLength === 1) ret = g;else ret.g = g; + break; + + case 'b': + if (nameLength === 1) ret = b;else ret.b = b; + break; + + case 'a': + if (nameLength === 1) ret = a;else ret.a = a; + break; + + case 'h': + if (nameLength === 1) ret = h;else ret.h = h; + break; + + case 's': + if (nameLength === 1) ret = s;else ret.s = s; + break; + + case 'v': + if (nameLength === 1) ret = v;else ret.v = v; + break; + } + }); + } + } + + return _typeof(ret) === 'object' && !Object.keys(ret).length ? val.call(that, 'all') : ret; + } + + if (!isNullish$1(context) && context === that) return undefined; + if (isNullish$1(name)) name = ''; var changed = false; - if (value == null) { - if (r != null) { + + if (isNullish$1(value)) { + if (!isNullish$1(r)) { r = null; changed = true; } - if (g != null) { + + if (!isNullish$1(g)) { g = null; changed = true; } - if (b != null) { + + if (!isNullish$1(b)) { b = null; changed = true; } - if (a != null) { + + if (!isNullish$1(a)) { a = null; changed = true; } - if (h != null) { + + if (!isNullish$1(h)) { h = null; changed = true; } - if (s != null) { + + if (!isNullish$1(s)) { s = null; changed = true; } - if (v != null) { + + if (!isNullish$1(v)) { v = null; changed = true; } - changed && fireChangeEvents.call($this, context || $this); - return; + + changed && fireChangeEvents.call(that, context || that); + return undefined; } + switch (name.toLowerCase()) { case 'ahex': case 'hex': - var _ret = ColorMethods.hexToRgba(value && (value.ahex || value.hex) || value || 'none'); - val.call($this, 'rgba', { r: _ret.r, g: _ret.g, b: _ret.b, a: name === 'ahex' ? _ret.a : a != null ? a : 255 }, context); - break; + { + var _ret = ColorMethods.hexToRgba(value && (value.ahex || value.hex) || value || 'none'); + + val.call(that, 'rgba', { + r: _ret.r, + g: _ret.g, + b: _ret.b, + a: name === 'ahex' ? _ret.a : !isNullish$1(a) ? a : 255 + }, context); + break; + } + default: - if (value && (value.ahex != null || value.hex != null)) { - val.call($this, 'ahex', value.ahex || value.hex || '00000000', context); - return; - } - var newV = {}; - var rgb = false, - hsv = false; - if (value.r !== undefined && !name.includes('r')) name += 'r'; - if (value.g !== undefined && !name.includes('g')) name += 'g'; - if (value.b !== undefined && !name.includes('b')) name += 'b'; - if (value.a !== undefined && !name.includes('a')) name += 'a'; - if (value.h !== undefined && !name.includes('h')) name += 'h'; - if (value.s !== undefined && !name.includes('s')) name += 's'; - if (value.v !== undefined && !name.includes('v')) name += 'v'; - for (var _i = 0; _i < name.length; _i++) { - switch (name.charAt(_i)) { - case 'r': - if (hsv) continue; - rgb = true; - newV.r = value && value.r && value.r | 0 || value && value | 0 || 0; - if (newV.r < 0) newV.r = 0;else if (newV.r > 255) newV.r = 255; - if (r !== newV.r) { - r = newV.r; - - changed = true; - } - break; - case 'g': - if (hsv) continue; - rgb = true; - newV.g = value && value.g && value.g | 0 || value && value | 0 || 0; - if (newV.g < 0) newV.g = 0;else if (newV.g > 255) newV.g = 255; - if (g !== newV.g) { - g = newV.g; - - changed = true; - } - break; - case 'b': - if (hsv) continue; - rgb = true; - newV.b = value && value.b && value.b | 0 || value && value | 0 || 0; - if (newV.b < 0) newV.b = 0;else if (newV.b > 255) newV.b = 255; - if (b !== newV.b) { - b = newV.b; - - changed = true; - } - break; - case 'a': - newV.a = value && value.a != null ? value.a | 0 : value != null ? value | 0 : 255; - if (newV.a < 0) newV.a = 0;else if (newV.a > 255) newV.a = 255; - if (a !== newV.a) { - a = newV.a; - - changed = true; - } - break; - case 'h': - if (rgb) continue; - hsv = true; - newV.h = value && value.h && value.h | 0 || value && value | 0 || 0; - if (newV.h < 0) newV.h = 0;else if (newV.h > 360) newV.h = 360; - if (h !== newV.h) { - h = newV.h; - - changed = true; - } - break; - case 's': - if (rgb) continue; - hsv = true; - newV.s = value && value.s != null ? value.s | 0 : value != null ? value | 0 : 100; - if (newV.s < 0) newV.s = 0;else if (newV.s > 100) newV.s = 100; - if (s !== newV.s) { - s = newV.s; - - changed = true; - } - break; - case 'v': - if (rgb) continue; - hsv = true; - newV.v = value && value.v != null ? value.v | 0 : value != null ? value | 0 : 100; - if (newV.v < 0) newV.v = 0;else if (newV.v > 100) newV.v = 100; - if (v !== newV.v) { - v = newV.v; - - changed = true; - } - break; + { + if (value && (!isNullish$1(value.ahex) || !isNullish$1(value.hex))) { + val.call(that, 'ahex', value.ahex || value.hex || '00000000', context); + return undefined; } - } - if (changed) { - if (rgb) { - r = r || 0; - g = g || 0; - b = b || 0; - var _ret2 = ColorMethods.rgbToHsv({ r: r, g: g, b: b }); - h = _ret2.h; - s = _ret2.s; - v = _ret2.v; - } else if (hsv) { - h = h || 0; - s = s != null ? s : 100; - v = v != null ? v : 100; - var _ret3 = ColorMethods.hsvToRgb({ h: h, s: s, v: v }); - r = _ret3.r; - g = _ret3.g; - b = _ret3.b; + + var newV = {}; + var rgb = false, + hsv = false; + if (value.r !== undefined && !name.includes('r')) name += 'r'; + if (value.g !== undefined && !name.includes('g')) name += 'g'; + if (value.b !== undefined && !name.includes('b')) name += 'b'; + if (value.a !== undefined && !name.includes('a')) name += 'a'; + if (value.h !== undefined && !name.includes('h')) name += 'h'; + if (value.s !== undefined && !name.includes('s')) name += 's'; + if (value.v !== undefined && !name.includes('v')) name += 'v'; + + _toConsumableArray(name).forEach(function (ch) { + switch (ch) { + case 'r': + if (hsv) return; + rgb = true; + newV.r = value.r && value.r | 0 || value | 0 || 0; + if (newV.r < 0) newV.r = 0;else if (newV.r > 255) newV.r = 255; + + if (r !== newV.r) { + r = newV.r; + changed = true; + } + + break; + + case 'g': + if (hsv) return; + rgb = true; + newV.g = value && value.g && value.g | 0 || value && value | 0 || 0; + if (newV.g < 0) newV.g = 0;else if (newV.g > 255) newV.g = 255; + + if (g !== newV.g) { + g = newV.g; + changed = true; + } + + break; + + case 'b': + if (hsv) return; + rgb = true; + newV.b = value && value.b && value.b | 0 || value && value | 0 || 0; + if (newV.b < 0) newV.b = 0;else if (newV.b > 255) newV.b = 255; + + if (b !== newV.b) { + b = newV.b; + changed = true; + } + + break; + + case 'a': + newV.a = value && !isNullish$1(value.a) ? value.a | 0 : value | 0; + if (newV.a < 0) newV.a = 0;else if (newV.a > 255) newV.a = 255; + + if (a !== newV.a) { + a = newV.a; + changed = true; + } + + break; + + case 'h': + if (rgb) return; + hsv = true; + newV.h = value && value.h && value.h | 0 || value && value | 0 || 0; + if (newV.h < 0) newV.h = 0;else if (newV.h > 360) newV.h = 360; + + if (h !== newV.h) { + h = newV.h; + changed = true; + } + + break; + + case 's': + if (rgb) return; + hsv = true; + newV.s = !isNullish$1(value.s) ? value.s | 0 : value | 0; + if (newV.s < 0) newV.s = 0;else if (newV.s > 100) newV.s = 100; + + if (s !== newV.s) { + s = newV.s; + changed = true; + } + + break; + + case 'v': + if (rgb) return; + hsv = true; + newV.v = !isNullish$1(value.v) ? value.v | 0 : value | 0; + if (newV.v < 0) newV.v = 0;else if (newV.v > 100) newV.v = 100; + + if (v !== newV.v) { + v = newV.v; + changed = true; + } + + break; + } + }); + + if (changed) { + if (rgb) { + r = r || 0; + g = g || 0; + b = b || 0; + + var _ret2 = ColorMethods.rgbToHsv({ + r: r, + g: g, + b: b + }); + + h = _ret2.h; + s = _ret2.s; + v = _ret2.v; + } else if (hsv) { + h = h || 0; + s = !isNullish$1(s) ? s : 100; + v = !isNullish$1(v) ? v : 100; + + var _ret3 = ColorMethods.hsvToRgb({ + h: h, + s: s, + v: v + }); + + r = _ret3.r; + g = _ret3.g; + b = _ret3.b; + } + + a = !isNullish$1(a) ? a : 255; + fireChangeEvents.call(that, context || that); } - a = a != null ? a : 255; - fireChangeEvents.call($this, context || $this); + + break; } - break; } + + return undefined; } + /** + * @param {GenericCallback} callback + * @returns {undefined} + */ + + function bind(callback) { + // eslint-disable-line promise/prefer-await-to-callbacks if (typeof callback === 'function') changeEvents.push(callback); } + /** + * @param {GenericCallback} callback + * @returns {undefined} + */ + + function unbind(callback) { + // eslint-disable-line promise/prefer-await-to-callbacks if (typeof callback !== 'function') return; - var i = void 0; + var i; + while (i = changeEvents.includes(callback)) { changeEvents.splice(i, 1); } } + /** + * Unset `changeEvents` + * @returns {undefined} + */ + + function destroy() { changeEvents = null; } - var r = void 0, - g = void 0, - b = void 0, - a = void 0, - h = void 0, - s = void 0, - v = void 0, - changeEvents = []; - $.extend(true, $this, { + var r, + g, + b, + a, + h, + s, + v, + changeEvents = []; + $.extend(true, that, { // public properties and methods val: val, bind: bind, unbind: unbind, destroy: destroy }); + if (init) { - if (init.ahex != null) { + if (!isNullish$1(init.ahex)) { val('ahex', init); - } else if (init.hex != null) { - val((init.a != null ? 'a' : '') + 'hex', init.a != null ? { ahex: init.hex + ColorMethods.intToHex(init.a) } : init); - } else if (init.r != null && init.g != null && init.b != null) { - val('rgb' + (init.a != null ? 'a' : ''), init); - } else if (init.h != null && init.s != null && init.v != null) { - val('hsv' + (init.a != null ? 'a' : ''), init); + } else if (!isNullish$1(init.hex)) { + val((!isNullish$1(init.a) ? 'a' : '') + 'hex', !isNullish$1(init.a) ? { + ahex: init.hex + ColorMethods.intToHex(init.a) + } : init); + } else if (!isNullish$1(init.r) && !isNullish$1(init.g) && !isNullish$1(init.b)) { + val('rgb' + (!isNullish$1(init.a) ? 'a' : ''), init); + } else if (!isNullish$1(init.h) && !isNullish$1(init.s) && !isNullish$1(init.v)) { + val('hsv' + (!isNullish$1(init.a) ? 'a' : ''), init); } } }, + /** * color conversion methods - make public to give use to external scripts * @namespace @@ -23240,24 +25942,32 @@ * @property {Integer} b * @property {Integer} a */ + /** * @typedef {PlainObject} module:jPicker.RGB * @property {Integer} r * @property {Integer} g * @property {Integer} b */ + /** * @param {string} hex * @returns {module:jPicker.RGBA} */ hexToRgba: function hexToRgba(hex) { - if (hex === '' || hex === 'none') return { r: null, g: null, b: null, a: null }; + if (hex === '' || hex === 'none') return { + r: null, + g: null, + b: null, + a: null + }; hex = this.validateHex(hex); var r = '00', g = '00', b = '00', a = '255'; if (hex.length === 6) hex += 'ff'; + if (hex.length > 6) { r = hex.substring(0, 2); g = hex.substring(2, 4); @@ -23268,14 +25978,20 @@ r = hex.substring(4, hex.length); hex = hex.substring(0, 4); } + if (hex.length > 2) { g = hex.substring(2, hex.length); hex = hex.substring(0, 2); } + if (hex.length > 0) b = hex.substring(0, hex.length); } + return { - r: this.hexToInt(r), g: this.hexToInt(g), b: this.hexToInt(b), a: this.hexToInt(a) + r: this.hexToInt(r), + g: this.hexToInt(g), + b: this.hexToInt(b), + a: this.hexToInt(a) }; }, @@ -23322,6 +26038,7 @@ * @property {Integer} s * @property {Integer} v */ + /** * @param {module:jPicker.RGB} rgb * @returns {module:jPicker.HSV} @@ -23330,9 +26047,14 @@ var r = rgb.r / 255, g = rgb.g / 255, b = rgb.b / 255, - hsv = { h: 0, s: 0, v: 0 }; + hsv = { + h: 0, + s: 0, + v: 0 + }; var min = 0, max = 0; + if (r >= g && r >= b) { max = r; min = g > b ? b : g; @@ -23343,9 +26065,10 @@ max = b; min = g > r ? r : g; } + hsv.v = max; hsv.s = max ? (max - min) / max : 0; - var delta = void 0; + var delta; if (!hsv.s) hsv.h = 0;else { delta = max - min; if (r === max) hsv.h = (g - b) / delta;else if (g === max) hsv.h = 2 + (b - r) / delta;else hsv.h = 4 + (r - g) / delta; @@ -23362,7 +26085,12 @@ * @returns {module:jPicker.RGB} */ hsvToRgb: function hsvToRgb(hsv) { - var rgb = { r: 0, g: 0, b: 0, a: 100 }; + var rgb = { + r: 0, + g: 0, + b: 0, + a: 100 + }; var h = hsv.h, s = hsv.s, v = hsv.v; @@ -23372,49 +26100,57 @@ } else { if (h === 360) h = 0; h /= 60; - s = s / 100; - v = v / 100; + s /= 100; + v /= 100; var i = h | 0, f = h - i, p = v * (1 - s), q = v * (1 - s * f), t = v * (1 - s * (1 - f)); + switch (i) { case 0: rgb.r = v; rgb.g = t; rgb.b = p; break; + case 1: rgb.r = q; rgb.g = v; rgb.b = p; break; + case 2: rgb.r = p; rgb.g = v; rgb.b = t; break; + case 3: rgb.r = p; rgb.g = q; rgb.b = v; break; + case 4: rgb.r = t; rgb.g = p; rgb.b = v; break; + case 5: rgb.r = v; rgb.g = p; rgb.b = q; break; } + rgb.r = rgb.r * 255 | 0; rgb.g = rgb.g * 255 | 0; rgb.b = rgb.b * 255 | 0; } + return rgb; } } @@ -23423,10 +26159,34 @@ Color = _$$jPicker.Color, List = _$$jPicker.List, ColorMethods = _$$jPicker.ColorMethods; // local copies for YUI compressor + /** * @function external:jQuery.fn.jPicker * @see {@link external:jQuery.fn.$.fn.jPicker} */ + + /** + * Will be bound to active {@link jQuery.jPicker.Color} + * @callback module:jPicker.LiveCallback + * @param {external:jQuery} ui + * @param {Element} context + * @returns {undefined} + */ + + /** + * @callback module:jPicker.CommitCallback + * @param {external:jQuery.jPicker.Color} activeColor + * @param {external:jQuery} okButton + * @returns {undefined} Return value not used. + */ + + /** + * @callback module:jPicker.CancelCallback + * @param {external:jQuery.jPicker.Color} activeColor + * @param {external:jQuery} cancelButton + * @returns {undefined} Return value not used. + */ + /** * While it would seem this should specify the name `jPicker` for JSDoc, that doesn't * get us treated as a function as well as a namespace (even with `@function name`), @@ -23434,577 +26194,1061 @@ * @namespace * @memberof external:jQuery.fn * @param {external:jQuery.fn.jPickerOptions} options + * @param {module:jPicker.CommitCallback} [commitCallback] + * @param {module:jPicker.LiveCallback} [liveCallback] + * @param {module:jPicker.CancelCallback} [cancelCallback] * @returns {external:jQuery} */ - $.fn.jPicker = function (options) { - var $arguments = arguments; + $.fn.jPicker = function (options, commitCallback, liveCallback, cancelCallback) { return this.each(function () { - var $this = this, + var that = this, settings = $.extend(true, {}, $.fn.jPicker.defaults, options); // local copies for YUI compressor - if ($($this).get(0).nodeName.toLowerCase() === 'input') { + + if ($(that).get(0).nodeName.toLowerCase() === 'input') { // Add color picker icon if binding to an input element and bind the events to the input $.extend(true, settings, { window: { bindToInput: true, expandable: true, - input: $($this) + input: $(that) } }); - if ($($this).val() === '') { - settings.color.active = new Color({ hex: null }); - settings.color.current = new Color({ hex: null }); - } else if (ColorMethods.validateHex($($this).val())) { - settings.color.active = new Color({ hex: $($this).val(), a: settings.color.active.val('a') }); - settings.color.current = new Color({ hex: $($this).val(), a: settings.color.active.val('a') }); + + if ($(that).val() === '') { + settings.color.active = new Color({ + hex: null + }); + settings.color.current = new Color({ + hex: null + }); + } else if (ColorMethods.validateHex($(that).val())) { + settings.color.active = new Color({ + hex: $(that).val(), + a: settings.color.active.val('a') + }); + settings.color.current = new Color({ + hex: $(that).val(), + a: settings.color.active.val('a') + }); } } + if (settings.window.expandable) { - $($this).after('<span class="jPicker"><span class="Icon"><span class="Color"> </span><span class="Alpha"> </span><span class="Image" title="Click To Open Color Picker"> </span><span class="Container"> </span></span></span>'); + $(that).after('<span class="jPicker"><span class="Icon"><span class="Color"> </span><span class="Alpha"> </span><span class="Image" title="Click To Open Color Picker"> </span><span class="Container"> </span></span></span>'); } else { settings.window.liveUpdate = false; // Basic control binding for inline use - You will need to override the liveCallback or commitCallback function to retrieve results } + var isLessThanIE7 = parseFloat(navigator.appVersion.split('MSIE')[1]) < 7 && document.body.filters; // needed to run the AlphaImageLoader function for IE6 // set color mode and update visuals for the new color mode + /** * - * @param {"h"|"s"|"v"|"r"|"g"|"b"|"a"} colorMode [description] + * @param {"h"|"s"|"v"|"r"|"g"|"b"|"a"} colorMode * @throws {Error} Invalid mode + * @returns {undefined} */ + function setColorMode(colorMode) { var active = color.active, hex = active.val('hex'); - var rgbMap = void 0, - rgbBar = void 0; + var rgbMap, rgbBar; settings.color.mode = colorMode; + switch (colorMode) { case 'h': setTimeout(function () { - setBG.call($this, colorMapDiv, 'transparent'); - setImgLoc.call($this, colorMapL1, 0); - setAlpha.call($this, colorMapL1, 100); - setImgLoc.call($this, colorMapL2, 260); - setAlpha.call($this, colorMapL2, 100); - setBG.call($this, colorBarDiv, 'transparent'); - setImgLoc.call($this, colorBarL1, 0); - setAlpha.call($this, colorBarL1, 100); - setImgLoc.call($this, colorBarL2, 260); - setAlpha.call($this, colorBarL2, 100); - setImgLoc.call($this, colorBarL3, 260); - setAlpha.call($this, colorBarL3, 100); - setImgLoc.call($this, colorBarL4, 260); - setAlpha.call($this, colorBarL4, 100); - setImgLoc.call($this, colorBarL6, 260); - setAlpha.call($this, colorBarL6, 100); + setBG.call(that, colorMapDiv, 'transparent'); + setImgLoc.call(that, colorMapL1, 0); + setAlpha.call(that, colorMapL1, 100); + setImgLoc.call(that, colorMapL2, 260); + setAlpha.call(that, colorMapL2, 100); + setBG.call(that, colorBarDiv, 'transparent'); + setImgLoc.call(that, colorBarL1, 0); + setAlpha.call(that, colorBarL1, 100); + setImgLoc.call(that, colorBarL2, 260); + setAlpha.call(that, colorBarL2, 100); + setImgLoc.call(that, colorBarL3, 260); + setAlpha.call(that, colorBarL3, 100); + setImgLoc.call(that, colorBarL4, 260); + setAlpha.call(that, colorBarL4, 100); + setImgLoc.call(that, colorBarL6, 260); + setAlpha.call(that, colorBarL6, 100); }, 0); - colorMap.range('all', { minX: 0, maxX: 100, minY: 0, maxY: 100 }); - colorBar.range('rangeY', { minY: 0, maxY: 360 }); - if (active.val('ahex') == null) break; - colorMap.val('xy', { x: active.val('s'), y: 100 - active.val('v') }, colorMap); + colorMap.range('all', { + minX: 0, + maxX: 100, + minY: 0, + maxY: 100 + }); + colorBar.range('rangeY', { + minY: 0, + maxY: 360 + }); + if (isNullish$1(active.val('ahex'))) break; + colorMap.val('xy', { + x: active.val('s'), + y: 100 - active.val('v') + }, colorMap); colorBar.val('y', 360 - active.val('h'), colorBar); break; + case 's': setTimeout(function () { - setBG.call($this, colorMapDiv, 'transparent'); - setImgLoc.call($this, colorMapL1, -260); - setImgLoc.call($this, colorMapL2, -520); - setImgLoc.call($this, colorBarL1, -260); - setImgLoc.call($this, colorBarL2, -520); - setImgLoc.call($this, colorBarL6, 260); - setAlpha.call($this, colorBarL6, 100); + setBG.call(that, colorMapDiv, 'transparent'); + setImgLoc.call(that, colorMapL1, -260); + setImgLoc.call(that, colorMapL2, -520); + setImgLoc.call(that, colorBarL1, -260); + setImgLoc.call(that, colorBarL2, -520); + setImgLoc.call(that, colorBarL6, 260); + setAlpha.call(that, colorBarL6, 100); }, 0); - colorMap.range('all', { minX: 0, maxX: 360, minY: 0, maxY: 100 }); - colorBar.range('rangeY', { minY: 0, maxY: 100 }); - if (active.val('ahex') == null) break; - colorMap.val('xy', { x: active.val('h'), y: 100 - active.val('v') }, colorMap); + colorMap.range('all', { + minX: 0, + maxX: 360, + minY: 0, + maxY: 100 + }); + colorBar.range('rangeY', { + minY: 0, + maxY: 100 + }); + if (isNullish$1(active.val('ahex'))) break; + colorMap.val('xy', { + x: active.val('h'), + y: 100 - active.val('v') + }, colorMap); colorBar.val('y', 100 - active.val('s'), colorBar); break; + case 'v': setTimeout(function () { - setBG.call($this, colorMapDiv, '000000'); - setImgLoc.call($this, colorMapL1, -780); - setImgLoc.call($this, colorMapL2, 260); - setBG.call($this, colorBarDiv, hex); - setImgLoc.call($this, colorBarL1, -520); - setImgLoc.call($this, colorBarL2, 260); - setAlpha.call($this, colorBarL2, 100); - setImgLoc.call($this, colorBarL6, 260); - setAlpha.call($this, colorBarL6, 100); + setBG.call(that, colorMapDiv, '000000'); + setImgLoc.call(that, colorMapL1, -780); + setImgLoc.call(that, colorMapL2, 260); + setBG.call(that, colorBarDiv, hex); + setImgLoc.call(that, colorBarL1, -520); + setImgLoc.call(that, colorBarL2, 260); + setAlpha.call(that, colorBarL2, 100); + setImgLoc.call(that, colorBarL6, 260); + setAlpha.call(that, colorBarL6, 100); }, 0); - colorMap.range('all', { minX: 0, maxX: 360, minY: 0, maxY: 100 }); - colorBar.range('rangeY', { minY: 0, maxY: 100 }); - if (active.val('ahex') == null) break; - colorMap.val('xy', { x: active.val('h'), y: 100 - active.val('s') }, colorMap); + colorMap.range('all', { + minX: 0, + maxX: 360, + minY: 0, + maxY: 100 + }); + colorBar.range('rangeY', { + minY: 0, + maxY: 100 + }); + if (isNullish$1(active.val('ahex'))) break; + colorMap.val('xy', { + x: active.val('h'), + y: 100 - active.val('s') + }, colorMap); colorBar.val('y', 100 - active.val('v'), colorBar); break; + case 'r': rgbMap = -1040; rgbBar = -780; - colorMap.range('all', { minX: 0, maxX: 255, minY: 0, maxY: 255 }); - colorBar.range('rangeY', { minY: 0, maxY: 255 }); - if (active.val('ahex') == null) break; - colorMap.val('xy', { x: active.val('b'), y: 255 - active.val('g') }, colorMap); + colorMap.range('all', { + minX: 0, + maxX: 255, + minY: 0, + maxY: 255 + }); + colorBar.range('rangeY', { + minY: 0, + maxY: 255 + }); + if (isNullish$1(active.val('ahex'))) break; + colorMap.val('xy', { + x: active.val('b'), + y: 255 - active.val('g') + }, colorMap); colorBar.val('y', 255 - active.val('r'), colorBar); break; + case 'g': rgbMap = -1560; rgbBar = -1820; - colorMap.range('all', { minX: 0, maxX: 255, minY: 0, maxY: 255 }); - colorBar.range('rangeY', { minY: 0, maxY: 255 }); - if (active.val('ahex') == null) break; - colorMap.val('xy', { x: active.val('b'), y: 255 - active.val('r') }, colorMap); + colorMap.range('all', { + minX: 0, + maxX: 255, + minY: 0, + maxY: 255 + }); + colorBar.range('rangeY', { + minY: 0, + maxY: 255 + }); + if (isNullish$1(active.val('ahex'))) break; + colorMap.val('xy', { + x: active.val('b'), + y: 255 - active.val('r') + }, colorMap); colorBar.val('y', 255 - active.val('g'), colorBar); break; + case 'b': rgbMap = -2080; rgbBar = -2860; - colorMap.range('all', { minX: 0, maxX: 255, minY: 0, maxY: 255 }); - colorBar.range('rangeY', { minY: 0, maxY: 255 }); - if (active.val('ahex') == null) break; - colorMap.val('xy', { x: active.val('r'), y: 255 - active.val('g') }, colorMap); + colorMap.range('all', { + minX: 0, + maxX: 255, + minY: 0, + maxY: 255 + }); + colorBar.range('rangeY', { + minY: 0, + maxY: 255 + }); + if (isNullish$1(active.val('ahex'))) break; + colorMap.val('xy', { + x: active.val('r'), + y: 255 - active.val('g') + }, colorMap); colorBar.val('y', 255 - active.val('b'), colorBar); break; + case 'a': setTimeout(function () { - setBG.call($this, colorMapDiv, 'transparent'); - setImgLoc.call($this, colorMapL1, -260); - setImgLoc.call($this, colorMapL2, -520); - setImgLoc.call($this, colorBarL1, 260); - setImgLoc.call($this, colorBarL2, 260); - setAlpha.call($this, colorBarL2, 100); - setImgLoc.call($this, colorBarL6, 0); - setAlpha.call($this, colorBarL6, 100); + setBG.call(that, colorMapDiv, 'transparent'); + setImgLoc.call(that, colorMapL1, -260); + setImgLoc.call(that, colorMapL2, -520); + setImgLoc.call(that, colorBarL1, 260); + setImgLoc.call(that, colorBarL2, 260); + setAlpha.call(that, colorBarL2, 100); + setImgLoc.call(that, colorBarL6, 0); + setAlpha.call(that, colorBarL6, 100); }, 0); - colorMap.range('all', { minX: 0, maxX: 360, minY: 0, maxY: 100 }); - colorBar.range('rangeY', { minY: 0, maxY: 255 }); - if (active.val('ahex') == null) break; - colorMap.val('xy', { x: active.val('h'), y: 100 - active.val('v') }, colorMap); + colorMap.range('all', { + minX: 0, + maxX: 360, + minY: 0, + maxY: 100 + }); + colorBar.range('rangeY', { + minY: 0, + maxY: 255 + }); + if (isNullish$1(active.val('ahex'))) break; + colorMap.val('xy', { + x: active.val('h'), + y: 100 - active.val('v') + }, colorMap); colorBar.val('y', 255 - active.val('a'), colorBar); break; + default: throw new Error('Invalid Mode'); } + switch (colorMode) { case 'h': break; + case 's': case 'v': case 'a': setTimeout(function () { - setAlpha.call($this, colorMapL1, 100); - setAlpha.call($this, colorBarL1, 100); - setImgLoc.call($this, colorBarL3, 260); - setAlpha.call($this, colorBarL3, 100); - setImgLoc.call($this, colorBarL4, 260); - setAlpha.call($this, colorBarL4, 100); + setAlpha.call(that, colorMapL1, 100); + setAlpha.call(that, colorBarL1, 100); + setImgLoc.call(that, colorBarL3, 260); + setAlpha.call(that, colorBarL3, 100); + setImgLoc.call(that, colorBarL4, 260); + setAlpha.call(that, colorBarL4, 100); }, 0); break; + case 'r': case 'g': case 'b': setTimeout(function () { - setBG.call($this, colorMapDiv, 'transparent'); - setBG.call($this, colorBarDiv, 'transparent'); - setAlpha.call($this, colorBarL1, 100); - setAlpha.call($this, colorMapL1, 100); - setImgLoc.call($this, colorMapL1, rgbMap); - setImgLoc.call($this, colorMapL2, rgbMap - 260); - setImgLoc.call($this, colorBarL1, rgbBar - 780); - setImgLoc.call($this, colorBarL2, rgbBar - 520); - setImgLoc.call($this, colorBarL3, rgbBar); - setImgLoc.call($this, colorBarL4, rgbBar - 260); - setImgLoc.call($this, colorBarL6, 260); - setAlpha.call($this, colorBarL6, 100); + setBG.call(that, colorMapDiv, 'transparent'); + setBG.call(that, colorBarDiv, 'transparent'); + setAlpha.call(that, colorBarL1, 100); + setAlpha.call(that, colorMapL1, 100); + setImgLoc.call(that, colorMapL1, rgbMap); + setImgLoc.call(that, colorMapL2, rgbMap - 260); + setImgLoc.call(that, colorBarL1, rgbBar - 780); + setImgLoc.call(that, colorBarL2, rgbBar - 520); + setImgLoc.call(that, colorBarL3, rgbBar); + setImgLoc.call(that, colorBarL4, rgbBar - 260); + setImgLoc.call(that, colorBarL6, 260); + setAlpha.call(that, colorBarL6, 100); }, 0); break; } - if (active.val('ahex') == null) return; - activeColorChanged.call($this, active); + + if (isNullish$1(active.val('ahex'))) return; + activeColorChanged.call(that, active); } - // Update color when user changes text values + /** + * Update color when user changes text values. + * @param {external:jQuery} ui + * @param {?module:jPicker.Slider} context + * @returns {undefined} + */ + + function activeColorChanged(ui, context) { - if (context == null || context !== colorBar && context !== colorMap) positionMapAndBarArrows.call($this, ui, context); + if (isNullish$1(context) || context !== colorBar && context !== colorMap) positionMapAndBarArrows.call(that, ui, context); setTimeout(function () { - updatePreview.call($this, ui); - updateMapVisuals.call($this, ui); - updateBarVisuals.call($this, ui); + updatePreview.call(that, ui); + updateMapVisuals.call(that, ui); + updateBarVisuals.call(that, ui); }, 0); } - // user has dragged the ColorMap pointer + /** + * User has dragged the ColorMap pointer. + * @param {external:jQuery} ui + * @param {?module:jPicker.Slider} context + * @returns {undefined} + */ + + function mapValueChanged(ui, context) { var active = color.active; - - if (context !== colorMap && active.val() == null) return; + if (context !== colorMap && isNullish$1(active.val())) return; var xy = ui.val('all'); + switch (settings.color.mode) { case 'h': - active.val('sv', { s: xy.x, v: 100 - xy.y }, context); + active.val('sv', { + s: xy.x, + v: 100 - xy.y + }, context); break; + case 's': case 'a': - active.val('hv', { h: xy.x, v: 100 - xy.y }, context); + active.val('hv', { + h: xy.x, + v: 100 - xy.y + }, context); break; + case 'v': - active.val('hs', { h: xy.x, s: 100 - xy.y }, context); + active.val('hs', { + h: xy.x, + s: 100 - xy.y + }, context); break; + case 'r': - active.val('gb', { g: 255 - xy.y, b: xy.x }, context); + active.val('gb', { + g: 255 - xy.y, + b: xy.x + }, context); break; + case 'g': - active.val('rb', { r: 255 - xy.y, b: xy.x }, context); + active.val('rb', { + r: 255 - xy.y, + b: xy.x + }, context); break; + case 'b': - active.val('rg', { r: xy.x, g: 255 - xy.y }, context); + active.val('rg', { + r: xy.x, + g: 255 - xy.y + }, context); break; } } - // user has dragged the ColorBar slider + /** + * User has dragged the ColorBar slider. + * @param {external:jQuery} ui + * @param {?module:jPicker.Slider} context + * @returns {undefined} + */ + + function colorBarValueChanged(ui, context) { var active = color.active; + if (context !== colorBar && isNullish$1(active.val())) return; - if (context !== colorBar && active.val() == null) return; switch (settings.color.mode) { case 'h': - active.val('h', { h: 360 - ui.val('y') }, context); + active.val('h', { + h: 360 - ui.val('y') + }, context); break; + case 's': - active.val('s', { s: 100 - ui.val('y') }, context); + active.val('s', { + s: 100 - ui.val('y') + }, context); break; + case 'v': - active.val('v', { v: 100 - ui.val('y') }, context); + active.val('v', { + v: 100 - ui.val('y') + }, context); break; + case 'r': - active.val('r', { r: 255 - ui.val('y') }, context); + active.val('r', { + r: 255 - ui.val('y') + }, context); break; + case 'g': - active.val('g', { g: 255 - ui.val('y') }, context); + active.val('g', { + g: 255 - ui.val('y') + }, context); break; + case 'b': - active.val('b', { b: 255 - ui.val('y') }, context); + active.val('b', { + b: 255 - ui.val('y') + }, context); break; + case 'a': active.val('a', 255 - ui.val('y'), context); break; } } - // position map and bar arrows to match current color + /** + * Position map and bar arrows to match current color. + * @param {external:jQuery} ui + * @param {?module:jPicker.Slider} context + * @returns {undefined} + */ + + function positionMapAndBarArrows(ui, context) { if (context !== colorMap) { switch (settings.color.mode) { case 'h': - var sv = ui.val('sv'); - colorMap.val('xy', { x: sv != null ? sv.s : 100, y: 100 - (sv != null ? sv.v : 100) }, context); - break; - case 's': + { + var sv = ui.val('sv'); + colorMap.val('xy', { + x: !isNullish$1(sv) ? sv.s : 100, + y: 100 - (!isNullish$1(sv) ? sv.v : 100) + }, context); + break; + } + + case 's': // Fall through + case 'a': - var hv = ui.val('hv'); - colorMap.val('xy', { x: hv && hv.h || 0, y: 100 - (hv != null ? hv.v : 100) }, context); - break; + { + var hv = ui.val('hv'); + colorMap.val('xy', { + x: hv && hv.h || 0, + y: 100 - (!isNullish$1(hv) ? hv.v : 100) + }, context); + break; + } + case 'v': - var hs = ui.val('hs'); - colorMap.val('xy', { x: hs && hs.h || 0, y: 100 - (hs != null ? hs.s : 100) }, context); - break; + { + var hs = ui.val('hs'); + colorMap.val('xy', { + x: hs && hs.h || 0, + y: 100 - (!isNullish$1(hs) ? hs.s : 100) + }, context); + break; + } + case 'r': - var bg = ui.val('bg'); - colorMap.val('xy', { x: bg && bg.b || 0, y: 255 - (bg && bg.g || 0) }, context); - break; + { + var bg = ui.val('bg'); + colorMap.val('xy', { + x: bg && bg.b || 0, + y: 255 - (bg && bg.g || 0) + }, context); + break; + } + case 'g': - var br = ui.val('br'); - colorMap.val('xy', { x: br && br.b || 0, y: 255 - (br && br.r || 0) }, context); - break; + { + var br = ui.val('br'); + colorMap.val('xy', { + x: br && br.b || 0, + y: 255 - (br && br.r || 0) + }, context); + break; + } + case 'b': - var rg = ui.val('rg'); - colorMap.val('xy', { x: rg && rg.r || 0, y: 255 - (rg && rg.g || 0) }, context); - break; + { + var rg = ui.val('rg'); + colorMap.val('xy', { + x: rg && rg.r || 0, + y: 255 - (rg && rg.g || 0) + }, context); + break; + } } } + if (context !== colorBar) { switch (settings.color.mode) { case 'h': colorBar.val('y', 360 - (ui.val('h') || 0), context); break; + case 's': - var s = ui.val('s'); - colorBar.val('y', 100 - (s != null ? s : 100), context); - break; + { + var s = ui.val('s'); + colorBar.val('y', 100 - (!isNullish$1(s) ? s : 100), context); + break; + } + case 'v': - var v = ui.val('v'); - colorBar.val('y', 100 - (v != null ? v : 100), context); - break; + { + var v = ui.val('v'); + colorBar.val('y', 100 - (!isNullish$1(v) ? v : 100), context); + break; + } + case 'r': colorBar.val('y', 255 - (ui.val('r') || 0), context); break; + case 'g': colorBar.val('y', 255 - (ui.val('g') || 0), context); break; + case 'b': colorBar.val('y', 255 - (ui.val('b') || 0), context); break; + case 'a': - var a = ui.val('a'); - colorBar.val('y', 255 - (a != null ? a : 255), context); - break; + { + var a = ui.val('a'); + colorBar.val('y', 255 - (!isNullish$1(a) ? a : 255), context); + break; + } } } } + /** + * @param {external:jQuery} ui + * @returns {undefined} + */ + + function updatePreview(ui) { try { var all = ui.val('all'); - activePreview.css({ backgroundColor: all && '#' + all.hex || 'transparent' }); - setAlpha.call($this, activePreview, all && Math.precision(all.a * 100 / 255, 4) || 0); + activePreview.css({ + backgroundColor: all && '#' + all.hex || 'transparent' + }); + setAlpha.call(that, activePreview, all && toFixedNumeric(all.a * 100 / 255, 4) || 0); } catch (e) {} } + /** + * @param {external:jQuery} ui + * @returns {undefined} + */ + + function updateMapVisuals(ui) { switch (settings.color.mode) { case 'h': - setBG.call($this, colorMapDiv, new Color({ h: ui.val('h') || 0, s: 100, v: 100 }).val('hex')); + setBG.call(that, colorMapDiv, new Color({ + h: ui.val('h') || 0, + s: 100, + v: 100 + }).val('hex')); break; + case 's': case 'a': - var s = ui.val('s'); - setAlpha.call($this, colorMapL2, 100 - (s != null ? s : 100)); - break; + { + var s = ui.val('s'); + setAlpha.call(that, colorMapL2, 100 - (!isNullish$1(s) ? s : 100)); + break; + } + case 'v': - var v = ui.val('v'); - setAlpha.call($this, colorMapL1, v != null ? v : 100); - break; + { + var v = ui.val('v'); + setAlpha.call(that, colorMapL1, !isNullish$1(v) ? v : 100); + break; + } + case 'r': - setAlpha.call($this, colorMapL2, Math.precision((ui.val('r') || 0) / 255 * 100, 4)); + setAlpha.call(that, colorMapL2, toFixedNumeric((ui.val('r') || 0) / 255 * 100, 4)); break; + case 'g': - setAlpha.call($this, colorMapL2, Math.precision((ui.val('g') || 0) / 255 * 100, 4)); + setAlpha.call(that, colorMapL2, toFixedNumeric((ui.val('g') || 0) / 255 * 100, 4)); break; + case 'b': - setAlpha.call($this, colorMapL2, Math.precision((ui.val('b') || 0) / 255 * 100)); + setAlpha.call(that, colorMapL2, toFixedNumeric((ui.val('b') || 0) / 255 * 100)); break; } + var a = ui.val('a'); - setAlpha.call($this, colorMapL3, Math.precision((255 - (a || 0)) * 100 / 255, 4)); + setAlpha.call(that, colorMapL3, toFixedNumeric((255 - (a || 0)) * 100 / 255, 4)); } + /** + * @param {external:jQuery} ui + * @returns {undefined} + */ + + function updateBarVisuals(ui) { switch (settings.color.mode) { case 'h': - var a = ui.val('a'); - setAlpha.call($this, colorBarL5, Math.precision((255 - (a || 0)) * 100 / 255, 4)); - break; + { + var a = ui.val('a'); + setAlpha.call(that, colorBarL5, toFixedNumeric((255 - (a || 0)) * 100 / 255, 4)); + break; + } + case 's': - var hva = ui.val('hva'), - saturatedColor = new Color({ h: hva && hva.h || 0, s: 100, v: hva != null ? hva.v : 100 }); - setBG.call($this, colorBarDiv, saturatedColor.val('hex')); - setAlpha.call($this, colorBarL2, 100 - (hva != null ? hva.v : 100)); - setAlpha.call($this, colorBarL5, Math.precision((255 - (hva && hva.a || 0)) * 100 / 255, 4)); - break; + { + var hva = ui.val('hva'), + saturatedColor = new Color({ + h: hva && hva.h || 0, + s: 100, + v: !isNullish$1(hva) ? hva.v : 100 + }); + setBG.call(that, colorBarDiv, saturatedColor.val('hex')); + setAlpha.call(that, colorBarL2, 100 - (!isNullish$1(hva) ? hva.v : 100)); + setAlpha.call(that, colorBarL5, toFixedNumeric((255 - (hva && hva.a || 0)) * 100 / 255, 4)); + break; + } + case 'v': - var hsa = ui.val('hsa'), - valueColor = new Color({ h: hsa && hsa.h || 0, s: hsa != null ? hsa.s : 100, v: 100 }); - setBG.call($this, colorBarDiv, valueColor.val('hex')); - setAlpha.call($this, colorBarL5, Math.precision((255 - (hsa && hsa.a || 0)) * 100 / 255, 4)); - break; + { + var hsa = ui.val('hsa'), + valueColor = new Color({ + h: hsa && hsa.h || 0, + s: !isNullish$1(hsa) ? hsa.s : 100, + v: 100 + }); + setBG.call(that, colorBarDiv, valueColor.val('hex')); + setAlpha.call(that, colorBarL5, toFixedNumeric((255 - (hsa && hsa.a || 0)) * 100 / 255, 4)); + break; + } + case 'r': case 'g': case 'b': - var rgba = ui.val('rgba'); - var hValue = 0, - vValue = 0; - if (settings.color.mode === 'r') { - hValue = rgba && rgba.b || 0; - vValue = rgba && rgba.g || 0; - } else if (settings.color.mode === 'g') { - hValue = rgba && rgba.b || 0; - vValue = rgba && rgba.r || 0; - } else if (settings.color.mode === 'b') { - hValue = rgba && rgba.r || 0; - vValue = rgba && rgba.g || 0; + { + var rgba = ui.val('rgba'); + var hValue = 0, + vValue = 0; + + if (settings.color.mode === 'r') { + hValue = rgba && rgba.b || 0; + vValue = rgba && rgba.g || 0; + } else if (settings.color.mode === 'g') { + hValue = rgba && rgba.b || 0; + vValue = rgba && rgba.r || 0; + } else if (settings.color.mode === 'b') { + hValue = rgba && rgba.r || 0; + vValue = rgba && rgba.g || 0; + } + + var middle = vValue > hValue ? hValue : vValue; + setAlpha.call(that, colorBarL2, hValue > vValue ? toFixedNumeric((hValue - vValue) / (255 - vValue) * 100, 4) : 0); + setAlpha.call(that, colorBarL3, vValue > hValue ? toFixedNumeric((vValue - hValue) / (255 - hValue) * 100, 4) : 0); + setAlpha.call(that, colorBarL4, toFixedNumeric(middle / 255 * 100, 4)); + setAlpha.call(that, colorBarL5, toFixedNumeric((255 - (rgba && rgba.a || 0)) * 100 / 255, 4)); + break; } - var middle = vValue > hValue ? hValue : vValue; - setAlpha.call($this, colorBarL2, hValue > vValue ? Math.precision((hValue - vValue) / (255 - vValue) * 100, 4) : 0); - setAlpha.call($this, colorBarL3, vValue > hValue ? Math.precision((vValue - hValue) / (255 - hValue) * 100, 4) : 0); - setAlpha.call($this, colorBarL4, Math.precision(middle / 255 * 100, 4)); - setAlpha.call($this, colorBarL5, Math.precision((255 - (rgba && rgba.a || 0)) * 100 / 255, 4)); - break; + case 'a': { var _a = ui.val('a'); - setBG.call($this, colorBarDiv, ui.val('hex') || '000000'); - setAlpha.call($this, colorBarL5, _a != null ? 0 : 100); - setAlpha.call($this, colorBarL6, _a != null ? 100 : 0); + + setBG.call(that, colorBarDiv, ui.val('hex') || '000000'); + setAlpha.call(that, colorBarL5, !isNullish$1(_a) ? 0 : 100); + setAlpha.call(that, colorBarL6, !isNullish$1(_a) ? 100 : 0); break; } } } + /** + * @param {external:jQuery} el + * @param {string} [c="transparent"] + * @returns {undefined} + */ + + function setBG(el, c) { - el.css({ backgroundColor: c && c.length === 6 && '#' + c || 'transparent' }); + el.css({ + backgroundColor: c && c.length === 6 && '#' + c || 'transparent' + }); } + /** + * @param {external:jQuery} img + * @param {string} src The image source + * @returns {undefined} + */ + + function setImg(img, src) { if (isLessThanIE7 && (src.includes('AlphaBar.png') || src.includes('Bars.png') || src.includes('Maps.png'))) { img.attr('pngSrc', src); - img.css({ backgroundImage: 'none', filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + src + '\', sizingMethod=\'scale\')' }); - } else img.css({ backgroundImage: 'url(\'' + src + '\')' }); + img.css({ + backgroundImage: 'none', + filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + src + '\', sizingMethod=\'scale\')' + }); + } else img.css({ + backgroundImage: 'url(\'' + src + '\')' + }); } + /** + * @param {external:jQuery} img + * @param {Float} y + * @returns {undefined} + */ + + function setImgLoc(img, y) { - img.css({ top: y + 'px' }); + img.css({ + top: y + 'px' + }); } + /** + * @param {external:jQuery} obj + * @param {Float} alpha + * @returns {undefined} + */ + + function setAlpha(obj, alpha) { - obj.css({ visibility: alpha > 0 ? 'visible' : 'hidden' }); + obj.css({ + visibility: alpha > 0 ? 'visible' : 'hidden' + }); + if (alpha > 0 && alpha < 100) { if (isLessThanIE7) { var src = obj.attr('pngSrc'); - if (src != null && (src.includes('AlphaBar.png') || src.includes('Bars.png') || src.includes('Maps.png'))) { - obj.css({ filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + src + '\', sizingMethod=\'scale\') progid:DXImageTransform.Microsoft.Alpha(opacity=' + alpha + ')' }); - } else obj.css({ opacity: Math.precision(alpha / 100, 4) }); - } else obj.css({ opacity: Math.precision(alpha / 100, 4) }); + + if (!isNullish$1(src) && (src.includes('AlphaBar.png') || src.includes('Bars.png') || src.includes('Maps.png'))) { + obj.css({ + filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + src + '\', sizingMethod=\'scale\') progid:DXImageTransform.Microsoft.Alpha(opacity=' + alpha + ')' + }); + } else obj.css({ + opacity: toFixedNumeric(alpha / 100, 4) + }); + } else obj.css({ + opacity: toFixedNumeric(alpha / 100, 4) + }); } else if (alpha === 0 || alpha === 100) { if (isLessThanIE7) { var _src = obj.attr('pngSrc'); - if (_src != null && (_src.includes('AlphaBar.png') || _src.includes('Bars.png') || _src.includes('Maps.png'))) { - obj.css({ filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + _src + '\', sizingMethod=\'scale\')' }); - } else obj.css({ opacity: '' }); - } else obj.css({ opacity: '' }); - } - } - // revert color to original color when opened - function revertColor() { - color.active.val('ahex', color.current.val('ahex')); - } - // commit the color changes - function commitColor() { - color.current.val('ahex', color.active.val('ahex')); - } - function radioClicked(e) { - $(this).parents('tbody:first').find('input:radio[value!="' + e.target.value + '"]').removeAttr('checked'); - setColorMode.call($this, e.target.value); - } - function currentClicked() { - revertColor.call($this); - } - function cancelClicked() { - revertColor.call($this); - settings.window.expandable && hide.call($this); - typeof cancelCallback === 'function' && cancelCallback.call($this, color.active, cancelButton); - } - function okClicked() { - commitColor.call($this); - settings.window.expandable && hide.call($this); - typeof commitCallback === 'function' && commitCallback.call($this, color.active, okButton); - } - function iconImageClicked() { - show.call($this); - } - function currentColorChanged(ui, context) { - var hex = ui.val('hex'); - currentPreview.css({ backgroundColor: hex && '#' + hex || 'transparent' }); - setAlpha.call($this, currentPreview, Math.precision((ui.val('a') || 0) * 100 / 255, 4)); - } - function expandableColorChanged(ui, context) { - var hex = ui.val('hex'); - var va = ui.val('va'); - iconColor.css({ backgroundColor: hex && '#' + hex || 'transparent' }); - setAlpha.call($this, iconAlpha, Math.precision((255 - (va && va.a || 0)) * 100 / 255, 4)); - if (settings.window.bindToInput && settings.window.updateInputColor) { - settings.window.input.css({ - backgroundColor: hex && '#' + hex || 'transparent', - color: va == null || va.v > 75 ? '#000000' : '#ffffff' + + if (!isNullish$1(_src) && (_src.includes('AlphaBar.png') || _src.includes('Bars.png') || _src.includes('Maps.png'))) { + obj.css({ + filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + _src + '\', sizingMethod=\'scale\')' + }); + } else obj.css({ + opacity: '' + }); + } else obj.css({ + opacity: '' }); } } + /** + * Revert color to original color when opened. + * @returns {undefined} + */ + + + function revertColor() { + color.active.val('ahex', color.current.val('ahex')); + } + /** + * Commit the color changes. + * @returns {undefined} + */ + + + function commitColor() { + color.current.val('ahex', color.active.val('ahex')); + } + /** + * @param {Event} e + * @returns {undefined} + */ + + + function radioClicked(e) { + $(this).parents('tbody:first').find('input:radio[value!="' + e.target.value + '"]').removeAttr('checked'); + setColorMode.call(that, e.target.value); + } + /** + * + * @returns {undefined} + */ + + + function currentClicked() { + revertColor.call(that); + } + /** + * + * @returns {undefined} + */ + + + function cancelClicked() { + revertColor.call(that); + settings.window.expandable && hide.call(that); + typeof cancelCallback === 'function' && cancelCallback.call(that, color.active, cancelButton); + } + /** + * + * @returns {undefined} + */ + + + function okClicked() { + commitColor.call(that); + settings.window.expandable && hide.call(that); + typeof commitCallback === 'function' && commitCallback.call(that, color.active, okButton); + } + /** + * + * @returns {undefined} + */ + + + function iconImageClicked() { + show.call(that); + } + /** + * @param {external:jQuery} ui + * @returns {undefined} + */ + + + function currentColorChanged(ui) { + var hex = ui.val('hex'); + currentPreview.css({ + backgroundColor: hex && '#' + hex || 'transparent' + }); + setAlpha.call(that, currentPreview, toFixedNumeric((ui.val('a') || 0) * 100 / 255, 4)); + } + /** + * @param {external:jQuery} ui + * @returns {undefined} + */ + + + function expandableColorChanged(ui) { + var hex = ui.val('hex'); + var va = ui.val('va'); + iconColor.css({ + backgroundColor: hex && '#' + hex || 'transparent' + }); + setAlpha.call(that, iconAlpha, toFixedNumeric((255 - (va && va.a || 0)) * 100 / 255, 4)); + + if (settings.window.bindToInput && settings.window.updateInputColor) { + settings.window.input.css({ + backgroundColor: hex && '#' + hex || 'transparent', + color: isNullish$1(va) || va.v > 75 ? '#000000' : '#ffffff' + }); + } + } + /** + * @param {Event} e + * @returns {undefined} + */ + + function moveBarMouseDown(e) { // const {element} = settings.window, // local copies for YUI compressor // {page} = settings.window; elementStartX = parseInt(container.css('left')); elementStartY = parseInt(container.css('top')); pageStartX = e.pageX; - pageStartY = e.pageY; - // bind events to document to move window - we will unbind these on mouseup + pageStartY = e.pageY; // bind events to document to move window - we will unbind these on mouseup + $(document).bind('mousemove', documentMouseMove).bind('mouseup', documentMouseUp); e.preventDefault(); // prevent attempted dragging of the column } + /** + * @param {Event} e + * @returns {false} + */ + + function documentMouseMove(e) { - container.css({ left: elementStartX - (pageStartX - e.pageX) + 'px', top: elementStartY - (pageStartY - e.pageY) + 'px' }); - if (settings.window.expandable && !$.support.boxModel) container.prev().css({ left: container.css('left'), top: container.css('top') }); + container.css({ + left: elementStartX - (pageStartX - e.pageX) + 'px', + top: elementStartY - (pageStartY - e.pageY) + 'px' + }); + + if (settings.window.expandable && !$.support.boxModel) { + container.prev().css({ + left: container.css('left'), + top: container.css('top') + }); + } + e.stopPropagation(); e.preventDefault(); return false; } + /** + * @param {Event} e + * @returns {false} + */ + + function documentMouseUp(e) { $(document).unbind('mousemove', documentMouseMove).unbind('mouseup', documentMouseUp); e.stopPropagation(); e.preventDefault(); return false; } + /** + * @param {Event} e + * @returns {false} + */ + + function quickPickClicked(e) { e.preventDefault(); e.stopPropagation(); color.active.val('ahex', $(this).attr('title') || null, e.target); return false; } + /** + * + * @returns {undefined} + */ + + function show() { color.current.val('ahex', color.active.val('ahex')); + /** + * + * @returns {undefined} + */ + function attachIFrame() { if (!settings.window.expandable || $.support.boxModel) return; var table = container.find('table:first'); container.before('<iframe/>'); - container.prev().css({ width: table.width(), height: container.height(), opacity: 0, position: 'absolute', left: container.css('left'), top: container.css('top') }); + container.prev().css({ + width: table.width(), + height: container.height(), + opacity: 0, + position: 'absolute', + left: container.css('left'), + top: container.css('top') + }); } + if (settings.window.expandable) { - $(document.body).children('div.jPicker.Container').css({ zIndex: 10 }); - container.css({ zIndex: 20 }); + $(document.body).children('div.jPicker.Container').css({ + zIndex: 10 + }); + container.css({ + zIndex: 20 + }); } + switch (settings.window.effects.type) { case 'fade': container.fadeIn(settings.window.effects.speed.show, attachIFrame); break; + case 'slide': container.slideDown(settings.window.effects.speed.show, attachIFrame); break; + case 'show': default: container.show(settings.window.effects.speed.show, attachIFrame); break; } } + /** + * + * @returns {undefined} + */ + + function hide() { + /** + * + * @returns {undefined} + */ function removeIFrame() { - if (settings.window.expandable) container.css({ zIndex: 10 }); + if (settings.window.expandable) container.css({ + zIndex: 10 + }); if (!settings.window.expandable || $.support.boxModel) return; container.prev().remove(); } + switch (settings.window.effects.type) { case 'fade': container.fadeOut(settings.window.effects.speed.hide, removeIFrame); break; + case 'slide': container.slideUp(settings.window.effects.speed.hide, removeIFrame); break; + case 'show': default: container.hide(settings.window.effects.speed.hide, removeIFrame); break; } } + /** + * + * @returns {undefined} + */ + + function initialize() { var win = settings.window, - popup = win.expandable ? $($this).next().find('.Container:first') : null; - container = win.expandable ? $('<div/>') : $($this); + popup = win.expandable ? $(that).next().find('.Container:first') : null; + container = win.expandable ? $('<div/>') : $(that); container.addClass('jPicker Container'); if (win.expandable) container.hide(); - container.get(0).onselectstart = function (event) { - if (event.target.nodeName.toLowerCase() !== 'input') return false; - }; - // inject html source code - we are using a single table for this control - I know tables are considered bad, but it takes care of equal height columns and + + container.get(0).onselectstart = function (e) { + if (e.target.nodeName.toLowerCase() !== 'input') return false; + return true; + }; // inject html source code - we are using a single table for this control - I know tables are considered bad, but it takes care of equal height columns and // this control really is tabular data, so I believe it is the right move + + var all = color.active.val('all'); if (win.alphaPrecision < 0) win.alphaPrecision = 0;else if (win.alphaPrecision > 2) win.alphaPrecision = 2; - var controlHtml = '<table class="jPicker" cellpadding="0" cellspacing="0"><tbody>' + (win.expandable ? '<tr><td class="Move" colspan="5"> </td></tr>' : '') + '<tr><td rowspan="9"><h2 class="Title">' + (win.title || localization.text.title) + '</h2><div class="Map"><span class="Map1"> </span><span class="Map2"> </span><span class="Map3"> </span><img src="' + images.clientPath + images.colorMap.arrow.file + '" class="Arrow"/></div></td><td rowspan="9"><div class="Bar"><span class="Map1"> </span><span class="Map2"> </span><span class="Map3"> </span><span class="Map4"> </span><span class="Map5"> </span><span class="Map6"> </span><img src="' + images.clientPath + images.colorBar.arrow.file + '" class="Arrow"/></div></td><td colspan="2" class="Preview">' + localization.text.newColor + '<div><span class="Active" title="' + localization.tooltips.colors.newColor + '"> </span><span class="Current" title="' + localization.tooltips.colors.currentColor + '"> </span></div>' + localization.text.currentColor + '</td><td rowspan="9" class="Button"><input type="button" class="Ok" value="' + localization.text.ok + '" title="' + localization.tooltips.buttons.ok + '"/><input type="button" class="Cancel" value="' + localization.text.cancel + '" title="' + localization.tooltips.buttons.cancel + '"/><hr/><div class="Grid"> </div></td></tr><tr class="Hue"><td class="Radio"><label title="' + localization.tooltips.hue.radio + '"><input type="radio" value="h"' + (settings.color.mode === 'h' ? ' checked="checked"' : '') + '/>H:</label></td><td class="Text"><input type="text" maxlength="3" value="' + (all != null ? all.h : '') + '" title="' + localization.tooltips.hue.textbox + '"/> °</td></tr><tr class="Saturation"><td class="Radio"><label title="' + localization.tooltips.saturation.radio + '"><input type="radio" value="s"' + (settings.color.mode === 's' ? ' checked="checked"' : '') + '/>S:</label></td><td class="Text"><input type="text" maxlength="3" value="' + (all != null ? all.s : '') + '" title="' + localization.tooltips.saturation.textbox + '"/> %</td></tr><tr class="Value"><td class="Radio"><label title="' + localization.tooltips.value.radio + '"><input type="radio" value="v"' + (settings.color.mode === 'v' ? ' checked="checked"' : '') + '/>V:</label><br/><br/></td><td class="Text"><input type="text" maxlength="3" value="' + (all != null ? all.v : '') + '" title="' + localization.tooltips.value.textbox + '"/> %<br/><br/></td></tr><tr class="Red"><td class="Radio"><label title="' + localization.tooltips.red.radio + '"><input type="radio" value="r"' + (settings.color.mode === 'r' ? ' checked="checked"' : '') + '/>R:</label></td><td class="Text"><input type="text" maxlength="3" value="' + (all != null ? all.r : '') + '" title="' + localization.tooltips.red.textbox + '"/></td></tr><tr class="Green"><td class="Radio"><label title="' + localization.tooltips.green.radio + '"><input type="radio" value="g"' + (settings.color.mode === 'g' ? ' checked="checked"' : '') + '/>G:</label></td><td class="Text"><input type="text" maxlength="3" value="' + (all != null ? all.g : '') + '" title="' + localization.tooltips.green.textbox + '"/></td></tr><tr class="Blue"><td class="Radio"><label title="' + localization.tooltips.blue.radio + '"><input type="radio" value="b"' + (settings.color.mode === 'b' ? ' checked="checked"' : '') + '/>B:</label></td><td class="Text"><input type="text" maxlength="3" value="' + (all != null ? all.b : '') + '" title="' + localization.tooltips.blue.textbox + '"/></td></tr><tr class="Alpha"><td class="Radio">' + (win.alphaSupport ? '<label title="' + localization.tooltips.alpha.radio + '"><input type="radio" value="a"' + (settings.color.mode === 'a' ? ' checked="checked"' : '') + '/>A:</label>' : ' ') + '</td><td class="Text">' + (win.alphaSupport ? '<input type="text" maxlength="' + (3 + win.alphaPrecision) + '" value="' + (all != null ? Math.precision(all.a * 100 / 255, win.alphaPrecision) : '') + '" title="' + localization.tooltips.alpha.textbox + '"/> %' : ' ') + '</td></tr><tr class="Hex"><td colspan="2" class="Text"><label title="' + localization.tooltips.hex.textbox + '">#:<input type="text" maxlength="6" class="Hex" value="' + (all != null ? all.hex : '') + '"/></label>' + (win.alphaSupport ? '<input type="text" maxlength="2" class="AHex" value="' + (all != null ? all.ahex.substring(6) : '') + '" title="' + localization.tooltips.hex.alpha + '"/></td>' : ' ') + '</tr></tbody></table>'; + var controlHtml = "<table class=\"jPicker\" cellpadding=\"0\" cellspacing=\"0\">\n <tbody>\n ".concat(win.expandable ? "<tr><td class=\"Move\" colspan=\"5\"> </td></tr>" : '', "\n <tr>\n <td rowspan=\"9\"><h2 class=\"Title\">").concat(win.title || localization.text.title, "</h2><div class=\"Map\"><span class=\"Map1\"> </span><span class=\"Map2\"> </span><span class=\"Map3\"> </span><img src=\"").concat(images.clientPath + images.colorMap.arrow.file, "\" class=\"Arrow\"/></div></td>\n <td rowspan=\"9\"><div class=\"Bar\"><span class=\"Map1\"> </span><span class=\"Map2\"> </span><span class=\"Map3\"> </span><span class=\"Map4\"> </span><span class=\"Map5\"> </span><span class=\"Map6\"> </span><img src=\"").concat(images.clientPath + images.colorBar.arrow.file, "\" class=\"Arrow\"/></div></td>\n <td colspan=\"2\" class=\"Preview\">").concat(localization.text.newColor, "<div><span class=\"Active\" title=\"").concat(localization.tooltips.colors.newColor, "\"> </span><span class=\"Current\" title=\"").concat(localization.tooltips.colors.currentColor, "\"> </span></div>").concat(localization.text.currentColor, "</td>\n <td rowspan=\"9\" class=\"Button\"><input type=\"button\" class=\"Ok\" value=\"").concat(localization.text.ok, "\" title=\"").concat(localization.tooltips.buttons.ok, "\"/><input type=\"button\" class=\"Cancel\" value=\"").concat(localization.text.cancel, "\" title=\"").concat(localization.tooltips.buttons.cancel, "\"/><hr/><div class=\"Grid\"> </div></td>\n </tr>\n <tr class=\"Hue\">\n <td class=\"Radio\"><label title=\"").concat(localization.tooltips.hue.radio, "\"><input type=\"radio\" value=\"h\"").concat(settings.color.mode === 'h' ? ' checked="checked"' : '', "/>H:</label></td>\n <td class=\"Text\"><input type=\"text\" maxlength=\"3\" value=\"").concat(!isNullish$1(all) ? all.h : '', "\" title=\"").concat(localization.tooltips.hue.textbox, "\"/> °</td>\n </tr>\n <tr class=\"Saturation\">\n <td class=\"Radio\"><label title=\"").concat(localization.tooltips.saturation.radio, "\"><input type=\"radio\" value=\"s\"").concat(settings.color.mode === 's' ? ' checked="checked"' : '', "/>S:</label></td>\n <td class=\"Text\"><input type=\"text\" maxlength=\"3\" value=\"").concat(!isNullish$1(all) ? all.s : '', "\" title=\"").concat(localization.tooltips.saturation.textbox, "\"/> %</td>\n </tr>\n <tr class=\"Value\">\n <td class=\"Radio\"><label title=\"").concat(localization.tooltips.value.radio, "\"><input type=\"radio\" value=\"v\"").concat(settings.color.mode === 'v' ? ' checked="checked"' : '', "/>V:</label><br/><br/></td>\n <td class=\"Text\"><input type=\"text\" maxlength=\"3\" value=\"").concat(!isNullish$1(all) ? all.v : '', "\" title=\"").concat(localization.tooltips.value.textbox, "\"/> %<br/><br/></td>\n </tr>\n <tr class=\"Red\">\n <td class=\"Radio\"><label title=\"").concat(localization.tooltips.red.radio, "\"><input type=\"radio\" value=\"r\"").concat(settings.color.mode === 'r' ? ' checked="checked"' : '', "/>R:</label></td>\n <td class=\"Text\"><input type=\"text\" maxlength=\"3\" value=\"").concat(!isNullish$1(all) ? all.r : '', "\" title=\"").concat(localization.tooltips.red.textbox, "\"/></td>\n </tr>\n <tr class=\"Green\">\n <td class=\"Radio\"><label title=\"").concat(localization.tooltips.green.radio, "\"><input type=\"radio\" value=\"g\"").concat(settings.color.mode === 'g' ? ' checked="checked"' : '', "/>G:</label></td>\n <td class=\"Text\"><input type=\"text\" maxlength=\"3\" value=\"").concat(!isNullish$1(all) ? all.g : '', "\" title=\"").concat(localization.tooltips.green.textbox, "\"/></td>\n </tr>\n <tr class=\"Blue\">\n <td class=\"Radio\"><label title=\"").concat(localization.tooltips.blue.radio, "\"><input type=\"radio\" value=\"b\"").concat(settings.color.mode === 'b' ? ' checked="checked"' : '', "/>B:</label></td>\n <td class=\"Text\"><input type=\"text\" maxlength=\"3\" value=\"").concat(!isNullish$1(all) ? all.b : '', "\" title=\"").concat(localization.tooltips.blue.textbox, "\"/></td>\n </tr>\n <tr class=\"Alpha\">\n <td class=\"Radio\">").concat(win.alphaSupport ? "<label title=\"".concat(localization.tooltips.alpha.radio, "\"><input type=\"radio\" value=\"a\"").concat(settings.color.mode === 'a' ? ' checked="checked"' : '', "/>A:</label>") : ' ', "</td>\n <td class=\"Text\">").concat(win.alphaSupport ? "<input type=\"text\" maxlength=\"".concat(3 + win.alphaPrecision, "\" value=\"").concat(!isNullish$1(all) ? toFixedNumeric(all.a * 100 / 255, win.alphaPrecision) : '', "\" title=\"").concat(localization.tooltips.alpha.textbox, "\"/> %") : ' ', "</td>\n </tr>\n <tr class=\"Hex\">\n <td colspan=\"2\" class=\"Text\"><label title=\"").concat(localization.tooltips.hex.textbox, "\">#:<input type=\"text\" maxlength=\"6\" class=\"Hex\" value=\"").concat(!isNullish$1(all) ? all.hex : '', "\"/></label>").concat(win.alphaSupport ? "<input type=\"text\" maxlength=\"2\" class=\"AHex\" value=\"".concat(!isNullish$1(all) ? all.ahex.substring(6) : '', "\" title=\"").concat(localization.tooltips.hex.alpha, "\"/></td>") : ' ', "\n </tr>\n </tbody></table>"); + if (win.expandable) { container.html(controlHtml); + if (!$(document.body).children('div.jPicker.Container').length) { $(document.body).prepend(container); } else { $(document.body).children('div.jPicker.Container:last').after(container); } + container.mousedown(function () { - $(document.body).children('div.jPicker.Container').css({ zIndex: 10 }); - container.css({ zIndex: 20 }); + $(document.body).children('div.jPicker.Container').css({ + zIndex: 10 + }); + container.css({ + zIndex: 20 + }); }); container.css( // positions must be set and display set to absolute before source code injection or IE will size the container to fit the window { @@ -24013,10 +27257,11 @@ top: win.position.y === 'top' ? popup.offset().top - 312 + 'px' : win.position.y === 'center' ? popup.offset().top - 156 + 'px' : win.position.y === 'bottom' ? popup.offset().top + 25 + 'px' : popup.offset().top + parseInt(win.position.y) + 'px' }); } else { - container = $($this); + container = $(that); container.html(controlHtml); - } - // initialize the objects to the source code just injected + } // initialize the objects to the source code just injected + + var tbody = container.find('tbody:first'); colorMapDiv = tbody.find('div.Map:first'); colorBarDiv = tbody.find('div.Bar:first'); @@ -24030,8 +27275,8 @@ colorBarL3 = BarMaps.filter('.Map3:first'); colorBarL4 = BarMaps.filter('.Map4:first'); colorBarL5 = BarMaps.filter('.Map5:first'); - colorBarL6 = BarMaps.filter('.Map6:first'); - // create color pickers and maps + colorBarL6 = BarMaps.filter('.Map6:first'); // create color pickers and maps + colorMap = new Slider(colorMapDiv, { map: { width: images.colorMap.width, @@ -24057,79 +27302,103 @@ }); colorBar.bind(colorBarValueChanged); colorPicker = new ColorValuePicker(tbody, color.active, win.expandable && win.bindToInput ? win.input : null, win.alphaPrecision); - var hex = all != null ? all.hex : null, + var hex = !isNullish$1(all) ? all.hex : null, preview = tbody.find('.Preview'), button = tbody.find('.Button'); - activePreview = preview.find('.Active:first').css({ backgroundColor: hex && '#' + hex || 'transparent' }); - currentPreview = preview.find('.Current:first').css({ backgroundColor: hex && '#' + hex || 'transparent' }).bind('click', currentClicked); - setAlpha.call($this, currentPreview, Math.precision(color.current.val('a') * 100) / 255, 4); + activePreview = preview.find('.Active:first').css({ + backgroundColor: hex && '#' + hex || 'transparent' + }); + currentPreview = preview.find('.Current:first').css({ + backgroundColor: hex && '#' + hex || 'transparent' + }).bind('click', currentClicked); + setAlpha.call(that, currentPreview, toFixedNumeric(color.current.val('a') * 100 / 255, 4)); okButton = button.find('.Ok:first').bind('click', okClicked); cancelButton = button.find('.Cancel:first').bind('click', cancelClicked); grid = button.find('.Grid:first'); setTimeout(function () { - setImg.call($this, colorMapL1, images.clientPath + 'Maps.png'); - setImg.call($this, colorMapL2, images.clientPath + 'Maps.png'); - setImg.call($this, colorMapL3, images.clientPath + 'map-opacity.png'); - setImg.call($this, colorBarL1, images.clientPath + 'Bars.png'); - setImg.call($this, colorBarL2, images.clientPath + 'Bars.png'); - setImg.call($this, colorBarL3, images.clientPath + 'Bars.png'); - setImg.call($this, colorBarL4, images.clientPath + 'Bars.png'); - setImg.call($this, colorBarL5, images.clientPath + 'bar-opacity.png'); - setImg.call($this, colorBarL6, images.clientPath + 'AlphaBar.png'); - setImg.call($this, preview.find('div:first'), images.clientPath + 'preview-opacity.png'); + setImg.call(that, colorMapL1, images.clientPath + 'Maps.png'); + setImg.call(that, colorMapL2, images.clientPath + 'Maps.png'); + setImg.call(that, colorMapL3, images.clientPath + 'map-opacity.png'); + setImg.call(that, colorBarL1, images.clientPath + 'Bars.png'); + setImg.call(that, colorBarL2, images.clientPath + 'Bars.png'); + setImg.call(that, colorBarL3, images.clientPath + 'Bars.png'); + setImg.call(that, colorBarL4, images.clientPath + 'Bars.png'); + setImg.call(that, colorBarL5, images.clientPath + 'bar-opacity.png'); + setImg.call(that, colorBarL6, images.clientPath + 'AlphaBar.png'); + setImg.call(that, preview.find('div:first'), images.clientPath + 'preview-opacity.png'); }, 0); - tbody.find('td.Radio input').bind('click', radioClicked); - // initialize quick list + tbody.find('td.Radio input').bind('click', radioClicked); // initialize quick list + if (color.quickList && color.quickList.length > 0) { var html = ''; + for (var i = 0; i < color.quickList.length; i++) { /* if default colors are hex strings, change them to color objects */ - if (_typeof(color.quickList[i]).toString().toLowerCase() === 'string') color.quickList[i] = new Color({ hex: color.quickList[i] }); - var alpha = color.quickList[i].val('a'); - var ahex = color.quickList[i].val('ahex'); - if (!win.alphaSupport && ahex) ahex = ahex.substring(0, 6) + 'ff'; + if (_typeof(color.quickList[i]).toString().toLowerCase() === 'string') color.quickList[i] = new Color({ + hex: color.quickList[i] + }); + + var _alpha = color.quickList[i].val('a'); + + var _ahex = color.quickList[i].val('ahex'); + + if (!win.alphaSupport && _ahex) _ahex = _ahex.substring(0, 6) + 'ff'; var quickHex = color.quickList[i].val('hex'); - if (!ahex) ahex = '00000000'; - html += '<span class="QuickColor"' + (ahex && ' title="#' + ahex + '"' || 'none') + ' style="background-color:' + (quickHex && '#' + quickHex || '') + ';' + (quickHex ? '' : 'background-image:url(' + images.clientPath + 'NoColor.png)') + (win.alphaSupport && alpha && alpha < 255 ? ';opacity:' + Math.precision(alpha / 255, 4) + ';filter:Alpha(opacity=' + Math.precision(alpha / 2.55, 4) + ')' : '') + '"> </span>'; + if (!_ahex) _ahex = '00000000'; + html += '<span class="QuickColor"' + (' title="#' + _ahex + '"') + ' style="background-color:' + (quickHex && '#' + quickHex || '') + ';' + (quickHex ? '' : 'background-image:url(' + images.clientPath + 'NoColor.png)') + (win.alphaSupport && _alpha && _alpha < 255 ? ';opacity:' + toFixedNumeric(_alpha / 255, 4) + ';filter:Alpha(opacity=' + toFixedNumeric(_alpha / 2.55, 4) + ')' : '') + '"> </span>'; } - setImg.call($this, grid, images.clientPath + 'bar-opacity.png'); + + setImg.call(that, grid, images.clientPath + 'bar-opacity.png'); grid.html(html); grid.find('.QuickColor').click(quickPickClicked); } - setColorMode.call($this, settings.color.mode); + + setColorMode.call(that, settings.color.mode); color.active.bind(activeColorChanged); typeof liveCallback === 'function' && color.active.bind(liveCallback); - color.current.bind(currentColorChanged); - // bind to input + color.current.bind(currentColorChanged); // bind to input + if (win.expandable) { - $this.icon = popup.parents('.Icon:first'); - iconColor = $this.icon.find('.Color:first').css({ backgroundColor: hex && '#' + hex || 'transparent' }); - iconAlpha = $this.icon.find('.Alpha:first'); - setImg.call($this, iconAlpha, images.clientPath + 'bar-opacity.png'); - setAlpha.call($this, iconAlpha, Math.precision((255 - (all != null ? all.a : 0)) * 100 / 255, 4)); - iconImage = $this.icon.find('.Image:first').css({ + that.icon = popup.parents('.Icon:first'); + iconColor = that.icon.find('.Color:first').css({ + backgroundColor: hex && '#' + hex || 'transparent' + }); + iconAlpha = that.icon.find('.Alpha:first'); + setImg.call(that, iconAlpha, images.clientPath + 'bar-opacity.png'); + setAlpha.call(that, iconAlpha, toFixedNumeric((255 - (!isNullish$1(all) ? all.a : 0)) * 100 / 255, 4)); + iconImage = that.icon.find('.Image:first').css({ backgroundImage: 'url(\'' + images.clientPath + images.picker.file + '\')' }).bind('click', iconImageClicked); + if (win.bindToInput && win.updateInputColor) { win.input.css({ backgroundColor: hex && '#' + hex || 'transparent', - color: all == null || all.v > 75 ? '#000000' : '#ffffff' + color: isNullish$1(all) || all.v > 75 ? '#000000' : '#ffffff' }); } + moveBar = tbody.find('.Move:first').bind('mousedown', moveBarMouseDown); color.active.bind(expandableColorChanged); - } else show.call($this); + } else show.call(that); } + /** + * + * @returns {undefined} + */ + + function destroy() { container.find('td.Radio input').unbind('click', radioClicked); currentPreview.unbind('click', currentClicked); cancelButton.unbind('click', cancelClicked); okButton.unbind('click', okClicked); + if (settings.window.expandable) { iconImage.unbind('click', iconImageClicked); moveBar.unbind('mousedown', moveBarMouseDown); - $this.icon = null; + that.icon = null; } + container.find('.QuickColor').unbind('click', quickPickClicked); colorMapDiv = null; colorBarDiv = null; @@ -24157,24 +27426,43 @@ cancelCallback = null; liveCallback = null; container.html(''); + for (var i = 0; i < List.length; i++) { - if (List[i] === $this) { + if (List[i] === that) { List.splice(i, 1); } } } + var images = settings.images, localization = settings.localization; // local copies for YUI compressor var color = { - active: _typeof(settings.color.active).toString().toLowerCase() === 'string' ? new Color({ ahex: !settings.window.alphaSupport && settings.color.active ? settings.color.active.substring(0, 6) + 'ff' : settings.color.active - }) : new Color({ ahex: !settings.window.alphaSupport && settings.color.active.val('ahex') ? settings.color.active.val('ahex').substring(0, 6) + 'ff' : settings.color.active.val('ahex') + active: _typeof(settings.color.active).toString().toLowerCase() === 'string' ? new Color({ + ahex: !settings.window.alphaSupport && settings.color.active ? settings.color.active.substring(0, 6) + 'ff' : settings.color.active + }) : new Color({ + ahex: !settings.window.alphaSupport && settings.color.active.val('ahex') ? settings.color.active.val('ahex').substring(0, 6) + 'ff' : settings.color.active.val('ahex') }), - current: _typeof(settings.color.active).toString().toLowerCase() === 'string' ? new Color({ ahex: !settings.window.alphaSupport && settings.color.active ? settings.color.active.substring(0, 6) + 'ff' : settings.color.active }) : new Color({ ahex: !settings.window.alphaSupport && settings.color.active.val('ahex') ? settings.color.active.val('ahex').substring(0, 6) + 'ff' : settings.color.active.val('ahex') + current: _typeof(settings.color.active).toString().toLowerCase() === 'string' ? new Color({ + ahex: !settings.window.alphaSupport && settings.color.active ? settings.color.active.substring(0, 6) + 'ff' : settings.color.active + }) : new Color({ + ahex: !settings.window.alphaSupport && settings.color.active.val('ahex') ? settings.color.active.val('ahex').substring(0, 6) + 'ff' : settings.color.active.val('ahex') }), quickList: settings.color.quickList }; + if (typeof commitCallback !== 'function') { + commitCallback = null; + } + + if (typeof liveCallback !== 'function') { + liveCallback = null; + } + + if (typeof cancelCallback !== 'function') { + cancelCallback = null; + } + var elementStartX = null, // Used to record the starting css positions for dragging the control elementStartY = null, @@ -24211,25 +27499,25 @@ // iconAlpha for popup icon iconImage = null, // iconImage popup icon - moveBar = null, - // drag bar - commitCallback = typeof $arguments[1] === 'function' ? $arguments[1] : null, - liveCallback = typeof $arguments[2] === 'function' ? $arguments[2] : null, - cancelCallback = typeof $arguments[3] === 'function' ? $arguments[3] : null; + moveBar = null; // drag bar - $.extend(true, $this, { + $.extend(true, that, { // public properties, methods, and callbacks - commitCallback: commitCallback, // commitCallback function can be overridden to return the selected color to a method you specify when the user clicks "OK" - liveCallback: liveCallback, // liveCallback function can be overridden to return the selected color to a method you specify in live mode (continuous update) - cancelCallback: cancelCallback, // cancelCallback function can be overridden to a method you specify when the user clicks "Cancel" + commitCallback: commitCallback, + // commitCallback function can be overridden to return the selected color to a method you specify when the user clicks "OK" + liveCallback: liveCallback, + // liveCallback function can be overridden to return the selected color to a method you specify in live mode (continuous update) + cancelCallback: cancelCallback, + // cancelCallback function can be overridden to a method you specify when the user clicks "Cancel" color: color, show: show, hide: hide, destroy: destroy // destroys this control entirely, removing all events and objects, and removing itself from the List + }); - List.push($this); + List.push(that); setTimeout(function () { - initialize.call($this); + initialize.call(that); }, 0); }); }; @@ -24239,17 +27527,20 @@ * @property {Float} width * @property {Float} height */ + /** * @typedef {PlainObject} external:jQuery.fn.jPickerOptionsImagesDimensionsArrow * @property {Float} width * @property {Float} height * @property {external:jQuery.fn.jPickerOptionsIconInfo} arrow */ + /** * @typedef {PlainObject} external:jQuery.fn.jPickerOptionsRadioTextboxLocale * @property {string} radio * @property {string} textbox */ + /** * @typedef {PlainObject} external:jQuery.fn.jPickerOptions * @property {PlainObject} window @@ -24271,6 +27562,9 @@ * @property {Float} window.alphaPrecision Set decimal precision for alpha percentage display - hex codes do * not map directly to percentage integers - range 0-2 * @property {boolean} window.updateInputColor Set to `false` to prevent binded input colors from changing + * @property {boolean} [window.bindToInput] Added by `$.fn.jPicker` + * @property {boolean} [window.expandable] Added by `$.fn.jPicker` + * @property {external:jQuery} [window.input] Added by `$.fn.jPicker` * @property {PlainObject} color * @property {"h"|"s"|"v"|"r"|"g"|"b"|"a"} color.mode Symbols stand for "h" (hue), "s" (saturation), "v" (value), "r" (red), "g" (green), "b" (blue), "a" (alpha) * @property {Color|string} color.active Strings are HEX values (e.g. #ffc000) WITH OR WITHOUT the "#" prefix @@ -24306,6 +27600,7 @@ * @property {string} localization.tooltips.hex.textbox * @property {string} localization.tooltips.hex.alpha */ + /** * jPicker defaults - you can change anything in this section (such as the * clientPath to your images) without fear of breaking the program @@ -24314,6 +27609,8 @@ * @borrows external:jQuery.fn.jPickerOptions as external:jQuery.fn.jPicker.defaults * @see Source for all of the values */ + + $.fn.jPicker.defaults = { window: { title: null, @@ -24336,8 +27633,294 @@ }, color: { mode: 'h', - active: new Color({ ahex: '#ffcc00ff' }), - quickList: [new Color({ h: 360, s: 33, v: 100 }), new Color({ h: 360, s: 66, v: 100 }), new Color({ h: 360, s: 100, v: 100 }), new Color({ h: 360, s: 100, v: 75 }), new Color({ h: 360, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 100 }), new Color({ h: 30, s: 33, v: 100 }), new Color({ h: 30, s: 66, v: 100 }), new Color({ h: 30, s: 100, v: 100 }), new Color({ h: 30, s: 100, v: 75 }), new Color({ h: 30, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 90 }), new Color({ h: 60, s: 33, v: 100 }), new Color({ h: 60, s: 66, v: 100 }), new Color({ h: 60, s: 100, v: 100 }), new Color({ h: 60, s: 100, v: 75 }), new Color({ h: 60, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 80 }), new Color({ h: 90, s: 33, v: 100 }), new Color({ h: 90, s: 66, v: 100 }), new Color({ h: 90, s: 100, v: 100 }), new Color({ h: 90, s: 100, v: 75 }), new Color({ h: 90, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 70 }), new Color({ h: 120, s: 33, v: 100 }), new Color({ h: 120, s: 66, v: 100 }), new Color({ h: 120, s: 100, v: 100 }), new Color({ h: 120, s: 100, v: 75 }), new Color({ h: 120, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 60 }), new Color({ h: 150, s: 33, v: 100 }), new Color({ h: 150, s: 66, v: 100 }), new Color({ h: 150, s: 100, v: 100 }), new Color({ h: 150, s: 100, v: 75 }), new Color({ h: 150, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 50 }), new Color({ h: 180, s: 33, v: 100 }), new Color({ h: 180, s: 66, v: 100 }), new Color({ h: 180, s: 100, v: 100 }), new Color({ h: 180, s: 100, v: 75 }), new Color({ h: 180, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 40 }), new Color({ h: 210, s: 33, v: 100 }), new Color({ h: 210, s: 66, v: 100 }), new Color({ h: 210, s: 100, v: 100 }), new Color({ h: 210, s: 100, v: 75 }), new Color({ h: 210, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 30 }), new Color({ h: 240, s: 33, v: 100 }), new Color({ h: 240, s: 66, v: 100 }), new Color({ h: 240, s: 100, v: 100 }), new Color({ h: 240, s: 100, v: 75 }), new Color({ h: 240, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 20 }), new Color({ h: 270, s: 33, v: 100 }), new Color({ h: 270, s: 66, v: 100 }), new Color({ h: 270, s: 100, v: 100 }), new Color({ h: 270, s: 100, v: 75 }), new Color({ h: 270, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 10 }), new Color({ h: 300, s: 33, v: 100 }), new Color({ h: 300, s: 66, v: 100 }), new Color({ h: 300, s: 100, v: 100 }), new Color({ h: 300, s: 100, v: 75 }), new Color({ h: 300, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 0 }), new Color({ h: 330, s: 33, v: 100 }), new Color({ h: 330, s: 66, v: 100 }), new Color({ h: 330, s: 100, v: 100 }), new Color({ h: 330, s: 100, v: 75 }), new Color({ h: 330, s: 100, v: 50 }), new Color()] + active: new Color({ + ahex: '#ffcc00ff' + }), + quickList: [new Color({ + h: 360, + s: 33, + v: 100 + }), new Color({ + h: 360, + s: 66, + v: 100 + }), new Color({ + h: 360, + s: 100, + v: 100 + }), new Color({ + h: 360, + s: 100, + v: 75 + }), new Color({ + h: 360, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 100 + }), new Color({ + h: 30, + s: 33, + v: 100 + }), new Color({ + h: 30, + s: 66, + v: 100 + }), new Color({ + h: 30, + s: 100, + v: 100 + }), new Color({ + h: 30, + s: 100, + v: 75 + }), new Color({ + h: 30, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 90 + }), new Color({ + h: 60, + s: 33, + v: 100 + }), new Color({ + h: 60, + s: 66, + v: 100 + }), new Color({ + h: 60, + s: 100, + v: 100 + }), new Color({ + h: 60, + s: 100, + v: 75 + }), new Color({ + h: 60, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 80 + }), new Color({ + h: 90, + s: 33, + v: 100 + }), new Color({ + h: 90, + s: 66, + v: 100 + }), new Color({ + h: 90, + s: 100, + v: 100 + }), new Color({ + h: 90, + s: 100, + v: 75 + }), new Color({ + h: 90, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 70 + }), new Color({ + h: 120, + s: 33, + v: 100 + }), new Color({ + h: 120, + s: 66, + v: 100 + }), new Color({ + h: 120, + s: 100, + v: 100 + }), new Color({ + h: 120, + s: 100, + v: 75 + }), new Color({ + h: 120, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 60 + }), new Color({ + h: 150, + s: 33, + v: 100 + }), new Color({ + h: 150, + s: 66, + v: 100 + }), new Color({ + h: 150, + s: 100, + v: 100 + }), new Color({ + h: 150, + s: 100, + v: 75 + }), new Color({ + h: 150, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 50 + }), new Color({ + h: 180, + s: 33, + v: 100 + }), new Color({ + h: 180, + s: 66, + v: 100 + }), new Color({ + h: 180, + s: 100, + v: 100 + }), new Color({ + h: 180, + s: 100, + v: 75 + }), new Color({ + h: 180, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 40 + }), new Color({ + h: 210, + s: 33, + v: 100 + }), new Color({ + h: 210, + s: 66, + v: 100 + }), new Color({ + h: 210, + s: 100, + v: 100 + }), new Color({ + h: 210, + s: 100, + v: 75 + }), new Color({ + h: 210, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 30 + }), new Color({ + h: 240, + s: 33, + v: 100 + }), new Color({ + h: 240, + s: 66, + v: 100 + }), new Color({ + h: 240, + s: 100, + v: 100 + }), new Color({ + h: 240, + s: 100, + v: 75 + }), new Color({ + h: 240, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 20 + }), new Color({ + h: 270, + s: 33, + v: 100 + }), new Color({ + h: 270, + s: 66, + v: 100 + }), new Color({ + h: 270, + s: 100, + v: 100 + }), new Color({ + h: 270, + s: 100, + v: 75 + }), new Color({ + h: 270, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 10 + }), new Color({ + h: 300, + s: 33, + v: 100 + }), new Color({ + h: 300, + s: 66, + v: 100 + }), new Color({ + h: 300, + s: 100, + v: 100 + }), new Color({ + h: 300, + s: 100, + v: 75 + }), new Color({ + h: 300, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 0 + }), new Color({ + h: 330, + s: 33, + v: 100 + }), new Color({ + h: 330, + s: 66, + v: 100 + }), new Color({ + h: 330, + s: 100, + v: 100 + }), new Color({ + h: 330, + s: 100, + v: 75 + }), new Color({ + h: 330, + s: 100, + v: 50 + }), new Color()] }, images: { clientPath: '/jPicker/images/', @@ -24420,45 +28003,47 @@ return $; }; - /* globals jQuery */ - var $$a = jQuery; - - var langParam = void 0; - + var langParam; /** * @param {"content"|"title"} type * @param {module:locale.LocaleSelectorValue} obj * @param {boolean} ids * @returns {undefined} */ + var setStrings = function setStrings(type, obj, ids) { // Root element to look for element from var parent = $$a('#svg_editor').parent(); Object.entries(obj).forEach(function (_ref) { - var _ref2 = slicedToArray(_ref, 2), + var _ref2 = _slicedToArray(_ref, 2), sel = _ref2[0], val = _ref2[1]; if (!val) { - console.log(sel); + console.log(sel); // eslint-disable-line no-console } if (ids) { sel = '#' + sel; } + var $elem = parent.find(sel); + if ($elem.length) { var elem = parent.find(sel)[0]; switch (type) { case 'content': - for (var i = 0, node; node = elem.childNodes[i]; i++) { + _toConsumableArray(elem.childNodes).some(function (node) { if (node.nodeType === 3 && node.textContent.trim()) { node.textContent = val; - break; + return true; } - } + + return false; + }); + break; case 'title': @@ -24466,11 +28051,10 @@ break; } } else { - console.log('Missing: ' + sel); + console.log('Missing element for localization: ' + sel); // eslint-disable-line no-console } }); }; - /** * The "data" property is generally set to an an array of objects with * "id" and "title" or "textContent" properties @@ -24481,23 +28065,24 @@ /** * @interface module:locale.LocaleEditorInit */ + /** * @function module:locale.LocaleEditorInit#addLangData * @param {string} langParam * @returns {module:locale.AddLangExtensionLocaleData} */ - var editor_ = void 0; + var editor_; /** * @function init * @memberof module:locale * @param {module:locale.LocaleEditorInit} editor * @returns {undefined} */ + var init$7 = function init(editor) { editor_ = editor; }; - /** * @typedef {PlainObject} module:locale.LangAndData * @property {string} langParam @@ -24510,8 +28095,13 @@ * @fires module:svgcanvas.SvgCanvas#event:ext-addLangData * @returns {Promise} Resolves to [`LangAndData`]{@link module:locale.LangAndData} */ - var readLang = function () { - var _ref3 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(langData) { + + var readLang = + /*#__PURE__*/ + function () { + var _ref3 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee(langData) { var more, _langData, tools, properties, config, layers, common, ui, opts; return regeneratorRuntime.wrap(function _callee$(_context) { @@ -24523,26 +28113,21 @@ case 2: more = _context.sent; - $$a.each(more, function (i, m) { if (m.data) { langData = $$a.merge(langData, m.data); } - }); - - // Old locale file, do nothing for now. + }); // Old locale file, do nothing for now. if (langData.tools) { _context.next = 6; break; } - return _context.abrupt('return'); + return _context.abrupt("return", undefined); case 6: _langData = langData, tools = _langData.tools, properties = _langData.properties, config = _langData.config, layers = _langData.layers, common = _langData.common, ui = _langData.ui; - - setStrings('content', { // copyrightLabel: misc.powered_by, // Currently commented out in svg-editor.html curve_segments: properties.curve_segments, @@ -24551,7 +28136,6 @@ fit_to_canvas: tools.fit_to_canvas, fit_to_layer_content: tools.fit_to_layer_content, fit_to_sel: tools.fit_to_sel, - icon_large: config.icon_large, icon_medium: config.icon_medium, icon_small: config.icon_small, @@ -24559,19 +28143,15 @@ image_opt_embed: config.image_opt_embed, image_opt_ref: config.image_opt_ref, includedImages: config.included_images, - largest_object: tools.largest_object, - layersLabel: layers.layers, page: tools.page, relativeToLabel: tools.relativeTo, selLayerLabel: layers.move_elems_to, selectedPredefined: config.select_predefined, - selected_objects: tools.selected_objects, smallest_object: tools.smallest_object, straight_segments: properties.straight_segments, - svginfo_bg_url: config.editor_img_url + ':', svginfo_bg_note: config.editor_bg_note, svginfo_change_background: config.background, @@ -24583,50 +28163,37 @@ svginfo_lang: config.language, svginfo_title: config.doc_title, svginfo_width: common.width, - tool_docprops_cancel: common.cancel, tool_docprops_save: common.ok, - tool_source_cancel: common.cancel, tool_source_save: common.ok, - tool_prefs_cancel: common.cancel, tool_prefs_save: common.ok, - sidepanel_handle: layers.layers.split('').join(' '), - tool_clear: tools.new_doc, tool_docprops: tools.docprops, tool_export: tools.export_img, tool_import: tools.import_doc, tool_open: tools.open_doc, tool_save: tools.save_doc, - svginfo_units_rulers: config.units_and_rulers, svginfo_rulers_onoff: config.show_rulers, svginfo_unit: config.base_unit, - svginfo_grid_settings: config.grid, svginfo_snap_onoff: config.snapping_onoff, svginfo_snap_step: config.snapping_stepsize, svginfo_grid_color: config.grid_color - }, true); + }, true); // Context menus - // Context menus opts = {}; - $$a.each(['cut', 'copy', 'paste', 'paste_in_place', 'delete', 'group', 'ungroup', 'move_front', 'move_up', 'move_down', 'move_back'], function () { opts['#cmenu_canvas a[href="#' + this + '"]'] = tools[this]; }); - $$a.each(['dupe', 'merge_down', 'merge_all'], function () { opts['#cmenu_layers a[href="#' + this + '"]'] = layers[this]; }); - opts['#cmenu_layers a[href="#delete"]'] = layers.del; - setStrings('content', opts); - setStrings('title', { align_relative_to: tools.align_relative_to, circle_cx: properties.circle_cx, @@ -24645,7 +28212,7 @@ image_width: properties.image_width, layer_delete: layers.del, layer_down: layers.move_down, - layer_new: layers['new'], + layer_new: layers.new, layer_rename: layers.rename, layer_moreopts: common.more_opts, layer_up: layers.move_up, @@ -24724,13 +28291,14 @@ tool_wireframe: tools.wireframe_mode, tool_zoom: tools.mode_zoom, url_notice: tools.no_embed - }, true); - - return _context.abrupt('return', { langParam: langParam, langData: langData }); + return _context.abrupt("return", { + langParam: langParam, + langData: langData + }); case 15: - case 'end': + case "end": return _context.stop(); } } @@ -24741,7 +28309,6 @@ return _ref3.apply(this, arguments); }; }(); - /** * @function module:locale.putLocale * @param {string} givenParam @@ -24752,8 +28319,13 @@ * @fires module:svgcanvas.SvgCanvas#event:ext-langChanged * @returns {Promise} Resolves to result of {@link module:locale.readLang} */ - var putLocale = function () { - var _ref4 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(givenParam, goodLangs, conf) { + + var putLocale = + /*#__PURE__*/ + function () { + var _ref4 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee2(givenParam, goodLangs, conf) { var url; return regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { @@ -24763,6 +28335,7 @@ langParam = givenParam; } else { langParam = $$a.pref('lang'); + if (!langParam) { if (navigator.userLanguage) { // Explorer @@ -24773,18 +28346,17 @@ } } - console.log('Lang: ' + langParam); - + console.log('Lang: ' + langParam); // eslint-disable-line no-console // Set to English if language is not in list of good langs + if (!goodLangs.includes(langParam) && langParam !== 'test') { langParam = 'en'; - } - - // don't bother on first run if language is English + } // don't bother on first run if language is English // The following line prevents setLang from running // extensions which depend on updated uiStrings, // so commenting it out. // if (langParam.startsWith('en')) {return;} + } url = conf.langPath + 'lang.' + langParam + '.js'; @@ -24796,10 +28368,10 @@ case 5: _context2.t1 = _context2.sent; - return _context2.abrupt('return', (0, _context2.t0)(_context2.t1)); + return _context2.abrupt("return", (0, _context2.t0)(_context2.t1)); case 7: - case 'end': + case "end": return _context2.stop(); } } @@ -24812,109 +28384,119 @@ }(); function loadStylesheets(stylesheets) { - var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, - beforeDefault = _ref.before, - afterDefault = _ref.after, - faviconDefault = _ref.favicon, - canvasDefault = _ref.canvas, - _ref$image = _ref.image, - imageDefault = _ref$image === undefined ? true : _ref$image, - acceptErrors = _ref.acceptErrors; + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + beforeDefault = _ref.before, + afterDefault = _ref.after, + faviconDefault = _ref.favicon, + canvasDefault = _ref.canvas, + _ref$image = _ref.image, + imageDefault = _ref$image === void 0 ? true : _ref$image, + acceptErrors = _ref.acceptErrors; - stylesheets = Array.isArray(stylesheets) ? stylesheets : [stylesheets]; + stylesheets = Array.isArray(stylesheets) ? stylesheets : [stylesheets]; - function setupLink(stylesheetURL) { - var options = {}; - if (Array.isArray(stylesheetURL)) { - var _stylesheetURL = stylesheetURL; + function setupLink(stylesheetURL) { + var options = {}; - var _stylesheetURL2 = slicedToArray(_stylesheetURL, 2); + if (Array.isArray(stylesheetURL)) { + var _stylesheetURL = stylesheetURL; - stylesheetURL = _stylesheetURL2[0]; - var _stylesheetURL2$ = _stylesheetURL2[1]; - options = _stylesheetURL2$ === undefined ? {} : _stylesheetURL2$; - } - var _options = options, - _options$favicon = _options.favicon, - favicon = _options$favicon === undefined ? faviconDefault : _options$favicon; - var _options2 = options, - _options2$before = _options2.before, - before = _options2$before === undefined ? beforeDefault : _options2$before, - _options2$after = _options2.after, - after = _options2$after === undefined ? afterDefault : _options2$after, - _options2$canvas = _options2.canvas, - canvas = _options2$canvas === undefined ? canvasDefault : _options2$canvas, - _options2$image = _options2.image, - image = _options2$image === undefined ? imageDefault : _options2$image; + var _stylesheetURL2 = _slicedToArray(_stylesheetURL, 2); - function addLink() { - if (before) { - before.before(link); - } else if (after) { - after.after(link); - } else { - document.head.appendChild(link); - } - } - - var link = document.createElement('link'); - return new Promise(function (resolve, reject) { - var rej = reject; - if (acceptErrors) { - rej = typeof acceptErrors === 'function' ? function (error) { - acceptErrors({ error: error, stylesheetURL: stylesheetURL, options: options, resolve: resolve, reject: reject }); - } : resolve; - } - if (stylesheetURL.endsWith('.css')) { - favicon = false; - } else if (stylesheetURL.endsWith('.ico')) { - favicon = true; - } - if (favicon) { - link.rel = 'shortcut icon'; - link.type = 'image/x-icon'; - - if (image === false) { - link.href = stylesheetURL; - addLink(); - resolve(link); - return; - } - - var cnv = document.createElement('canvas'); - cnv.width = 16; - cnv.height = 16; - var context = cnv.getContext('2d'); - var img = document.createElement('img'); - img.addEventListener('error', function (error) { - reject(error); - }); - img.addEventListener('load', function () { - context.drawImage(img, 0, 0); - link.href = canvas ? cnv.toDataURL('image/x-icon') : stylesheetURL; - addLink(); - resolve(link); - }); - img.src = stylesheetURL; - return; - } - link.rel = 'stylesheet'; - link.type = 'text/css'; - link.href = stylesheetURL; - addLink(); - link.addEventListener('error', function (error) { - rej(error); - }); - link.addEventListener('load', function () { - resolve(link); - }); - }); + stylesheetURL = _stylesheetURL2[0]; + var _stylesheetURL2$ = _stylesheetURL2[1]; + options = _stylesheetURL2$ === void 0 ? {} : _stylesheetURL2$; } - return Promise.all(stylesheets.map(setupLink)); - } + var _options = options, + _options$favicon = _options.favicon, + favicon = _options$favicon === void 0 ? faviconDefault : _options$favicon; + var _options2 = options, + _options2$before = _options2.before, + before = _options2$before === void 0 ? beforeDefault : _options2$before, + _options2$after = _options2.after, + after = _options2$after === void 0 ? afterDefault : _options2$after, + _options2$canvas = _options2.canvas, + canvas = _options2$canvas === void 0 ? canvasDefault : _options2$canvas, + _options2$image = _options2.image, + image = _options2$image === void 0 ? imageDefault : _options2$image; - /* globals jQuery */ + function addLink() { + if (before) { + before.before(link); + } else if (after) { + after.after(link); + } else { + document.head.appendChild(link); + } + } + + var link = document.createElement('link'); + return new Promise(function (resolve, reject) { + var rej = reject; + + if (acceptErrors) { + rej = typeof acceptErrors === 'function' ? function (error) { + acceptErrors({ + error: error, + stylesheetURL: stylesheetURL, + options: options, + resolve: resolve, + reject: reject + }); + } : resolve; + } + + if (stylesheetURL.endsWith('.css')) { + favicon = false; + } else if (stylesheetURL.endsWith('.ico')) { + favicon = true; + } + + if (favicon) { + link.rel = 'shortcut icon'; + link.type = 'image/x-icon'; + + if (image === false) { + link.href = stylesheetURL; + addLink(); + resolve(link); + return; + } + + var cnv = document.createElement('canvas'); + cnv.width = 16; + cnv.height = 16; + var context = cnv.getContext('2d'); + var img = document.createElement('img'); + img.addEventListener('error', function (error) { + reject(error); + }); + img.addEventListener('load', function () { + context.drawImage(img, 0, 0); + link.href = canvas ? cnv.toDataURL('image/x-icon') : stylesheetURL; + addLink(); + resolve(link); + }); + img.src = stylesheetURL; + return; + } + + link.rel = 'stylesheet'; + link.type = 'text/css'; + link.href = stylesheetURL; + addLink(); + link.addEventListener('error', function (error) { + rej(error); + }); + link.addEventListener('load', function () { + resolve(link); + }); + }); + } + + return Promise.all(stylesheets.map(setupLink)); + } /** * The main module for the visual SVG Editor @@ -24931,58 +28513,70 @@ * @borrows module:locale.readLang as readLang * @borrows module:locale.setStrings as setStrings */ + var editor = {}; - - var $$b = [jqPluginJSHotkeys, jqPluginBBQ, jqPluginSVGIcons, jqPluginJGraduate, jqPluginSpinBtn, jqPluginSVG, jQueryContextMenu, jPicker].reduce(function ($, cb) { - return cb($); + var $$b = [jQueryPluginJSHotkeys, jQueryPluginBBQ, jQueryPluginSVGIcons, jQueryPluginJGraduate, jQueryPluginSpinButton, jQueryPluginSVG, jQueryContextMenu, jPicker].reduce(function (jq, func) { + return func(jq); }, jQuery); - /* if (!$.loadingStylesheets) { $.loadingStylesheets = []; } */ + var stylesheet = 'svg-editor.css'; + if (!$$b.loadingStylesheets.includes(stylesheet)) { $$b.loadingStylesheets.push(stylesheet); } + var favicon = 'images/logo.png'; + if ($$b.loadingStylesheets.some(function (item) { return !Array.isArray(item) || item[0] !== favicon; })) { - $$b.loadingStylesheets.push([favicon, { favicon: true }]); - } - - // EDITOR PROPERTIES: (defined below) + $$b.loadingStylesheets.push([favicon, { + favicon: true + }]); + } // EDITOR PROPERTIES: (defined below) // curPrefs, curConfig, canvas, storage, uiStrings // // STATE MAINTENANCE PROPERTIES + /** * @type {Float} */ + + editor.tool_scale = 1; // Dependent on icon size, so any use to making configurable instead? Used by `jQuery.SpinButton.js` + /** * @type {Integer} */ + editor.exportWindowCt = 0; /** * @type {boolean} */ + editor.langChanged = false; /** * @type {boolean} */ + editor.showSaveWarning = false; /** - * @type {boolean} + * Will be set to a boolean by `ext-storage.js` + * @type {"ignore"|"waiting"|"closed"} */ - editor.storagePromptClosed = false; // For use with ext-storage.js + editor.storagePromptState = 'ignore'; var callbacks = [], /** * @typedef {"s"|"m"|"l"|"xl"|Float} module:SVGEditor.IconSize */ + /** * Preferences * @interface module:SVGEditor.Prefs @@ -24995,18 +28589,23 @@ * @property {boolean} [export_notice_done=false] Used to track alert status * @todo `save_notice_done` and `export_notice_done` should be changed to flags rather than preferences */ + /** * @namespace {module:SVGEditor.Prefs} defaultPrefs * @memberof module:SVGEditor~ * @implements {module:SVGEditor.Prefs} */ // The iteration algorithm for defaultPrefs does not currently support array/objects - defaultPrefs = /** @lends module:SVGEditor~defaultPrefs */{ + defaultPrefs = + /** @lends module:SVGEditor~defaultPrefs */ + { // EDITOR OPTIONS (DIALOG) + /** * Default to "en" if locale.js detection does not detect another language */ lang: '', + /** * Will default to 's' if the window height is smaller than the minimum height and * 'm' otherwise @@ -25031,12 +28630,14 @@ /** * @typedef {"@default"|string} module:SVGEditor.Stylesheet `@default` will automatically load all of the default CSS paths for SVGEditor */ + /** * @typedef {GenericArray} module:SVGEditor.XYDimensions * @property {Integer} length 2 * @property {Float} 0 * @property {Float} 1 */ + /** * @tutorial ConfigOptions * @interface module:SVGEditor.Config @@ -25058,7 +28659,7 @@ * @property {boolean} [emptyStorageOnDecline=false] Used by `ext-storage.js`; empty any prior storage if the user declines to store * @property {string[]} [extensions=module:SVGEditor~defaultExtensions] Extensions to load on startup. Use an array in `setConfig` and comma separated file names in the URL. Extension names must begin with "ext-". Note that as of version 2.7, paths containing "/", "\", or ":", are disallowed for security reasons. Although previous versions of this list would entirely override the default list, as of version 2.7, the defaults will always be added to this explicit list unless the configuration `noDefaultExtensions` is included. * @property {module:SVGEditor.Stylesheet[]} [stylesheets=["@default"]] An array of required stylesheets to load in parallel; include the value `"@default"` within this array to ensure all default stylesheets are loaded. - * @property {string[]} [allowedOrigins=[]] Used by `ext-xdomain-messaging.js` to indicate which origins are permitted for cross-domain messaging (e.g., between the embedded editor and main editor code). Besides explicit domains, one might add '' to allow all domains (not recommended for privacy/data integrity of your user's content!), `window.location.origin` for allowing the same origin (should be safe if you trust all apps on your domain), 'null' to allow `file://` URL usage + * @property {string[]} [allowedOrigins=[]] Used by `ext-xdomain-messaging.js` to indicate which origins are permitted for cross-domain messaging (e.g., between the embedded editor and main editor code). Besides explicit domains, one might add '*' to allow all domains (not recommended for privacy/data integrity of your user's content!), `window.location.origin` for allowing the same origin (should be safe if you trust all apps on your domain), 'null' to allow `file:///` URL usage * @property {null|PlainObject} [colorPickerCSS=null] Object of CSS properties mapped to values (for jQuery) to apply to the color picker. See {@link http://api.jquery.com/css/#css-properties}. A `null` value (the default) will cause the CSS to default to `left` with a position equal to that of the `fill_color` or `stroke_color` element minus 140, and a `bottom` equal to 40 * @property {string} [paramurl] This was available via URL only. Allowed an un-encoded URL within the query string (use "url" or "source" with a data: URI instead) * @property {Float} [canvas_expansion=3] The minimum area visible outside the canvas, as a multiple of the image dimensions. The larger the number, the more one can scroll outside the canvas. @@ -25089,6 +28690,7 @@ * @property {boolean} [selectNew=true] If true, will replace the selection with the current element and automatically select element objects (when not in "path" mode) after they are created, showing their grips (v2.6). Set and used in `svgcanvas.js` (`mouseUp`). * @todo Some others could be preferences as well (e.g., preventing URL changing of extensions, defaultExtensions, stylesheets, colorPickerCSS); Change the following to preferences and add pref controls where missing to the UI (e.g., `canvas_expansion`, `initFill`, `initStroke`, `text`, `initOpacity`, `dimensions`, `initTool`, `wireframe`, `showlayers`, `gridSnapping`, `gridColor`, `baseUnit`, `snappingStep`, `showRulers`, `exportWindowType`, `showGrid`, `show_outside_canvas`, `selectNew`)? */ + /** * @namespace {module:SVGEditor.Config} defaultConfig * @memberof module:SVGEditor~ @@ -25098,12 +28700,14 @@ canvasName: 'default', canvas_expansion: 3, initFill: { - color: 'FF0000', // solid red + color: 'FF0000', + // solid red opacity: 1 }, initStroke: { width: 5, - color: '000000', // solid black + color: '000000', + // solid black opacity: 1 }, text: { @@ -25112,21 +28716,27 @@ font_family: 'serif' }, initOpacity: 1, - colorPickerCSS: null, // Defaults to 'left' with a position equal to that of the fill_color or stroke_color element minus 140, and a 'bottom' equal to 40 + colorPickerCSS: null, + // Defaults to 'left' with a position equal to that of the fill_color or stroke_color element minus 140, and a 'bottom' equal to 40 initTool: 'select', - exportWindowType: 'new', // 'same' (todo: also support 'download') + exportWindowType: 'new', + // 'same' (todo: also support 'download') wireframe: false, showlayers: false, no_save_warning: false, // PATH CONFIGURATION // The following path configuration items are disallowed in the URL (as should any future path configurations) + langPath: 'locale/', + // Default will be changed if this is a non-modular load + extPath: 'extensions/', + // Default will be changed if this is a non-modular load + canvgPath: 'canvg/', + // Default will be changed if this is a non-modular load + jspdfPath: 'jspdf/', + // Default will be changed if this is a non-modular load imgPath: 'images/', - langPath: 'locale/', // Default will be changed if this is a modular load - extPath: 'extensions/', // Default will be changed if this is a modular load - canvgPath: 'canvg/', // Default will be changed if this is a modular load - jspdfPath: 'jspdf/', // Default will be changed if this is a modular load - extIconsPath: 'extensions/', jGraduatePath: 'jgraduate/images/', + extIconsPath: 'extensions/', // DOCUMENT PROPERTIES // Change the following to a preference (already in the Document Properties dialog)? dimensions: [640, 480], @@ -25141,14 +28751,20 @@ preventAllURLConfig: false, preventURLContentLoading: false, // EXTENSION CONFIGURATION (see also preventAllURLConfig) - lockExtensions: false, // Disallowed in URL setting - noDefaultExtensions: false, // noDefaultExtensions can only be meaningfully used in `svgedit-config-iife.js` or in the URL + lockExtensions: false, + // Disallowed in URL setting + noDefaultExtensions: false, + // noDefaultExtensions can only be meaningfully used in `svgedit-config-iife.js` or in the URL // EXTENSION-RELATED (GRID) - showGrid: false, // Set by ext-grid.js + showGrid: false, + // Set by ext-grid.js // EXTENSION-RELATED (STORAGE) - noStorageOnLoad: false, // Some interaction with ext-storage.js; prevent even the loading of previously saved local storage - forceStorage: false, // Some interaction with ext-storage.js; strongly discouraged from modification as it bypasses user privacy by preventing them from choosing whether to keep local storage or not + noStorageOnLoad: false, + // Some interaction with ext-storage.js; prevent even the loading of previously saved local storage + forceStorage: false, + // Some interaction with ext-storage.js; strongly discouraged from modification as it bypasses user privacy by preventing them from choosing whether to keep local storage or not emptyStorageOnDecline: false // Used by ext-storage.js; empty any prior storage if the user declines to store + }, /** @@ -25157,15 +28773,13 @@ * @type {PlainObject} */ uiStrings$1 = editor.uiStrings = {}; - - var svgCanvas = void 0, - urldata = void 0, + var svgCanvas, + urldata, isReady = false, customExportImage = false, customExportPDF = false, curPrefs = {}, - - // Note: The difference between Prefs and Config is that Prefs + // Note: The difference between Prefs and Config is that Prefs // can be changed in the UI and are stored in the browser, // while config cannot curConfig = { @@ -25173,121 +28787,168 @@ // procedures (we obtain instead from defaultExtensions) extensions: [], stylesheets: [], + /** - * Can use window.location.origin to indicate the current + * Can use `location.origin` to indicate the current * origin. Can contain a '*' to allow all domains or 'null' (as - * a string) to support all file:// URLs. Cannot be set by + * a string) to support all `file:///` URLs. Cannot be set by * URL for security reasons (not safe, at least for * privacy or data integrity of SVG content). * Might have been fairly safe to allow - * `new URL(window.location.href).origin` by default but + * `new URL(location.href).origin` by default but * avoiding it ensures some more security that even third * party apps on the same domain also cannot communicate * with this app by default. - * For use with ext-xdomain-messaging.js + * For use with `ext-xdomain-messaging.js` * @todo We might instead make as a user-facing preference. */ allowedOrigins: [] }; + /** + * + * @param {string} str SVG string + * @param {PlainObject} [opts={}] + * @param {boolean} [opts.noAlert] + * @throws {Error} Upon failure to load SVG + * @returns {Promise} Resolves to undefined upon success (or if `noAlert` is + * falsey, though only until after the `alert` is closed); rejects if SVG + * loading fails and `noAlert` is truthy. + */ - function loadSvgString(str, callback) { - var success = svgCanvas.setSvgString(str) !== false; - callback = callback || $$b.noop; - if (success) { - callback(true); // eslint-disable-line standard/no-callback-literal - } else { - $$b.alert(uiStrings$1.notification.errorLoadingSVG, function () { - callback(false); // eslint-disable-line standard/no-callback-literal - }); - } + function loadSvgString(_x) { + return _loadSvgString.apply(this, arguments); } - /** * @function module:SVGEditor~getImportLocale - * @param {string} defaultLang - * @param {string} defaultName + * @param {PlainObject} defaults + * @param {string} defaults.defaultLang + * @param {string} defaults.defaultName * @returns {module:SVGEditor~ImportLocale} */ + + + function _loadSvgString() { + _loadSvgString = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee23(str) { + var _ref45, + noAlert, + success, + _args23 = arguments; + + return regeneratorRuntime.wrap(function _callee23$(_context23) { + while (1) { + switch (_context23.prev = _context23.next) { + case 0: + _ref45 = _args23.length > 1 && _args23[1] !== undefined ? _args23[1] : {}, noAlert = _ref45.noAlert; + success = svgCanvas.setSvgString(str) !== false; + + if (!success) { + _context23.next = 4; + break; + } + + return _context23.abrupt("return"); + + case 4: + if (noAlert) { + _context23.next = 8; + break; + } + + _context23.next = 7; + return $$b.alert(uiStrings$1.notification.errorLoadingSVG); + + case 7: + return _context23.abrupt("return"); + + case 8: + throw new Error('Error loading SVG'); + + case 9: + case "end": + return _context23.stop(); + } + } + }, _callee23, this); + })); + return _loadSvgString.apply(this, arguments); + } + function getImportLocale(_ref) { var defaultLang = _ref.defaultLang, defaultName = _ref.defaultName; /** * @function module:SVGEditor~ImportLocale - * @param {string} [name] Defaults to `defaultName` of {@link module:SVGEditor~getImportLocale} - * @param {string} [lang=defaultLang] Defaults to `defaultLang` of {@link module:SVGEditor~getImportLocale} + * @param {PlainObject} localeInfo + * @param {string} [localeInfo.name] Defaults to `defaultName` 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} */ - return function () { - var _ref2 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2() { - var importLocale = function () { - var _ref4 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(lang) { - var url; - return regeneratorRuntime.wrap(function _callee$(_context) { - while (1) { - switch (_context.prev = _context.next) { - case 0: - url = curConfig.extPath + 'ext-locale/' + name + '/' + lang + '.js'; - return _context.abrupt('return', importSetGlobalDefault(url, { - global: 'svgEditorExtensionLocale_' + name + '_' + lang - })); + return ( + /*#__PURE__*/ + function () { + var _importLocaleDefaulting = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee() { + var _ref2, + _ref2$name, + name, + _ref2$lang, + lang, + importLocale, + _args = arguments; - case 2: - case 'end': - return _context.stop(); - } + return regeneratorRuntime.wrap(function _callee$(_context) { + while (1) { + switch (_context.prev = _context.next) { + case 0: + importLocale = function _ref3(language) { + var url = "".concat(curConfig.extPath, "ext-locale/").concat(name, "/").concat(language, ".js"); + return importSetGlobalDefault(url, { + global: "svgEditorExtensionLocale_".concat(name, "_").concat(language.replace(/-/g, '_')) + }); + }; + + _ref2 = _args.length > 0 && _args[0] !== undefined ? _args[0] : {}, _ref2$name = _ref2.name, name = _ref2$name === void 0 ? defaultName : _ref2$name, _ref2$lang = _ref2.lang, lang = _ref2$lang === void 0 ? defaultLang : _ref2$lang; + _context.prev = 2; + _context.next = 5; + return importLocale(lang); + + case 5: + return _context.abrupt("return", _context.sent); + + case 8: + _context.prev = 8; + _context.t0 = _context["catch"](2); + return _context.abrupt("return", importLocale('en')); + + case 11: + case "end": + return _context.stop(); } - }, _callee, this); - })); - - return function importLocale(_x2) { - return _ref4.apply(this, arguments); - }; - }(); - - var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, - _ref3$name = _ref3.name, - name = _ref3$name === undefined ? defaultName : _ref3$name, - _ref3$lang = _ref3.lang, - lang = _ref3$lang === undefined ? defaultLang : _ref3$lang; - - return regeneratorRuntime.wrap(function _callee2$(_context2) { - while (1) { - switch (_context2.prev = _context2.next) { - case 0: - _context2.prev = 0; - return _context2.abrupt('return', importLocale(lang)); - - case 4: - _context2.prev = 4; - _context2.t0 = _context2['catch'](0); - return _context2.abrupt('return', importLocale('en')); - - case 7: - case 'end': - return _context2.stop(); } - } - }, _callee2, this, [[0, 4]]); - })); + }, _callee, this, [[2, 8]]); + })); - function importLocale() { - return _ref2.apply(this, arguments); - } + function importLocaleDefaulting() { + return _importLocaleDefaulting.apply(this, arguments); + } - return importLocale; - }(); + return importLocaleDefaulting; + }() + ); } - /** * EXPORTS */ /** - * Store and retrieve preferences + * Store and retrieve preferences. * @param {string} key The preference name to be retrieved or set * @param {string} [val] The value. If the value supplied is missing or falsey, no change to the preference will be made. - * @returns {string} If val is missing or falsey, the value of the previously stored preference will be returned. + * @returns {string|undefined} If val is missing or falsey, the value of the previously stored preference will be returned. * @todo Can we change setting on the jQuery namespace (onto editor) to avoid conflicts? * @todo Review whether any remaining existing direct references to * getting `curPrefs` can be changed to use `$.pref()` getting to ensure @@ -25295,6 +28956,8 @@ * the pref dialog has a button to auto-calculate background, but otherwise uses `$.pref()` to be able to get default prefs * or overridable settings */ + + $$b.pref = function (key, val) { if (val) { curPrefs[key] = val; @@ -25303,21 +28966,24 @@ * @memberof module:SVGEditor * @implements {module:SVGEditor.Prefs} */ + editor.curPrefs = curPrefs; // Update exported value - return; + + return undefined; } + return key in curPrefs ? curPrefs[key] : defaultPrefs[key]; }; - /* * EDITOR PUBLIC METHODS // Todo: Sort these methods per invocation order, ideally with init at the end // Todo: Prevent execution until init executes if dependent on it? */ + + editor.putLocale = putLocale; editor.readLang = readLang; editor.setStrings = setStrings; - /** * Where permitted, sets canvas and/or `defaultPrefs` based on previous * storage. This will override URL settings (for security reasons) but @@ -25331,41 +28997,41 @@ * that, it will then be subject to tampering * @returns {undefined} */ - editor.loadContentAndPrefs = function () { - if (!curConfig.forceStorage && (curConfig.noStorageOnLoad || !document.cookie.match(/(?:^|;\s*)store=(?:prefsAndContent|prefsOnly)/))) { - return; - } - // LOAD CONTENT + editor.loadContentAndPrefs = function () { + if (!curConfig.forceStorage && (curConfig.noStorageOnLoad || !document.cookie.match(/(?:^|;\s*)svgeditstore=(?:prefsAndContent|prefsOnly)/))) { + return; + } // LOAD CONTENT + + if (editor.storage && ( // Cookies do not have enough available memory to hold large documents - curConfig.forceStorage || !curConfig.noStorageOnLoad && document.cookie.match(/(?:^|;\s*)store=prefsAndContent/))) { - var _name = 'svgedit-' + curConfig.canvasName; - var cached = editor.storage.getItem(_name); + curConfig.forceStorage || !curConfig.noStorageOnLoad && document.cookie.match(/(?:^|;\s*)svgeditstore=prefsAndContent/))) { + var name = 'svgedit-' + curConfig.canvasName; + var cached = editor.storage.getItem(name); + if (cached) { editor.loadFromString(cached); } - } + } // LOAD PREFS - // LOAD PREFS - for (var key in defaultPrefs) { - if (defaultPrefs.hasOwnProperty(key)) { - // It's our own config, so we don't need to iterate up the prototype chain - var storeKey = 'svg-edit-' + key; - if (editor.storage) { - var val = editor.storage.getItem(storeKey); - if (val) { - defaultPrefs[key] = String(val); // Convert to string for FF (.value fails in Webkit) - } - } else if (window.widget) { - defaultPrefs[key] = window.widget.preferenceForKey(storeKey); - } else { - var result = document.cookie.match(new RegExp('(?:^|;\\s*)' + regexEscape(encodeURIComponent(storeKey)) + '=([^;]+)')); - defaultPrefs[key] = result ? decodeURIComponent(result[1]) : ''; + + Object.keys(defaultPrefs).forEach(function (key) { + var storeKey = 'svg-edit-' + key; + + if (editor.storage) { + var val = editor.storage.getItem(storeKey); + + if (val) { + defaultPrefs[key] = String(val); // Convert to string for FF (.value fails in Webkit) } + } else if (window.widget) { + defaultPrefs[key] = window.widget.preferenceForKey(storeKey); + } else { + var result = document.cookie.match(new RegExp('(?:^|;\\s*)' + regexEscape(encodeURIComponent(storeKey)) + '=([^;]+)')); + defaultPrefs[key] = result ? decodeURIComponent(result[1]) : ''; } - } + }); }; - /** * Allows setting of preferences or configuration (including extensions). * @param {module:SVGEditor.Config|module:SVGEditor.Prefs} opts The preferences or configuration (including extensions). See the tutorial on {@tutorial ConfigOptions} for info on config and preferences. @@ -25386,8 +29052,18 @@ * not be needed in `svgedit-config-iife.js`. * @returns {undefined} */ + + editor.setConfig = function (opts, cfgCfg) { cfgCfg = cfgCfg || {}; + /** + * + * @param {module:SVGEditor.Config|module:SVGEditor.Prefs} cfgObj + * @param {string} key + * @param {Any} val See {@link module:SVGEditor.Config} or {@link module:SVGEditor.Prefs} + * @returns {undefined} + */ + function extendOrAdd(cfgObj, key, val) { if (cfgObj[key] && _typeof(cfgObj[key]) === 'object') { $$b.extend(true, cfgObj[key], val); @@ -25395,13 +29071,15 @@ cfgObj[key] = val; } } + $$b.each(opts, function (key, val) { - if (opts.hasOwnProperty(key)) { + if ({}.hasOwnProperty.call(opts, key)) { // Only allow prefs defined in defaultPrefs - if (defaultPrefs.hasOwnProperty(key)) { - if (cfgCfg.overwrite === false && (curConfig.preventAllURLConfig || curPrefs.hasOwnProperty(key))) { + if ({}.hasOwnProperty.call(defaultPrefs, key)) { + if (cfgCfg.overwrite === false && (curConfig.preventAllURLConfig || {}.hasOwnProperty.call(curPrefs, key))) { return; } + if (cfgCfg.allowInitialUserOverride === true) { defaultPrefs[key] = val; } else { @@ -25411,29 +29089,28 @@ if (cfgCfg.overwrite === false && (curConfig.preventAllURLConfig || ['allowedOrigins', 'stylesheets'].includes(key) || key === 'extensions' && curConfig.lockExtensions)) { return; } + curConfig[key] = curConfig[key].concat(val); // We will handle any dupes later // Only allow other curConfig if defined in defaultConfig - } else if (defaultConfig.hasOwnProperty(key)) { - if (cfgCfg.overwrite === false && (curConfig.preventAllURLConfig || curConfig.hasOwnProperty(key))) { + } else if ({}.hasOwnProperty.call(defaultConfig, key)) { + if (cfgCfg.overwrite === false && (curConfig.preventAllURLConfig || {}.hasOwnProperty.call(curConfig, key))) { return; - } - // Potentially overwriting of previously set config - if (curConfig.hasOwnProperty(key)) { + } // Potentially overwriting of previously set config + + + if ({}.hasOwnProperty.call(curConfig, key)) { if (cfgCfg.overwrite === false) { return; } + extendOrAdd(curConfig, key, val); + } else if (cfgCfg.allowInitialUserOverride === true) { + extendOrAdd(defaultConfig, key, val); + } else if (defaultConfig[key] && _typeof(defaultConfig[key]) === 'object') { + curConfig[key] = Array.isArray(defaultConfig[key]) ? [] : {}; + $$b.extend(true, curConfig[key], val); // Merge properties recursively, e.g., on initFill, initStroke objects } else { - if (cfgCfg.allowInitialUserOverride === true) { - extendOrAdd(defaultConfig, key, val); - } else { - if (defaultConfig[key] && _typeof(defaultConfig[key]) === 'object') { - curConfig[key] = {}; - $$b.extend(true, curConfig[key], val); // Merge properties recursively, e.g., on initFill, initStroke objects - } else { - curConfig[key] = val; - } - } + curConfig[key] = val; } } } @@ -25443,14 +29120,15 @@ * @memberof module:SVGEditor * @implements {module:SVGEditor.Config} */ + editor.curConfig = curConfig; // Update exported value }; - /** * All methods are optional * @interface module:SVGEditor.CustomHandler * @type {PlainObject} */ + /** * Its responsibilities are: * - invoke a file chooser dialog in 'open' mode @@ -25460,6 +29138,7 @@ * @function module:SVGEditor.CustomHandler#open * @returns {undefined} */ + /** * Its responsibilities are: * - accept the string contents of the current document @@ -25471,6 +29150,7 @@ * @listens module:svgcanvas.SvgCanvas#event:saved * @returns {undefined} */ + /** * Its responsibilities (with regard to the object it is supplied in its 2nd argument) are: * - inform user of any issues supplied via the "issues" property @@ -25484,6 +29164,7 @@ * @listens module:svgcanvas.SvgCanvas#event:exported * @returns {undefined} */ + /** * @function module:SVGEditor.CustomHandler#exportPDF * @param {external:Window} win @@ -25498,6 +29179,8 @@ * @param {module:SVGEditor.CustomHandler} opts Extension mechanisms may call `setCustomHandlers` with three functions: `opts.open`, `opts.save`, and `opts.exportImage` * @returns {undefined} */ + + editor.setCustomHandlers = function (opts) { editor.ready(function () { if (opts.open) { @@ -25505,35 +29188,41 @@ $$b('#tool_open').show(); svgCanvas.open = opts.open; } + if (opts.save) { editor.showSaveWarning = false; svgCanvas.bind('saved', opts.save); } + if (opts.exportImage) { customExportImage = opts.exportImage; svgCanvas.bind('exported', customExportImage); // canvg and our RGBColor will be available to the method } + if (opts.exportPDF) { customExportPDF = opts.exportPDF; svgCanvas.bind('exportedPDF', customExportPDF); // jsPDF and our RGBColor will be available to the method } }); }; - /** * @param {boolean} arg * @returns {undefined} */ + + editor.randomizeIds = function (arg) { return svgCanvas.randomizeIds(arg); }; - /** - * Auto-run after a Promise microtask + * Auto-run after a Promise microtask. * @returns {undefined} */ + + editor.init = function () { var modularVersion = !('svgEditor' in window) || !window.svgEditor || window.svgEditor.modules !== false; + if (!modularVersion) { Object.assign(defaultConfig, { langPath: '../dist/locale/', @@ -25541,18 +29230,20 @@ canvgPath: '../dist/', jspdfPath: '../dist/' }); - } - - // const host = location.hostname, + } // const host = location.hostname, // onWeb = host && host.includes('.'); // Some FF versions throw security errors here when directly accessing + + try { if ('localStorage' in window) { // && onWeb removed so Webkit works locally + /** * The built-in interface implemented by `localStorage` * @external Storage */ + /** * @name storage * @memberof module:SVGEditor @@ -25560,41 +29251,54 @@ */ editor.storage = localStorage; } - } catch (err) {} + } catch (err) {} // Todo: Avoid const-defined functions and group functions together, etc. where possible + - // Todo: Avoid const-defined functions and group functions together, etc. where possible var goodLangs = []; $$b('#lang_select option').each(function () { goodLangs.push(this.value); }); + /** + * Sets up current preferences based on defaults. + * @returns {undefined} + */ function setupCurPrefs() { curPrefs = $$b.extend(true, {}, defaultPrefs, curPrefs); // Now safe to merge with priority for curPrefs in the event any are already set // Export updated prefs + editor.curPrefs = curPrefs; } + /** + * Sets up current config based on defaults. + * @returns {undefined} + */ + + function setupCurConfig() { curConfig = $$b.extend(true, {}, defaultConfig, curConfig); // Now safe to merge with priority for curConfig in the event any are already set - // Now deal with extensions and other array config + if (!curConfig.noDefaultExtensions) { curConfig.extensions = curConfig.extensions.concat(defaultExtensions); - } - // ...and remove any dupes + } // ...and remove any dupes + + ['extensions', 'stylesheets', 'allowedOrigins'].forEach(function (cfg) { curConfig[cfg] = $$b.grep(curConfig[cfg], function (n, i) { // Supposedly faster than filter per http://amandeep1986.blogspot.hk/2015/02/jquery-grep-vs-js-filter.html return i === curConfig[cfg].indexOf(n); }); - }); - // Export updated config + }); // Export updated config + editor.curConfig = curConfig; } + (function () { // Load config/data from URL if given - var src = void 0, - qstr = void 0; + var src, qstr; urldata = $$b.deparam.querystring(true); + if (!$$b.isEmptyObject(urldata)) { if (urldata.dimensions) { urldata.dimensions = urldata.dimensions.split(','); @@ -25607,44 +29311,50 @@ if (urldata.extensions) { // For security reasons, disallow cross-domain or cross-folder extensions via URL urldata.extensions = urldata.extensions.match(/[:/\\]/) ? '' : urldata.extensions.split(','); - } - - // Disallowing extension paths via URL for + } // Disallowing extension paths via URL for // security reasons, even for same-domain // ones given potential to interact in undesirable // ways with other script resources - ['extPath', 'imgPath', 'extIconsPath', 'canvgPath', 'langPath', 'jGraduatePath', 'jspdfPath'].forEach(function (pathConfig) { + + + ['langPath', 'extPath', 'canvgPath', 'jspdfPath', 'imgPath', 'jGraduatePath', 'extIconsPath'].forEach(function (pathConfig) { if (urldata[pathConfig]) { delete urldata[pathConfig]; } }); - - editor.setConfig(urldata, { overwrite: false }); // Note: source and url (as with storagePrompt later) are not set on config but are used below + editor.setConfig(urldata, { + overwrite: false + }); // Note: source and url (as with storagePrompt later) are not set on config but are used below setupCurConfig(); if (!curConfig.preventURLContentLoading) { src = urldata.source; qstr = $$b.param.querystring(); + if (!src) { // urldata.source may have been null if it ended with '=' if (qstr.includes('source=data:')) { src = qstr.match(/source=(data:[^&]*)/)[1]; } } + if (src) { if (src.startsWith('data:')) { editor.loadFromDataURI(src); } else { editor.loadFromString(src); } + return; } + if (urldata.url) { editor.loadFromURL(urldata.url); return; } } + if (!urldata.noStorageOnLoad || curConfig.forceStorage) { editor.loadContentAndPrefs(); } @@ -25652,25 +29362,30 @@ setupCurConfig(); editor.loadContentAndPrefs(); } + setupCurPrefs(); })(); - /** - * Called internally + * Called internally. * @param {string|Element|external:jQuery} elem * @param {string|external:jQuery} iconId * @param {Float} forcedSize Not in use * @returns {undefined} */ + + var setIcon = editor.setIcon = function (elem, iconId, forcedSize) { var icon = typeof iconId === 'string' ? $$b.getSvgIcon(iconId, true) : iconId.clone(); + if (!icon) { - console.log('NOTE: Icon image missing: ' + iconId); + // Todo: Investigate why this still occurs in some cases + console.log('NOTE: Icon image missing: ' + iconId); // eslint-disable-line no-console + return; } + $$b(elem).empty().append(icon); }; - /** * @fires module:svgcanvas.SvgCanvas#event:ext-addLangData * @fires module:svgcanvas.SvgCanvas#event:ext-langReady @@ -25678,49 +29393,65 @@ * @fires module:svgcanvas.SvgCanvas#event:extensions_added * @returns {Promise} Resolves to result of {@link module:locale.readLang} */ - var extAndLocaleFunc = function () { - var _ref5 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4() { - var _this = this; - var _ref6, langParam, langData; - return regeneratorRuntime.wrap(function _callee4$(_context4) { + var extAndLocaleFunc = + /*#__PURE__*/ + function () { + var _ref4 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee3() { + var _ref5, langParam, langData, _uiStrings$common, ok, cancel; + + return regeneratorRuntime.wrap(function _callee3$(_context3) { while (1) { - switch (_context4.prev = _context4.next) { + switch (_context3.prev = _context3.next) { case 0: - _context4.next = 2; + _context3.next = 2; return editor.putLocale(null, goodLangs, curConfig); case 2: - _ref6 = _context4.sent; - langParam = _ref6.langParam; - langData = _ref6.langData; + _ref5 = _context3.sent; + langParam = _ref5.langParam; + langData = _ref5.langData; + _context3.next = 7; + return setLang(langParam, langData); - setLang(langParam, langData); + case 7: + _uiStrings$common = uiStrings$1.common, ok = _uiStrings$common.ok, cancel = _uiStrings$common.cancel; + jQueryPluginDBox($$b, { + ok: ok, + cancel: cancel + }); + setIcons(); // Wait for dbox as needed for i18n - _context4.prev = 6; - _context4.next = 9; - return Promise.all(curConfig.extensions.map(function () { - var _ref7 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(extname) { - var extName, url, imported, _imported$name, _name2, init$$1, importLocale; + _context3.prev = 10; + _context3.next = 13; + return Promise.all(curConfig.extensions.map( + /*#__PURE__*/ + function () { + var _ref6 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee2(extname) { + var extName, url, imported, _imported$name, name, init, importLocale; - return regeneratorRuntime.wrap(function _callee3$(_context3) { + return regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { - switch (_context3.prev = _context3.next) { + switch (_context2.prev = _context2.next) { case 0: extName = extname.match(/^ext-(.+)\.js/); if (extName) { - _context3.next = 3; + _context2.next = 3; break; } - return _context3.abrupt('return'); + return _context2.abrupt("return", undefined); case 3: - url = curConfig.extPath + extname; - // Todo: Replace this with `return import(url);` when + url = curConfig.extPath + extname; // Todo: Replace this with `return import(url);` when // `import()` widely supported + /** * @tutorial ExtensionDocs * @typedef {PlainObject} module:SVGEditor.ExtensionObject @@ -25728,39 +29459,48 @@ * @property {module:svgcanvas.ExtensionInitCallback} [init] */ - _context3.prev = 4; - _context3.next = 7; + _context2.prev = 4; + _context2.next = 7; return importSetGlobalDefault(url, { global: 'svgEditorExtension_' + extName[1].replace(/-/g, '_') }); case 7: - imported = _context3.sent; - _imported$name = imported.name, _name2 = _imported$name === undefined ? extName[1] : _imported$name, init$$1 = imported.init; - importLocale = getImportLocale({ defaultLang: langParam, defaultName: _name2 }); - return _context3.abrupt('return', editor.addExtension(_name2, init$$1 && init$$1.bind(editor), importLocale)); + imported = _context2.sent; + _imported$name = imported.name, name = _imported$name === void 0 ? extName[1] : _imported$name, init = imported.init; + importLocale = getImportLocale({ + defaultLang: langParam, + defaultName: name + }); + return _context2.abrupt("return", editor.addExtension(name, init && init.bind(editor), { + $: $$b, + importLocale: importLocale + })); case 13: - _context3.prev = 13; - _context3.t0 = _context3['catch'](4); + _context2.prev = 13; + _context2.t0 = _context2["catch"](4); + // Todo: Add config to alert any errors + console.log(_context2.t0); // eslint-disable-line no-console - console.log(_context3.t0); - console.error('Extension failed to load: ' + extname + '; ' + _context3.t0); + console.error('Extension failed to load: ' + extname + '; ' + _context2.t0); // eslint-disable-line no-console - case 17: - case 'end': - return _context3.stop(); + return _context2.abrupt("return", undefined); + + case 18: + case "end": + return _context2.stop(); } } - }, _callee3, _this, [[4, 13]]); + }, _callee2, this, [[4, 13]]); })); - return function (_x3) { - return _ref7.apply(this, arguments); + return function (_x2) { + return _ref6.apply(this, arguments); }; }())); - case 9: + case 13: svgCanvas.bind('extensions_added', /** * @param {external:Window} win @@ -25771,10 +29511,14 @@ function (win, data) { extensionsAdded = true; Actions.setAll(); - $$b('.flyout_arrow_horiz:empty').each(function () { $$b(this).append($$b.getSvgIcon('arrow_right', true).width(5).height(5)); }); + + if (editor.storagePromptState === 'ignore') { + updateCanvas(true); + } + messageQueue.forEach( /** * @param {module:svgcanvas.SvgCanvas#event:message} messageObj @@ -25786,29 +29530,35 @@ }); }); svgCanvas.call('extensions_added'); - _context4.next = 16; + _context3.next = 20; break; - case 13: - _context4.prev = 13; - _context4.t0 = _context4['catch'](6); + case 17: + _context3.prev = 17; + _context3.t0 = _context3["catch"](10); + // Todo: Report errors through the UI + console.log(_context3.t0); // eslint-disable-line no-console - console.log(_context4.t0); - - case 16: - case 'end': - return _context4.stop(); + case 20: + case "end": + return _context3.stop(); } } - }, _callee4, this, [[6, 13]]); + }, _callee3, this, [[10, 17]]); })); return function extAndLocaleFunc() { - return _ref5.apply(this, arguments); + return _ref4.apply(this, arguments); }; }(); - var stateObj = { tool_scale: editor.tool_scale }; + var stateObj = { + tool_scale: editor.tool_scale + }; + /** + * + * @returns {undefined} + */ var setFlyoutPositions = function setFlyoutPositions() { $$b('.tools_flyout').each(function () { @@ -25819,87 +29569,106 @@ top = _shower$offset.top; var w = shower.outerWidth(); - $$b(this).css({ left: (left + w) * editor.tool_scale, top: top }); + $$b(this).css({ + left: (left + w) * editor.tool_scale, + top: top + }); }); }; + /** + * @type {string} + */ + var uaPrefix = function () { var regex = /^(Moz|Webkit|Khtml|O|ms|Icab)(?=[A-Z])/; var someScript = document.getElementsByTagName('script')[0]; + for (var prop in someScript.style) { if (regex.test(prop)) { // test is faster than match, so it's better to perform // that on the lot and match only when necessary return prop.match(regex)[0]; } - } - // Nothing found so far? + } // Nothing found so far? + + if ('WebkitOpacity' in someScript.style) { return 'Webkit'; } + if ('KhtmlOpacity' in someScript.style) { return 'Khtml'; } return ''; }(); + /** + * @param {external:jQuery} elems + * @param {Float} scale + * @returns {undefined} + */ + var scaleElements = function scaleElements(elems, scale) { // const prefix = '-' + uaPrefix.toLowerCase() + '-'; // Currently unused var sides = ['top', 'left', 'bottom', 'right']; - elems.each(function () { // Handled in CSS // this.style[uaPrefix + 'Transform'] = 'scale(' + scale + ')'; var el = $$b(this); var w = el.outerWidth() * (scale - 1); - var h = el.outerHeight() * (scale - 1); - // const margins = {}; // Currently unused + var h = el.outerHeight() * (scale - 1); // const margins = {}; // Currently unused for (var i = 0; i < 4; i++) { var s = sides[i]; var cur = el.data('orig_margin-' + s); - if (cur == null) { - cur = parseInt(el.css('margin-' + s), 10); - // Cache the original margin + + if (isNullish(cur)) { + cur = parseInt(el.css('margin-' + s)); // Cache the original margin + el.data('orig_margin-' + s, cur); } + var val = cur * scale; + if (s === 'right') { val += w; } else if (s === 'bottom') { val += h; } - el.css('margin-' + s, val); - // el.css('outline', '1px solid red'); + el.css('margin-' + s, val); // el.css('outline', '1px solid red'); } }); }; - /** * Called internally. * @param {module:SVGEditor.IconSize} size * @returns {undefined} */ + + var setIconSize = editor.setIconSize = function (size) { // const elems = $('.tool_button, .push_button, .tool_button_current, .disabled, .icon_label, #url_notice, #tool_open'); var selToscale = '#tools_top .toolset, #editor_panel > *, #history_panel > *,' + ' #main_button, #tools_left > *, #path_node_panel > *, #multiselected_panel > *,' + ' #g_panel > *, #tool_font_size > *, .tools_flyout'; - var elems = $$b(selToscale); - var scale = 1; + if (typeof size === 'number') { scale = size; } else { - var iconSizes = { s: 0.75, m: 1, l: 1.25, xl: 1.5 }; + var iconSizes = { + s: 0.75, + m: 1, + l: 1.25, + xl: 1.5 + }; scale = iconSizes[size]; } stateObj.tool_scale = editor.tool_scale = scale; - - setFlyoutPositions(); - // $('.tools_flyout').each(function () { + setFlyoutPositions(); // $('.tools_flyout').each(function () { // const pos = $(this).position(); // console.log($(this), pos.left+(34 * scale)); // $(this).css({left: pos.left+(34 * scale), top: pos.top+(77 * scale)}); @@ -25911,13 +29680,10 @@ var hiddenPs = elems.parents(':hidden'); hiddenPs.css('visibility', 'hidden').show(); scaleElements(elems, scale); - hiddenPs.css('visibility', 'visible').hide(); - // return; + hiddenPs.css('visibility', 'visible').hide(); // return; $$b.pref('iconsize', size); - $$b('#iconsize').val(size); - - // Change icon size + $$b('#iconsize').val(size); // Change icon size // $('.tool_button, .push_button, .tool_button_current, .disabled, .icon_label, #url_notice, #tool_open') // .find('> svg, > img').each(function () { // this.setAttribute('width',size_num); @@ -25932,8 +29698,8 @@ // if (size != 's') { // $.resizeSvgIcons({'#layerbuttons svg, #layerbuttons img': size_num * .6}); // } - // Note that all rules will be prefixed with '#svg_editor' when parsed + var cssResizeRules = { // '.tool_button,\ // .push_button,\ @@ -25964,8 +29730,7 @@ }, 'div#workarea': { left: 38, - top: 74 - // '#tools_bottom': { + top: 74 // '#tools_bottom': { // left: {s: '27px', l: '46px', xl: '65px'}, // height: {s: '58px', l: '98px', xl: '145px'} // }, @@ -26047,9 +29812,11 @@ // '#position_opts': { // width: {all: (size_num*4) +'px'} // } - } }; + } + }; var ruleElem = $$b('#tool_size_rules'); + if (!ruleElem.length) { ruleElem = $$b('<style id="tool_size_rules"></style>').appendTo('head'); } else { @@ -26062,17 +29829,19 @@ selector = '#svg_editor ' + selector.replace(/,/g, ', #svg_editor'); styleStr += selector + '{'; $$b.each(rules, function (prop, values) { - var val = void 0; + var val; + if (typeof values === 'number') { val = values * scale + 'px'; } else if (values[size] || values.all) { val = values[size] || values.all; } + styleStr += prop + ':' + val + ';'; }); styleStr += '}'; - }); - // this.style[uaPrefix + 'Transform'] = 'scale(' + scale + ')'; + }); // this.style[uaPrefix + 'Transform'] = 'scale(' + scale + ')'; + var prefix = '-' + uaPrefix.toLowerCase() + '-'; styleStr += selToscale + '{' + prefix + 'transform: scale(' + scale + ');}' + ' #svg_editor div.toolset .toolset {' + prefix + 'transform: scale(1); margin: 1px !important;}' + // Hack for markers ' #svg_editor .ui-slider {' + prefix + 'transform: scale(' + 1 / scale + ');}' // Hack for sliders @@ -26082,280 +29851,307 @@ setFlyoutPositions(); }; - $$b.svgIcons(curConfig.imgPath + 'svg_edit_icons.svg', { - w: 24, h: 24, - id_match: false, - no_img: !isWebkit(), // Opera & Firefox 4 gives odd behavior w/images - fallback_path: curConfig.imgPath, - fallback: { - logo: 'logo.png', + /** + * Setup SVG icons + */ - select: 'select.png', - select_node: 'select_node.png', - square: 'square.png', - rect: 'rect.png', - fh_rect: 'freehand-square.png', - circle: 'circle.png', - ellipse: 'ellipse.png', - fh_ellipse: 'freehand-circle.png', - pencil: 'fhpath.png', - pen: 'line.png', - text: 'text.png', - path: 'path.png', - add_subpath: 'add_subpath.png', - close_path: 'closepath.png', - open_path: 'openpath.png', + function setIcons() { + $$b.svgIcons(curConfig.imgPath + 'svg_edit_icons.svg', { + w: 24, + h: 24, + id_match: false, + no_img: !isWebkit(), + // Opera & Firefox 4 gives odd behavior w/images + fallback_path: curConfig.imgPath, + fallback: { + logo: 'logo.png', + select: 'select.png', + select_node: 'select_node.png', + square: 'square.png', + rect: 'rect.png', + fh_rect: 'freehand-square.png', + circle: 'circle.png', + ellipse: 'ellipse.png', + fh_ellipse: 'freehand-circle.png', + pencil: 'fhpath.png', + pen: 'line.png', + text: 'text.png', + path: 'path.png', + add_subpath: 'add_subpath.png', + close_path: 'closepath.png', + open_path: 'openpath.png', + image: 'image.png', + zoom: 'zoom.png', + arrow_right: 'flyouth.png', + arrow_right_big: 'arrow_right_big.png', + arrow_down: 'dropdown.gif', + fill: 'fill.png', + stroke: 'stroke.png', + opacity: 'opacity.png', + new_image: 'clear.png', + save: 'save.png', + export: 'export.png', + open: 'open.png', + import: 'import.png', + docprops: 'document-properties.png', + source: 'source.png', + wireframe: 'wireframe.png', + undo: 'undo.png', + redo: 'redo.png', + clone: 'clone.png', + delete: 'delete.png', + go_up: 'go-up.png', + go_down: 'go-down.png', + context_menu: 'context_menu.png', + move_bottom: 'move_bottom.png', + move_top: 'move_top.png', + to_path: 'to_path.png', + link_controls: 'link_controls.png', + reorient: 'reorient.png', + group_elements: 'shape_group_elements.png', + ungroup: 'shape_ungroup.png', + unlink_use: 'unlink_use.png', + width: 'width.png', + height: 'height.png', + c_radius: 'c_radius.png', + angle: 'angle.png', + blur: 'blur.png', + fontsize: 'fontsize.png', + align: 'align.png', + align_left: 'align-left.png', + align_center: 'align-center.png', + align_right: 'align-right.png', + align_top: 'align-top.png', + align_middle: 'align-middle.png', + align_bottom: 'align-bottom.png', + linecap_butt: 'linecap_butt.png', + linecap_square: 'linecap_square.png', + linecap_round: 'linecap_round.png', + linejoin_miter: 'linejoin_miter.png', + linejoin_bevel: 'linejoin_bevel.png', + linejoin_round: 'linejoin_round.png', + eye: 'eye.png', + no_color: 'no_color.png', + ok: 'save.png', + cancel: 'cancel.png', + warning: 'warning.png', + node_delete: 'node_delete.png', + node_clone: 'node_clone.png', + globe_link: 'globe_link.png' + }, + placement: { + '#logo': 'logo', + '#tool_clear div,#layer_new': 'new_image', + '#tool_save div': 'save', + '#tool_export div': 'export', + '#tool_open div div': 'open', + '#tool_import div div': 'import', + '#tool_source': 'source', + '#tool_docprops > div': 'docprops', + '#tool_wireframe': 'wireframe', + '#tool_undo': 'undo', + '#tool_redo': 'redo', + '#tool_select': 'select', + '#tool_fhpath': 'pencil', + '#tool_line': 'pen', + '#tool_rect,#tools_rect_show': 'rect', + '#tool_square': 'square', + '#tool_fhrect': 'fh_rect', + '#tool_ellipse,#tools_ellipse_show': 'ellipse', + '#tool_circle': 'circle', + '#tool_fhellipse': 'fh_ellipse', + '#tool_path': 'path', + '#tool_text,#layer_rename': 'text', + '#tool_image': 'image', + '#tool_zoom': 'zoom', + '#tool_clone,#tool_clone_multi': 'clone', + '#tool_node_clone': 'node_clone', + '#layer_delete,#tool_delete,#tool_delete_multi': 'delete', + '#tool_node_delete': 'node_delete', + '#tool_add_subpath': 'add_subpath', + '#tool_openclose_path': 'open_path', + '#tool_move_top': 'move_top', + '#tool_move_bottom': 'move_bottom', + '#tool_topath': 'to_path', + '#tool_node_link': 'link_controls', + '#tool_reorient': 'reorient', + '#tool_group_elements': 'group_elements', + '#tool_ungroup': 'ungroup', + '#tool_unlink_use': 'unlink_use', + '#tool_alignleft, #tool_posleft': 'align_left', + '#tool_aligncenter, #tool_poscenter': 'align_center', + '#tool_alignright, #tool_posright': 'align_right', + '#tool_aligntop, #tool_postop': 'align_top', + '#tool_alignmiddle, #tool_posmiddle': 'align_middle', + '#tool_alignbottom, #tool_posbottom': 'align_bottom', + '#cur_position': 'align', + '#linecap_butt,#cur_linecap': 'linecap_butt', + '#linecap_round': 'linecap_round', + '#linecap_square': 'linecap_square', + '#linejoin_miter,#cur_linejoin': 'linejoin_miter', + '#linejoin_round': 'linejoin_round', + '#linejoin_bevel': 'linejoin_bevel', + '#url_notice': 'warning', + '#layer_up': 'go_up', + '#layer_down': 'go_down', + '#layer_moreopts': 'context_menu', + '#layerlist td.layervis': 'eye', + '#tool_source_save,#tool_docprops_save,#tool_prefs_save': 'ok', + '#tool_source_cancel,#tool_docprops_cancel,#tool_prefs_cancel': 'cancel', + '#rwidthLabel, #iwidthLabel': 'width', + '#rheightLabel, #iheightLabel': 'height', + '#cornerRadiusLabel span': 'c_radius', + '#angleLabel': 'angle', + '#linkLabel,#tool_make_link,#tool_make_link_multi': 'globe_link', + '#zoomLabel': 'zoom', + '#tool_fill label': 'fill', + '#tool_stroke .icon_label': 'stroke', + '#group_opacityLabel': 'opacity', + '#blurLabel': 'blur', + '#font_sizeLabel': 'fontsize', + '.flyout_arrow_horiz': 'arrow_right', + '.dropdown button, #main_button .dropdown': 'arrow_down', + '#palette .palette_item:first, #fill_bg, #stroke_bg': 'no_color' + }, + resize: { + '#logo .svg_icon': 28, + '.flyout_arrow_horiz .svg_icon': 5, + '.layer_button .svg_icon, #layerlist td.layervis .svg_icon': 14, + '.dropdown button .svg_icon': 7, + '#main_button .dropdown .svg_icon': 9, + '.palette_item:first .svg_icon': 15, + '#fill_bg .svg_icon, #stroke_bg .svg_icon': 16, + '.toolbar_button button .svg_icon': 16, + '.stroke_tool div div .svg_icon': 20, + '#tools_bottom label .svg_icon': 18 + }, + callback: function () { + var _callback = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee4(icons) { + var tleft, minHeight, size, getStylesheetPriority, stylesheets, idx, _stylesheets; - image: 'image.png', - zoom: 'zoom.png', + return regeneratorRuntime.wrap(function _callee4$(_context4) { + while (1) { + switch (_context4.prev = _context4.next) { + case 0: + getStylesheetPriority = function _ref8(stylesheetFile) { + switch (stylesheetFile) { + case 'jgraduate/css/jPicker.css': + return 1; - arrow_right: 'flyouth.png', - arrow_right_big: 'arrow_right_big.png', - arrow_down: 'dropdown.gif', - fill: 'fill.png', - stroke: 'stroke.png', - opacity: 'opacity.png', + case 'jgraduate/css/jGraduate.css': + return 2; - new_image: 'clear.png', - save: 'save.png', - export: 'export.png', - open: 'open.png', - import: 'import.png', - docprops: 'document-properties.png', - source: 'source.png', - wireframe: 'wireframe.png', + case 'svg-editor.css': + return 3; - undo: 'undo.png', - redo: 'redo.png', + case 'spinbtn/jQuery.SpinButton.css': + return 4; - clone: 'clone.png', - delete: 'delete.png', - go_up: 'go-up.png', - go_down: 'go-down.png', - context_menu: 'context_menu.png', - move_bottom: 'move_bottom.png', - move_top: 'move_top.png', - to_path: 'to_path.png', - link_controls: 'link_controls.png', - reorient: 'reorient.png', - group_elements: 'shape_group_elements.png', + default: + return Infinity; + } + }; - ungroup: 'shape_ungroup.png', - unlink_use: 'unlink_use.png', - width: 'width.png', - height: 'height.png', - c_radius: 'c_radius.png', - angle: 'angle.png', - blur: 'blur.png', - fontsize: 'fontsize.png', - align: 'align.png', + $$b('.toolbar_button button > svg, .toolbar_button button > img').each(function () { + $$b(this).parent().prepend(this); + }); + tleft = $$b('#tools_left'); - align_left: 'align-left.png', - align_center: 'align-center.png', - align_right: 'align-right.png', - align_top: 'align-top.png', - align_middle: 'align-middle.png', - align_bottom: 'align-bottom.png', + if (tleft.length) { + minHeight = tleft.offset().top + tleft.outerHeight(); + } - linecap_butt: 'linecap_butt.png', - linecap_square: 'linecap_square.png', - linecap_round: 'linecap_round.png', - linejoin_miter: 'linejoin_miter.png', - linejoin_bevel: 'linejoin_bevel.png', - linejoin_round: 'linejoin_round.png', - eye: 'eye.png', - no_color: 'no_color.png', + size = $$b.pref('iconsize'); + editor.setIconSize(size || ($$b(window).height() < minHeight ? 's' : 'm')); // Look for any missing flyout icons from plugins - ok: 'save.png', - cancel: 'cancel.png', - warning: 'warning.png', + $$b('.tools_flyout').each(function () { + var shower = $$b('#' + this.id + '_show'); + var sel = shower.attr('data-curopt'); // Check if there's an icon here - node_delete: 'node_delete.png', - node_clone: 'node_clone.png', + if (!shower.children('svg, img').length) { + var clone = $$b(sel).children().clone(); - globe_link: 'globe_link.png' - }, - placement: { - '#logo': 'logo', + if (clone.length) { + clone[0].removeAttribute('style'); // Needed for Opera - '#tool_clear div,#layer_new': 'new_image', - '#tool_save div': 'save', - '#tool_export div': 'export', - '#tool_open div div': 'open', - '#tool_import div div': 'import', - '#tool_source': 'source', - '#tool_docprops > div': 'docprops', - '#tool_wireframe': 'wireframe', + shower.append(clone); + } + } + }); + /** + * 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} + */ - '#tool_undo': 'undo', - '#tool_redo': 'redo', + stylesheets = $$b.loadingStylesheets.sort(function (a, b) { + var priorityA = getStylesheetPriority(a); + var priorityB = getStylesheetPriority(b); - '#tool_select': 'select', - '#tool_fhpath': 'pencil', - '#tool_line': 'pen', - '#tool_rect,#tools_rect_show': 'rect', - '#tool_square': 'square', - '#tool_fhrect': 'fh_rect', - '#tool_ellipse,#tools_ellipse_show': 'ellipse', - '#tool_circle': 'circle', - '#tool_fhellipse': 'fh_ellipse', - '#tool_path': 'path', - '#tool_text,#layer_rename': 'text', - '#tool_image': 'image', - '#tool_zoom': 'zoom', + if (priorityA === priorityB) { + return 0; + } - '#tool_clone,#tool_clone_multi': 'clone', - '#tool_node_clone': 'node_clone', - '#layer_delete,#tool_delete,#tool_delete_multi': 'delete', - '#tool_node_delete': 'node_delete', - '#tool_add_subpath': 'add_subpath', - '#tool_openclose_path': 'open_path', - '#tool_move_top': 'move_top', - '#tool_move_bottom': 'move_bottom', - '#tool_topath': 'to_path', - '#tool_node_link': 'link_controls', - '#tool_reorient': 'reorient', - '#tool_group_elements': 'group_elements', - '#tool_ungroup': 'ungroup', - '#tool_unlink_use': 'unlink_use', + return priorityA > priorityB; + }); - '#tool_alignleft, #tool_posleft': 'align_left', - '#tool_aligncenter, #tool_poscenter': 'align_center', - '#tool_alignright, #tool_posright': 'align_right', - '#tool_aligntop, #tool_postop': 'align_top', - '#tool_alignmiddle, #tool_posmiddle': 'align_middle', - '#tool_alignbottom, #tool_posbottom': 'align_bottom', - '#cur_position': 'align', + if (curConfig.stylesheets.length) { + // Ensure a copy with unique items + stylesheets = _toConsumableArray(new Set(curConfig.stylesheets)); + idx = stylesheets.indexOf('@default'); - '#linecap_butt,#cur_linecap': 'linecap_butt', - '#linecap_round': 'linecap_round', - '#linecap_square': 'linecap_square', + if (idx > -1) { + (_stylesheets = stylesheets).splice.apply(_stylesheets, [idx, 1].concat(_toConsumableArray($$b.loadingStylesheets))); + } + } - '#linejoin_miter,#cur_linejoin': 'linejoin_miter', - '#linejoin_round': 'linejoin_round', - '#linejoin_bevel': 'linejoin_bevel', + _context4.next = 11; + return loadStylesheets(stylesheets, { + acceptErrors: function acceptErrors(_ref7) { + var stylesheetURL = _ref7.stylesheetURL, + reject = _ref7.reject, + resolve = _ref7.resolve; - '#url_notice': 'warning', + if ($$b.loadingStylesheets.includes(stylesheetURL)) { + reject(new Error("Missing expected stylesheet: ".concat(stylesheetURL))); + return; + } - '#layer_up': 'go_up', - '#layer_down': 'go_down', - '#layer_moreopts': 'context_menu', - '#layerlist td.layervis': 'eye', + resolve(); + } + }); - '#tool_source_save,#tool_docprops_save,#tool_prefs_save': 'ok', - '#tool_source_cancel,#tool_docprops_cancel,#tool_prefs_cancel': 'cancel', + case 11: + $$b('#svg_container')[0].style.visibility = 'visible'; + _context4.next = 14; + return editor.runCallbacks(); - '#rwidthLabel, #iwidthLabel': 'width', - '#rheightLabel, #iheightLabel': 'height', - '#cornerRadiusLabel span': 'c_radius', - '#angleLabel': 'angle', - '#linkLabel,#tool_make_link,#tool_make_link_multi': 'globe_link', - '#zoomLabel': 'zoom', - '#tool_fill label': 'fill', - '#tool_stroke .icon_label': 'stroke', - '#group_opacityLabel': 'opacity', - '#blurLabel': 'blur', - '#font_sizeLabel': 'fontsize', + case 14: + case "end": + return _context4.stop(); + } + } + }, _callee4, this); + })); - '.flyout_arrow_horiz': 'arrow_right', - '.dropdown button, #main_button .dropdown': 'arrow_down', - '#palette .palette_item:first, #fill_bg, #stroke_bg': 'no_color' - }, - resize: { - '#logo .svg_icon': 28, - '.flyout_arrow_horiz .svg_icon': 5, - '.layer_button .svg_icon, #layerlist td.layervis .svg_icon': 14, - '.dropdown button .svg_icon': 7, - '#main_button .dropdown .svg_icon': 9, - '.palette_item:first .svg_icon': 15, - '#fill_bg .svg_icon, #stroke_bg .svg_icon': 16, - '.toolbar_button button .svg_icon': 16, - '.stroke_tool div div .svg_icon': 20, - '#tools_bottom label .svg_icon': 18 - }, - callback: function callback(icons) { - $$b('.toolbar_button button > svg, .toolbar_button button > img').each(function () { - $$b(this).parent().prepend(this); - }); - - var tleft = $$b('#tools_left'); - - var minHeight = void 0; - if (tleft.length) { - minHeight = tleft.offset().top + tleft.outerHeight(); - } - - var size = $$b.pref('iconsize'); - editor.setIconSize(size || ($$b(window).height() < minHeight ? 's' : 'm')); - - // Look for any missing flyout icons from plugins - $$b('.tools_flyout').each(function () { - var shower = $$b('#' + this.id + '_show'); - var sel = shower.attr('data-curopt'); - // Check if there's an icon here - if (!shower.children('svg, img').length) { - var clone = $$b(sel).children().clone(); - if (clone.length) { - clone[0].removeAttribute('style'); // Needed for Opera - shower.append(clone); - } + function callback(_x3) { + return _callback.apply(this, arguments); } - }); - - function getStylesheetPriority(stylesheet) { - switch (stylesheet) { - case 'jgraduate/css/jPicker.css': - return 1; - case 'jgraduate/css/jGraduate.css': - return 2; - case 'svg-editor.css': - return 3; - case 'spinbtn/jQuery.SpinButton.css': - return 4; - default: - return Infinity; - } - } - var stylesheets = $$b.loadingStylesheets.sort(function (a, b) { - var priorityA = getStylesheetPriority(a); - var priorityB = getStylesheetPriority(b); - if (priorityA === priorityB) { - return 0; - } - return priorityA > priorityB; - }); - if (curConfig.stylesheets.length) { - // Ensure a copy with unique items - stylesheets = [].concat(toConsumableArray(new Set(curConfig.stylesheets))); - var idx = stylesheets.indexOf('@default'); - if (idx > -1) { - var _stylesheets; - - (_stylesheets = stylesheets).splice.apply(_stylesheets, [idx, 1].concat(toConsumableArray($$b.loadingStylesheets))); - } - } - loadStylesheets(stylesheets, { acceptErrors: function acceptErrors(_ref8) { - var stylesheetURL = _ref8.stylesheetURL, - reject = _ref8.reject, - resolve = _ref8.resolve; - - if ($$b.loadingStylesheets.includes(stylesheetURL)) { - reject(new Error('Missing expected stylesheet: ' + stylesheetURL)); - return; - } - resolve(); - } }).then(function () { - $$b('#svg_container')[0].style.visibility = 'visible'; - editor.runCallbacks(); - }); - } - }); + return callback; + }() + }); + } /** * @name module:SVGEditor.canvas * @type {module:svgcanvas.SvgCanvas} */ + + editor.canvas = svgCanvas = new SvgCanvas(document.getElementById('svgcanvas'), curConfig); var palette = [// Todo: Make into configuration item? '#000000', '#3f3f3f', '#7f7f7f', '#bfbfbf', '#ffffff', '#ff0000', '#ff7f00', '#ffff00', '#7fff00', '#00ff00', '#00ff7f', '#00ffff', '#007fff', '#0000ff', '#7f00ff', '#ff00ff', '#ff007f', '#7f0000', '#7f3f00', '#7f7f00', '#3f7f00', '#007f00', '#007f3f', '#007f7f', '#003f7f', '#00007f', '#3f007f', '#7f007f', '#7f003f', '#ffaaaa', '#ffd4aa', '#ffffaa', '#d4ffaa', '#aaffaa', '#aaffd4', '#aaffff', '#aad4ff', '#aaaaff', '#d4aaff', '#ffaaff', '#ffaad4'], @@ -26365,21 +30161,21 @@ undoMgr = _svgCanvas.undoMgr, workarea = $$b('#workarea'), canvMenu = $$b('#cmenu_canvas'), - paintBox = { fill: null, stroke: null }; - - - var resizeTimer = void 0, - curScrollPos = void 0; + paintBox = { + fill: null, + stroke: null + }; + var resizeTimer, curScrollPos; var exportWindow = null, defaultImageURL = curConfig.imgPath + 'logo.png', zoomInIcon = 'crosshair', zoomOutIcon = 'crosshair', - uiContext = 'toolbars'; + uiContext = 'toolbars'; // For external openers - // For external openers (function () { // let the opener know SVG Edit is ready (now that config is set up) var w = window.opener || window.parent; + if (w) { try { /** @@ -26390,6 +30186,7 @@ * @property {true} bubbles * @property {true} cancelable */ + /** * @name module:SVGEditor.svgEditorReadyEvent * @type {module:SVGEditor#event:svgEditorReadyEvent} @@ -26402,158 +30199,71 @@ } catch (e) {} } })(); + /** + * + * @returns {undefined} + */ - // This sets up alternative dialog boxes. They mostly work the same way as - // their UI counterparts, expect instead of returning the result, a callback - // needs to be included that returns the result as its first parameter. - // In the future we may want to add additional types of dialog boxes, since - // they should be easy to handle this way. - (function () { - $$b('#dialog_container').draggable({ - cancel: '#dialog_content, #dialog_buttons *', - containment: 'window' - }).css('position', 'absolute'); - var box = $$b('#dialog_box'), - btnHolder = $$b('#dialog_buttons'), - dialogContent = $$b('#dialog_content'), - dbox = function dbox(type, msg, callback, defaultVal, opts, changeCb, checkbox) { - dialogContent.html('<p>' + msg.replace(/\n/g, '</p><p>') + '</p>').toggleClass('prompt', type === 'prompt'); - btnHolder.empty(); - - var ok = $$b('<input type="button" value="' + uiStrings$1.common.ok + '">').appendTo(btnHolder); - - if (type !== 'alert') { - $$b('<input type="button" value="' + uiStrings$1.common.cancel + '">').appendTo(btnHolder).click(function () { - box.hide(); - if (callback) { - callback(false); // eslint-disable-line standard/no-callback-literal - } - }); - } - - var ctrl = void 0, - chkbx = void 0; - if (type === 'prompt') { - ctrl = $$b('<input type="text">').prependTo(btnHolder); - ctrl.val(defaultVal || ''); - ctrl.bind('keydown', 'return', function () { - ok.click(); - }); - } else if (type === 'select') { - var div = $$b('<div style="text-align:center;">'); - ctrl = $$b('<select>').appendTo(div); - if (checkbox) { - var label = $$b('<label>').text(checkbox.label); - chkbx = $$b('<input type="checkbox">').appendTo(label); - chkbx.val(checkbox.value); - if (checkbox.tooltip) { - label.attr('title', checkbox.tooltip); - } - chkbx.prop('checked', !!checkbox.checked); - div.append($$b('<div>').append(label)); - } - $$b.each(opts || [], function (opt, val) { - if ((typeof val === 'undefined' ? 'undefined' : _typeof(val)) === 'object') { - ctrl.append($$b('<option>').val(val.value).html(val.text)); - } else { - ctrl.append($$b('<option>').html(val)); - } - }); - dialogContent.append(div); - if (defaultVal) { - ctrl.val(defaultVal); - } - if (changeCb) { - ctrl.bind('change', 'return', changeCb); - } - ctrl.bind('keydown', 'return', function () { - ok.click(); - }); - } else if (type === 'process') { - ok.hide(); - } - - box.show(); - - ok.click(function () { - box.hide(); - var resp = type === 'prompt' || type === 'select' ? ctrl.val() : true; - if (callback) { - if (chkbx) { - callback(resp, chkbx.prop('checked')); - } else { - callback(resp); - } - } - }).focus(); - - if (type === 'prompt' || type === 'select') { - ctrl.focus(); - } - }; - - $$b.alert = function (msg, cb) { - dbox('alert', msg, cb); - }; - $$b.confirm = function (msg, cb) { - dbox('confirm', msg, cb); - }; - $$b.process_cancel = function (msg, cb) { - dbox('process', msg, cb); - }; - $$b.prompt = function (msg, txt, cb) { - dbox('prompt', msg, cb, txt); - }; - $$b.select = function (msg, opts, cb, changeCb, txt, checkbox) { - dbox('select', msg, cb, txt, opts, changeCb, checkbox); - }; - })(); var setSelectMode = function setSelectMode() { var curr = $$b('.tool_button_current'); + if (curr.length && curr[0].id !== 'tool_select') { curr.removeClass('tool_button_current').addClass('tool_button'); $$b('#tool_select').addClass('tool_button_current').removeClass('tool_button'); - $$b('#styleoverrides').text('#svgcanvas svg *{cursor:move;pointer-events:all} #svgcanvas svg{cursor:default}'); + $$b('#styleoverrides').text("\n #svgcanvas svg * {\n cursor: move;\n pointer-events: all;\n }\n #svgcanvas svg {\n cursor: default;\n }\n "); } + svgCanvas.setMode('select'); workarea.css('cursor', 'auto'); - }; - - // used to make the flyouts stay on the screen longer the very first time + }; // used to make the flyouts stay on the screen longer the very first time // const flyoutspeed = 1250; // Currently unused // let textBeingEntered = false; // Currently unused - var origTitle = $$b('title:first').text(); - // Make [1,2,5] array + + + var origTitle = $$b('title:first').text(); // Make [1,2,5] array + var rIntervals = []; + for (var i = 0.1; i < 1E5; i *= 10) { rIntervals.push(i); rIntervals.push(2 * i); rIntervals.push(5 * i); } + /** + * This function highlights the layer passed in (by fading out the other layers). + * If no layer is passed in, this function restores the other layers + * @param {string} [layerNameToHighlight] + * @returns {undefined} + */ + - // This function highlights the layer passed in (by fading out the other layers) - // if no layer is passed in, this function restores the other layers var toggleHighlightLayer = function toggleHighlightLayer(layerNameToHighlight) { - var i = void 0; + var i; var curNames = [], numLayers = svgCanvas.getCurrentDrawing().getNumLayers(); + for (i = 0; i < numLayers; i++) { curNames[i] = svgCanvas.getCurrentDrawing().getLayerName(i); } if (layerNameToHighlight) { - for (i = 0; i < numLayers; ++i) { - if (curNames[i] !== layerNameToHighlight) { - svgCanvas.getCurrentDrawing().setLayerOpacity(curNames[i], 0.5); + curNames.forEach(function (curName) { + if (curName !== layerNameToHighlight) { + svgCanvas.getCurrentDrawing().setLayerOpacity(curName, 0.5); } - } + }); } else { - for (i = 0; i < numLayers; ++i) { - svgCanvas.getCurrentDrawing().setLayerOpacity(curNames[i], 1.0); - } + curNames.forEach(function (curName) { + svgCanvas.getCurrentDrawing().setLayerOpacity(curName, 1.0); + }); } }; + /** + * + * @returns {undefined} + */ + var populateLayers = function populateLayers() { svgCanvas.clearSelection(); @@ -26562,22 +30272,26 @@ var drawing = svgCanvas.getCurrentDrawing(); var currentLayerName = drawing.getCurrentLayerName(); var icon = $$b.getSvgIcon('eye'); - var layer = svgCanvas.getCurrentDrawing().getNumLayers(); - // we get the layers in the reverse z-order (the layer rendered on top is listed first) + var layer = svgCanvas.getCurrentDrawing().getNumLayers(); // we get the layers in the reverse z-order (the layer rendered on top is listed first) + while (layer--) { - var _name3 = drawing.getLayerName(layer); - var layerTr = $$b('<tr class="layer">').toggleClass('layersel', _name3 === currentLayerName); - var layerVis = $$b('<td class="layervis">').toggleClass('layerinvis', !drawing.getLayerVisibility(_name3)); - var layerName = $$b('<td class="layername">' + _name3 + '</td>'); + var name = drawing.getLayerName(layer); + var layerTr = $$b('<tr class="layer">').toggleClass('layersel', name === currentLayerName); + var layerVis = $$b('<td class="layervis">').toggleClass('layerinvis', !drawing.getLayerVisibility(name)); + var layerName = $$b('<td class="layername">' + name + '</td>'); layerlist.append(layerTr.append(layerVis, layerName)); - selLayerNames.append('<option value="' + _name3 + '">' + _name3 + '</option>'); + selLayerNames.append('<option value="' + name + '">' + name + '</option>'); } + if (icon !== undefined) { var copy = icon.clone(); $$b('td.layervis', layerlist).append(copy); - $$b.resizeSvgIcons({ 'td.layervis .svg_icon': 14 }); - } - // handle selection of layer + $$b.resizeSvgIcons({ + 'td.layervis .svg_icon': 14 + }); + } // handle selection of layer + + $$b('#layerlist td.layername').mouseup(function (evt) { $$b('#layerlist tr.layer').removeClass('layersel'); $$b(this.parentNode).addClass('layersel'); @@ -26594,10 +30308,10 @@ var vis = $$b(this).hasClass('layerinvis'); svgCanvas.setLayerVisibility(name, vis); $$b(this).toggleClass('layerinvis'); - }); + }); // if there were too few rows, let's add a few to make it not so lonely - // if there were too few rows, let's add a few to make it not so lonely var num = 5 - $$b('#layerlist tr.layer').size(); + while (num-- > 0) { // FIXME: there must a better way to do this layerlist.append('<tr><td style="color:white">_</td><td/></tr>'); @@ -26606,6 +30320,12 @@ var editingsource = false; var origSource = ''; + /** + * @param {Event} [e] Not used. + * @param {boolean} forSaving + * @returns {undefined} + */ + var showSourceEditor = function showSourceEditor(e, forSaving) { if (editingsource) { return; @@ -26613,7 +30333,7 @@ editingsource = true; origSource = svgCanvas.getSvgString(); - $$b('#save_output_btns').toggle(!!forSaving); + $$b('#save_output_btns').toggle(Boolean(forSaving)); $$b('#tool_source_back').toggle(!forSaving); $$b('#svg_source_textarea').val(origSource); $$b('#svg_source_editor').fadeIn(); @@ -26622,16 +30342,23 @@ var selectedElement = null; var multiselected = false; + /** + * @param {boolean} editmode + * @param {module:svgcanvas.SvgCanvas#event:selected} elems + * @returns {undefined} + */ var togglePathEditMode = function togglePathEditMode(editmode, elems) { $$b('#path_node_panel').toggle(editmode); $$b('#tools_bottom_2,#tools_bottom_3').toggle(!editmode); + if (editmode) { // Change select icon $$b('.tool_button_current').removeClass('tool_button_current').addClass('tool_button'); $$b('#tool_select').addClass('tool_button_current').removeClass('tool_button'); setIcon('#tool_select', 'select_node'); multiselected = false; + if (elems.length) { selectedElement = elems[0]; } @@ -26641,7 +30368,6 @@ }, 1000); } }; - /** * @type {module:svgcanvas.EventHandler} * @param {external:Window} wind @@ -26649,34 +30375,36 @@ * @listens module:svgcanvas.SvgCanvas#event:saved * @returns {undefined} */ + + var saveHandler = function saveHandler(wind, svg) { - editor.showSaveWarning = false; - - // by default, we add the XML prolog back, systems integrating SVG-edit (wikis, CMSs) + editor.showSaveWarning = false; // by default, we add the XML prolog back, systems integrating SVG-edit (wikis, CMSs) // can just provide their own custom save handler and might not want the XML prolog - svg = '<?xml version="1.0"?>\n' + svg; - // IE9 doesn't allow standalone Data URLs + svg = '<?xml version="1.0"?>\n' + svg; // IE9 doesn't allow standalone Data URLs // https://connect.microsoft.com/IE/feedback/details/542600/data-uri-images-fail-when-loaded-by-themselves + if (isIE()) { showSourceEditor(0, true); return; - } - - // Since saving SVGs by opening a new window was removed in Chrome use artificial link-click + } // Since saving SVGs by opening a new window was removed in Chrome use artificial link-click // https://stackoverflow.com/questions/45603201/window-is-not-allowed-to-navigate-top-frame-navigations-to-data-urls + + var a = document.createElement('a'); a.href = 'data:image/svg+xml;base64,' + encode64(svg); a.download = 'icon.svg'; + a.style = 'display: none;'; + document.body.append(a); // Need to append for Firefox - a.click(); - - // Alert will only appear the first time saved OR the + a.click(); // Alert will only appear the first time saved OR the // first time the bug is encountered + var done = $$b.pref('save_notice_done'); + if (done !== 'all') { - var note = uiStrings$1.notification.saveFromBrowser.replace('%s', 'SVG'); - // Check if FF and has <defs/> + var note = uiStrings$1.notification.saveFromBrowser.replace('%s', 'SVG'); // Check if FF and has <defs/> + if (isGecko()) { if (svg.includes('<defs')) { // warning about Mozilla bug #308590 when applicable (seems to be fixed now in Feb 2013) @@ -26689,125 +30417,147 @@ } else { $$b.pref('save_notice_done', 'all'); } + if (done !== 'part') { - alert(note); + $$b.alert(note); } } }; - /** * @param {external:Window} win * @param {module:svgcanvas.SvgCanvas#event:exported} data * @listens module:svgcanvas.SvgCanvas#event:exported * @returns {undefined} */ + + var exportHandler = function exportHandler(win, data) { var issues = data.issues, exportWindowName = data.exportWindowName; - - - if (exportWindowName) { - exportWindow = window.open(blankPageObjectURL || '', exportWindowName); // A hack to get the window via JSON-able name without opening a new one - } + exportWindow = window.open(blankPageObjectURL || '', exportWindowName); // A hack to get the window via JSON-able name without opening a new one if (!exportWindow || exportWindow.closed) { + /* await */ $$b.alert(uiStrings$1.notification.popupWindowBlocked); return; } exportWindow.location.href = data.bloburl || data.datauri; var done = $$b.pref('export_notice_done'); + if (done !== 'all') { - var note = uiStrings$1.notification.saveFromBrowser.replace('%s', data.type); + var note = uiStrings$1.notification.saveFromBrowser.replace('%s', data.type); // Check if there are issues - // Check if there are issues if (issues.length) { - var pre = '\n \u2022 '; + var pre = "\n \u2022 "; note += '\n\n' + uiStrings$1.notification.noteTheseIssues + pre + issues.join(pre); - } - - // Note that this will also prevent the notice even though new issues may appear later. + } // Note that this will also prevent the notice even though new issues may appear later. // May want to find a way to deal with that without annoying the user + + $$b.pref('export_notice_done', 'all'); exportWindow.alert(note); } }; + /** + * + * @returns {undefined} + */ + var operaRepaint = function operaRepaint() { // Repaints canvas in Opera. Needed for stroke-dasharray change as well as fill change if (!window.opera) { return; } + $$b('<p/>').hide().appendTo('body').remove(); }; + /** + * + * @param {Element} opt + * @param {boolean} changeElem + * @returns {undefined} + */ + function setStrokeOpt(opt, changeElem) { var id = opt.id; - var bits = id.split('_'); - var pre = bits[0]; - var val = bits[1]; + + var _bits = _slicedToArray(bits, 2), + pre = _bits[0], + val = _bits[1]; if (changeElem) { svgCanvas.setStrokeAttr('stroke-' + pre, val); } + operaRepaint(); setIcon('#cur_' + pre, id, 20); $$b(opt).addClass('current').siblings().removeClass('current'); } - /** - * This is a common function used when a tool has been clicked (chosen) + * This is a common function used when a tool has been clicked (chosen). * It does several common things: - * - removes the `tool_button_current` class from whatever tool currently has it - * - hides any flyouts - * - adds the `tool_button_current` class to the button passed in + * - Removes the `tool_button_current` class from whatever tool currently has it. + * - Hides any flyouts. + * - Adds the `tool_button_current` class to the button passed in. * @function module:SVGEDitor.toolButtonClick * @param {string|Element} button The DOM element or string selector representing the toolbar button * @param {boolean} noHiding Whether not to hide any flyouts * @returns {boolean} Whether the button was disabled or not */ + + var toolButtonClick = editor.toolButtonClick = function (button, noHiding) { if ($$b(button).hasClass('disabled')) { return false; } + if ($$b(button).parent().hasClass('tools_flyout')) { return true; } + var fadeFlyouts = 'normal'; + if (!noHiding) { $$b('.tools_flyout').fadeOut(fadeFlyouts); } + $$b('#styleoverrides').text(''); workarea.css('cursor', 'auto'); $$b('.tool_button_current').removeClass('tool_button_current').addClass('tool_button'); $$b(button).addClass('tool_button_current').removeClass('tool_button'); return true; }; - /** * Unless the select toolbar button is disabled, sets the button * and sets the select mode and cursor styles. * @function module:SVGEditor.clickSelect * @returns {undefined} */ + + var clickSelect = editor.clickSelect = function () { if (toolButtonClick('#tool_select')) { svgCanvas.setMode('select'); - $$b('#styleoverrides').text('#svgcanvas svg *{cursor:move;pointer-events:all}, #svgcanvas svg{cursor:default}'); + $$b('#styleoverrides').text("\n #svgcanvas svg * {\n cursor: move;\n pointer-events: all;\n }\n #svgcanvas svg {\n cursor: default;\n }\n "); } }; - /** - * Set a selected image's URL + * Set a selected image's URL. * @function module:SVGEditor.setImageURL * @param {string} url * @returns {undefined} */ + + var setImageURL = editor.setImageURL = function (url) { if (!url) { url = defaultImageURL; } + svgCanvas.setImageURL(url); $$b('#image_url').val(url); @@ -26826,68 +30576,116 @@ $$b('#change_image_url').hide(); } }; + /** + * + * @param {string} color + * @param {string} url + * @returns {undefined} + */ + function setBackground(color, url) { // if (color == $.pref('bkgd_color') && url == $.pref('bkgd_url')) { return; } $$b.pref('bkgd_color', color); - $$b.pref('bkgd_url', url); + $$b.pref('bkgd_url', url); // This should be done in svgcanvas.js for the borderRect fill - // This should be done in svgcanvas.js for the borderRect fill svgCanvas.setBackground(color, url); } + /** + * @param {PlainObject} [opts={}] + * @param {boolean} [opts.cancelDeletes=false}] + * @returns {Promise} Resolves to `undefined` + */ + function promptImgURL() { - var _ref9 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, - _ref9$cancelDeletes = _ref9.cancelDeletes, - cancelDeletes = _ref9$cancelDeletes === undefined ? false : _ref9$cancelDeletes; + return _promptImgURL.apply(this, arguments); + } + /** + * @param {Element} elem + * @returns {undefined} + */ - var curhref = svgCanvas.getHref(selectedElement); - curhref = curhref.startsWith('data:') ? '' : curhref; - $$b.prompt(uiStrings$1.notification.enterNewImgURL, curhref, function (url) { - if (url) { - setImageURL(url); - } else if (cancelDeletes) { - svgCanvas.deleteSelectedElements(); - } - }); + + function _promptImgURL() { + _promptImgURL = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee18() { + var _ref31, + _ref31$cancelDeletes, + cancelDeletes, + curhref, + url, + _args18 = arguments; + + return regeneratorRuntime.wrap(function _callee18$(_context18) { + while (1) { + switch (_context18.prev = _context18.next) { + case 0: + _ref31 = _args18.length > 0 && _args18[0] !== undefined ? _args18[0] : {}, _ref31$cancelDeletes = _ref31.cancelDeletes, cancelDeletes = _ref31$cancelDeletes === void 0 ? false : _ref31$cancelDeletes; + curhref = svgCanvas.getHref(selectedElement); + curhref = curhref.startsWith('data:') ? '' : curhref; + _context18.next = 5; + return $$b.prompt(uiStrings$1.notification.enterNewImgURL, curhref); + + case 5: + url = _context18.sent; + + if (url) { + setImageURL(url); + } else if (cancelDeletes) { + svgCanvas.deleteSelectedElements(); + } + + case 7: + case "end": + return _context18.stop(); + } + } + }, _callee18, this); + })); + return _promptImgURL.apply(this, arguments); } var setInputWidth = function setInputWidth(elem) { var w = Math.min(Math.max(12 + elem.value.length * 6, 50), 300); $$b(elem).width(w); }; + /** + * + * @param {HTMLDivElement} [scanvas] + * @param {Float} [zoom] + * @returns {undefined} + */ + function updateRulers(scanvas, zoom) { if (!zoom) { zoom = svgCanvas.getZoom(); } + if (!scanvas) { scanvas = $$b('#svgcanvas'); } - var d = void 0, - i = void 0; + var d, i; var limit = 30000; var contentElem = svgCanvas.getContentElem(); var units = getTypeMap(); var unit = units[curConfig.baseUnit]; // 1 = 1px - // draw x ruler then y ruler + for (d = 0; d < 2; d++) { var isX = d === 0; var dim = isX ? 'x' : 'y'; var lentype = isX ? 'width' : 'height'; var contentDim = Number(contentElem.getAttribute(dim)); + var $hcanvOrig = $$b('#ruler_' + dim + ' canvas:first'); // Bit of a hack to fully clear the canvas in Safari & IE9 - var $hcanvOrig = $$b('#ruler_' + dim + ' canvas:first'); - - // Bit of a hack to fully clear the canvas in Safari & IE9 var $hcanv = $hcanvOrig.clone(); $hcanvOrig.replaceWith($hcanv); + var hcanv = $hcanv[0]; // Set the canvas size to the width of the container - var hcanv = $hcanv[0]; - - // Set the canvas size to the width of the container var rulerLen = scanvas[lentype](); var totalLen = rulerLen; hcanv.parentNode.style[lentype] = totalLen + 'px'; @@ -26895,19 +30693,17 @@ var ctxArr = void 0, num = void 0, ctxArrNum = void 0; - ctx.fillStyle = 'rgb(200,0,0)'; - ctx.fillRect(0, 0, hcanv.width, hcanv.height); + ctx.fillRect(0, 0, hcanv.width, hcanv.height); // Remove any existing canvasses - // Remove any existing canvasses - $hcanv.siblings().remove(); + $hcanv.siblings().remove(); // Create multiple canvases when necessary (due to browser limits) - // Create multiple canvases when necessary (due to browser limits) if (rulerLen >= limit) { - ctxArrNum = parseInt(rulerLen / limit, 10) + 1; + ctxArrNum = parseInt(rulerLen / limit) + 1; ctxArr = []; ctxArr[0] = ctx; var copy = void 0; + for (i = 1; i < ctxArrNum; i++) { hcanv[lentype] = limit; copy = hcanv.cloneNode(true); @@ -26915,40 +30711,38 @@ ctxArr[i] = copy.getContext('2d'); } - copy[lentype] = rulerLen % limit; + copy[lentype] = rulerLen % limit; // set copy width to last - // set copy width to last rulerLen = limit; } hcanv[lentype] = rulerLen; + var uMulti = unit * zoom; // Calculate the main number interval - var uMulti = unit * zoom; - - // Calculate the main number interval var rawM = 50 / uMulti; var multi = 1; + for (i = 0; i < rIntervals.length; i++) { num = rIntervals[i]; multi = num; + if (rawM <= num) { break; } } var bigInt = multi * uMulti; - ctx.font = '9px sans-serif'; - var rulerD = contentDim / uMulti % multi * uMulti; - var labelPos = rulerD - bigInt; - // draw big intervals + var labelPos = rulerD - bigInt; // draw big intervals + var ctxNum = 0; + while (rulerD < totalLen) { - labelPos += bigInt; - // const realD = rulerD - contentDim; // Currently unused + labelPos += bigInt; // const realD = rulerD - contentDim; // Currently unused var curD = Math.round(rulerD) + 0.5; + if (isX) { ctx.moveTo(curD, 15); ctx.lineTo(curD, 0); @@ -26959,14 +30753,15 @@ num = (labelPos - contentDim) / uMulti; var label = void 0; + if (multi >= 1) { label = Math.round(num); } else { var decs = String(multi).split('.')[1].length; label = num.toFixed(decs); - } + } // Change 1000s to Ks + - // Change 1000s to Ks if (label !== 0 && label !== 1000 && label % 1000 === 0) { label = label / 1000 + 'K'; } @@ -26976,30 +30771,35 @@ } else { // draw label vertically var _str = String(label).split(''); + for (i = 0; i < _str.length; i++) { ctx.fillText(_str[i], 1, rulerD + 9 + i * 9); } } - var part = bigInt / 10; - // draw the small intervals + var part = bigInt / 10; // draw the small intervals + for (i = 1; i < 10; i++) { var subD = Math.round(rulerD + part * i) + 0.5; + if (ctxArr && subD > rulerLen) { ctxNum++; ctx.stroke(); + if (ctxNum >= ctxArrNum) { i = 10; rulerD = totalLen; continue; } + ctx = ctxArr[ctxNum]; rulerD -= limit; subD = Math.round(rulerD + part * i) + 0.5; - } + } // odd lines are slighly longer + - // odd lines are slighly longer var lineNum = i % 2 ? 12 : 10; + if (isX) { ctx.moveTo(subD, 15); ctx.lineTo(subD, lineNum); @@ -27008,24 +30808,26 @@ ctx.lineTo(lineNum, subD); } } + rulerD += bigInt; } + ctx.strokeStyle = '#000'; ctx.stroke(); } } - /** * @function module:SVGEditor.updateCanvas * @param {boolean} center * @param {module:math.XYObject} newCtr * @returns {undefined} */ + + var updateCanvas = editor.updateCanvas = function (center, newCtr) { var zoom = svgCanvas.getZoom(); var wArea = workarea; var cnvs = $$b('#svgcanvas'); - var w = workarea.width(), h = workarea.height(); var wOrig = w, @@ -27050,19 +30852,16 @@ var newCanY = h / 2; var newCanX = w / 2; var offset = svgCanvas.updateCanvas(w, h); - var ratio = newCanX / oldCanX; + var scrollX = w / 2 - wOrig / 2; // eslint-disable-line no-shadow - var scrollX = w / 2 - wOrig / 2; - var scrollY = h / 2 - hOrig / 2; + var scrollY = h / 2 - hOrig / 2; // eslint-disable-line no-shadow if (!newCtr) { var oldDistX = oldCtr.x - oldCanX; var newX = newCanX + oldDistX * ratio; - var oldDistY = oldCtr.y - oldCanY; var newY = newCanY + oldDistY * ratio; - newCtr = { x: newX, y: newY @@ -27087,62 +30886,63 @@ wArea[0].scrollLeft = newCtr.x - wOrig / 2; wArea[0].scrollTop = newCtr.y - hOrig / 2; } + if (curConfig.showRulers) { updateRulers(cnvs, zoom); workarea.scroll(); } - if (urldata.storagePrompt !== true && !editor.storagePromptClosed) { + + if (urldata.storagePrompt !== true && editor.storagePromptState === 'ignore') { $$b('#dialog_box').hide(); } }; - /** * @fires module:svgcanvas.SvgCanvas#event:ext-toolButtonStateUpdate * @returns {undefined} */ + + var updateToolButtonState = function updateToolButtonState() { - var index = void 0, - button = void 0; var bNoFill = svgCanvas.getColor('fill') === 'none'; var bNoStroke = svgCanvas.getColor('stroke') === 'none'; var buttonsNeedingStroke = ['#tool_fhpath', '#tool_line']; var buttonsNeedingFillAndStroke = ['#tools_rect .tool_button', '#tools_ellipse .tool_button', '#tool_text', '#tool_path']; + if (bNoStroke) { - for (index in buttonsNeedingStroke) { - button = buttonsNeedingStroke[index]; - if ($$b(button).hasClass('tool_button_current')) { + buttonsNeedingStroke.forEach(function (btn) { + if ($$b(btn).hasClass('tool_button_current')) { clickSelect(); } - $$b(button).addClass('disabled'); - } + + $$b(btn).addClass('disabled'); + }); } else { - for (index in buttonsNeedingStroke) { - button = buttonsNeedingStroke[index]; - $$b(button).removeClass('disabled'); - } + buttonsNeedingStroke.forEach(function (btn) { + $$b(btn).removeClass('disabled'); + }); } if (bNoStroke && bNoFill) { - for (index in buttonsNeedingFillAndStroke) { - button = buttonsNeedingFillAndStroke[index]; - if ($$b(button).hasClass('tool_button_current')) { + buttonsNeedingFillAndStroke.forEach(function (btn) { + if ($$b(btn).hasClass('tool_button_current')) { clickSelect(); } - $$b(button).addClass('disabled'); - } + + $$b(btn).addClass('disabled'); + }); } else { - for (index in buttonsNeedingFillAndStroke) { - button = buttonsNeedingFillAndStroke[index]; - $$b(button).removeClass('disabled'); - } + buttonsNeedingFillAndStroke.forEach(function (btn) { + $$b(btn).removeClass('disabled'); + }); } - svgCanvas.runExtensions('toolButtonStateUpdate', /** @type {module:svgcanvas.SvgCanvas#event:ext-toolButtonStateUpdate} */{ + svgCanvas.runExtensions('toolButtonStateUpdate', + /** @type {module:svgcanvas.SvgCanvas#event:ext-toolButtonStateUpdate} */ + { nofill: bNoFill, nostroke: bNoStroke - }); + }); // Disable flyouts if all inside are disabled - // Disable flyouts if all inside are disabled $$b('.tools_flyout').each(function () { var shower = $$b('#' + this.id + '_show'); var hasEnabled = false; @@ -27153,65 +30953,72 @@ }); shower.toggleClass('disabled', !hasEnabled); }); - operaRepaint(); }; + /** + * Updates the toolbar (colors, opacity, etc) based on the selected element. + * This function also updates the opacity and id elements that are in the + * context panel. + * @returns {undefined} + */ + - // Updates the toolbar (colors, opacity, etc) based on the selected element - // This function also updates the opacity and id elements that are in the context panel var updateToolbar = function updateToolbar() { - var i = void 0, - len = void 0; - if (selectedElement != null) { + var i, len; + + if (!isNullish(selectedElement)) { switch (selectedElement.tagName) { case 'use': case 'image': case 'foreignObject': break; + case 'g': case 'a': - // Look for common styles - var childs = selectedElement.getElementsByTagName('*'); - var gWidth = null; - for (i = 0, len = childs.length; i < len; i++) { - var swidth = childs[i].getAttribute('stroke-width'); + { + // Look for common styles + var childs = selectedElement.getElementsByTagName('*'); + var gWidth = null; - if (i === 0) { - gWidth = swidth; - } else if (gWidth !== swidth) { - gWidth = null; + for (i = 0, len = childs.length; i < len; i++) { + var swidth = childs[i].getAttribute('stroke-width'); + + if (i === 0) { + gWidth = swidth; + } else if (gWidth !== swidth) { + gWidth = null; + } + } + + $$b('#stroke_width').val(gWidth === null ? '' : gWidth); + paintBox.fill.update(true); + paintBox.stroke.update(true); + break; + } + + default: + { + paintBox.fill.update(true); + paintBox.stroke.update(true); + $$b('#stroke_width').val(selectedElement.getAttribute('stroke-width') || 1); + $$b('#stroke_style').val(selectedElement.getAttribute('stroke-dasharray') || 'none'); + var attr = selectedElement.getAttribute('stroke-linejoin') || 'miter'; + + if ($$b('#linejoin_' + attr).length) { + setStrokeOpt($$b('#linejoin_' + attr)[0]); + } + + attr = selectedElement.getAttribute('stroke-linecap') || 'butt'; + + if ($$b('#linecap_' + attr).length) { + setStrokeOpt($$b('#linecap_' + attr)[0]); } } - - $$b('#stroke_width').val(gWidth === null ? '' : gWidth); - - paintBox.fill.update(true); - paintBox.stroke.update(true); - - break; - default: - paintBox.fill.update(true); - paintBox.stroke.update(true); - - $$b('#stroke_width').val(selectedElement.getAttribute('stroke-width') || 1); - $$b('#stroke_style').val(selectedElement.getAttribute('stroke-dasharray') || 'none'); - - var attr = selectedElement.getAttribute('stroke-linejoin') || 'miter'; - - if ($$b('#linejoin_' + attr).length) { - setStrokeOpt($$b('#linejoin_' + attr)[0]); - } - - attr = selectedElement.getAttribute('stroke-linecap') || 'butt'; - - if ($$b('#linecap_' + attr).length) { - setStrokeOpt($$b('#linecap_' + attr)[0]); - } } - } + } // All elements including image and group have opacity - // All elements including image and group have opacity - if (selectedElement != null) { + + if (!isNullish(selectedElement)) { var opacPerc = (selectedElement.getAttribute('opacity') || 1.0) * 100; $$b('#group_opacity').val(opacPerc); $$b('#opac_slider').slider('option', 'value', opacPerc); @@ -27221,24 +31028,29 @@ updateToolButtonState(); }; + /** + * Updates the context panel tools based on the selected element. + * @returns {undefined} + */ + - // updates the context panel tools based on the selected element var updateContextPanel = function updateContextPanel() { - var elem = selectedElement; - // If element has just been deleted, consider it null - if (elem != null && !elem.parentNode) { + var elem = selectedElement; // If element has just been deleted, consider it null + + if (!isNullish(elem) && !elem.parentNode) { elem = null; } + var currentLayerName = svgCanvas.getCurrentDrawing().getCurrentLayerName(); var currentMode = svgCanvas.getMode(); var unit = curConfig.baseUnit !== 'px' ? curConfig.baseUnit : null; - var isNode = currentMode === 'pathedit'; // elem ? (elem.id && elem.id.startsWith('pathpointgrip')) : false; + var menuItems = $$b('#cmenu_canvas li'); $$b('#selected_panel, #multiselected_panel, #g_panel, #rect_panel, #circle_panel,' + '#ellipse_panel, #line_panel, #text_panel, #image_panel, #container_panel,' + ' #use_panel, #a_panel').hide(); - if (elem != null) { - var elname = elem.nodeName; - // If this is a link with no transform and one child, pretend + + if (!isNullish(elem)) { + var elname = elem.nodeName; // If this is a link with no transform and one child, pretend // its child is selected // if (elname === 'a') { // && !$(elem).attr('transform')) { // elem = elem.firstChild; @@ -27246,7 +31058,6 @@ var angle = svgCanvas.getRotationAngle(elem); $$b('#angle').val(angle); - var blurval = svgCanvas.getBlur(elem); $$b('#blur').val(blurval); $$b('#blur_slider').slider('option', 'value', blurval); @@ -27255,26 +31066,29 @@ if (elname === 'image' && svgCanvas.getMode() === 'image') { // Prompt for URL if not a data URL if (!svgCanvas.getHref(elem).startsWith('data:')) { - promptImgURL({ cancelDeletes: true }); + /* await */ + promptImgURL({ + cancelDeletes: true + }); } } /* else if (elname == 'text') { // TODO: Do something here for new text } */ + } if (!isNode && currentMode !== 'pathedit') { - $$b('#selected_panel').show(); - // Elements in this array already have coord fields + $$b('#selected_panel').show(); // Elements in this array already have coord fields + if (['line', 'circle', 'ellipse'].includes(elname)) { $$b('#xy_panel').hide(); } else { - var x = void 0, - y = void 0; + var x, y; // Get BBox vals for g, polyline and path - // Get BBox vals for g, polyline and path if (['g', 'polyline', 'path'].includes(elname)) { var bb = svgCanvas.getStrokedBBox([elem]); + if (bb) { x = bb.x; y = bb.y; @@ -27292,9 +31106,9 @@ $$b('#selected_x').val(x || 0); $$b('#selected_y').val(y || 0); $$b('#xy_panel').show(); - } + } // Elements in this array cannot be converted to a path + - // Elements in this array cannot be converted to a path var noPath = !['image', 'text', 'path', 'g', 'use'].includes(elname); $$b('#tool_topath').toggle(noPath); $$b('#tool_reorient').toggle(elname === 'path'); @@ -27302,29 +31116,32 @@ } else { var point = path.getNodePoint(); $$b('#tool_add_subpath').removeClass('push_button_pressed').addClass('tool_button'); - $$b('#tool_node_delete').toggleClass('disabled', !path.canDeleteNodes); + $$b('#tool_node_delete').toggleClass('disabled', !path.canDeleteNodes); // Show open/close button based on selected point - // Show open/close button based on selected point setIcon('#tool_openclose_path', path.closed_subpath ? 'open_path' : 'close_path'); if (point) { var segType = $$b('#seg_type'); + if (unit) { point.x = convertUnit(point.x); point.y = convertUnit(point.y); } + $$b('#path_node_x').val(point.x); $$b('#path_node_y').val(point.y); + if (point.type) { segType.val(point.type).removeAttr('disabled'); } else { segType.val(4).attr('disabled', 'disabled'); } } - return; - } - // update contextual tools here + return; + } // update contextual tools here + + var panels = { g: [], a: [], @@ -27336,15 +31153,13 @@ text: [], use: [] }; - var _elem = elem, - tagName = _elem.tagName; - - // if ($(elem).data('gsvg')) { + tagName = _elem.tagName; // if ($(elem).data('gsvg')) { // $('#g_panel').show(); // } var linkHref = null; + if (tagName === 'a') { linkHref = svgCanvas.getHref(elem); $$b('#g_panel').show(); @@ -27355,9 +31170,9 @@ $$b('#a_panel').show(); linkHref = svgCanvas.getHref(elem.parentNode); } - } + } // Hide/show the make_link buttons + - // Hide/show the make_link buttons $$b('#tool_make_link, #tool_make_link').toggle(!linkHref); if (linkHref) { @@ -27366,44 +31181,47 @@ if (panels[tagName]) { var curPanel = panels[tagName]; - $$b('#' + tagName + '_panel').show(); - $$b.each(curPanel, function (i, item) { var attrVal = elem.getAttribute(item); + if (curConfig.baseUnit !== 'px' && elem[item]) { var bv = elem[item].baseVal.value; attrVal = convertUnit(bv); } + $$b('#' + tagName + '_' + item).val(attrVal || 0); }); if (tagName === 'text') { $$b('#text_panel').css('display', 'inline'); $$b('#tool_font_size').css('display', 'inline'); + if (svgCanvas.getItalic()) { $$b('#tool_italic').addClass('push_button_pressed').removeClass('tool_button'); } else { $$b('#tool_italic').removeClass('push_button_pressed').addClass('tool_button'); } + if (svgCanvas.getBold()) { $$b('#tool_bold').addClass('push_button_pressed').removeClass('tool_button'); } else { $$b('#tool_bold').removeClass('push_button_pressed').addClass('tool_button'); } + $$b('#font_family').val(elem.getAttribute('font-family')); $$b('#font_size').val(elem.getAttribute('font-size')); $$b('#text').val(elem.textContent); + if (svgCanvas.addedNew) { // Timeout needed for IE9 setTimeout(function () { $$b('#text').focus().select(); }, 100); - } - // text + } // text + } else if (tagName === 'image' && svgCanvas.getMode() === 'image') { - setImageURL(svgCanvas.getHref(elem)); - // image + setImageURL(svgCanvas.getHref(elem)); // image } else if (tagName === 'g' || tagName === 'use') { $$b('#container_panel').show(); var title = svgCanvas.getTitle(); @@ -27413,32 +31231,35 @@ $$b('#g_title').prop('disabled', tagName === 'use'); } } + menuItems[(tagName === 'g' ? 'en' : 'dis') + 'ableContextMenuItems']('#ungroup'); - menuItems[(tagName === 'g' || !multiselected ? 'dis' : 'en') + 'ableContextMenuItems']('#group'); - // if (elem != null) + menuItems[(tagName === 'g' || !multiselected ? 'dis' : 'en') + 'ableContextMenuItems']('#group'); // if (!Utils.isNullish(elem)) } else if (multiselected) { $$b('#multiselected_panel').show(); menuItems.enableContextMenuItems('#group').disableContextMenuItems('#ungroup'); } else { menuItems.disableContextMenuItems('#delete,#cut,#copy,#group,#ungroup,#move_front,#move_up,#move_down,#move_back'); - } + } // update history buttons + - // update history buttons $$b('#tool_undo').toggleClass('disabled', undoMgr.getUndoStackSize() === 0); $$b('#tool_redo').toggleClass('disabled', undoMgr.getRedoStackSize() === 0); - svgCanvas.addedNew = false; if (elem && !isNode || multiselected) { // update the selected elements' layer - $$b('#selLayerNames').removeAttr('disabled').val(currentLayerName); + $$b('#selLayerNames').removeAttr('disabled').val(currentLayerName); // Enable regular menu options - // Enable regular menu options canvMenu.enableContextMenuItems('#delete,#cut,#copy,#move_front,#move_up,#move_down,#move_back'); } else { $$b('#selLayerNames').attr('disabled', 'disabled'); } }; + /** + * + * @returns {undefined} + */ + var updateWireFrame = function updateWireFrame() { // Test support @@ -27446,24 +31267,26 @@ return; } - var rule = '#workarea.wireframe #svgcontent * { stroke-width: ' + 1 / svgCanvas.getZoom() + 'px; }'; + var rule = "\n #workarea.wireframe #svgcontent * {\n stroke-width: ".concat(1 / svgCanvas.getZoom(), "px;\n }\n "); $$b('#wireframe_rules').text(workarea.hasClass('wireframe') ? rule : ''); }; var curContext = ''; + /** + * @param {string} [title=svgCanvas.getDocumentTitle()] + * @returns {undefined} + */ var updateTitle = function updateTitle(title) { title = title || svgCanvas.getDocumentTitle(); - var newTitle = origTitle + (title ? ': ' + title : ''); - - // Remove title update with current context info, isn't really necessary + var newTitle = origTitle + (title ? ': ' + title : ''); // Remove title update with current context info, isn't really necessary // if (curContext) { // new_title = new_title + curContext; // } - $$b('title:first').text(newTitle); - }; - // called when we've selected a different element + $$b('title:first').text(newTitle); + }; // called when we've selected a different element + /** * * @param {external:Window} win @@ -27472,37 +31295,43 @@ * @fires module:svgcanvas.SvgCanvas#event:ext-selectedChanged * @returns {undefined} */ + + var selectedChanged = function selectedChanged(win, elems) { var mode = svgCanvas.getMode(); + if (mode === 'select') { setSelectMode(); } - var isNode = mode === 'pathedit'; - // if elems[1] is present, then we have more than one element - selectedElement = elems.length === 1 || elems[1] == null ? elems[0] : null; - multiselected = elems.length >= 2 && elems[1] != null; - if (selectedElement != null) { + + var isNode = mode === 'pathedit'; // if elems[1] is present, then we have more than one element + + selectedElement = elems.length === 1 || isNullish(elems[1]) ? elems[0] : null; + multiselected = elems.length >= 2 && !isNullish(elems[1]); + + if (!isNullish(selectedElement)) { // unless we're already in always set the mode of the editor to select because // upon creation of a text element the editor is switched into // select mode and this event fires - we need our UI to be in sync - if (!isNode) { updateToolbar(); } - } // if (elem != null) - + } // if (!Utils.isNullish(elem)) // Deal with pathedit mode + + togglePathEditMode(isNode, elems); updateContextPanel(); - svgCanvas.runExtensions('selectedChanged', /** @type {module:svgcanvas.SvgCanvas#event:ext-selectedChanged} */{ + svgCanvas.runExtensions('selectedChanged', + /** @type {module:svgcanvas.SvgCanvas#event:ext-selectedChanged} */ + { elems: elems, selectedElement: selectedElement, multiselected: multiselected }); - }; - - // Call when part of element is in process of changing, generally + }; // Call when part of element is in process of changing, generally // on mousemove actions like rotate, move, etc. + /** * @param {external:Window} win * @param {module:svgcanvas.SvgCanvas#event:transition} elems @@ -27510,6 +31339,8 @@ * @fires module:svgcanvas.SvgCanvas#event:ext-elementTransition * @returns {undefined} */ + + var elementTransition = function elementTransition(win, elems) { var mode = svgCanvas.getMode(); var elem = elems[0]; @@ -27518,37 +31349,41 @@ return; } - multiselected = elems.length >= 2 && elems[1] != null; - // Only updating fields for single elements for now + multiselected = elems.length >= 2 && !isNullish(elems[1]); // Only updating fields for single elements for now + if (!multiselected) { switch (mode) { case 'rotate': - var ang = svgCanvas.getRotationAngle(elem); - $$b('#angle').val(ang); - $$b('#tool_reorient').toggleClass('disabled', ang === 0); - break; - - // TODO: Update values that change on move/resize, etc - // case 'select': - // case 'resize': - // break; + { + var ang = svgCanvas.getRotationAngle(elem); + $$b('#angle').val(ang); + $$b('#tool_reorient').toggleClass('disabled', ang === 0); + break; // TODO: Update values that change on move/resize, etc + // } case 'select': { + // } case 'resize': { + // break; + // } + } } } - svgCanvas.runExtensions('elementTransition', /** @type {module:svgcanvas.SvgCanvas#event:ext-elementTransition} */{ + + svgCanvas.runExtensions('elementTransition', + /** @type {module:svgcanvas.SvgCanvas#event:ext-elementTransition} */ + { elems: elems }); }; - /** * Test whether an element is a layer or not. * @param {SVGGElement} elem - The SVGGElement to test. * @returns {boolean} True if the element is a layer */ + + function isLayer(elem) { return elem && elem.tagName === 'g' && Layer.CLASS_REGEX.test(elem.getAttribute('class')); - } + } // called when any element has changed - // called when any element has changed /** * @param {external:Window} win * @param {module:svgcanvas.SvgCanvas#event:changed} elems @@ -27556,60 +31391,61 @@ * @fires module:svgcanvas.SvgCanvas#event:ext-elementChanged * @returns {undefined} */ + + var elementChanged = function elementChanged(win, elems) { var mode = svgCanvas.getMode(); + if (mode === 'select') { setSelectMode(); } for (var _i = 0; _i < elems.length; ++_i) { var elem = elems[_i]; - var isSvgElem = elem && elem.tagName === 'svg'; + if (isSvgElem || isLayer(elem)) { - populateLayers(); - // if the element changed was the svg, then it could be a resolution change + populateLayers(); // if the element changed was the svg, then it could be a resolution change + if (isSvgElem) { updateCanvas(); - } - // 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 - } else if (elem && selectedElement && selectedElement.parentNode == null) { + + } else if (elem && selectedElement && isNullish(selectedElement.parentNode)) { // || elem && elem.tagName == "path" && !multiselected) { // This was added in r1430, but not sure why selectedElement = elem; } } - editor.showSaveWarning = true; - - // we update the contextual panel with potentially new + editor.showSaveWarning = true; // we update the contextual panel with potentially new // positional/sizing information (we DON'T want to update the // toolbar here as that creates an infinite loop) // also this updates the history buttons - // we tell it to skip focusing the text control if the // text element was previously in focus - updateContextPanel(); - // In the event a gradient was flipped: + updateContextPanel(); // In the event a gradient was flipped: + if (selectedElement && mode === 'select') { paintBox.fill.update(); paintBox.stroke.update(); } - svgCanvas.runExtensions('elementChanged', /** @type {module:svgcanvas.SvgCanvas#event:ext-elementChanged} */{ + svgCanvas.runExtensions('elementChanged', + /** @type {module:svgcanvas.SvgCanvas#event:ext-elementChanged} */ + { elems: elems }); }; - /** * @returns {undefined} */ - var zoomDone = function zoomDone() { - updateWireFrame(); - // updateCanvas(); // necessary? - }; + + var zoomDone = function zoomDone() { + updateWireFrame(); // updateCanvas(); // necessary? + }; /** * @typedef {PlainObject} module:SVGEditor.BBoxObjectWithFactor (like `DOMRect`) * @property {Float} x @@ -27629,21 +31465,26 @@ * @listens module:svgcanvas.SvgCanvas#event:zoomed * @returns {undefined} */ + + var zoomChanged = svgCanvas.zoomChanged = function (win, bbox, autoCenter) { var scrbar = 15, + // res = svgCanvas.getResolution(), // Currently unused + wArea = workarea; // const canvasPos = $('#svgcanvas').position(); // Currently unused - // res = svgCanvas.getResolution(), // Currently unused - wArea = workarea; - // const canvasPos = $('#svgcanvas').position(); // Currently unused var zInfo = svgCanvas.setBBoxZoom(bbox, wArea.width() - scrbar, wArea.height() - scrbar); + if (!zInfo) { return; } + var zoomlevel = zInfo.zoom, bb = zInfo.bbox; if (zoomlevel < 0.001) { - changeZoom({ value: 0.1 }); + changeZoom({ + value: 0.1 + }); return; } @@ -27652,7 +31493,10 @@ if (autoCenter) { updateCanvas(); } else { - updateCanvas(false, { x: bb.x * zoomlevel + bb.width * zoomlevel / 2, y: bb.y * zoomlevel + bb.height * zoomlevel / 2 }); + updateCanvas(false, { + x: bb.x * zoomlevel + bb.width * zoomlevel / 2, + y: bb.y * zoomlevel + bb.height * zoomlevel / 2 + }); } if (svgCanvas.getMode() === 'zoom' && bb.width) { @@ -27662,16 +31506,21 @@ zoomDone(); }; + /** + * @implements {module:jQuerySpinButton.ValueCallback} + */ + var changeZoom = function changeZoom(ctl) { var zoomlevel = ctl.value / 100; + if (zoomlevel < 0.001) { ctl.value = 0.1; return; } + var zoom = svgCanvas.getZoom(); var wArea = workarea; - zoomChanged(window, { width: 0, height: 0, @@ -27684,30 +31533,33 @@ $$b('#cur_context_panel').delegate('a', 'click', function () { var link = $$b(this); + if (link.attr('data-root')) { svgCanvas.leaveContext(); } else { svgCanvas.setContext(link.text()); } + svgCanvas.clearSelection(); return false; }); - /** * @param {external:Window} win * @param {module:svgcanvas.SvgCanvas#event:contextset} context * @listens module:svgcanvas.SvgCanvas#event:contextset * @returns {undefined} */ + var contextChanged = function contextChanged(win, context) { var linkStr = ''; + if (context) { var _str2 = ''; linkStr = '<a href="#" data-root="y">' + svgCanvas.getCurrentDrawing().getCurrentLayerName() + '</a>'; - $$b(context).parentsUntil('#svgcontent > g').andSelf().each(function () { if (this.id) { _str2 += ' > ' + this.id; + if (this !== context) { linkStr += ' > <a href="#">' + this.id + '</a>'; } else { @@ -27715,27 +31567,35 @@ } } }); - curContext = _str2; } else { curContext = null; } - $$b('#cur_context_panel').toggle(!!context).html(linkStr); + $$b('#cur_context_panel').toggle(Boolean(context)).html(linkStr); updateTitle(); }; + /** + * Makes sure the current selected paint is available to work with. + * @returns {undefined} + */ + - // Makes sure the current selected paint is available to work with var prepPaints = function prepPaints() { paintBox.fill.prep(); paintBox.stroke.prep(); }; var flyoutFuncs = {}; + /** + * + * @returns {undefined} + */ var setFlyoutTitles = function setFlyoutTitles() { $$b('.tools_flyout').each(function () { var shower = $$b('#' + this.id + '_show'); + if (shower.data('isLibrary')) { return; } @@ -27749,9 +31609,10 @@ var allHolders = {}; /** - * @param {Object.<string, module:SVGEditor.ToolButton>} holders Key is a selector + * @param {PlainObject.<string, module:SVGEditor.ToolButton>} holders Key is a selector * @returns {undefined} */ + var setupFlyouts = function setupFlyouts(holders) { $$b.each(holders, function (holdSel, btnOpts) { var _allHolders$holdSel; @@ -27759,7 +31620,8 @@ if (!allHolders[holdSel]) { allHolders[holdSel] = []; } - (_allHolders$holdSel = allHolders[holdSel]).push.apply(_allHolders$holdSel, toConsumableArray(btnOpts)); + + (_allHolders$holdSel = allHolders[holdSel]).push.apply(_allHolders$holdSel, _toConsumableArray(btnOpts)); var buttons = $$b(holdSel).children().not('.tool_button_evt_handled'); var showSel = holdSel + '_show'; @@ -27770,18 +31632,16 @@ // Get this button's options var idSel = '#' + this.getAttribute('id'); - var _Object$entries$find = Object.entries(btnOpts).find(function (_ref10) { - var _ref11 = slicedToArray(_ref10, 2), - i = _ref11[0], - sel = _ref11[1].sel; + var _Object$entries$find = Object.entries(btnOpts).find(function (_ref9) { + var _ref10 = _slicedToArray(_ref9, 2), + _ = _ref10[0], + sel = _ref10[1].sel; return sel === idSel; }), - _Object$entries$find2 = slicedToArray(_Object$entries$find, 2), + _Object$entries$find2 = _slicedToArray(_Object$entries$find, 2), i = _Object$entries$find2[0], - opts = _Object$entries$find2[1]; - - // Remember the function that goes with this ID + opts = _Object$entries$find2[1]; // Remember the function that goes with this ID flyoutFuncs[opts.sel] = opts.fn; @@ -27789,44 +31649,51 @@ if (opts.isDefault) { def = i; } - /** - * Clicking the icon in flyout should set this set's icon + * Clicking the icon in flyout should set this set's icon. * @param {Event} ev * @returns {undefined} */ + + var flyoutAction = function flyoutAction(ev) { - var options = opts; - // Find the currently selected tool if comes from keystroke + var options = opts; // Find the currently selected tool if comes from keystroke + if (ev.type === 'keydown') { var flyoutIsSelected = $$b(options.parent + '_show').hasClass('tool_button_current'); var currentOperation = $$b(options.parent + '_show').attr('data-curopt'); - Object.entries(holders[opts.parent]).some(function (_ref12) { - var _ref13 = slicedToArray(_ref12, 2), - i = _ref13[0], - tool = _ref13[1]; + Object.entries(holders[opts.parent]).some(function (_ref11) { + var _ref12 = _slicedToArray(_ref11, 2), + j = _ref12[0], + tool = _ref12[1]; if (tool.sel !== currentOperation) { - return; + return false; } + if (!ev.shiftKey || !flyoutIsSelected) { options = tool; } else { // If flyout is selected, allow shift key to iterate through subitems - i = parseInt(i, 10); - // Use `allHolders` to include both extension `includeWith` and toolbarButtons - options = allHolders[opts.parent][i + 1] || holders[opts.parent][0]; + j = parseInt(j); // Use `allHolders` to include both extension `includeWith` and toolbarButtons + + options = allHolders[opts.parent][j + 1] || holders[opts.parent][0]; } + return true; }); } + if ($$b(this).hasClass('disabled')) { return false; } + if (toolButtonClick(showSel)) { options.fn(); } - var icon = void 0; + + var icon; + if (options.icon) { icon = $$b.getSvgIcon(options.icon, true); } else { @@ -27837,6 +31704,8 @@ icon[0].setAttribute('height', shower.height()); shower.children(':not(.flyout_arrow_horiz)').remove(); shower.append(icon).attr('data-curopt', options.sel); // This sets the current mode + + return true; }; $$b(this).mouseup(flyoutAction); @@ -27844,6 +31713,8 @@ if (opts.key) { $$b(document).bind('keydown', opts.key[0] + ' shift+' + opts.key[0], flyoutAction); } + + return true; }); if (def) { @@ -27853,14 +31724,14 @@ shower.attr('data-curopt', btnOpts[0].sel); } - var timer = void 0; - var pos = $$b(showSel).position(); + var timer; + var pos = $$b(showSel).position(); // Clicking the "show" icon should set the current mode - // Clicking the "show" icon should set the current mode shower.mousedown(function (evt) { if (shower.hasClass('disabled')) { return false; } + var holder = $$b(holdSel); var l = pos.left + 34; var w = holder.width() * -1; @@ -27874,72 +31745,100 @@ } else { holder.css('left', l).show(); } + holder.data('shown_popop', true); }, time); evt.preventDefault(); + return true; }).mouseup(function (evt) { clearTimeout(timer); - var opt = $$b(this).attr('data-curopt'); - // Is library and popped up, so do nothing + var opt = $$b(this).attr('data-curopt'); // Is library and popped up, so do nothing + if (shower.data('isLibrary') && $$b(showSel.replace('_show', '')).is(':visible')) { toolButtonClick(showSel, true); return; } + if (toolButtonClick(showSel) && flyoutFuncs[opt]) { flyoutFuncs[opt](); } - }); - // $('#tools_rect').mouseleave(function () { $('#tools_rect').fadeOut(); }); + }); // $('#tools_rect').mouseleave(function () { $('#tools_rect').fadeOut(); }); }); setFlyoutTitles(); setFlyoutPositions(); }; + /** + * @param {string} id + * @param {external:jQuery} child + * @returns {undefined} + */ + var makeFlyoutHolder = function makeFlyoutHolder(id, child) { var div = $$b('<div>', { class: 'tools_flyout', id: id }).appendTo('#svg_editor').append(child); - return div; }; + /** + * @param {string} elemSel + * @param {string} listSel + * @param {external:jQuery.Function} callback + * @param {PlainObject} opts + * @param {boolean} opts.dropUp + * @param {boolean} opts.seticon + * @param {boolean} opts.multiclick + * @todo Combine this with `addDropDown` or find other way to optimize. + * @returns {undefined} + */ - // TODO: Combine this with addDropDown or find other way to optimize - var addAltDropDown = function addAltDropDown(elem, list, callback, opts) { - var button = $$b(elem); + + var addAltDropDown = function addAltDropDown(elemSel, listSel, callback, opts) { + var button = $$b(elemSel); var dropUp = opts.dropUp; + var list = $$b(listSel); - list = $$b(list); if (dropUp) { - $$b(elem).addClass('dropup'); + $$b(elemSel).addClass('dropup'); } + list.find('li').bind('mouseup', function () { if (opts.seticon) { setIcon('#cur_' + button[0].id, $$b(this).children()); $$b(this).addClass('current').siblings().removeClass('current'); } - callback.apply(this, arguments); - }); + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + callback.apply.apply(callback, [this].concat(args)); + }); var onButton = false; $$b(window).mouseup(function (evt) { if (!onButton) { button.removeClass('down'); list.hide(); - list.css({ top: 0, left: 0 }); + list.css({ + top: 0, + left: 0 + }); } - onButton = false; - }); - // const height = list.height(); // Currently unused + onButton = false; + }); // const height = list.height(); // Currently unused + button.bind('mousedown', function () { var off = button.offset(); + if (dropUp) { off.top -= list.height(); off.left += 8; } else { off.top += button.height(); } + list.offset(off); if (!button.hasClass('down')) { @@ -27948,8 +31847,12 @@ } else { // CSS position must be reset for Webkit list.hide(); - list.css({ top: 0, left: 0 }); + list.css({ + top: 0, + left: 0 + }); } + button.toggleClass('down'); }).hover(function () { onButton = true; @@ -27969,437 +31872,536 @@ * @param {external:Window} win * @param {module:svgcanvas.SvgCanvas#event:extension_added} ext * @listens module:svgcanvas.SvgCanvas#event:extension_added - * @returns {Promise} Resolves to `undefined` + * @returns {Promise|undefined} Resolves to `undefined` */ - var extAdded = function extAdded(win, ext) { - if (!ext) { - return; - } - var cbCalled = false; - var resizeDone = false; - if (ext.langReady) { - if (editor.langChanged) { - // We check for this since the "lang" pref could have been set by storage - var lang = $$b.pref('lang'); - ext.langReady({ - lang: lang, - uiStrings: uiStrings$1, - importLocale: getImportLocale({ defaultLang: lang, defaultName: ext.name }) - }); - } else { - extsPreLang.push(ext); - } - } + var extAdded = + /*#__PURE__*/ + function () { + var _ref13 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee5(win, ext) { + var cbCalled, resizeDone, lang, prepResize, runCallback, btnSelects, svgicons, fallbackObj, placementObj, holders; + return regeneratorRuntime.wrap(function _callee5$(_context5) { + while (1) { + switch (_context5.prev = _context5.next) { + case 0: + prepResize = function _ref14() { + if (resizeTimer) { + clearTimeout(resizeTimer); + resizeTimer = null; + } - function prepResize() { - if (resizeTimer) { - clearTimeout(resizeTimer); - resizeTimer = null; - } - if (!resizeDone) { - resizeTimer = setTimeout(function () { - resizeDone = true; - setIconSize($$b.pref('iconsize')); - }, 50); - } - } + if (!resizeDone) { + resizeTimer = setTimeout(function () { + resizeDone = true; + setIconSize($$b.pref('iconsize')); + }, 50); + } + }; - var runCallback = function runCallback() { - if (ext.callback && !cbCalled) { - cbCalled = true; - ext.callback.call(editor); - } - }; + if (ext) { + _context5.next = 3; + break; + } - var btnSelects = []; + return _context5.abrupt("return", undefined); - /** - * @typedef {PlainObject} module:SVGEditor.ContextTool - * @property {string} panel The ID of the existing panel to which the tool is being added. Required. - * @property {string} id The ID of the actual tool element. Required. - * @property {PlainObject.<string, external:jQuery.Function>|PlainObject.<"change", external:jQuery.Function>} events DOM event names keyed to associated functions. Example: `{change () { alert('Option was changed') } }`. "change" event is one specifically handled for the "button-select" type. Required. - * @property {string} title The tooltip text that will appear when the user hovers over the tool. Required. - * @property {"tool_button"|"select"|"button-select"|"input"|string} type The type of tool being added. Expected. - * @property {PlainObject.<string, string>} [options] List of options and their labels for select tools. Example: `{1: 'One', 2: 'Two', all: 'All' }`. Required by "select" tools. - * @property {string} [container_id] The ID to be given to the tool's container element. - * @property {string} [defval] Default value - * @property {string|Integer} [colnum] Added as part of the option list class. - * @property {string} [label] Label associated with the tool, visible in the UI - * @property {Integer} [size] Value of the "size" attribute of the tool input - * @property {module:jQuerySpinButton.SpinButtonConfig} [spindata] When added to a tool of type "input", this tool becomes a "spinner" which allows the number to be in/decreased. - */ - if (ext.context_tools) { - $$b.each(ext.context_tools, function (i, tool) { - // Add select tool - var contId = tool.container_id ? ' id="' + tool.container_id + '"' : ''; + case 3: + cbCalled = false; + resizeDone = false; - var panel = $$b('#' + tool.panel); - // create the panel if it doesn't exist - if (!panel.length) { - panel = $$b('<div>', { id: tool.panel }).appendTo('#tools_top'); - } + if (!ext.langReady) { + _context5.next = 14; + break; + } - var html = void 0; - // TODO: Allow support for other types, or adding to existing tool - switch (tool.type) { - case 'tool_button': - html = '<div class="tool_button">' + tool.id + '</div>'; - var div = $$b(html).appendTo(panel); - if (tool.events) { - $$b.each(tool.events, function (evt, func) { - $$b(div).bind(evt, func); + if (!editor.langChanged) { + _context5.next = 13; + break; + } + + // We check for this since the "lang" pref could have been set by storage + lang = $$b.pref('lang'); + _context5.next = 10; + return ext.langReady({ + lang: lang, + uiStrings: uiStrings$1, + importLocale: getImportLocale({ + defaultLang: lang, + defaultName: ext.name + }) }); - } - break; - case 'select': - html = '<label' + contId + '>' + '<select id="' + tool.id + '">'; - $$b.each(tool.options, function (val, text) { - var sel = val === tool.defval ? ' selected' : ''; - html += '<option value="' + val + '"' + sel + '>' + text + '</option>'; - }); - html += '</select></label>'; - // Creates the tool, hides & adds it, returns the select element - var sel = $$b(html).appendTo(panel).find('select'); - $$b.each(tool.events, function (evt, func) { - $$b(sel).bind(evt, func); - }); - break; - case 'button-select': - html = '<div id="' + tool.id + '" class="dropdown toolset" title="' + tool.title + '">' + '<div id="cur_' + tool.id + '" class="icon_label"></div><button></button></div>'; + case 10: + loadedExtensionNames.push(ext.name); + _context5.next = 14; + break; - var list = $$b('<ul id="' + tool.id + '_opts"></ul>').appendTo('#option_lists'); + case 13: + extsPreLang.push(ext); - if (tool.colnum) { - list.addClass('optcols' + tool.colnum); - } + case 14: + /** + * + * @returns {undefined} + */ + runCallback = function runCallback() { + if (ext.callback && !cbCalled) { + cbCalled = true; + ext.callback.call(editor); + } + }; - // Creates the tool, hides & adds it, returns the select element - /* const dropdown = */$$b(html).appendTo(panel).children(); + btnSelects = []; + /** + * @typedef {PlainObject} module:SVGEditor.ContextTool + * @property {string} panel The ID of the existing panel to which the tool is being added. Required. + * @property {string} id The ID of the actual tool element. Required. + * @property {PlainObject.<string, external:jQuery.Function>|PlainObject.<"change", external:jQuery.Function>} events DOM event names keyed to associated functions. Example: `{change () { alert('Option was changed') } }`. "change" event is one specifically handled for the "button-select" type. Required. + * @property {string} title The tooltip text that will appear when the user hovers over the tool. Required. + * @property {"tool_button"|"select"|"button-select"|"input"|string} type The type of tool being added. Expected. + * @property {PlainObject.<string, string>} [options] List of options and their labels for select tools. Example: `{1: 'One', 2: 'Two', all: 'All' }`. Required by "select" tools. + * @property {string} [container_id] The ID to be given to the tool's container element. + * @property {string} [defval] Default value + * @property {string|Integer} [colnum] Added as part of the option list class. + * @property {string} [label] Label associated with the tool, visible in the UI + * @property {Integer} [size] Value of the "size" attribute of the tool input + * @property {module:jQuerySpinButton.SpinButtonConfig} [spindata] When added to a tool of type "input", this tool becomes a "spinner" which allows the number to be in/decreased. + */ - btnSelects.push({ - elem: '#' + tool.id, - list: '#' + tool.id + '_opts', - title: tool.title, - callback: tool.events.change, - cur: '#cur_' + tool.id - }); + if (ext.context_tools) { + $$b.each(ext.context_tools, function (i, tool) { + // Add select tool + var contId = tool.container_id ? ' id="' + tool.container_id + '"' : ''; + var panel = $$b('#' + tool.panel); // create the panel if it doesn't exist - break; - case 'input': - html = '<label' + contId + '>' + '<span id="' + tool.id + '_label">' + tool.label + ':</span>' + '<input id="' + tool.id + '" title="' + tool.title + '" size="' + (tool.size || '4') + '" value="' + (tool.defval || '') + '" type="text"/></label>'; + if (!panel.length) { + panel = $$b('<div>', { + id: tool.panel + }).appendTo('#tools_top'); + } - // Creates the tool, hides & adds it, returns the select element + var html; // TODO: Allow support for other types, or adding to existing tool - // Add to given tool.panel - var inp = $$b(html).appendTo(panel).find('input'); + switch (tool.type) { + case 'tool_button': + { + html = '<div class="tool_button">' + tool.id + '</div>'; + var div = $$b(html).appendTo(panel); - if (tool.spindata) { - inp.SpinButton(tool.spindata); - } + if (tool.events) { + $$b.each(tool.events, function (evt, func) { + $$b(div).bind(evt, func); + }); + } - if (tool.events) { - $$b.each(tool.events, function (evt, func) { - inp.bind(evt, func); - }); - } - break; + break; + } - default: - break; - } - }); - } + case 'select': + { + html = '<label' + contId + '>' + '<select id="' + tool.id + '">'; + $$b.each(tool.options, function (val, text) { + var sel = val === tool.defval ? ' selected' : ''; + html += '<option value="' + val + '"' + sel + '>' + text + '</option>'; + }); + html += '</select></label>'; // Creates the tool, hides & adds it, returns the select element - var svgicons = ext.svgicons; + var sel = $$b(html).appendTo(panel).find('select'); + $$b.each(tool.events, function (evt, func) { + $$b(sel).bind(evt, func); + }); + break; + } - if (ext.buttons) { - var fallbackObj = {}, - placementObj = {}, - holders = {}; + case 'button-select': + { + html = '<div id="' + tool.id + '" class="dropdown toolset" title="' + tool.title + '">' + '<div id="cur_' + tool.id + '" class="icon_label"></div><button></button></div>'; + var list = $$b('<ul id="' + tool.id + '_opts"></ul>').appendTo('#option_lists'); - /** - * @typedef {GenericArray} module:SVGEditor.KeyArray - * @property {string} 0 The key to bind (on `keydown`) - * @property {boolean} 1 Whether to `preventDefault` on the `keydown` event - * @property {boolean} 2 Not apparently in use (NoDisableInInput) - */ - /** - * @typedef {string|module:SVGEditor.KeyArray} module:SVGEditor.Key - */ - /** - * @typedef {PlainObject} module:SVGEditor.Button - * @property {string} id A unique identifier for this button. If SVG icons are used, this must match the ID used in the icon file. Required. - * @property {"mode_flyout"|"mode"|"context"|"app_menu"} type Type of button. Required. - * @property {string} title The tooltip text that will appear when the user hovers over the icon. Required. - * @property {PlainObject.<string, external:jQuery.Function>|PlainObject.<"click", external:jQuery.Function>} events DOM event names with associated functions. Example: `{click () { alert('Button was clicked') } }`. Click is used with `includeWith` and `type` of "mode_flyout" (and "mode"); any events may be added if `list` is not present. Expected. - * @property {string} panel The ID of the context panel to be included, if type is "context". Required only if type is "context". - * @property {string} icon The file path to the raster version of the icon image source. Required only if no `svgicons` is supplied from [ExtensionInitResponse]{@link module:svgcanvas.ExtensionInitResponse}. - * @property {string} [svgicon] If absent, will utilize the button "id"; used to set "placement" on the `svgIcons` call - * @property {string} [list] Points to the "id" of a `context_tools` item of type "button-select" into which the button will be added as a panel list item - * @property {Integer} [position] The numeric index for placement; defaults to last position (as of the time of extension addition) if not present. For use with {@link http://api.jquery.com/eq/}. - * @property {boolean} [isDefault] Whether or not the button is the default. Used with `list`. - * @property {PlainObject} [includeWith] Object with flyout menu data - * @property {boolean} [includeWith.isDefault] Indicates whether button is default in flyout list or not. - * @property {string} includeWith.button jQuery selector of the existing button to be joined. Example: '#tool_line'. Required if `includeWith` is used. - * @property {"last"|Integer} [includeWith.position] Position of icon in flyout list; will be added to end if not indicated. Integer is for use with {@link http://api.jquery.com/eq/}. - * @property {module:SVGEditor.Key} [key] The key to bind to the button - */ - // Add buttons given by extension - $$b.each(ext.buttons, function (i, /** @type {module:SVGEditor.Button} */btn) { - var id = btn.id; + if (tool.colnum) { + list.addClass('optcols' + tool.colnum); + } // Creates the tool, hides & adds it, returns the select element - var num = i; - // Give button a unique ID - while ($$b('#' + id).length) { - id = btn.id + '_' + ++num; - } + /* const dropdown = */ - var icon = void 0; - if (!svgicons) { - icon = $$b('<img src="' + btn.icon + '">'); - } else { - fallbackObj[id] = btn.icon; - var svgicon = btn.svgicon || btn.id; - if (btn.type === 'app_menu') { - placementObj['#' + id + ' > div'] = svgicon; - } else { - placementObj['#' + id] = svgicon; - } - } - var cls = void 0, - parent = void 0; + $$b(html).appendTo(panel).children(); + btnSelects.push({ + elem: '#' + tool.id, + list: '#' + tool.id + '_opts', + title: tool.title, + callback: tool.events.change, + cur: '#cur_' + tool.id + }); + break; + } - // Set button up according to its type - switch (btn.type) { - case 'mode_flyout': - case 'mode': - cls = 'tool_button'; - parent = '#tools_left'; - break; - case 'context': - cls = 'tool_button'; - parent = '#' + btn.panel; - // create the panel if it doesn't exist - if (!$$b(parent).length) { - $$b('<div>', { id: btn.panel }).appendTo('#tools_top'); - } - break; - case 'app_menu': - cls = ''; - parent = '#main_menu ul'; - break; - } - var flyoutHolder = void 0, - curH = void 0, - showBtn = void 0, - refData = void 0, - refBtn = void 0; - var button = $$b(btn.list || btn.type === 'app_menu' ? '<li/>' : '<div/>').attr('id', id).attr('title', btn.title).addClass(cls); - if (!btn.includeWith && !btn.list) { - if ('position' in btn) { - if ($$b(parent).children().eq(btn.position).length) { - $$b(parent).children().eq(btn.position).before(button); - } else { - $$b(parent).children().last().before(button); - } - } else { - button.appendTo(parent); - } + case 'input': + { + html = '<label' + contId + '>' + '<span id="' + tool.id + '_label">' + tool.label + ':</span>' + '<input id="' + tool.id + '" title="' + tool.title + '" size="' + (tool.size || '4') + '" value="' + (tool.defval || '') + '" type="text"/></label>'; // Creates the tool, hides & adds it, returns the select element + // Add to given tool.panel - if (btn.type === 'mode_flyout') { - // Add to flyout menu / make flyout menu - // const opts = btn.includeWith; - // // opts.button, default, position - refBtn = $$b(button); + var inp = $$b(html).appendTo(panel).find('input'); - flyoutHolder = refBtn.parent(); - // Create a flyout menu if there isn't one already - var tlsId = void 0; - if (!refBtn.parent().hasClass('tools_flyout')) { - // Create flyout placeholder - tlsId = refBtn[0].id.replace('tool_', 'tools_'); - showBtn = refBtn.clone().attr('id', tlsId + '_show').append($$b('<div>', { class: 'flyout_arrow_horiz' })); + if (tool.spindata) { + inp.SpinButton(tool.spindata); + } - refBtn.before(showBtn); + if (tool.events) { + $$b.each(tool.events, function (evt, func) { + inp.bind(evt, func); + }); + } - // Create a flyout div - flyoutHolder = makeFlyoutHolder(tlsId, refBtn); - flyoutHolder.data('isLibrary', true); - showBtn.data('isLibrary', true); - } - // refData = Actions.getButtonData(opts.button); + break; + } - placementObj['#' + tlsId + '_show'] = btn.id; - // TODO: Find way to set the current icon using the iconloader if this is not default - - // Include data for extension button as well as ref button - curH = holders['#' + flyoutHolder[0].id] = [{ - sel: '#' + id, - fn: btn.events.click, - icon: btn.id, - // key: btn.key, - isDefault: true - }]; // , refData - // - // // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'} - // - // const pos = ('position' in opts)?opts.position:'last'; - // const len = flyoutHolder.children().length; - // - // // Add at given position or end - // if (!isNaN(pos) && pos >= 0 && pos < len) { - // flyoutHolder.children().eq(pos).before(button); - // } else { - // flyoutHolder.append(button); - // curH.reverse(); - // } - } else if (btn.type === 'app_menu') { - button.append('<div>').append(btn.title); - } - } else if (btn.list) { - // Add button to list - button.addClass('push_button'); - $$b('#' + btn.list + '_opts').append(button); - if (btn.isDefault) { - $$b('#cur_' + btn.list).append(button.children().clone()); - var _svgicon = btn.svgicon || btn.id; - placementObj['#cur_' + btn.list] = _svgicon; - } - } else if (btn.includeWith) { - // Add to flyout menu / make flyout menu - var opts = btn.includeWith; - // opts.button, default, position - refBtn = $$b(opts.button); - - flyoutHolder = refBtn.parent(); - // Create a flyout menu if there isn't one already - var _tlsId = void 0; - if (!refBtn.parent().hasClass('tools_flyout')) { - // Create flyout placeholder - _tlsId = refBtn[0].id.replace('tool_', 'tools_'); - showBtn = refBtn.clone().attr('id', _tlsId + '_show').append($$b('<div>', { class: 'flyout_arrow_horiz' })); - - refBtn.before(showBtn); - // Create a flyout div - flyoutHolder = makeFlyoutHolder(_tlsId, refBtn); - } - - refData = Actions.getButtonData(opts.button); - - if (opts.isDefault) { - placementObj['#' + _tlsId + '_show'] = btn.id; - } - // TODO: Find way to set the current icon using the iconloader if this is not default - - // Include data for extension button as well as ref button - curH = holders['#' + flyoutHolder[0].id] = [{ - sel: '#' + id, - fn: btn.events.click, - icon: btn.id, - key: btn.key, - isDefault: Boolean(btn.includeWith && btn.includeWith.isDefault) - }, refData]; - - // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'} - - var pos = 'position' in opts ? opts.position : 'last'; - var len = flyoutHolder.children().length; - - // Add at given position or end - if (!isNaN(pos) && pos >= 0 && pos < len) { - flyoutHolder.children().eq(pos).before(button); - } else { - flyoutHolder.append(button); - curH.reverse(); - } - } - - if (!svgicons) { - button.append(icon); - } - - if (!btn.list) { - // Add given events to button - $$b.each(btn.events, function (name, func) { - if (name === 'click' && btn.type === 'mode') { - if (btn.includeWith) { - button.bind(name, func); - } else { - button.bind(name, function () { - if (toolButtonClick(button)) { - func(); + default: + break; } }); } - if (btn.key) { - $$b(document).bind('keydown', btn.key, func); - if (btn.title) { - button.attr('title', btn.title + ' [' + btn.key + ']'); + + svgicons = ext.svgicons; + + if (!ext.buttons) { + _context5.next = 24; + break; + } + + fallbackObj = {}, placementObj = {}, holders = {}; + /** + * @typedef {GenericArray} module:SVGEditor.KeyArray + * @property {string} 0 The key to bind (on `keydown`) + * @property {boolean} 1 Whether to `preventDefault` on the `keydown` event + * @property {boolean} 2 Not apparently in use (NoDisableInInput) + */ + + /** + * @typedef {string|module:SVGEditor.KeyArray} module:SVGEditor.Key + */ + + /** + * @typedef {PlainObject} module:SVGEditor.Button + * @property {string} id A unique identifier for this button. If SVG icons are used, this must match the ID used in the icon file. Required. + * @property {"mode_flyout"|"mode"|"context"|"app_menu"} type Type of button. Required. + * @property {string} title The tooltip text that will appear when the user hovers over the icon. Required. + * @property {PlainObject.<string, external:jQuery.Function>|PlainObject.<"click", external:jQuery.Function>} events DOM event names with associated functions. Example: `{click () { alert('Button was clicked') } }`. Click is used with `includeWith` and `type` of "mode_flyout" (and "mode"); any events may be added if `list` is not present. Expected. + * @property {string} panel The ID of the context panel to be included, if type is "context". Required only if type is "context". + * @property {string} icon The file path to the raster version of the icon image source. Required only if no `svgicons` is supplied from [ExtensionInitResponse]{@link module:svgcanvas.ExtensionInitResponse}. + * @property {string} [svgicon] If absent, will utilize the button "id"; used to set "placement" on the `svgIcons` call + * @property {string} [list] Points to the "id" of a `context_tools` item of type "button-select" into which the button will be added as a panel list item + * @property {Integer} [position] The numeric index for placement; defaults to last position (as of the time of extension addition) if not present. For use with {@link http://api.jquery.com/eq/}. + * @property {boolean} [isDefault] Whether or not the button is the default. Used with `list`. + * @property {PlainObject} [includeWith] Object with flyout menu data + * @property {boolean} [includeWith.isDefault] Indicates whether button is default in flyout list or not. + * @property {string} includeWith.button jQuery selector of the existing button to be joined. Example: '#tool_line'. Required if `includeWith` is used. + * @property {"last"|Integer} [includeWith.position] Position of icon in flyout list; will be added to end if not indicated. Integer is for use with {@link http://api.jquery.com/eq/}. + * @property {module:SVGEditor.Key} [key] The key to bind to the button + */ + // Add buttons given by extension + + $$b.each(ext.buttons, function (i, + /** @type {module:SVGEditor.Button} */ + btn) { + var id = btn.id; + var num = i; // Give button a unique ID + + while ($$b('#' + id).length) { + id = btn.id + '_' + ++num; } + + var icon; + + if (!svgicons) { + icon = $$b('<img src="' + btn.icon + '">'); + } else { + fallbackObj[id] = btn.icon; + var svgicon = btn.svgicon || btn.id; + + if (btn.type === 'app_menu') { + placementObj['#' + id + ' > div'] = svgicon; + } else { + placementObj['#' + id] = svgicon; + } + } + + var cls, parent; // Set button up according to its type + + switch (btn.type) { + case 'mode_flyout': + case 'mode': + cls = 'tool_button'; + parent = '#tools_left'; + break; + + case 'context': + cls = 'tool_button'; + parent = '#' + btn.panel; // create the panel if it doesn't exist + + if (!$$b(parent).length) { + $$b('<div>', { + id: btn.panel + }).appendTo('#tools_top'); + } + + break; + + case 'app_menu': + cls = ''; + parent = '#main_menu ul'; + break; + } + + var flyoutHolder, showBtn, refData, refBtn; + var button = $$b(btn.list || btn.type === 'app_menu' ? '<li/>' : '<div/>').attr('id', id).attr('title', btn.title).addClass(cls); + + if (!btn.includeWith && !btn.list) { + if ('position' in btn) { + if ($$b(parent).children().eq(btn.position).length) { + $$b(parent).children().eq(btn.position).before(button); + } else { + $$b(parent).children().last().after(button); + } + } else { + button.appendTo(parent); + } + + if (btn.type === 'mode_flyout') { + // Add to flyout menu / make flyout menu + // const opts = btn.includeWith; + // // opts.button, default, position + refBtn = $$b(button); + flyoutHolder = refBtn.parent(); // Create a flyout menu if there isn't one already + + var tlsId; + + if (!refBtn.parent().hasClass('tools_flyout')) { + // Create flyout placeholder + tlsId = refBtn[0].id.replace('tool_', 'tools_'); + showBtn = refBtn.clone().attr('id', tlsId + '_show').append($$b('<div>', { + class: 'flyout_arrow_horiz' + })); + refBtn.before(showBtn); // Create a flyout div + + flyoutHolder = makeFlyoutHolder(tlsId, refBtn); + flyoutHolder.data('isLibrary', true); + showBtn.data('isLibrary', true); + } // refData = Actions.getButtonData(opts.button); + + + placementObj['#' + tlsId + '_show'] = btn.id; // TODO: Find way to set the current icon using the iconloader if this is not default + // Include data for extension button as well as ref button + + /* curH = */ + + holders['#' + flyoutHolder[0].id] = [{ + sel: '#' + id, + fn: btn.events.click, + icon: btn.id, + // key: btn.key, + isDefault: true + }]; // , refData + // + // // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'} + // + // const pos = ('position' in opts)?opts.position:'last'; + // const len = flyoutHolder.children().length; + // + // // Add at given position or end + // if (!isNaN(pos) && pos >= 0 && pos < len) { + // flyoutHolder.children().eq(pos).before(button); + // } else { + // flyoutHolder.append(button); + // curH.reverse(); + // } + } else if (btn.type === 'app_menu') { + button.append('<div>').append(btn.title); + } + } else if (btn.list) { + // Add button to list + button.addClass('push_button'); + $$b('#' + btn.list + '_opts').append(button); + + if (btn.isDefault) { + $$b('#cur_' + btn.list).append(button.children().clone()); + + var _svgicon = btn.svgicon || btn.id; + + placementObj['#cur_' + btn.list] = _svgicon; + } + } else if (btn.includeWith) { + // Add to flyout menu / make flyout menu + var opts = btn.includeWith; // opts.button, default, position + + refBtn = $$b(opts.button); + flyoutHolder = refBtn.parent(); // Create a flyout menu if there isn't one already + + var _tlsId; + + if (!refBtn.parent().hasClass('tools_flyout')) { + // Create flyout placeholder + _tlsId = refBtn[0].id.replace('tool_', 'tools_'); + showBtn = refBtn.clone().attr('id', _tlsId + '_show').append($$b('<div>', { + class: 'flyout_arrow_horiz' + })); + refBtn.before(showBtn); // Create a flyout div + + flyoutHolder = makeFlyoutHolder(_tlsId, refBtn); + } + + refData = Actions.getButtonData(opts.button); + + if (opts.isDefault) { + placementObj['#' + _tlsId + '_show'] = btn.id; + } // TODO: Find way to set the current icon using the iconloader if this is not default + // Include data for extension button as well as ref button + + + var curH = holders['#' + flyoutHolder[0].id] = [{ + sel: '#' + id, + fn: btn.events.click, + icon: btn.id, + key: btn.key, + isDefault: Boolean(btn.includeWith && btn.includeWith.isDefault) + }, refData]; // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'} + + var pos = 'position' in opts ? opts.position : 'last'; + var len = flyoutHolder.children().length; // Add at given position or end + + if (!isNaN(pos) && pos >= 0 && pos < len) { + flyoutHolder.children().eq(pos).before(button); + } else { + flyoutHolder.append(button); + curH.reverse(); + } + } + + if (!svgicons) { + button.append(icon); + } + + if (!btn.list) { + // Add given events to button + $$b.each(btn.events, function (name, func) { + if (name === 'click' && btn.type === 'mode') { + // `touch.js` changes `touchstart` to `mousedown`, + // so we must map extension click events as well + if (isTouch() && name === 'click') { + name = 'mousedown'; + } + + if (btn.includeWith) { + button.bind(name, func); + } else { + button.bind(name, function () { + if (toolButtonClick(button)) { + func(); + } + }); + } + + if (btn.key) { + $$b(document).bind('keydown', btn.key, func); + + if (btn.title) { + button.attr('title', btn.title + ' [' + btn.key + ']'); + } + } + } else { + button.bind(name, func); + } + }); + } + + setupFlyouts(holders); + }); + $$b.each(btnSelects, function () { + addAltDropDown(this.elem, this.list, this.callback, { + seticon: true + }); + }); + + if (!svgicons) { + _context5.next = 24; + break; } - } else { - button.bind(name, func); - } - }); + + return _context5.abrupt("return", new Promise(function (resolve, reject) { + // eslint-disable-line promise/avoid-new + $$b.svgIcons(svgicons, { + w: 24, + h: 24, + id_match: false, + no_img: !isWebkit(), + fallback: fallbackObj, + placement: placementObj, + callback: function callback(icons) { + // Non-ideal hack to make the icon match the current size + // if (curPrefs.iconsize && curPrefs.iconsize !== 'm') { + if ($$b.pref('iconsize') !== 'm') { + prepResize(); + } + + runCallback(); + resolve(); + } + }); + })); + + case 24: + return _context5.abrupt("return", runCallback()); + + case 25: + case "end": + return _context5.stop(); + } } + }, _callee5, this); + })); - setupFlyouts(holders); - }); + return function extAdded(_x4, _x5) { + return _ref13.apply(this, arguments); + }; + }(); + /** + * @param {string} color + * @param {Float} opac + * @param {string} type + * @returns {module:jGraduate~Paint} + */ - $$b.each(btnSelects, function () { - addAltDropDown(this.elem, this.list, this.callback, { seticon: true }); - }); - - if (svgicons) { - return new Promise(function (resolve, reject) { - $$b.svgIcons(svgicons, { - w: 24, h: 24, - id_match: false, - no_img: !isWebkit(), - fallback: fallbackObj, - placement: placementObj, - callback: function callback(icons) { - // Non-ideal hack to make the icon match the current size - // if (curPrefs.iconsize && curPrefs.iconsize !== 'm') { - if ($$b.pref('iconsize') !== 'm') { - prepResize(); - } - runCallback(); - resolve(); - } - }); - }); - } - } - return runCallback(); - }; var getPaint = function getPaint(color, opac, type) { // update the editor's fill paint - var opts = { alpha: opac }; + var opts = { + alpha: opac + }; + if (color.startsWith('url(#')) { var refElem = svgCanvas.getRefElem(color); + if (refElem) { refElem = refElem.cloneNode(true); } else { refElem = $$b('#' + type + '_color defs *')[0]; } + opts[refElem.tagName] = refElem; } else if (color.startsWith('#')) { opts.solidColor = color.substr(1); } else { opts.solidColor = 'none'; } + return new $$b.jGraduate.Paint(opts); - }; - - // $('#text').focus(function () { textBeingEntered = true; }); + }; // $('#text').focus(function () { textBeingEntered = true; }); // $('#text').blur(function () { textBeingEntered = false; }); - // bind the selected event to our function that handles updates to the UI + + svgCanvas.bind('selected', selectedChanged); svgCanvas.bind('transition', elementTransition); svgCanvas.bind('changed', elementChanged); @@ -28410,15 +32412,19 @@ // Ignore Chrome return; } + var exportWindowName = data.exportWindowName; if (exportWindowName) { exportWindow = window.open('', exportWindowName); // A hack to get the window via JSON-able name without opening a new one } + if (!exportWindow || exportWindow.closed) { + /* await */ $$b.alert(uiStrings$1.notification.popupWindowBlocked); return; } + exportWindow.location.href = data.output; }); svgCanvas.bind('zoomed', zoomChanged); @@ -28426,30 +32432,29 @@ svgCanvas.bind('updateCanvas', /** * @param {external:Window} win - * @param {false} center - * @param {module:math.XYObject} newCtr + * @param {PlainObject} centerInfo + * @param {false} centerInfo.center + * @param {module:math.XYObject} centerInfo.newCtr * @listens module:svgcanvas.SvgCanvas#event:updateCanvas * @returns {undefined} */ - function (win, _ref14) { - var center = _ref14.center, - newCtr = _ref14.newCtr; - + function (win, _ref15) { + var center = _ref15.center, + newCtr = _ref15.newCtr; updateCanvas(center, newCtr); }); svgCanvas.bind('contextset', contextChanged); svgCanvas.bind('extension_added', extAdded); svgCanvas.textActions.setInputElem($$b('#text')[0]); - var str = '<div class="palette_item" data-rgb="none"></div>'; $$b.each(palette, function (i, item) { str += '<div class="palette_item" style="background-color: ' + item + ';" data-rgb="' + item + '"></div>'; }); - $$b('#palette').append(str); - - // Set up editor background functionality + $$b('#palette').append(str); // Set up editor background functionality // TODO add checkerboard as "pattern" + var colorBlocks = ['#FFF', '#888', '#000']; // ,'url(data:image/gif;base64,R0lGODlhEAAQAIAAAP%2F%2F%2F9bW1iH5BAAAAAAALAAAAAAQABAAAAIfjG%2Bgq4jM3IFLJgpswNly%2FXkcBpIiVaInlLJr9FZWAQA7)']; + str = ''; $$b.each(colorBlocks, function () { str += '<div class="color_block" style="background-color:' + this + ';"></div>'; @@ -28464,53 +32469,87 @@ $$b(this).addClass(curBg); }); }); - setBackground($$b.pref('bkgd_color'), $$b.pref('bkgd_url')); - $$b('#image_save_opts input').val([$$b.pref('img_save')]); + /** + * @implements {module:jQuerySpinButton.ValueCallback} + */ var changeRectRadius = function changeRectRadius(ctl) { svgCanvas.setRectRadius(ctl.value); }; + /** + * @implements {module:jQuerySpinButton.ValueCallback} + */ + var changeFontSize = function changeFontSize(ctl) { svgCanvas.setFontSize(ctl.value); }; + /** + * @implements {module:jQuerySpinButton.ValueCallback} + */ + var changeStrokeWidth = function changeStrokeWidth(ctl) { var val = ctl.value; + if (val === 0 && selectedElement && ['line', 'polyline'].includes(selectedElement.nodeName)) { val = ctl.value = 1; } + svgCanvas.setStrokeWidth(val); }; + /** + * @implements {module:jQuerySpinButton.ValueCallback} + */ + var changeRotationAngle = function changeRotationAngle(ctl) { svgCanvas.setRotationAngle(ctl.value); - $$b('#tool_reorient').toggleClass('disabled', parseInt(ctl.value, 10) === 0); + $$b('#tool_reorient').toggleClass('disabled', parseInt(ctl.value) === 0); }; + /** + * @param {external:jQuery.fn.SpinButton} ctl Spin Button + * @param {string} [val=ctl.value] + * @returns {undefined} + */ + var changeOpacity = function changeOpacity(ctl, val) { - if (val == null) { + if (isNullish(val)) { val = ctl.value; } + $$b('#group_opacity').val(val); + if (!ctl || !ctl.handle) { $$b('#opac_slider').slider('option', 'value', val); } + svgCanvas.setOpacity(val / 100); }; + /** + * @param {external:jQuery.fn.SpinButton} ctl Spin Button + * @param {string} [val=ctl.value] + * @param {boolean} noUndo + * @returns {undefined} + */ + var changeBlur = function changeBlur(ctl, val, noUndo) { - if (val == null) { + if (isNullish(val)) { val = ctl.value; } + $$b('#blur').val(val); var complete = false; + if (!ctl || !ctl.handle) { $$b('#blur_slider').slider('option', 'value', val); complete = true; } + if (noUndo) { svgCanvas.setBlurNoUndo(val); } else { @@ -28522,56 +32561,94 @@ svgCanvas.setStrokeAttr('stroke-dasharray', $$b(this).val()); operaRepaint(); }); - $$b('#stroke_linejoin').change(function () { svgCanvas.setStrokeAttr('stroke-linejoin', $$b(this).val()); operaRepaint(); - }); + }); // Lose focus for select elements when changed (Allows keyboard shortcuts to work better) - // Lose focus for select elements when changed (Allows keyboard shortcuts to work better) $$b('select').change(function () { $$b(this).blur(); - }); + }); // fired when user wants to move elements to another layer - // fired when user wants to move elements to another layer var promptMoveLayerOnce = false; - $$b('#selLayerNames').change(function () { - var destLayer = this.options[this.selectedIndex].value; - var confirmStr = uiStrings$1.notification.QmoveElemsToLayer.replace('%s', destLayer); - var moveToLayer = function moveToLayer(ok) { - if (!ok) { - return; - } - promptMoveLayerOnce = true; - svgCanvas.moveSelectedToLayer(destLayer); - svgCanvas.clearSelection(); - populateLayers(); - }; - if (destLayer) { - if (promptMoveLayerOnce) { - moveToLayer(true); - } else { - $$b.confirm(confirmStr, moveToLayer); - } - } - }); + $$b('#selLayerNames').change( + /*#__PURE__*/ + _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee6() { + var destLayer, confirmStr, moveToLayer, ok; + return regeneratorRuntime.wrap(function _callee6$(_context6) { + while (1) { + switch (_context6.prev = _context6.next) { + case 0: + destLayer = this.options[this.selectedIndex].value; + confirmStr = uiStrings$1.notification.QmoveElemsToLayer.replace('%s', destLayer); + /** + * @param {boolean} ok + * @returns {undefined} + */ + moveToLayer = function moveToLayer(ok) { + if (!ok) { + return; + } + + promptMoveLayerOnce = true; + svgCanvas.moveSelectedToLayer(destLayer); + svgCanvas.clearSelection(); + populateLayers(); + }; + + if (!destLayer) { + _context6.next = 14; + break; + } + + if (!promptMoveLayerOnce) { + _context6.next = 8; + break; + } + + moveToLayer(true); + _context6.next = 14; + break; + + case 8: + _context6.next = 10; + return $$b.confirm(confirmStr); + + case 10: + ok = _context6.sent; + + if (ok) { + _context6.next = 13; + break; + } + + return _context6.abrupt("return"); + + case 13: + moveToLayer(true); + + case 14: + case "end": + return _context6.stop(); + } + } + }, _callee6, this); + }))); $$b('#font_family').change(function () { svgCanvas.setFontFamily(this.value); }); - $$b('#seg_type').change(function () { svgCanvas.setSegType($$b(this).val()); }); - $$b('#text').bind('keyup input', function () { svgCanvas.setTextContent(this.value); }); - $$b('#image_url').change(function () { setImageURL(this.value); }); - $$b('#link_url').change(function () { if (this.value.length) { svgCanvas.setLinkURL(this.value); @@ -28579,19 +32656,19 @@ svgCanvas.removeHyperlink(); } }); - $$b('#g_title').change(function () { svgCanvas.setGroupTitle(this.value); }); - $$b('.attr_changer').change(function () { var attr = this.getAttribute('data-attr'); var val = this.value; var valid = isValidUnit(attr, val, selectedElement); if (!valid) { - $$b.alert(uiStrings$1.notification.invalidAttrValGiven); this.value = selectedElement.getAttribute(attr); + /* await */ + + $$b.alert(uiStrings$1.notification.invalidAttrValGiven); return false; } @@ -28600,17 +32677,16 @@ val = svgCanvas.convertToNum(attr, val); } else if (curConfig.baseUnit !== 'px') { // Convert unitless value to one with given unit - var unitData = getTypeMap(); if (selectedElement[attr] || svgCanvas.getMode() === 'pathedit' || attr === 'x' || attr === 'y') { val *= unitData[curConfig.baseUnit]; } } - } - - // if the user is changing the id, then de-select the element first + } // if the user is changing the id, then de-select the element first // change the ID, then re-select it with the new ID + + if (attr === 'id') { var elem = selectedElement; svgCanvas.clearSelection(); @@ -28619,28 +32695,30 @@ } else { svgCanvas.changeSelectedAttribute(attr, val); } - this.blur(); - }); - // Prevent selection of elements when shift-clicking + this.blur(); + return true; + }); // Prevent selection of elements when shift-clicking + $$b('#palette').mouseover(function () { var inp = $$b('<input type="hidden">'); $$b(this).append(inp); inp.focus().remove(); }); - $$b('.palette_item').mousedown(function (evt) { // shift key or right click for stroke var picker = evt.shiftKey || evt.button === 2 ? 'stroke' : 'fill'; var color = $$b(this).data('rgb'); - var paint = void 0; + var paint; // Webkit-based browsers returned 'initial' here for no stroke - // Webkit-based browsers returned 'initial' here for no stroke if (color === 'none' || color === 'transparent' || color === 'initial') { color = 'none'; paint = new $$b.jGraduate.Paint(); } else { - paint = new $$b.jGraduate.Paint({ alpha: 100, solidColor: color.substr(1) }); + paint = new $$b.jGraduate.Paint({ + alpha: 100, + solidColor: color.substr(1) + }); } paintBox[picker].setPaint(paint); @@ -28649,37 +32727,35 @@ if (color !== 'none' && svgCanvas.getPaintOpacity(picker) !== 1) { svgCanvas.setPaintOpacity(picker, 1.0); } + updateToolButtonState(); }).bind('contextmenu', function (e) { e.preventDefault(); }); - $$b('#toggle_stroke_tools').on('click', function () { $$b('#tools_bottom').toggleClass('expanded'); }); (function () { var wArea = workarea[0]; - var lastX = null, lastY = null, panning = false, keypan = false; - $$b('#svgcanvas').bind('mousemove mouseup', function (evt) { if (panning === false) { - return; + return true; } wArea.scrollLeft -= evt.clientX - lastX; wArea.scrollTop -= evt.clientY - lastY; - lastX = evt.clientX; lastY = evt.clientY; if (evt.type === 'mouseup') { panning = false; } + return false; }).mousedown(function (evt) { if (evt.button === 1 || keypan === true) { @@ -28688,12 +32764,12 @@ lastY = evt.clientY; return false; } - }); + return true; + }); $$b(window).mouseup(function () { panning = false; }); - $$b(document).bind('keydown', 'space', function (evt) { svgCanvas.spaceKey = keypan = true; evt.preventDefault(); @@ -28709,11 +32785,11 @@ workarea.css('cursor', zoomInIcon); } }); - /** * @param {boolean} active * @returns {undefined} */ + editor.setPanning = function (active) { svgCanvas.spaceKey = keypan = active; }; @@ -28723,12 +32799,10 @@ var button = $$b('#main_icon'); var overlay = $$b('#main_icon span'); var list = $$b('#main_menu'); - var onButton = false; var height = 0; var jsHover = true; var setClick = false; - /* // Currently unused const hideMenu = function () { @@ -28738,9 +32812,9 @@ $$b(window).mouseup(function (evt) { if (!onButton) { - button.removeClass('buttondown'); - // do not hide if it was the file input as that input needs to be visible + button.removeClass('buttondown'); // do not hide if it was the file input as that input needs to be visible // for its change event to fire + if (evt.target.tagName !== 'INPUT') { list.fadeOut(200); } else if (!setClick) { @@ -28750,23 +32824,26 @@ }); } } + onButton = false; }).mousedown(function (evt) { // $('.contextMenu').hide(); var islib = $$b(evt.target).closest('div.tools_flyout, .contextMenu').length; + if (!islib) { $$b('.tools_flyout:visible,.contextMenu').fadeOut(250); } }); - overlay.bind('mousedown', function () { if (!button.hasClass('buttondown')) { // Margin must be reset in case it was changed before; list.css('margin-left', 0).show(); + if (!height) { height = list.height(); - } - // Using custom animation as slideDown has annoying 'bounce effect' + } // Using custom animation as slideDown has annoying 'bounce effect' + + list.css('height', 0).animate({ height: height }, 200); @@ -28774,20 +32851,19 @@ } else { list.fadeOut(200); } + button.toggleClass('buttondown buttonup'); }).hover(function () { onButton = true; }).mouseout(function () { onButton = false; }); + var listItems = $$b('#main_menu li'); // Check if JS method of hovering needs to be used (Webkit bug) - var listItems = $$b('#main_menu li'); - - // Check if JS method of hovering needs to be used (Webkit bug) listItems.mouseover(function () { jsHover = $$b(this).css('background-color') === 'rgba(0, 0, 0, 0)'; - listItems.unbind('mouseover'); + if (jsHover) { listItems.mouseover(function () { this.style.backgroundColor = '#FFC'; @@ -28797,9 +32873,9 @@ }); } }); - })(); - // Made public for UI customization. + })(); // Made public for UI customization. // TODO: Group UI functions into a public editor.ui interface. + /** * See {@link http://api.jquery.com/bind/#bind-eventType-eventData-handler} * @callback module:SVGEditor.DropDownCallback @@ -28807,35 +32883,41 @@ * @listens external:jQuery.Event * @returns {undefined|boolean} Calls `preventDefault()` and `stopPropagation()` */ + /** * @param {Element|string} elem DOM Element or selector * @param {module:SVGEditor.DropDownCallback} callback Mouseup callback * @param {boolean} dropUp * @returns {undefined} */ + + editor.addDropDown = function (elem, callback, dropUp) { if (!$$b(elem).length) { return; } // Quit if called on non-existent element + + var button = $$b(elem).find('button'); var list = $$b(elem).find('ul').attr('id', $$b(elem)[0].id + '-list'); + if (dropUp) { $$b(elem).addClass('dropup'); } else { // Move list to place where it can overflow container $$b('#option_lists').append(list); } - list.find('li').bind('mouseup', callback); + list.find('li').bind('mouseup', callback); var onButton = false; $$b(window).mouseup(function (evt) { if (!onButton) { button.removeClass('down'); list.hide(); } + onButton = false; }); - button.bind('mousedown', function () { if (!button.hasClass('down')) { if (!dropUp) { @@ -28845,11 +32927,13 @@ left: pos.left - 10 }); } + list.show(); onButton = true; } else { list.hide(); } + button.toggleClass('down'); }).hover(function () { onButton = true; @@ -28861,16 +32945,15 @@ editor.addDropDown('#font_family_dropdown', function () { $$b('#font_family').val($$b(this).text()).change(); }); - editor.addDropDown('#opacity_dropdown', function () { if ($$b(this).find('div').length) { return; } - var perc = parseInt($$b(this).text().split('%')[0], 10); - changeOpacity(false, perc); - }, true); - // For slider usage, see: http://jqueryui.com/demos/slider/ + var perc = parseInt($$b(this).text().split('%')[0]); + changeOpacity(false, perc); + }, true); // For slider usage, see: http://jqueryui.com/demos/slider/ + $$b('#opac_slider').slider({ start: function start() { $$b('#opacity_dropdown li:not(.special)').hide(); @@ -28883,9 +32966,7 @@ changeOpacity(ui); } }); - editor.addDropDown('#blur_dropdown', $$b.noop); - var slideStart = false; $$b('#blur_slider').slider({ max: 10, @@ -28903,30 +32984,34 @@ changeBlur(ui, null, slideStart); } }); - editor.addDropDown('#zoom_dropdown', function () { var item = $$b(this); var val = item.data('val'); + if (val) { zoomChanged(window, val); } else { - changeZoom({ value: parseFloat(item.text()) }); + changeZoom({ + value: parseFloat(item.text()) + }); } }, true); - addAltDropDown('#stroke_linecap', '#linecap_opts', function () { setStrokeOpt(this, true); - }, { dropUp: true }); - + }, { + dropUp: true + }); addAltDropDown('#stroke_linejoin', '#linejoin_opts', function () { setStrokeOpt(this, true); - }, { dropUp: true }); - + }, { + dropUp: true + }); addAltDropDown('#tool_position', '#position_opts', function () { var letter = this.id.replace('tool_pos', '').charAt(0); svgCanvas.alignSelectedElements(letter, 'page'); - }, { multiclick: true }); - + }, { + multiclick: true + }); /* When a flyout icon is selected (if flyout) { @@ -28939,81 +33024,137 @@ , else: - Just run its stuff */ - // Unfocus text input when workarea is mousedowned. + (function () { - var inp = void 0; + var inp; + /** + * + * @returns {undefined} + */ + var unfocus = function unfocus() { $$b(inp).blur(); }; $$b('#svg_editor').find('button, select, input:not(#text)').focus(function () { - inp = this; + inp = this; // eslint-disable-line consistent-this + uiContext = 'toolbars'; workarea.mousedown(unfocus); }).blur(function () { uiContext = 'canvas'; - workarea.unbind('mousedown', unfocus); - // Go back to selecting text if in textedit mode + workarea.unbind('mousedown', unfocus); // Go back to selecting text if in textedit mode + if (svgCanvas.getMode() === 'textedit') { $$b('#text').focus(); } }); })(); + /** + * + * @returns {undefined} + */ + var clickFHPath = function clickFHPath() { if (toolButtonClick('#tool_fhpath')) { svgCanvas.setMode('fhpath'); } }; + /** + * + * @returns {undefined} + */ + var clickLine = function clickLine() { if (toolButtonClick('#tool_line')) { svgCanvas.setMode('line'); } }; + /** + * + * @returns {undefined} + */ + var clickSquare = function clickSquare() { if (toolButtonClick('#tool_square')) { svgCanvas.setMode('square'); } }; + /** + * + * @returns {undefined} + */ + var clickRect = function clickRect() { if (toolButtonClick('#tool_rect')) { svgCanvas.setMode('rect'); } }; + /** + * + * @returns {undefined} + */ + var clickFHRect = function clickFHRect() { if (toolButtonClick('#tool_fhrect')) { svgCanvas.setMode('fhrect'); } }; + /** + * + * @returns {undefined} + */ + var clickCircle = function clickCircle() { if (toolButtonClick('#tool_circle')) { svgCanvas.setMode('circle'); } }; + /** + * + * @returns {undefined} + */ + var clickEllipse = function clickEllipse() { if (toolButtonClick('#tool_ellipse')) { svgCanvas.setMode('ellipse'); } }; + /** + * + * @returns {undefined} + */ + var clickFHEllipse = function clickFHEllipse() { if (toolButtonClick('#tool_fhellipse')) { svgCanvas.setMode('fhellipse'); } }; + /** + * + * @returns {undefined} + */ + var clickImage = function clickImage() { if (toolButtonClick('#tool_image')) { svgCanvas.setMode('image'); } }; + /** + * + * @returns {undefined} + */ + var clickZoom = function clickZoom() { if (toolButtonClick('#tool_zoom')) { @@ -29021,16 +33162,26 @@ workarea.css('cursor', zoomInIcon); } }; + /** + * @param {Float} multiplier + * @returns {undefined} + */ + var zoomImage = function zoomImage(multiplier) { var res = svgCanvas.getResolution(); - multiplier = multiplier ? res.zoom * multiplier : 1; - // setResolution(res.w * multiplier, res.h * multiplier, true); + multiplier = multiplier ? res.zoom * multiplier : 1; // setResolution(res.w * multiplier, res.h * multiplier, true); + $$b('#zoom').val(multiplier * 100); svgCanvas.setZoom(multiplier); zoomDone(); updateCanvas(true); }; + /** + * + * @returns {undefined} + */ + var dblclickZoom = function dblclickZoom() { if (toolButtonClick('#tool_zoom')) { @@ -29038,38 +33189,67 @@ setSelectMode(); } }; + /** + * + * @returns {undefined} + */ + var clickText = function clickText() { if (toolButtonClick('#tool_text')) { svgCanvas.setMode('text'); } }; + /** + * + * @returns {undefined} + */ + var clickPath = function clickPath() { if (toolButtonClick('#tool_path')) { svgCanvas.setMode('path'); } }; + /** + * Delete is a contextual tool that only appears in the ribbon if + * an element has been selected. + * @returns {undefined} + */ + - // Delete is a contextual tool that only appears in the ribbon if - // an element has been selected var deleteSelected = function deleteSelected() { - if (selectedElement != null || multiselected) { + if (!isNullish(selectedElement) || multiselected) { svgCanvas.deleteSelectedElements(); } }; + /** + * + * @returns {undefined} + */ + var cutSelected = function cutSelected() { - if (selectedElement != null || multiselected) { + if (!isNullish(selectedElement) || multiselected) { svgCanvas.cutSelectedElements(); } }; + /** + * + * @returns {undefined} + */ + var copySelected = function copySelected() { - if (selectedElement != null || multiselected) { + if (!isNullish(selectedElement) || multiselected) { svgCanvas.copySelectedElements(); } }; + /** + * + * @returns {undefined} + */ + var pasteInCenter = function pasteInCenter() { var zoom = svgCanvas.getZoom(); @@ -29077,76 +33257,162 @@ var y = (workarea[0].scrollTop + workarea.height() / 2) / zoom - svgCanvas.contentH; svgCanvas.pasteElements('point', x, y); }; + /** + * + * @returns {undefined} + */ + var moveToTopSelected = function moveToTopSelected() { - if (selectedElement != null) { + if (!isNullish(selectedElement)) { svgCanvas.moveToTopSelectedElement(); } }; + /** + * + * @returns {undefined} + */ + var moveToBottomSelected = function moveToBottomSelected() { - if (selectedElement != null) { + if (!isNullish(selectedElement)) { svgCanvas.moveToBottomSelectedElement(); } }; + /** + * @param {"Up"|"Down"} dir + * @returns {undefined} + */ + var moveUpDownSelected = function moveUpDownSelected(dir) { - if (selectedElement != null) { + if (!isNullish(selectedElement)) { svgCanvas.moveUpDownSelected(dir); } }; + /** + * + * @returns {undefined} + */ - var convertToPath$$1 = function convertToPath$$1() { - if (selectedElement != null) { + + var convertToPath = function convertToPath() { + if (!isNullish(selectedElement)) { svgCanvas.convertToPath(); } }; + /** + * + * @returns {undefined} + */ + var reorientPath = function reorientPath() { - if (selectedElement != null) { + if (!isNullish(selectedElement)) { path.reorient(); } }; + /** + * + * @returns {Promise} Resolves to `undefined` + */ - var makeHyperlink = function makeHyperlink() { - if (selectedElement != null || multiselected) { - $$b.prompt(uiStrings$1.notification.enterNewLinkURL, 'http://', function (url) { - if (url) { - svgCanvas.makeHyperlink(url); + + var makeHyperlink = + /*#__PURE__*/ + function () { + var _ref17 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee7() { + var url; + return regeneratorRuntime.wrap(function _callee7$(_context7) { + while (1) { + switch (_context7.prev = _context7.next) { + case 0: + if (!(!isNullish(selectedElement) || multiselected)) { + _context7.next = 5; + break; + } + + _context7.next = 3; + return $$b.prompt(uiStrings$1.notification.enterNewLinkURL, 'http://'); + + case 3: + url = _context7.sent; + + if (url) { + svgCanvas.makeHyperlink(url); + } + + case 5: + case "end": + return _context7.stop(); + } } - }); - } - }; + }, _callee7, this); + })); + + return function makeHyperlink() { + return _ref17.apply(this, arguments); + }; + }(); + /** + * @param {Float} dx + * @param {Float} dy + * @returns {undefined} + */ + var moveSelected = function moveSelected(dx, dy) { - if (selectedElement != null || multiselected) { + if (!isNullish(selectedElement) || multiselected) { if (curConfig.gridSnapping) { // Use grid snap value regardless of zoom level var multi = svgCanvas.getZoom() * curConfig.snappingStep; dx *= multi; dy *= multi; } + svgCanvas.moveSelectedElements(dx, dy); } }; + /** + * + * @returns {undefined} + */ + var linkControlPoints = function linkControlPoints() { $$b('#tool_node_link').toggleClass('push_button_pressed tool_button'); var linked = $$b('#tool_node_link').hasClass('push_button_pressed'); path.linkControlPoints(linked); }; + /** + * + * @returns {undefined} + */ + var clonePathNode = function clonePathNode() { if (path.getNodePoint()) { path.clonePathNode(); } }; + /** + * + * @returns {undefined} + */ + var deletePathNode = function deletePathNode() { if (path.getNodePoint()) { path.deletePathNode(); } }; + /** + * + * @returns {undefined} + */ + var addSubPath = function addSubPath() { var button = $$b('#tool_add_subpath'); @@ -29154,67 +33420,135 @@ button.toggleClass('push_button_pressed tool_button'); path.addSubPath(sp); }; + /** + * + * @returns {undefined} + */ + var opencloseSubPath = function opencloseSubPath() { path.opencloseSubPath(); }; + /** + * + * @returns {undefined} + */ + var selectNext = function selectNext() { svgCanvas.cycleElement(1); }; + /** + * + * @returns {undefined} + */ + var selectPrev = function selectPrev() { svgCanvas.cycleElement(0); }; + /** + * @param {0|1} cw + * @param {Integer} step + * @returns {undefined} + */ + var rotateSelected = function rotateSelected(cw, step) { - if (selectedElement == null || multiselected) { + if (isNullish(selectedElement) || multiselected) { return; } + if (!cw) { step *= -1; } + var angle = parseFloat($$b('#angle').val()) + step; svgCanvas.setRotationAngle(angle); updateContextPanel(); }; - /** * @fires module:svgcanvas.SvgCanvas#event:ext-onNewDocument - * @returns {undefined} + * @returns {Promise} Resolves to `undefined` */ - var clickClear = function clickClear() { - var _curConfig$dimensions = slicedToArray(curConfig.dimensions, 2), - x = _curConfig$dimensions[0], - y = _curConfig$dimensions[1]; - $$b.confirm(uiStrings$1.notification.QwantToClear, function (ok) { - if (!ok) { - return; - } - setSelectMode(); - svgCanvas.clear(); - svgCanvas.setResolution(x, y); - updateCanvas(true); - zoomImage(); - populateLayers(); - updateContextPanel(); - prepPaints(); - svgCanvas.runExtensions('onNewDocument'); - }); - }; + + var clickClear = + /*#__PURE__*/ + function () { + var _ref18 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee8() { + var _curConfig$dimensions, x, y, ok; + + return regeneratorRuntime.wrap(function _callee8$(_context8) { + while (1) { + switch (_context8.prev = _context8.next) { + case 0: + _curConfig$dimensions = _slicedToArray(curConfig.dimensions, 2), x = _curConfig$dimensions[0], y = _curConfig$dimensions[1]; + _context8.next = 3; + return $$b.confirm(uiStrings$1.notification.QwantToClear); + + case 3: + ok = _context8.sent; + + if (ok) { + _context8.next = 6; + break; + } + + return _context8.abrupt("return"); + + case 6: + setSelectMode(); + svgCanvas.clear(); + svgCanvas.setResolution(x, y); + updateCanvas(true); + zoomImage(); + populateLayers(); + updateContextPanel(); + prepPaints(); + svgCanvas.runExtensions('onNewDocument'); + + case 15: + case "end": + return _context8.stop(); + } + } + }, _callee8, this); + })); + + return function clickClear() { + return _ref18.apply(this, arguments); + }; + }(); + /** + * + * @returns {false} + */ + var clickBold = function clickBold() { svgCanvas.setBold(!svgCanvas.getBold()); updateContextPanel(); return false; }; + /** + * + * @returns {false} + */ + var clickItalic = function clickItalic() { svgCanvas.setItalic(!svgCanvas.getItalic()); updateContextPanel(); return false; }; + /** + * + * @returns {undefined} + */ + var clickSave = function clickSave() { // In the future, more options can be provided here @@ -29225,105 +33559,142 @@ svgCanvas.save(saveOpts); }; - var loadingURL = void 0; - var clickExport = function clickExport() { - $$b.select('Select an image type for export: ', [ - // See http://kangax.github.io/jstests/toDataUrl_mime_type_test/ for a useful list of MIME types and browser support - // 'ICO', // Todo: Find a way to preserve transparency in SVG-Edit if not working presently and do full packaging for x-icon; then switch back to position after 'PNG' - 'PNG', 'JPEG', 'BMP', 'WEBP', 'PDF'], function () { - var _ref15 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5(imgType) { - var exportWindowName, openExportWindow, chrome, quality; - return regeneratorRuntime.wrap(function _callee5$(_context5) { - while (1) { - switch (_context5.prev = _context5.next) { - case 0: - openExportWindow = function openExportWindow() { - var str = uiStrings$1.notification.loadingImage; - if (curConfig.exportWindowType === 'new') { - editor.exportWindowCt++; - } - exportWindowName = curConfig.canvasName + editor.exportWindowCt; - var popHTML = void 0, - popURL = void 0; - if (loadingURL) { - popURL = loadingURL; + var loadingURL; + /** + * + * @returns {Promise} Resolves to `undefined` + */ + + var clickExport = + /*#__PURE__*/ + function () { + var _ref19 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee9() { + var imgType, exportWindowName, openExportWindow, chrome, quality; + return regeneratorRuntime.wrap(function _callee9$(_context9) { + while (1) { + switch (_context9.prev = _context9.next) { + case 0: + openExportWindow = function _ref20() { + var loadingImage = uiStrings$1.notification.loadingImage; + + if (curConfig.exportWindowType === 'new') { + editor.exportWindowCt++; + } + + exportWindowName = curConfig.canvasName + editor.exportWindowCt; + var popHTML, popURL; + + if (loadingURL) { + popURL = loadingURL; + } else { + popHTML = "<!DOCTYPE html><html>\n <head>\n <meta charset=\"utf-8\">\n <title>".concat(loadingImage, "\n \n

    ").concat(loadingImage, "

    \n "); + + if (typeof URL !== 'undefined' && URL.createObjectURL) { + var blob = new Blob([popHTML], { + type: 'text/html' + }); + popURL = URL.createObjectURL(blob); } else { - popHTML = '\n \n \n ' + str + '\n \n

    ' + str + '

    \n '; - if ((typeof URL === 'undefined' ? 'undefined' : _typeof(URL)) && URL.createObjectURL) { - var blob = new Blob([popHTML], { type: 'text/html' }); - popURL = URL.createObjectURL(blob); - } else { - popURL = 'data:text/html;base64;charset=utf-8,' + encode64(popHTML); - } - loadingURL = popURL; + popURL = 'data:text/html;base64;charset=utf-8,' + encode64(popHTML); } - exportWindow = window.open(popURL, exportWindowName); - }; - if (imgType) { - _context5.next = 3; - break; + loadingURL = popURL; } - return _context5.abrupt('return'); + exportWindow = window.open(popURL, exportWindowName); + }; - case 3: - // Open placeholder window (prevents popup) - exportWindowName = void 0; - chrome = isChrome(); + _context9.next = 3; + return $$b.select('Select an image type for export: ', [// See http://kangax.github.io/jstests/toDataUrl_mime_type_test/ for a useful list of MIME types and browser support + // 'ICO', // Todo: Find a way to preserve transparency in SVG-Edit if not working presently and do full packaging for x-icon; then switch back to position after 'PNG' + 'PNG', 'JPEG', 'BMP', 'WEBP', 'PDF'], function () { + var sel = $$b(this); - if (!(imgType === 'PDF')) { - _context5.next = 10; - break; + if (sel.val() === 'JPEG' || sel.val() === 'WEBP') { + if (!$$b('#image-slider').length) { + $$b("
    ")).appendTo(sel.parent()); + } + } else { + $$b('#image-slider').parent().remove(); } + }); - if (!customExportPDF && !chrome) { - openExportWindow(); - } - svgCanvas.exportPDF(exportWindowName, chrome ? 'save' : undefined); - _context5.next = 14; + case 3: + imgType = _context9.sent; + + if (imgType) { + _context9.next = 6; break; + } - case 10: - if (!customExportImage) { - openExportWindow(); - } - quality = parseInt($$b('#image-slider').val(), 10) / 100; - /* const results = */ - _context5.next = 14; - return svgCanvas.rasterExport(imgType, quality, exportWindowName); + return _context9.abrupt("return"); - case 14: - case 'end': - return _context5.stop(); - } + case 6: + chrome = isChrome(); + + if (!(imgType === 'PDF')) { + _context9.next = 12; + break; + } + + if (!customExportPDF && !chrome) { + openExportWindow(); + } + + svgCanvas.exportPDF(exportWindowName); + _context9.next = 16; + break; + + case 12: + if (!customExportImage) { + openExportWindow(); + } + + quality = parseInt($$b('#image-slider').val()) / 100; + /* const results = */ + + _context9.next = 16; + return svgCanvas.rasterExport(imgType, quality, exportWindowName); + + case 16: + case "end": + return _context9.stop(); } - }, _callee5, this); - })); - - return function (_x5) { - return _ref15.apply(this, arguments); - }; - }(), function () { - var sel = $$b(this); - if (sel.val() === 'JPEG' || sel.val() === 'WEBP') { - if (!$$b('#image-slider').length) { - $$b('
    ').appendTo(sel.parent()); } - } else { - $$b('#image-slider').parent().remove(); - } - }); - }; + }, _callee9, this); + })); + + return function clickExport() { + return _ref19.apply(this, arguments); + }; + }(); + /** + * By default, svgCanvas.open() is a no-op. It is up to an extension + * mechanism (opera widget, etc.) to call `setCustomHandlers()` which + * will make it do something. + * @returns {undefined} + */ + - // by default, svgCanvas.open() is a no-op. - // it is up to an extension mechanism (opera widget, etc) - // to call setCustomHandlers() which will make it do something var clickOpen = function clickOpen() { svgCanvas.open(); }; + /** + * + * @returns {undefined} + */ + + + var clickImport = function clickImport() { + /* */ + }; + /** + * + * @returns {undefined} + */ - var clickImport = function clickImport() {}; var clickUndo = function clickUndo() { if (undoMgr.getUndoStackSize() > 0) { @@ -29331,6 +33702,11 @@ populateLayers(); } }; + /** + * + * @returns {undefined} + */ + var clickRedo = function clickRedo() { if (undoMgr.getRedoStackSize() > 0) { @@ -29338,25 +33714,44 @@ populateLayers(); } }; + /** + * + * @returns {undefined} + */ + var clickGroup = function clickGroup() { // group if (multiselected) { - svgCanvas.groupSelectedElements(); - // ungroup + svgCanvas.groupSelectedElements(); // ungroup } else if (selectedElement) { svgCanvas.ungroupSelectedElement(); } }; + /** + * + * @returns {undefined} + */ + var clickClone = function clickClone() { svgCanvas.cloneSelectedElements(20, 20); }; + /** + * + * @returns {undefined} + */ + var clickAlign = function clickAlign() { var letter = this.id.replace('tool_align', '').charAt(0); svgCanvas.alignSelectedElements(letter, $$b('#align_relative_to').val()); }; + /** + * + * @returns {undefined} + */ + var clickWireframe = function clickWireframe() { $$b('#tool_wireframe').toggleClass('push_button_pressed tool_button'); @@ -29365,9 +33760,12 @@ if (supportsNonSS) { return; } + var wfRules = $$b('#wireframe_rules'); + if (!wfRules.length) { - wfRules = $$b('').appendTo('head'); + /* wfRules = */ + $$b('').appendTo('head'); } else { wfRules.empty(); } @@ -29379,21 +33777,24 @@ cancel: 'button,fieldset', containment: 'window' }).css('position', 'absolute'); - var docprops = false; var preferences = false; + /** + * + * @returns {undefined} + */ var showDocProperties = function showDocProperties() { if (docprops) { return; } - docprops = true; - // This selects the correct radio button by using the array notation - $$b('#image_save_opts input').val([$$b.pref('img_save')]); + docprops = true; // This selects the correct radio button by using the array notation + + $$b('#image_save_opts input').val([$$b.pref('img_save')]); // update resolution option with actual resolution - // update resolution option with actual resolution var res = svgCanvas.getResolution(); + if (curConfig.baseUnit !== 'px') { res.w = convertUnit(res.w) + curConfig.baseUnit; res.h = convertUnit(res.h) + curConfig.baseUnit; @@ -29402,75 +33803,135 @@ $$b('#canvas_width').val(res.w); $$b('#canvas_height').val(res.h); $$b('#canvas_title').val(svgCanvas.getDocumentTitle()); - $$b('#svg_docprops').show(); }; + /** + * + * @returns {undefined} + */ + var showPreferences = function showPreferences() { if (preferences) { return; } - preferences = true; - $$b('#main_menu').hide(); - // Update background color with current one - var blocks = $$b('#bg_blocks div'); - var curBg = 'cur_background'; + preferences = true; + $$b('#main_menu').hide(); // Update background color with current one + var canvasBg = curPrefs.bkgd_color; var url = $$b.pref('bkgd_url'); blocks.each(function () { var blk = $$b(this); var isBg = blk.css('background-color') === canvasBg; blk.toggleClass(curBg, isBg); + if (isBg) { $$b('#canvas_bg_url').removeClass(curBg); } }); + if (!canvasBg) { blocks.eq(0).addClass(curBg); } + if (url) { $$b('#canvas_bg_url').val(url); } + $$b('#grid_snapping_on').prop('checked', curConfig.gridSnapping); $$b('#grid_snapping_step').attr('value', curConfig.snappingStep); $$b('#grid_color').attr('value', curConfig.gridColor); - $$b('#svg_prefs').show(); }; + /** + * + * @returns {undefined} + */ + var hideSourceEditor = function hideSourceEditor() { $$b('#svg_source_editor').hide(); editingsource = false; $$b('#svg_source_textarea').blur(); }; + /** + * + * @returns {Promise} Resolves to `undefined` + */ - var saveSourceEditor = function saveSourceEditor() { - if (!editingsource) { - return; - } - var saveChanges = function saveChanges() { - svgCanvas.clearSelection(); - hideSourceEditor(); - zoomImage(); - populateLayers(); - updateTitle(); - prepPaints(); - }; + var saveSourceEditor = + /*#__PURE__*/ + function () { + var _ref21 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee10() { + var saveChanges, ok; + return regeneratorRuntime.wrap(function _callee10$(_context10) { + while (1) { + switch (_context10.prev = _context10.next) { + case 0: + if (editingsource) { + _context10.next = 2; + break; + } - if (!svgCanvas.setSvgString($$b('#svg_source_textarea').val())) { - $$b.confirm(uiStrings$1.notification.QerrorsRevertToSource, function (ok) { - if (!ok) { - return false; + return _context10.abrupt("return"); + + case 2: + saveChanges = function saveChanges() { + svgCanvas.clearSelection(); + hideSourceEditor(); + zoomImage(); + populateLayers(); + updateTitle(); + prepPaints(); + }; + + if (svgCanvas.setSvgString($$b('#svg_source_textarea').val())) { + _context10.next = 11; + break; + } + + _context10.next = 6; + return $$b.confirm(uiStrings$1.notification.QerrorsRevertToSource); + + case 6: + ok = _context10.sent; + + if (ok) { + _context10.next = 9; + break; + } + + return _context10.abrupt("return"); + + case 9: + saveChanges(); + return _context10.abrupt("return"); + + case 11: + saveChanges(); + setSelectMode(); + + case 13: + case "end": + return _context10.stop(); + } } - saveChanges(); - }); - } else { - saveChanges(); - } - setSelectMode(); - }; + }, _callee10, this); + })); + + return function saveSourceEditor() { + return _ref21.apply(this, arguments); + }; + }(); + /** + * + * @returns {undefined} + */ + var hideDocProperties = function hideDocProperties() { $$b('#svg_docprops').hide(); @@ -29479,150 +33940,250 @@ $$b('#image_save_opts input').val([$$b.pref('img_save')]); docprops = false; }; + /** + * + * @returns {undefined} + */ + var hidePreferences = function hidePreferences() { $$b('#svg_prefs').hide(); preferences = false; }; + /** + * + * @returns {boolean} Whether there were problems saving the document properties + */ + var saveDocProperties = function saveDocProperties() { // set title var newTitle = $$b('#canvas_title').val(); updateTitle(newTitle); - svgCanvas.setDocumentTitle(newTitle); + svgCanvas.setDocumentTitle(newTitle); // update resolution - // update resolution var width = $$b('#canvas_width'), w = width.val(); var height = $$b('#canvas_height'), h = height.val(); if (w !== 'fit' && !isValidUnit('width', w)) { - $$b.alert(uiStrings$1.notification.invalidAttrValGiven); width.parent().addClass('error'); + /* await */ + + $$b.alert(uiStrings$1.notification.invalidAttrValGiven); return false; } width.parent().removeClass('error'); if (h !== 'fit' && !isValidUnit('height', h)) { - $$b.alert(uiStrings$1.notification.invalidAttrValGiven); height.parent().addClass('error'); + /* await */ + + $$b.alert(uiStrings$1.notification.invalidAttrValGiven); return false; } height.parent().removeClass('error'); if (!svgCanvas.setResolution(w, h)) { + /* await */ $$b.alert(uiStrings$1.notification.noContentToFitTo); return false; - } + } // Set image save option + - // Set image save option $$b.pref('img_save', $$b('#image_save_opts :checked').val()); updateCanvas(); hideDocProperties(); + return true; }; - /** - * Save user preferences based on current values in the UI + * Save user preferences based on current values in the UI. * @function module:SVGEditor.savePreferences * @returns {undefined} */ - var savePreferences = editor.savePreferences = function () { - // Set background - var color = $$b('#bg_blocks div.cur_background').css('background-color') || '#FFF'; - setBackground(color, $$b('#canvas_bg_url').val()); - // set language - var lang = $$b('#lang_select').val(); - if (lang !== $$b.pref('lang')) { - editor.putLocale(lang, goodLangs, curConfig); - } - // set icon size - setIconSize($$b('#iconsize').val()); + var savePreferences = editor.savePreferences = + /*#__PURE__*/ + _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee11() { + var color, lang, _ref23, langParam, langData; - // set grid setting - curConfig.gridSnapping = $$b('#grid_snapping_on')[0].checked; - curConfig.snappingStep = $$b('#grid_snapping_step').val(); - curConfig.gridColor = $$b('#grid_color').val(); - curConfig.showRulers = $$b('#show_rulers')[0].checked; + return regeneratorRuntime.wrap(function _callee11$(_context11) { + while (1) { + switch (_context11.prev = _context11.next) { + case 0: + // Set background + color = $$b('#bg_blocks div.cur_background').css('background-color') || '#FFF'; + setBackground(color, $$b('#canvas_bg_url').val()); // set language - $$b('#rulers').toggle(curConfig.showRulers); - if (curConfig.showRulers) { - updateRulers(); - } - curConfig.baseUnit = $$b('#base_unit').val(); + lang = $$b('#lang_select').val(); - svgCanvas.setConfig(curConfig); + if (!(lang !== $$b.pref('lang'))) { + _context11.next = 11; + break; + } - updateCanvas(); - hidePreferences(); - }; + _context11.next = 6; + return editor.putLocale(lang, goodLangs, curConfig); + + case 6: + _ref23 = _context11.sent; + langParam = _ref23.langParam; + langData = _ref23.langData; + _context11.next = 11; + return setLang(langParam, langData); + + case 11: + // set icon size + setIconSize($$b('#iconsize').val()); // set grid setting + + curConfig.gridSnapping = $$b('#grid_snapping_on')[0].checked; + curConfig.snappingStep = $$b('#grid_snapping_step').val(); + curConfig.gridColor = $$b('#grid_color').val(); + curConfig.showRulers = $$b('#show_rulers')[0].checked; + $$b('#rulers').toggle(curConfig.showRulers); + + if (curConfig.showRulers) { + updateRulers(); + } + + curConfig.baseUnit = $$b('#base_unit').val(); + svgCanvas.setConfig(curConfig); + updateCanvas(); + hidePreferences(); + + case 22: + case "end": + return _context11.stop(); + } + } + }, _callee11, this); + })); var resetScrollPos = $$b.noop; + /** + * + * @returns {Promise} Resolves to `undefined` + */ - var cancelOverlays = function cancelOverlays() { - $$b('#dialog_box').hide(); - if (!editingsource && !docprops && !preferences) { - if (curContext) { - svgCanvas.leaveContext(); - } - return; - } + var cancelOverlays = + /*#__PURE__*/ + function () { + var _ref24 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee12() { + var ok; + return regeneratorRuntime.wrap(function _callee12$(_context12) { + while (1) { + switch (_context12.prev = _context12.next) { + case 0: + $$b('#dialog_box').hide(); - if (editingsource) { - if (origSource !== $$b('#svg_source_textarea').val()) { - $$b.confirm(uiStrings$1.notification.QignoreSourceChanges, function (ok) { - if (ok) { - hideSourceEditor(); + if (!(!editingsource && !docprops && !preferences)) { + _context12.next = 4; + break; + } + + if (curContext) { + svgCanvas.leaveContext(); + } + + return _context12.abrupt("return"); + + case 4: + if (!editingsource) { + _context12.next = 15; + break; + } + + if (!(origSource !== $$b('#svg_source_textarea').val())) { + _context12.next = 12; + break; + } + + _context12.next = 8; + return $$b.confirm(uiStrings$1.notification.QignoreSourceChanges); + + case 8: + ok = _context12.sent; + + if (ok) { + hideSourceEditor(); + } + + _context12.next = 13; + break; + + case 12: + hideSourceEditor(); + + case 13: + _context12.next = 16; + break; + + case 15: + if (docprops) { + hideDocProperties(); + } else if (preferences) { + hidePreferences(); + } + + case 16: + resetScrollPos(); + + case 17: + case "end": + return _context12.stop(); } - }); - } else { - hideSourceEditor(); - } - } else if (docprops) { - hideDocProperties(); - } else if (preferences) { - hidePreferences(); - } - resetScrollPos(); - }; - - var winWh = { width: $$b(window).width(), height: $$b(window).height() }; - - // Fix for Issue 781: Drawing area jumps to top-left corner on window resize (IE9) - if (isIE()) { - (function () { - resetScrollPos = function resetScrollPos() { - if (workarea[0].scrollLeft === 0 && workarea[0].scrollTop === 0) { - workarea[0].scrollLeft = curScrollPos.left; - workarea[0].scrollTop = curScrollPos.top; } - }; + }, _callee12, this); + })); + return function cancelOverlays() { + return _ref24.apply(this, arguments); + }; + }(); + + var winWh = { + width: $$b(window).width(), + height: $$b(window).height() + }; // Fix for Issue 781: Drawing area jumps to top-left corner on window resize (IE9) + + if (isIE()) { + resetScrollPos = function resetScrollPos() { + if (workarea[0].scrollLeft === 0 && workarea[0].scrollTop === 0) { + workarea[0].scrollLeft = curScrollPos.left; + workarea[0].scrollTop = curScrollPos.top; + } + }; + + curScrollPos = { + left: workarea[0].scrollLeft, + top: workarea[0].scrollTop + }; + $$b(window).resize(resetScrollPos); + editor.ready(function () { + // TODO: Find better way to detect when to do this to minimize + // flickering effect + return new Promise(function (resolve, reject) { + // eslint-disable-line promise/avoid-new + setTimeout(function () { + resetScrollPos(); + resolve(); + }, 500); + }); + }); + workarea.scroll(function () { curScrollPos = { left: workarea[0].scrollLeft, top: workarea[0].scrollTop }; - - $$b(window).resize(resetScrollPos); - editor.ready(function () { - // TODO: Find better way to detect when to do this to minimize - // flickering effect - setTimeout(function () { - resetScrollPos(); - }, 500); - }); - - workarea.scroll(function () { - curScrollPos = { - left: workarea[0].scrollLeft, - top: workarea[0].scrollTop - }; - }); - })(); + }); } $$b(window).resize(function (evt) { @@ -29633,43 +34194,35 @@ }); setFlyoutPositions(); }); + workarea.scroll(function () { + // TODO: jQuery's scrollLeft/Top() wouldn't require a null check + if ($$b('#ruler_x').length) { + $$b('#ruler_x')[0].scrollLeft = workarea[0].scrollLeft; + } - (function () { - workarea.scroll(function () { - // TODO: jQuery's scrollLeft/Top() wouldn't require a null check - if ($$b('#ruler_x').length) { - $$b('#ruler_x')[0].scrollLeft = workarea[0].scrollLeft; - } - if ($$b('#ruler_y').length) { - $$b('#ruler_y')[0].scrollTop = workarea[0].scrollTop; - } - }); - })(); - + if ($$b('#ruler_y').length) { + $$b('#ruler_y')[0].scrollTop = workarea[0].scrollTop; + } + }); $$b('#url_notice').click(function () { + /* await */ $$b.alert(this.title); }); - - $$b('#change_image_url').click(promptImgURL); - - // added these event handlers for all the push buttons so they + $$b('#change_image_url').click(promptImgURL); // added these event handlers for all the push buttons so they // behave more like buttons being pressed-in and not images + (function () { var toolnames = ['clear', 'open', 'save', 'source', 'delete', 'delete_multi', 'paste', 'clone', 'clone_multi', 'move_top', 'move_bottom']; var curClass = 'tool_button_current'; - var allTools = ''; - $$b.each(toolnames, function (i, item) { allTools += (i ? ',' : '') + '#tool_' + item; }); - $$b(allTools).mousedown(function () { $$b(this).addClass(curClass); }).bind('mousedown mouseout', function () { $$b(this).removeClass(curClass); }); - $$b('#tool_undo, #tool_redo').mousedown(function () { if (!$$b(this).hasClass('disabled')) { $$b(this).addClass(curClass); @@ -29677,42 +34230,54 @@ }).bind('mousedown mouseout', function () { $$b(this).removeClass(curClass); }); - })(); - - // switch modifier key in tooltips if mac + })(); // switch modifier key in tooltips if mac // NOTE: This code is not used yet until I can figure out how to successfully bind ctrl/meta // in Opera and Chrome + + if (isMac() && !window.opera) { var shortcutButtons = ['tool_clear', 'tool_save', 'tool_source', 'tool_undo', 'tool_redo', 'tool_clone']; var _i2 = shortcutButtons.length; + while (_i2--) { var button = document.getElementById(shortcutButtons[_i2]); + if (button) { var title = button.title; - var index = title.indexOf('Ctrl+'); button.title = [title.substr(0, index), 'Cmd+', title.substr(index + 5)].join(''); } } } + /** + * @param {external:jQuery} elem + * @todo Go back to the color boxes having white background-color and then setting + * background-image to none.png (otherwise partially transparent gradients look weird) + * @returns {undefined} + */ + - // TODO: go back to the color boxes having white background-color and then setting - // background-image to none.png (otherwise partially transparent gradients look weird) var colorPicker = function colorPicker(elem) { - var picker = elem.attr('id') === 'stroke_color' ? 'stroke' : 'fill'; - // const opacity = (picker == 'stroke' ? $('#stroke_opacity') : $('#fill_opacity')); - var title = picker === 'stroke' ? uiStrings$1.ui.pick_stroke_paint_opacity : uiStrings$1.ui.pick_fill_paint_opacity; - // let wasNone = false; // Currently unused + var picker = elem.attr('id') === 'stroke_color' ? 'stroke' : 'fill'; // const opacity = (picker == 'stroke' ? $('#stroke_opacity') : $('#fill_opacity')); + + var title = picker === 'stroke' ? uiStrings$1.ui.pick_stroke_paint_opacity : uiStrings$1.ui.pick_fill_paint_opacity; // let wasNone = false; // Currently unused + var pos = elem.offset(); var paint = paintBox[picker].paint; - $$b('#color_picker').draggable({ cancel: '.jGraduate_tabs, .jGraduate_colPick, .jGraduate_gradPick, .jPicker', containment: 'window' - }).css(curConfig.colorPickerCSS || { left: pos.left - 140, bottom: 40 }).jGraduate({ + }).css(curConfig.colorPickerCSS || { + left: pos.left - 140, + bottom: 40 + }).jGraduate({ paint: paint, - window: { pickerTitle: title }, - images: { clientPath: curConfig.jGraduatePath }, + window: { + pickerTitle: title + }, + images: { + clientPath: curConfig.jGraduatePath + }, newstop: 'inverse' }, function (p) { paint = new $$b.jGraduate.Paint(p); @@ -29724,158 +34289,183 @@ }); }; - var PaintBox = function PaintBox(container, type) { - var paintColor = void 0, - paintOpacity = void 0; - var cur = curConfig[type === 'fill' ? 'initFill' : 'initStroke']; - // set up gradients to be used for the buttons - var svgdocbox = new DOMParser().parseFromString('\n \n \n ', 'text/xml'); + var PaintBox = + /*#__PURE__*/ + function () { + function PaintBox(container, type) { + _classCallCheck(this, PaintBox); - var docElem = svgdocbox.documentElement; - docElem = $$b(container)[0].appendChild(document.importNode(docElem, true)); - docElem.setAttribute('width', 16.5); + var cur = curConfig[type === 'fill' ? 'initFill' : 'initStroke']; // set up gradients to be used for the buttons - this.rect = docElem.firstElementChild; - this.defs = docElem.getElementsByTagName('defs')[0]; - this.grad = this.defs.firstElementChild; - this.paint = new $$b.jGraduate.Paint({ solidColor: cur.color }); - this.type = type; + var svgdocbox = new DOMParser().parseFromString("\n \n \n "), 'text/xml'); + var docElem = svgdocbox.documentElement; + docElem = $$b(container)[0].appendChild(document.importNode(docElem, true)); + docElem.setAttribute('width', 16.5); + this.rect = docElem.firstElementChild; + this.defs = docElem.getElementsByTagName('defs')[0]; + this.grad = this.defs.firstElementChild; + this.paint = new $$b.jGraduate.Paint({ + solidColor: cur.color + }); + this.type = type; + } - this.setPaint = function (paint, apply) { - this.paint = paint; + _createClass(PaintBox, [{ + key: "setPaint", + value: function setPaint(paint, apply) { + this.paint = paint; + var ptype = paint.type; + var opac = paint.alpha / 100; + var fillAttr = 'none'; - var ptype = paint.type; - var opac = paint.alpha / 100; - - var fillAttr = 'none'; - switch (ptype) { - case 'solidColor': - fillAttr = paint[ptype] !== 'none' ? '#' + paint[ptype] : paint[ptype]; - break; - case 'linearGradient': - case 'radialGradient': - this.grad.remove(); - this.grad = this.defs.appendChild(paint[ptype]); - var id = this.grad.id = 'gradbox_' + this.type; - fillAttr = 'url(#' + id + ')'; - break; - } - - this.rect.setAttribute('fill', fillAttr); - this.rect.setAttribute('opacity', opac); - - if (apply) { - svgCanvas.setColor(this.type, paintColor, true); - svgCanvas.setPaintOpacity(this.type, paintOpacity, true); - } - }; - - this.update = function (apply) { - if (!selectedElement) { - return; - } - - var type = this.type; - - switch (selectedElement.tagName) { - case 'use': - case 'image': - case 'foreignObject': - // These elements don't have fill or stroke, so don't change - // the current value - return; - case 'g': - case 'a': - { - var childs = selectedElement.getElementsByTagName('*'); - - var gPaint = null; - for (var _i3 = 0, len = childs.length; _i3 < len; _i3++) { - var elem = childs[_i3]; - var p = elem.getAttribute(type); - if (_i3 === 0) { - gPaint = p; - } else if (gPaint !== p) { - gPaint = null; - break; - } - } - - if (gPaint === null) { - // No common color, don't update anything - paintColor = null; - return; - } - paintColor = gPaint; - paintOpacity = 1; + switch (ptype) { + case 'solidColor': + fillAttr = paint[ptype] !== 'none' ? '#' + paint[ptype] : paint[ptype]; break; - }default: - paintOpacity = parseFloat(selectedElement.getAttribute(type + '-opacity')); - if (isNaN(paintOpacity)) { - paintOpacity = 1.0; - } - var defColor = type === 'fill' ? 'black' : 'none'; - paintColor = selectedElement.getAttribute(type) || defColor; + case 'linearGradient': + case 'radialGradient': + { + this.grad.remove(); + this.grad = this.defs.appendChild(paint[ptype]); + var id = this.grad.id = 'gradbox_' + this.type; + fillAttr = 'url(#' + id + ')'; + break; + } + } + + this.rect.setAttribute('fill', fillAttr); + this.rect.setAttribute('opacity', opac); + + if (apply) { + svgCanvas.setColor(this.type, this._paintColor, true); + svgCanvas.setPaintOpacity(this.type, this._paintOpacity, true); + } } + }, { + key: "update", + value: function update(apply) { + if (!selectedElement) { + return; + } - if (apply) { - svgCanvas.setColor(type, paintColor, true); - svgCanvas.setPaintOpacity(type, paintOpacity, true); + var type = this.type; + + switch (selectedElement.tagName) { + case 'use': + case 'image': + case 'foreignObject': + // These elements don't have fill or stroke, so don't change + // the current value + return; + + case 'g': + case 'a': + { + var childs = selectedElement.getElementsByTagName('*'); + var gPaint = null; + + for (var _i3 = 0, len = childs.length; _i3 < len; _i3++) { + var elem = childs[_i3]; + var p = elem.getAttribute(type); + + if (_i3 === 0) { + gPaint = p; + } else if (gPaint !== p) { + gPaint = null; + break; + } + } + + if (gPaint === null) { + // No common color, don't update anything + this._paintColor = null; + return; + } + + this._paintColor = gPaint; + this._paintOpacity = 1; + break; + } + + default: + { + this._paintOpacity = parseFloat(selectedElement.getAttribute(type + '-opacity')); + + if (isNaN(this._paintOpacity)) { + this._paintOpacity = 1.0; + } + + var defColor = type === 'fill' ? 'black' : 'none'; + this._paintColor = selectedElement.getAttribute(type) || defColor; + } + } + + if (apply) { + svgCanvas.setColor(type, this._paintColor, true); + svgCanvas.setPaintOpacity(type, this._paintOpacity, true); + } + + this._paintOpacity *= 100; + var paint = getPaint(this._paintColor, this._paintOpacity, type); // update the rect inside #fill_color/#stroke_color + + this.setPaint(paint); } + }, { + key: "prep", + value: function prep() { + var ptype = this.paint.type; - paintOpacity *= 100; - - var paint = getPaint(paintColor, paintOpacity, type); - // update the rect inside #fill_color/#stroke_color - this.setPaint(paint); - }; - - this.prep = function () { - var ptype = this.paint.type; - - switch (ptype) { - case 'linearGradient': - case 'radialGradient': - var paint = new $$b.jGraduate.Paint({ copy: this.paint }); - svgCanvas.setPaint(type, paint); - break; + switch (ptype) { + case 'linearGradient': + case 'radialGradient': + { + var paint = new $$b.jGraduate.Paint({ + copy: this.paint + }); + svgCanvas.setPaint(this.type, paint); + break; + } + } } - }; - }; + }]); + + return PaintBox; + }(); paintBox.fill = new PaintBox('#fill_color', 'fill'); paintBox.stroke = new PaintBox('#stroke_color', 'stroke'); - $$b('#stroke_width').val(curConfig.initStroke.width); - $$b('#group_opacity').val(curConfig.initOpacity * 100); + $$b('#group_opacity').val(curConfig.initOpacity * 100); // Use this SVG elem to test vectorEffect support - // Use this SVG elem to test vectorEffect support var testEl = paintBox.fill.rect.cloneNode(false); testEl.setAttribute('style', 'vector-effect:non-scaling-stroke'); var supportsNonSS = testEl.style.vectorEffect === 'non-scaling-stroke'; testEl.removeAttribute('style'); - var svgdocbox = paintBox.fill.rect.ownerDocument; - // Use this to test support for blur element. Seems to work to test support in Webkit + var svgdocbox = paintBox.fill.rect.ownerDocument; // Use this to test support for blur element. Seems to work to test support in Webkit + var blurTest = svgdocbox.createElementNS(NS.SVG, 'feGaussianBlur'); + if (blurTest.stdDeviationX === undefined) { $$b('#tool_blur').hide(); } - $$b(blurTest).remove(); - // Test for zoom icon support + $$b(blurTest).remove(); // Test for zoom icon support + (function () { var pre = '-' + uaPrefix.toLowerCase() + '-zoom-'; var zoom = pre + 'in'; workarea.css('cursor', zoom); + if (workarea.css('cursor') === zoom) { zoomInIcon = zoom; zoomOutIcon = pre + 'out'; } - workarea.css('cursor', 'auto'); - })(); - // Test for embedImage support (use timeout to not interfere with page load) + workarea.css('cursor', 'auto'); + })(); // Test for embedImage support (use timeout to not interfere with page load) + + setTimeout(function () { svgCanvas.embedImage('images/logo.png', function (datauri) { if (!datauri) { @@ -29887,32 +34477,26 @@ } }); }, 1000); - $$b('#fill_color, #tool_fill .icon_label').click(function () { colorPicker($$b('#fill_color')); updateToolButtonState(); }); - $$b('#stroke_color, #tool_stroke .icon_label').click(function () { colorPicker($$b('#stroke_color')); updateToolButtonState(); }); - $$b('#group_opacityLabel').click(function () { $$b('#opacity_dropdown button').mousedown(); $$b(window).mouseup(); }); - $$b('#zoomLabel').click(function () { $$b('#zoom_dropdown button').mousedown(); $$b(window).mouseup(); }); - $$b('#tool_move_top').mousedown(function (evt) { $$b('#tools_stacking').show(); evt.preventDefault(); }); - $$b('.layer_button').mousedown(function () { $$b(this).addClass('layer_buttonpressed'); }).mouseout(function () { @@ -29920,7 +34504,6 @@ }).mouseup(function () { $$b(this).removeClass('layer_buttonpressed'); }); - $$b('.push_button').mousedown(function () { if (!$$b(this).hasClass('disabled')) { $$b(this).addClass('push_button_pressed').removeClass('push_button'); @@ -29929,72 +34512,157 @@ $$b(this).removeClass('push_button_pressed').addClass('push_button'); }).mouseup(function () { $$b(this).removeClass('push_button_pressed').addClass('push_button'); - }); + }); // ask for a layer name - // ask for a layer name - $$b('#layer_new').click(function () { - var uniqName = void 0, - i = svgCanvas.getCurrentDrawing().getNumLayers(); - do { - uniqName = uiStrings$1.layers.layer + ' ' + ++i; - } while (svgCanvas.getCurrentDrawing().hasLayer(uniqName)); + $$b('#layer_new').click( + /*#__PURE__*/ + _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee13() { + var uniqName, i, newName; + return regeneratorRuntime.wrap(function _callee13$(_context13) { + while (1) { + switch (_context13.prev = _context13.next) { + case 0: + i = svgCanvas.getCurrentDrawing().getNumLayers(); - $$b.prompt(uiStrings$1.notification.enterUniqueLayerName, uniqName, function (newName) { - if (!newName) { - return; + do { + uniqName = uiStrings$1.layers.layer + ' ' + ++i; + } while (svgCanvas.getCurrentDrawing().hasLayer(uniqName)); + + _context13.next = 4; + return $$b.prompt(uiStrings$1.notification.enterUniqueLayerName, uniqName); + + case 4: + newName = _context13.sent; + + if (newName) { + _context13.next = 7; + break; + } + + return _context13.abrupt("return"); + + case 7: + if (!svgCanvas.getCurrentDrawing().hasLayer(newName)) { + _context13.next = 10; + break; + } + + /* await */ + $$b.alert(uiStrings$1.notification.dupeLayerName); + return _context13.abrupt("return"); + + case 10: + svgCanvas.createLayer(newName); + updateContextPanel(); + populateLayers(); + + case 13: + case "end": + return _context13.stop(); + } } - if (svgCanvas.getCurrentDrawing().hasLayer(newName)) { - $$b.alert(uiStrings$1.notification.dupeLayerName); - return; - } - svgCanvas.createLayer(newName); - updateContextPanel(); - populateLayers(); - }); - }); + }, _callee13, this); + }))); + /** + * + * @returns {undefined} + */ function deleteLayer() { if (svgCanvas.deleteCurrentLayer()) { updateContextPanel(); - populateLayers(); - // This matches what SvgCanvas does + populateLayers(); // This matches what SvgCanvas does // TODO: make this behavior less brittle (svg-editor should get which // layer is selected from the canvas and then select that one in the UI) + $$b('#layerlist tr.layer').removeClass('layersel'); $$b('#layerlist tr.layer:first').addClass('layersel'); } } + /** + * + * @returns {undefined} + */ + function cloneLayer() { - var name = svgCanvas.getCurrentDrawing().getCurrentLayerName() + ' copy'; + return _cloneLayer.apply(this, arguments); + } + /** + * + * @returns {undefined} + */ - $$b.prompt(uiStrings$1.notification.enterUniqueLayerName, name, function (newName) { - if (!newName) { - return; - } - if (svgCanvas.getCurrentDrawing().hasLayer(newName)) { - $$b.alert(uiStrings$1.notification.dupeLayerName); - return; - } - svgCanvas.cloneLayer(newName); - updateContextPanel(); - populateLayers(); - }); + + function _cloneLayer() { + _cloneLayer = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee19() { + var name, newName; + return regeneratorRuntime.wrap(function _callee19$(_context19) { + while (1) { + switch (_context19.prev = _context19.next) { + case 0: + name = svgCanvas.getCurrentDrawing().getCurrentLayerName() + ' copy'; + _context19.next = 3; + return $$b.prompt(uiStrings$1.notification.enterUniqueLayerName, name); + + case 3: + newName = _context19.sent; + + if (newName) { + _context19.next = 6; + break; + } + + return _context19.abrupt("return"); + + case 6: + if (!svgCanvas.getCurrentDrawing().hasLayer(newName)) { + _context19.next = 9; + break; + } + + /* await */ + $$b.alert(uiStrings$1.notification.dupeLayerName); + return _context19.abrupt("return"); + + case 9: + svgCanvas.cloneLayer(newName); + updateContextPanel(); + populateLayers(); + + case 12: + case "end": + return _context19.stop(); + } + } + }, _callee19, this); + })); + return _cloneLayer.apply(this, arguments); } function mergeLayer() { if ($$b('#layerlist tr.layersel').index() === svgCanvas.getCurrentDrawing().getNumLayers() - 1) { return; } + svgCanvas.mergeLayer(); updateContextPanel(); populateLayers(); } + /** + * @param {Integer} pos + * @returns {undefined} + */ + function moveLayer(pos) { var total = svgCanvas.getCurrentDrawing().getNumLayers(); - var curIndex = $$b('#layerlist tr.layersel').index(); + if (curIndex > 0 || curIndex < total - 1) { curIndex += pos; svgCanvas.setCurrentLayerPosition(total - curIndex - 1); @@ -30003,92 +34671,130 @@ } $$b('#layer_delete').click(deleteLayer); - $$b('#layer_up').click(function () { moveLayer(-1); }); - $$b('#layer_down').click(function () { moveLayer(1); }); + $$b('#layer_rename').click( + /*#__PURE__*/ + _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee14() { + var oldName, newName; + return regeneratorRuntime.wrap(function _callee14$(_context14) { + while (1) { + switch (_context14.prev = _context14.next) { + case 0: + // const curIndex = $('#layerlist tr.layersel').prevAll().length; // Currently unused + oldName = $$b('#layerlist tr.layersel td.layername').text(); + _context14.next = 3; + return $$b.prompt(uiStrings$1.notification.enterNewLayerName, ''); - $$b('#layer_rename').click(function () { - // const curIndex = $('#layerlist tr.layersel').prevAll().length; // Currently unused - var oldName = $$b('#layerlist tr.layersel td.layername').text(); - $$b.prompt(uiStrings$1.notification.enterNewLayerName, '', function (newName) { - if (!newName) { - return; + case 3: + newName = _context14.sent; + + if (newName) { + _context14.next = 6; + break; + } + + return _context14.abrupt("return"); + + case 6: + if (!(oldName === newName || svgCanvas.getCurrentDrawing().hasLayer(newName))) { + _context14.next = 9; + break; + } + + /* await */ + $$b.alert(uiStrings$1.notification.layerHasThatName); + return _context14.abrupt("return"); + + case 9: + svgCanvas.renameCurrentLayer(newName); + populateLayers(); + + case 11: + case "end": + return _context14.stop(); + } } - if (oldName === newName || svgCanvas.getCurrentDrawing().hasLayer(newName)) { - $$b.alert(uiStrings$1.notification.layerHasThatName); - return; - } - - svgCanvas.renameCurrentLayer(newName); - populateLayers(); - }); - }); - + }, _callee14, this); + }))); var SIDEPANEL_MAXWIDTH = 300; var SIDEPANEL_OPENWIDTH = 150; var sidedrag = -1, sidedragging = false, allowmove = false; - /** * @param {Float} delta * @fires module:svgcanvas.SvgCanvas#event:ext-workareaResized * @returns {undefined} */ + var changeSidePanelWidth = function changeSidePanelWidth(delta) { var rulerX = $$b('#ruler_x'); $$b('#sidepanels').width('+=' + delta); $$b('#layerpanel').width('+=' + delta); - rulerX.css('right', parseInt(rulerX.css('right'), 10) + delta); - workarea.css('right', parseInt(workarea.css('right'), 10) + delta); + rulerX.css('right', parseInt(rulerX.css('right')) + delta); + workarea.css('right', parseInt(workarea.css('right')) + delta); svgCanvas.runExtensions('workareaResized'); }; + /** + * @param {Event} evt + * @returns {undefined} + */ + var resizeSidePanel = function resizeSidePanel(evt) { if (!allowmove) { return; } + if (sidedrag === -1) { return; } + sidedragging = true; var deltaX = sidedrag - evt.pageX; var sideWidth = $$b('#sidepanels').width(); + if (sideWidth + deltaX > SIDEPANEL_MAXWIDTH) { - deltaX = SIDEPANEL_MAXWIDTH - sideWidth; - sideWidth = SIDEPANEL_MAXWIDTH; + deltaX = SIDEPANEL_MAXWIDTH - sideWidth; // sideWidth = SIDEPANEL_MAXWIDTH; } else if (sideWidth + deltaX < 2) { - deltaX = 2 - sideWidth; - sideWidth = 2; + deltaX = 2 - sideWidth; // sideWidth = 2; } + if (deltaX === 0) { return; } + sidedrag -= deltaX; changeSidePanelWidth(deltaX); }; - /** - * If width is non-zero, then fully close it, otherwise fully open it + * If width is non-zero, then fully close it; otherwise fully open it. * @param {boolean} close Forces the side panel closed * @returns {undefined} */ + + var toggleSidePanel = function toggleSidePanel(close) { + var dpr = window.devicePixelRatio || 1; var w = $$b('#sidepanels').width(); - var deltaX = (w > 2 || close ? 2 : SIDEPANEL_OPENWIDTH) - w; + var isOpened = (dpr < 1 ? w : w / dpr) > 2; + var zoomAdjustedSidepanelWidth = (dpr < 1 ? 1 : dpr) * SIDEPANEL_OPENWIDTH; + var deltaX = (isOpened || close ? 0 : zoomAdjustedSidepanelWidth) - w; changeSidePanelWidth(deltaX); }; $$b('#sidepanel_handle').mousedown(function (evt) { sidedrag = evt.pageX; $$b(window).mousemove(resizeSidePanel); - allowmove = false; - // Silly hack for Chrome, which always runs mousemove right after mousedown + allowmove = false; // Silly hack for Chrome, which always runs mousemove right after mousedown + setTimeout(function () { allowmove = true; }, 20); @@ -30096,19 +34802,16 @@ if (!sidedragging) { toggleSidePanel(); } + sidedrag = -1; sidedragging = false; }); - $$b(window).mouseup(function () { sidedrag = -1; sidedragging = false; $$b('#svg_editor').unbind('mousemove', resizeSidePanel); }); - - populateLayers(); - - // function changeResolution (x,y) { + populateLayers(); // function changeResolution (x,y) { // const {zoom} = svgCanvas.getResolution(); // setResolution(x * zoom, y * zoom); // } @@ -30119,11 +34822,15 @@ }; $$b(window).bind('load resize', centerCanvas); + /** + * @implements {module:jQuerySpinButton.StepCallback} + */ function stepFontSize(elem, step) { var origVal = Number(elem.value); var sugVal = origVal + step; var increasing = sugVal >= origVal; + if (step === 0) { return origVal; } @@ -30132,23 +34839,34 @@ if (increasing) { return Math.round(origVal * 1.1); } + return Math.round(origVal / 1.1); } + if (origVal <= 1) { if (increasing) { return origVal * 2; } + return origVal / 2; } + return sugVal; } + /** + * @implements {module:jQuerySpinButton.StepCallback} + */ + function stepZoom(elem, step) { var origVal = Number(elem.value); + if (origVal === 0) { return 100; } + var sugVal = origVal + step; + if (step === 0) { return origVal; } @@ -30156,13 +34874,13 @@ if (origVal >= 100) { return sugVal; } + if (sugVal >= origVal) { return origVal * 2; } - return origVal / 2; - } - // function setResolution (w, h, center) { + return origVal / 2; + } // function setResolution (w, h, center) { // updateCanvas(); // // w -= 0; h -= 0; // // $('#svgcanvas').css({width: w, height: h}); @@ -30178,8 +34896,10 @@ // // } // } + $$b('#resolution').change(function () { var wh = $$b('#canvas_width,#canvas_height'); + if (!this.selectedIndex) { if ($$b('#canvas_width').val() === 'fit') { wh.removeAttr('disabled').val(100); @@ -30192,15 +34912,15 @@ $$b('#canvas_height').val(dims[1]); wh.removeAttr('disabled'); } - }); + }); // Prevent browser from erroneously repopulating fields - // Prevent browser from erroneously repopulating fields $$b('input,select').attr('autocomplete', 'off'); - + var dialogSelectors = ['#tool_source_cancel', '#tool_docprops_cancel', '#tool_prefs_cancel', '.overlay']; /** * Associate all button actions as well as non-button keyboard shortcuts * @namespace {PlainObject} module:SVGEditor~Actions */ + var Actions = function () { /** * @typedef {PlainObject} module:SVGEditor.ToolButton @@ -30213,218 +34933,527 @@ * @property {string} [icon] The button ID * @property {boolean} isDefault For flyout holders */ + /** * * @name module:SVGEditor~ToolButtons * @type {module:SVGEditor.ToolButton[]} */ - var toolButtons = [{ sel: '#tool_select', fn: clickSelect, evt: 'click', key: ['V', true] }, { sel: '#tool_fhpath', fn: clickFHPath, evt: 'click', key: ['Q', true] }, { sel: '#tool_line', fn: clickLine, evt: 'click', key: ['L', true], parent: '#tools_line', prepend: true }, { sel: '#tool_rect', fn: clickRect, evt: 'mouseup', - key: ['R', true], parent: '#tools_rect', icon: 'rect' }, { sel: '#tool_square', fn: clickSquare, evt: 'mouseup', - parent: '#tools_rect', icon: 'square' }, { sel: '#tool_fhrect', fn: clickFHRect, evt: 'mouseup', - parent: '#tools_rect', icon: 'fh_rect' }, { sel: '#tool_ellipse', fn: clickEllipse, evt: 'mouseup', - key: ['E', true], parent: '#tools_ellipse', icon: 'ellipse' }, { sel: '#tool_circle', fn: clickCircle, evt: 'mouseup', - parent: '#tools_ellipse', icon: 'circle' }, { sel: '#tool_fhellipse', fn: clickFHEllipse, evt: 'mouseup', - parent: '#tools_ellipse', icon: 'fh_ellipse' }, { sel: '#tool_path', fn: clickPath, evt: 'click', key: ['P', true] }, { sel: '#tool_text', fn: clickText, evt: 'click', key: ['T', true] }, { sel: '#tool_image', fn: clickImage, evt: 'mouseup' }, { sel: '#tool_zoom', fn: clickZoom, evt: 'mouseup', key: ['Z', true] }, { sel: '#tool_clear', fn: clickClear, evt: 'mouseup', key: ['N', true] }, { sel: '#tool_save', fn: function fn() { + var toolButtons = [{ + sel: '#tool_select', + fn: clickSelect, + evt: 'click', + key: ['V', true] + }, { + sel: '#tool_fhpath', + fn: clickFHPath, + evt: 'click', + key: ['Q', true] + }, { + sel: '#tool_line', + fn: clickLine, + evt: 'click', + key: ['L', true], + parent: '#tools_line', + prepend: true + }, { + sel: '#tool_rect', + fn: clickRect, + evt: 'mouseup', + key: ['R', true], + parent: '#tools_rect', + icon: 'rect' + }, { + sel: '#tool_square', + fn: clickSquare, + evt: 'mouseup', + parent: '#tools_rect', + icon: 'square' + }, { + sel: '#tool_fhrect', + fn: clickFHRect, + evt: 'mouseup', + parent: '#tools_rect', + icon: 'fh_rect' + }, { + sel: '#tool_ellipse', + fn: clickEllipse, + evt: 'mouseup', + key: ['E', true], + parent: '#tools_ellipse', + icon: 'ellipse' + }, { + sel: '#tool_circle', + fn: clickCircle, + evt: 'mouseup', + parent: '#tools_ellipse', + icon: 'circle' + }, { + sel: '#tool_fhellipse', + fn: clickFHEllipse, + evt: 'mouseup', + parent: '#tools_ellipse', + icon: 'fh_ellipse' + }, { + sel: '#tool_path', + fn: clickPath, + evt: 'click', + key: ['P', true] + }, { + sel: '#tool_text', + fn: clickText, + evt: 'click', + key: ['T', true] + }, { + sel: '#tool_image', + fn: clickImage, + evt: 'mouseup' + }, { + sel: '#tool_zoom', + fn: clickZoom, + evt: 'mouseup', + key: ['Z', true] + }, { + sel: '#tool_clear', + fn: clickClear, + evt: 'mouseup', + key: ['N', true] + }, { + sel: '#tool_save', + fn: function fn() { if (editingsource) { saveSourceEditor(); } else { clickSave(); } }, - evt: 'mouseup', key: ['S', true] }, { sel: '#tool_export', fn: clickExport, evt: 'mouseup' }, { sel: '#tool_open', fn: clickOpen, evt: 'mouseup', key: ['O', true] }, { sel: '#tool_import', fn: clickImport, evt: 'mouseup' }, { sel: '#tool_source', fn: showSourceEditor, evt: 'click', key: ['U', true] }, { sel: '#tool_wireframe', fn: clickWireframe, evt: 'click', key: ['F', true] }, { sel: '#tool_source_cancel,.overlay,#tool_docprops_cancel,#tool_prefs_cancel', - fn: cancelOverlays, evt: 'click', key: ['esc', false, false], hidekey: true }, { sel: '#tool_source_save', fn: saveSourceEditor, evt: 'click' }, { sel: '#tool_docprops_save', fn: saveDocProperties, evt: 'click' }, { sel: '#tool_docprops', fn: showDocProperties, evt: 'mouseup' }, { sel: '#tool_prefs_save', fn: savePreferences, evt: 'click' }, { sel: '#tool_prefs_option', fn: function fn() { - showPreferences();return false; + evt: 'mouseup', + key: ['S', true] + }, { + sel: '#tool_export', + fn: clickExport, + evt: 'mouseup' + }, { + sel: '#tool_open', + fn: clickOpen, + evt: 'mouseup', + key: ['O', true] + }, { + sel: '#tool_import', + fn: clickImport, + evt: 'mouseup' + }, { + sel: '#tool_source', + fn: showSourceEditor, + evt: 'click', + key: ['U', true] + }, { + sel: '#tool_wireframe', + fn: clickWireframe, + evt: 'click', + key: ['F', true] + }, { + key: ['esc', false, false], + fn: function fn() { + if (dialogSelectors.every(function (sel) { + return $$b(sel + ':hidden').length; + })) { + svgCanvas.clearSelection(); + } }, - evt: 'mouseup' }, { sel: '#tool_delete,#tool_delete_multi', fn: deleteSelected, - evt: 'click', key: ['del/backspace', true] }, { sel: '#tool_reorient', fn: reorientPath, evt: 'click' }, { sel: '#tool_node_link', fn: linkControlPoints, evt: 'click' }, { sel: '#tool_node_clone', fn: clonePathNode, evt: 'click' }, { sel: '#tool_node_delete', fn: deletePathNode, evt: 'click' }, { sel: '#tool_openclose_path', fn: opencloseSubPath, evt: 'click' }, { sel: '#tool_add_subpath', fn: addSubPath, evt: 'click' }, { sel: '#tool_move_top', fn: moveToTopSelected, evt: 'click', key: 'ctrl+shift+]' }, { sel: '#tool_move_bottom', fn: moveToBottomSelected, evt: 'click', key: 'ctrl+shift+[' }, { sel: '#tool_topath', fn: convertToPath$$1, evt: 'click' }, { sel: '#tool_make_link,#tool_make_link_multi', fn: makeHyperlink, evt: 'click' }, { sel: '#tool_undo', fn: clickUndo, evt: 'click' }, { sel: '#tool_redo', fn: clickRedo, evt: 'click' }, { sel: '#tool_clone,#tool_clone_multi', fn: clickClone, evt: 'click', key: ['D', true] }, { sel: '#tool_group_elements', fn: clickGroup, evt: 'click', key: ['G', true] }, { sel: '#tool_ungroup', fn: clickGroup, evt: 'click' }, { sel: '#tool_unlink_use', fn: clickGroup, evt: 'click' }, { sel: '[id^=tool_align]', fn: clickAlign, evt: 'click' }, - // these two lines are required to make Opera work properly with the flyout mechanism + hidekey: true + }, { + sel: dialogSelectors.join(','), + fn: cancelOverlays, + evt: 'click', + key: ['esc', false, false], + hidekey: true + }, { + sel: '#tool_source_save', + fn: saveSourceEditor, + evt: 'click' + }, { + sel: '#tool_docprops_save', + fn: saveDocProperties, + evt: 'click' + }, { + sel: '#tool_docprops', + fn: showDocProperties, + evt: 'mouseup' + }, { + sel: '#tool_prefs_save', + fn: savePreferences, + evt: 'click' + }, { + sel: '#tool_prefs_option', + fn: function fn() { + showPreferences(); + return false; + }, + evt: 'mouseup' + }, { + sel: '#tool_delete,#tool_delete_multi', + fn: deleteSelected, + evt: 'click', + key: ['del/backspace', true] + }, { + sel: '#tool_reorient', + fn: reorientPath, + evt: 'click' + }, { + sel: '#tool_node_link', + fn: linkControlPoints, + evt: 'click' + }, { + sel: '#tool_node_clone', + fn: clonePathNode, + evt: 'click' + }, { + sel: '#tool_node_delete', + fn: deletePathNode, + evt: 'click' + }, { + sel: '#tool_openclose_path', + fn: opencloseSubPath, + evt: 'click' + }, { + sel: '#tool_add_subpath', + fn: addSubPath, + evt: 'click' + }, { + sel: '#tool_move_top', + fn: moveToTopSelected, + evt: 'click', + key: 'ctrl+shift+]' + }, { + sel: '#tool_move_bottom', + fn: moveToBottomSelected, + evt: 'click', + key: 'ctrl+shift+[' + }, { + sel: '#tool_topath', + fn: convertToPath, + evt: 'click' + }, { + sel: '#tool_make_link,#tool_make_link_multi', + fn: makeHyperlink, + evt: 'click' + }, { + sel: '#tool_undo', + fn: clickUndo, + evt: 'click' + }, { + sel: '#tool_redo', + fn: clickRedo, + evt: 'click' + }, { + sel: '#tool_clone,#tool_clone_multi', + fn: clickClone, + evt: 'click', + key: ['D', true] + }, { + sel: '#tool_group_elements', + fn: clickGroup, + evt: 'click', + key: ['G', true] + }, { + sel: '#tool_ungroup', + fn: clickGroup, + evt: 'click' + }, { + sel: '#tool_unlink_use', + fn: clickGroup, + evt: 'click' + }, { + sel: '[id^=tool_align]', + fn: clickAlign, + evt: 'click' + }, // these two lines are required to make Opera work properly with the flyout mechanism // {sel: '#tools_rect_show', fn: clickRect, evt: 'click'}, // {sel: '#tools_ellipse_show', fn: clickEllipse, evt: 'click'}, - { sel: '#tool_bold', fn: clickBold, evt: 'mousedown' }, { sel: '#tool_italic', fn: clickItalic, evt: 'mousedown' }, { sel: '#sidepanel_handle', fn: toggleSidePanel, key: ['X'] }, { sel: '#copy_save_done', fn: cancelOverlays, evt: 'click' }, - - // Shortcuts not associated with buttons - - { key: 'ctrl+left', fn: function fn() { + { + sel: '#tool_bold', + fn: clickBold, + evt: 'mousedown' + }, { + sel: '#tool_italic', + fn: clickItalic, + evt: 'mousedown' + }, { + sel: '#sidepanel_handle', + fn: toggleSidePanel, + key: ['X'] + }, { + sel: '#copy_save_done', + fn: cancelOverlays, + evt: 'click' + }, // Shortcuts not associated with buttons + { + key: 'ctrl+left', + fn: function fn() { rotateSelected(0, 1); } - }, { key: 'ctrl+right', fn: function fn() { + }, { + key: 'ctrl+right', + fn: function fn() { rotateSelected(1, 1); } - }, { key: 'ctrl+shift+left', fn: function fn() { + }, { + key: 'ctrl+shift+left', + fn: function fn() { rotateSelected(0, 5); } - }, { key: 'ctrl+shift+right', fn: function fn() { + }, { + key: 'ctrl+shift+right', + fn: function fn() { rotateSelected(1, 5); } - }, { key: 'shift+O', fn: selectPrev }, { key: 'shift+P', fn: selectNext }, { key: [modKey + 'up', true], fn: function fn() { + }, { + key: 'shift+O', + fn: selectPrev + }, { + key: 'shift+P', + fn: selectNext + }, { + key: [modKey + 'up', true], + fn: function fn() { zoomImage(2); } - }, { key: [modKey + 'down', true], fn: function fn() { + }, { + key: [modKey + 'down', true], + fn: function fn() { zoomImage(0.5); } - }, { key: [modKey + ']', true], fn: function fn() { + }, { + key: [modKey + ']', true], + fn: function fn() { moveUpDownSelected('Up'); } - }, { key: [modKey + '[', true], fn: function fn() { + }, { + key: [modKey + '[', true], + fn: function fn() { moveUpDownSelected('Down'); } - }, { key: ['up', true], fn: function fn() { + }, { + key: ['up', true], + fn: function fn() { moveSelected(0, -1); } - }, { key: ['down', true], fn: function fn() { + }, { + key: ['down', true], + fn: function fn() { moveSelected(0, 1); } - }, { key: ['left', true], fn: function fn() { + }, { + key: ['left', true], + fn: function fn() { moveSelected(-1, 0); } - }, { key: ['right', true], fn: function fn() { + }, { + key: ['right', true], + fn: function fn() { moveSelected(1, 0); } - }, { key: 'shift+up', fn: function fn() { + }, { + key: 'shift+up', + fn: function fn() { moveSelected(0, -10); } - }, { key: 'shift+down', fn: function fn() { + }, { + key: 'shift+down', + fn: function fn() { moveSelected(0, 10); } - }, { key: 'shift+left', fn: function fn() { + }, { + key: 'shift+left', + fn: function fn() { moveSelected(-10, 0); } - }, { key: 'shift+right', fn: function fn() { + }, { + key: 'shift+right', + fn: function fn() { moveSelected(10, 0); } - }, { key: ['alt+up', true], fn: function fn() { + }, { + key: ['alt+up', true], + fn: function fn() { svgCanvas.cloneSelectedElements(0, -1); } - }, { key: ['alt+down', true], fn: function fn() { + }, { + key: ['alt+down', true], + fn: function fn() { svgCanvas.cloneSelectedElements(0, 1); } - }, { key: ['alt+left', true], fn: function fn() { + }, { + key: ['alt+left', true], + fn: function fn() { svgCanvas.cloneSelectedElements(-1, 0); } - }, { key: ['alt+right', true], fn: function fn() { + }, { + key: ['alt+right', true], + fn: function fn() { svgCanvas.cloneSelectedElements(1, 0); } - }, { key: ['alt+shift+up', true], fn: function fn() { + }, { + key: ['alt+shift+up', true], + fn: function fn() { svgCanvas.cloneSelectedElements(0, -10); } - }, { key: ['alt+shift+down', true], fn: function fn() { + }, { + key: ['alt+shift+down', true], + fn: function fn() { svgCanvas.cloneSelectedElements(0, 10); } - }, { key: ['alt+shift+left', true], fn: function fn() { + }, { + key: ['alt+shift+left', true], + fn: function fn() { svgCanvas.cloneSelectedElements(-10, 0); } - }, { key: ['alt+shift+right', true], fn: function fn() { + }, { + key: ['alt+shift+right', true], + fn: function fn() { svgCanvas.cloneSelectedElements(10, 0); } - }, { key: 'A', fn: function fn() { + }, { + key: 'a', + fn: function fn() { svgCanvas.selectAllInCurrentLayer(); } - }, + }, { + key: modKey + 'a', + fn: function fn() { + svgCanvas.selectAllInCurrentLayer(); + } + }, // Standard shortcuts + { + key: modKey + 'z', + fn: clickUndo + }, { + key: modKey + 'shift+z', + fn: clickRedo + }, { + key: modKey + 'y', + fn: clickRedo + }, { + key: modKey + 'x', + fn: cutSelected + }, { + key: modKey + 'c', + fn: copySelected + }, { + key: modKey + 'v', + fn: pasteInCenter + }]; // Tooltips not directly associated with a single function - // Standard shortcuts - { key: modKey + 'z', fn: clickUndo }, { key: modKey + 'shift+z', fn: clickRedo }, { key: modKey + 'y', fn: clickRedo }, { key: modKey + 'x', fn: cutSelected }, { key: modKey + 'c', fn: copySelected }, { key: modKey + 'v', fn: pasteInCenter }]; - - // Tooltips not directly associated with a single function var keyAssocs = { '4/Shift+4': '#tools_rect_show', '5/Shift+5': '#tools_ellipse_show' }; - return { /** @lends module:SVGEditor~Actions */ + /** * @returns {undefined} */ setAll: function setAll() { var flyouts = {}; - $$b.each(toolButtons, function (i, opts) { // Bind function to button - var btn = void 0; + var btn; + if (opts.sel) { btn = $$b(opts.sel); + if (!btn.length) { return true; } // Skip if markup does not exist + + if (opts.evt) { + // `touch.js` changes `touchstart` to `mousedown`, + // so we must map tool button click events as well if (isTouch() && opts.evt === 'click') { opts.evt = 'mousedown'; } - btn[opts.evt](opts.fn); - } - // Add to parent flyout menu, if able to be displayed + btn[opts.evt](opts.fn); + } // Add to parent flyout menu, if able to be displayed + + if (opts.parent && $$b(opts.parent + '_show').length) { var fH = $$b(opts.parent); + if (!fH.length) { fH = makeFlyoutHolder(opts.parent.substr(1)); } + if (opts.prepend) { btn[0].style.margin = 'initial'; } + fH[opts.prepend ? 'prepend' : 'append'](btn); if (!Array.isArray(flyouts[opts.parent])) { flyouts[opts.parent] = []; } + flyouts[opts.parent].push(opts); } - } + } // Bind function to shortcut key + - // Bind function to shortcut key if (opts.key) { // Set shortcut based on options - var keyval = void 0, - - // disInInp = true, + var keyval, + // disInInp = true, pd = false; + if (Array.isArray(opts.key)) { keyval = opts.key[0]; + if (opts.key.length > 1) { pd = opts.key[1]; - } - // if (opts.key.length > 2) { disInInp = opts.key[2]; } + } // if (opts.key.length > 2) { disInInp = opts.key[2]; } + } else { keyval = opts.key; } - keyval += ''; + keyval = String(keyval); var fn = opts.fn; - - $$b.each(keyval.split('/'), function (i, key) { + $$b.each(keyval.split('/'), function (j, key) { $$b(document).bind('keydown', key, function (e) { fn(); + if (pd) { e.preventDefault(); - } - // Prevent default on ALL keys? + } // Prevent default on ALL keys? + + return false; }); - }); + }); // Put shortcut in title - // Put shortcut in title if (opts.sel && !opts.hidekey && btn.attr('title')) { var newTitle = btn.attr('title').split('[')[0] + ' (' + keyval + ')'; - keyAssocs[keyval] = opts.sel; - // Disregard for menu items + keyAssocs[keyval] = opts.sel; // Disregard for menu items + if (!btn.parents('#main_menu').length) { btn.attr('title', newTitle); } } } - }); - // Setup flyouts - setupFlyouts(flyouts); - - // Misc additional actions + return true; + }); // Setup flyouts + setupFlyouts(flyouts); // Misc additional actions // Make 'return' keypress trigger the change event + $$b('.attr_changer, #image_url').bind('keydown', 'return', function (evt) { $$b(this).change(); evt.preventDefault(); }); - $$b(window).bind('keydown', 'tab', function (e) { if (uiContext === 'canvas') { e.preventDefault(); @@ -30436,7 +35465,6 @@ selectPrev(); } }); - $$b('#tool_zoom').dblclick(dblclickZoom); }, @@ -30446,25 +35474,29 @@ setTitles: function setTitles() { $$b.each(keyAssocs, function (keyval, sel) { var menu = $$b(sel).parents('#main_menu').length; - $$b(sel).each(function () { - var t = void 0; + var t; + if (menu) { t = $$b(this).text().split(' [')[0]; } else { t = this.title.split(' [')[0]; } - var keyStr = ''; - // Shift+Up + + var keyStr = ''; // Shift+Up + $$b.each(keyval.split('/'), function (i, key) { var modBits = key.split('+'); var mod = ''; + if (modBits.length > 1) { mod = modBits[0] + '+'; key = modBits[1]; } + keyStr += (i ? '/' : '') + mod + (uiStrings$1['key_' + key] || key); }); + if (menu) { this.lastChild.textContent = t + ' [' + keyStr + ']'; } else { @@ -30484,15 +35516,16 @@ }); } }; - }(); + }(); // Select given tool + - // Select given tool editor.ready(function () { - var tool = void 0; + var tool; var itool = curConfig.initTool, container = $$b('#tools_left, #svg_editor .tools_flyout'), preTool = container.find('#tool_' + itool), regTool = container.find('#' + itool); + if (preTool.length) { tool = preTool; } else if (regTool.length) { @@ -30500,6 +35533,7 @@ } else { tool = $$b('#tool_select'); } + tool.click().mouseup(); if (curConfig.wireframe) { @@ -30510,7 +35544,7 @@ toggleSidePanel(); } - $$b('#rulers').toggle(!!curConfig.showRulers); + $$b('#rulers').toggle(Boolean(curConfig.showRulers)); if (curConfig.showRulers) { $$b('#show_rulers')[0].checked = true; @@ -30531,19 +35565,57 @@ if (curConfig.gridColor) { $$b('#grid_color').val(curConfig.gridColor); } + }); // init SpinButtons + + $$b('#rect_rx').SpinButton({ + min: 0, + max: 1000, + stateObj: stateObj, + callback: changeRectRadius }); + $$b('#stroke_width').SpinButton({ + min: 0, + max: 99, + smallStep: 0.1, + stateObj: stateObj, + callback: changeStrokeWidth + }); + $$b('#angle').SpinButton({ + min: -180, + max: 180, + step: 5, + stateObj: stateObj, + callback: changeRotationAngle + }); + $$b('#font_size').SpinButton({ + min: 0.001, + stepfunc: stepFontSize, + stateObj: stateObj, + callback: changeFontSize + }); + $$b('#group_opacity').SpinButton({ + min: 0, + max: 100, + step: 5, + stateObj: stateObj, + callback: changeOpacity + }); + $$b('#blur').SpinButton({ + min: 0, + max: 10, + step: 0.1, + stateObj: stateObj, + callback: changeBlur + }); + $$b('#zoom').SpinButton({ + min: 0.001, + max: 10000, + step: 50, + stepfunc: stepZoom, + stateObj: stateObj, + callback: changeZoom // Set default zoom - // init SpinButtons - $$b('#rect_rx').SpinButton({ min: 0, max: 1000, stateObj: stateObj, callback: changeRectRadius }); - $$b('#stroke_width').SpinButton({ min: 0, max: 99, smallStep: 0.1, stateObj: stateObj, callback: changeStrokeWidth }); - $$b('#angle').SpinButton({ min: -180, max: 180, step: 5, stateObj: stateObj, callback: changeRotationAngle }); - $$b('#font_size').SpinButton({ min: 0.001, stepfunc: stepFontSize, stateObj: stateObj, callback: changeFontSize }); - $$b('#group_opacity').SpinButton({ min: 0, max: 100, step: 5, stateObj: stateObj, callback: changeOpacity }); - $$b('#blur').SpinButton({ min: 0, max: 10, step: 0.1, stateObj: stateObj, callback: changeBlur }); - $$b('#zoom').SpinButton({ min: 0.001, max: 10000, step: 50, stepfunc: stepZoom, stateObj: stateObj, callback: changeZoom }) - // Set default zoom - .val(svgCanvas.getZoom() * 100); - + }).val(svgCanvas.getZoom() * 100); $$b('#workarea').contextMenu({ menu: 'cmenu_canvas', inSpeed: 0 @@ -30552,56 +35624,79 @@ case 'delete': deleteSelected(); break; + case 'cut': cutSelected(); break; + case 'copy': copySelected(); break; + case 'paste': svgCanvas.pasteElements(); break; + case 'paste_in_place': svgCanvas.pasteElements('in_place'); break; + case 'group': case 'group_elements': svgCanvas.groupSelectedElements(); break; + case 'ungroup': svgCanvas.ungroupSelectedElement(); break; + case 'move_front': moveToTopSelected(); break; + case 'move_up': moveUpDownSelected('Up'); break; + case 'move_down': moveUpDownSelected('Down'); break; + case 'move_back': moveToBottomSelected(); break; + default: if (hasCustomHandler(action)) { getCustomHandler(action).call(); } + break; } }); + /** + * Implements {@see module:jQueryContextMenu.jQueryContextMenuListener} + * @param {"dupe"|"delete"|"merge_down"|"merge_all"} action + * @param {external:jQuery} el + * @param {{x: Float, y: Float, docX: Float, docY: Float}} pos + * @returns {undefined} + */ var lmenuFunc = function lmenuFunc(action, el, pos) { switch (action) { case 'dupe': + /* await */ cloneLayer(); break; + case 'delete': deleteLayer(); break; + case 'merge_down': mergeLayer(); break; + case 'merge_all': svgCanvas.mergeAllLayers(); updateContextPanel(); @@ -30614,29 +35709,31 @@ menu: 'cmenu_layers', inSpeed: 0 }, lmenuFunc); - $$b('#layer_moreopts').contextMenu({ menu: 'cmenu_layers', inSpeed: 0, allowLeft: true }, lmenuFunc); - $$b('.contextMenu li').mousedown(function (ev) { ev.preventDefault(); }); - $$b('#cmenu_canvas li').disableContextMenu(); canvMenu.enableContextMenuItems('#delete,#cut,#copy'); + /** + * @returns {undefined} + */ function enableOrDisableClipboard() { - var svgeditClipboard = void 0; + var svgeditClipboard; + try { svgeditClipboard = localStorage.getItem('svgedit_clipboard'); } catch (err) {} + canvMenu[(svgeditClipboard ? 'en' : 'dis') + 'ableContextMenuItems']('#paste,#paste_in_place'); } - enableOrDisableClipboard(); + enableOrDisableClipboard(); window.addEventListener('storage', function (e) { if (e.key !== 'svgedit_clipboard') { return; @@ -30644,69 +35741,89 @@ enableOrDisableClipboard(); }); - window.addEventListener('beforeunload', function (e) { // Suppress warning if page is empty if (undoMgr.getUndoStackSize() === 0) { editor.showSaveWarning = false; - } + } // showSaveWarning is set to 'false' when the page is saved. + - // showSaveWarning is set to 'false' when the page is saved. if (!curConfig.no_save_warning && editor.showSaveWarning) { // Browser already asks question about closing the page e.returnValue = uiStrings$1.notification.unsavedChanges; // Firefox needs this when beforeunload set by addEventListener (even though message is not used) + return uiStrings$1.notification.unsavedChanges; } - }, false); + return true; + }); /** - * Expose the uiStrings + * Expose the `uiStrings`. * @function module:SVGEditor.canvas.getUIStrings * @returns {module:SVGEditor.uiStrings} */ + editor.canvas.getUIStrings = function () { return uiStrings$1; }; + /** + * @returns {Promise} Resolves to boolean indicating `true` if there were no changes + * and `false` after the user confirms. + */ - /** - * @callback module:SVGEditor.OpenPrepCallback - * @param {boolean} noChanges - * @returns {undefined} - */ - /** - * @param {module:SVGEditor.OpenPrepCallback} func Confirmation dialog callback - * @returns {undefined} - */ - editor.openPrep = function (func) { + + editor.openPrep = function () { $$b('#main_menu').hide(); + if (undoMgr.getUndoStackSize() === 0) { - func(true); - } else { - $$b.confirm(uiStrings$1.notification.QwantToOpen, func); + return true; } + + return $$b.confirm(uiStrings$1.notification.QwantToOpen); }; + /** + * + * @param {Event} e + * @returns {undefined} + */ + function onDragEnter(e) { e.stopPropagation(); - e.preventDefault(); - // and indicator should be displayed here, such as "drop files here" + e.preventDefault(); // and indicator should be displayed here, such as "drop files here" } + /** + * + * @param {Event} e + * @returns {undefined} + */ + function onDragOver(e) { e.stopPropagation(); e.preventDefault(); } + /** + * + * @param {Event} e + * @returns {undefined} + */ + function onDragLeave(e) { e.stopPropagation(); - e.preventDefault(); - // hypothetical indicator should be removed here - } - // Use HTML5 File API: http://www.w3.org/TR/FileAPI/ + e.preventDefault(); // hypothetical indicator should be removed here + } // Use HTML5 File API: http://www.w3.org/TR/FileAPI/ // if browser has HTML5 File API support, then we will show the open menu item // and provide a file input to click. When that change event fires, it will // get the text contents of the file and send it to the canvas + + if (window.FileReader) { + /** + * @param {Event} e + * @returns {undefined} + */ var importImage = function importImage(e) { $$b.process_cancel(uiStrings$1.notification.loadingImage); e.stopPropagation(); @@ -30714,6 +35831,7 @@ $$b('#workarea').removeAttr('style'); $$b('#main_menu').hide(); var file = e.type === 'drop' ? e.dataTransfer.files[0] : this.files[0]; + if (!file) { $$b('#dialog_box').hide(); return; @@ -30721,178 +35839,293 @@ /* if (file.type === 'application/pdf') { // Todo: Handle PDF imports } else */ - if (file.type.includes('image')) { - // Detected an image - // svg handling - var reader = void 0; - if (file.type.includes('svg')) { - reader = new FileReader(); - reader.onloadend = function (e) { - var newElement = svgCanvas.importSvgString(e.target.result, true); - svgCanvas.ungroupSelectedElement(); - svgCanvas.ungroupSelectedElement(); - svgCanvas.groupSelectedElements(); + + + if (!file.type.includes('image')) { + return; + } // Detected an image + // svg handling + + + var reader; + + if (file.type.includes('svg')) { + reader = new FileReader(); + + reader.onloadend = function (ev) { + var newElement = svgCanvas.importSvgString(ev.target.result, true); + svgCanvas.ungroupSelectedElement(); + svgCanvas.ungroupSelectedElement(); + svgCanvas.groupSelectedElements(); + svgCanvas.alignSelectedElements('m', 'page'); + svgCanvas.alignSelectedElements('c', 'page'); // highlight imported element, otherwise we get strange empty selectbox + + svgCanvas.selectOnly([newElement]); + $$b('#dialog_box').hide(); + }; + + reader.readAsText(file); + } else { + // bitmap handling + reader = new FileReader(); + + reader.onloadend = function (_ref27) { + var result = _ref27.target.result; + + /** + * Insert the new image until we know its dimensions + * @param {Float} width + * @param {Float} height + * @returns {undefined} + */ + var insertNewImage = function insertNewImage(width, height) { + var newImage = svgCanvas.addSVGElementFromJson({ + element: 'image', + attr: { + x: 0, + y: 0, + width: width, + height: height, + id: svgCanvas.getNextId(), + style: 'pointer-events:inherit' + } + }); + svgCanvas.setHref(newImage, result); + svgCanvas.selectOnly([newImage]); svgCanvas.alignSelectedElements('m', 'page'); svgCanvas.alignSelectedElements('c', 'page'); - // highlight imported element, otherwise we get strange empty selectbox - svgCanvas.selectOnly([newElement]); + updateContextPanel(); $$b('#dialog_box').hide(); - }; - reader.readAsText(file); - } else { - // bitmap handling - reader = new FileReader(); - reader.onloadend = function (_ref16) { - var result = _ref16.target.result; + }; // create dummy img so we know the default dimensions - // let's insert the new image until we know its dimensions - var insertNewImage = function insertNewImage(width, height) { - var newImage = svgCanvas.addSVGElementFromJson({ - element: 'image', - attr: { - x: 0, - y: 0, - width: width, - height: height, - id: svgCanvas.getNextId(), - style: 'pointer-events:inherit' - } - }); - svgCanvas.setHref(newImage, result); - svgCanvas.selectOnly([newImage]); - svgCanvas.alignSelectedElements('m', 'page'); - svgCanvas.alignSelectedElements('c', 'page'); - updateContextPanel(); - $$b('#dialog_box').hide(); - }; - // create dummy img so we know the default dimensions - var imgWidth = 100; - var imgHeight = 100; - var img = new Image(); - img.style.opacity = 0; - img.onload = function () { - imgWidth = img.offsetWidth || img.naturalWidth || img.width; - imgHeight = img.offsetHeight || img.naturalHeight || img.height; - insertNewImage(imgWidth, imgHeight); - }; - img.src = result; - }; - reader.readAsDataURL(file); - } + + var imgWidth = 100; + var imgHeight = 100; + var img = new Image(); + img.style.opacity = 0; + img.addEventListener('load', function () { + imgWidth = img.offsetWidth || img.naturalWidth || img.width; + imgHeight = img.offsetHeight || img.naturalHeight || img.height; + insertNewImage(imgWidth, imgHeight); + }); + img.src = result; + }; + + reader.readAsDataURL(file); } }; - workarea[0].addEventListener('dragenter', onDragEnter, false); - workarea[0].addEventListener('dragover', onDragOver, false); - workarea[0].addEventListener('dragleave', onDragLeave, false); - workarea[0].addEventListener('drop', importImage, false); + workarea[0].addEventListener('dragenter', onDragEnter); + workarea[0].addEventListener('dragover', onDragOver); + workarea[0].addEventListener('dragleave', onDragLeave); + workarea[0].addEventListener('drop', importImage); + var open = $$b('').click( + /*#__PURE__*/ + _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee16() { + var ok, reader; + return regeneratorRuntime.wrap(function _callee16$(_context16) { + while (1) { + switch (_context16.prev = _context16.next) { + case 0: + _context16.next = 2; + return editor.openPrep(); - var open = $$b('').change(function () { - var f = this; - editor.openPrep(function (ok) { - if (!ok) { - return; + case 2: + ok = _context16.sent; + + if (ok) { + _context16.next = 5; + break; + } + + return _context16.abrupt("return"); + + case 5: + svgCanvas.clear(); + + if (this.files.length === 1) { + $$b.process_cancel(uiStrings$1.notification.loadingImage); + reader = new FileReader(); + + reader.onloadend = + /*#__PURE__*/ + function () { + var _ref29 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee15(e) { + return regeneratorRuntime.wrap(function _callee15$(_context15) { + while (1) { + switch (_context15.prev = _context15.next) { + case 0: + _context15.next = 2; + return loadSvgString(e.target.result); + + case 2: + updateCanvas(); + + case 3: + case "end": + return _context15.stop(); + } + } + }, _callee15, this); + })); + + return function (_x6) { + return _ref29.apply(this, arguments); + }; + }(); + + reader.readAsText(this.files[0]); + } + + case 7: + case "end": + return _context16.stop(); + } } - svgCanvas.clear(); - if (f.files.length === 1) { - $$b.process_cancel(uiStrings$1.notification.loadingImage); - var reader = new FileReader(); - reader.onloadend = function (e) { - loadSvgString(e.target.result); - updateCanvas(); - }; - reader.readAsText(f.files[0]); - } - }); - }); + }, _callee16, this); + }))); $$b('#tool_open').show().prepend(open); - var imgImport = $$b('').change(importImage); $$b('#tool_import').show().prepend(imgImport); } - // $(function () { - updateCanvas(true); - // }); - - // const revnums = 'svg-editor.js ($Rev$) '; + updateCanvas(true); // const revnums = 'svg-editor.js ($Rev$) '; // revnums += svgCanvas.getVersion(); // $('#copyright')[0].setAttribute('title', revnums); + var loadedExtensionNames = []; /** * @function module:SVGEditor.setLang * @param {string} lang The language code * @param {module:locale.LocaleStrings} allStrings See {@tutorial LocaleDocs} * @fires module:svgcanvas.SvgCanvas#event:ext-langReady * @fires module:svgcanvas.SvgCanvas#event:ext-langChanged - * @returns {undefined} + * @returns {Promise} A Promise which resolves to `undefined` */ - var setLang = editor.setLang = function (lang, allStrings) { - editor.langChanged = true; - $$b.pref('lang', lang); - $$b('#lang_select').val(lang); - if (!allStrings) { - return; - } - $$b.extend(uiStrings$1, allStrings); - // const notif = allStrings.notification; // Currently unused - // $.extend will only replace the given strings - var oldLayerName = $$b('#layerlist tr.layersel td.layername').text(); - var renameLayer = oldLayerName === uiStrings$1.common.layer + ' 1'; + var setLang = editor.setLang = + /*#__PURE__*/ + function () { + var _ref30 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee17(lang, allStrings) { + var _this = this; - svgCanvas.setUiStrings(allStrings); - Actions.setTitles(); + var oldLayerName, renameLayer, elems; + return regeneratorRuntime.wrap(function _callee17$(_context17) { + while (1) { + switch (_context17.prev = _context17.next) { + case 0: + editor.langChanged = true; + $$b.pref('lang', lang); + $$b('#lang_select').val(lang); - if (renameLayer) { - svgCanvas.renameCurrentLayer(uiStrings$1.common.layer + ' 1'); - populateLayers(); - } + if (allStrings) { + _context17.next = 5; + break; + } - // In case extensions loaded before the locale, now we execute a callback on them - if (extsPreLang.length) { - while (extsPreLang.length) { - var ext = extsPreLang.shift(); - ext.langReady({ - lang: lang, - uiStrings: uiStrings$1, - importLocale: getImportLocale({ defaultLang: lang, defaultName: ext.name }) - }); - } - } else { - svgCanvas.runExtensions('langReady', /** @type {module:svgcanvas.SvgCanvas#event:ext-langReady} */{ lang: lang, uiStrings: uiStrings$1 }); - } - svgCanvas.runExtensions('langChanged', /** @type {module:svgcanvas.SvgCanvas#event:ext-langChanged} */lang); + return _context17.abrupt("return"); - // Update flyout tooltips - setFlyoutTitles(); + case 5: + $$b.extend(uiStrings$1, allStrings); // const notif = allStrings.notification; // Currently unused + // $.extend will only replace the given strings - // Copy title for certain tool elements - var elems = { - '#stroke_color': '#tool_stroke .icon_label, #tool_stroke .color_block', - '#fill_color': '#tool_fill label, #tool_fill .color_block', - '#linejoin_miter': '#cur_linejoin', - '#linecap_butt': '#cur_linecap' + oldLayerName = $$b('#layerlist tr.layersel td.layername').text(); + renameLayer = oldLayerName === uiStrings$1.common.layer + ' 1'; + svgCanvas.setUiStrings(allStrings); + Actions.setTitles(); + + if (renameLayer) { + svgCanvas.renameCurrentLayer(uiStrings$1.common.layer + ' 1'); + populateLayers(); + } // In case extensions loaded before the locale, now we execute a callback on them + + + if (!extsPreLang.length) { + _context17.next = 17; + break; + } + + _context17.next = 14; + return Promise.all(extsPreLang.map(function (ext) { + loadedExtensionNames.push(ext.name); + return ext.langReady({ + lang: lang, + uiStrings: uiStrings$1, + importLocale: getImportLocale({ + defaultLang: lang, + defaultName: ext.name + }) + }); + })); + + case 14: + extsPreLang.length = 0; + _context17.next = 18; + break; + + case 17: + loadedExtensionNames.forEach(function (loadedExtensionName) { + _this.runExtension(loadedExtensionName, 'langReady', + /** @type {module:svgcanvas.SvgCanvas#event:ext-langReady} */ + { + lang: lang, + uiStrings: uiStrings$1, + importLocale: getImportLocale({ + defaultLang: lang, + defaultName: loadedExtensionName + }) + }); + }); + + case 18: + svgCanvas.runExtensions('langChanged', + /** @type {module:svgcanvas.SvgCanvas#event:ext-langChanged} */ + lang); // Update flyout tooltips + + setFlyoutTitles(); // Copy title for certain tool elements + + elems = { + '#stroke_color': '#tool_stroke .icon_label, #tool_stroke .color_block', + '#fill_color': '#tool_fill label, #tool_fill .color_block', + '#linejoin_miter': '#cur_linejoin', + '#linecap_butt': '#cur_linecap' + }; + $$b.each(elems, function (source, dest) { + $$b(dest).attr('title', $$b(source)[0].title); + }); // Copy alignment titles + + $$b('#multiselected_panel div[id^=tool_align]').each(function () { + $$b('#tool_pos' + this.id.substr(10))[0].title = this.title; + }); + + case 23: + case "end": + return _context17.stop(); + } + } + }, _callee17, this); + })); + + return function (_x7, _x8) { + return _ref30.apply(this, arguments); }; + }(); - $$b.each(elems, function (source, dest) { - $$b(dest).attr('title', $$b(source)[0].title); - }); - - // Copy alignment titles - $$b('#multiselected_panel div[id^=tool_align]').each(function () { - $$b('#tool_pos' + this.id.substr(10))[0].title = this.title; - }); - }; init$7( /** * @implements {module:locale.LocaleEditorInit} */ { /** - * Gets an array of results from extensions with a `addLangData` method + * Gets an array of results from extensions with a `addLangData` method, * returning an object with a `data` property set to its locales (to be - * merged with regular locales) + * merged with regular locales). * @param {string} langParam * @fires module:svgcanvas.SvgCanvas#event:ext-addLangData * @todo Can we forego this in favor of `langReady` (or forego `langReady`)? @@ -30903,189 +36136,313 @@ /** * @function * @type {module:svgcanvas.ExtensionVarBuilder} - * @param {string} defaultLang - * @param {string} defaultName + * @param {string} name * @returns {module:svgcanvas.SvgCanvas#event:ext-addLangData} */ function (name) { // We pass in a function as we don't know the extension name here when defining this `addLangData` method return { lang: langParam, - importLocale: getImportLocale({ defaultLang: langParam, defaultName: name }) + importLocale: getImportLocale({ + defaultLang: langParam, + defaultName: name + }) }; }, true); }, - curConfig: curConfig - }); - // Load extensions + }); // Load extensions // Bit of a hack to run extensions in local Opera/IE9 + if (document.location.protocol === 'file:') { setTimeout(extAndLocaleFunc, 100); } else { - // Returns a promise (if we wanted to fire 'extensions-loaded' event, potentially useful to hide interface as some extension locales are only available after this) + // Returns a promise (if we wanted to fire 'extensions-loaded' event, + // potentially useful to hide interface as some extension locales + // are only available after this) extAndLocaleFunc(); } }; - /** * @callback module:SVGEditor.ReadyCallback - * @returns {undefined} + * @returns {Promise|undefined} */ + /** * Queues a callback to be invoked when the editor is ready (or * to be invoked immediately if it is already ready--i.e., - * if `svgEditor.runCallbacks` has been run) + * if `runCallbacks` has been run). * @param {module:SVGEditor.ReadyCallback} cb Callback to be queued to invoke - * @returns {undefined} + * @returns {Promise} Resolves when all callbacks, including the supplied have resolved */ - editor.ready = function (cb) { - if (!isReady) { - callbacks.push(cb); - } else { - cb(); - } - }; + + editor.ready = function (cb) { + // eslint-disable-line promise/prefer-await-to-callbacks + return new Promise(function (resolve, reject) { + // eslint-disable-line promise/avoid-new + if (isReady) { + resolve(cb()); // eslint-disable-line callback-return, promise/prefer-await-to-callbacks + + return; + } + + callbacks.push([cb, resolve, reject]); + }); + }; /** * Invokes the callbacks previous set by `svgEditor.ready` - * @returns {undefined} + * @returns {Promise} Resolves to `undefined` if all callbacks succeeded and rejects otherwise */ - editor.runCallbacks = function () { - callbacks.forEach(function (cb) { - cb(); - }); - isReady = true; - }; + + editor.runCallbacks = + /*#__PURE__*/ + _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee20() { + return regeneratorRuntime.wrap(function _callee20$(_context20) { + while (1) { + switch (_context20.prev = _context20.next) { + case 0: + _context20.prev = 0; + _context20.next = 3; + return Promise.all(callbacks.map(function (_ref33) { + var _ref34 = _slicedToArray(_ref33, 1), + cb = _ref34[0]; + + return cb(); // eslint-disable-line promise/prefer-await-to-callbacks + })); + + case 3: + _context20.next = 9; + break; + + case 5: + _context20.prev = 5; + _context20.t0 = _context20["catch"](0); + callbacks.forEach(function (_ref35) { + var _ref36 = _slicedToArray(_ref35, 3), + reject = _ref36[2]; + + reject(); + }); + throw _context20.t0; + + case 9: + callbacks.forEach(function (_ref37) { + var _ref38 = _slicedToArray(_ref37, 2), + resolve = _ref38[1]; + + resolve(); + }); + isReady = true; + + case 11: + case "end": + return _context20.stop(); + } + } + }, _callee20, this, [[0, 5]]); + })); /** * @param {string} str The SVG string to load - * @returns {undefined} + * @param {PlainObject} [opts={}] + * @param {boolean} [opts.noAlert=false] Option to avoid alert to user and instead get rejected promise + * @returns {Promise} */ - editor.loadFromString = function (str) { - editor.ready(function () { - loadSvgString(str); - }); - }; + editor.loadFromString = function (str) { + var _ref39 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + noAlert = _ref39.noAlert; + + editor.ready( + /*#__PURE__*/ + _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee21() { + return regeneratorRuntime.wrap(function _callee21$(_context21) { + while (1) { + switch (_context21.prev = _context21.next) { + case 0: + _context21.prev = 0; + _context21.next = 3; + return loadSvgString(str, { + noAlert: noAlert + }); + + case 3: + _context21.next = 9; + break; + + case 5: + _context21.prev = 5; + _context21.t0 = _context21["catch"](0); + + if (!noAlert) { + _context21.next = 9; + break; + } + + throw _context21.t0; + + case 9: + case "end": + return _context21.stop(); + } + } + }, _callee21, this, [[0, 5]]); + }))); + }; /** - * Not presently in use + * Not presently in use. * @param {PlainObject} featList * @returns {undefined} */ - editor.disableUI = function (featList) { - // $(function () { + + + editor.disableUI = function (featList) {// $(function () { // $('#tool_wireframe, #tool_image, #main_button, #tool_source, #sidepanels').remove(); // $('#tools_top').css('left', 5); // }); }; - /** * @callback module:SVGEditor.URLLoadCallback * @param {boolean} success * @returns {undefined} */ + /** * @param {string} url URL from which to load an SVG string via Ajax - * @param {PlainObject} [opts] May contain properties: `cache`, `callback` - * @param {boolean} opts.cache - * @param {module:SVGEditor.URLLoadCallback} opts.callback Invoked with `true` or `false` depending on success - * @returns {undefined} + * @param {PlainObject} [opts={}] May contain properties: `cache`, `callback` + * @param {boolean} [opts.cache] + * @param {boolean} [opts.noAlert] + * @returns {Promise} Resolves to `undefined` or rejects upon bad loading of + * the SVG (or upon failure to parse the loaded string) when `noAlert` is + * enabled */ - editor.loadFromURL = function (url, opts) { - if (!opts) { - opts = {}; - } - - var _opts = opts, - cache = _opts.cache, - cb = _opts.callback; - editor.ready(function () { - $$b.ajax({ - url: url, - dataType: 'text', - cache: !!cache, - beforeSend: function beforeSend() { - $$b.process_cancel(uiStrings$1.notification.loadingImage); - }, - success: function success(str) { - loadSvgString(str, cb); - }, - error: function error(xhr, stat, err) { - if (xhr.status !== 404 && xhr.responseText) { - loadSvgString(xhr.responseText, cb); - } else { - $$b.alert(uiStrings$1.notification.URLloadFail + ': \n' + err, cb); + editor.loadFromURL = function (url) { + var _ref41 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + cache = _ref41.cache, + noAlert = _ref41.noAlert; + + return editor.ready(function () { + return new Promise(function (resolve, reject) { + // eslint-disable-line promise/avoid-new + $$b.ajax({ + url: url, + dataType: 'text', + cache: Boolean(cache), + beforeSend: function beforeSend() { + $$b.process_cancel(uiStrings$1.notification.loadingImage); + }, + success: function success(str) { + resolve(loadSvgString(str, { + noAlert: noAlert + })); + }, + error: function error(xhr, stat, err) { + if (xhr.status !== 404 && xhr.responseText) { + resolve(loadSvgString(xhr.responseText, { + noAlert: noAlert + })); + return; + } + + if (noAlert) { + reject(new Error('URLLoadFail')); + return; + } + + $$b.alert(uiStrings$1.notification.URLLoadFail + ': \n' + err); + resolve(); + }, + complete: function complete() { + $$b('#dialog_box').hide(); } - }, - complete: function complete() { - $$b('#dialog_box').hide(); - } + }); }); }); }; - /** * @param {string} str The Data URI to base64-decode (if relevant) and load - * @returns {undefined} + * @param {PlainObject} [opts={}] + * @param {boolean} [opts.noAlert] + * @returns {Promise} Resolves to `undefined` and rejects if loading SVG string fails and `noAlert` is enabled */ + + editor.loadFromDataURI = function (str) { + var _ref42 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + noAlert = _ref42.noAlert; + editor.ready(function () { var base64 = false; var pre = str.match(/^data:image\/svg\+xml;base64,/); + if (pre) { base64 = true; } else { - pre = str.match(/^data:image\/svg\+xml(?:;(?:utf8)?)?,/); + pre = str.match(/^data:image\/svg\+xml(?:;|;utf8)?,/); } + if (pre) { pre = pre[0]; } + var src = str.slice(pre.length); - loadSvgString(base64 ? decode64(src) : decodeURIComponent(src)); + return loadSvgString(base64 ? decode64(src) : decodeURIComponent(src), { + noAlert: noAlert + }); }); }; - /** * @param {string} name Used internally; no need for i18n. * @param {module:svgcanvas.ExtensionInitCallback} init Config to be invoked on this module - * @param {module:SVGEditor~ImportLocale} importLocale Importer defaulting to pth with current extension name and locale + * @param {module:svgcanvas.ExtensionInitArgs} initArgs * @throws {Error} If called too early * @returns {Promise} Resolves to `undefined` */ - editor.addExtension = function (name, init$$1, importLocale) { + + + editor.addExtension = function (name, init, initArgs) { // Note that we don't want this on editor.ready since some extensions // may want to run before then (like server_opensave). // $(function () { if (!svgCanvas) { throw new Error('Extension added too early'); } - return svgCanvas.addExtension.call(this, name, init$$1, importLocale); - // }); - }; - // Defer injection to wait out initial menu processing. This probably goes + return svgCanvas.addExtension.call(this, name, init, initArgs); // }); + }; // Defer injection to wait out initial menu processing. This probably goes // away once all context menu behavior is brought to context menu. + + editor.ready(function () { injectExtendedContextMenuItemsIntoDom(); }); - var extensionsAdded = false; var messageQueue = []; /** - * @param {Any} data - * @param {string} origin + * @param {PlainObject} info + * @param {Any} info.data + * @param {string} info.origin * @fires module:svgcanvas.SvgCanvas#event:message * @returns {undefined} */ - var messageListener = function messageListener(_ref17) { - var data = _ref17.data, - origin = _ref17.origin; + var messageListener = function messageListener(_ref43) { + var data = _ref43.data, + origin = _ref43.origin; + // eslint-disable-line no-shadow // console.log('data, origin, extensionsAdded', data, origin, extensionsAdded); - var messageObj = { data: data, origin: origin }; + var messageObj = { + data: data, + origin: origin + }; + if (!extensionsAdded) { messageQueue.push(messageObj); } else { @@ -31094,19 +36451,44 @@ svgCanvas.call('message', messageObj); } }; - window.addEventListener('message', messageListener); - // Run init once DOM is loaded + window.addEventListener('message', messageListener); // Run init once DOM is loaded // jQuery(editor.init); - Promise.resolve().then(function () { - // We wait a micro-task to let the svgEditor variable be defined for module checks - editor.init(); - }); + + _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee22() { + return regeneratorRuntime.wrap(function _callee22$(_context22) { + while (1) { + switch (_context22.prev = _context22.next) { + case 0: + _context22.prev = 0; + _context22.next = 3; + return Promise.resolve(); + + case 3: + editor.init(); + _context22.next = 9; + break; + + case 6: + _context22.prev = 6; + _context22.t0 = _context22["catch"](0); + console.error(_context22.t0); // eslint-disable-line no-console + + case 9: + case "end": + return _context22.stop(); + } + } + }, _callee22, this, [[0, 6]]); + }))(); window.svgEditor = editor; window.svgEditor.modules = false; - editor.setConfig({ + canvasName: 'xdomain', + // Namespace this allowedOrigins: ['*'] }); diff --git a/firefox-extension/content/svg-edit-overlay.js b/firefox-extension/content/svg-edit-overlay.js index 06be3886..ccc7523a 100644 --- a/firefox-extension/content/svg-edit-overlay.js +++ b/firefox-extension/content/svg-edit-overlay.js @@ -1,3 +1,7 @@ +/** + * Opens the dialog with the SVG Editor. + * @returns {undefined} + */ function startSvgEdit () { // eslint-disable-line no-unused-vars const url = 'chrome://svg-edit/content/editor/svg-editor.html'; window.openDialog(url, 'SVG Editor', 'width=1024,height=700,menubar=no,toolbar=no'); diff --git a/firefox-extension/handlers.js b/firefox-extension/handlers.js index 51d51c69..d33cb0ec 100644 --- a/firefox-extension/handlers.js +++ b/firefox-extension/handlers.js @@ -3,6 +3,11 @@ jQuery(function () { if (!window.Components) return; + /** + * Offer choice of file. + * @param {boolean} readflag + * @returns {nsILocalFile} + */ function mozFilePicker (readflag) { const fp = window.Components.classes['@mozilla.org/filepicker;1'] .createInstance(Components.interfaces.nsIFilePicker); @@ -19,16 +24,16 @@ jQuery(function () { netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); const file = mozFilePicker(true); if (!file) { - return null; + return; } const inputStream = Components.classes['@mozilla.org/network/file-input-stream;1'].createInstance(Components.interfaces.nsIFileInputStream); - inputStream.init(file, 0x01, parseInt('00004', 8), null); + inputStream.init(file, 0x01, 0o00004, null); const sInputStream = Components.classes['@mozilla.org/scriptableinputstream;1'].createInstance(Components.interfaces.nsIScriptableInputStream); sInputStream.init(inputStream); svgCanvas.setSvgString(sInputStream.read(sInputStream.available())); } catch (e) { - console.log('Exception while attempting to load' + e); + console.log('Exception while attempting to load' + e); // eslint-disable-line no-console } }, save (svg, str) { @@ -39,16 +44,16 @@ jQuery(function () { } if (!file.exists()) { - file.create(0, parseInt('0664', 8)); + file.create(0, 0o0664); } const out = Components.classes['@mozilla.org/network/file-output-stream;1'].createInstance(Components.interfaces.nsIFileOutputStream); - out.init(file, 0x20 | 0x02, parseInt('00004', 8), null); + out.init(file, 0x20 | 0x02, 0o00004, null); // eslint-disable-line no-bitwise out.write(str, str.length); out.flush(); out.close(); } catch (e) { - alert(e); + alert(e); // eslint-disable-line no-alert } } }); diff --git a/grep-jsdoc.js b/jsdoc-check-overly-generic-types.js similarity index 60% rename from grep-jsdoc.js rename to jsdoc-check-overly-generic-types.js index 13fd0dce..e63367cb 100644 --- a/grep-jsdoc.js +++ b/jsdoc-check-overly-generic-types.js @@ -2,7 +2,8 @@ /** * @todo Fork find-in-files to get ignore pattern support */ -const fif = require('find-in-files'); +import fif from 'find-in-files'; + (async () => { /** * @typedef {PlainObject} FileResult @@ -15,13 +16,13 @@ const fileMatchPatterns = ['editor']; * Keys are file name strings * @type {Object.} */ -let results = await Promise.all(fileMatchPatterns.map(async (fileMatchPattern) => { +let results = await Promise.all(fileMatchPatterns.map((fileMatchPattern) => { return fif.find( { // We grab to the end of the line as the `line` result for `find-in-files` // only grabs from the beginning of the file to the end of the match. - term: `(@[^{\\n]*{[^}\\n]*(\\bobject|\\barray\\b|function|\\bnumber|\\*)[^}\\n]*}|@.*{}).*`, - flags: 'g' + term: `(@[^{\\n]*{[^}\\n]*(\\bobject|\\barray\\b|[^.]function|\\bnumber|\\*)[^}\\n]*}|@.*{} ).*`, + flags: 'gi' }, fileMatchPattern, '([^n]|[^i]n|[^m]in|[^.]min).js$' @@ -46,26 +47,32 @@ Object.entries(results).forEach(([file, res]) => { }); */ }); -console.log(`${output}\nTotal failures found: ${total}.\n`); +console.log(`${output}\nTotal failures found: ${total}.\n`); // eslint-disable-line no-console +/** + * @external FindInFilesResult + * @type {PlainObject} + * @property {string[]} matches The matched strings + * @property {Integer} count The number of matches + * @property {string[]} line The lines that were matched. The docs mistakenly indicate the property is named `lines`; see {@link https://github.com/kaesetoast/find-in-files/pull/19}. + */ + +/** + * Eliminates known false matches against overly generic types. + * @param {string} file + * @param {external:FindInFilesResult} res + * @returns {undefined} + */ function reduceFalseMatches (file, res) { switch (file) { + case 'editor/external/jamilih/jml-es.js': case 'editor/xdomain-svgedit-config-iife.js': // Ignore res.line = []; break; - case 'editor/external/dynamic-import-polyfill/importModule.js': - res.line = res.line.filter((line) => { - return ![ - '* @returns {*} The return depends on the export of the targeted module.', - '* @returns {ArbitraryModule|*} The return depends on the export of the targeted module.' - ].includes(line); - }); - break; case 'editor/embedapi.js': res.line = res.line.filter((line) => { return ![ - '* @param {...*} args Signature dependent on the function', - '* @returns {*} Return dependent on the function' + '* @param {...*} args Signature dependent on the function' ].includes(line); }); break; @@ -73,9 +80,12 @@ function reduceFalseMatches (file, res) { res.line = res.line.filter((line) => { return ![ '* @typedef {number} Float', - '* @typedef {object} ArbitraryObject', - '* @typedef {object} ArbitraryModule', - '* @typedef {*} Any' + '* @typedef {Object} ArbitraryObject', + '* @typedef {Object} ArbitraryModule', + '* @typedef {Array} GenericArray', + '* @typedef {*} Any', + '* @param {...*} args Signature dependent on the function', + '* @returns {*} Return dependent on the function' ].includes(line); }); break; diff --git a/lgtm.yml b/lgtm.yml new file mode 100644 index 00000000..544fd6e8 --- /dev/null +++ b/lgtm.yml @@ -0,0 +1,8 @@ +extraction: + javascript: + index: + filters: + - exclude: "editor/xdomain-svgedit-config-iife.js" + - exclude: "editor/redirect-on-no-module-support.js" + - exclude: "svgedit-config-iife.js" + - exclude: "dist" diff --git a/opera-widget/handlers.js b/opera-widget/handlers.js index 30e391ae..e5d2a549 100644 --- a/opera-widget/handlers.js +++ b/opera-widget/handlers.js @@ -1,5 +1,7 @@ /* globals jQuery, svgCanvas */ -// Note: This JavaScript file must be included as the last script on the main HTML editor page to override the open/save handlers +/* eslint-disable no-console */ +// Note: This JavaScript file must be included as the last script on the main +// HTML editor page to override the open/save handlers jQuery(function () { if (window.opera && window.opera.io && window.opera.io.filesystem) { svgCanvas.setCustomHandlers({ @@ -31,9 +33,9 @@ jQuery(function () { console.log('Open file failed.'); } }, - save (window, svg) { + save (win, svg) { try { - window.opera.io.filesystem.browseForSave( + win.opera.io.filesystem.browseForSave( new Date().getTime(), /* mountpoint name */ '', /* default location */ function (file) { diff --git a/package-lock.json b/package-lock.json index 0bf58afc..e8604fd6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svgedit", - "version": "3.0.0-rc.2", + "version": "4.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -13,6 +13,457 @@ "@babel/highlight": "^7.0.0" } }, + "@babel/core": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.3.3.tgz", + "integrity": "sha512-w445QGI2qd0E0GlSnq6huRZWPMmQGCp5gd5ZWS4hagn0EiwzxD5QMFkpchyusAyVC1n27OKXzQ0/88aVU9n4xQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.3.3", + "@babel/helpers": "^7.2.0", + "@babel/parser": "^7.3.3", + "@babel/template": "^7.2.2", + "@babel/traverse": "^7.2.2", + "@babel/types": "^7.3.3", + "convert-source-map": "^1.1.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.11", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "@babel/generator": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.3.tgz", + "integrity": "sha512-aEADYwRRZjJyMnKN7llGIlircxTCofm3dtV5pmY6ob18MSIuipHpA2yZWkPlycwu5HJcx/pADS3zssd8eY7/6A==", + "dev": true, + "requires": { + "@babel/types": "^7.3.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/parser": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.3.3.tgz", + "integrity": "sha512-xsH1CJoln2r74hR+y7cg2B5JCPaTh+Hd+EbBRk9nWGSNspuo6krjhX0Om6RnRQuIvFq8wVXCLKH3kwKDYhanSg==", + "dev": true + }, + "@babel/template": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" + } + }, + "@babel/traverse": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.2.3.tgz", + "integrity": "sha512-Z31oUD/fJvEWVR0lNZtfgvVt512ForCTNKYcJBGbPb1QZfve4WGH8Wsy7+Mev33/45fhP/hwQtvgusNdcCMgSw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.2.2", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.2.3", + "@babel/types": "^7.2.2", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + } + }, + "@babel/types": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.3.tgz", + "integrity": "sha512-2tACZ80Wg09UnPg5uGAOUvvInaqLk3l/IAhQzlxLQOIXacr6bMsra5SH6AWw/hIDRCSbCdHP2KzSOD+cT7TzMQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "@babel/generator": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.1.3.tgz", + "integrity": "sha512-ZoCZGcfIJFJuZBqxcY9OjC1KW2lWK64qrX1o4UYL3yshVhwKFYgzpWZ0vvtGMNJdTlvkw0W+HR1VnYN8q3QPFQ==", + "dev": true, + "requires": { + "@babel/types": "^7.1.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.10", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", + "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", + "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-call-delegate": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.1.0.tgz", + "integrity": "sha512-YEtYZrw3GUK6emQHKthltKNZwszBcHK58Ygcis+gVUrF4/FmTVr5CCqQNSfmvg2y+YDEANyYoaLz/SHsnusCwQ==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.0.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-define-map": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.1.0.tgz", + "integrity": "sha512-yPPcW8dc3gZLN+U1mhYV91QU3n5uTbx7DUdf8NnPbjS0RMwBuHi9Xt2MUgppmNz7CJxTBWsGczTiEp1CSOTPRg==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/types": "^7.0.0", + "lodash": "^4.17.10" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", + "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0.tgz", + "integrity": "sha512-Ggv5sldXUeSKsuzLkddtyhyHe2YantsxWKNi7A+7LeD12ExRDWTRk29JCXpaHPAbMaIPZSil7n+lq78WY2VY7w==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", + "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-module-transforms": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.1.0.tgz", + "integrity": "sha512-0JZRd2yhawo79Rcm4w0LwSMILFmFXjugG3yqf+P/UsKsRS1mJCmMwwlHDlMg7Avr9LrvSpp4ZSULO9r8jpCzcw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0", + "lodash": "^4.17.10" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", + "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + }, + "@babel/helper-regex": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.0.0.tgz", + "integrity": "sha512-TR0/N0NDCcUIUEbqV6dCO+LptmmSQFQ7q70lfcEB4URsjD0E1HzicrwUH+ap6BAQ2jhCX9Q4UqZy4wilujWlkg==", + "dev": true, + "requires": { + "lodash": "^4.17.10" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", + "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-wrap-function": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-replace-supers": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.2.3.tgz", + "integrity": "sha512-GyieIznGUfPXPWu0yLS6U55Mz67AZD9cUk0BfirOWlPrXlBcan9Gz+vHGz+cPfuoweZSnPzPIm67VtQM0OWZbA==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.0.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/traverse": "^7.2.3", + "@babel/types": "^7.0.0" + }, + "dependencies": { + "@babel/generator": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.3.tgz", + "integrity": "sha512-aEADYwRRZjJyMnKN7llGIlircxTCofm3dtV5pmY6ob18MSIuipHpA2yZWkPlycwu5HJcx/pADS3zssd8eY7/6A==", + "dev": true, + "requires": { + "@babel/types": "^7.3.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + }, + "dependencies": { + "@babel/types": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.3.tgz", + "integrity": "sha512-2tACZ80Wg09UnPg5uGAOUvvInaqLk3l/IAhQzlxLQOIXacr6bMsra5SH6AWw/hIDRCSbCdHP2KzSOD+cT7TzMQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.3.3.tgz", + "integrity": "sha512-xsH1CJoln2r74hR+y7cg2B5JCPaTh+Hd+EbBRk9nWGSNspuo6krjhX0Om6RnRQuIvFq8wVXCLKH3kwKDYhanSg==", + "dev": true + }, + "@babel/traverse": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.2.3.tgz", + "integrity": "sha512-Z31oUD/fJvEWVR0lNZtfgvVt512ForCTNKYcJBGbPb1QZfve4WGH8Wsy7+Mev33/45fhP/hwQtvgusNdcCMgSw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.2.2", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.2.3", + "@babel/types": "^7.2.2", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + }, + "dependencies": { + "@babel/types": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.3.tgz", + "integrity": "sha512-2tACZ80Wg09UnPg5uGAOUvvInaqLk3l/IAhQzlxLQOIXacr6bMsra5SH6AWw/hIDRCSbCdHP2KzSOD+cT7TzMQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "@babel/helper-simple-access": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", + "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", + "dev": true, + "requires": { + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", + "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-wrap-function": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", + "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.2.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.3.tgz", + "integrity": "sha512-2tACZ80Wg09UnPg5uGAOUvvInaqLk3l/IAhQzlxLQOIXacr6bMsra5SH6AWw/hIDRCSbCdHP2KzSOD+cT7TzMQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helpers": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.3.1.tgz", + "integrity": "sha512-Q82R3jKsVpUV99mgX50gOPCWwco9Ec5Iln/8Vyu4osNIOQgSrd9RFrQeUvmvddFNoLwMyOUWU+5ckioEKpDoGA==", + "dev": true, + "requires": { + "@babel/template": "^7.1.2", + "@babel/traverse": "^7.1.5", + "@babel/types": "^7.3.0" + }, + "dependencies": { + "@babel/generator": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.3.tgz", + "integrity": "sha512-aEADYwRRZjJyMnKN7llGIlircxTCofm3dtV5pmY6ob18MSIuipHpA2yZWkPlycwu5HJcx/pADS3zssd8eY7/6A==", + "dev": true, + "requires": { + "@babel/types": "^7.3.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/parser": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.3.3.tgz", + "integrity": "sha512-xsH1CJoln2r74hR+y7cg2B5JCPaTh+Hd+EbBRk9nWGSNspuo6krjhX0Om6RnRQuIvFq8wVXCLKH3kwKDYhanSg==", + "dev": true + }, + "@babel/traverse": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.2.3.tgz", + "integrity": "sha512-Z31oUD/fJvEWVR0lNZtfgvVt512ForCTNKYcJBGbPb1QZfve4WGH8Wsy7+Mev33/45fhP/hwQtvgusNdcCMgSw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.2.2", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.2.3", + "@babel/types": "^7.2.2", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + } + }, + "@babel/types": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.3.tgz", + "integrity": "sha512-2tACZ80Wg09UnPg5uGAOUvvInaqLk3l/IAhQzlxLQOIXacr6bMsra5SH6AWw/hIDRCSbCdHP2KzSOD+cT7TzMQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, "@babel/highlight": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", @@ -22,14 +473,515 @@ "chalk": "^2.0.0", "esutils": "^2.0.2", "js-tokens": "^4.0.0" - }, - "dependencies": { - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - } + } + }, + "@babel/node": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/node/-/node-7.2.2.tgz", + "integrity": "sha512-jPqgTycE26uFsuWpLika9Ohz9dmLQHWjOnMNxBOjYb1HXO+eLKxEr5FfKSXH/tBvFwwaw+pzke3gagnurGOfCA==", + "dev": true, + "requires": { + "@babel/polyfill": "^7.0.0", + "@babel/register": "^7.0.0", + "commander": "^2.8.1", + "lodash": "^4.17.10", + "v8flags": "^3.1.1" + } + }, + "@babel/parser": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.1.3.tgz", + "integrity": "sha512-gqmspPZOMW3MIRb9HlrnbZHXI1/KHTOroBwN1NcLL6pWxzqzEKGvRTq0W/PxS45OtQGbaFikSQpkS5zbnsQm2w==", + "dev": true + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz", + "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0", + "@babel/plugin-syntax-async-generators": "^7.2.0" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", + "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-json-strings": "^7.2.0" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.3.2.tgz", + "integrity": "sha512-DjeMS+J2+lpANkYLLO+m6GjoTMygYglKmRe6cDTbFv3L9i6mmiE8fe6B8MtCSLZpVXscD5kn7s6SgtHrDoBWoA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", + "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.2.0.tgz", + "integrity": "sha512-LvRVYb7kikuOtIoUeWTkOxQEV1kYvL5B6U3iWEGCzPNRus1MzJweFqORTj+0jkxozkTSYNJozPOddxmqdqsRpw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0", + "regexpu-core": "^4.2.0" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", + "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", + "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", + "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", + "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", + "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.2.0.tgz", + "integrity": "sha512-CEHzg4g5UraReozI9D4fblBYABs7IM6UerAVG7EJVrTLC5keh00aEuLUT+O40+mJCEzaXkYfTCUKIyeDfMOFFQ==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", + "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.2.0.tgz", + "integrity": "sha512-vDTgf19ZEV6mx35yiPJe4fS02mPQUUcBNwWQSZFXSzTSbsJFQvHt7DqyS3LK8oOWALFOsJ+8bbqBgkirZteD5Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "lodash": "^4.17.10" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.3.3.tgz", + "integrity": "sha512-n0CLbsg7KOXsMF4tSTLCApNMoXk0wOPb0DYfsOO1e7SfIb9gOyfbpKI2MZ+AXfqvlfzq2qsflJ1nEns48Caf2w==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-define-map": "^7.1.0", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", + "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.3.2.tgz", + "integrity": "sha512-Lrj/u53Ufqxl/sGxyjsJ2XNtNuEjDyjpqdhMNh5aZ+XFOdThL46KBj27Uem4ggoezSYBxKWAil6Hu8HtwqesYw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.2.0.tgz", + "integrity": "sha512-sKxnyHfizweTgKZf7XsXu/CNupKhzijptfTM+bozonIuyVrLWVUvYjE2bhuSBML8VQeMxq4Mm63Q9qvcvUcciQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0", + "regexpu-core": "^4.1.3" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz", + "integrity": "sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", + "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.2.0.tgz", + "integrity": "sha512-Kz7Mt0SsV2tQk6jG5bBv5phVbkd0gd27SgYD4hH1aLMJRchM0dzHaXvrWhVZ+WxAlDoAKZ7Uy3jVTW2mKXQ1WQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.2.0.tgz", + "integrity": "sha512-kWgksow9lHdvBC2Z4mxTsvc7YdY7w/V6B2vy9cTIPtLEE9NhwoWivaxdNM/S37elu5bqlLP/qOY906LukO9lkQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", + "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz", + "integrity": "sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.2.0.tgz", + "integrity": "sha512-V6y0uaUQrQPXUrmj+hgnks8va2L0zcZymeU7TtWEgdRLNkceafKXEduv7QzgQAE4lT+suwooG9dC7LFhdRAbVQ==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.2.0.tgz", + "integrity": "sha512-aYJwpAhoK9a+1+O625WIjvMY11wkB/ok0WClVwmeo3mCjcNRjt+/8gHWrB5i+00mUju0gWsBkQnPpdvQ7PImmQ==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz", + "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.3.0.tgz", + "integrity": "sha512-NxIoNVhk9ZxS+9lSoAQ/LM0V2UEvARLttEHUrRDGKFaAxOYQcrkN/nLRE+BbbicCAvZPl7wMP0X60HsHE5DtQw==", + "dev": true, + "requires": { + "regexp-tree": "^0.1.0" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz", + "integrity": "sha512-yin069FYjah+LbqfGeTfzIBODex/e++Yfa0rH0fpfam9uTbuEeEOx5GLGr210ggOV77mVRNoeqSYqeuaqSzVSw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz", + "integrity": "sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.1.0" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.3.3.tgz", + "integrity": "sha512-IrIP25VvXWu/VlBWTpsjGptpomtIkYrN/3aDp4UKm7xK6UxZY88kcJ1UwETbzHAlwN21MnNfwlar0u8y3KpiXw==", + "dev": true, + "requires": { + "@babel/helper-call-delegate": "^7.1.0", + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0.tgz", + "integrity": "sha512-sj2qzsEx8KDVv1QuJc/dEfilkg3RRPvPYx/VnKLtItVQRWt1Wqf5eVCOLZm29CiGFfYYsA3VPjfizTCV0S0Dlw==", + "dev": true, + "requires": { + "regenerator-transform": "^0.13.3" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", + "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz", + "integrity": "sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", + "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.2.0.tgz", + "integrity": "sha512-FkPix00J9A/XWXv4VoKJBMeSkyY9x/TqIh76wzcdfl57RJJcf8CehQ08uwfhCDNtRQYtHQKBTwKZDEyjE13Lwg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", + "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.2.0.tgz", + "integrity": "sha512-m48Y0lMhrbXEJnVUaYly29jRXbQ3ksxPrS1Tg8t+MHqzXhtBYAvI51euOBaoAlZLPHsieY9XPVMf80a5x0cPcA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0", + "regexpu-core": "^4.1.3" + } + }, + "@babel/polyfill": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.2.5.tgz", + "integrity": "sha512-8Y/t3MWThtMLYr0YNC/Q76tqN1w30+b0uQMeFUYauG2UGTR19zyUtFrAzT23zNtBxPp+LbE5E/nwV/q/r3y6ug==", + "dev": true, + "requires": { + "core-js": "^2.5.7", + "regenerator-runtime": "^0.12.0" + } + }, + "@babel/preset-env": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.3.1.tgz", + "integrity": "sha512-FHKrD6Dxf30e8xgHQO0zJZpUPfVZg+Xwgz5/RdSWCbza9QLNk4Qbp40ctRoqDxml3O8RMzB1DU55SXeDG6PqHQ==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-async-generator-functions": "^7.2.0", + "@babel/plugin-proposal-json-strings": "^7.2.0", + "@babel/plugin-proposal-object-rest-spread": "^7.3.1", + "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.2.0", + "@babel/plugin-syntax-async-generators": "^7.2.0", + "@babel/plugin-syntax-json-strings": "^7.2.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", + "@babel/plugin-transform-arrow-functions": "^7.2.0", + "@babel/plugin-transform-async-to-generator": "^7.2.0", + "@babel/plugin-transform-block-scoped-functions": "^7.2.0", + "@babel/plugin-transform-block-scoping": "^7.2.0", + "@babel/plugin-transform-classes": "^7.2.0", + "@babel/plugin-transform-computed-properties": "^7.2.0", + "@babel/plugin-transform-destructuring": "^7.2.0", + "@babel/plugin-transform-dotall-regex": "^7.2.0", + "@babel/plugin-transform-duplicate-keys": "^7.2.0", + "@babel/plugin-transform-exponentiation-operator": "^7.2.0", + "@babel/plugin-transform-for-of": "^7.2.0", + "@babel/plugin-transform-function-name": "^7.2.0", + "@babel/plugin-transform-literals": "^7.2.0", + "@babel/plugin-transform-modules-amd": "^7.2.0", + "@babel/plugin-transform-modules-commonjs": "^7.2.0", + "@babel/plugin-transform-modules-systemjs": "^7.2.0", + "@babel/plugin-transform-modules-umd": "^7.2.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.3.0", + "@babel/plugin-transform-new-target": "^7.0.0", + "@babel/plugin-transform-object-super": "^7.2.0", + "@babel/plugin-transform-parameters": "^7.2.0", + "@babel/plugin-transform-regenerator": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.2.0", + "@babel/plugin-transform-spread": "^7.2.0", + "@babel/plugin-transform-sticky-regex": "^7.2.0", + "@babel/plugin-transform-template-literals": "^7.2.0", + "@babel/plugin-transform-typeof-symbol": "^7.2.0", + "@babel/plugin-transform-unicode-regex": "^7.2.0", + "browserslist": "^4.3.4", + "invariant": "^2.2.2", + "js-levenshtein": "^1.1.3", + "semver": "^5.3.0" + } + }, + "@babel/register": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.0.0.tgz", + "integrity": "sha512-f/+CRmaCe7rVEvcvPvxeA8j5aJhHC3aJie7YuqcMDhUOuyWLA7J/aNrTaHIzoWPEhpHA54mec4Mm8fv8KBlv3g==", + "dev": true, + "requires": { + "core-js": "^2.5.7", + "find-cache-dir": "^1.0.0", + "home-or-tmp": "^3.0.0", + "lodash": "^4.17.10", + "mkdirp": "^0.5.1", + "pirates": "^4.0.0", + "source-map-support": "^0.5.9" + } + }, + "@babel/runtime": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.3.1.tgz", + "integrity": "sha512-7jGW8ppV0ant637pIqAcFfQDDH1orEPGJb8aXfUozuCU3QqX7rX4DA8iwrbPrR1hcH0FTTHz47yQnk+bl5xHQA==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.12.0" + } + }, + "@babel/template": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", + "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.1.2", + "@babel/types": "^7.1.2" + } + }, + "@babel/traverse": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.4.tgz", + "integrity": "sha512-my9mdrAIGdDiSVBuMjpn/oXYpva0/EZwWL3sm3Wcy/AVWO2eXnsoZruOT9jOGNRXU8KbCIu5zsKnXcAJ6PcV6Q==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.1.3", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.1.3", + "@babel/types": "^7.1.3", + "debug": "^3.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + } + }, + "@babel/types": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.1.3.tgz", + "integrity": "sha512-RpPOVfK+yatXyn8n4PB1NW6k9qjinrXrRR8ugBN8fD6hCy5RXI6PSbVqpOJBO9oSaY7Nom4ohj35feb0UR9hSA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" } }, "@mrmlnc/readdir-enhanced": { @@ -42,40 +994,104 @@ "glob-to-regexp": "^0.3.0" } }, + "@mysticatea/eslint-plugin": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@mysticatea/eslint-plugin/-/eslint-plugin-9.0.1.tgz", + "integrity": "sha512-JjuOUOfgx+WpOnBo+Y1C0Mrmqmgj0D3r95h+pTvnqtcxWTF6WDQN5YHoLl9XRcN7aegOq5h7bHtJrxbidJa3Dw==", + "dev": true, + "requires": { + "@typescript-eslint/eslint-plugin": "~1.1.1", + "@typescript-eslint/parser": "~1.1.1", + "eslint-plugin-eslint-comments": "~3.0.1", + "eslint-plugin-eslint-plugin": "~2.0.0", + "eslint-plugin-node": "~8.0.0", + "eslint-plugin-prettier": "~3.0.0", + "eslint-plugin-vue": "~5.1.0", + "prettier": "~1.14.3", + "vue-eslint-parser": "^5.0.0" + }, + "dependencies": { + "eslint-plugin-eslint-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.0.1.tgz", + "integrity": "sha512-7zU6gCulKVmfG3AZdnvDxzfHaGdvkA8tsLiKbneeI/TlVaulJsRzOyMCctH9QTobKVJ6LIsiJbrkSKkgcFLHxw==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "ignore": "^3.3.8" + } + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + } + } + }, "@nodelib/fs.stat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.0.tgz", - "integrity": "sha512-LAQ1d4OPfSJ/BMbI2DuizmYrrkD9JMaTdi2hQTlI53lQ4kRQPyZQRS4CYQ7O66bnBBnP/oYdRxbk++X0xuFU6A==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", "dev": true }, + "@octetstream/eslint-config": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@octetstream/eslint-config/-/eslint-config-3.0.0.tgz", + "integrity": "sha512-VX8gZ6h9PNKrWb+N9AoWM2DA+eVBAqAL0OLHwLjh+iwLrICQRFYzJDxxHIpD7rN413PCppr2vp6cy8UGdZGd+A==", + "dev": true, + "requires": { + "babel-eslint": "^9.0.0", + "eslint-config-airbnb-base": "^13.1.0", + "eslint-plugin-import": "^2.14.0", + "eslint-plugin-promise": "^4.0.0" + } + }, "@octetstream/promisify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@octetstream/promisify/-/promisify-1.1.0.tgz", - "integrity": "sha512-+ns1dHOaK4f8tvgf8uAkyuvdG+o9QkSQzLNU/a36cDPxKhORHCK0xNQ+GQb4ZOU8ouSS8akvfaKdJmZP5PrPow==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@octetstream/promisify/-/promisify-2.0.1.tgz", + "integrity": "sha512-UgxIh3BQBpqAoaFE4jPgtw5QQfdoD1M7AYI0tsz8FzS2HC2oP5aTPBReOLxguXLPhbGzXkmqsD3uv6JQiOlWFg==", "dev": true }, "@sinonjs/commons": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.0.2.tgz", - "integrity": "sha512-WR3dlgqJP4QNrLC4iXN/5/2WaLQQ0VijOOkmflqFGVJ6wLEpbSjo7c0ZeGIdtY8Crk7xBBp87sM6+Mkerz7alw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.3.0.tgz", + "integrity": "sha512-j4ZwhaHmwsCb4DlDOIWnI5YyKDNMoNThsmwEpfHx6a1EpsGZ9qYLxP++LMlmBRjtGptGHFsGItJ768snllFWpA==", "dev": true, "requires": { "type-detect": "4.0.8" } }, "@sinonjs/formatio": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", - "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.1.0.tgz", + "integrity": "sha512-ZAR2bPHOl4Xg6eklUGpsdiIJ4+J1SNag1DHHrG/73Uz/nVwXqjgUtRPLoS+aVyieN9cSbc0E4LsU984tWcDyNg==", "dev": true, "requires": { - "samsam": "1.3.0" + "@sinonjs/samsam": "^2 || ^3" } }, "@sinonjs/samsam": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-2.0.0.tgz", - "integrity": "sha512-D7VxhADdZbDJ0HjUTMnSQ5xIGb4H2yWpg8k9Sf1T08zfFiQYlaxM8LZydpR4FQ2E6LZJX8IlabNZ5io4vdChwg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.1.1.tgz", + "integrity": "sha512-ILlwvQUwAiaVBzr3qz8oT1moM7AIUHqUc2UmEjQcH9lLe+E+BZPwUMuc9FFojMswRK4r96x5zDTTrowMLw/vuA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.0.2", + "array-from": "^2.1.1", + "lodash": "^4.17.11" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true + }, + "@types/error-stack-parser": { + "version": "1.3.18", + "resolved": "https://registry.npmjs.org/@types/error-stack-parser/-/error-stack-parser-1.3.18.tgz", + "integrity": "sha1-4ByfjIXKg7YQMgxiJYsMkCat4Pc=", "dev": true }, "@types/estree": { @@ -84,65 +1100,66 @@ "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", "dev": true }, - "@types/events": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", - "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==", - "dev": true - }, - "@types/execa": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@types/execa/-/execa-0.9.0.tgz", - "integrity": "sha512-mgfd93RhzjYBUHHV532turHC2j4l/qxsF/PbfDmprHDEUHmNZGlDn1CEsulGK3AfsPdhkWzZQT/S/k0UGhLGsA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/fs-extra": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.3.tgz", - "integrity": "sha512-m2QKoRrJnei1s10e1ZfMIa7QcABBVLdQhVUv5+bMRaHhPzxO/IWMmREiags59AqFbI+piWPq/PupTahNS/0kyA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/glob": { - "version": "5.0.35", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.35.tgz", - "integrity": "sha512-wc+VveszMLyMWFvXLkloixT4n0harUIVZjnpzztaZ0nKLuul7Z32iMt2fUFGAaZ4y1XWjFRMtCI5ewvyh4aIeg==", - "dev": true, - "requires": { - "@types/events": "*", - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/globby/-/globby-6.1.0.tgz", - "integrity": "sha512-j3XSDNoK4LO5T+ZviQD6PqfEjm07QFEacOTbJR3hnLWuWX0ZMLJl9oRPgj1PyrfGbXhfHFkksC9QZ9HFltJyrw==", - "dev": true, - "requires": { - "@types/glob": "*" - } - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "@types/lodash": { + "version": "4.14.121", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.121.tgz", + "integrity": "sha512-ORj7IBWj13iYufXt/VXrCNMbUuCTJfhzme5kx9U/UtcIPdJYuvPDUAlHlbNhz/8lKCLy9XGIZnGrqXOtQbPGoQ==", "dev": true }, "@types/node": { - "version": "10.3.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.3.2.tgz", - "integrity": "sha512-9NfEUDp3tgRhmoxzTpTo+lq+KIVFxZahuRX0LHF/9IzKHaWuoWsIrrJ61zw5cnnlGINX8lqJzXYfQTOICS5Q+A==", + "version": "11.9.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.9.4.tgz", + "integrity": "sha512-Zl8dGvAcEmadgs1tmSPcvwzO1YRsz38bVJQvH1RvRqSR9/5n61Q1ktcDL0ht3FXWR+ZpVmXVwN1LuH4Ax23NsA==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.1.1.tgz", + "integrity": "sha512-7uLG6yevcS3YNMnizbZjC1xCDD2RNwqbUAPFkjz80x3NeytlIExvPR40+meGwiJ+LilgJVlqqlDMFu7PHJ6Kzw==", + "dev": true, + "requires": { + "@typescript-eslint/parser": "1.1.1", + "requireindex": "^1.2.0" + } + }, + "@typescript-eslint/parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.1.1.tgz", + "integrity": "sha512-P6v+iYkI+ywp6MaFyAJ6NqU5W6fiAvMXWjCV63xTJbkQdtAngdjSCajlEEweqJqL4RNsgFCHBe5HbYyT6TmW4g==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "1.1.1", + "eslint-scope": "^4.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "@typescript-eslint/typescript-estree": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.1.1.tgz", + "integrity": "sha512-rERZSjNWb4WC425daCUktfh+0fFLy4WWlnu9bESdJv5l+t0ww0yUprRUbgzehag/dGd56Me+3uyXGV2O12qxrQ==", + "dev": true, + "requires": { + "lodash.unescape": "4.0.1", + "semver": "5.5.0" + }, + "dependencies": { + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + } + } + }, + "abab": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", + "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", "dev": true }, "abstract-leveldown": { "version": "0.12.4", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-0.12.4.tgz", + "resolved": "http://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-0.12.4.tgz", "integrity": "sha1-KeGOYy5g5OIh1YECR4UqY9ey5BA=", "dev": true, "requires": { @@ -158,24 +1175,43 @@ } }, "acorn": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.2.tgz", - "integrity": "sha512-cJrKCNcr2kv8dlDnbw+JPUGjHZzo4myaxOLmpOX8a+rgX94YeTcTMv/LFJUSByRpc+i4GgVnnhLxvMu/2Y+rqw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.0.tgz", + "integrity": "sha512-MW/FjM+IvU9CgBzjO3UIPCE2pyEwUsoFl+VGdczOPEdxfGFjuKny/gN54mOuX7Qxmb9Rg9MCn2oKiSUeW+pjrw==", + "dev": true + }, + "acorn-globals": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.0.tgz", + "integrity": "sha512-hMtHj3s5RnuhvHPowpBYvJVj3rAar82JiDQHvGs1zO0l10ocX/xEdBShNHTJaboucJUsScghp74pH3s7EnHHQw==", + "dev": true, + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + } + }, + "acorn-hammerhead": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/acorn-hammerhead/-/acorn-hammerhead-0.1.2.tgz", + "integrity": "sha512-Jb0MFSnuyVE3mdVf/Hg8ol5XTmL2D0QWzVB2O3MQo+NkxJP2CmHOerZ9g5qThwCSusVFezUiGBZ4EKJZ1mZSLw==", "dev": true }, "acorn-jsx": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz", - "integrity": "sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw==", - "dev": true, - "requires": { - "acorn": "^5.0.3" - } + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", + "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", + "dev": true + }, + "acorn-walk": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", + "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", + "dev": true }, "ajv": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz", - "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", + "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -184,28 +1220,55 @@ "uri-js": "^4.2.2" } }, - "ajv-keywords": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", - "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", "dev": true }, + "ansi-cyan": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", + "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, "ansi-escapes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", - "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", "dev": true }, + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", "dev": true }, "anymatch": { @@ -245,12 +1308,36 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", + "dev": true + }, + "array-find": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-find/-/array-find-1.0.0.tgz", + "integrity": "sha1-bI4obRHtdoMn+OYuzuhzU8o+eLg=", + "dev": true + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true }, + "array-from": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", + "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", @@ -278,6 +1365,15 @@ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, "asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", @@ -289,18 +1385,93 @@ "minimalistic-assert": "^1.0.0" } }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, - "atob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", - "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=", + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "dev": true }, + "async": { + "version": "0.2.6", + "resolved": "http://registry.npmjs.org/async/-/async-0.2.6.tgz", + "integrity": "sha1-rT83PZJJrjJIgVZVgryQ4VKrvWg=", + "dev": true + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "async-exit-hook": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-1.1.2.tgz", + "integrity": "sha1-gJXXXkiMKazuBVH+hyUhadeJz7o=", + "dev": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true + }, + "axe-core": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-2.6.1.tgz", + "integrity": "sha512-QFfI3d+x/v92HJWGBaNfgrxdfon9/xXzd04YYfm5w5NJQOLex8qkJCctOt7+ky6e1l9zcQ5E7jsvbnTgQzyfTw==", + "dev": true + }, + "axe-testcafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/axe-testcafe/-/axe-testcafe-1.1.0.tgz", + "integrity": "sha1-tODnMpaU+wkKWZ66wBu6V2Jejr8=", + "dev": true, + "requires": { + "axe-core": "^2.2.3" + } + }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -312,9 +1483,21 @@ "js-tokens": "^3.0.2" }, "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -325,14 +1508,26 @@ "supports-color": "^2.0.0" } }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { "ansi-regex": "^2.0.0" } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true } } }, @@ -363,6 +1558,12 @@ "source-map": "^0.5.7" }, "dependencies": { + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -372,11 +1573,49 @@ "ms": "2.0.0" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "json5": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + } + } + }, + "babel-eslint": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-9.0.0.tgz", + "integrity": "sha512-itv1MwE3TMbY0QtNfeL7wzak1mV47Uy+n6HtSOO4Xd7rvmO+tsGQSgyOEEgo6Y2vHZKZphaoelNeSVj4vkLA1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "^1.0.0" + }, + "dependencies": { + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } } } }, @@ -396,14 +1635,25 @@ "trim-right": "^1.0.1" }, "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", "dev": true } } }, + "babel-helper-bindify-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", + "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, "babel-helper-builder-binary-assignment-operator-visitor": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", @@ -450,6 +1700,18 @@ "babel-types": "^6.24.1" } }, + "babel-helper-explode-class": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", + "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", + "dev": true, + "requires": { + "babel-helper-bindify-decorators": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, "babel-helper-function-name": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", @@ -559,31 +1821,52 @@ "babel-runtime": "^6.22.0" } }, - "babel-plugin-external-helpers": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-external-helpers/-/babel-plugin-external-helpers-6.22.0.tgz", - "integrity": "sha1-IoX0iwK9Xe3oUXXK+MYuhq3M76E=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", "dev": true }, + "babel-plugin-syntax-async-generators": { + "version": "6.13.0", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", + "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", + "dev": true + }, + "babel-plugin-syntax-class-properties": { + "version": "6.13.0", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", + "dev": true + }, + "babel-plugin-syntax-decorators": { + "version": "6.13.0", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", + "dev": true + }, + "babel-plugin-syntax-dynamic-import": { + "version": "6.18.0", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", + "dev": true + }, "babel-plugin-syntax-exponentiation-operator": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", "dev": true }, + "babel-plugin-syntax-flow": { + "version": "6.18.0", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", + "dev": true + }, "babel-plugin-syntax-object-rest-spread": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", - "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", + "version": "7.0.0-beta.3", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-7.0.0-beta.3.tgz", + "integrity": "sha512-21/MnmUFduLr4JzxrKMm/MeF+Jjyi5UdZo38IqzrP0sLhmPbal5ZAUJ4HgWH4339SdjnYgENacbY5wfk/zxTGg==", "dev": true }, "babel-plugin-syntax-trailing-function-commas": { @@ -592,6 +1875,17 @@ "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", "dev": true }, + "babel-plugin-transform-async-generator-functions": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", + "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-generators": "^6.5.0", + "babel-runtime": "^6.22.0" + } + }, "babel-plugin-transform-async-to-generator": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", @@ -603,6 +1897,31 @@ "babel-runtime": "^6.22.0" } }, + "babel-plugin-transform-class-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-plugin-syntax-class-properties": "^6.8.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", + "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", + "dev": true, + "requires": { + "babel-helper-explode-class": "^6.24.1", + "babel-plugin-syntax-decorators": "^6.13.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-types": "^6.24.1" + } + }, "babel-plugin-transform-es2015-arrow-functions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", @@ -835,6 +2154,40 @@ "babel-helper-regex": "^6.24.1", "babel-runtime": "^6.22.0", "regexpu-core": "^2.0.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "http://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + } + } } }, "babel-plugin-transform-exponentiation-operator": { @@ -848,14 +2201,29 @@ "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-object-rest-spread": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", - "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "babel-plugin-transform-flow-strip-types": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", + "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", "dev": true, "requires": { - "babel-plugin-syntax-object-rest-spread": "^6.8.0", - "babel-runtime": "^6.26.0" + "babel-plugin-syntax-flow": "^6.18.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-for-of-as-array": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-for-of-as-array/-/babel-plugin-transform-for-of-as-array-1.1.1.tgz", + "integrity": "sha512-eE4hZJhOUKpX0q/X3adR8B4hLox+t8oe4ZqmhANUmv4cds07AbWt6O0rtFXK7PKFPPnW4nz/5mpbkPMkflyGeg==", + "dev": true + }, + "babel-plugin-transform-object-rest-spread": { + "version": "7.0.0-beta.3", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-7.0.0-beta.3.tgz", + "integrity": "sha512-NOlhrq1CmxyuI94vNsqMhRPMuL5VG2EKUOIJQ0bwNiXBiwWRLdPoWyPT+Irrx5g4g0PkFgA46tnRj7Dc4ZGsxg==", + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "7.0.0-beta.3" } }, "babel-plugin-transform-regenerator": { @@ -865,6 +2233,28 @@ "dev": true, "requires": { "regenerator-transform": "^0.10.0" + }, + "dependencies": { + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, + "requires": { + "babel-runtime": "^6.18.0", + "babel-types": "^6.19.0", + "private": "^0.1.6" + } + } + } + }, + "babel-plugin-transform-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz", + "integrity": "sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-strict-mode": { @@ -877,17 +2267,6 @@ "babel-types": "^6.24.1" } }, - "babel-polyfill": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", - "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "regenerator-runtime": "^0.10.5" - } - }, "babel-preset-env": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", @@ -924,6 +2303,70 @@ "browserslist": "^3.2.6", "invariant": "^2.2.2", "semver": "^5.3.0" + }, + "dependencies": { + "browserslist": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" + } + } + } + }, + "babel-preset-flow": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", + "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", + "dev": true, + "requires": { + "babel-plugin-transform-flow-strip-types": "^6.22.0" + } + }, + "babel-preset-stage-2": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", + "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", + "dev": true, + "requires": { + "babel-plugin-syntax-dynamic-import": "^6.18.0", + "babel-plugin-transform-class-properties": "^6.24.1", + "babel-plugin-transform-decorators": "^6.24.1", + "babel-preset-stage-3": "^6.24.1" + } + }, + "babel-preset-stage-3": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", + "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", + "dev": true, + "requires": { + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-generator-functions": "^6.24.1", + "babel-plugin-transform-async-to-generator": "^6.24.1", + "babel-plugin-transform-exponentiation-operator": "^6.24.1", + "babel-plugin-transform-object-rest-spread": "^6.22.0" + }, + "dependencies": { + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", + "dev": true + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "^6.8.0", + "babel-runtime": "^6.26.0" + } + } } }, "babel-register": { @@ -939,6 +2382,27 @@ "lodash": "^4.17.4", "mkdirp": "^0.5.1", "source-map-support": "^0.4.15" + }, + "dependencies": { + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + } + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "^0.5.6" + } + } } }, "babel-runtime": { @@ -970,6 +2434,14 @@ "babel-types": "^6.26.0", "babylon": "^6.18.0", "lodash": "^4.17.4" + }, + "dependencies": { + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + } } }, "babel-traverse": { @@ -989,6 +2461,12 @@ "lodash": "^4.17.4" }, "dependencies": { + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -1003,6 +2481,12 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -1016,12 +2500,26 @@ "esutils": "^2.0.2", "lodash": "^4.17.4", "to-fast-properties": "^1.0.3" + }, + "dependencies": { + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + } } }, "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "version": "7.0.0-beta.19", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz", + "integrity": "sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A==", + "dev": true + }, + "bail": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz", + "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==", "dev": true }, "balanced-match": { @@ -1085,9 +2583,36 @@ } } }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bin-v8-flags-filter": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bin-v8-flags-filter/-/bin-v8-flags-filter-1.2.0.tgz", + "integrity": "sha512-g8aeYkY7GhyyKRvQMBsJQZjhm2iCX3dKYvfrMpwVR8IxmUGrkpCBFoKbB9Rh0o3sTLCjU/1tFpZ4C7j3f+D+3g==", + "dev": true + }, + "binary-extensions": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", + "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", + "dev": true + }, "bl": { "version": "0.8.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-0.8.2.tgz", + "resolved": "http://registry.npmjs.org/bl/-/bl-0.8.2.tgz", "integrity": "sha1-yba8oI0bwuoA/Ir7Txpf0eHGbk4=", "dev": true, "requires": { @@ -1102,7 +2627,7 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { @@ -1121,9 +2646,9 @@ } }, "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", "dev": true }, "bn.js": { @@ -1132,6 +2657,12 @@ "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", "dev": true }, + "bowser": { + "version": "1.6.0", + "resolved": "http://registry.npmjs.org/bowser/-/bowser-1.6.0.tgz", + "integrity": "sha1-N/w4e2Fstq7zcNq01r1AK3TFxU0=", + "dev": true + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1177,9 +2708,24 @@ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", "dev": true }, + "brotli": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.2.tgz", + "integrity": "sha1-UlqcrU/LqWR119OI9q7LE+7VL0Y=", + "dev": true, + "requires": { + "base64-js": "^1.1.2" + } + }, + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", + "dev": true + }, "browserify-aes": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, "requires": { @@ -1203,14 +2749,15 @@ } }, "browserify-des": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.1.tgz", - "integrity": "sha512-zy0Cobe3hhgpiOM32Tj7KQ3Vl91m0njwsjzZQK1L+JDf11dzP9qIvjreVinsvXrgfjhStXwUWAEpB9D7Gwmayw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", "dev": true, "requires": { "cipher-base": "^1.0.1", "des.js": "^1.0.0", - "inherits": "^2.0.1" + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" } }, "browserify-fs": { @@ -1226,7 +2773,7 @@ }, "browserify-rsa": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "dev": true, "requires": { @@ -1250,22 +2797,14 @@ } }, "browserslist": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", - "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.4.1.tgz", + "integrity": "sha512-pEBxEXg7JwaakBXjATYw/D1YZh4QUSCX/Mnd/wnqSRPPSi1U39iDhDoKGoBUcraKdxDlrYqJxSI5nNvD+dWP2A==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000844", - "electron-to-chromium": "^1.3.47" - } - }, - "bser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.0.0.tgz", - "integrity": "sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk=", - "dev": true, - "requires": { - "node-int64": "^0.4.0" + "caniuse-lite": "^1.0.30000929", + "electron-to-chromium": "^1.3.103", + "node-releases": "^1.1.3" } }, "buffer-es6": { @@ -1275,9 +2814,9 @@ "dev": true }, "buffer-from": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", - "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, "buffer-xor": { @@ -1315,51 +2854,68 @@ "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", "dev": true }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "callsite-record": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/callsite-record/-/callsite-record-4.1.3.tgz", + "integrity": "sha512-otAcPmu8TiHZ38cIL3NjQa1nGoSQRRe8WDDUgj5ZUwJWn1wzOYBwVSJbpVyzZ0sesQeKlYsPu9DG70fhh6AK9g==", "dev": true, "requires": { - "callsites": "^0.2.0" + "@types/error-stack-parser": "^1.3.18", + "@types/lodash": "^4.14.72", + "callsite": "^1.0.0", + "chalk": "^2.4.0", + "error-stack-parser": "^1.3.3", + "highlight-es": "^1.0.0", + "lodash": "4.6.1 || ^4.16.1", + "pinkie-promise": "^2.0.0" } }, "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.0.0.tgz", + "integrity": "sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw==", "dev": true }, "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true }, "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", "dev": true, "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" } }, - "caniuse-lite": { - "version": "1.0.30000846", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000846.tgz", - "integrity": "sha512-qxUOHr5mTaadWH1ap0ueivHd8x42Bnemcn+JutVr7GWmm2bU4zoBhjuv5QdXgALQnnT626lOQros7cCDf8PwCg==", + "caniuse-db": { + "version": "1.0.30000938", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000938.tgz", + "integrity": "sha512-1lbcoAGPQFUYOdY7sxpsl8ZDBfn5cyn80XuYnZwk7N4Qp7Behw7uxZCH5jjH2qWTV2WM6hgjvDVpP/uV3M/l9g==", "dev": true }, - "capture-exit": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-1.2.0.tgz", - "integrity": "sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28=", - "dev": true, - "requires": { - "rsvp": "^3.3.3" - } + "caniuse-lite": { + "version": "1.0.30000938", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000938.tgz", + "integrity": "sha512-ekW8NQ3/FvokviDxhdKLZZAx7PptXNwxKgXtnR5y+PR3hckwuP3yJ1Ir+4/c97dsHNqtAyfKUGdw8P4EYzBNgw==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true }, "catharsis": { "version": "0.8.9", @@ -1370,6 +2926,26 @@ "underscore-contrib": "~0.3.0" } }, + "ccount": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.3.tgz", + "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==", + "dev": true + }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } + }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", @@ -1379,34 +2955,106 @@ "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } } }, + "character-entities": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz", + "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==", + "dev": true + }, + "character-entities-html4": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.2.tgz", + "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==", + "dev": true + }, + "character-entities-legacy": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz", + "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==", + "dev": true + }, + "character-reference-invalid": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz", + "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==", + "dev": true + }, "chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "chokidar": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" + } + }, + "chrome-emulated-devices-list": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/chrome-emulated-devices-list/-/chrome-emulated-devices-list-0.1.1.tgz", + "integrity": "sha512-wQu6YKNTNGaUXovpkvXLnfeumVK47r2TKpOuCTwOKv/5SmRzfHual+E+oDIwS3KFWAcJPAhoNRAOLvXwzC6/pw==", + "dev": true + }, + "chrome-remote-interface": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/chrome-remote-interface/-/chrome-remote-interface-0.25.7.tgz", + "integrity": "sha512-6zI6LbR2IiGmduFZededaerEr9hHXabxT/L+fRrdq65a0CfyLMzpq0BKuZiqN0Upqcacsb6q2POj7fmobwBsEA==", + "dev": true, + "requires": { + "commander": "2.11.x", + "ws": "3.3.x" + }, + "dependencies": { + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "dev": true + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + } + } + }, + "ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "dev": true + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -1417,12 +3065,6 @@ "safe-buffer": "^5.0.1" } }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "dev": true - }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", @@ -1446,6 +3088,15 @@ } } }, + "clean-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", + "integrity": "sha1-jffHquUf02h06PjQW5GAvBGj/tc=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", @@ -1455,18 +3106,58 @@ "restore-cursor": "^2.0.0" } }, + "cli-table3": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", + "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", + "dev": true, + "requires": { + "colors": "^1.1.2", + "object-assign": "^4.1.0", + "string-width": "^2.1.1" + } + }, "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", "dev": true }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, "clone": { "version": "0.1.19", "resolved": "https://registry.npmjs.org/clone/-/clone-0.1.19.tgz", "integrity": "sha1-YT+2hjmyaklKxTJT4Vsaa9iK2oU=", "dev": true }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "coffeescript": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-2.3.2.tgz", + "integrity": "sha512-YObiFDoukx7qPBi/K0kUKyntEZDfBQiqs/DbrR1xzASKOBjGT7auD85/DiPeRr9k++lRj7l3uA9TNMLfyfcD/Q==", + "dev": true + }, + "collapse-white-space": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.4.tgz", + "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==", + "dev": true + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -1478,12 +3169,12 @@ } }, "color-convert": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { - "color-name": "^1.1.1" + "color-name": "1.1.3" } }, "color-name": { @@ -1493,9 +3184,36 @@ "dev": true }, "colors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.0.tgz", - "integrity": "sha512-EDpX3a7wHMWFA7PUHWPHNWqOxIIRSJetuwl0AS5Oi/5FMV8kWm69RTlgm00GKjBO1xFHMtBbL49yRtMMdticBw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.2.tgz", + "integrity": "sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ==", + "dev": true + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + }, + "comment-parser": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-0.5.4.tgz", + "integrity": "sha512-0h7W6Y1Kb6zKQMJqdX41C5qf9ITCVIsD2qP2RaqDF3GFkXFrmuAuv5zUOuo19YzyC9scjBNpqzuaRQ2Sy5pxMQ==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, "component-emitter": { @@ -1522,6 +3240,12 @@ "typedarray": "^0.0.6" } }, + "connected-domain": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/connected-domain/-/connected-domain-1.0.0.tgz", + "integrity": "sha1-v+dyOMdL5FOnnwy2BY3utPI1jpM=", + "dev": true + }, "contains-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", @@ -1529,10 +3253,13 @@ "dev": true }, "convert-source-map": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", - "dev": true + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } }, "copy-descriptor": { "version": "0.1.1", @@ -1541,9 +3268,9 @@ "dev": true }, "core-js": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.6.tgz", - "integrity": "sha512-lQUVfQi0aLix2xpyjrrJEvfuYCqPc/HwmTKsC/VNf8q0zsjX7SQZtp4+oRONN5Tsur9GDETPjj+Ub2iDiGZfSQ==", + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz", + "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==", "dev": true }, "core-util-is": { @@ -1564,7 +3291,7 @@ }, "create-hash": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dev": true, "requires": { @@ -1577,7 +3304,7 @@ }, "create-hmac": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dev": true, "requires": { @@ -1621,6 +3348,50 @@ "randomfill": "^1.0.3" } }, + "crypto-md5": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-md5/-/crypto-md5-1.0.0.tgz", + "integrity": "sha1-zMjadQx1PH7curxUKWdHKjhOhrs=", + "dev": true + }, + "css": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.3.tgz", + "integrity": "sha512-0W171WccAjQGGTKLhw4m2nnl0zPHUlTO/I8td4XzJgIB8Hg3ZZx71qT4G4eX8OVsSiaAKiUMy73E3nsbPlg2DQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "source-map": "^0.1.38", + "source-map-resolve": "^0.5.1", + "urix": "^0.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "cssom": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.6.tgz", + "integrity": "sha512-DtUeseGk9/GBW0hl0vVPpU22iHL6YB5BUX7ml1hB+GMpo0NX5G4voX3kdWiMSEguFtcW3Vh3djqNF4aIe6ne0A==", + "dev": true + }, + "cssstyle": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.2.1.tgz", + "integrity": "sha512-7DYm8qe+gPx/h77QlCyFmX80+fGaE/6A/Ekl0zaszYOubvySO2saYFdQ78P29D0UsULxFKCetDGNaNRUdSF+2A==", + "dev": true, + "requires": { + "cssom": "0.3.x" + } + }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -1630,13 +3401,33 @@ "array-find-index": "^1.0.1" } }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "requires": { - "ms": "2.0.0" + "assert-plus": "^1.0.0" + } + }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" } }, "decamelize": { @@ -1645,12 +3436,51 @@ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, + "decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + } + } + }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, + "dedent": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.4.0.tgz", + "integrity": "sha1-h979BAvUwVldljKC7FfzwqhSVkI=", + "dev": true + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -1666,6 +3496,15 @@ "abstract-leveldown": "~0.12.1" } }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", @@ -1708,20 +3547,54 @@ } }, "del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", + "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", "dev": true, "requires": { - "globby": "^5.0.0", + "globby": "^6.1.0", "is-path-cwd": "^1.0.0", "is-path-in-cwd": "^1.0.0", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", + "p-map": "^1.1.1", + "pify": "^3.0.0", "rimraf": "^2.2.8" + }, + "dependencies": { + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } } }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, "des.js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", @@ -1732,12 +3605,6 @@ "minimalistic-assert": "^1.0.0" } }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, "detect-indent": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", @@ -1755,7 +3622,7 @@ }, "diffie-hellman": { "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "dev": true, "requires": { @@ -1765,12 +3632,11 @@ } }, "dir-glob": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", - "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", "dev": true, "requires": { - "arrify": "^1.0.1", "path-type": "^3.0.0" }, "dependencies": { @@ -1792,24 +3658,49 @@ } }, "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "requires": { "esutils": "^2.0.2" } }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "requires": { + "webidl-conversions": "^4.0.2" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, "electron-to-chromium": { - "version": "1.3.48", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.48.tgz", - "integrity": "sha1-07DYWTgUBE4JLs4hCPw6ya6kuQA=", + "version": "1.3.113", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.113.tgz", + "integrity": "sha512-De+lPAxEcpxvqPTyZAXELNpRZXABRxf+uL/rSykstQhzj/B0l1150G/ExIIxKc16lI89Hgz81J0BHAcbTqK49g==", + "dev": true + }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", "dev": true }, "elliptic": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", - "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -1821,12 +3712,54 @@ "minimalistic-crypto-utils": "^1.0.0" } }, - "ensure-posix-path": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ensure-posix-path/-/ensure-posix-path-1.0.2.tgz", - "integrity": "sha1-pls+QtC3HPxYXrd0+ZQ8jZuRsMI=", + "emittery": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.4.1.tgz", + "integrity": "sha512-r4eRSeStEGf6M5SKdrQhhLK5bOwOBxQhIE3YSTnZE3GpKiLfnnhE+tPtrJE79+eDJgm39BM6LSoI8SCx4HbwlQ==", "dev": true }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "endpoint-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/endpoint-utils/-/endpoint-utils-1.0.2.tgz", + "integrity": "sha1-CAjDNppyfNeWejn/NOvJJriBRqg=", + "dev": true, + "requires": { + "ip": "^1.1.3", + "pinkie-promise": "^1.0.0" + }, + "dependencies": { + "pinkie": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-1.0.0.tgz", + "integrity": "sha1-Wkfyi6EBXQIBvae/DzWOR77Ix+Q=", + "dev": true + }, + "pinkie-promise": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-1.0.0.tgz", + "integrity": "sha1-0dpn9UglY7t89X8oauKCLs+/NnA=", + "dev": true, + "requires": { + "pinkie": "^1.0.0" + } + } + } + }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", @@ -1837,80 +3770,163 @@ } }, "error-ex": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "requires": { "is-arrayish": "^0.2.1" } }, + "error-stack-parser": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-1.3.6.tgz", + "integrity": "sha1-4Oc7k+QXE40c18C3RrGkoUhUwpI=", + "dev": true, + "requires": { + "stackframe": "^0.3.1" + } + }, + "es-abstract": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", + "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.1.1", + "function-bind": "^1.1.1", + "has": "^1.0.1", + "is-callable": "^1.1.3", + "is-regex": "^1.0.4" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, + "escodegen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", + "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", + "dev": true, + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, "eslint": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.5.0.tgz", - "integrity": "sha512-m+az4vYehIJgl1Z0gb25KnFXeqQRdNreYsei1jdvkd9bB+UNQD3fsuiC2AWSQ56P+/t++kFSINZXFbfai+krOw==", + "version": "5.14.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.14.1.tgz", + "integrity": "sha512-CyUMbmsjxedx8B0mr79mNOqetvkbij/zrXnFeK2zc3pGRn3/tibjiNAv/3UxFEyfMDjh+ZqTrJrEGBFiGfD5Og==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "ajv": "^6.5.3", + "ajv": "^6.9.1", "chalk": "^2.1.0", "cross-spawn": "^6.0.5", - "debug": "^3.1.0", - "doctrine": "^2.1.0", + "debug": "^4.0.1", + "doctrine": "^3.0.0", "eslint-scope": "^4.0.0", "eslint-utils": "^1.3.1", "eslint-visitor-keys": "^1.0.0", - "espree": "^4.0.0", + "espree": "^5.0.1", "esquery": "^1.0.1", "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", + "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", "glob": "^7.1.2", "globals": "^11.7.0", "ignore": "^4.0.6", + "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^6.1.0", - "is-resolvable": "^1.1.0", + "inquirer": "^6.2.2", "js-yaml": "^3.12.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.3.0", - "lodash": "^4.17.5", + "lodash": "^4.17.11", "minimatch": "^3.0.4", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", "optionator": "^0.8.2", "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", "progress": "^2.0.0", - "regexpp": "^2.0.0", - "require-uncached": "^1.0.3", + "regexpp": "^2.0.1", "semver": "^5.5.1", "strip-ansi": "^4.0.0", "strip-json-comments": "^2.0.1", - "table": "^4.0.3", + "table": "^5.2.3", "text-table": "^0.2.0" }, "dependencies": { - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", - "dev": true + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } } } }, + "eslint-ast-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-ast-utils/-/eslint-ast-utils-1.1.0.tgz", + "integrity": "sha512-otzzTim2/1+lVrlH19EfQQJEhVJSu0zOb9ygb3iapN6UlyaDtyRq4b5U1FuW0v1lRa9Fp/GJyHkSwm6NqABgCA==", + "dev": true, + "requires": { + "lodash.get": "^4.4.2", + "lodash.zip": "^4.2.0" + } + }, + "eslint-config-airbnb-base": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-13.1.0.tgz", + "integrity": "sha512-XWwQtf3U3zIoKO1BbHh6aUhJZQweOwSt4c2JrPDg9FP3Ltv3+YfEv7jIDB8275tVnO/qOHbfuYg3kzw6Je7uWw==", + "dev": true, + "requires": { + "eslint-restricted-globals": "^0.1.1", + "object.assign": "^4.1.0", + "object.entries": "^1.0.4" + } + }, + "eslint-config-ash-nazg": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/eslint-config-ash-nazg/-/eslint-config-ash-nazg-0.4.4.tgz", + "integrity": "sha512-3jwgLaDwfAxMd9Zh1mw3LP5PZUa4H8MqAYQjlOaHV5gWKeh+zZsTNTT2ktpVTkEHqxggf69a2Dd6MtliQTzvLA==", + "dev": true + }, "eslint-config-standard": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-12.0.0.tgz", @@ -1935,17 +3951,23 @@ "requires": { "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, "eslint-module-utils": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", - "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.3.0.tgz", + "integrity": "sha512-lmDJgeOOjk8hObTysjqH7wyMi+nsHwwvfBykwfhjR1LNdd7C2uFJBvx4OpWYpXOw4df1yE1cDEVd1yLHitk34w==", "dev": true, "requires": { "debug": "^2.6.8", - "pkg-dir": "^1.0.0" + "pkg-dir": "^2.0.0" }, "dependencies": { "debug": { @@ -1956,35 +3978,77 @@ "requires": { "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, + "eslint-plugin-compat": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-2.7.0.tgz", + "integrity": "sha512-3J4Ic1WS+SgF1smUOc62fdf7Cnrdsg0GNwKmGVPziPtWdrc2vV5Oq2ut4kG6SM5DJcxOoz/sWJIN7rkcsWh60Q==", + "dev": true, + "requires": { + "@babel/runtime": "^7.3.1", + "browserslist": "^4.4.1", + "caniuse-db": "^1.0.30000935", + "mdn-browser-compat-data": "^0.0.65" + } + }, "eslint-plugin-es": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-1.3.1.tgz", - "integrity": "sha512-9XcVyZiQRVeFjqHw8qHNDAZcQLqaHlOGGpeYqzYh8S4JYCWTCO3yzyen8yVmA5PratfzTRWDwCOFphtDEG+w/w==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-1.4.0.tgz", + "integrity": "sha512-XfFmgFdIUDgvaRAlaXUkxrRg5JSADoRC8IkKLc/cISeR3yHVMefFHQZpcyXXEUUPHfy5DwviBcrfqlyqEwlQVw==", "dev": true, "requires": { "eslint-utils": "^1.3.0", - "regexpp": "^2.0.0" + "regexpp": "^2.0.1" } }, + "eslint-plugin-eslint-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.1.1.tgz", + "integrity": "sha512-GZDKhOFqJLKlaABX+kdoLskcTINMrVOWxGca54KcFb1QCPd0CLmqgAMRxkkUfGSmN+5NJUMGh7NGccIMcWPSfQ==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "ignore": "^5.0.5" + }, + "dependencies": { + "ignore": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.0.5.tgz", + "integrity": "sha512-kOC8IUb8HSDMVcYrDVezCxpJkzSQWTAzf3olpKM6o9rM5zpojx23O0Fl8Wr4+qJ6ZbPEHqf1fdwev/DS7v7pmA==", + "dev": true + } + } + }, + "eslint-plugin-eslint-plugin": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-plugin/-/eslint-plugin-eslint-plugin-2.0.1.tgz", + "integrity": "sha512-kJ5TZsRJH/xYstG07v3YeOy/W5SDAEzV+bvvoL0aiG1HtqDmg4mJvNPnn/JngANMmsx8oXlJrIcBTCpJzm+9kg==", + "dev": true + }, "eslint-plugin-import": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz", - "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.16.0.tgz", + "integrity": "sha512-z6oqWlf1x5GkHIFgrSvtmudnqM6Q60KM4KvpWi5ubonMjycLjndvd5+8VAZIsTlHC03djdgJuyKG6XO577px6A==", "dev": true, "requires": { "contains-path": "^0.1.0", - "debug": "^2.6.8", + "debug": "^2.6.9", "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.1", - "eslint-module-utils": "^2.2.0", - "has": "^1.0.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.3", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.3.0", + "has": "^1.0.3", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", "read-pkg-up": "^2.0.0", - "resolve": "^1.6.0" + "resolve": "^1.9.0" }, "dependencies": { "debug": { @@ -2005,41 +4069,150 @@ "esutils": "^2.0.2", "isarray": "^1.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "resolve": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } } } }, + "eslint-plugin-jsdoc": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-4.1.0.tgz", + "integrity": "sha512-XNyl+G2ZtmKXNn/MDGsDVQwgkM81i/hDLwVPc7CPMHrob/0Po0vzKNOvxwIoluBhhigCssvYUg7hg2gN0N2vgw==", + "dev": true, + "requires": { + "comment-parser": "^0.5.1", + "jsdoctypeparser": "^2.0.0-alpha-8", + "lodash": "^4.17.11" + } + }, + "eslint-plugin-markdown": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-markdown/-/eslint-plugin-markdown-1.0.0.tgz", + "integrity": "sha512-YIrClt3yLgyGov+rInjIoC/05zMxb/c6YXQZkyI9UKuBRFLgCrL37cxthj0JYWiTYtiHq0p8O0Nt0/HrvO48iQ==", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "remark-parse": "^5.0.0", + "unified": "^6.1.2" + }, + "dependencies": { + "remark-parse": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", + "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", + "dev": true, + "requires": { + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^1.1.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^1.0.0", + "vfile-location": "^2.0.0", + "xtend": "^4.0.1" + } + }, + "unified": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", + "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", + "dev": true, + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^1.1.0", + "trough": "^1.0.0", + "vfile": "^2.0.0", + "x-is-string": "^0.1.0" + } + }, + "vfile": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", + "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", + "dev": true, + "requires": { + "is-buffer": "^1.1.4", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "^1.0.0", + "vfile-message": "^1.0.0" + } + } + } + }, + "eslint-plugin-no-use-extend-native": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-no-use-extend-native/-/eslint-plugin-no-use-extend-native-0.4.0.tgz", + "integrity": "sha512-9W2747CwC7aTJknLKY6ftdzj3AZz8DSaa64zONOMIemxH7YRr0+hqrvsNtHK/v9DusPuMxM9y9hBnfHwzKFmww==", + "dev": true, + "requires": { + "is-get-set-prop": "^1.0.0", + "is-js-type": "^2.0.0", + "is-obj-prop": "^1.0.0", + "is-proto-prop": "^2.0.0" + } + }, "eslint-plugin-node": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-7.0.1.tgz", - "integrity": "sha512-lfVw3TEqThwq0j2Ba/Ckn2ABdwmL5dkOgAux1rvOk6CO7A6yGyPI2+zIxN6FyNkp1X1X/BSvKOceD6mBWSj4Yw==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-8.0.1.tgz", + "integrity": "sha512-ZjOjbjEi6jd82rIpFSgagv4CHWzG9xsQAVp1ZPlhRnnYxcTgENUVBvhYmkQ7GvT1QFijUSo69RaiOJKhMu6i8w==", "dev": true, "requires": { "eslint-plugin-es": "^1.3.1", "eslint-utils": "^1.3.1", - "ignore": "^4.0.2", + "ignore": "^5.0.2", "minimatch": "^3.0.4", "resolve": "^1.8.1", "semver": "^5.5.0" }, "dependencies": { "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.0.5.tgz", + "integrity": "sha512-kOC8IUb8HSDMVcYrDVezCxpJkzSQWTAzf3olpKM6o9rM5zpojx23O0Fl8Wr4+qJ6ZbPEHqf1fdwev/DS7v7pmA==", "dev": true } } }, + "eslint-plugin-prettier": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.0.1.tgz", + "integrity": "sha512-/PMttrarPAY78PLvV3xfWibMOdMDl57hmlQ2XqFeA37wd+CJ7WSxV7txqjVPHi/AAFKd2lX0ZqfsOc/i5yFCSQ==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, "eslint-plugin-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.0.0.tgz", - "integrity": "sha512-3on8creJifkmNHvT425jCWSuVK0DG0Quf3H75ENZFqvHl6/s2xme8z6bfxww13XwqfELYWKxc/N3AtBXyV1hdg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.0.1.tgz", + "integrity": "sha512-Si16O0+Hqz1gDHsys6RtFRrW7cCTB6P7p3OJmKp3Y3dxpQE2qwOA7d3xnV+0mBmrPoi0RBnxlCKvqu70te6wjg==", "dev": true }, "eslint-plugin-qunit": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-qunit/-/eslint-plugin-qunit-3.3.1.tgz", - "integrity": "sha512-entAEwuXE1GU9NaOAJkufuDszOmGWDnNvmY7AP64GZFB55mg2UivCz6//UKFVjvtjQRYW37OLIoIks4ajG4BRA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-qunit/-/eslint-plugin-qunit-4.0.0.tgz", + "integrity": "sha512-+0i2xcYryUoLawi47Lp0iJKzkP931G5GXwIOq1KBKQc2pknV1VPjfE6b4mI2mR2RnL7WRoS30YjwC9SjQgJDXQ==", "dev": true }, "eslint-plugin-standard": { @@ -2048,6 +4221,101 @@ "integrity": "sha512-OwxJkR6TQiYMmt1EsNRMe5qG3GsbjlcOhbGUBY4LtavF9DsLaTcoR+j2Tdjqi23oUwKNUqX7qcn5fPStafMdlA==", "dev": true }, + "eslint-plugin-testcafe": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-testcafe/-/eslint-plugin-testcafe-0.2.1.tgz", + "integrity": "sha1-QIn2RtrbabE3agHX5ggYSQfmA2s=", + "dev": true + }, + "eslint-plugin-unicorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-7.1.0.tgz", + "integrity": "sha512-lW/ZwGR638V0XuZgR160qVQvPtw8tw3laKT5LjJPt+W+tN7kVf2S2V7x+ZrEEwSjEb3OiEzb3cppzaKuYtgYeg==", + "dev": true, + "requires": { + "clean-regexp": "^1.0.0", + "eslint-ast-utils": "^1.0.0", + "import-modules": "^1.1.0", + "lodash.camelcase": "^4.1.1", + "lodash.kebabcase": "^4.0.1", + "lodash.snakecase": "^4.0.1", + "lodash.upperfirst": "^4.2.0", + "safe-regex": "^2.0.1" + }, + "dependencies": { + "regexp-tree": { + "version": "0.0.86", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.0.86.tgz", + "integrity": "sha512-xjTX9GmRw7Nn2wxinLoqQXv9Dt5yerP7CJIsYe/5z5gFs0Ltu20wRuZophafi9sf0JpsdVtki5EuICRYpgB1AQ==", + "dev": true, + "requires": { + "cli-table3": "^0.5.0", + "colors": "^1.1.2", + "yargs": "^10.0.3" + } + }, + "safe-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.0.1.tgz", + "integrity": "sha512-4tbOl0xq/cxbhEhdvxKaCZgzwOKeqt2tnHc2OPBkMsVdZ0s0C5oJwI6voRI9XzPSzeN35PECDNDK946x4d/0eA==", + "dev": true, + "requires": { + "regexp-tree": "~0.0.85" + } + } + } + }, + "eslint-plugin-vue": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-5.1.0.tgz", + "integrity": "sha512-C7avvbGLb9J1PyGiFolPcGR4ljUc+dKm5ZJdrUKXwXFxHHx4SqOmRI29AsFyW7PbCGcnOvIlaq7NJS6HDIak+g==", + "dev": true, + "requires": { + "vue-eslint-parser": "^4.0.2" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "espree": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz", + "integrity": "sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w==", + "dev": true, + "requires": { + "acorn": "^6.0.2", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "vue-eslint-parser": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-4.0.3.tgz", + "integrity": "sha512-AUeQsYdO6+7QXCems+WvGlrXd37PHv/zcRQSQdY1xdOMwdFAPEnMBsv7zPvk0TPGulXkK/5p/ITgrjiYB7k3ag==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "eslint-scope": "^4.0.0", + "eslint-visitor-keys": "^1.0.0", + "espree": "^4.1.0", + "esquery": "^1.0.1", + "lodash": "^4.17.11" + } + } + } + }, + "eslint-restricted-globals": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz", + "integrity": "sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc=", + "dev": true + }, "eslint-scope": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", @@ -2070,14 +4338,21 @@ "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", "dev": true }, + "esotope-hammerhead": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/esotope-hammerhead/-/esotope-hammerhead-0.1.0.tgz", + "integrity": "sha512-vOruOE2tIa6C6iDzz4A3bo8e2DQPEJY3ieTcMXykze8I9pL8Ae8/0XnVGfWImhuFMTpXdteBM/z7pCCeE/ygow==", + "dev": true + }, "espree": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-4.0.0.tgz", - "integrity": "sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", "dev": true, "requires": { - "acorn": "^5.6.0", - "acorn-jsx": "^4.1.1" + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" } }, "esprima": { @@ -2132,22 +4407,13 @@ "safe-buffer": "^5.1.1" } }, - "exec-sh": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.2.tgz", - "integrity": "sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==", - "dev": true, - "requires": { - "merge": "^1.2.0" - } - }, "execa": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", - "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", "dev": true, "requires": { - "cross-spawn": "^6.0.0", + "cross-spawn": "^5.0.1", "get-stream": "^3.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", @@ -2157,26 +4423,18 @@ }, "dependencies": { "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", + "lru-cache": "^4.0.1", "shebang-command": "^1.2.0", "which": "^1.2.9" } } } }, - "exists-stat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/exists-stat/-/exists-stat-1.0.0.tgz", - "integrity": "sha1-BmDjUlouidnkRhKUQMJy7foktSk=", - "dev": true - }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -2218,6 +4476,12 @@ "requires": { "is-extendable": "^0.1.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -2272,14 +4536,11 @@ } } }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true }, "extend-shallow": { "version": "3.0.2", @@ -2378,23 +4639,35 @@ } } }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", "dev": true }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, "fast-glob": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.2.tgz", - "integrity": "sha512-TR6zxCKftDQnUAPvkrCWdBgDq/gbqx8A3ApnBrR5rMvpp6+KMJI0Igw7fkWPgeVK0uhRXTXdvO3O+YP0CaUX2g==", + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.6.tgz", + "integrity": "sha512-0BvMaZc1k9F+MeWWMe8pL6YltFzZYcJsYU7D4JyDA6PAczaXvxqQQ/z+mDF7/4Mw01DeUc+i3CTKajnkANkV4w==", "dev": true, "requires": { "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.0.1", + "@nodelib/fs.stat": "^1.1.2", "glob-parent": "^3.1.0", "is-glob": "^4.0.0", - "merge2": "^1.2.1", + "merge2": "^1.2.3", "micromatch": "^3.1.10" } }, @@ -2410,13 +4683,13 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, - "fb-watchman": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", - "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=", + "fault": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.2.tgz", + "integrity": "sha512-o2eo/X2syzzERAtN5LcGbiVQ0WwZSlN3qLtadwAz3X8Bu+XWD16dja/KMsjZLiQr+BLGPDnHGkc4yUJf1Xpkpw==", "dev": true, "requires": { - "bser": "^2.0.0" + "format": "^0.2.2" } }, "figures": { @@ -2429,19 +4702,18 @@ } }, "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", "dev": true, "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" + "flat-cache": "^2.0.1" } }, "file-type": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", - "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-10.4.0.tgz", + "integrity": "sha512-/Ha0T7TRFOFKgj36icy46h93By2tTwHirW9qeNLslo5NYmd7BbITVv2tkcuohmZWsNLqg9/dKNKwRXF3OVgVdA==", "dev": true }, "filename-regex": { @@ -2482,6 +4754,17 @@ "traverse-chain": "~0.1.0" } }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^2.0.0" + } + }, "find-in-files": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/find-in-files/-/find-in-files-0.5.0.tgz", @@ -2493,50 +4776,37 @@ } }, "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } + "locate-path": "^2.0.0" } }, "flat-cache": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", - "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", "dev": true, "requires": { - "circular-json": "^0.3.1", - "del": "^2.0.2", - "graceful-fs": "^4.1.2", - "write": "^0.2.1" + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" } }, + "flatted": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", + "dev": true + }, + "fn-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fn-name/-/fn-name-2.0.1.tgz", + "integrity": "sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc=", + "dev": true + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -2558,6 +4828,29 @@ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", "dev": true }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=", + "dev": true + }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -2568,9 +4861,9 @@ } }, "fs-extra": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz", - "integrity": "sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, "requires": { "graceful-fs": "^4.1.2", @@ -3142,7 +5435,7 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { @@ -3160,10 +5453,28 @@ } } }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "get-set-props": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-set-props/-/get-set-props-0.1.0.tgz", + "integrity": "sha1-mYR1wXhEVobQsyJG2l3428++jqM=", + "dev": true + }, "get-stdin": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", - "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", "dev": true }, "get-stream": { @@ -3178,10 +5489,19 @@ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -3255,56 +5575,77 @@ "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", "dev": true }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, "globals": { - "version": "11.7.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", - "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==", + "version": "11.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.8.0.tgz", + "integrity": "sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA==", "dev": true }, "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-9.0.0.tgz", + "integrity": "sha512-q0qiO/p1w/yJ0hk8V9x1UXlgsXUxlGd0AHUOXZVXBO6aznDtpx7M8D1kBrCAItoPm+4l8r6ATXV1JpjY2SBQOw==", "dev": true, "requires": { - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "array-union": "^1.0.2", + "dir-glob": "^2.2.1", + "fast-glob": "^2.2.6", + "glob": "^7.1.3", + "ignore": "^4.0.3", + "pify": "^4.0.1", + "slash": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } } }, "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.14.tgz", + "integrity": "sha512-ns/IGcSmmGNPP085JCheg0Nombh1QPvSCnlx+2V+byQWRQEIL4ZB5jXJMNIHOFVS1roi85HIi5Ka0h43iWXfcQ==", "dev": true }, + "graphlib": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.7.tgz", + "integrity": "sha512-TyI9jIy2J4j0qgPmOOrHTCtpPqJGN/aurBwc6ZT+bRii+di1I+Wv3obRhVrmBEXet+qkMaEX67dXrwsd3QQM6w==", + "dev": true, + "requires": { + "lodash": "^4.17.5" + } + }, + "gulp-data": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/gulp-data/-/gulp-data-1.3.1.tgz", + "integrity": "sha512-fvpQJvgVyhkwRcFP3Y9QUS9sWvIFsAlJDinQjhLuknmHZz52jH0gHmTujYBFjr9aTlTHlrAayY5m1d0tA1HzGQ==", + "dev": true, + "requires": { + "plugin-error": "^0.1.2", + "through2": "^2.0.0", + "util-extend": "^1.0.1" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -3321,6 +5662,14 @@ "dev": true, "requires": { "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } } }, "has-flag": { @@ -3329,6 +5678,12 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -3372,13 +5727,32 @@ } }, "hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", + "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", "dev": true, "requires": { "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" + "minimalistic-assert": "^1.0.1" + } + }, + "highlight-es": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/highlight-es/-/highlight-es-1.0.3.tgz", + "integrity": "sha512-s/SIX6yp/5S1p8aC/NRDC1fwEb+myGIfp8/TzZz0rtAv8fzsdX7vGl3Q1TrXCsczFq8DI3CBFBCySPClfBSdbg==", + "dev": true, + "requires": { + "chalk": "^2.4.0", + "is-es2016-keyword": "^1.0.0", + "js-tokens": "^3.0.0" + }, + "dependencies": { + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + } } }, "hmac-drbg": { @@ -3393,14 +5767,10 @@ } }, "home-or-tmp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", - "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-3.0.0.tgz", + "integrity": "sha1-V6j+JM8zzdUkhgoVgh3cJchmcfs=", + "dev": true }, "homedir-polyfill": { "version": "1.0.1", @@ -3412,11 +5782,31 @@ } }, "hosted-git-info": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", - "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -3433,58 +5823,84 @@ "dev": true }, "ignore": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.8.tgz", - "integrity": "sha512-pUh+xUQQhQzevjRHHFqqcTy0/dP/kS9I8HSrUydhihjuD09W6ldVWFtIrwhXdUJHis3i2rZNqEHpZH/cbinFbg==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, "imageoptim-cli": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/imageoptim-cli/-/imageoptim-cli-2.0.3.tgz", - "integrity": "sha512-QJZ8H6EOF7oV8sknqqfal42nAOtFtmy4pbKD5rfPriltZ1aLkCK2wI+z2G56pvHtIQI/5sBowUNSPWqR2yb5Bw==", + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/imageoptim-cli/-/imageoptim-cli-2.3.5.tgz", + "integrity": "sha512-TXbvGZJAH5F+ZqGhfWl92+LnYqKdyE5k249GjwwD61KcLG1R+Or5DhXm9pDJ9kM1u7ES3exlnj9ooZP+/cuLVg==", "dev": true, "requires": { - "@types/execa": "0.9.0", - "@types/fs-extra": "5.0.3", - "@types/globby": "6.1.0", - "@types/node": "10.3.2", - "chalk": "2.4.1", - "commander": "2.15.1", - "execa": "0.10.0", - "fs-extra": "6.0.1", - "globby": "8.0.1", + "chalk": "2.4.2", + "commander": "2.19.0", + "execa": "1.0.0", + "fs-extra": "7.0.1", + "globby": "9.0.0", "pretty-bytes": "5.1.0" }, "dependencies": { - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "globby": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.1.tgz", - "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==", + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { - "array-union": "^1.0.1", - "dir-glob": "^2.0.0", - "fast-glob": "^2.0.2", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } } } }, + "import-fresh": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz", + "integrity": "sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-lazy": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-3.1.0.tgz", + "integrity": "sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ==", + "dev": true + }, + "import-modules": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/import-modules/-/import-modules-1.1.0.tgz", + "integrity": "sha1-dI23nFzEK7lwHvq0JPiU5yYA6dw=", + "dev": true + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -3492,13 +5908,10 @@ "dev": true }, "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true }, "indexof": { "version": "0.0.1", @@ -3529,24 +5942,52 @@ "dev": true }, "inquirer": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz", - "integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.2.tgz", + "integrity": "sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", "cli-cursor": "^2.1.0", "cli-width": "^2.0.0", - "external-editor": "^3.0.0", + "external-editor": "^3.0.3", "figures": "^2.0.0", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "mute-stream": "0.0.7", "run-async": "^2.2.0", - "rxjs": "^6.1.0", + "rxjs": "^6.4.0", "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", + "strip-ansi": "^5.0.0", "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", + "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "strip-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", + "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", + "dev": true, + "requires": { + "ansi-regex": "^4.0.0" + } + } } }, "invariant": { @@ -3558,9 +5999,21 @@ "loose-envify": "^1.0.0" } }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, "is": { "version": "0.2.7", - "resolved": "https://registry.npmjs.org/is/-/is-0.2.7.tgz", + "resolved": "http://registry.npmjs.org/is/-/is-0.2.7.tgz", "integrity": "sha1-OzSixI81mXLzUEKEkZOucmS2NWI=", "dev": true }, @@ -3584,12 +6037,43 @@ } } }, + "is-alphabetical": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.2.tgz", + "integrity": "sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg==", + "dev": true + }, + "is-alphanumeric": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", + "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=", + "dev": true + }, + "is-alphanumerical": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz", + "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==", + "dev": true, + "requires": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + } + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -3598,13 +6082,28 @@ }, "is-builtin-module": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { "builtin-modules": "^1.0.0" } }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-ci": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", + "dev": true, + "requires": { + "ci-info": "^1.5.0" + } + }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -3625,6 +6124,18 @@ } } }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-decimal": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.2.tgz", + "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==", + "dev": true + }, "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", @@ -3650,6 +6161,12 @@ "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", "dev": true }, + "is-empty": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-empty/-/is-empty-1.2.0.tgz", + "integrity": "sha1-3pu1snhzigWgsJpX4ftNSjQan2s=", + "dev": true + }, "is-equal-shallow": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", @@ -3659,6 +6176,12 @@ "is-primitive": "^2.0.0" } }, + "is-es2016-keyword": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-es2016-keyword/-/is-es2016-keyword-1.0.0.tgz", + "integrity": "sha1-9uVOEQxeT40mXmnS7Q6vjPX0dxg=", + "dev": true + }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -3686,6 +6209,16 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, + "is-get-set-prop": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-get-set-prop/-/is-get-set-prop-1.0.0.tgz", + "integrity": "sha1-JzGHfk14pqae3M5rudaLB3nnYxI=", + "dev": true, + "requires": { + "get-set-props": "^0.1.0", + "lowercase-keys": "^1.0.0" + } + }, "is-glob": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", @@ -3695,6 +6228,33 @@ "is-extglob": "^2.1.1" } }, + "is-hexadecimal": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz", + "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==", + "dev": true + }, + "is-hidden": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-hidden/-/is-hidden-1.1.1.tgz", + "integrity": "sha512-175UKecS8+U4hh2PSY0j4xnm2GKYzvSKnbh+naC93JjuBA7LgIo6YxlbcsSo6seFBdQO3RuIcH980yvqqD/2cA==", + "dev": true + }, + "is-jquery-obj": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-jquery-obj/-/is-jquery-obj-0.1.1.tgz", + "integrity": "sha512-18toSebUVF7y717dgw/Dzn6djOCqrkiDp3MhB8P6TdKyCVkbD1ZwE7Uz8Hwx6hUPTvKjbyYH9ncXT4ts4qLaSA==", + "dev": true + }, + "is-js-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-js-type/-/is-js-type-2.0.0.tgz", + "integrity": "sha1-c2FwBtZZtOtHKbunR9KHgt8PfiI=", + "dev": true, + "requires": { + "js-types": "^1.0.0" + } + }, "is-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", @@ -3721,29 +6281,22 @@ } } }, - "is-object": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-0.1.2.tgz", - "integrity": "sha1-AO+8CIFsM8/ErIJR0TLhDcZQmNc=", - "dev": true - }, - "is-odd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", - "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", + "is-obj-prop": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-obj-prop/-/is-obj-prop-1.0.0.tgz", + "integrity": "sha1-s03nnEULjXxzqyzfZ9yHWtuF+A4=", "dev": true, "requires": { - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } + "lowercase-keys": "^1.0.0", + "obj-props": "^1.0.0" } }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", + "dev": true + }, "is-path-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", @@ -3768,6 +6321,12 @@ "path-is-inside": "^1.0.1" } }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -3795,11 +6354,24 @@ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true + "is-proto-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-proto-prop/-/is-proto-prop-2.0.0.tgz", + "integrity": "sha512-jl3NbQ/fGLv5Jhan4uX+Ge9ohnemqyblWVVCpAvtTQzNFvV2xhJq+esnkIbYQ9F1nITXoLfDDQLp7LBw/zzncg==", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0", + "proto-props": "^2.0.0" + } + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } }, "is-stream": { "version": "1.1.0", @@ -3807,18 +6379,51 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, + "is-whitespace-character": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz", + "integrity": "sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ==", + "dev": true + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, + "is-word-character": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.2.tgz", + "integrity": "sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -3843,15 +6448,49 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, - "jest-worker": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-23.2.0.tgz", - "integrity": "sha1-+vcGqNo2+uYOsmlXJX+ntdjqArk=", + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "jamilih": { + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/jamilih/-/jamilih-0.44.0.tgz", + "integrity": "sha512-MiYNr9CqA3ynQVVt61cl+SEAffOP0/Pz0AJDsDXTQCQOZ4oarD/T0OhcGIl19LSXO1bMsJyEWqqw9R8ipH/Ggw==", "dev": true, "requires": { - "merge-stream": "^1.0.1" + "@babel/polyfill": "^7.0.0", + "jsdom": "13.0.0" } }, + "jest-worker": { + "version": "24.0.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.0.0.tgz", + "integrity": "sha512-s64/OThpfQvoCeHG963MiEZOAAxu8kHsaL/rCMF7lpdzo7vgF0CtPml9hfguOMgykgH/eOm4jFP4ibfHLruytg==", + "dev": true, + "requires": { + "merge-stream": "^1.0.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "dev": true + }, "js-reporters": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/js-reporters/-/js-reporters-1.2.1.tgz", @@ -3859,9 +6498,15 @@ "dev": true }, "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-types": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/js-types/-/js-types-1.0.0.tgz", + "integrity": "sha1-0kLmSU7Vcq08koCfyL7X92h8vwM=", "dev": true }, "js-yaml": { @@ -3883,6 +6528,12 @@ "xmlcreate": "^1.0.1" } }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, "jsdoc": { "version": "3.5.5", "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.5.tgz", @@ -3901,20 +6552,70 @@ "strip-json-comments": "~2.0.1", "taffydb": "2.6.2", "underscore": "~1.8.3" - }, - "dependencies": { - "babylon": { - "version": "7.0.0-beta.19", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz", - "integrity": "sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A==", - "dev": true - } + } + }, + "jsdoctypeparser": { + "version": "2.0.0-alpha-8", + "resolved": "https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-2.0.0-alpha-8.tgz", + "integrity": "sha1-uvE3+44qVYgQrc8Z0tKi9oDpCl8=", + "dev": true + }, + "jsdom": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-13.0.0.tgz", + "integrity": "sha512-Kmq4ASMNkgpY+YufE322EnIKoiz0UWY2DRkKlU7d5YrIW4xiVRhWFrZV1fr6w/ZNxQ50wGAH5gGRzydgnmkkvw==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "acorn": "^6.0.2", + "acorn-globals": "^4.3.0", + "array-equal": "^1.0.0", + "cssom": "^0.3.4", + "cssstyle": "^1.1.1", + "data-urls": "^1.0.1", + "domexception": "^1.0.1", + "escodegen": "^1.11.0", + "html-encoding-sniffer": "^1.0.2", + "nwsapi": "^2.0.9", + "parse5": "5.1.0", + "pn": "^1.1.0", + "request": "^2.88.0", + "request-promise-native": "^1.0.5", + "saxes": "^3.1.3", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.4.3", + "w3c-hr-time": "^1.0.1", + "w3c-xmlserializer": "^1.0.0", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0", + "ws": "^6.1.0", + "xml-name-validator": "^3.0.0" } }, "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz", + "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=", + "dev": true + }, + "json-hammerhead": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/json-hammerhead/-/json-hammerhead-0.1.0.tgz", + "integrity": "sha512-yzhX0+ozvTYDrD6Itf3sRRThqMd+5USJlCcOlfSwimdkVIWH6aSRDSlV44A27DrXLkp0E5gCq7NPFWvVbJC4CQ==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", "dev": true }, "json-schema-traverse": { @@ -3929,12 +6630,29 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, + "json5": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -3944,10 +6662,22 @@ "graceful-fs": "^4.1.6" } }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, "just-extend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-3.0.0.tgz", - "integrity": "sha512-Fu3T6pKBuxjWT/p4DkqGHFRsysc8OauWr4ZRTY9dIx07Y9O0RkoR5jcv28aeD1vuAwhm3nLkDurwLXoALp4DpQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", + "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", "dev": true }, "kind-of": { @@ -3965,6 +6695,15 @@ "graceful-fs": "^4.1.9" } }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, "level-blobs": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/level-blobs/-/level-blobs-0.1.7.tgz", @@ -3984,7 +6723,7 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { @@ -4017,17 +6756,25 @@ "octal": "^1.0.0", "once": "^1.3.0", "xtend": "^2.2.0" + }, + "dependencies": { + "xtend": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.2.0.tgz", + "integrity": "sha1-7vax8ZjByN6vrYsXZaBNrUoBxak=", + "dev": true + } } }, "level-fix-range": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/level-fix-range/-/level-fix-range-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/level-fix-range/-/level-fix-range-1.0.2.tgz", "integrity": "sha1-vxW5Fa422EcMgh6IPd95zRZCCCg=", "dev": true }, "level-hooks": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/level-hooks/-/level-hooks-4.5.0.tgz", + "resolved": "http://registry.npmjs.org/level-hooks/-/level-hooks-4.5.0.tgz", "integrity": "sha1-G5rmGSKTDzMF0aYfxNg8gQLA3ZM=", "dev": true, "requires": { @@ -4067,7 +6814,7 @@ }, "level-peek": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/level-peek/-/level-peek-1.0.6.tgz", + "resolved": "http://registry.npmjs.org/level-peek/-/level-peek-1.0.6.tgz", "integrity": "sha1-vsUccqgu5GTTNkNMfIdsP8vM538=", "dev": true, "requires": { @@ -4076,7 +6823,7 @@ }, "level-sublevel": { "version": "5.2.3", - "resolved": "https://registry.npmjs.org/level-sublevel/-/level-sublevel-5.2.3.tgz", + "resolved": "http://registry.npmjs.org/level-sublevel/-/level-sublevel-5.2.3.tgz", "integrity": "sha1-dEwSxy0ucr543eO5tc2E1iGRQTo=", "dev": true, "requires": { @@ -4086,15 +6833,32 @@ "xtend": "~2.0.4" }, "dependencies": { + "is-object": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-0.1.2.tgz", + "integrity": "sha1-AO+8CIFsM8/ErIJR0TLhDcZQmNc=", + "dev": true + }, "level-fix-range": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/level-fix-range/-/level-fix-range-2.0.0.tgz", + "resolved": "http://registry.npmjs.org/level-fix-range/-/level-fix-range-2.0.0.tgz", "integrity": "sha1-xBfWIVlEIVGhnZojZ4aPFyTC1Ug=", "dev": true, "requires": { "clone": "~0.1.9" } }, + "object-keys": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.2.0.tgz", + "integrity": "sha1-zd7AKZiwkb5CvxA1rjLknxy26mc=", + "dev": true, + "requires": { + "foreach": "~2.0.1", + "indexof": "~0.0.1", + "is": "~0.2.6" + } + }, "xtend": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.0.6.tgz", @@ -4136,7 +6900,7 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { @@ -4148,7 +6912,7 @@ }, "semver": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-2.3.2.tgz", + "resolved": "http://registry.npmjs.org/semver/-/semver-2.3.2.tgz", "integrity": "sha1-uYSPJdbPNjMwc+ye+IVtQvEjPlI=", "dev": true }, @@ -4176,9 +6940,18 @@ "type-check": "~0.3.2" } }, + "linux-platform-info": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/linux-platform-info/-/linux-platform-info-0.0.3.tgz", + "integrity": "sha1-La4yQ4Xmbj11W+yD+Gx77qYc64M=", + "dev": true, + "requires": { + "os-family": "^1.0.0" + } + }, "load-json-file": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "dev": true, "requires": { @@ -4188,6 +6961,24 @@ "strip-bom": "^3.0.0" } }, + "load-plugin": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/load-plugin/-/load-plugin-2.2.2.tgz", + "integrity": "sha512-FYzamtURIJefQykZGtiClYuZkJBUKzmx8Tc74y8JGAulDzbzVm/C+w/MbAljHRr+REL0cRzy3WgnHE+T8gce5g==", + "dev": true, + "requires": { + "npm-prefix": "^1.2.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + } + } + }, "load-stylesheets": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/load-stylesheets/-/load-stylesheets-0.7.0.tgz", @@ -4213,9 +7004,21 @@ } }, "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "dev": true + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", "dev": true }, "lodash.get": { @@ -4224,19 +7027,81 @@ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, + "lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=", + "dev": true + }, + "lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha1-OdcUo1NXFHg3rv1ktdy7Fr7Nj40=", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, + "lodash.unescape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", + "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=", + "dev": true + }, + "lodash.upperfirst": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", + "integrity": "sha1-E2Xt9DFIBIHvDRxolXpe2Z1J984=", + "dev": true + }, + "lodash.zip": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz", + "integrity": "sha1-7GZi5IlkCO1KtsVCo5kLcswIACA=", + "dev": true + }, + "log-update-async-hook": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/log-update-async-hook/-/log-update-async-hook-2.0.2.tgz", + "integrity": "sha512-HQwkKFTZeUOrDi1Duf2CSUa/pSpcaCHKLdx3D/Z16DsipzByOBffcg5y0JZA1q0n80dYgLXe2hFM9JGNgBsTDw==", + "dev": true, + "requires": { + "ansi-escapes": "^2.0.0", + "async-exit-hook": "^1.1.2", + "onetime": "^2.0.1", + "wrap-ansi": "^2.1.0" + }, + "dependencies": { + "ansi-escapes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-2.0.0.tgz", + "integrity": "sha1-W65SvkJIeN2Xg+iRDj/Cki6DyBs=", + "dev": true + } + } + }, "lolex": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.4.tgz", - "integrity": "sha512-Gh6Vffq/piTeHwunLNFR1jFVaqlwK9GMNUxFcsO1cwHyvbRKHwX8UDkxmrDnbcPdHNmpv7z2kxtkkSx5xkNpMw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-3.1.0.tgz", + "integrity": "sha512-zFo5MgCJ0rZ7gQg69S4pqBsLURbFw11X68C18OcJjJQbqaXm2NoTrGl1IMM3TIz0/BnN1tIs2tzmmqvCsOMMjw==", + "dev": true + }, + "longest-streak": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", + "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==", "dev": true }, "loose-envify": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dev": true, "requires": { - "js-tokens": "^3.0.0" + "js-tokens": "^3.0.0 || ^4.0.0" } }, "loud-rejection": { @@ -4249,6 +7114,22 @@ "signal-exit": "^3.0.0" } }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, "ltgt": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", @@ -4256,21 +7137,29 @@ "dev": true }, "magic-string": { - "version": "0.22.5", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz", - "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.1.tgz", + "integrity": "sha512-sCuTz6pYom8Rlt4ISPFn6wuFodbKMIHUMv4Qko9P17dpxb7s52KJTmRuZZqHdGmLCK9AOcDare039nRIcfdkEg==", "dev": true, "requires": { - "vlq": "^0.2.2" + "sourcemap-codec": "^1.4.1" } }, - "makeerror": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", - "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", "dev": true, "requires": { - "tmpl": "1.0.x" + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } } }, "map-cache": { @@ -4280,9 +7169,15 @@ "dev": true }, "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true + }, + "map-reverse": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "resolved": "https://registry.npmjs.org/map-reverse/-/map-reverse-1.0.1.tgz", + "integrity": "sha1-J06fUAphEVMYO1uNhJCpwcI+4xA=", "dev": true }, "map-visit": { @@ -4294,19 +7189,37 @@ "object-visit": "^1.0.0" } }, + "markdown-escapes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.2.tgz", + "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==", + "dev": true + }, + "markdown-extensions": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-1.1.1.tgz", + "integrity": "sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==", + "dev": true + }, + "markdown-table": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.2.tgz", + "integrity": "sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw==", + "dev": true + }, "marked": { "version": "0.3.19", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz", + "resolved": "http://registry.npmjs.org/marked/-/marked-0.3.19.tgz", "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==", "dev": true }, - "matcher-collection": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/matcher-collection/-/matcher-collection-1.0.5.tgz", - "integrity": "sha512-nUCmzKipcJEwYsBVAFh5P+d7JBuhJaW1xs85Hara9xuMLqtCVUrW6DSC0JVIkluxEH2W45nPBM/wjHtBXa/tYA==", + "match-url-wildcard": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/match-url-wildcard/-/match-url-wildcard-0.0.2.tgz", + "integrity": "sha512-XQWEV4NdsB6HymtjW5sJthh1oHr/IZZPp+lOhu+RPkWDD0iQYXVCe8ozGQmi5ZxWqXYteERjHhN80zxLV/TNWA==", "dev": true, "requires": { - "minimatch": "^3.0.2" + "escape-string-regexp": "^1.0.5" } }, "math-random": { @@ -4316,101 +7229,129 @@ "dev": true }, "md5.js": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", - "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", "dev": true, "requires": { "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mdast-util-compact": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.2.tgz", + "integrity": "sha512-d2WS98JSDVbpSsBfVvD9TaDMlqPRz7ohM/11G0rp5jOBb5q96RJ6YLszQ/09AAixyzh23FeIpCGqfaamEADtWg==", + "dev": true, + "requires": { + "unist-util-visit": "^1.1.0" + } + }, + "mdn-browser-compat-data": { + "version": "0.0.65", + "resolved": "https://registry.npmjs.org/mdn-browser-compat-data/-/mdn-browser-compat-data-0.0.65.tgz", + "integrity": "sha512-OC27wWCLD2mw2aW6+8zZTwCv0+9WMTOFxuvTBfWoCx8f9gVFNUXHxGYA16mhKyso7hEa4tw1hY+ruCB/kg3EzQ==", + "dev": true, + "requires": { + "extend": "3.0.2" + } + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" } }, "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz", + "integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==", "dev": true, "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", + "minimist-options": "^3.0.1", "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0", + "yargs-parser": "^10.0.0" }, "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, "requires": { "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" } }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } }, "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "pify": "^3.0.0" } }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", "dev": true, "requires": { - "load-json-file": "^1.0.0", + "load-json-file": "^4.0.0", "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" + "path-type": "^3.0.0" } }, "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", "dev": true, "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" } } } }, - "merge": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz", - "integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo=", - "dev": true - }, "merge-stream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", @@ -4421,9 +7362,9 @@ } }, "merge2": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.2.tgz", - "integrity": "sha512-bgM8twH86rWni21thii6WCMQMRMmwqqdW3sGWi9IipnVAszdLXRjwDwAnyrVXo6DuP3AjRMMttZKUB48QWIFGg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.3.tgz", + "integrity": "sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==", "dev": true }, "micromatch": { @@ -4463,6 +7404,21 @@ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true }, + "mime-db": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", + "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==", + "dev": true + }, + "mime-types": { + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", + "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", + "dev": true, + "requires": { + "mime-db": "~1.38.0" + } + }, "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", @@ -4492,10 +7448,20 @@ }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, + "minimist-options": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", + "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0" + } + }, "mixin-deep": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", @@ -4519,17 +7485,35 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "requires": { "minimist": "0.0.8" } }, + "moment": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==", + "dev": true + }, + "moment-duration-format-commonjs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/moment-duration-format-commonjs/-/moment-duration-format-commonjs-1.0.0.tgz", + "integrity": "sha512-MVFR4hIh4jfuwSCPBEE5CCwn3refvTsxK/Yv/DpKJ6YcNnCimlVJ6DQeTJG1KVQPw1o8m3tkbHE9gVjivyv9iA==", + "dev": true + }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "mustache": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.2.tgz", + "integrity": "sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ==", "dev": true }, "mute-stream": { @@ -4539,16 +7523,22 @@ "dev": true }, "nan": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.0.tgz", - "integrity": "sha512-F4miItu2rGnV2ySkXOQoA8FKz/SR2Q2sWP0sbTxNxz/tuokeC8WxOhPMcwi0qIyGtVn/rrSeLbvVkznqCdwYnw==", + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", + "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==", "dev": true, "optional": true }, + "nanoid": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-1.3.4.tgz", + "integrity": "sha512-4ug4BsuHxiVHoRUe1ud6rUFT3WUMmjXt1W0quL0CviZQANdan7D8kqN5/maw53hmAApY/jfzMRkC57BNNs60ZQ==", + "dev": true + }, "nanomatch": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", - "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", "dev": true, "requires": { "arr-diff": "^4.0.0", @@ -4556,7 +7546,6 @@ "define-property": "^2.0.2", "extend-shallow": "^3.0.2", "fragment-cache": "^0.2.1", - "is-odd": "^2.0.0", "is-windows": "^1.0.2", "kind-of": "^6.0.2", "object.pick": "^1.3.0", @@ -4572,34 +7561,51 @@ "dev": true }, "nice-try": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", - "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, "nise": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.4.tgz", - "integrity": "sha512-pxE0c9PzgrUTyhfv5p+5eMIdfU2bLEsq8VQEuE0kxM4zP7SujSar7rk9wpI2F7RyyCEvLyj5O7Is3RER5F36Fg==", + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.10.tgz", + "integrity": "sha512-sa0RRbj53dovjc7wombHmVli9ZihXbXCQ2uH3TNm03DyvOSIQbxg+pbqDKrk2oxMK1rtLGVlKxcB9rrc6X5YjA==", "dev": true, "requires": { - "@sinonjs/formatio": "^2.0.0", - "just-extend": "^3.0.0", + "@sinonjs/formatio": "^3.1.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", "lolex": "^2.3.2", - "path-to-regexp": "^1.7.0", - "text-encoding": "^0.6.4" + "path-to-regexp": "^1.7.0" + }, + "dependencies": { + "lolex": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", + "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", + "dev": true + } } }, - "node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "node-modules-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", + "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", "dev": true }, + "node-releases": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.8.tgz", + "integrity": "sha512-gQm+K9mGCiT/NXHy+V/ZZS1N/LOaGGqRAAJJs3X9Ah1g+CIbRcBgNyoNYQ+SEtcyAtB9KqDruu+fF7nWjsqRaA==", + "dev": true, + "requires": { + "semver": "^5.3.0" + } + }, "node-static": { - "version": "0.7.10", - "resolved": "https://registry.npmjs.org/node-static/-/node-static-0.7.10.tgz", - "integrity": "sha512-bd7zO5hvCWzdglgwz9t82T4mYTEUzEG5pXnSqEzitvmEacusbhl8/VwuCbMaYR9g2PNK5191yBtAEQLJEmQh1A==", + "version": "0.7.11", + "resolved": "https://registry.npmjs.org/node-static/-/node-static-0.7.11.tgz", + "integrity": "sha512-zfWC/gICcqb74D9ndyvxZWaI1jzcoHmf4UTHWQchBNuNMxdBLJMDiUgZ1tjGLEIe/BMhj2DxKD8HOuc2062pDQ==", "dev": true, "requires": { "colors": ">=0.6.0", @@ -4607,6 +7613,18 @@ "optimist": ">=0.3.4" } }, + "node-version": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/node-version/-/node-version-1.2.0.tgz", + "integrity": "sha512-ma6oU4Sk0qOoKEAymVoTvk8EdXEobdS7m/mAGhDJ8Rouugho48crHBORAmy5BoOcv8wraPM6xumapQp5hl4iIQ==", + "dev": true + }, + "node-watch": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.6.0.tgz", + "integrity": "sha512-XAgTL05z75ptd7JSVejH1a2Dm1zmXYhuDr9l230Qk6Z7/7GPcnAs/UyJJ4ggsXSvWil8iOzwQLW0zuGUvHpG8g==", + "dev": true + }, "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -4628,6 +7646,17 @@ "remove-trailing-separator": "^1.0.1" } }, + "npm-prefix": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/npm-prefix/-/npm-prefix-1.2.0.tgz", + "integrity": "sha1-5hlFX3B0ulTMZtbQ033Z8b5ry8A=", + "dev": true, + "requires": { + "rc": "^1.1.0", + "shellsubstitute": "^1.1.0", + "untildify": "^2.1.0" + } + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -4643,6 +7672,24 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, + "nwsapi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.0.tgz", + "integrity": "sha512-ZG3bLAvdHmhIjaQ/Db1qvBxsGvFMLIRpQszyqbg31VJ53UP++uZX1/gf3Ut96pdwN9AuDwlMqIYLm0UPCdUeHg==", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "obj-props": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/obj-props/-/obj-props-1.1.0.tgz", + "integrity": "sha1-YmMT+qRCvv1KROmgLDy2vek3tRE=", + "dev": true + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -4681,15 +7728,10 @@ } }, "object-keys": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.2.0.tgz", - "integrity": "sha1-zd7AKZiwkb5CvxA1rjLknxy26mc=", - "dev": true, - "requires": { - "foreach": "~2.0.1", - "indexof": "~0.0.1", - "is": "~0.2.6" - } + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", + "dev": true }, "object-visit": { "version": "1.0.1", @@ -4700,6 +7742,30 @@ "isobject": "^3.0.0" } }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.entries": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.0.4.tgz", + "integrity": "sha1-G/mk3SKI9bM/Opk9JXZh8F0WGl8=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.6.1", + "function-bind": "^1.1.0", + "has": "^1.0.1" + } + }, "object.omit": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", @@ -4744,26 +7810,25 @@ } }, "opn": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/opn/-/opn-4.0.2.tgz", - "integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz", + "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==", "dev": true, "requires": { - "object-assign": "^4.0.1", - "pinkie-promise": "^2.0.0" + "is-wsl": "^1.1.0" } }, "opn-cli": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/opn-cli/-/opn-cli-3.1.0.tgz", - "integrity": "sha1-+BmubK4LQRvQFJuFYP5siK2tIPg=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/opn-cli/-/opn-cli-4.0.0.tgz", + "integrity": "sha512-/NxjgPPxgYWAEznUwbvQd3H/vfMBRoIy8ZAvKNNgye2TbFE4pToVwmbi34Xo2rkmlfJIeWPa++zUSj4WBVGJxQ==", "dev": true, "requires": { - "file-type": "^3.6.0", - "get-stdin": "^5.0.1", - "meow": "^3.7.0", - "opn": "^4.0.0", - "temp-write": "^2.1.0" + "file-type": "^10.4.0", + "get-stdin": "^6.0.0", + "meow": "^5.0.0", + "opn": "^5.4.0", + "temp-write": "^3.4.0" } }, "optimist": { @@ -4798,12 +7863,29 @@ "wordwrap": "~1.0.0" } }, + "os-family": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/os-family/-/os-family-1.1.0.tgz", + "integrity": "sha512-E3Orl5pvDJXnVmpaAA2TeNNpNhTMl4o5HghuWhOivBjEiTnJSrMYSa5uZMek1lBEvu8kKEsa2YgVcGFVDqX/9w==", + "dev": true + }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -4834,15 +7916,30 @@ "p-limit": "^1.1.0" } }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "dev": true + }, "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, + "parent-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.0.tgz", + "integrity": "sha512-8Mf5juOMmiE4FcmzYc4IaiS9L3+9paz2KOiXzkRviCP6aDmN49Hz6EMWz0lGNp9pX80GvvAuLADtyGfW/Em3TA==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, "parse-asn1": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", + "resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", "dev": true, "requires": { @@ -4853,6 +7950,20 @@ "pbkdf2": "^3.0.3" } }, + "parse-entities": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.0.tgz", + "integrity": "sha512-XXtDdOPLSB0sHecbEapQi6/58U/ODj/KWfIXmmMCJF/eRn8laX6LZbOyioMoETOOJoWRW8/qTSl5VQkUIfKM5g==", + "dev": true, + "requires": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, "parse-glob": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", @@ -4897,6 +8008,12 @@ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true }, + "parse5": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", + "dev": true + }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", @@ -4909,15 +8026,6 @@ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", "dev": true }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -4968,10 +8076,16 @@ "pify": "^2.0.0" } }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, "pbkdf2": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", - "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", "dev": true, "requires": { "create-hash": "^1.1.2", @@ -4981,9 +8095,15 @@ "sha.js": "^2.4.8" } }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, @@ -5002,19 +8122,80 @@ "pinkie": "^2.0.0" } }, - "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "pirates": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", + "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", "dev": true, "requires": { - "find-up": "^1.0.0" + "node-modules-regexp": "^1.0.0" } }, - "pluralize": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" + }, + "dependencies": { + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "array-slice": "^0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "^1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", + "dev": true + } + } + }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true + }, + "pngjs": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.3.3.tgz", + "integrity": "sha512-1n3Z4p3IOxArEs1VRXnZ/RXdfEniAUS9jb68g58FIXMNkPJeZd+Qh4Uq7/e0LVxAQGos1eIUrqrt4FpjdnEd+Q==", "dev": true }, "posix-character-classes": { @@ -5035,6 +8216,21 @@ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", "dev": true }, + "prettier": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.14.3.tgz", + "integrity": "sha512-qZDVnCrnpsRJJq5nSsiHCE3BYMED2OtsI+cmzIzF1QIfqm5ALf8tEJcO27zV1gKNKRPdhjO0dNWnrzssDQ1tFg==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, "pretty-bytes": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.1.0.tgz", @@ -5060,37 +8256,85 @@ "dev": true }, "progress": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", - "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, "promise-fs": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/promise-fs/-/promise-fs-1.3.0.tgz", - "integrity": "sha512-CXT/dzuNzWDl9UoJ49MHgv5GqjLcOw5iq7laC3DfBjDRpDFVt3kal6Ar8rTafzEv1cS5BJIW/5o3tTKYHOcEtg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-fs/-/promise-fs-2.0.1.tgz", + "integrity": "sha512-lxCgMLa0tQfCXgY8It9LIyYbai4HtgO0HxpVn8ra0KfWAaFJzYy12gk1L8+TdnoqGSy436xjej3UnVmZjvKZ3g==", "dev": true, "requires": { - "@octetstream/promisify": "1.1.0" + "@octetstream/eslint-config": "3.0.0", + "@octetstream/promisify": "2.0.1" } }, + "promisify-event": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/promisify-event/-/promisify-event-1.0.0.tgz", + "integrity": "sha1-vXUj6ga3AWLzcJeQFrU6aGxg6Q8=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "proto-props": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/proto-props/-/proto-props-2.0.0.tgz", + "integrity": "sha512-2yma2tog9VaRZY2mn3Wq51uiSW4NcPYT1cQdBagwyrznrilKSZwIZ0UG3ZPL/mx+axEns0hE35T5ufOYZXEnBQ==", + "dev": true + }, "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", "dev": true }, + "ps-node": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ps-node/-/ps-node-0.1.6.tgz", + "integrity": "sha1-mvZ6mdex0BMuUaUDCZ04qNKs4sM=", + "dev": true, + "requires": { + "table-parser": "^0.1.3" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "psl": { + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", + "dev": true + }, "public-encrypt": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", - "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", "dev": true, "requires": { "bn.js": "^4.1.0", "browserify-rsa": "^4.0.0", "create-hash": "^1.1.0", "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1" + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, "punycode": { @@ -5105,19 +8349,45 @@ "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "dev": true }, + "qr-manipulation": { + "version": "git+https://github.com/brettz9/qr-manipulation.git#832651199b675ae6c5abfc3f49f1a2f4238812b1", + "from": "git+https://github.com/brettz9/qr-manipulation.git", + "dev": true + }, + "qrcode-terminal": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.10.0.tgz", + "integrity": "sha1-p2pI4mEKGPl/o6K9UytoKs/4bFM=", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "query-result": { + "version": "git+https://github.com/WebReflection/query-result.git#6b33ed9e3193f685ee0f35a59ff6088ca57f8597", + "from": "git+https://github.com/WebReflection/query-result.git", + "dev": true + }, + "quick-lru": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", + "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", + "dev": true + }, "qunit": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/qunit/-/qunit-2.6.2.tgz", - "integrity": "sha512-PHbKulmd4rrDhFto7iHicIstDTX7oMRvAcI7loHstvU8J7AOGwzcchONmy+EG4KU8HDk0K90o7vO0GhlYyKlOg==", + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/qunit/-/qunit-2.9.1.tgz", + "integrity": "sha512-ipXgW4SD557GrQtiBhj+g7eHk76pmSIYKglEXuAD/WsC06XzXDc4r9qlm4DSG5LxqxvpgK8naGlJ1Zcnj9/NdQ==", "dev": true, "requires": { "commander": "2.12.2", - "exists-stat": "1.0.0", - "findup-sync": "2.0.0", "js-reporters": "1.2.1", - "resolve": "1.5.0", - "sane": "^2.5.2", - "walk-sync": "0.3.2" + "minimatch": "3.0.4", + "node-watch": "0.6.0", + "resolve": "1.5.0" }, "dependencies": { "commander": { @@ -5138,9 +8408,9 @@ } }, "randomatic": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.0.0.tgz", - "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", "dev": true, "requires": { "is-number": "^4.0.0", @@ -5175,6 +8445,35 @@ "safe-buffer": "^5.1.0" } }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "read-file-relative": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/read-file-relative/-/read-file-relative-1.2.0.tgz", + "integrity": "sha1-mPfZbqoh0rTHov69Y9L8jPNen5s=", + "dev": true, + "requires": { + "callsite": "^1.0.0" + } + }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", @@ -5194,22 +8493,11 @@ "requires": { "find-up": "^2.0.0", "read-pkg": "^2.0.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - } } }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -5222,14 +8510,25 @@ "util-deprecate": "~1.0.1" } }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "dev": true, + "requires": { + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" } }, "regenerate": { @@ -5238,20 +8537,27 @@ "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", "dev": true }, + "regenerate-unicode-properties": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz", + "integrity": "sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw==", + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } + }, "regenerator-runtime": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", + "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==", "dev": true }, "regenerator-transform": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.3.tgz", + "integrity": "sha512-5ipTrZFSq5vU2YoGoww4uaRVAK4wyYC4TSICibbfEPOruUu8FFP7ErV0BjmbIOEpn3O/k9na9UEdYR/3m7N6uA==", "dev": true, "requires": { - "babel-runtime": "^6.18.0", - "babel-types": "^6.19.0", "private": "^0.1.6" } }, @@ -5274,33 +8580,42 @@ "safe-regex": "^1.1.0" } }, + "regexp-tree": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.5.tgz", + "integrity": "sha512-nUmxvfJyAODw+0B13hj8CFVAxhe7fDEAgJgaotBu3nnR+IgGgZq59YedJP5VYTlkEfqjuK6TuRpnymKdatLZfQ==", + "dev": true + }, "regexpp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.0.tgz", - "integrity": "sha512-g2FAVtR8Uh8GO1Nv5wpxW7VFVwHcCEr4wyA8/MHiRkO8uHoR5ntAA8Uq3P1vvMTX/BeQiRVSpDGLd+Wn5HNOTA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", "dev": true }, "regexpu-core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", - "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.4.0.tgz", + "integrity": "sha512-eDDWElbwwI3K0Lo6CqbQbA6FwgtCz4kYTarrri1okfkRLZAqstU+B3voZBCjg8Fl6iq0gXrJG6MvRgLthfvgOA==", "dev": true, "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^7.0.0", + "regjsgen": "^0.5.0", + "regjsparser": "^0.6.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.0.2" } }, "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", + "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", "dev": true }, "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", + "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", "dev": true, "requires": { "jsesc": "~0.5.0" @@ -5314,6 +8629,85 @@ } } }, + "remark": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/remark/-/remark-10.0.1.tgz", + "integrity": "sha512-E6lMuoLIy2TyiokHprMjcWNJ5UxfGQjaMSMhV+f4idM625UjjK4j798+gPs5mfjzDE6vL0oFKVeZM6gZVSVrzQ==", + "dev": true, + "requires": { + "remark-parse": "^6.0.0", + "remark-stringify": "^6.0.0", + "unified": "^7.0.0" + } + }, + "remark-cli": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/remark-cli/-/remark-cli-6.0.1.tgz", + "integrity": "sha512-h7Hwnfdcm5J03t2mxhl9BAav+Goqauqfz3LhpE7TP+RIiPnK6njU7qRDD7qlUd/hLyMSB+WBjYc7gVDQT3pv0A==", + "dev": true, + "requires": { + "markdown-extensions": "^1.1.0", + "remark": "^10.0.0", + "unified-args": "^6.0.0" + } + }, + "remark-lint-ordered-list-marker-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/remark-lint-ordered-list-marker-value/-/remark-lint-ordered-list-marker-value-1.0.2.tgz", + "integrity": "sha512-vIPD07u+FBjTjEETZ+UWUp2nydzvOe5AHIX812JlNXWuHYuCybq8DGnkYUcoiK3HbIE+KdG+e7C5xHkim0PSjw==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-parse": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-6.0.3.tgz", + "integrity": "sha512-QbDXWN4HfKTUC0hHa4teU463KclLAnwpn/FBn87j9cKYJWWawbiLgMfP2Q4XwhxxuuuOxHlw+pSN0OKuJwyVvg==", + "dev": true, + "requires": { + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^1.1.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^1.0.0", + "vfile-location": "^2.0.0", + "xtend": "^4.0.1" + } + }, + "remark-stringify": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-6.0.4.tgz", + "integrity": "sha512-eRWGdEPMVudijE/psbIDNcnJLRVx3xhfuEsTDGgH4GsFF91dVhw5nhmnBppafJ7+NWINW6C7ZwWbi30ImJzqWg==", + "dev": true, + "requires": { + "ccount": "^1.0.0", + "is-alphanumeric": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "longest-streak": "^2.0.1", + "markdown-escapes": "^1.0.0", + "markdown-table": "^1.1.0", + "mdast-util-compact": "^1.0.0", + "parse-entities": "^1.0.2", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "stringify-entities": "^1.0.1", + "unherit": "^1.0.4", + "xtend": "^4.0.1" + } + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -5321,9 +8715,9 @@ "dev": true }, "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", "dev": true }, "repeat-string": { @@ -5341,16 +8735,102 @@ "is-finite": "^1.0.0" } }, - "require-uncached": { + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "replicator": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "resolved": "https://registry.npmjs.org/replicator/-/replicator-1.0.3.tgz", + "integrity": "sha512-WsKsraaM0x0QHy5CtzdgFXUxyowoBhyNkmPqmZShW6h+rOWnyT6Od3zRdTX9r616rAA6kDC9MKQGnSM/CJKfVQ==", + "dev": true + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", "dev": true, "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + } } }, + "request-promise-core": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", + "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, + "request-promise-native": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", + "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", + "dev": true, + "requires": { + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "dev": true + }, "requizzle": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz", @@ -5377,20 +8857,27 @@ "path-parse": "^1.0.5" } }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "resolve-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-1.0.0.tgz", + "integrity": "sha1-Tq7qQe0EDRcCRX32SkKysH0kb58=", "dev": true, "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" + "resolve-from": "^2.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", + "dev": true + } } }, "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, "resolve-url": { @@ -5416,12 +8903,12 @@ "dev": true }, "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "requires": { - "glob": "^7.0.5" + "glob": "^7.1.3" } }, "ripemd160": { @@ -5435,61 +8922,45 @@ } }, "rollup": { - "version": "0.65.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.65.2.tgz", - "integrity": "sha512-BbXOrpxVbx0MpElI6vVLR2B6vnWHvYU/QAMw3GcEXvs601bvgrozuaW30cnvt43B96a6DeoYA0i9T5THanN+Rw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.2.2.tgz", + "integrity": "sha512-fsn5KJcfSuejjrv8GV7kZNciElqxyzZdUq8rA3e528JsR3ccxrWwoptyUY8GGLlgMFAQMB3dZW8nWF2I1/xrZA==", "dev": true, "requires": { "@types/estree": "0.0.39", - "@types/node": "*" + "@types/node": "*", + "acorn": "^6.1.0" } }, "rollup-plugin-babel": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/rollup-plugin-babel/-/rollup-plugin-babel-3.0.7.tgz", - "integrity": "sha512-bVe2y0z/V5Ax1qU8NX/0idmzIwJPdUGu8Xx3vXH73h0yGjxfv2gkFI82MBVg49SlsFlLTBadBHb67zy4TWM3hA==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-babel/-/rollup-plugin-babel-4.3.2.tgz", + "integrity": "sha512-KfnizE258L/4enADKX61ozfwGHoqYauvoofghFJBhFnpH9Sb9dNPpWg8QHOaAfVASUYV8w0mCx430i9z0LJoJg==", "dev": true, "requires": { - "rollup-pluginutils": "^1.5.0" - }, - "dependencies": { - "estree-walker": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.2.1.tgz", - "integrity": "sha1-va/oCVOD2EFNXcLs9MkXO225QS4=", - "dev": true - }, - "rollup-pluginutils": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz", - "integrity": "sha1-HhVud4+UtyVb+hs9AXi+j1xVJAg=", - "dev": true, - "requires": { - "estree-walker": "^0.2.1", - "minimatch": "^3.0.2" - } - } + "@babel/helper-module-imports": "^7.0.0", + "rollup-pluginutils": "^2.3.0" } }, "rollup-plugin-commonjs": { - "version": "9.1.6", - "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-9.1.6.tgz", - "integrity": "sha512-J7GOJm9uzEeLqkVxYSgjyoieh34hATWpa9G2M1ilGzWOLYGfQx5IDQ9ewG8QUj/Z2dzgV+d0/AyloAzElkABAA==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-9.2.0.tgz", + "integrity": "sha512-0RM5U4Vd6iHjL6rLvr3lKBwnPsaVml+qxOGaaNUWN1lSq6S33KhITOfHmvxV3z2vy9Mk4t0g4rNlVaJJsNQPWA==", "dev": true, "requires": { - "estree-walker": "^0.5.1", - "magic-string": "^0.22.4", - "resolve": "^1.5.0", - "rollup-pluginutils": "^2.0.1" + "estree-walker": "^0.5.2", + "magic-string": "^0.25.1", + "resolve": "^1.8.1", + "rollup-pluginutils": "^2.3.3" } }, "rollup-plugin-json": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-3.0.0.tgz", - "integrity": "sha512-WUAV9/I/uFWvHhyRTqFb+3SIapjISFJS7R1xN/cXxWESrfYo9I8ncHI7AxJHflKRXhBVSv7revBVJh2wvhWh5w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-3.1.0.tgz", + "integrity": "sha512-BlYk5VspvGpjz7lAwArVzBXR60JK+4EKtPkCHouAWg39obk9S61hZYJDBfMK+oitPdoe11i69TlxKlMQNFC/Uw==", "dev": true, "requires": { - "rollup-pluginutils": "^2.2.0" + "rollup-pluginutils": "^2.3.1" } }, "rollup-plugin-node-builtins": { @@ -5505,20 +8976,20 @@ } }, "rollup-plugin-node-resolve": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.4.0.tgz", - "integrity": "sha512-PJcd85dxfSBWih84ozRtBkB731OjXk0KnzN0oGp7WOWcarAFkVa71cV5hTJg2qpVsV2U8EUwrzHP3tvy9vS3qg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-4.0.0.tgz", + "integrity": "sha512-7Ni+/M5RPSUBfUaP9alwYQiIKnKeXCOHiqBpKUl9kwp3jX5ZJtgXAait1cne6pGEVUUztPD6skIKH9Kq9sNtfw==", "dev": true, "requires": { - "builtin-modules": "^2.0.0", + "builtin-modules": "^3.0.0", "is-module": "^1.0.0", - "resolve": "^1.1.6" + "resolve": "^1.8.1" }, "dependencies": { "builtin-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-2.0.0.tgz", - "integrity": "sha512-3U5kUA5VPsRUA3nofm/BXX7GVHKfxz0hOBAPxXrIvHzlDRkQVqEn6yi8QJegxl4LzOHLdvb7XF5dVawa/VVYBg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.0.0.tgz", + "integrity": "sha512-hMIeU4K2ilbXV6Uv93ZZ0Avg/M91RaKXucQ+4me2Do1txxBDyDZWCBa5bJSLqoNTRpXTLwEzIk1KmloenDDjhg==", "dev": true } } @@ -5535,7 +9006,7 @@ "dependencies": { "magic-string": { "version": "0.16.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.16.0.tgz", + "resolved": "http://registry.npmjs.org/magic-string/-/magic-string-0.16.0.tgz", "integrity": "sha1-lw67DacZMwEoX7GqZQ85vdgetFo=", "dev": true, "requires": { @@ -5545,20 +9016,21 @@ } }, "rollup-plugin-terser": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-2.0.2.tgz", - "integrity": "sha512-B+oXJLFrIyczYRUuq4I+cP1AQBvnvr5CFa6RN0mx1o8s6OrTmnRVBx4a8hk7eRY2Z00DE3jw4LxV3708gBQsdQ==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-4.0.4.tgz", + "integrity": "sha512-wPANT5XKVJJ8RDUN0+wIr7UPd0lIXBo4UdJ59VmlPCtlFsE20AM+14pe+tk7YunCsWEiuzkDBY3QIkSCjtrPXg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "jest-worker": "^23.2.0", - "terser": "^3.8.2" + "jest-worker": "^24.0.0", + "serialize-javascript": "^1.6.1", + "terser": "^3.14.1" } }, "rollup-pluginutils": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.3.0.tgz", - "integrity": "sha512-xB6hsRsjdJdIYWEyYUJy/3ki5g69wrf0luHPGNK3ZSocV6HLNfio59l3dZ3TL4xUwEKgROhFi9jOCt6c5gfUWw==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.3.3.tgz", + "integrity": "sha512-2XZwja7b6P5q4RZ5FhyX1+f46xi1Z3qBKigLRZ6VTZjwbN0K1IFGMlwm06Uu0Emcre2Z63l77nq/pzn+KxIEoA==", "dev": true, "requires": { "estree-walker": "^0.5.2", @@ -5656,12 +9128,6 @@ } } }, - "rsvp": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz", - "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==", - "dev": true - }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", @@ -5672,9 +9138,9 @@ } }, "rxjs": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.2.tgz", - "integrity": "sha512-hV7criqbR0pe7EeL3O66UYVg92IR0XsA97+9y+BWTePK9SKmEI5Qd3Zj6uPnGkNzXsBywBQWTvujPl+1Kn9Zjw==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -5688,7 +9154,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { @@ -5701,41 +9167,40 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, - "samsam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", - "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", - "dev": true - }, - "sane": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/sane/-/sane-2.5.2.tgz", - "integrity": "sha1-tNwYYcIbQn6SlQej51HiosuKs/o=", + "sanitize-filename": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.1.tgz", + "integrity": "sha1-YS2hyWRz+gLczaktzVtKsWSmdyo=", "dev": true, "requires": { - "anymatch": "^2.0.0", - "capture-exit": "^1.2.0", - "exec-sh": "^0.2.0", - "fb-watchman": "^2.0.0", - "fsevents": "^1.2.3", - "micromatch": "^3.1.4", - "minimist": "^1.1.1", - "walker": "~1.0.5", - "watch": "~0.18.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } + "truncate-utf8-bytes": "^1.0.0" + } + }, + "saxes": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-3.1.6.tgz", + "integrity": "sha512-LAYs+lChg1v5uKNzPtsgTxSS5hLo8aIhSMCJt1WMpefAxm3D1RTpMwSpb6ebdL31cubiLTnhokVktBW+cv9Y9w==", + "dev": true, + "requires": { + "xmlchars": "^1.3.1" } }, "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, + "serialize-javascript": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.6.1.tgz", + "integrity": "sha512-A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, "set-value": { @@ -5763,7 +9228,7 @@ }, "sha.js": { "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { @@ -5786,6 +9251,12 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, + "shellsubstitute": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shellsubstitute/-/shellsubstitute-1.2.0.tgz", + "integrity": "sha1-5PcCpQxRiw9v6YRRiQ1wWvKba3A=", + "dev": true + }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -5793,54 +9264,49 @@ "dev": true }, "sinon": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-6.2.0.tgz", - "integrity": "sha512-gLFZz5UYvOhYzQ+DBzw/OCkmWaLAHlAyQiE2wxUOmAGVdasP9Yw93E+OwZ0UuhW3ReMu1FKniuNsL6VukvC77w==", + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.2.4.tgz", + "integrity": "sha512-FGlcfrkiBRfaEIKRw8s/9mk4nP4AMGswvKFixLo+AzsOhskjaBCHAHGLMd8pCJpQGS+9ZI71px6qoQUyvADeyA==", "dev": true, "requires": { - "@sinonjs/commons": "^1.0.2", - "@sinonjs/formatio": "^2.0.0", - "@sinonjs/samsam": "^2.0.0", + "@sinonjs/commons": "^1.3.0", + "@sinonjs/formatio": "^3.1.0", + "@sinonjs/samsam": "^3.1.1", "diff": "^3.5.0", - "lodash.get": "^4.4.2", - "lolex": "^2.7.2", - "nise": "^1.4.4", - "supports-color": "^5.5.0", - "type-detect": "^4.0.8" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "lolex": "^3.1.0", + "nise": "^1.4.10", + "supports-color": "^5.5.0" } }, "sinon-test": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/sinon-test/-/sinon-test-2.3.0.tgz", - "integrity": "sha512-dhy6lbkZAvVW6XVsngX9HY0MNBurNPP3vqVdXGYAN4B3BNq3eXO6d5V1nuS7UsjX2tXSk7QhMEb6cUk/Fia95g==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/sinon-test/-/sinon-test-2.4.0.tgz", + "integrity": "sha512-oQnO02I7JDbtrSKN8Qs3upobCQRythJCBn3DzPmv4m/SoPvhZJDVqHDFkRZ1lZhN2GkBqOR3m7WT79190z9kEg==", "dev": true }, "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", "dev": true }, "slice-ansi": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", "dev": true, "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", "is-fullwidth-code-point": "^2.0.0" } }, + "sliced": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", + "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=", + "dev": true + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -5884,10 +9350,10 @@ "is-extendable": "^0.1.0" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true } } @@ -5964,9 +9430,9 @@ } }, "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, "source-map-resolve": { @@ -5983,18 +9449,19 @@ } }, "source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz", + "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==", "dev": true, "requires": { - "source-map": "^0.5.6" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" }, "dependencies": { "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true } } @@ -6005,10 +9472,16 @@ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, + "sourcemap-codec": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.3.tgz", + "integrity": "sha512-vFrY/x/NdsD7Yc8mpTJXuao9S8lq08Z/kOITHz6b7YbfI9xL8Spe5EvSQUHOI7SbpY8bRPr0U3kKSsPuqEGSfA==", + "dev": true + }, "spdx-correct": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", - "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", + "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -6016,9 +9489,9 @@ } }, "spdx-exceptions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", "dev": true }, "spdx-expression-parse": { @@ -6032,9 +9505,9 @@ } }, "spdx-license-ids": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz", + "integrity": "sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg==", "dev": true }, "split-string": { @@ -6052,6 +9525,41 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stackblur-canvas": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.2.0.tgz", + "integrity": "sha512-5Gf8dtlf8k6NbLzuly2NkGrkS/Ahh+I5VUjO7TnFizdJtgpfpLLEdQlLe9umbcnZlitU84kfYjXE67xlSXfhfQ==", + "dev": true + }, + "stackframe": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-0.3.1.tgz", + "integrity": "sha1-M6qE8Rd6VUjIk1Uzy/6zQgl19aQ=", + "dev": true + }, + "state-toggle": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.1.tgz", + "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==", + "dev": true + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -6073,9 +9581,15 @@ } } }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, "string-range": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/string-range/-/string-range-1.2.2.tgz", + "resolved": "http://registry.npmjs.org/string-range/-/string-range-1.2.2.tgz", "integrity": "sha1-qJPtNH5yKZvIO++78qaSqNI51d0=", "dev": true }, @@ -6098,6 +9612,18 @@ "safe-buffer": "~5.1.0" } }, + "stringify-entities": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", + "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", + "dev": true, + "requires": { + "character-entities-html4": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -6105,14 +9631,6 @@ "dev": true, "requires": { "ansi-regex": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - } } }, "strip-bom": { @@ -6123,26 +9641,15 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1" - }, - "dependencies": { - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - } - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true }, "strip-json-comments": { "version": "2.0.1", @@ -6151,23 +9658,67 @@ "dev": true }, "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "symbol-tree": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", + "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=", "dev": true }, "table": { - "version": "4.0.3", - "resolved": "http://registry.npmjs.org/table/-/table-4.0.3.tgz", - "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz", + "integrity": "sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==", "dev": true, "requires": { - "ajv": "^6.0.1", - "ajv-keywords": "^3.0.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" + "ajv": "^6.9.1", + "lodash": "^4.17.11", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", + "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==", + "dev": true + }, + "string-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.0.0.tgz", + "integrity": "sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.0.0" + } + }, + "strip-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", + "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", + "dev": true, + "requires": { + "ansi-regex": "^4.0.0" + } + } + } + }, + "table-parser": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/table-parser/-/table-parser-0.1.3.tgz", + "integrity": "sha1-BEHPzhallIFoTCfRtaZ/8VpDx7A=", + "dev": true, + "requires": { + "connected-domain": "^1.0.0" } }, "taffydb": { @@ -6176,29 +9727,43 @@ "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", "dev": true }, + "temp-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", + "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", + "dev": true + }, "temp-write": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/temp-write/-/temp-write-2.1.0.tgz", - "integrity": "sha1-WYkJGODvCdVIqqNC9L00CdhATpY=", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-write/-/temp-write-3.4.0.tgz", + "integrity": "sha1-jP9jD7fp2gXwR8dM5M5NaFRX1JI=", "dev": true, "requires": { "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "os-tmpdir": "^1.0.0", - "pify": "^2.2.0", - "pinkie-promise": "^2.0.0", - "uuid": "^2.0.1" + "is-stream": "^1.1.0", + "make-dir": "^1.0.0", + "pify": "^3.0.0", + "temp-dir": "^1.0.0", + "uuid": "^3.0.1" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } } }, "terser": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-3.8.2.tgz", - "integrity": "sha512-FGSBXiBJe2TSXy6pWwXpY0YcEWEK35UKL64BBbxX3aHqM4Nj0RMqXvqBuoSGfyd80t8MKQ5JwYm5jRRGTSEFNg==", + "version": "3.16.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-3.16.1.tgz", + "integrity": "sha512-JDJjgleBROeek2iBcSNzOHLKsB/MdDf+E/BOAJ0Tk9r7p9/fVobfv7LMJ/g/k3v9SXdmjZnIlFd5nfn/Rt0Xow==", "dev": true, "requires": { "commander": "~2.17.1", "source-map": "~0.6.1", - "source-map-support": "~0.5.6" + "source-map-support": "~0.5.9" }, "dependencies": { "commander": { @@ -6207,22 +9772,487 @@ "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", "dev": true }, - "source-map-support": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", - "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "testcafe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/testcafe/-/testcafe-1.0.1.tgz", + "integrity": "sha512-Wx/8vgsZIMTf8+RAnjcdks8z4qyPkJiPnGVuJ40dmpWIk5erQX1YT/DIbLbU2MZ2XtZbORSmxIBAN0LXg6jNqA==", + "dev": true, + "requires": { + "@types/node": "^10.12.19", + "async-exit-hook": "^1.1.2", + "babel-core": "^6.22.1", + "babel-plugin-transform-class-properties": "^6.24.1", + "babel-plugin-transform-for-of-as-array": "^1.1.1", + "babel-plugin-transform-runtime": "^6.22.0", + "babel-preset-env": "^1.1.8", + "babel-preset-flow": "^6.23.0", + "babel-preset-stage-2": "^6.22.0", + "babel-runtime": "^6.22.0", + "bin-v8-flags-filter": "^1.1.2", + "callsite": "^1.0.0", + "callsite-record": "^4.0.0", + "chai": "^4.1.2", + "chalk": "^1.1.0", + "chrome-emulated-devices-list": "^0.1.0", + "chrome-remote-interface": "^0.25.3", + "coffeescript": "^2.3.1", + "commander": "^2.8.1", + "debug": "^2.2.0", + "dedent": "^0.4.0", + "del": "^3.0.0", + "elegant-spinner": "^1.0.1", + "emittery": "^0.4.1", + "endpoint-utils": "^1.0.2", + "error-stack-parser": "^1.3.6", + "globby": "^3.0.1", + "graceful-fs": "^4.1.11", + "graphlib": "^2.1.5", + "gulp-data": "^1.3.1", + "import-lazy": "^3.1.0", + "indent-string": "^1.2.2", + "is-ci": "^1.0.10", + "is-glob": "^2.0.1", + "is-stream": "^1.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.11", + "log-update-async-hook": "^2.0.2", + "make-dir": "^1.3.0", + "map-reverse": "^1.0.1", + "moment": "^2.10.3", + "moment-duration-format-commonjs": "^1.0.0", + "mustache": "^2.1.2", + "nanoid": "^1.0.1", + "node-version": "^1.0.0", + "os-family": "^1.0.0", + "parse5": "^1.5.0", + "pify": "^2.3.0", + "pinkie": "^2.0.4", + "pngjs": "^3.3.1", + "promisify-event": "^1.0.0", + "ps-node": "^0.1.6", + "qrcode-terminal": "^0.10.0", + "read-file-relative": "^1.2.0", + "replicator": "^1.0.3", + "resolve-cwd": "^1.0.0", + "resolve-from": "^4.0.0", + "sanitize-filename": "^1.6.0", + "source-map-support": "^0.5.5", + "strip-bom": "^2.0.0", + "testcafe-browser-tools": "1.6.5", + "testcafe-hammerhead": "14.4.14", + "testcafe-legacy-api": "3.1.10", + "testcafe-reporter-json": "^2.1.0", + "testcafe-reporter-list": "^2.1.0", + "testcafe-reporter-minimal": "^2.1.0", + "testcafe-reporter-spec": "^2.1.1", + "testcafe-reporter-xunit": "^2.1.0", + "time-limit-promise": "^1.0.2", + "tmp": "0.0.28", + "tree-kill": "^1.1.0", + "typescript": "^2.2.2", + "useragent": "^2.1.7" + }, + "dependencies": { + "@types/node": { + "version": "10.12.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.26.tgz", + "integrity": "sha512-nMRqS+mL1TOnIJrL6LKJcNZPB8V3eTfRo9FQA2b5gDvrHurC8XbSA86KNe0dShlEL7ReWJv/OU9NL7Z0dnqWTg==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globby": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-3.0.1.tgz", + "integrity": "sha1-IJSvhCHhkVIVDViT62QWsxLZoi8=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^5.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^1.0.0" + } + }, + "indent-string": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-1.2.2.tgz", + "integrity": "sha1-25m8xYPrarux5I3LsZmamGBBy2s=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1", + "minimist": "^1.1.0", + "repeating": "^1.1.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "parse5": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", + "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ=", + "dev": true + }, + "pinkie-promise": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-1.0.0.tgz", + "integrity": "sha1-0dpn9UglY7t89X8oauKCLs+/NnA=", + "dev": true, + "requires": { + "pinkie": "^1.0.0" + }, + "dependencies": { + "pinkie": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-1.0.0.tgz", + "integrity": "sha1-Wkfyi6EBXQIBvae/DzWOR77Ix+Q=", + "dev": true + } + } + }, + "repeating": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz", + "integrity": "sha1-PUEUIYh3U3SU+X93+Xhfq4EPpKw=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "tmp": { + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.28.tgz", + "integrity": "sha1-Fyc1t/YU6nrzlmT6hM8N5OUV0SA=", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.1" } } } }, - "text-encoding": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", - "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", + "testcafe-browser-tools": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/testcafe-browser-tools/-/testcafe-browser-tools-1.6.5.tgz", + "integrity": "sha512-VsdAxRCRo7pSUYUNO0fw6uX8w84ooOhg8ZMAUBmMkTU9xOYBKpJF/Kvh40fBs2tOB4r/q8yPYnT/Y8z8HsekcA==", + "dev": true, + "requires": { + "array-find": "^1.0.0", + "babel-runtime": "^5.6.15", + "graceful-fs": "^4.1.11", + "linux-platform-info": "^0.0.3", + "mkdirp": "^0.5.1", + "mustache": "^2.1.2", + "os-family": "^1.0.0", + "pify": "^2.3.0", + "pinkie": "^2.0.1", + "read-file-relative": "^1.2.0", + "which-promise": "^1.0.0" + }, + "dependencies": { + "babel-runtime": { + "version": "5.8.38", + "resolved": "http://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.38.tgz", + "integrity": "sha1-HAsC62MxL18If/IEUIJ7QlydTBk=", + "dev": true, + "requires": { + "core-js": "^1.0.0" + } + }, + "core-js": { + "version": "1.2.7", + "resolved": "http://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", + "dev": true + } + } + }, + "testcafe-hammerhead": { + "version": "14.4.14", + "resolved": "https://registry.npmjs.org/testcafe-hammerhead/-/testcafe-hammerhead-14.4.14.tgz", + "integrity": "sha512-vpwe8RQ3CmXmk2QbSizCIZ4sDNW18vHH9NUH+g4swqPSbDBSvpirY7x3HUD514qJ7j9lOf+s7p1e070AYXzZ4g==", + "dev": true, + "requires": { + "acorn-hammerhead": "^0.1.2", + "bowser": "1.6.0", + "brotli": "^1.3.1", + "crypto-md5": "^1.0.0", + "css": "2.2.3", + "esotope-hammerhead": "^0.1.0", + "iconv-lite": "0.4.11", + "json-hammerhead": "^0.1.0", + "lodash": "4.17.11", + "lru-cache": "2.6.3", + "match-url-wildcard": "0.0.2", + "merge-stream": "^1.0.1", + "mime": "~1.4.1", + "mustache": "^2.1.1", + "nanoid": "^0.2.2", + "os-family": "^1.0.0", + "parse5": "^1.5.0", + "pify": "^2.3.0", + "pinkie": "1.0.0", + "read-file-relative": "^1.2.0", + "semver": "5.5.0", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "webauth": "^1.1.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.11", + "resolved": "http://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz", + "integrity": "sha1-LstC/SlHRJIiCaLnxATayHk9it4=", + "dev": true + }, + "lru-cache": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.3.tgz", + "integrity": "sha1-UczQtPwMhDWH16VwnOTTt2Kb7cU=", + "dev": true + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "dev": true + }, + "nanoid": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-0.2.2.tgz", + "integrity": "sha512-GHoRrvNEKiwdkwQ/enKL8AhQkkrBC/2KxMZkDvQzp8OtkpX8ZAmoYJWFVl7l8F2+HcEJUfdg21Ab2wXXfrvACQ==", + "dev": true + }, + "parse5": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", + "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ=", + "dev": true + }, + "pinkie": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-1.0.0.tgz", + "integrity": "sha1-Wkfyi6EBXQIBvae/DzWOR77Ix+Q=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "dev": true, + "requires": { + "punycode": "^1.4.1" + } + } + } + }, + "testcafe-legacy-api": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/testcafe-legacy-api/-/testcafe-legacy-api-3.1.10.tgz", + "integrity": "sha512-21CrLzYneDKZ/nC1F/nqj4HF4qhUYLsDW0q6aQZKr7jyml3LtiYdBj98LZteNNdykYJR5ra3gIlvA+i+EJk1lQ==", + "dev": true, + "requires": { + "async": "0.2.6", + "babel-runtime": "^5.8.34", + "dedent": "^0.6.0", + "highlight-es": "^1.0.0", + "is-jquery-obj": "^0.1.0", + "lodash": "^4.14.0", + "moment": "^2.14.1", + "mustache": "^2.2.1", + "os-family": "^1.0.0", + "parse5": "^2.1.5", + "pify": "^2.3.0", + "pinkie": "^2.0.1", + "strip-bom": "^2.0.0" + }, + "dependencies": { + "babel-runtime": { + "version": "5.8.38", + "resolved": "http://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.38.tgz", + "integrity": "sha1-HAsC62MxL18If/IEUIJ7QlydTBk=", + "dev": true, + "requires": { + "core-js": "^1.0.0" + } + }, + "core-js": { + "version": "1.2.7", + "resolved": "http://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", + "dev": true + }, + "dedent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.6.0.tgz", + "integrity": "sha1-Dm2o8M5Sg471zsXI+TlrDBtko8s=", + "dev": true + }, + "parse5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-2.2.3.tgz", + "integrity": "sha1-DE/EHBAAxea5PUiwP4CDg3g06fY=", + "dev": true + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + } + } + }, + "testcafe-reporter-json": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/testcafe-reporter-json/-/testcafe-reporter-json-2.1.0.tgz", + "integrity": "sha1-gLm1pt/y7h3h+R4mcHBsFHLmQAY=", + "dev": true + }, + "testcafe-reporter-list": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/testcafe-reporter-list/-/testcafe-reporter-list-2.1.0.tgz", + "integrity": "sha1-n6ifcbl9Pf5ktDAtXiJ97mmuxrk=", + "dev": true + }, + "testcafe-reporter-minimal": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/testcafe-reporter-minimal/-/testcafe-reporter-minimal-2.1.0.tgz", + "integrity": "sha1-Z28DVHY0FDxurzq1KGgnOkvr9CE=", + "dev": true + }, + "testcafe-reporter-spec": { + "version": "2.1.1", + "resolved": "http://registry.npmjs.org/testcafe-reporter-spec/-/testcafe-reporter-spec-2.1.1.tgz", + "integrity": "sha1-gVb87Q9RMkhlWa1WC8gGdkaSdew=", + "dev": true + }, + "testcafe-reporter-xunit": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/testcafe-reporter-xunit/-/testcafe-reporter-xunit-2.1.0.tgz", + "integrity": "sha1-5tZsVyzhWvJmcGrw/WELKoQd1EM=", "dev": true }, "text-table": { @@ -6233,10 +10263,26 @@ }, "through": { "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "time-limit-promise": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/time-limit-promise/-/time-limit-promise-1.0.4.tgz", + "integrity": "sha512-FLHDDsIDducw7MBcRWlFtW2Tm50DoKOSFf0Nzx17qwXj8REXCte0eUkHrJl9QU3Bl9arG3XNYX0PcHpZ9xyuLw==", + "dev": true + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -6246,16 +10292,10 @@ "os-tmpdir": "~1.0.2" } }, - "tmpl": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", - "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", - "dev": true - }, "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true }, "to-object-path": { @@ -6300,16 +10340,65 @@ "repeat-string": "^1.6.1" } }, + "to-vfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/to-vfile/-/to-vfile-4.0.0.tgz", + "integrity": "sha512-Y7EDM+uoU8TZxF5ej2mUR0dLO4qbuuNRnJKxEht2QJWEq2421pyG1D1x8YxPKmyTc6nHh7Td/jLGFxYo+9vkLA==", + "dev": true, + "requires": { + "is-buffer": "^2.0.0", + "vfile": "^3.0.0" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", + "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", + "dev": true + } + } + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, "traverse-chain": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/traverse-chain/-/traverse-chain-0.1.0.tgz", "integrity": "sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE=", "dev": true }, + "tree-kill": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz", + "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==", + "dev": true + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", "dev": true }, "trim-right": { @@ -6318,12 +10407,48 @@ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, + "trim-trailing-lines": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz", + "integrity": "sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==", + "dev": true + }, + "trough": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.3.tgz", + "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==", + "dev": true + }, + "truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha1-QFkjkJWS1W94pYGENLC3hInKXys=", + "dev": true, + "requires": { + "utf8-byte-length": "^1.0.1" + } + }, "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", "dev": true }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -6351,6 +10476,18 @@ "integrity": "sha1-m7i6DoQfs/TPH+fCRenz+opf6Zw=", "dev": true }, + "typescript": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", + "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", + "dev": true + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true + }, "underscore": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", @@ -6374,6 +10511,151 @@ } } }, + "unherit": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz", + "integrity": "sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "xtend": "^4.0.1" + } + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz", + "integrity": "sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz", + "integrity": "sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg==", + "dev": true + }, + "unified": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/unified/-/unified-7.0.2.tgz", + "integrity": "sha512-H7HiczCdNcPrqy4meJPtlJSch9+hm6GXLQ9FFLOUiFI1DIUbjvBhMKJtQ7YCaBhEPVXZwwqNyiot9xBUEtmlbg==", + "dev": true, + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^1.1.0", + "trough": "^1.0.0", + "vfile": "^3.0.0", + "x-is-string": "^0.1.0" + } + }, + "unified-args": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unified-args/-/unified-args-6.0.0.tgz", + "integrity": "sha512-1m2pGiTClgcCtCvgtABkJLze8JJiZpzsqujRhzBjZsRwaIIU1Yj36YHY6t2RvidO8d6fucZdk3KX+8eS4+uv9g==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "chalk": "^2.0.0", + "chokidar": "^2.0.0", + "fault": "^1.0.2", + "json5": "^1.0.0", + "minimist": "^1.2.0", + "text-table": "^0.2.0", + "unified-engine": "^6.0.0" + }, + "dependencies": { + "camelcase": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", + "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "http://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "unified-engine": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unified-engine/-/unified-engine-6.0.1.tgz", + "integrity": "sha512-iDJYH82TgcezQA4IZzhCNJQx7vBsGk4h9s4Q7Fscrb3qcPsxBqVrVNYez2W3sBVTxuU1bFAhyRpA6ba/R4j93A==", + "dev": true, + "requires": { + "concat-stream": "^1.5.1", + "debug": "^3.1.0", + "fault": "^1.0.0", + "fn-name": "^2.0.1", + "glob": "^7.0.3", + "ignore": "^3.2.0", + "is-empty": "^1.0.0", + "is-hidden": "^1.0.1", + "is-object": "^1.0.1", + "js-yaml": "^3.6.1", + "load-plugin": "^2.0.0", + "parse-json": "^4.0.0", + "to-vfile": "^4.0.0", + "trough": "^1.0.0", + "unist-util-inspect": "^4.1.2", + "vfile-reporter": "^5.0.0", + "vfile-statistics": "^1.1.0", + "x-is-string": "^0.1.0", + "xtend": "^4.0.1" + }, + "dependencies": { + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + } + } + }, + "unified-lint-rule": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/unified-lint-rule/-/unified-lint-rule-1.0.3.tgz", + "integrity": "sha512-6z+HH3mtlFdj/w3MaQpObrZAd9KRiro370GxBFh13qkV8LYR21lLozA4iQiZPhe7KuX/lHewoGOEgQ4AWrAR3Q==", + "dev": true, + "requires": { + "wrapped": "^1.0.1" + } + }, "union-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", @@ -6409,6 +10691,66 @@ } } }, + "unist-util-generated": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.3.tgz", + "integrity": "sha512-qlPeDqnQnd84KIqwphzOR+l02cxjDzvEYEBl84EjmKRrX4eUmjyAo8xJv1SCDhJqNjyHRnBMZWNKAiBtXE6hBg==", + "dev": true + }, + "unist-util-inspect": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/unist-util-inspect/-/unist-util-inspect-4.1.3.tgz", + "integrity": "sha512-Fv9R88ZBbDp7mHN+wsbxS1r8VW3unyhZh/F18dcJRQsg0+g3DxNQnMS+AEG/uotB8Md+HMK/TfzSU5lUDWxkZg==", + "dev": true, + "requires": { + "is-empty": "^1.0.0" + } + }, + "unist-util-is": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.2.tgz", + "integrity": "sha512-YkXBK/H9raAmG7KXck+UUpnKiNmUdB+aBGrknfQ4EreE1banuzrKABx3jP6Z5Z3fMSPMQQmeXBlKpCbMwBkxVw==", + "dev": true + }, + "unist-util-position": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.2.tgz", + "integrity": "sha512-npmFu92l/+b1Ao6uGP4I1WFz9hsKv7qleZ4aliw6x0RVu6A9A3tAf57NMpFfzQ02jxRtJZuRn+C8xWT7GWnH0g==", + "dev": true + }, + "unist-util-remove-position": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz", + "integrity": "sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q==", + "dev": true, + "requires": { + "unist-util-visit": "^1.1.0" + } + }, + "unist-util-stringify-position": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", + "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==", + "dev": true + }, + "unist-util-visit": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.0.tgz", + "integrity": "sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw==", + "dev": true, + "requires": { + "unist-util-visit-parents": "^2.0.0" + } + }, + "unist-util-visit-parents": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.0.1.tgz", + "integrity": "sha512-6B0UTiMfdWql4cQ03gDTCSns+64Zkfo2OCbK31Ov0uMizEz+CJeAp0cgZVb5Fhmcd7Bct2iRNywejT0orpbqUA==", + "dev": true, + "requires": { + "unist-util-is": "^2.1.2" + } + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -6455,6 +10797,21 @@ } } }, + "untildify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-2.1.0.tgz", + "integrity": "sha1-F+soB5h/dpUunASF/DEdBqgmouA=", + "dev": true, + "requires": { + "os-homedir": "^1.0.0" + } + }, + "upath": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "dev": true + }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -6471,94 +10828,350 @@ "dev": true }, "use": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", - "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "useragent": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", "dev": true, "requires": { - "kind-of": "^6.0.2" + "lru-cache": "4.1.x", + "tmp": "0.0.x" } }, + "utf8-byte-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", + "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=", + "dev": true + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "uuid": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", - "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "util-extend": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz", + "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=", "dev": true }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true + }, + "v8flags": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.2.tgz", + "integrity": "sha512-MtivA7GF24yMPte9Rp/BWGCYQNaUj86zeYxV/x2RRJMKagImbbv3u8iJC57lNhWLPcGLJmHcHmFWkNsplbbLWw==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, "validate-npm-package-license": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", - "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "requires": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vfile": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-3.0.1.tgz", + "integrity": "sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ==", + "dev": true, + "requires": { + "is-buffer": "^2.0.0", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "^1.0.0", + "vfile-message": "^1.0.0" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", + "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", + "dev": true + } + } + }, + "vfile-location": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.3.tgz", + "integrity": "sha512-zM5/l4lfw1CBoPx3Jimxoc5RNDAHHpk6AM6LM0pTIkm5SUSsx8ZekZ0PVdf0WEZ7kjlhSt7ZlqbRL6Cd6dBs6A==", + "dev": true + }, + "vfile-message": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.1.tgz", + "integrity": "sha512-vSGCkhNvJzO6VcWC6AlJW4NtYOVtS+RgCaqFIYUjoGIlHnFL+i0LbtYvonDWOMcB97uTPT4PRsyYY7REWC9vug==", + "dev": true, + "requires": { + "unist-util-stringify-position": "^1.1.1" + } + }, + "vfile-reporter": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-5.1.0.tgz", + "integrity": "sha512-I6h4GrkNCZf7nWCxcN7BSDAez8+4xD9+qfu5I7yroH6Kj+lpAFFIYfY6WgfCHyscAow5BkOpfHS5hHGBN1Qf8g==", + "dev": true, + "requires": { + "repeat-string": "^1.5.0", + "string-width": "^2.0.0", + "supports-color": "^5.4.0", + "unist-util-stringify-position": "^1.0.0", + "vfile-sort": "^2.1.2", + "vfile-statistics": "^1.1.0" + } + }, + "vfile-sort": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.1.2.tgz", + "integrity": "sha512-KoX1SaGv5CGoIIPHScklExODrVzCFC5Zo0uBM7iQTmd0PtbCswVIQ2cSESUak/dUICNc2lJyDzl9tXEB+4+P/g==", + "dev": true + }, + "vfile-statistics": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.1.tgz", + "integrity": "sha512-dxUM6IYvGChHuwMT3dseyU5BHprNRXzAV0OHx1A769lVGsTiT50kU7BbpRFV+IE6oWmU+PwHdsTKfXhnDIRIgQ==", + "dev": true + }, "vlq": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", "dev": true }, - "walk-sync": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/walk-sync/-/walk-sync-0.3.2.tgz", - "integrity": "sha512-FMB5VqpLqOCcqrzA9okZFc0wq0Qbmdm396qJxvQZhDpyu0W95G9JCmp74tx7iyYnyOcBtUuKJsgIKAqjozvmmQ==", + "vue-eslint-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-5.0.0.tgz", + "integrity": "sha512-JlHVZwBBTNVvzmifwjpZYn0oPWH2SgWv5dojlZBsrhablDu95VFD+hriB1rQGwbD+bms6g+rAFhQHk6+NyiS6g==", "dev": true, "requires": { - "ensure-posix-path": "^1.0.0", - "matcher-collection": "^1.0.0" - } - }, - "walker": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", - "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", - "dev": true, - "requires": { - "makeerror": "1.0.x" - } - }, - "watch": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/watch/-/watch-0.18.0.tgz", - "integrity": "sha1-KAlUdsbffJDJYxOJkMClQj60uYY=", - "dev": true, - "requires": { - "exec-sh": "^0.2.0", - "minimist": "^1.2.0" + "debug": "^4.1.0", + "eslint-scope": "^4.0.0", + "eslint-visitor-keys": "^1.0.0", + "espree": "^4.1.0", + "esquery": "^1.0.1", + "lodash": "^4.17.11" }, "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "espree": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz", + "integrity": "sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w==", + "dev": true, + "requires": { + "acorn": "^6.0.2", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } } } }, + "w3c-hr-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", + "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "dev": true, + "requires": { + "browser-process-hrtime": "^0.1.2" + } + }, + "w3c-xmlserializer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.0.1.tgz", + "integrity": "sha512-XZGI1OH/OLQr/NaJhhPmzhngwcAnZDLytsvXnRmlYeRkmbb0I7sqFFA22erq4WQR0sUu17ZSQOAV9mFwCqKRNg==", + "dev": true, + "requires": { + "domexception": "^1.0.1", + "webidl-conversions": "^4.0.2", + "xml-name-validator": "^3.0.0" + } + }, + "webauth": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/webauth/-/webauth-1.1.0.tgz", + "integrity": "sha1-ZHBPa4AmmGYFvDymKZUubib90QA=", + "dev": true + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", + "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { "isexe": "^2.0.0" } }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "which-promise": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-promise/-/which-promise-1.0.0.tgz", + "integrity": "sha1-ILch3wWzW3Bhdv+hCwkJq6RgMDU=", + "dev": true, + "requires": { + "pify": "^2.2.0", + "pinkie-promise": "^1.0.0", + "which": "^1.1.2" + }, + "dependencies": { + "pinkie": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-1.0.0.tgz", + "integrity": "sha1-Wkfyi6EBXQIBvae/DzWOR77Ix+Q=", + "dev": true + }, + "pinkie-promise": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-1.0.0.tgz", + "integrity": "sha1-0dpn9UglY7t89X8oauKCLs+/NnA=", + "dev": true, + "requires": { + "pinkie": "^1.0.0" + } + } + } + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "wrapped": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wrapped/-/wrapped-1.0.1.tgz", + "integrity": "sha1-x4PZ2Aeyc+mwHoUWgKk4yHyQckI=", + "dev": true, + "requires": { + "co": "3.1.0", + "sliced": "^1.0.1" + }, + "dependencies": { + "co": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/co/-/co-3.1.0.tgz", + "integrity": "sha1-TqVOpaCJOBUxheFSEMaNkJK8G3g=", + "dev": true + } + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -6566,14 +11179,41 @@ "dev": true }, "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", "dev": true, "requires": { "mkdirp": "^0.5.1" } }, + "ws": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", + "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "x-is-string": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", + "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=", + "dev": true + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "xmlchars": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-1.3.1.tgz", + "integrity": "sha512-tGkGJkN8XqCod7OT+EvGYK5Z4SfDQGD30zAa58OcnAa0RRWgzUEK72tkXhsX1FZd+rgnhRxFtmO+ihkp8LHSkw==", + "dev": true + }, "xmlcreate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-1.0.2.tgz", @@ -6581,10 +11221,62 @@ "dev": true }, "xtend": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.2.0.tgz", - "integrity": "sha1-7vax8ZjByN6vrYsXZaBNrUoBxak=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-10.1.2.tgz", + "integrity": "sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^8.1.0" + }, + "dependencies": { + "yargs-parser": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz", + "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } } } } diff --git a/package.json b/package.json index fb2ba2e6..24fb061c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svgedit", - "version": "3.0.0-rc.2", + "version": "4.2.0", "description": "Powerful SVG-Editor for your browser ", "main": "dist/index-umd.js", "module": "dist/index-es.js", @@ -9,23 +9,27 @@ "example": "examples", "test": "test" }, - "engines": {}, + "engines": { + "node": ">= 7.6.0" + }, "scripts": { "prepublishOnly": "npm run test-prep", "build-config": "rollup -c rollup-config.config.js", - "grep-doc": "node grep-jsdoc", + "types-doc": "npx babel-node --plugins @babel/plugin-transform-modules-commonjs jsdoc-check-overly-generic-types.js", "open-es-allext": "opn http://localhost:8000/editor/svg-editor-es.html?extensions=ext-arrows.js,ext-closepath.js,ext-foreignobject.js,ext-helloworld.js,ext-mathjax.js,ext-php_savefile.js,ext-server_moinsave.js,ext-server_opensave.js,ext-webappfind.js,ext-xdomain-messaging.js", - "build-doc": "rm -rf docs/jsdoc/*;jsdoc --pedantic -c docs/jsdoc-config.json editor", - "build-html": "node build-html.js", + "build-doc": "rm -rf docs/jsdoc/*;jsdoc --pedantic -c docs/jsdoc-config.js editor", + "build-html": "npx babel-node --plugins @babel/plugin-transform-modules-commonjs build-html.js", "compress-images": "imageoptim 'chrome-app/*.png' && imageoptim 'editor/extensions/*.png' && imageoptim 'editor/spinbtn/*.png' && imageoptim 'editor/jgraduate/images/*.{png,gif}' && imageoptim 'editor/images/*.png'", - "copy-deps": "cp node_modules/load-stylesheets/dist/index-es.js editor/external/load-stylesheets/index-es.js && cp node_modules/babel-polyfill/dist/polyfill.min.js editor/external/babel-polyfill/polyfill.min.js && cp node_modules/babel-polyfill/dist/polyfill.js editor/external/babel-polyfill/polyfill.js", - "eslint": "eslint .", + "copy": "cp node_modules/load-stylesheets/dist/index-es.js editor/external/load-stylesheets/index-es.js && cp node_modules/@babel/polyfill/dist/polyfill.min.js editor/external/@babel/polyfill/polyfill.min.js && cp node_modules/@babel/polyfill/dist/polyfill.js editor/external/@babel/polyfill/polyfill.js && cp node_modules/jamilih/dist/jml-es.js editor/external/jamilih/jml-es.js && cp node_modules/query-result/esm/index.js editor/external/query-result/esm/index.js && cp node_modules/qr-manipulation/dist/index-es.js editor/external/qr-manipulation/dist/index-es.js && cp node_modules/stackblur-canvas/dist/stackblur-es.js editor/external/stackblur-canvas/dist/stackblur-es.js", + "remark": "remark -q -f .", + "eslint": "eslint --report-unused-disable-directives --ext js,md .", "rollup": "rollup -c", "start-embedded": "echo \"Open file to http://localhost:8000/editor/embedapi.html\" && static -p 8000 | static -p 8001 -H '{\"Access-Control-Allow-Origin\": \"*\"}'", "start": "echo \"Open file to http://localhost:8000/test/all_tests.html\" && static -p 8000", "test-no-build": "npm run eslint && npm run build-html && npm run build-config && opn http://localhost:8000/test/all_tests.html && static -p 8000", "test-prep": "npm run eslint && npm run build-html && npm run rollup && npm run build-config", - "test": "npm run test-prep && opn http://localhost:8000/test/all_tests.html && static -p 8000" + "test": "testcafe chrome test/ui-tests/**/*.js", + "browser-test": "npm run test-prep && opn http://localhost:8000/test/all_tests.html && static -p 8000" }, "repository": { "type": "git", @@ -51,37 +55,74 @@ "url": "https://github.com/SVG-Edit/svgedit/issues" }, "homepage": "https://github.com/SVG-Edit/svgedit#readme", + "browserslist": [ + "cover 100%", + "last 3 Chrome versions", + "last 3 Firefox versions", + "last 3 Edge versions", + "last 3 Safari versions", + "last 3 ios_saf versions", + "last 3 Android versions", + "last 3 Opera versions", + "last 3 IE versions", + "last 3 op_mini versions", + "last 3 bb versions", + "last 3 op_mob versions", + "last 3 and_chr versions", + "last 3 and_ff versions", + "last 3 ie_mob versions", + "last 3 and_uc versions", + "last 3 Samsung versions" + ], "dependencies": {}, "devDependencies": { - "babel-core": "6.26.3", - "babel-plugin-external-helpers": "^6.22.0", - "babel-plugin-transform-object-rest-spread": "^6.26.0", - "babel-polyfill": "^6.26.0", - "babel-preset-env": "^1.7.0", - "eslint": "5.5.0", + "@babel/core": "^7.3.3", + "@babel/node": "^7.2.2", + "@babel/plugin-transform-modules-commonjs": "^7.2.0", + "@babel/polyfill": "^7.2.5", + "@babel/preset-env": "^7.3.1", + "@mysticatea/eslint-plugin": "^9.0.1", + "axe-testcafe": "^1.1.0", + "babel-plugin-transform-object-rest-spread": "^7.0.0-beta.3", + "eslint": "5.14.1", + "eslint-config-ash-nazg": "0.4.4", "eslint-config-standard": "12.0.0", - "eslint-plugin-import": "2.14.0", - "eslint-plugin-node": "7.0.1", - "eslint-plugin-promise": "4.0.0", - "eslint-plugin-qunit": "^3.3.1", + "eslint-plugin-compat": "2.7.0", + "eslint-plugin-eslint-comments": "^3.1.1", + "eslint-plugin-import": "2.16.0", + "eslint-plugin-jsdoc": "^4.1.0", + "eslint-plugin-markdown": "^1.0.0", + "eslint-plugin-no-use-extend-native": "^0.4.0", + "eslint-plugin-node": "8.0.1", + "eslint-plugin-promise": "4.0.1", + "eslint-plugin-qunit": "^4.0.0", "eslint-plugin-standard": "4.0.0", + "eslint-plugin-testcafe": "^0.2.1", + "eslint-plugin-unicorn": "^7.1.0", "find-in-files": "^0.5.0", - "imageoptim-cli": "^2.0.3", + "imageoptim-cli": "^2.3.5", + "jamilih": "^0.44.0", "jsdoc": "^3.5.5", "load-stylesheets": "^0.7.0", - "node-static": "^0.7.10", - "opn-cli": "^3.1.0", - "promise-fs": "^1.3.0", - "qunit": "^2.6.2", - "rollup": "0.65.2", - "rollup-plugin-babel": "^3.0.7", - "rollup-plugin-commonjs": "^9.1.6", - "rollup-plugin-json": "^3.0.0", + "node-static": "^0.7.11", + "opn-cli": "^4.0.0", + "promise-fs": "^2.0.1", + "qr-manipulation": "https://github.com/brettz9/qr-manipulation", + "query-result": "https://github.com/WebReflection/query-result", + "qunit": "^2.9.1", + "remark-cli": "^6.0.1", + "remark-lint-ordered-list-marker-value": "^1.0.2", + "rollup": "1.2.2", + "rollup-plugin-babel": "^4.3.2", + "rollup-plugin-commonjs": "^9.2.0", + "rollup-plugin-json": "^3.1.0", "rollup-plugin-node-builtins": "^2.1.2", - "rollup-plugin-node-resolve": "^3.4.0", + "rollup-plugin-node-resolve": "^4.0.0", "rollup-plugin-re": "^1.0.7", - "rollup-plugin-terser": "^2.0.2", - "sinon": "^6.2.0", - "sinon-test": "^2.3.0" + "rollup-plugin-terser": "^4.0.4", + "sinon": "^7.2.4", + "sinon-test": "^2.4.0", + "stackblur-canvas": "^2.2.0", + "testcafe": "^1.0.1" } } diff --git a/rollup-config.config.js b/rollup-config.config.js index 6f2122af..20544f17 100644 --- a/rollup-config.config.js +++ b/rollup-config.config.js @@ -33,6 +33,7 @@ window.svgEditor.modules = false; }) ]; +/* eslint-disable import/no-anonymous-default-export */ export default [ { input: 'svgedit-config-es.js', @@ -51,3 +52,4 @@ export default [ plugins } ]; +/* eslint-enable import/no-anonymous-default-export */ diff --git a/rollup.config.js b/rollup.config.js index 7beae993..02b8f69b 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -8,16 +8,17 @@ import babel from 'rollup-plugin-babel'; import {terser} from 'rollup-plugin-terser'; import replace from 'rollup-plugin-re'; -const {lstatSync, readdirSync} = require('fs'); +const {lstatSync, readdirSync} = require('fs'); // eslint-disable-line import/no-commonjs +const {join, basename} = require('path'); // eslint-disable-line import/no-commonjs + const localeFiles = readdirSync('editor/locale'); const extensionFiles = readdirSync('editor/extensions'); -const {join, basename} = require('path'); const isDirectory = (source) => { return lstatSync(source).isDirectory(); }; const getDirectories = (source) => { - return readdirSync(source).map(name => join(source, name)).filter(isDirectory); + return readdirSync(source).map((nme) => join(source, nme)).filter((i) => isDirectory(i)); }; const extensionLocaleDirs = getDirectories('editor/extensions/ext-locale'); const extensionLocaleFiles = []; @@ -27,6 +28,18 @@ extensionLocaleDirs.forEach((dir) => { }); }); +/** + * @external RollupConfig + * @type {PlainObject} + * @see {@link https://rollupjs.org/guide/en#big-list-of-options} + */ + +/** + * @param {PlainObject} config + * @param {boolean} config.minifying + * @param {string} [config.format='umd'} = {}] + * @returns {external:RollupConfig} + */ function getRollupObject ({minifying, format = 'umd'} = {}) { const nonMinified = { input: 'editor/svg-editor.js', @@ -60,6 +73,23 @@ export default [ getRollupObject({minifying: true, format: 'es'}), getRollupObject({minifying: false, format: 'es'}), // **/ + ...[true, false].map((min) => { + return { + input: 'editor/svgcanvas.js', + output: { + format: 'iife', + sourcemap: min, + name: 'SvgCanvas', + file: `dist/svgcanvas-iife${min ? '.min' : ''}.js` + }, + plugins: [ + babel({ + plugins: ['transform-object-rest-spread'] + }), + min ? terser() : null + ] + }; + }), ...extensionLocaleFiles.map(([dir, file]) => { const lang = file.replace(/\.js$/, '').replace(/-/g, '_'); return { @@ -69,9 +99,7 @@ export default [ name: `svgEditorExtensionLocale_${basename(dir)}_${lang}`, file: `dist/extensions/ext-locale/${basename(dir)}/${file}` }, - plugins: [ - babel() - ] + plugins: [babel()] }; }), { @@ -80,9 +108,7 @@ export default [ format: 'iife', file: `dist/redirect-on-lacking-support.js` }, - plugins: [ - babel() - ] + plugins: [babel()] }, { input: 'editor/jspdf/jspdf.plugin.svgToPdf.js', @@ -90,9 +116,7 @@ export default [ format: 'iife', file: `dist/jspdf.plugin.svgToPdf.js` }, - plugins: [ - babel() - ] + plugins: [babel()] }, { input: 'editor/extensions/imagelib/index.js', @@ -106,15 +130,25 @@ export default [ }) ] }, + { + input: 'editor/extensions/imagelib/openclipart.js', + output: { + format: 'iife', + file: 'dist/extensions/imagelib/openclipart.js' + }, + plugins: [ + babel({ + plugins: ['transform-object-rest-spread'] + }) + ] + }, { input: 'editor/external/dom-polyfill/dom-polyfill.js', output: { format: 'iife', file: 'dist/dom-polyfill.js' }, - plugins: [ - babel() - ] + plugins: [babel()] }, { input: 'editor/canvg/canvg.js', @@ -123,16 +157,14 @@ export default [ name: 'canvg', file: 'dist/canvg.js' }, - plugins: [ - babel() - ] + plugins: [babel()] }, ...localeFiles.map((localeFile) => { // lang.*.js const localeRegex = /^lang\.([\w-]+?)\.js$/; const lang = localeFile.match(localeRegex); if (!lang) { - return; + return undefined; } return { input: 'editor/locale/' + localeFile, @@ -142,7 +174,8 @@ export default [ file: 'dist/locale/' + localeFile }, plugins: [ - babel() // Probably don't need here, but... + // Probably don't need here, but... + babel() ] }; }), @@ -150,7 +183,7 @@ export default [ // ext-*.js const extensionName = extensionFile.match(/^ext-(.+?)\.js$/); if (!extensionName) { - return; + return undefined; } return { input: 'editor/extensions/' + extensionFile, @@ -176,10 +209,10 @@ export default [ // For now, we'll replace with globals // We'll still make at least one import: editor/ext-locale/storage/ `import '../svgpathseg.js';` - ].map((test) => { + ].map((tst) => { return { match: /editor\/extensions/, - test, + test: tst, replace: '' }; }) diff --git a/screencasts/svgopen2010/script.js b/screencasts/svgopen2010/script.js index 5dcb7882..0f20e549 100644 --- a/screencasts/svgopen2010/script.js +++ b/screencasts/svgopen2010/script.js @@ -9,9 +9,9 @@ const byId = function (id) { return id; }; -const query = function (query, root) { - if (!query) { return []; } - if (typeof query !== 'string') { return [...query]; } +const query = function (qry, root) { + if (!qry) { return []; } + if (typeof qry !== 'string') { return [...qry]; } if (typeof root === 'string') { root = byId(root); if (!root) { return []; } @@ -19,17 +19,17 @@ const query = function (query, root) { root = root || document; const rootIsDoc = (root.nodeType === 9); - const doc = rootIsDoc ? root : (root.ownerDocument || document); + const dcmnt = rootIsDoc ? root : (root.ownerDocument || document); // rewrite the query to be ID rooted - if (!rootIsDoc || ('>~+'.includes(query[0]))) { + if (!rootIsDoc || ('>~+'.includes(qry[0]))) { root.id = root.id || ('qUnique' + (ctr++)); - query = '#' + root.id + ' ' + query; + qry = '#' + root.id + ' ' + qry; } // don't choke on something like ".yada.yada >" - if ('>~+'.includes(query.slice(-1))) { query += ' *'; } + if ('>~+'.includes(qry.slice(-1))) { qry += ' *'; } - return [...doc.querySelectorAll(query)]; + return [...dcmnt.querySelectorAll(qry)]; }; const ua = navigator.userAgent; @@ -66,9 +66,11 @@ Slide.prototype = { _buildList: [], _visited: false, _currentState: '', - _states: [ 'distant-slide', 'far-past', + _states: [ + 'distant-slide', 'far-past', 'past', 'current', 'future', - 'far-future', 'distant-slide' ], + 'far-future', 'distant-slide' + ], setState (state) { if (typeof state !== 'string') { state = this._states[state]; @@ -85,8 +87,8 @@ Slide.prototype = { /* this._runAutos(); */ - const _t = this; - setTimeout(function () { _t._runAutos(); }, 400); + const that = this; + setTimeout(function () { that._runAutos(); }, 400); }, _makeCounter () { if (!this._count || !this._node) { return; } @@ -121,18 +123,18 @@ Slide.prototype = { if (idx >= 0) { const elem = this._buildList.splice(idx, 1)[0]; const transitionEnd = isWK ? 'webkitTransitionEnd' : (isFF ? 'mozTransitionEnd' : 'oTransitionEnd'); - const _t = this; + const that = this; if (canTransition()) { const l = function (evt) { - elem.parentNode.removeEventListener(transitionEnd, l, false); - _t._runAutos(); + elem.parentNode.removeEventListener(transitionEnd, l); + that._runAutos(); }; - elem.parentNode.addEventListener(transitionEnd, l, false); + elem.parentNode.addEventListener(transitionEnd, l); elem.classList.remove('to-build'); } else { setTimeout(function () { elem.classList.remove('to-build'); - _t._runAutos(); + that._runAutos(); }, 400); } } @@ -156,22 +158,22 @@ const SlideShow = function (slides) { const h = window.location.hash; try { - this.current = parseInt(h.split('#slide')[1], 10); + this.current = parseInt(h.split('#slide')[1]); } catch (e) { /* squeltch */ } this.current = isNaN(this.current) ? 1 : this.current; - const _t = this; + const that = this; doc.addEventListener('keydown', - function (e) { _t.handleKeys(e); }, false); + function (e) { that.handleKeys(e); }); doc.addEventListener('mousewheel', - function (e) { _t.handleWheel(e); }, false); + function (e) { that.handleWheel(e); }); doc.addEventListener('DOMMouseScroll', - function (e) { _t.handleWheel(e); }, false); + function (e) { that.handleWheel(e); }); doc.addEventListener('touchstart', - function (e) { _t.handleTouchStart(e); }, false); + function (e) { that.handleTouchStart(e); }); doc.addEventListener('touchend', - function (e) { _t.handleTouchEnd(e); }, false); + function (e) { that.handleTouchEnd(e); }); window.addEventListener('popstate', - function (e) { _t.go(e.state); }, false); + function (e) { that.go(e.state); }); this._update(); }; @@ -242,7 +244,7 @@ SlideShow.prototype = { } }, handleKeys (e) { - if (/^(input|textarea)$/i.test(e.target.nodeName)) return; + if ((/^(input|textarea)$/i).test(e.target.nodeName)) return; switch (e.keyCode) { case 37: // left arrow @@ -272,25 +274,33 @@ SlideShow.prototype = { }; // Initialize -const slideshow = new SlideShow(query('.slide')); // eslint-disable-line no-unused-vars +/* const slideshow = */ new SlideShow(query('.slide')); // eslint-disable-line no-new -document.querySelector('#toggle-counter').addEventListener('click', toggleCounter, false); -document.querySelector('#toggle-size').addEventListener('click', toggleSize, false); -document.querySelector('#toggle-transitions').addEventListener('click', toggleTransitions, false); -document.querySelector('#toggle-gradients').addEventListener('click', toggleGradients, false); +document.querySelector('#toggle-counter').addEventListener('click', toggleCounter); +document.querySelector('#toggle-size').addEventListener('click', toggleSize); +document.querySelector('#toggle-transitions').addEventListener('click', toggleTransitions); +document.querySelector('#toggle-gradients').addEventListener('click', toggleGradients); const counters = document.querySelectorAll('.counter'); const slides = document.querySelectorAll('.slide'); +/** + * Show or hide the counters. + * @returns {undefined} + */ function toggleCounter () { [...counters].forEach(function (el) { el.style.display = (el.offsetHeight) ? 'none' : 'block'; }); } +/** + * Add or remove `reduced` (size) class. + * @returns {undefined} + */ function toggleSize () { [...slides].forEach(function (el) { - if (!/reduced/.test(el.className)) { + if (!(/reduced/).test(el.className)) { el.classList.add('reduced'); } else { el.classList.remove('reduced'); @@ -298,9 +308,13 @@ function toggleSize () { }); } +/** + * Add or remove `no-transitions` class. + * @returns {undefined} + */ function toggleTransitions () { [...slides].forEach(function (el) { - if (!/no-transitions/.test(el.className)) { + if (!(/no-transitions/).test(el.className)) { el.classList.add('no-transitions'); } else { el.classList.remove('no-transitions'); @@ -308,9 +322,13 @@ function toggleTransitions () { }); } +/** + * Add or remove `no-gradients` class. + * @returns {undefined} + */ function toggleGradients () { [...slides].forEach(function (el) { - if (!/no-gradients/.test(el.className)) { + if (!(/no-gradients/).test(el.className)) { el.classList.add('no-gradients'); } else { el.classList.remove('no-gradients'); diff --git a/svgedit-config-es.js b/svgedit-config-es.js index c90fc147..1511c4e2 100644 --- a/svgedit-config-es.js +++ b/svgedit-config-es.js @@ -87,11 +87,11 @@ svgEditor.setConfig({ // jGraduatePath: 'jgraduate/images/', /* Uncomment the following to allow at least same domain (embedded) access, - including file:// access. + including `file:///` access. Setting as `['*']` would allow any domain to access but would be unsafe to data privacy and integrity. */ - // allowedOrigins: [window.location.origin || 'null'], // May be 'null' (as a string) when used as a file:// URL + // allowedOrigins: [location.origin || 'null'], // May be 'null' (as a string) when used as a `file:///` URL // DOCUMENT PROPERTIES // dimensions: [640, 480], // EDITOR OPTIONS diff --git a/svgedit-config-iife.js b/svgedit-config-iife.js index 4721995a..c4979214 100644 --- a/svgedit-config-iife.js +++ b/svgedit-config-iife.js @@ -1,20 +1,226 @@ (function () { 'use strict'; + function _typeof(obj) { + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); + } + + function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { + try { + var info = gen[key](arg); + var value = info.value; + } catch (error) { + reject(error); + return; + } + + if (info.done) { + resolve(value); + } else { + Promise.resolve(value).then(_next, _throw); + } + } + + function _asyncToGenerator(fn) { + return function () { + var self = this, + args = arguments; + return new Promise(function (resolve, reject) { + var gen = fn.apply(self, args); + + function _next(value) { + asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); + } + + function _throw(err) { + asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); + } + + _next(undefined); + }); + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } + + function _extends() { + _extends = Object.assign || function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target; + }; + + return _extends.apply(this, arguments); + } + + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf(subClass, superClass); + } + + function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); + } + + function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + return _setPrototypeOf(o, p); + } + + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; + } + + function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } + + return _assertThisInitialized(self); + } + + function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); + } + + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); + } + + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) { + for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; + + return arr2; + } + } + + function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; + } + + function _iterableToArray(iter) { + if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); + } + + function _iterableToArrayLimit(arr, i) { + var _arr = []; + var _n = true; + var _d = false; + var _e = undefined; + + try { + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; + } + } + + return _arr; + } + + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance"); + } + + function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance"); + } + // http://ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript/ + + /** + * + * @param {Event} ev + * @returns {undefined} + */ function touchHandler(ev) { var changedTouches = ev.changedTouches, first = changedTouches[0]; - - var type = ''; + switch (ev.type) { case 'touchstart': - type = 'mousedown';break; + type = 'mousedown'; + break; + case 'touchmove': - type = 'mousemove';break; + type = 'mousemove'; + break; + case 'touchend': - type = 'mouseup';break; + type = 'mouseup'; + break; + default: return; } @@ -22,7 +228,7 @@ var screenX = first.screenX, screenY = first.screenY, clientX = first.clientX, - clientY = first.clientY; + clientY = first.clientY; // eslint-disable-line no-shadow var simulatedEvent = new MouseEvent(type, { // Event interface @@ -30,17 +236,23 @@ cancelable: true, // UIEvent interface view: window, - detail: 1, // click count + detail: 1, + // click count // MouseEvent interface (customized) - screenX: screenX, screenY: screenY, clientX: clientX, clientY: clientY, + screenX: screenX, + screenY: screenY, + clientX: clientX, + clientY: clientY, // MouseEvent interface (defaults) - these could be removed ctrlKey: false, altKey: false, shiftKey: false, metaKey: false, - button: 0, // main button (usually left) + button: 0, + // main button (usually left) relatedTarget: null }); + if (changedTouches.length < 2) { first.target.dispatchEvent(simulatedEvent); ev.preventDefault(); @@ -52,151 +264,6 @@ document.addEventListener('touchend', touchHandler, true); document.addEventListener('touchcancel', touchHandler, true); - var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { - return typeof obj; - } : function (obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; - }; - - var asyncToGenerator = function (fn) { - return function () { - var gen = fn.apply(this, arguments); - return new Promise(function (resolve, reject) { - function step(key, arg) { - try { - var info = gen[key](arg); - var value = info.value; - } catch (error) { - reject(error); - return; - } - - if (info.done) { - resolve(value); - } else { - return Promise.resolve(value).then(function (value) { - step("next", value); - }, function (err) { - step("throw", err); - }); - } - } - - return step("next"); - }); - }; - }; - - var classCallCheck = function (instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } - }; - - var createClass = function () { - function defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } - } - - return function (Constructor, protoProps, staticProps) { - if (protoProps) defineProperties(Constructor.prototype, protoProps); - if (staticProps) defineProperties(Constructor, staticProps); - return Constructor; - }; - }(); - - var _extends = Object.assign || function (target) { - for (var i = 1; i < arguments.length; i++) { - var source = arguments[i]; - - for (var key in source) { - if (Object.prototype.hasOwnProperty.call(source, key)) { - target[key] = source[key]; - } - } - } - - return target; - }; - - var inherits = function (subClass, superClass) { - if (typeof superClass !== "function" && superClass !== null) { - throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); - } - - subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - value: subClass, - enumerable: false, - writable: true, - configurable: true - } - }); - if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; - }; - - var possibleConstructorReturn = function (self, call) { - if (!self) { - throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); - } - - return call && (typeof call === "object" || typeof call === "function") ? call : self; - }; - - var slicedToArray = function () { - function sliceIterator(arr, i) { - var _arr = []; - var _n = true; - var _d = false; - var _e = undefined; - - try { - for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { - _arr.push(_s.value); - - if (i && _arr.length === i) break; - } - } catch (err) { - _d = true; - _e = err; - } finally { - try { - if (!_n && _i["return"]) _i["return"](); - } finally { - if (_d) throw _e; - } - } - - return _arr; - } - - return function (arr, i) { - if (Array.isArray(arr)) { - return arr; - } else if (Symbol.iterator in Object(arr)) { - return sliceIterator(arr, i); - } else { - throw new TypeError("Invalid attempt to destructure non-iterable instance"); - } - }; - }(); - - var toConsumableArray = function (arr) { - if (Array.isArray(arr)) { - for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; - - return arr2; - } else { - return Array.from(arr); - } - }; - /** * Namespaces or tools therefor * @module namespaces @@ -217,16 +284,17 @@ XLINK: 'http://www.w3.org/1999/xlink', XML: 'http://www.w3.org/XML/1998/namespace', XMLNS: 'http://www.w3.org/2000/xmlns/' // see http://www.w3.org/TR/REC-xml-names/#xmlReserved - }; + }; /** * @function module:namespaces.getReverseNS * @returns {string} The NS with key values switched and lowercase */ + var getReverseNS = function getReverseNS() { var reverseNS = {}; Object.entries(NS).forEach(function (_ref) { - var _ref2 = slicedToArray(_ref, 2), + var _ref2 = _slicedToArray(_ref, 2), name = _ref2[0], URI = _ref2[1]; @@ -244,6 +312,7 @@ SVGPathSegCurvetoCubicSmoothAbs, SVGPathSegCurvetoQuadraticRel, SVGPathSegCurvetoQuadraticAbs, SVGPathSegCurvetoQuadraticSmoothRel, SVGPathSegCurvetoQuadraticSmoothAbs, SVGPathSegArcRel, SVGPathSegArcAbs */ + /** * SVGPathSeg API polyfill * https://github.com/progers/pathseg @@ -253,33 +322,39 @@ * including the latest spec changes which were implemented in Firefox 43 and * Chrome 46. */ + + /* eslint-disable no-shadow, class-methods-use-this */ + // Linting: We avoid `no-shadow` as ESLint thinks these are still available globals + // Linting: We avoid `class-methods-use-this` as this is a polyfill that must + // follow the conventions (function () { if (!('SVGPathSeg' in window)) { // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSeg - var _SVGPathSeg = function () { + var _SVGPathSeg = + /*#__PURE__*/ + function () { function _SVGPathSeg(type, typeAsLetter, owningPathSegList) { - classCallCheck(this, _SVGPathSeg); + _classCallCheck(this, _SVGPathSeg); this.pathSegType = type; this.pathSegTypeAsLetter = typeAsLetter; this._owningPathSegList = owningPathSegList; - } - // Notify owning PathSegList on any changes so they can be synchronized back to the path element. + } // Notify owning PathSegList on any changes so they can be synchronized back to the path element. - createClass(_SVGPathSeg, [{ - key: '_segmentChanged', + _createClass(_SVGPathSeg, [{ + key: "_segmentChanged", value: function _segmentChanged() { if (this._owningPathSegList) { this._owningPathSegList.segmentChanged(this); } } }]); + return _SVGPathSeg; }(); _SVGPathSeg.prototype.classname = 'SVGPathSeg'; - _SVGPathSeg.PATHSEG_UNKNOWN = 0; _SVGPathSeg.PATHSEG_CLOSEPATH = 1; _SVGPathSeg.PATHSEG_MOVETO_ABS = 2; @@ -301,247 +376,401 @@ _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18; _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19; - var _SVGPathSegClosePath = function (_SVGPathSeg2) { - inherits(_SVGPathSegClosePath, _SVGPathSeg2); + var _SVGPathSegClosePath = + /*#__PURE__*/ + function (_SVGPathSeg2) { + _inherits(_SVGPathSegClosePath, _SVGPathSeg2); function _SVGPathSegClosePath(owningPathSegList) { - classCallCheck(this, _SVGPathSegClosePath); - return possibleConstructorReturn(this, (_SVGPathSegClosePath.__proto__ || Object.getPrototypeOf(_SVGPathSegClosePath)).call(this, _SVGPathSeg.PATHSEG_CLOSEPATH, 'z', owningPathSegList)); + _classCallCheck(this, _SVGPathSegClosePath); + + return _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegClosePath).call(this, _SVGPathSeg.PATHSEG_CLOSEPATH, 'z', owningPathSegList)); } - createClass(_SVGPathSegClosePath, [{ - key: 'toString', + _createClass(_SVGPathSegClosePath, [{ + key: "toString", value: function toString() { return '[object SVGPathSegClosePath]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegClosePath(undefined); } }]); + return _SVGPathSegClosePath; }(_SVGPathSeg); - var _SVGPathSegMovetoAbs = function (_SVGPathSeg3) { - inherits(_SVGPathSegMovetoAbs, _SVGPathSeg3); + var _SVGPathSegMovetoAbs = + /*#__PURE__*/ + function (_SVGPathSeg3) { + _inherits(_SVGPathSegMovetoAbs, _SVGPathSeg3); function _SVGPathSegMovetoAbs(owningPathSegList, x, y) { - classCallCheck(this, _SVGPathSegMovetoAbs); + var _this; - var _this2 = possibleConstructorReturn(this, (_SVGPathSegMovetoAbs.__proto__ || Object.getPrototypeOf(_SVGPathSegMovetoAbs)).call(this, _SVGPathSeg.PATHSEG_MOVETO_ABS, 'M', owningPathSegList)); + _classCallCheck(this, _SVGPathSegMovetoAbs); - _this2._x = x; - _this2._y = y; - return _this2; + _this = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegMovetoAbs).call(this, _SVGPathSeg.PATHSEG_MOVETO_ABS, 'M', owningPathSegList)); + _this._x = x; + _this._y = y; + return _this; } - createClass(_SVGPathSegMovetoAbs, [{ - key: 'toString', + _createClass(_SVGPathSegMovetoAbs, [{ + key: "toString", value: function toString() { return '[object SVGPathSegMovetoAbs]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegMovetoAbs(undefined, this._x, this._y); } }]); + return _SVGPathSegMovetoAbs; }(_SVGPathSeg); Object.defineProperties(_SVGPathSegMovetoAbs.prototype, { x: { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); + set: function set(x) { + this._x = x; + + this._segmentChanged(); }, enumerable: true }, y: { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); + set: function set(y) { + this._y = y; + + this._segmentChanged(); }, enumerable: true } }); - var _SVGPathSegMovetoRel = function (_SVGPathSeg4) { - inherits(_SVGPathSegMovetoRel, _SVGPathSeg4); + var _SVGPathSegMovetoRel = + /*#__PURE__*/ + function (_SVGPathSeg4) { + _inherits(_SVGPathSegMovetoRel, _SVGPathSeg4); function _SVGPathSegMovetoRel(owningPathSegList, x, y) { - classCallCheck(this, _SVGPathSegMovetoRel); + var _this2; - var _this3 = possibleConstructorReturn(this, (_SVGPathSegMovetoRel.__proto__ || Object.getPrototypeOf(_SVGPathSegMovetoRel)).call(this, _SVGPathSeg.PATHSEG_MOVETO_REL, 'm', owningPathSegList)); + _classCallCheck(this, _SVGPathSegMovetoRel); - _this3._x = x; - _this3._y = y; - return _this3; + _this2 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegMovetoRel).call(this, _SVGPathSeg.PATHSEG_MOVETO_REL, 'm', owningPathSegList)); + _this2._x = x; + _this2._y = y; + return _this2; } - createClass(_SVGPathSegMovetoRel, [{ - key: 'toString', + _createClass(_SVGPathSegMovetoRel, [{ + key: "toString", value: function toString() { return '[object SVGPathSegMovetoRel]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegMovetoRel(undefined, this._x, this._y); } }]); + return _SVGPathSegMovetoRel; }(_SVGPathSeg); Object.defineProperties(_SVGPathSegMovetoRel.prototype, { x: { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); + set: function set(x) { + this._x = x; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y: { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); + set: function set(y) { + this._y = y; + + this._segmentChanged(); }, - enumerable: true } + enumerable: true + } }); - var _SVGPathSegLinetoAbs = function (_SVGPathSeg5) { - inherits(_SVGPathSegLinetoAbs, _SVGPathSeg5); + var _SVGPathSegLinetoAbs = + /*#__PURE__*/ + function (_SVGPathSeg5) { + _inherits(_SVGPathSegLinetoAbs, _SVGPathSeg5); function _SVGPathSegLinetoAbs(owningPathSegList, x, y) { - classCallCheck(this, _SVGPathSegLinetoAbs); + var _this3; - var _this4 = possibleConstructorReturn(this, (_SVGPathSegLinetoAbs.__proto__ || Object.getPrototypeOf(_SVGPathSegLinetoAbs)).call(this, _SVGPathSeg.PATHSEG_LINETO_ABS, 'L', owningPathSegList)); + _classCallCheck(this, _SVGPathSegLinetoAbs); - _this4._x = x; - _this4._y = y; - return _this4; + _this3 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegLinetoAbs).call(this, _SVGPathSeg.PATHSEG_LINETO_ABS, 'L', owningPathSegList)); + _this3._x = x; + _this3._y = y; + return _this3; } - createClass(_SVGPathSegLinetoAbs, [{ - key: 'toString', + _createClass(_SVGPathSegLinetoAbs, [{ + key: "toString", value: function toString() { return '[object SVGPathSegLinetoAbs]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegLinetoAbs(undefined, this._x, this._y); } }]); + return _SVGPathSegLinetoAbs; }(_SVGPathSeg); Object.defineProperties(_SVGPathSegLinetoAbs.prototype, { x: { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); + set: function set(x) { + this._x = x; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y: { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); + set: function set(y) { + this._y = y; + + this._segmentChanged(); }, - enumerable: true } + enumerable: true + } }); - var _SVGPathSegLinetoRel = function (_SVGPathSeg6) { - inherits(_SVGPathSegLinetoRel, _SVGPathSeg6); + var _SVGPathSegLinetoRel = + /*#__PURE__*/ + function (_SVGPathSeg6) { + _inherits(_SVGPathSegLinetoRel, _SVGPathSeg6); function _SVGPathSegLinetoRel(owningPathSegList, x, y) { - classCallCheck(this, _SVGPathSegLinetoRel); + var _this4; - var _this5 = possibleConstructorReturn(this, (_SVGPathSegLinetoRel.__proto__ || Object.getPrototypeOf(_SVGPathSegLinetoRel)).call(this, _SVGPathSeg.PATHSEG_LINETO_REL, 'l', owningPathSegList)); + _classCallCheck(this, _SVGPathSegLinetoRel); - _this5._x = x; - _this5._y = y; - return _this5; + _this4 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegLinetoRel).call(this, _SVGPathSeg.PATHSEG_LINETO_REL, 'l', owningPathSegList)); + _this4._x = x; + _this4._y = y; + return _this4; } - createClass(_SVGPathSegLinetoRel, [{ - key: 'toString', + _createClass(_SVGPathSegLinetoRel, [{ + key: "toString", value: function toString() { return '[object SVGPathSegLinetoRel]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegLinetoRel(undefined, this._x, this._y); } }]); + return _SVGPathSegLinetoRel; }(_SVGPathSeg); Object.defineProperties(_SVGPathSegLinetoRel.prototype, { x: { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); + set: function set(x) { + this._x = x; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y: { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); + set: function set(y) { + this._y = y; + + this._segmentChanged(); }, - enumerable: true } + enumerable: true + } }); - var _SVGPathSegCurvetoCubicAbs = function (_SVGPathSeg7) { - inherits(_SVGPathSegCurvetoCubicAbs, _SVGPathSeg7); + var _SVGPathSegCurvetoCubicAbs = + /*#__PURE__*/ + function (_SVGPathSeg7) { + _inherits(_SVGPathSegCurvetoCubicAbs, _SVGPathSeg7); function _SVGPathSegCurvetoCubicAbs(owningPathSegList, x, y, x1, y1, x2, y2) { - classCallCheck(this, _SVGPathSegCurvetoCubicAbs); + var _this5; - var _this6 = possibleConstructorReturn(this, (_SVGPathSegCurvetoCubicAbs.__proto__ || Object.getPrototypeOf(_SVGPathSegCurvetoCubicAbs)).call(this, _SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS, 'C', owningPathSegList)); + _classCallCheck(this, _SVGPathSegCurvetoCubicAbs); + _this5 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegCurvetoCubicAbs).call(this, _SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS, 'C', owningPathSegList)); + _this5._x = x; + _this5._y = y; + _this5._x1 = x1; + _this5._y1 = y1; + _this5._x2 = x2; + _this5._y2 = y2; + return _this5; + } + + _createClass(_SVGPathSegCurvetoCubicAbs, [{ + key: "toString", + value: function toString() { + return '[object SVGPathSegCurvetoCubicAbs]'; + } + }, { + key: "_asPathString", + value: function _asPathString() { + return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; + } + }, { + key: "clone", + value: function clone() { + return new _SVGPathSegCurvetoCubicAbs(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); + } + }]); + + return _SVGPathSegCurvetoCubicAbs; + }(_SVGPathSeg); + + Object.defineProperties(_SVGPathSegCurvetoCubicAbs.prototype, { + x: { + get: function get() { + return this._x; + }, + set: function set(x) { + this._x = x; + + this._segmentChanged(); + }, + enumerable: true + }, + y: { + get: function get() { + return this._y; + }, + set: function set(y) { + this._y = y; + + this._segmentChanged(); + }, + enumerable: true + }, + x1: { + get: function get() { + return this._x1; + }, + set: function set(x1) { + this._x1 = x1; + + this._segmentChanged(); + }, + enumerable: true + }, + y1: { + get: function get() { + return this._y1; + }, + set: function set(y1) { + this._y1 = y1; + + this._segmentChanged(); + }, + enumerable: true + }, + x2: { + get: function get() { + return this._x2; + }, + set: function set(x2) { + this._x2 = x2; + + this._segmentChanged(); + }, + enumerable: true + }, + y2: { + get: function get() { + return this._y2; + }, + set: function set(y2) { + this._y2 = y2; + + this._segmentChanged(); + }, + enumerable: true + } + }); + + var _SVGPathSegCurvetoCubicRel = + /*#__PURE__*/ + function (_SVGPathSeg8) { + _inherits(_SVGPathSegCurvetoCubicRel, _SVGPathSeg8); + + function _SVGPathSegCurvetoCubicRel(owningPathSegList, x, y, x1, y1, x2, y2) { + var _this6; + + _classCallCheck(this, _SVGPathSegCurvetoCubicRel); + + _this6 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegCurvetoCubicRel).call(this, _SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, 'c', owningPathSegList)); _this6._x = x; _this6._y = y; _this6._x1 = x1; @@ -551,171 +780,191 @@ return _this6; } - createClass(_SVGPathSegCurvetoCubicAbs, [{ - key: 'toString', - value: function toString() { - return '[object SVGPathSegCurvetoCubicAbs]'; - } - }, { - key: '_asPathString', - value: function _asPathString() { - return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; - } - }, { - key: 'clone', - value: function clone() { - return new _SVGPathSegCurvetoCubicAbs(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); - } - }]); - return _SVGPathSegCurvetoCubicAbs; - }(_SVGPathSeg); - - Object.defineProperties(_SVGPathSegCurvetoCubicAbs.prototype, { - x: { - get: function get$$1() { - return this._x; - }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); - }, - enumerable: true }, - y: { - get: function get$$1() { - return this._y; - }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); - }, - enumerable: true }, - x1: { - get: function get$$1() { - return this._x1; - }, - set: function set$$1(x1) { - this._x1 = x1;this._segmentChanged(); - }, - enumerable: true }, - y1: { - get: function get$$1() { - return this._y1; - }, - set: function set$$1(y1) { - this._y1 = y1;this._segmentChanged(); - }, - enumerable: true }, - x2: { - get: function get$$1() { - return this._x2; - }, - set: function set$$1(x2) { - this._x2 = x2;this._segmentChanged(); - }, - enumerable: true }, - y2: { - get: function get$$1() { - return this._y2; - }, - set: function set$$1(y2) { - this._y2 = y2;this._segmentChanged(); - }, - enumerable: true } - }); - - var _SVGPathSegCurvetoCubicRel = function (_SVGPathSeg8) { - inherits(_SVGPathSegCurvetoCubicRel, _SVGPathSeg8); - - function _SVGPathSegCurvetoCubicRel(owningPathSegList, x, y, x1, y1, x2, y2) { - classCallCheck(this, _SVGPathSegCurvetoCubicRel); - - var _this7 = possibleConstructorReturn(this, (_SVGPathSegCurvetoCubicRel.__proto__ || Object.getPrototypeOf(_SVGPathSegCurvetoCubicRel)).call(this, _SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, 'c', owningPathSegList)); - - _this7._x = x; - _this7._y = y; - _this7._x1 = x1; - _this7._y1 = y1; - _this7._x2 = x2; - _this7._y2 = y2; - return _this7; - } - - createClass(_SVGPathSegCurvetoCubicRel, [{ - key: 'toString', + _createClass(_SVGPathSegCurvetoCubicRel, [{ + key: "toString", value: function toString() { return '[object SVGPathSegCurvetoCubicRel]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegCurvetoCubicRel(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); } }]); + return _SVGPathSegCurvetoCubicRel; }(_SVGPathSeg); Object.defineProperties(_SVGPathSegCurvetoCubicRel.prototype, { x: { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); + set: function set(x) { + this._x = x; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y: { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); + set: function set(y) { + this._y = y; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, x1: { - get: function get$$1() { + get: function get() { return this._x1; }, - set: function set$$1(x1) { - this._x1 = x1;this._segmentChanged(); + set: function set(x1) { + this._x1 = x1; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y1: { - get: function get$$1() { + get: function get() { return this._y1; }, - set: function set$$1(y1) { - this._y1 = y1;this._segmentChanged(); + set: function set(y1) { + this._y1 = y1; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, x2: { - get: function get$$1() { + get: function get() { return this._x2; }, - set: function set$$1(x2) { - this._x2 = x2;this._segmentChanged(); + set: function set(x2) { + this._x2 = x2; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y2: { - get: function get$$1() { + get: function get() { return this._y2; }, - set: function set$$1(y2) { - this._y2 = y2;this._segmentChanged(); + set: function set(y2) { + this._y2 = y2; + + this._segmentChanged(); }, - enumerable: true } + enumerable: true + } }); - var _SVGPathSegCurvetoQuadraticAbs = function (_SVGPathSeg9) { - inherits(_SVGPathSegCurvetoQuadraticAbs, _SVGPathSeg9); + var _SVGPathSegCurvetoQuadraticAbs = + /*#__PURE__*/ + function (_SVGPathSeg9) { + _inherits(_SVGPathSegCurvetoQuadraticAbs, _SVGPathSeg9); function _SVGPathSegCurvetoQuadraticAbs(owningPathSegList, x, y, x1, y1) { - classCallCheck(this, _SVGPathSegCurvetoQuadraticAbs); + var _this7; - var _this8 = possibleConstructorReturn(this, (_SVGPathSegCurvetoQuadraticAbs.__proto__ || Object.getPrototypeOf(_SVGPathSegCurvetoQuadraticAbs)).call(this, _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS, 'Q', owningPathSegList)); + _classCallCheck(this, _SVGPathSegCurvetoQuadraticAbs); + _this7 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegCurvetoQuadraticAbs).call(this, _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS, 'Q', owningPathSegList)); + _this7._x = x; + _this7._y = y; + _this7._x1 = x1; + _this7._y1 = y1; + return _this7; + } + + _createClass(_SVGPathSegCurvetoQuadraticAbs, [{ + key: "toString", + value: function toString() { + return '[object SVGPathSegCurvetoQuadraticAbs]'; + } + }, { + key: "_asPathString", + value: function _asPathString() { + return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x + ' ' + this._y; + } + }, { + key: "clone", + value: function clone() { + return new _SVGPathSegCurvetoQuadraticAbs(undefined, this._x, this._y, this._x1, this._y1); + } + }]); + + return _SVGPathSegCurvetoQuadraticAbs; + }(_SVGPathSeg); + + Object.defineProperties(_SVGPathSegCurvetoQuadraticAbs.prototype, { + x: { + get: function get() { + return this._x; + }, + set: function set(x) { + this._x = x; + + this._segmentChanged(); + }, + enumerable: true + }, + y: { + get: function get() { + return this._y; + }, + set: function set(y) { + this._y = y; + + this._segmentChanged(); + }, + enumerable: true + }, + x1: { + get: function get() { + return this._x1; + }, + set: function set(x1) { + this._x1 = x1; + + this._segmentChanged(); + }, + enumerable: true + }, + y1: { + get: function get() { + return this._y1; + }, + set: function set(y1) { + this._y1 = y1; + + this._segmentChanged(); + }, + enumerable: true + } + }); + + var _SVGPathSegCurvetoQuadraticRel = + /*#__PURE__*/ + function (_SVGPathSeg10) { + _inherits(_SVGPathSegCurvetoQuadraticRel, _SVGPathSeg10); + + function _SVGPathSegCurvetoQuadraticRel(owningPathSegList, x, y, x1, y1) { + var _this8; + + _classCallCheck(this, _SVGPathSegCurvetoQuadraticRel); + + _this8 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegCurvetoQuadraticRel).call(this, _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL, 'q', owningPathSegList)); _this8._x = x; _this8._y = y; _this8._x1 = x1; @@ -723,137 +972,205 @@ return _this8; } - createClass(_SVGPathSegCurvetoQuadraticAbs, [{ - key: 'toString', - value: function toString() { - return '[object SVGPathSegCurvetoQuadraticAbs]'; - } - }, { - key: '_asPathString', - value: function _asPathString() { - return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x + ' ' + this._y; - } - }, { - key: 'clone', - value: function clone() { - return new _SVGPathSegCurvetoQuadraticAbs(undefined, this._x, this._y, this._x1, this._y1); - } - }]); - return _SVGPathSegCurvetoQuadraticAbs; - }(_SVGPathSeg); - - Object.defineProperties(_SVGPathSegCurvetoQuadraticAbs.prototype, { - x: { - get: function get$$1() { - return this._x; - }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); - }, - enumerable: true }, - y: { - get: function get$$1() { - return this._y; - }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); - }, - enumerable: true }, - x1: { - get: function get$$1() { - return this._x1; - }, - set: function set$$1(x1) { - this._x1 = x1;this._segmentChanged(); - }, - enumerable: true }, - y1: { - get: function get$$1() { - return this._y1; - }, - set: function set$$1(y1) { - this._y1 = y1;this._segmentChanged(); - }, - enumerable: true } - }); - - var _SVGPathSegCurvetoQuadraticRel = function (_SVGPathSeg10) { - inherits(_SVGPathSegCurvetoQuadraticRel, _SVGPathSeg10); - - function _SVGPathSegCurvetoQuadraticRel(owningPathSegList, x, y, x1, y1) { - classCallCheck(this, _SVGPathSegCurvetoQuadraticRel); - - var _this9 = possibleConstructorReturn(this, (_SVGPathSegCurvetoQuadraticRel.__proto__ || Object.getPrototypeOf(_SVGPathSegCurvetoQuadraticRel)).call(this, _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL, 'q', owningPathSegList)); - - _this9._x = x; - _this9._y = y; - _this9._x1 = x1; - _this9._y1 = y1; - return _this9; - } - - createClass(_SVGPathSegCurvetoQuadraticRel, [{ - key: 'toString', + _createClass(_SVGPathSegCurvetoQuadraticRel, [{ + key: "toString", value: function toString() { return '[object SVGPathSegCurvetoQuadraticRel]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegCurvetoQuadraticRel(undefined, this._x, this._y, this._x1, this._y1); } }]); + return _SVGPathSegCurvetoQuadraticRel; }(_SVGPathSeg); Object.defineProperties(_SVGPathSegCurvetoQuadraticRel.prototype, { x: { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); + set: function set(x) { + this._x = x; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y: { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); + set: function set(y) { + this._y = y; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, x1: { - get: function get$$1() { + get: function get() { return this._x1; }, - set: function set$$1(x1) { - this._x1 = x1;this._segmentChanged(); + set: function set(x1) { + this._x1 = x1; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y1: { - get: function get$$1() { + get: function get() { return this._y1; }, - set: function set$$1(y1) { - this._y1 = y1;this._segmentChanged(); + set: function set(y1) { + this._y1 = y1; + + this._segmentChanged(); }, - enumerable: true } + enumerable: true + } }); - var _SVGPathSegArcAbs = function (_SVGPathSeg11) { - inherits(_SVGPathSegArcAbs, _SVGPathSeg11); + var _SVGPathSegArcAbs = + /*#__PURE__*/ + function (_SVGPathSeg11) { + _inherits(_SVGPathSegArcAbs, _SVGPathSeg11); function _SVGPathSegArcAbs(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) { - classCallCheck(this, _SVGPathSegArcAbs); + var _this9; - var _this10 = possibleConstructorReturn(this, (_SVGPathSegArcAbs.__proto__ || Object.getPrototypeOf(_SVGPathSegArcAbs)).call(this, _SVGPathSeg.PATHSEG_ARC_ABS, 'A', owningPathSegList)); + _classCallCheck(this, _SVGPathSegArcAbs); + _this9 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegArcAbs).call(this, _SVGPathSeg.PATHSEG_ARC_ABS, 'A', owningPathSegList)); + _this9._x = x; + _this9._y = y; + _this9._r1 = r1; + _this9._r2 = r2; + _this9._angle = angle; + _this9._largeArcFlag = largeArcFlag; + _this9._sweepFlag = sweepFlag; + return _this9; + } + + _createClass(_SVGPathSegArcAbs, [{ + key: "toString", + value: function toString() { + return '[object SVGPathSegArcAbs]'; + } + }, { + key: "_asPathString", + value: function _asPathString() { + return this.pathSegTypeAsLetter + ' ' + this._r1 + ' ' + this._r2 + ' ' + this._angle + ' ' + (this._largeArcFlag ? '1' : '0') + ' ' + (this._sweepFlag ? '1' : '0') + ' ' + this._x + ' ' + this._y; + } + }, { + key: "clone", + value: function clone() { + return new _SVGPathSegArcAbs(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); + } + }]); + + return _SVGPathSegArcAbs; + }(_SVGPathSeg); + + Object.defineProperties(_SVGPathSegArcAbs.prototype, { + x: { + get: function get() { + return this._x; + }, + set: function set(x) { + this._x = x; + + this._segmentChanged(); + }, + enumerable: true + }, + y: { + get: function get() { + return this._y; + }, + set: function set(y) { + this._y = y; + + this._segmentChanged(); + }, + enumerable: true + }, + r1: { + get: function get() { + return this._r1; + }, + set: function set(r1) { + this._r1 = r1; + + this._segmentChanged(); + }, + enumerable: true + }, + r2: { + get: function get() { + return this._r2; + }, + set: function set(r2) { + this._r2 = r2; + + this._segmentChanged(); + }, + enumerable: true + }, + angle: { + get: function get() { + return this._angle; + }, + set: function set(angle) { + this._angle = angle; + + this._segmentChanged(); + }, + enumerable: true + }, + largeArcFlag: { + get: function get() { + return this._largeArcFlag; + }, + set: function set(largeArcFlag) { + this._largeArcFlag = largeArcFlag; + + this._segmentChanged(); + }, + enumerable: true + }, + sweepFlag: { + get: function get() { + return this._sweepFlag; + }, + set: function set(sweepFlag) { + this._sweepFlag = sweepFlag; + + this._segmentChanged(); + }, + enumerable: true + } + }); + + var _SVGPathSegArcRel = + /*#__PURE__*/ + function (_SVGPathSeg12) { + _inherits(_SVGPathSegArcRel, _SVGPathSeg12); + + function _SVGPathSegArcRel(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) { + var _this10; + + _classCallCheck(this, _SVGPathSegArcRel); + + _this10 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegArcRel).call(this, _SVGPathSeg.PATHSEG_ARC_REL, 'a', owningPathSegList)); _this10._x = x; _this10._y = y; _this10._r1 = r1; @@ -864,348 +1181,390 @@ return _this10; } - createClass(_SVGPathSegArcAbs, [{ - key: 'toString', - value: function toString() { - return '[object SVGPathSegArcAbs]'; - } - }, { - key: '_asPathString', - value: function _asPathString() { - return this.pathSegTypeAsLetter + ' ' + this._r1 + ' ' + this._r2 + ' ' + this._angle + ' ' + (this._largeArcFlag ? '1' : '0') + ' ' + (this._sweepFlag ? '1' : '0') + ' ' + this._x + ' ' + this._y; - } - }, { - key: 'clone', - value: function clone() { - return new _SVGPathSegArcAbs(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); - } - }]); - return _SVGPathSegArcAbs; - }(_SVGPathSeg); - - Object.defineProperties(_SVGPathSegArcAbs.prototype, { - x: { - get: function get$$1() { - return this._x; - }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); - }, - enumerable: true }, - y: { - get: function get$$1() { - return this._y; - }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); - }, - enumerable: true }, - r1: { - get: function get$$1() { - return this._r1; - }, - set: function set$$1(r1) { - this._r1 = r1;this._segmentChanged(); - }, - enumerable: true }, - r2: { - get: function get$$1() { - return this._r2; - }, - set: function set$$1(r2) { - this._r2 = r2;this._segmentChanged(); - }, - enumerable: true }, - angle: { - get: function get$$1() { - return this._angle; - }, - set: function set$$1(angle) { - this._angle = angle;this._segmentChanged(); - }, - enumerable: true }, - largeArcFlag: { - get: function get$$1() { - return this._largeArcFlag; - }, - set: function set$$1(largeArcFlag) { - this._largeArcFlag = largeArcFlag;this._segmentChanged(); - }, - enumerable: true }, - sweepFlag: { - get: function get$$1() { - return this._sweepFlag; - }, - set: function set$$1(sweepFlag) { - this._sweepFlag = sweepFlag;this._segmentChanged(); - }, - enumerable: true } - }); - - var _SVGPathSegArcRel = function (_SVGPathSeg12) { - inherits(_SVGPathSegArcRel, _SVGPathSeg12); - - function _SVGPathSegArcRel(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) { - classCallCheck(this, _SVGPathSegArcRel); - - var _this11 = possibleConstructorReturn(this, (_SVGPathSegArcRel.__proto__ || Object.getPrototypeOf(_SVGPathSegArcRel)).call(this, _SVGPathSeg.PATHSEG_ARC_REL, 'a', owningPathSegList)); - - _this11._x = x; - _this11._y = y; - _this11._r1 = r1; - _this11._r2 = r2; - _this11._angle = angle; - _this11._largeArcFlag = largeArcFlag; - _this11._sweepFlag = sweepFlag; - return _this11; - } - - createClass(_SVGPathSegArcRel, [{ - key: 'toString', + _createClass(_SVGPathSegArcRel, [{ + key: "toString", value: function toString() { return '[object SVGPathSegArcRel]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._r1 + ' ' + this._r2 + ' ' + this._angle + ' ' + (this._largeArcFlag ? '1' : '0') + ' ' + (this._sweepFlag ? '1' : '0') + ' ' + this._x + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegArcRel(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); } }]); + return _SVGPathSegArcRel; }(_SVGPathSeg); Object.defineProperties(_SVGPathSegArcRel.prototype, { x: { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); + set: function set(x) { + this._x = x; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y: { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); + set: function set(y) { + this._y = y; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, r1: { - get: function get$$1() { + get: function get() { return this._r1; }, - set: function set$$1(r1) { - this._r1 = r1;this._segmentChanged(); + set: function set(r1) { + this._r1 = r1; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, r2: { - get: function get$$1() { + get: function get() { return this._r2; }, - set: function set$$1(r2) { - this._r2 = r2;this._segmentChanged(); + set: function set(r2) { + this._r2 = r2; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, angle: { - get: function get$$1() { + get: function get() { return this._angle; }, - set: function set$$1(angle) { - this._angle = angle;this._segmentChanged(); + set: function set(angle) { + this._angle = angle; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, largeArcFlag: { - get: function get$$1() { + get: function get() { return this._largeArcFlag; }, - set: function set$$1(largeArcFlag) { - this._largeArcFlag = largeArcFlag;this._segmentChanged(); + set: function set(largeArcFlag) { + this._largeArcFlag = largeArcFlag; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, sweepFlag: { - get: function get$$1() { + get: function get() { return this._sweepFlag; }, - set: function set$$1(sweepFlag) { - this._sweepFlag = sweepFlag;this._segmentChanged(); + set: function set(sweepFlag) { + this._sweepFlag = sweepFlag; + + this._segmentChanged(); }, - enumerable: true } + enumerable: true + } }); - var _SVGPathSegLinetoHorizontalAbs = function (_SVGPathSeg13) { - inherits(_SVGPathSegLinetoHorizontalAbs, _SVGPathSeg13); + var _SVGPathSegLinetoHorizontalAbs = + /*#__PURE__*/ + function (_SVGPathSeg13) { + _inherits(_SVGPathSegLinetoHorizontalAbs, _SVGPathSeg13); function _SVGPathSegLinetoHorizontalAbs(owningPathSegList, x) { - classCallCheck(this, _SVGPathSegLinetoHorizontalAbs); + var _this11; - var _this12 = possibleConstructorReturn(this, (_SVGPathSegLinetoHorizontalAbs.__proto__ || Object.getPrototypeOf(_SVGPathSegLinetoHorizontalAbs)).call(this, _SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS, 'H', owningPathSegList)); + _classCallCheck(this, _SVGPathSegLinetoHorizontalAbs); - _this12._x = x; - return _this12; + _this11 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegLinetoHorizontalAbs).call(this, _SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS, 'H', owningPathSegList)); + _this11._x = x; + return _this11; } - createClass(_SVGPathSegLinetoHorizontalAbs, [{ - key: 'toString', + _createClass(_SVGPathSegLinetoHorizontalAbs, [{ + key: "toString", value: function toString() { return '[object SVGPathSegLinetoHorizontalAbs]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegLinetoHorizontalAbs(undefined, this._x); } }]); + return _SVGPathSegLinetoHorizontalAbs; }(_SVGPathSeg); Object.defineProperty(_SVGPathSegLinetoHorizontalAbs.prototype, 'x', { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); - }, - enumerable: true }); + set: function set(x) { + this._x = x; - var _SVGPathSegLinetoHorizontalRel = function (_SVGPathSeg14) { - inherits(_SVGPathSegLinetoHorizontalRel, _SVGPathSeg14); + this._segmentChanged(); + }, + enumerable: true + }); + + var _SVGPathSegLinetoHorizontalRel = + /*#__PURE__*/ + function (_SVGPathSeg14) { + _inherits(_SVGPathSegLinetoHorizontalRel, _SVGPathSeg14); function _SVGPathSegLinetoHorizontalRel(owningPathSegList, x) { - classCallCheck(this, _SVGPathSegLinetoHorizontalRel); + var _this12; - var _this13 = possibleConstructorReturn(this, (_SVGPathSegLinetoHorizontalRel.__proto__ || Object.getPrototypeOf(_SVGPathSegLinetoHorizontalRel)).call(this, _SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL, 'h', owningPathSegList)); + _classCallCheck(this, _SVGPathSegLinetoHorizontalRel); - _this13._x = x; - return _this13; + _this12 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegLinetoHorizontalRel).call(this, _SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL, 'h', owningPathSegList)); + _this12._x = x; + return _this12; } - createClass(_SVGPathSegLinetoHorizontalRel, [{ - key: 'toString', + _createClass(_SVGPathSegLinetoHorizontalRel, [{ + key: "toString", value: function toString() { return '[object SVGPathSegLinetoHorizontalRel]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegLinetoHorizontalRel(undefined, this._x); } }]); + return _SVGPathSegLinetoHorizontalRel; }(_SVGPathSeg); Object.defineProperty(_SVGPathSegLinetoHorizontalRel.prototype, 'x', { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); - }, - enumerable: true }); + set: function set(x) { + this._x = x; - var _SVGPathSegLinetoVerticalAbs = function (_SVGPathSeg15) { - inherits(_SVGPathSegLinetoVerticalAbs, _SVGPathSeg15); + this._segmentChanged(); + }, + enumerable: true + }); + + var _SVGPathSegLinetoVerticalAbs = + /*#__PURE__*/ + function (_SVGPathSeg15) { + _inherits(_SVGPathSegLinetoVerticalAbs, _SVGPathSeg15); function _SVGPathSegLinetoVerticalAbs(owningPathSegList, y) { - classCallCheck(this, _SVGPathSegLinetoVerticalAbs); + var _this13; - var _this14 = possibleConstructorReturn(this, (_SVGPathSegLinetoVerticalAbs.__proto__ || Object.getPrototypeOf(_SVGPathSegLinetoVerticalAbs)).call(this, _SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS, 'V', owningPathSegList)); + _classCallCheck(this, _SVGPathSegLinetoVerticalAbs); - _this14._y = y; - return _this14; + _this13 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegLinetoVerticalAbs).call(this, _SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS, 'V', owningPathSegList)); + _this13._y = y; + return _this13; } - createClass(_SVGPathSegLinetoVerticalAbs, [{ - key: 'toString', + _createClass(_SVGPathSegLinetoVerticalAbs, [{ + key: "toString", value: function toString() { return '[object SVGPathSegLinetoVerticalAbs]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegLinetoVerticalAbs(undefined, this._y); } }]); + return _SVGPathSegLinetoVerticalAbs; }(_SVGPathSeg); Object.defineProperty(_SVGPathSegLinetoVerticalAbs.prototype, 'y', { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); - }, - enumerable: true }); + set: function set(y) { + this._y = y; - var _SVGPathSegLinetoVerticalRel = function (_SVGPathSeg16) { - inherits(_SVGPathSegLinetoVerticalRel, _SVGPathSeg16); + this._segmentChanged(); + }, + enumerable: true + }); + + var _SVGPathSegLinetoVerticalRel = + /*#__PURE__*/ + function (_SVGPathSeg16) { + _inherits(_SVGPathSegLinetoVerticalRel, _SVGPathSeg16); function _SVGPathSegLinetoVerticalRel(owningPathSegList, y) { - classCallCheck(this, _SVGPathSegLinetoVerticalRel); + var _this14; - var _this15 = possibleConstructorReturn(this, (_SVGPathSegLinetoVerticalRel.__proto__ || Object.getPrototypeOf(_SVGPathSegLinetoVerticalRel)).call(this, _SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL, 'v', owningPathSegList)); + _classCallCheck(this, _SVGPathSegLinetoVerticalRel); - _this15._y = y; - return _this15; + _this14 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegLinetoVerticalRel).call(this, _SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL, 'v', owningPathSegList)); + _this14._y = y; + return _this14; } - createClass(_SVGPathSegLinetoVerticalRel, [{ - key: 'toString', + _createClass(_SVGPathSegLinetoVerticalRel, [{ + key: "toString", value: function toString() { return '[object SVGPathSegLinetoVerticalRel]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegLinetoVerticalRel(undefined, this._y); } }]); + return _SVGPathSegLinetoVerticalRel; }(_SVGPathSeg); Object.defineProperty(_SVGPathSegLinetoVerticalRel.prototype, 'y', { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); - }, - enumerable: true }); + set: function set(y) { + this._y = y; - var _SVGPathSegCurvetoCubicSmoothAbs = function (_SVGPathSeg17) { - inherits(_SVGPathSegCurvetoCubicSmoothAbs, _SVGPathSeg17); + this._segmentChanged(); + }, + enumerable: true + }); + + var _SVGPathSegCurvetoCubicSmoothAbs = + /*#__PURE__*/ + function (_SVGPathSeg17) { + _inherits(_SVGPathSegCurvetoCubicSmoothAbs, _SVGPathSeg17); function _SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, x, y, x2, y2) { - classCallCheck(this, _SVGPathSegCurvetoCubicSmoothAbs); + var _this15; - var _this16 = possibleConstructorReturn(this, (_SVGPathSegCurvetoCubicSmoothAbs.__proto__ || Object.getPrototypeOf(_SVGPathSegCurvetoCubicSmoothAbs)).call(this, _SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, 'S', owningPathSegList)); + _classCallCheck(this, _SVGPathSegCurvetoCubicSmoothAbs); + _this15 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegCurvetoCubicSmoothAbs).call(this, _SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, 'S', owningPathSegList)); + _this15._x = x; + _this15._y = y; + _this15._x2 = x2; + _this15._y2 = y2; + return _this15; + } + + _createClass(_SVGPathSegCurvetoCubicSmoothAbs, [{ + key: "toString", + value: function toString() { + return '[object SVGPathSegCurvetoCubicSmoothAbs]'; + } + }, { + key: "_asPathString", + value: function _asPathString() { + return this.pathSegTypeAsLetter + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; + } + }, { + key: "clone", + value: function clone() { + return new _SVGPathSegCurvetoCubicSmoothAbs(undefined, this._x, this._y, this._x2, this._y2); + } + }]); + + return _SVGPathSegCurvetoCubicSmoothAbs; + }(_SVGPathSeg); + + Object.defineProperties(_SVGPathSegCurvetoCubicSmoothAbs.prototype, { + x: { + get: function get() { + return this._x; + }, + set: function set(x) { + this._x = x; + + this._segmentChanged(); + }, + enumerable: true + }, + y: { + get: function get() { + return this._y; + }, + set: function set(y) { + this._y = y; + + this._segmentChanged(); + }, + enumerable: true + }, + x2: { + get: function get() { + return this._x2; + }, + set: function set(x2) { + this._x2 = x2; + + this._segmentChanged(); + }, + enumerable: true + }, + y2: { + get: function get() { + return this._y2; + }, + set: function set(y2) { + this._y2 = y2; + + this._segmentChanged(); + }, + enumerable: true + } + }); + + var _SVGPathSegCurvetoCubicSmoothRel = + /*#__PURE__*/ + function (_SVGPathSeg18) { + _inherits(_SVGPathSegCurvetoCubicSmoothRel, _SVGPathSeg18); + + function _SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, x, y, x2, y2) { + var _this16; + + _classCallCheck(this, _SVGPathSegCurvetoCubicSmoothRel); + + _this16 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegCurvetoCubicSmoothRel).call(this, _SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL, 's', owningPathSegList)); _this16._x = x; _this16._y = y; _this16._x2 = x2; @@ -1213,287 +1572,268 @@ return _this16; } - createClass(_SVGPathSegCurvetoCubicSmoothAbs, [{ - key: 'toString', - value: function toString() { - return '[object SVGPathSegCurvetoCubicSmoothAbs]'; - } - }, { - key: '_asPathString', - value: function _asPathString() { - return this.pathSegTypeAsLetter + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; - } - }, { - key: 'clone', - value: function clone() { - return new _SVGPathSegCurvetoCubicSmoothAbs(undefined, this._x, this._y, this._x2, this._y2); - } - }]); - return _SVGPathSegCurvetoCubicSmoothAbs; - }(_SVGPathSeg); - - Object.defineProperties(_SVGPathSegCurvetoCubicSmoothAbs.prototype, { - x: { - get: function get$$1() { - return this._x; - }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); - }, - enumerable: true }, - y: { - get: function get$$1() { - return this._y; - }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); - }, - enumerable: true }, - x2: { - get: function get$$1() { - return this._x2; - }, - set: function set$$1(x2) { - this._x2 = x2;this._segmentChanged(); - }, - enumerable: true }, - y2: { - get: function get$$1() { - return this._y2; - }, - set: function set$$1(y2) { - this._y2 = y2;this._segmentChanged(); - }, - enumerable: true } - }); - - var _SVGPathSegCurvetoCubicSmoothRel = function (_SVGPathSeg18) { - inherits(_SVGPathSegCurvetoCubicSmoothRel, _SVGPathSeg18); - - function _SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, x, y, x2, y2) { - classCallCheck(this, _SVGPathSegCurvetoCubicSmoothRel); - - var _this17 = possibleConstructorReturn(this, (_SVGPathSegCurvetoCubicSmoothRel.__proto__ || Object.getPrototypeOf(_SVGPathSegCurvetoCubicSmoothRel)).call(this, _SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL, 's', owningPathSegList)); - - _this17._x = x; - _this17._y = y; - _this17._x2 = x2; - _this17._y2 = y2; - return _this17; - } - - createClass(_SVGPathSegCurvetoCubicSmoothRel, [{ - key: 'toString', + _createClass(_SVGPathSegCurvetoCubicSmoothRel, [{ + key: "toString", value: function toString() { return '[object SVGPathSegCurvetoCubicSmoothRel]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegCurvetoCubicSmoothRel(undefined, this._x, this._y, this._x2, this._y2); } }]); + return _SVGPathSegCurvetoCubicSmoothRel; }(_SVGPathSeg); Object.defineProperties(_SVGPathSegCurvetoCubicSmoothRel.prototype, { x: { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); + set: function set(x) { + this._x = x; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y: { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); + set: function set(y) { + this._y = y; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, x2: { - get: function get$$1() { + get: function get() { return this._x2; }, - set: function set$$1(x2) { - this._x2 = x2;this._segmentChanged(); + set: function set(x2) { + this._x2 = x2; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y2: { - get: function get$$1() { + get: function get() { return this._y2; }, - set: function set$$1(y2) { - this._y2 = y2;this._segmentChanged(); + set: function set(y2) { + this._y2 = y2; + + this._segmentChanged(); }, - enumerable: true } + enumerable: true + } }); - var _SVGPathSegCurvetoQuadraticSmoothAbs = function (_SVGPathSeg19) { - inherits(_SVGPathSegCurvetoQuadraticSmoothAbs, _SVGPathSeg19); + var _SVGPathSegCurvetoQuadraticSmoothAbs = + /*#__PURE__*/ + function (_SVGPathSeg19) { + _inherits(_SVGPathSegCurvetoQuadraticSmoothAbs, _SVGPathSeg19); function _SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, x, y) { - classCallCheck(this, _SVGPathSegCurvetoQuadraticSmoothAbs); + var _this17; - var _this18 = possibleConstructorReturn(this, (_SVGPathSegCurvetoQuadraticSmoothAbs.__proto__ || Object.getPrototypeOf(_SVGPathSegCurvetoQuadraticSmoothAbs)).call(this, _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, 'T', owningPathSegList)); + _classCallCheck(this, _SVGPathSegCurvetoQuadraticSmoothAbs); - _this18._x = x; - _this18._y = y; - return _this18; + _this17 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegCurvetoQuadraticSmoothAbs).call(this, _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, 'T', owningPathSegList)); + _this17._x = x; + _this17._y = y; + return _this17; } - createClass(_SVGPathSegCurvetoQuadraticSmoothAbs, [{ - key: 'toString', + _createClass(_SVGPathSegCurvetoQuadraticSmoothAbs, [{ + key: "toString", value: function toString() { return '[object SVGPathSegCurvetoQuadraticSmoothAbs]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegCurvetoQuadraticSmoothAbs(undefined, this._x, this._y); } }]); + return _SVGPathSegCurvetoQuadraticSmoothAbs; }(_SVGPathSeg); Object.defineProperties(_SVGPathSegCurvetoQuadraticSmoothAbs.prototype, { x: { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); + set: function set(x) { + this._x = x; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y: { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); + set: function set(y) { + this._y = y; + + this._segmentChanged(); }, - enumerable: true } + enumerable: true + } }); - var _SVGPathSegCurvetoQuadraticSmoothRel = function (_SVGPathSeg20) { - inherits(_SVGPathSegCurvetoQuadraticSmoothRel, _SVGPathSeg20); + var _SVGPathSegCurvetoQuadraticSmoothRel = + /*#__PURE__*/ + function (_SVGPathSeg20) { + _inherits(_SVGPathSegCurvetoQuadraticSmoothRel, _SVGPathSeg20); function _SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, x, y) { - classCallCheck(this, _SVGPathSegCurvetoQuadraticSmoothRel); + var _this18; - var _this19 = possibleConstructorReturn(this, (_SVGPathSegCurvetoQuadraticSmoothRel.__proto__ || Object.getPrototypeOf(_SVGPathSegCurvetoQuadraticSmoothRel)).call(this, _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, 't', owningPathSegList)); + _classCallCheck(this, _SVGPathSegCurvetoQuadraticSmoothRel); - _this19._x = x; - _this19._y = y; - return _this19; + _this18 = _possibleConstructorReturn(this, _getPrototypeOf(_SVGPathSegCurvetoQuadraticSmoothRel).call(this, _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, 't', owningPathSegList)); + _this18._x = x; + _this18._y = y; + return _this18; } - createClass(_SVGPathSegCurvetoQuadraticSmoothRel, [{ - key: 'toString', + _createClass(_SVGPathSegCurvetoQuadraticSmoothRel, [{ + key: "toString", value: function toString() { return '[object SVGPathSegCurvetoQuadraticSmoothRel]'; } }, { - key: '_asPathString', + key: "_asPathString", value: function _asPathString() { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; } }, { - key: 'clone', + key: "clone", value: function clone() { return new _SVGPathSegCurvetoQuadraticSmoothRel(undefined, this._x, this._y); } }]); + return _SVGPathSegCurvetoQuadraticSmoothRel; }(_SVGPathSeg); Object.defineProperties(_SVGPathSegCurvetoQuadraticSmoothRel.prototype, { x: { - get: function get$$1() { + get: function get() { return this._x; }, - set: function set$$1(x) { - this._x = x;this._segmentChanged(); + set: function set(x) { + this._x = x; + + this._segmentChanged(); }, - enumerable: true }, + enumerable: true + }, y: { - get: function get$$1() { + get: function get() { return this._y; }, - set: function set$$1(y) { - this._y = y;this._segmentChanged(); - }, - enumerable: true } - }); + set: function set(y) { + this._y = y; - // Add createSVGPathSeg* functions to SVGPathElement. + this._segmentChanged(); + }, + enumerable: true + } + }); // Add createSVGPathSeg* functions to SVGPathElement. // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathElement. + SVGPathElement.prototype.createSVGPathSegClosePath = function () { return new _SVGPathSegClosePath(undefined); }; + SVGPathElement.prototype.createSVGPathSegMovetoAbs = function (x, y) { return new _SVGPathSegMovetoAbs(undefined, x, y); }; + SVGPathElement.prototype.createSVGPathSegMovetoRel = function (x, y) { return new _SVGPathSegMovetoRel(undefined, x, y); }; + SVGPathElement.prototype.createSVGPathSegLinetoAbs = function (x, y) { return new _SVGPathSegLinetoAbs(undefined, x, y); }; + SVGPathElement.prototype.createSVGPathSegLinetoRel = function (x, y) { return new _SVGPathSegLinetoRel(undefined, x, y); }; + SVGPathElement.prototype.createSVGPathSegCurvetoCubicAbs = function (x, y, x1, y1, x2, y2) { return new _SVGPathSegCurvetoCubicAbs(undefined, x, y, x1, y1, x2, y2); }; + SVGPathElement.prototype.createSVGPathSegCurvetoCubicRel = function (x, y, x1, y1, x2, y2) { return new _SVGPathSegCurvetoCubicRel(undefined, x, y, x1, y1, x2, y2); }; + SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticAbs = function (x, y, x1, y1) { return new _SVGPathSegCurvetoQuadraticAbs(undefined, x, y, x1, y1); }; + SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticRel = function (x, y, x1, y1) { return new _SVGPathSegCurvetoQuadraticRel(undefined, x, y, x1, y1); }; + SVGPathElement.prototype.createSVGPathSegArcAbs = function (x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new _SVGPathSegArcAbs(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); }; + SVGPathElement.prototype.createSVGPathSegArcRel = function (x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new _SVGPathSegArcRel(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); }; + SVGPathElement.prototype.createSVGPathSegLinetoHorizontalAbs = function (x) { return new _SVGPathSegLinetoHorizontalAbs(undefined, x); }; + SVGPathElement.prototype.createSVGPathSegLinetoHorizontalRel = function (x) { return new _SVGPathSegLinetoHorizontalRel(undefined, x); }; + SVGPathElement.prototype.createSVGPathSegLinetoVerticalAbs = function (y) { return new _SVGPathSegLinetoVerticalAbs(undefined, y); }; + SVGPathElement.prototype.createSVGPathSegLinetoVerticalRel = function (y) { return new _SVGPathSegLinetoVerticalRel(undefined, y); }; + SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothAbs = function (x, y, x2, y2) { return new _SVGPathSegCurvetoCubicSmoothAbs(undefined, x, y, x2, y2); }; + SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothRel = function (x, y, x2, y2) { return new _SVGPathSegCurvetoCubicSmoothRel(undefined, x, y, x2, y2); }; + SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothAbs = function (x, y) { return new _SVGPathSegCurvetoQuadraticSmoothAbs(undefined, x, y); }; + SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothRel = function (x, y) { return new _SVGPathSegCurvetoQuadraticSmoothRel(undefined, x, y); }; @@ -1509,20 +1849,22 @@ var measurementElement = document.createElementNS('http://www.w3.org/2000/svg', 'path'); measurementElement.setAttribute('d', this.getAttribute('d')); - var lastPathSegment = measurementElement.pathSegList.numberOfItems - 1; + var lastPathSegment = measurementElement.pathSegList.numberOfItems - 1; // If the path is empty, return 0. - // If the path is empty, return 0. if (lastPathSegment <= 0) { return 0; } do { measurementElement.pathSegList.removeItem(lastPathSegment); + if (distance > measurementElement.getTotalLength()) { break; } + lastPathSegment--; } while (lastPathSegment > 0); + return lastPathSegment; }; } @@ -1547,127 +1889,141 @@ window.SVGPathSegCurvetoCubicSmoothRel = _SVGPathSegCurvetoCubicSmoothRel; window.SVGPathSegCurvetoQuadraticSmoothAbs = _SVGPathSegCurvetoQuadraticSmoothAbs; window.SVGPathSegCurvetoQuadraticSmoothRel = _SVGPathSegCurvetoQuadraticSmoothRel; - } - - // Checking for SVGPathSegList in window checks for the case of an implementation without the + } // Checking for SVGPathSegList in window checks for the case of an implementation without the // SVGPathSegList API. // The second check for appendItem is specific to Firefox 59+ which removed only parts of the // SVGPathSegList API (e.g., appendItem). In this case we need to re-implement the entire API // so the polyfill data (i.e., _list) is used throughout. + + if (!('SVGPathSegList' in window) || !('appendItem' in window.SVGPathSegList.prototype)) { // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSegList - var SVGPathSegList = function () { + var SVGPathSegList = + /*#__PURE__*/ + function () { function SVGPathSegList(pathElement) { - classCallCheck(this, SVGPathSegList); + _classCallCheck(this, SVGPathSegList); this._pathElement = pathElement; - this._list = this._parsePath(this._pathElement.getAttribute('d')); + this._list = this._parsePath(this._pathElement.getAttribute('d')); // Use a MutationObserver to catch changes to the path's "d" attribute. - // Use a MutationObserver to catch changes to the path's "d" attribute. - this._mutationObserverConfig = { attributes: true, attributeFilter: ['d'] }; + this._mutationObserverConfig = { + attributes: true, + attributeFilter: ['d'] + }; this._pathElementMutationObserver = new MutationObserver(this._updateListFromPathMutations.bind(this)); + this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig); - } - // Process any pending mutations to the path element and update the list as needed. + } // Process any pending mutations to the path element and update the list as needed. // This should be the first call of all public functions and is needed because // MutationObservers are not synchronous so we can have pending asynchronous mutations. - createClass(SVGPathSegList, [{ - key: '_checkPathSynchronizedToList', + _createClass(SVGPathSegList, [{ + key: "_checkPathSynchronizedToList", value: function _checkPathSynchronizedToList() { this._updateListFromPathMutations(this._pathElementMutationObserver.takeRecords()); } }, { - key: '_updateListFromPathMutations', + key: "_updateListFromPathMutations", value: function _updateListFromPathMutations(mutationRecords) { if (!this._pathElement) { return; } + var hasPathMutations = false; mutationRecords.forEach(function (record) { if (record.attributeName === 'd') { hasPathMutations = true; } }); + if (hasPathMutations) { this._list = this._parsePath(this._pathElement.getAttribute('d')); } - } - - // Serialize the list and update the path's 'd' attribute. + } // Serialize the list and update the path's 'd' attribute. }, { - key: '_writeListToPath', + key: "_writeListToPath", value: function _writeListToPath() { this._pathElementMutationObserver.disconnect(); - this._pathElement.setAttribute('d', SVGPathSegList._pathSegArrayAsString(this._list)); - this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig); - } - // When a path segment changes the list needs to be synchronized back to the path element. + this._pathElement.setAttribute('d', SVGPathSegList._pathSegArrayAsString(this._list)); + + this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig); + } // When a path segment changes the list needs to be synchronized back to the path element. }, { - key: 'segmentChanged', + key: "segmentChanged", value: function segmentChanged(pathSeg) { this._writeListToPath(); } }, { - key: 'clear', + key: "clear", value: function clear() { this._checkPathSynchronizedToList(); this._list.forEach(function (pathSeg) { pathSeg._owningPathSegList = null; }); + this._list = []; + this._writeListToPath(); } }, { - key: 'initialize', + key: "initialize", value: function initialize(newItem) { this._checkPathSynchronizedToList(); this._list = [newItem]; newItem._owningPathSegList = this; + this._writeListToPath(); + return newItem; } }, { - key: '_checkValidIndex', + key: "_checkValidIndex", value: function _checkValidIndex(index) { if (isNaN(index) || index < 0 || index >= this.numberOfItems) { throw new Error('INDEX_SIZE_ERR'); } } }, { - key: 'getItem', + key: "getItem", value: function getItem(index) { this._checkPathSynchronizedToList(); this._checkValidIndex(index); + return this._list[index]; } }, { - key: 'insertItemBefore', + key: "insertItemBefore", value: function insertItemBefore(newItem, index) { - this._checkPathSynchronizedToList(); + this._checkPathSynchronizedToList(); // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list. + - // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list. if (index > this.numberOfItems) { index = this.numberOfItems; } + if (newItem._owningPathSegList) { // SVG2 spec says to make a copy. newItem = newItem.clone(); } + this._list.splice(index, 0, newItem); + newItem._owningPathSegList = this; + this._writeListToPath(); + return newItem; } }, { - key: 'replaceItem', + key: "replaceItem", value: function replaceItem(newItem, index) { this._checkPathSynchronizedToList(); @@ -1675,25 +2031,33 @@ // SVG2 spec says to make a copy. newItem = newItem.clone(); } + this._checkValidIndex(index); + this._list[index] = newItem; newItem._owningPathSegList = this; + this._writeListToPath(); + return newItem; } }, { - key: 'removeItem', + key: "removeItem", value: function removeItem(index) { this._checkPathSynchronizedToList(); this._checkValidIndex(index); + var item = this._list[index]; + this._list.splice(index, 1); + this._writeListToPath(); + return item; } }, { - key: 'appendItem', + key: "appendItem", value: function appendItem(newItem) { this._checkPathSynchronizedToList(); @@ -1701,43 +2065,49 @@ // SVG2 spec says to make a copy. newItem = newItem.clone(); } - this._list.push(newItem); - newItem._owningPathSegList = this; - // TODO: Optimize this to just append to the existing attribute. - this._writeListToPath(); - return newItem; - } - // This closely follows SVGPathParser::parsePath from Source/core/svg/SVGPathParser.cpp. + this._list.push(newItem); + + newItem._owningPathSegList = this; // TODO: Optimize this to just append to the existing attribute. + + this._writeListToPath(); + + return newItem; + } // This closely follows SVGPathParser::parsePath from Source/core/svg/SVGPathParser.cpp. }, { - key: '_parsePath', + key: "_parsePath", value: function _parsePath(string) { if (!string || !string.length) { return []; } - var owningPathSegList = this; + var owningPathSegList = this; // eslint-disable-line consistent-this - var Builder = function () { + var Builder = + /*#__PURE__*/ + function () { function Builder() { - classCallCheck(this, Builder); + _classCallCheck(this, Builder); this.pathSegList = []; } - createClass(Builder, [{ - key: 'appendSegment', + _createClass(Builder, [{ + key: "appendSegment", value: function appendSegment(pathSeg) { this.pathSegList.push(pathSeg); } }]); + return Builder; }(); - var Source = function () { + var Source = + /*#__PURE__*/ + function () { function Source(string) { - classCallCheck(this, Source); + _classCallCheck(this, Source); this._string = string; this._currentIndex = 0; @@ -1747,124 +2117,149 @@ this._skipOptionalSpaces(); } - createClass(Source, [{ - key: '_isCurrentSpace', + _createClass(Source, [{ + key: "_isCurrentSpace", value: function _isCurrentSpace() { var character = this._string[this._currentIndex]; return character <= ' ' && (character === ' ' || character === '\n' || character === '\t' || character === '\r' || character === '\f'); } }, { - key: '_skipOptionalSpaces', + key: "_skipOptionalSpaces", value: function _skipOptionalSpaces() { while (this._currentIndex < this._endIndex && this._isCurrentSpace()) { this._currentIndex++; } + return this._currentIndex < this._endIndex; } }, { - key: '_skipOptionalSpacesOrDelimiter', + key: "_skipOptionalSpacesOrDelimiter", value: function _skipOptionalSpacesOrDelimiter() { if (this._currentIndex < this._endIndex && !this._isCurrentSpace() && this._string.charAt(this._currentIndex) !== ',') { return false; } + if (this._skipOptionalSpaces()) { if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) === ',') { this._currentIndex++; + this._skipOptionalSpaces(); } } + return this._currentIndex < this._endIndex; } }, { - key: 'hasMoreData', + key: "hasMoreData", value: function hasMoreData() { return this._currentIndex < this._endIndex; } }, { - key: 'peekSegmentType', + key: "peekSegmentType", value: function peekSegmentType() { var lookahead = this._string[this._currentIndex]; return this._pathSegTypeFromChar(lookahead); } }, { - key: '_pathSegTypeFromChar', + key: "_pathSegTypeFromChar", value: function _pathSegTypeFromChar(lookahead) { switch (lookahead) { case 'Z': case 'z': return SVGPathSeg.PATHSEG_CLOSEPATH; + case 'M': return SVGPathSeg.PATHSEG_MOVETO_ABS; + case 'm': return SVGPathSeg.PATHSEG_MOVETO_REL; + case 'L': return SVGPathSeg.PATHSEG_LINETO_ABS; + case 'l': return SVGPathSeg.PATHSEG_LINETO_REL; + case 'C': return SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS; + case 'c': return SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL; + case 'Q': return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS; + case 'q': return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL; + case 'A': return SVGPathSeg.PATHSEG_ARC_ABS; + case 'a': return SVGPathSeg.PATHSEG_ARC_REL; + case 'H': return SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS; + case 'h': return SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL; + case 'V': return SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS; + case 'v': return SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL; + case 'S': return SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS; + case 's': return SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL; + case 'T': return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS; + case 't': return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL; + default: return SVGPathSeg.PATHSEG_UNKNOWN; } } }, { - key: '_nextCommandHelper', + key: "_nextCommandHelper", value: function _nextCommandHelper(lookahead, previousCommand) { // Check for remaining coordinates in the current command. if ((lookahead === '+' || lookahead === '-' || lookahead === '.' || lookahead >= '0' && lookahead <= '9') && previousCommand !== SVGPathSeg.PATHSEG_CLOSEPATH) { if (previousCommand === SVGPathSeg.PATHSEG_MOVETO_ABS) { return SVGPathSeg.PATHSEG_LINETO_ABS; } + if (previousCommand === SVGPathSeg.PATHSEG_MOVETO_REL) { return SVGPathSeg.PATHSEG_LINETO_REL; } + return previousCommand; } + return SVGPathSeg.PATHSEG_UNKNOWN; } }, { - key: 'initialCommandIsMoveTo', + key: "initialCommandIsMoveTo", value: function initialCommandIsMoveTo() { // If the path is empty it is still valid, so return true. if (!this.hasMoreData()) { return true; } - var command = this.peekSegmentType(); - // Path must start with moveTo. - return command === SVGPathSeg.PATHSEG_MOVETO_ABS || command === SVGPathSeg.PATHSEG_MOVETO_REL; - } - // Parse a number from an SVG path. This very closely follows genericParseNumber(...) from Source/core/svg/SVGParserUtilities.cpp. + var command = this.peekSegmentType(); // Path must start with moveTo. + + return command === SVGPathSeg.PATHSEG_MOVETO_ABS || command === SVGPathSeg.PATHSEG_MOVETO_REL; + } // Parse a number from an SVG path. This very closely follows genericParseNumber(...) from Source/core/svg/SVGParserUtilities.cpp. // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-PathDataBNF }, { - key: '_parseNumber', + key: "_parseNumber", value: function _parseNumber() { var exponent = 0; var integer = 0; @@ -1872,12 +2267,11 @@ var decimal = 0; var sign = 1; var expsign = 1; - var startIndex = this._currentIndex; - this._skipOptionalSpaces(); + this._skipOptionalSpaces(); // Read the sign. + - // Read the sign. if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) === '+') { this._currentIndex++; } else if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) === '-') { @@ -1888,10 +2282,11 @@ if (this._currentIndex === this._endIndex || (this._string.charAt(this._currentIndex) < '0' || this._string.charAt(this._currentIndex) > '9') && this._string.charAt(this._currentIndex) !== '.') { // The first character of a number must be one of [0-9+-.]. return undefined; - } + } // Read the integer part, build right-to-left. + - // Read the integer part, build right-to-left. var startIntPartIndex = this._currentIndex; + while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= '0' && this._string.charAt(this._currentIndex) <= '9') { this._currentIndex++; // Advance to first non-digit. } @@ -1899,40 +2294,40 @@ if (this._currentIndex !== startIntPartIndex) { var scanIntPartIndex = this._currentIndex - 1; var multiplier = 1; + while (scanIntPartIndex >= startIntPartIndex) { integer += multiplier * (this._string.charAt(scanIntPartIndex--) - '0'); multiplier *= 10; } - } + } // Read the decimals. + - // Read the decimals. if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) === '.') { - this._currentIndex++; + this._currentIndex++; // There must be a least one digit following the . - // There must be a least one digit following the . if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < '0' || this._string.charAt(this._currentIndex) > '9') { return undefined; } + while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= '0' && this._string.charAt(this._currentIndex) <= '9') { frac *= 10; decimal += (this._string.charAt(this._currentIndex) - '0') / frac; this._currentIndex += 1; } - } + } // Read the exponent part. + - // Read the exponent part. if (this._currentIndex !== startIndex && this._currentIndex + 1 < this._endIndex && (this._string.charAt(this._currentIndex) === 'e' || this._string.charAt(this._currentIndex) === 'E') && this._string.charAt(this._currentIndex + 1) !== 'x' && this._string.charAt(this._currentIndex + 1) !== 'm') { - this._currentIndex++; + this._currentIndex++; // Read the sign of the exponent. - // Read the sign of the exponent. if (this._string.charAt(this._currentIndex) === '+') { this._currentIndex++; } else if (this._string.charAt(this._currentIndex) === '-') { this._currentIndex++; expsign = -1; - } + } // There must be an exponent. + - // There must be an exponent. if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < '0' || this._string.charAt(this._currentIndex) > '9') { return undefined; } @@ -1960,13 +2355,16 @@ return number; } }, { - key: '_parseArcFlag', + key: "_parseArcFlag", value: function _parseArcFlag() { if (this._currentIndex >= this._endIndex) { return undefined; } + var flag = false; + var flagChar = this._string.charAt(this._currentIndex++); + if (flagChar === '0') { flag = false; } else if (flagChar === '1') { @@ -1976,19 +2374,24 @@ } this._skipOptionalSpacesOrDelimiter(); + return flag; } }, { - key: 'parseSegment', + key: "parseSegment", value: function parseSegment() { var lookahead = this._string[this._currentIndex]; + var command = this._pathSegTypeFromChar(lookahead); + if (command === SVGPathSeg.PATHSEG_UNKNOWN) { // Possibly an implicit command. Not allowed if this is the first command. if (this._previousCommand === SVGPathSeg.PATHSEG_UNKNOWN) { return null; } + command = this._nextCommandHelper(lookahead, this._previousCommand); + if (command === SVGPathSeg.PATHSEG_UNKNOWN) { return null; } @@ -2001,63 +2404,143 @@ switch (command) { case SVGPathSeg.PATHSEG_MOVETO_REL: return new SVGPathSegMovetoRel(owningPathSegList, this._parseNumber(), this._parseNumber()); + case SVGPathSeg.PATHSEG_MOVETO_ABS: return new SVGPathSegMovetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber()); + case SVGPathSeg.PATHSEG_LINETO_REL: return new SVGPathSegLinetoRel(owningPathSegList, this._parseNumber(), this._parseNumber()); + case SVGPathSeg.PATHSEG_LINETO_ABS: return new SVGPathSegLinetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber()); + case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL: return new SVGPathSegLinetoHorizontalRel(owningPathSegList, this._parseNumber()); + case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS: return new SVGPathSegLinetoHorizontalAbs(owningPathSegList, this._parseNumber()); + case SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL: return new SVGPathSegLinetoVerticalRel(owningPathSegList, this._parseNumber()); + case SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS: return new SVGPathSegLinetoVerticalAbs(owningPathSegList, this._parseNumber()); + case SVGPathSeg.PATHSEG_CLOSEPATH: this._skipOptionalSpaces(); + return new SVGPathSegClosePath(owningPathSegList); + case SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL: { - var _points = { x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber() }; - return new SVGPathSegCurvetoCubicRel(owningPathSegList, _points.x, _points.y, _points.x1, _points.y1, _points.x2, _points.y2); - }case SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS: + var points = { + x1: this._parseNumber(), + y1: this._parseNumber(), + x2: this._parseNumber(), + y2: this._parseNumber(), + x: this._parseNumber(), + y: this._parseNumber() + }; + return new SVGPathSegCurvetoCubicRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2); + } + + case SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS: { - var _points2 = { x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber() }; - return new SVGPathSegCurvetoCubicAbs(owningPathSegList, _points2.x, _points2.y, _points2.x1, _points2.y1, _points2.x2, _points2.y2); - }case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL: + var _points = { + x1: this._parseNumber(), + y1: this._parseNumber(), + x2: this._parseNumber(), + y2: this._parseNumber(), + x: this._parseNumber(), + y: this._parseNumber() + }; + return new SVGPathSegCurvetoCubicAbs(owningPathSegList, _points.x, _points.y, _points.x1, _points.y1, _points.x2, _points.y2); + } + + case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL: { - var _points3 = { x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber() }; - return new SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, _points3.x, _points3.y, _points3.x2, _points3.y2); - }case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: + var _points2 = { + x2: this._parseNumber(), + y2: this._parseNumber(), + x: this._parseNumber(), + y: this._parseNumber() + }; + return new SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, _points2.x, _points2.y, _points2.x2, _points2.y2); + } + + case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: { - var _points4 = { x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber() }; - return new SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, _points4.x, _points4.y, _points4.x2, _points4.y2); - }case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL: + var _points3 = { + x2: this._parseNumber(), + y2: this._parseNumber(), + x: this._parseNumber(), + y: this._parseNumber() + }; + return new SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, _points3.x, _points3.y, _points3.x2, _points3.y2); + } + + case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL: { - var _points5 = { x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber() }; - return new SVGPathSegCurvetoQuadraticRel(owningPathSegList, _points5.x, _points5.y, _points5.x1, _points5.y1); - }case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS: - var 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); + var _points4 = { + x1: this._parseNumber(), + y1: this._parseNumber(), + x: this._parseNumber(), + y: this._parseNumber() + }; + return new SVGPathSegCurvetoQuadraticRel(owningPathSegList, _points4.x, _points4.y, _points4.x1, _points4.y1); + } + + case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS: + { + var _points5 = { + x1: this._parseNumber(), + y1: this._parseNumber(), + x: this._parseNumber(), + y: this._parseNumber() + }; + return new SVGPathSegCurvetoQuadraticAbs(owningPathSegList, _points5.x, _points5.y, _points5.x1, _points5.y1); + } + case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL: return new SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, this._parseNumber(), this._parseNumber()); + case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS: return new SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, this._parseNumber(), this._parseNumber()); + case SVGPathSeg.PATHSEG_ARC_REL: { - var _points6 = { x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber() }; + var _points6 = { + x1: this._parseNumber(), + y1: this._parseNumber(), + arcAngle: this._parseNumber(), + arcLarge: this._parseArcFlag(), + arcSweep: this._parseArcFlag(), + x: this._parseNumber(), + y: this._parseNumber() + }; return new SVGPathSegArcRel(owningPathSegList, _points6.x, _points6.y, _points6.x1, _points6.y1, _points6.arcAngle, _points6.arcLarge, _points6.arcSweep); - }case SVGPathSeg.PATHSEG_ARC_ABS: + } + + case SVGPathSeg.PATHSEG_ARC_ABS: { - var _points7 = { x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber() }; + var _points7 = { + x1: this._parseNumber(), + y1: this._parseNumber(), + arcAngle: this._parseNumber(), + arcLarge: this._parseArcFlag(), + arcSweep: this._parseArcFlag(), + x: this._parseNumber(), + y: this._parseNumber() + }; return new SVGPathSegArcAbs(owningPathSegList, _points7.x, _points7.y, _points7.x1, _points7.y1, _points7.arcAngle, _points7.arcLarge, _points7.arcSweep); - }default: + } + + default: throw new Error('Unknown path seg type.'); } } }]); + return Source; }(); @@ -2067,28 +2550,31 @@ if (!source.initialCommandIsMoveTo()) { return []; } + while (source.hasMoreData()) { var pathSeg = source.parseSegment(); + if (!pathSeg) { return []; } + builder.appendSegment(pathSeg); } return builder.pathSegList; } }]); + return SVGPathSegList; }(); SVGPathSegList.prototype.classname = 'SVGPathSegList'; - Object.defineProperty(SVGPathSegList.prototype, 'numberOfItems', { - get: function get$$1() { + get: function get() { this._checkPathSynchronizedToList(); + return this._list.length; }, - enumerable: true }); @@ -2104,57 +2590,55 @@ } }); return string; - }; - - // Add the pathSegList accessors to SVGPathElement. + }; // Add the pathSegList accessors to SVGPathElement. // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGAnimatedPathData + + Object.defineProperties(SVGPathElement.prototype, { pathSegList: { - get: function get$$1() { + get: function get() { if (!this._pathSegList) { this._pathSegList = new SVGPathSegList(this); } + return this._pathSegList; }, - enumerable: true }, // FIXME: The following are not implemented and simply return SVGPathElement.pathSegList. normalizedPathSegList: { - get: function get$$1() { + get: function get() { return this.pathSegList; }, - enumerable: true }, + enumerable: true + }, animatedPathSegList: { - get: function get$$1() { + get: function get() { return this.pathSegList; }, - enumerable: true }, + enumerable: true + }, animatedNormalizedPathSegList: { - get: function get$$1() { + get: function get() { return this.pathSegList; }, - enumerable: true } + enumerable: true + } }); window.SVGPathSegList = SVGPathSegList; } })(); - /* globals jQuery */ - var $ = jQuery; var supportsSVG_ = function () { - return !!document.createElementNS && !!document.createElementNS(NS.SVG, 'svg').createSVGRect; + return Boolean(document.createElementNS && document.createElementNS(NS.SVG, 'svg').createSVGRect); }(); - var _navigator = navigator, userAgent = _navigator.userAgent; + var svg = document.createElementNS(NS.SVG, 'svg'); // Note: Browser sniffing should only be used if no other detection method is possible - var svg = document.createElementNS(NS.SVG, 'svg'); - - // Note: Browser sniffing should only be used if no other detection method is possible - var isOpera_ = !!window.opera; + var isOpera_ = Boolean(window.opera); var isWebkit_ = userAgent.includes('AppleWebKit'); var isGecko_ = userAgent.includes('Gecko/'); var isIE_ = userAgent.includes('MSIE'); @@ -2164,23 +2648,25 @@ var isTouch_ = 'ontouchstart' in window; var supportsSelectors_ = function () { - return !!svg.querySelector; + return Boolean(svg.querySelector); }(); var 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) var supportsPathReplaceItem_ = function () { var path = document.createElementNS(NS.SVG, 'path'); path.setAttribute('d', 'M0,0 10,10'); var seglist = path.pathSegList; var seg = path.createSVGPathSegLinetoAbs(5, 5); + try { seglist.replaceItem(seg, 1); return true; } catch (err) {} + return false; }(); @@ -2189,14 +2675,16 @@ path.setAttribute('d', 'M0,0 10,10'); var seglist = path.pathSegList; var seg = path.createSVGPathSegLinetoAbs(5, 5); + try { seglist.insertItemBefore(seg, 1); return true; } catch (err) {} - return false; - }(); - // text character positioning (for IE9) + return false; + }(); // text character positioning (for IE9 and now Chrome) + + var supportsGoodTextCharPos_ = function () { var svgroot = document.createElementNS(NS.SVG, 'svg'); var svgcontent = document.createElementNS(NS.SVG, 'svg'); @@ -2206,9 +2694,16 @@ var text = document.createElementNS(NS.SVG, 'text'); text.textContent = 'a'; svgcontent.append(text); - var pos = text.getStartPositionOfChar(0).x; - svgroot.remove(); - return pos === 0; + + try { + // Chrome now fails here + var pos = text.getStartPositionOfChar(0).x; + return pos === 0; + } catch (err) { + return false; + } finally { + svgroot.remove(); + } }(); var supportsPathBBox_ = function () { @@ -2220,9 +2715,9 @@ var bbox = path.getBBox(); svgcontent.remove(); return bbox.height > 4 && bbox.height < 5; - }(); + }(); // Support for correct bbox sizing on groups with horizontal/vertical lines + - // Support for correct bbox sizing on groups with horizontal/vertical lines var supportsHVLineContainerBBox_ = function () { var svgcontent = document.createElementNS(NS.SVG, 'svg'); document.documentElement.append(svgcontent); @@ -2234,8 +2729,8 @@ g.append(path, path2); svgcontent.append(g); var bbox = g.getBBox(); - svgcontent.remove(); - // Webkit gives 0, FF gives 10, Opera (correctly) gives 15 + svgcontent.remove(); // Webkit gives 0, FF gives 10, Opera (correctly) gives 15 + return bbox.width === 15; }(); @@ -2245,10 +2740,12 @@ rect.setAttribute('x', 0.1); var crect = rect.cloneNode(false); var retValue = !crect.getAttribute('x').includes(','); + if (!retValue) { // Todo: i18nize or remove $.alert('NOTE: This version of Opera is known to contain bugs in SVG-edit.\n' + 'Please upgrade to the
    latest version in which the problems have been fixed.'); } + return retValue; }(); @@ -2264,16 +2761,21 @@ var t1 = svg.createSVGTransform(); rxform.appendItem(t1); var r1 = rxform.getItem(0); - // Todo: Do frame-independent instance checking - return r1 instanceof SVGTransform && t1 instanceof SVGTransform && r1.type === t1.type && r1.angle === t1.angle && r1.matrix.a === t1.matrix.a && r1.matrix.b === t1.matrix.b && r1.matrix.c === t1.matrix.c && r1.matrix.d === t1.matrix.d && r1.matrix.e === t1.matrix.e && r1.matrix.f === t1.matrix.f; - }(); - // Public API + var isSVGTransform = function isSVGTransform(o) { + // https://developer.mozilla.org/en-US/docs/Web/API/SVGTransform + return o && _typeof(o) === 'object' && typeof o.setMatrix === 'function' && 'angle' in o; + }; + + return isSVGTransform(r1) && isSVGTransform(t1) && r1.type === t1.type && r1.angle === t1.angle && r1.matrix.a === t1.matrix.a && r1.matrix.b === t1.matrix.b && r1.matrix.c === t1.matrix.c && r1.matrix.d === t1.matrix.d && r1.matrix.e === t1.matrix.e && r1.matrix.f === t1.matrix.f; + }(); // Public API /** * @function module:browser.isOpera * @returns {boolean} */ + + var isOpera = function isOpera() { return isOpera_; }; @@ -2281,6 +2783,7 @@ * @function module:browser.isWebkit * @returns {boolean} */ + var isWebkit = function isWebkit() { return isWebkit_; }; @@ -2288,6 +2791,7 @@ * @function module:browser.isGecko * @returns {boolean} */ + var isGecko = function isGecko() { return isGecko_; }; @@ -2295,6 +2799,7 @@ * @function module:browser.isIE * @returns {boolean} */ + var isIE = function isIE() { return isIE_; }; @@ -2302,6 +2807,7 @@ * @function module:browser.isChrome * @returns {boolean} */ + var isChrome = function isChrome() { return isChrome_; }; @@ -2309,6 +2815,7 @@ * @function module:browser.isMac * @returns {boolean} */ + var isMac = function isMac() { return isMac_; }; @@ -2316,78 +2823,79 @@ * @function module:browser.isTouch * @returns {boolean} */ + var isTouch = function isTouch() { return isTouch_; }; - /** * @function module:browser.supportsSelectors * @returns {boolean} */ + var supportsSelectors = function supportsSelectors() { return supportsSelectors_; }; - /** * @function module:browser.supportsXpath * @returns {boolean} */ + var supportsXpath = function supportsXpath() { return supportsXpath_; }; - /** * @function module:browser.supportsPathReplaceItem * @returns {boolean} */ + var supportsPathReplaceItem = function supportsPathReplaceItem() { return supportsPathReplaceItem_; }; - /** * @function module:browser.supportsPathInsertItemBefore * @returns {boolean} */ + var supportsPathInsertItemBefore = function supportsPathInsertItemBefore() { return supportsPathInsertItemBefore_; }; - /** * @function module:browser.supportsPathBBox * @returns {boolean} */ + var supportsPathBBox = function supportsPathBBox() { return supportsPathBBox_; }; - /** * @function module:browser.supportsHVLineContainerBBox * @returns {boolean} */ + var supportsHVLineContainerBBox = function supportsHVLineContainerBBox() { return supportsHVLineContainerBBox_; }; - /** * @function module:browser.supportsGoodTextCharPos * @returns {boolean} */ + var supportsGoodTextCharPos = function supportsGoodTextCharPos() { return supportsGoodTextCharPos_; }; - /** * @function module:browser.supportsNonScalingStroke * @returns {boolean} */ + var supportsNonScalingStroke = function supportsNonScalingStroke() { return supportsNonScalingStroke_; }; - /** * @function module:browser.supportsNativeTransformLists * @returns {boolean} */ + var supportsNativeTransformLists = function supportsNativeTransformLists() { return supportsNativeSVGTransformLists_; }; @@ -2402,36 +2910,40 @@ * This fixes `$(...).attr()` to work as expected with SVG elements. * Does not currently use `*AttributeNS()` since we rarely need that. * Adds {@link external:jQuery.fn.attr}. - * See {@link https://api.jquery.com/attr/} for basic documentation of `.attr()` + * See {@link https://api.jquery.com/attr/} for basic documentation of `.attr()`. * * Additional functionality: * - When getting attributes, a string that's a number is returned as type number. * - If an array is supplied as the first parameter, multiple values are returned - * as an object with values for each given attribute + * as an object with values for each given attribute. * @function module:jQueryAttr.jQueryAttr * @param {external:jQuery} $ The jQuery object to which to add the plug-in * @returns {external:jQuery} */ - function jqPluginSVG ($) { + function jQueryPluginSVG($) { var proxied = $.fn.attr, svgns = 'http://www.w3.org/2000/svg'; /** * @typedef {PlainObject.} module:jQueryAttr.Attributes */ + /** * @function external:jQuery.fn.attr * @param {string|string[]|PlainObject.} key * @param {string} value * @returns {external:jQuery|module:jQueryAttr.Attributes} */ + $.fn.attr = function (key, value) { var len = this.length; + if (!len) { - return proxied.apply(this, arguments); + return proxied.call(this, key, value); } + for (var i = 0; i < len; ++i) { - var elem = this[i]; - // set/get SVG attribute + var elem = this[i]; // set/get SVG attribute + if (elem.namespaceURI === svgns) { // Setting attribute if (value !== undefined) { @@ -2443,87 +2955,72 @@ while (j--) { var aname = key[j]; - var attr = elem.getAttribute(aname); - // This returns a number when appropriate + var attr = elem.getAttribute(aname); // This returns a number when appropriate + if (attr || attr === '0') { attr = isNaN(attr) ? attr : attr - 0; } + obj[aname] = attr; } + return obj; } - if ((typeof key === 'undefined' ? 'undefined' : _typeof(key)) === 'object') { + + if (_typeof(key) === 'object') { // Setting attributes from object - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; + var _arr = Object.entries(key); - try { - for (var _iterator = Object.entries(key)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var _ref = _step.value; + for (var _i = 0; _i < _arr.length; _i++) { + var _arr$_i = _slicedToArray(_arr[_i], 2), + name = _arr$_i[0], + val = _arr$_i[1]; - var _ref2 = slicedToArray(_ref, 2); + elem.setAttribute(name, val); + } // Getting attribute - var name = _ref2[0]; - var val = _ref2[1]; - - elem.setAttribute(name, val); - } - // Getting attribute - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } } else { var _attr = elem.getAttribute(key); + if (_attr || _attr === '0') { _attr = isNaN(_attr) ? _attr : _attr - 0; } + return _attr; } } else { - return proxied.apply(this, arguments); + return proxied.call(this, key, value); } } + return this; }; + return $; } + var svgroot = document.createElementNS(NS.SVG, 'svg'); /** - * Partial polyfill of `SVGTransformList` - * @module SVGTransformList - * - * @license MIT - * - * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller + * Helper function to convert `SVGTransform` to a string. + * @param {SVGTransform} xform + * @returns {string} */ - var svgroot = document.createElementNS(NS.SVG, 'svg'); - - // Helper function. function transformToString(xform) { var m = xform.matrix; var text = ''; + switch (xform.type) { case 1: // MATRIX text = 'matrix(' + [m.a, m.b, m.c, m.d, m.e, m.f].join(',') + ')'; break; + case 2: // TRANSLATE text = 'translate(' + m.e + ',' + m.f + ')'; break; + case 3: // SCALE if (m.a === m.d) { @@ -2531,49 +3028,57 @@ } else { text = 'scale(' + m.a + ',' + m.d + ')'; } + break; + case 4: { // ROTATE var cx = 0; - var cy = 0; - // this prevents divide by zero + var cy = 0; // this prevents divide by zero + if (xform.angle !== 0) { var K = 1 - m.a; cy = (K * m.f + m.b * m.e) / (K * K + m.b * m.b); cx = (m.e - m.b * cy) / K; } + text = 'rotate(' + xform.angle + ' ' + cx + ',' + cy + ')'; break; } } + return text; } - /** * Map of SVGTransformList objects. */ - var listMap_ = {}; + + var listMap_ = {}; /** * @interface module:SVGTransformList.SVGEditTransformList * @property {Integer} numberOfItems unsigned long */ + /** * @function module:SVGTransformList.SVGEditTransformList#clear * @returns {undefined} */ + /** * @function module:SVGTransformList.SVGEditTransformList#initialize * @param {SVGTransform} newItem * @returns {SVGTransform} */ + /** * (DOES NOT THROW DOMException, INDEX_SIZE_ERR) * @function module:SVGTransformList.SVGEditTransformList#getItem * @param {Integer} index unsigned long * @returns {SVGTransform} */ + /** * (DOES NOT THROW DOMException, INDEX_SIZE_ERR) * @function module:SVGTransformList.SVGEditTransformList#insertItemBefore @@ -2581,6 +3086,7 @@ * @param {Integer} index unsigned long * @returns {SVGTransform} */ + /** * (DOES NOT THROW DOMException, INDEX_SIZE_ERR) * @function module:SVGTransformList.SVGEditTransformList#replaceItem @@ -2588,17 +3094,20 @@ * @param {Integer} index unsigned long * @returns {SVGTransform} */ + /** * (DOES NOT THROW DOMException, INDEX_SIZE_ERR) * @function module:SVGTransformList.SVGEditTransformList#removeItem * @param {Integer} index unsigned long * @returns {SVGTransform} */ + /** * @function module:SVGTransformList.SVGEditTransformList#appendItem * @param {SVGTransform} newItem * @returns {SVGTransform} */ + /** * NOT IMPLEMENTED * @ignore @@ -2606,6 +3115,7 @@ * @param {SVGMatrix} matrix * @returns {SVGTransform} */ + /** * NOT IMPLEMENTED * @ignore @@ -2618,42 +3128,55 @@ * These methods do not currently raise any exceptions. * These methods also do not check that transforms are being inserted. This is basically * implementing as much of SVGTransformList that we need to get the job done. + * @implements {module:SVGTransformList.SVGEditTransformList} */ - var SVGTransformList = function () { + + var SVGTransformList = + /*#__PURE__*/ + function () { + // eslint-disable-line no-shadow + /** * @param {Element} elem */ function SVGTransformList(elem) { - classCallCheck(this, SVGTransformList); + _classCallCheck(this, SVGTransformList); this._elem = elem || null; - this._xforms = []; - // TODO: how do we capture the undo-ability in the changed transform list? + this._xforms = []; // TODO: how do we capture the undo-ability in the changed transform list? + this._update = function () { - var tstr = ''; - /* const concatMatrix = */svgroot.createSVGMatrix(); + var tstr = ''; // /* const concatMatrix = */ svgroot.createSVGMatrix(); + for (var i = 0; i < this.numberOfItems; ++i) { var xform = this._list.getItem(i); + tstr += transformToString(xform) + ' '; } + this._elem.setAttribute('transform', tstr); }; + this._list = this; + this._init = function () { var _this = this; // Transform attribute parser var str = this._elem.getAttribute('transform'); + if (!str) { return; - } + } // TODO: Add skew support in future + - // TODO: Add skew support in future var re = /\s*((scale|matrix|rotate|translate)\s*\(.*?\))\s*,?\s*/; var m = true; + while (m) { m = str.match(re); str = str.replace(re, ''); + if (m && m[1]) { (function () { var x = m[1]; @@ -2666,6 +3189,7 @@ var mtx = svgroot.createSVGMatrix(); Object.values(valArr).forEach(function (item, i) { valArr[i] = parseFloat(item); + if (name === 'matrix') { mtx[letters[i]] = valArr[i]; } @@ -2681,30 +3205,29 @@ } else if (name === 'rotate' && values.length === 1) { values.push(0, 0); } - xform[fname].apply(xform, values); + + xform[fname].apply(xform, _toConsumableArray(values)); + _this._list.appendItem(xform); })(); } } }; + this._removeFromOtherLists = function (item) { if (item) { // Check if this transform is already in a transformlist, and // remove it if so. - var found = false; - for (var id in listMap_) { - var tl = listMap_[id]; + Object.values(listMap_).some(function (tl) { for (var i = 0, len = tl._xforms.length; i < len; ++i) { if (tl._xforms[i] === item) { - found = true; tl.removeItem(i); - break; + return true; } } - if (found) { - break; - } - } + + return false; + }); } }; @@ -2715,26 +3238,26 @@ */ - createClass(SVGTransformList, [{ - key: 'clear', + _createClass(SVGTransformList, [{ + key: "clear", value: function clear() { this.numberOfItems = 0; this._xforms = []; } - /** * @param {SVGTransform} newItem * @returns {SVGTransform} */ }, { - key: 'initialize', + key: "initialize", value: function initialize(newItem) { this.numberOfItems = 1; + this._removeFromOtherLists(newItem); + this._xforms = [newItem]; } - /** * @param {Integer} index unsigned long * @throws {Error} @@ -2742,16 +3265,16 @@ */ }, { - key: 'getItem', + key: "getItem", value: function getItem(index) { if (index < this.numberOfItems && index >= 0) { return this._xforms[index]; } + var err = new Error('DOMException with code=INDEX_SIZE_ERR'); err.code = 1; throw err; } - /** * @param {SVGTransform} newItem * @param {Integer} index unsigned long @@ -2759,33 +3282,40 @@ */ }, { - key: 'insertItemBefore', + key: "insertItemBefore", value: function insertItemBefore(newItem, index) { var retValue = null; + if (index >= 0) { if (index < this.numberOfItems) { this._removeFromOtherLists(newItem); - var newxforms = new Array(this.numberOfItems + 1); - // TODO: use array copying and slicing - var i = void 0; + + var newxforms = new Array(this.numberOfItems + 1); // TODO: use array copying and slicing + + var i; + for (i = 0; i < index; ++i) { newxforms[i] = this._xforms[i]; } + newxforms[i] = newItem; + for (var j = i + 1; i < this.numberOfItems; ++j, ++i) { newxforms[j] = this._xforms[i]; } + this.numberOfItems++; this._xforms = newxforms; retValue = newItem; + this._list._update(); } else { retValue = this._list.appendItem(newItem); } } + return retValue; } - /** * @param {SVGTransform} newItem * @param {Integer} index unsigned long @@ -2793,18 +3323,21 @@ */ }, { - key: 'replaceItem', + key: "replaceItem", value: function replaceItem(newItem, index) { var retValue = null; + if (index < this.numberOfItems && index >= 0) { this._removeFromOtherLists(newItem); + this._xforms[index] = newItem; retValue = newItem; + this._list._update(); } + return retValue; } - /** * @param {Integer} index unsigned long * @throws {Error} @@ -2812,90 +3345,108 @@ */ }, { - key: 'removeItem', + key: "removeItem", value: function removeItem(index) { if (index < this.numberOfItems && index >= 0) { var retValue = this._xforms[index]; var newxforms = new Array(this.numberOfItems - 1); - var i = void 0; + var i; + for (i = 0; i < index; ++i) { newxforms[i] = this._xforms[i]; } + for (var j = i; j < this.numberOfItems - 1; ++j, ++i) { newxforms[j] = this._xforms[i + 1]; } + this.numberOfItems--; this._xforms = newxforms; + this._list._update(); + return retValue; } + var err = new Error('DOMException with code=INDEX_SIZE_ERR'); err.code = 1; throw err; } - /** * @param {SVGTransform} newItem * @returns {SVGTransform} */ }, { - key: 'appendItem', + key: "appendItem", value: function appendItem(newItem) { this._removeFromOtherLists(newItem); + this._xforms.push(newItem); + this.numberOfItems++; + this._list._update(); + return newItem; } }]); + return SVGTransformList; }(); - /** * @function module:SVGTransformList.resetListMap * @returns {undefined} */ + var resetListMap = function resetListMap() { listMap_ = {}; }; - /** * Removes transforms of the given element from the map. * @function module:SVGTransformList.removeElementFromListMap * @param {Element} elem - a DOM Element * @returns {undefined} */ + var removeElementFromListMap = function removeElementFromListMap(elem) { + // eslint-disable-line import/no-mutable-exports if (elem.id && listMap_[elem.id]) { delete listMap_[elem.id]; } }; - /** - * Returns an object that behaves like a `SVGTransformList` for the given DOM element + * Returns an object that behaves like a `SVGTransformList` for the given DOM element. * @function module:SVGTransformList.getTransformList * @param {Element} elem - DOM element to get a transformlist from * @todo The polyfill should have `SVGAnimatedTransformList` and this should use it * @returns {SVGAnimatedTransformList|SVGTransformList} */ + var getTransformList = function getTransformList(elem) { if (!supportsNativeTransformLists()) { var id = elem.id || 'temp'; var t = listMap_[id]; + if (!t || id === 'temp') { listMap_[id] = new SVGTransformList(elem); + listMap_[id]._init(); + t = listMap_[id]; } + return t; } + if (elem.transform) { return elem.transform.baseVal; } + if (elem.gradientTransform) { return elem.gradientTransform.baseVal; } + if (elem.patternTransform) { return elem.patternTransform.baseVal; } @@ -2910,11 +3461,10 @@ * * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller */ - var wAttrs = ['x', 'x1', 'cx', 'rx', 'width']; var hAttrs = ['y', 'y1', 'cy', 'ry', 'height']; - var unitAttrs = ['r', 'radius'].concat(wAttrs, hAttrs); - // unused + var unitAttrs = ['r', 'radius'].concat(wAttrs, hAttrs); // unused + /* const unitNumMap = { '%': 2, @@ -2929,30 +3479,34 @@ }; */ // Container of elements. - var elementContainer_ = void 0; - // Stores mapping of unit type to user coordinates. + var elementContainer_; // Stores mapping of unit type to user coordinates. + var typeMap_ = {}; - /** * @interface module:units.ElementContainer */ + /** * @function module:units.ElementContainer#getBaseUnit * @returns {string} The base unit type of the container ('em') */ + /** * @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 * @returns {Float} The container's height */ + /** * @function module:units.ElementContainer#getWidth * @returns {Float} The container's width */ + /** * @function module:units.ElementContainer#getRoundDigits * @returns {Integer} The number of digits number should be rounded to @@ -2978,10 +3532,10 @@ * @param {module:units.ElementContainer} elementContainer - An object implementing the ElementContainer interface. * @returns {undefined} */ - var init = function init(elementContainer) { - elementContainer_ = elementContainer; - // Get correct em/ex values by creating a temporary SVG. + var init = function init(elementContainer) { + elementContainer_ = elementContainer; // Get correct em/ex values by creating a temporary SVG. + var svg = document.createElementNS(NS.SVG, 'svg'); document.body.append(svg); var rect = document.createElementNS(NS.SVG, 'rect'); @@ -2991,7 +3545,6 @@ svg.append(rect); var bb = rect.getBBox(); svg.remove(); - var inch = bb.x; typeMap_ = { em: bb.width, @@ -3005,7 +3558,6 @@ '%': 0 }; }; - /** * Group: Unit conversion functions */ @@ -3014,10 +3566,10 @@ * @function module:units.getTypeMap * @returns {module:units.TypeMap} The unit object with values for each unit */ + var getTypeMap = function getTypeMap() { return typeMap_; }; - /** * @typedef {GenericArray} module:units.CompareNumbers * @property {Integer} length 2 @@ -3034,31 +3586,35 @@ * @returns {Float|string} If a string/number was given, returns a Float. If an array, return a string * with comma-separated floats */ + var shortFloat = function shortFloat(val) { var digits = elementContainer_.getRoundDigits(); + if (!isNaN(val)) { - // Note that + converts to Number - return +(+val).toFixed(digits); + return Number(Number(val).toFixed(digits)); } + if (Array.isArray(val)) { return shortFloat(val[0]) + ',' + shortFloat(val[1]); } + return parseFloat(val).toFixed(digits) - 0; }; - /** - * Converts the number to given unit or baseUnit + * Converts the number to given unit or baseUnit. * @function module:units.convertUnit + * @param {string|Float} val + * @param {"em"|"ex"|"in"|"cm"|"mm"|"pt"|"pc"|"px"|"%"} [unit] * @returns {Float} */ + var convertUnit = function convertUnit(val, unit) { - unit = unit || elementContainer_.getBaseUnit(); - // baseVal.convertToSpecifiedUnits(unitNumMap[unit]); + unit = unit || elementContainer_.getBaseUnit(); // baseVal.convertToSpecifiedUnits(unitNumMap[unit]); // const val = baseVal.valueInSpecifiedUnits; // baseVal.convertToSpecifiedUnits(1); + return shortFloat(val / typeMap_[unit]); }; - /** * Sets an element's attribute based on the unit in its current value. * @@ -3068,11 +3624,11 @@ * @param {string} val - Attribute value to convert * @returns {undefined} */ + var setUnitAttr = function setUnitAttr(elem, attr, val) { // if (!isNaN(val)) { // New value is a number, so check currently used unit // const oldVal = elem.getAttribute(attr); - // Enable this for alternate mode // if (oldVal !== null && (isNaN(oldVal) || elementContainer_.getBaseUnit() !== 'px')) { // // Old value was a number, so get unit, then convert @@ -3102,109 +3658,112 @@ // } elem.setAttribute(attr, val); }; - /** * Converts given values to numbers. Attributes must be supplied in - * case a percentage is given + * case a percentage is given. * * @function module:units.convertToNum * @param {string} attr - Name of the attribute associated with the value * @param {string} val - Attribute value to convert * @returns {Float} The converted number */ + var convertToNum = function convertToNum(attr, val) { // Return a number if that's what it already is if (!isNaN(val)) { return val - 0; } + if (val.substr(-1) === '%') { // Deal with percentage, depends on attribute var _num = val.substr(0, val.length - 1) / 100; + var width = elementContainer_.getWidth(); var height = elementContainer_.getHeight(); if (wAttrs.includes(attr)) { return _num * width; } + if (hAttrs.includes(attr)) { return _num * height; } + return _num * Math.sqrt(width * width + height * height) / Math.sqrt(2); } + var unit = val.substr(-2); - var num = val.substr(0, val.length - 2); - // Note that this multiplication turns the string into a number + var num = val.substr(0, val.length - 2); // Note that this multiplication turns the string into a number + return num * typeMap_[unit]; }; - /** - * Check if an attribute's value is in a valid format + * Check if an attribute's value is in a valid format. * @function module:units.isValidUnit * @param {string} attr - The name of the attribute associated with the value * @param {string} val - The attribute value to check + * @param {Element} selectedElement * @returns {boolean} Whether the unit is valid */ + var isValidUnit = function isValidUnit(attr, val, selectedElement) { if (unitAttrs.includes(attr)) { // True if it's just a number if (!isNaN(val)) { return true; - } - // Not a number, check if it has a valid unit + } // Not a number, check if it has a valid unit + + val = val.toLowerCase(); return Object.keys(typeMap_).some(function (unit) { var re = new RegExp('^-?[\\d\\.]+' + unit + '$'); return re.test(val); }); } + if (attr === 'id') { // if we're trying to change the id, make sure it's not already present in the doc // and the id value is valid. - - var result = false; - // because getElem() can throw an exception in the case of an invalid id + var result = false; // because getElem() can throw an exception in the case of an invalid id // (according to https://www.w3.org/TR/xml-id/ IDs must be a NCName) // we wrap it in an exception and only return true if the ID was valid and // not already present + try { var elem = elementContainer_.getElement(val); - result = elem == null || elem === selectedElement; + result = isNullish(elem) || elem === selectedElement; } catch (e) {} + return result; } + return true; }; - /** - * For command history tracking and undo functionality - * @module history - * @license MIT - * @copyright 2010 Jeff Schiller - */ - /** * Group: Undo/Redo history management */ + var HistoryEventTypes = { BEFORE_APPLY: 'before_apply', AFTER_APPLY: 'after_apply', BEFORE_UNAPPLY: 'before_unapply', AFTER_UNAPPLY: 'after_unapply' - }; - - // const removedElements = {}; + }; // const removedElements = {}; /** - * Base class for commands + * Base class for commands. */ - var Command = function () { + var Command = + /*#__PURE__*/ + function () { function Command() { - classCallCheck(this, Command); + _classCallCheck(this, Command); } - createClass(Command, [{ - key: 'getText', + _createClass(Command, [{ + key: "getText", /** * @returns {string} @@ -3213,10 +3772,9 @@ return this.text; } }]); - return Command; - }(); - // Todo: Figure out why the interface members aren't showing + return Command; + }(); // Todo: Figure out why the interface members aren't showing // up (with or without modules applied), despite our apparently following // http://usejsdoc.org/tags-interface.html#virtual-comments @@ -3224,6 +3782,7 @@ * An interface that all command objects must implement. * @interface module:history.HistoryCommand */ + /** * Applies * @@ -3232,6 +3791,7 @@ * @fires module:history~Command#event:history * @returns {undefined|true} */ + /** * * Unapplies @@ -3240,21 +3800,25 @@ * @fires module:history~Command#event:history * @returns {undefined|true} */ + /** * Returns the elements * @function module:history.HistoryCommand#elements * @returns {Element[]} */ + /** * Gets the text * @function module:history.HistoryCommand#getText * @returns {string} */ + /** * Gives the type * @function module:history.HistoryCommand.type * @returns {string} */ + /** * Gives the type * @function module:history.HistoryCommand#type @@ -3270,6 +3834,7 @@ * An interface for objects that will handle history events. * @interface module:history.HistoryEventHandler */ + /** * * @function module:history.HistoryEventHandler#handleHistoryEvent @@ -3281,7 +3846,7 @@ */ /** - * History command for an element that had its DOM position changed + * History command for an element that had its DOM position changed. * @implements {module:history.HistoryCommand} * @param {Element} elem - The DOM element that was moved * @param {Element} oldNextSibling - The element's next sibling before it was moved @@ -3290,14 +3855,17 @@ */ - var MoveElementCommand = function (_Command) { - inherits(MoveElementCommand, _Command); + var MoveElementCommand = + /*#__PURE__*/ + function (_Command) { + _inherits(MoveElementCommand, _Command); function MoveElementCommand(elem, oldNextSibling, oldParent, text) { - classCallCheck(this, MoveElementCommand); + var _this; - var _this = possibleConstructorReturn(this, (MoveElementCommand.__proto__ || Object.getPrototypeOf(MoveElementCommand)).call(this)); + _classCallCheck(this, MoveElementCommand); + _this = _possibleConstructorReturn(this, _getPrototypeOf(MoveElementCommand).call(this)); _this.elem = elem; _this.text = text ? 'Move ' + elem.tagName + ' to ' + text : 'Move ' + elem.tagName; _this.oldNextSibling = oldNextSibling; @@ -3307,21 +3875,21 @@ return _this; } - createClass(MoveElementCommand, [{ - key: 'type', + _createClass(MoveElementCommand, [{ + key: "type", value: function type() { + // eslint-disable-line class-methods-use-this return 'svgedit.history.MoveElementCommand'; } - /** - * Re-positions the element + * Re-positions the element. * @param {module:history.HistoryEventHandler} handler * @fires module:history~Command#event:history * @returns {undefined} */ }, { - key: 'apply', + key: "apply", value: function apply(handler) { // TODO(codedread): Refactor this common event code into a base HistoryCommand class. if (handler) { @@ -3334,16 +3902,15 @@ handler.handleHistoryEvent(HistoryEventTypes.AFTER_APPLY, this); } } - /** - * Positions the element back to its original location + * Positions the element back to its original location. * @param {module:history.HistoryEventHandler} handler * @fires module:history~Command#event:history * @returns {undefined} */ }, { - key: 'unapply', + key: "unapply", value: function unapply(handler) { if (handler) { handler.handleHistoryEvent(HistoryEventTypes.BEFORE_UNAPPLY, this); @@ -3355,36 +3922,39 @@ handler.handleHistoryEvent(HistoryEventTypes.AFTER_UNAPPLY, this); } } - /** * @returns {Element[]} Array with element associated with this command */ }, { - key: 'elements', + key: "elements", value: function elements() { return [this.elem]; } }]); + return MoveElementCommand; }(Command); MoveElementCommand.type = MoveElementCommand.prototype.type; - /** - * History command for an element that was added to the DOM + * History command for an element that was added to the DOM. * @implements {module:history.HistoryCommand} * * @param {Element} elem - The newly added DOM element * @param {string} text - An optional string visible to user related to this change */ - var InsertElementCommand = function (_Command2) { - inherits(InsertElementCommand, _Command2); + + var InsertElementCommand = + /*#__PURE__*/ + function (_Command2) { + _inherits(InsertElementCommand, _Command2); function InsertElementCommand(elem, text) { - classCallCheck(this, InsertElementCommand); + var _this2; - var _this2 = possibleConstructorReturn(this, (InsertElementCommand.__proto__ || Object.getPrototypeOf(InsertElementCommand)).call(this)); + _classCallCheck(this, InsertElementCommand); + _this2 = _possibleConstructorReturn(this, _getPrototypeOf(InsertElementCommand).call(this)); _this2.elem = elem; _this2.text = text || 'Create ' + elem.tagName; _this2.parent = elem.parentNode; @@ -3392,21 +3962,21 @@ return _this2; } - createClass(InsertElementCommand, [{ - key: 'type', + _createClass(InsertElementCommand, [{ + key: "type", value: function type() { + // eslint-disable-line class-methods-use-this return 'svgedit.history.InsertElementCommand'; } - /** - * Re-inserts the new element + * Re-inserts the new element. * @param {module:history.HistoryEventHandler} handler * @fires module:history~Command#event:history * @returns {undefined} */ }, { - key: 'apply', + key: "apply", value: function apply(handler) { if (handler) { handler.handleHistoryEvent(HistoryEventTypes.BEFORE_APPLY, this); @@ -3418,16 +3988,15 @@ handler.handleHistoryEvent(HistoryEventTypes.AFTER_APPLY, this); } } - /** - * Removes the element + * Removes the element. * @param {module:history.HistoryEventHandler} handler * @fires module:history~Command#event:history * @returns {undefined} */ }, { - key: 'unapply', + key: "unapply", value: function unapply(handler) { if (handler) { handler.handleHistoryEvent(HistoryEventTypes.BEFORE_UNAPPLY, this); @@ -3440,62 +4009,64 @@ handler.handleHistoryEvent(HistoryEventTypes.AFTER_UNAPPLY, this); } } - /** * @returns {Element[]} Array with element associated with this command */ }, { - key: 'elements', + key: "elements", value: function elements() { return [this.elem]; } }]); + return InsertElementCommand; }(Command); InsertElementCommand.type = InsertElementCommand.prototype.type; - /** - * History command for an element removed from the DOM + * History command for an element removed from the DOM. * @implements {module:history.HistoryCommand} * @param {Element} elem - The removed DOM element * @param {Node} oldNextSibling - The DOM element's nextSibling when it was in the DOM * @param {Element} oldParent - The DOM element's parent * @param {string} [text] - An optional string visible to user related to this change */ - var RemoveElementCommand = function (_Command3) { - inherits(RemoveElementCommand, _Command3); + + var RemoveElementCommand = + /*#__PURE__*/ + function (_Command3) { + _inherits(RemoveElementCommand, _Command3); function RemoveElementCommand(elem, oldNextSibling, oldParent, text) { - classCallCheck(this, RemoveElementCommand); + var _this3; - var _this3 = possibleConstructorReturn(this, (RemoveElementCommand.__proto__ || Object.getPrototypeOf(RemoveElementCommand)).call(this)); + _classCallCheck(this, RemoveElementCommand); + _this3 = _possibleConstructorReturn(this, _getPrototypeOf(RemoveElementCommand).call(this)); _this3.elem = elem; _this3.text = text || 'Delete ' + elem.tagName; _this3.nextSibling = oldNextSibling; - _this3.parent = oldParent; + _this3.parent = oldParent; // special hack for webkit: remove this element's entry in the svgTransformLists map - // special hack for webkit: remove this element's entry in the svgTransformLists map removeElementFromListMap(elem); return _this3; } - createClass(RemoveElementCommand, [{ - key: 'type', + _createClass(RemoveElementCommand, [{ + key: "type", value: function type() { + // eslint-disable-line class-methods-use-this return 'svgedit.history.RemoveElementCommand'; } - /** - * Re-removes the new element + * Re-removes the new element. * @param {module:history.HistoryEventHandler} handler * @fires module:history~Command#event:history * @returns {undefined} */ }, { - key: 'apply', + key: "apply", value: function apply(handler) { if (handler) { handler.handleHistoryEvent(HistoryEventTypes.BEFORE_APPLY, this); @@ -3509,51 +4080,52 @@ handler.handleHistoryEvent(HistoryEventTypes.AFTER_APPLY, this); } } - /** - * Re-adds the new element + * Re-adds the new element. * @param {module:history.HistoryEventHandler} handler * @fires module:history~Command#event:history * @returns {undefined} */ }, { - key: 'unapply', + key: "unapply", value: function unapply(handler) { if (handler) { handler.handleHistoryEvent(HistoryEventTypes.BEFORE_UNAPPLY, this); } removeElementFromListMap(this.elem); - if (this.nextSibling == null) { + + if (isNullish(this.nextSibling)) { if (window.console) { - console.log('Error: reference element was lost'); + console.log('Error: reference element was lost'); // eslint-disable-line no-console } } + this.parent.insertBefore(this.elem, this.nextSibling); // Don't use `before` or `prepend` as `this.nextSibling` may be `null` if (handler) { handler.handleHistoryEvent(HistoryEventTypes.AFTER_UNAPPLY, this); } } - /** * @returns {Element[]} Array with element associated with this command */ }, { - key: 'elements', + key: "elements", value: function elements() { return [this.elem]; } }]); + return RemoveElementCommand; }(Command); RemoveElementCommand.type = RemoveElementCommand.prototype.type; - /** * @typedef {"#text"|"#href"|string} module:history.CommandAttributeName */ + /** * @typedef {PlainObject.} module:history.CommandAttributes */ @@ -3566,18 +4138,23 @@ * @param {module:history.CommandAttributes} attrs - Attributes to be changed with the values they had *before* the change * @param {string} text - An optional string visible to user related to this change */ - var ChangeElementCommand = function (_Command4) { - inherits(ChangeElementCommand, _Command4); + + var ChangeElementCommand = + /*#__PURE__*/ + function (_Command4) { + _inherits(ChangeElementCommand, _Command4); function ChangeElementCommand(elem, attrs, text) { - classCallCheck(this, ChangeElementCommand); + var _this4; - var _this4 = possibleConstructorReturn(this, (ChangeElementCommand.__proto__ || Object.getPrototypeOf(ChangeElementCommand)).call(this)); + _classCallCheck(this, ChangeElementCommand); + _this4 = _possibleConstructorReturn(this, _getPrototypeOf(ChangeElementCommand).call(this)); _this4.elem = elem; _this4.text = text ? 'Change ' + elem.tagName + ' ' + text : 'Change ' + elem.tagName; _this4.newValues = {}; _this4.oldValues = attrs; + for (var attr in attrs) { if (attr === '#text') { _this4.newValues[attr] = elem.textContent; @@ -3587,61 +4164,68 @@ _this4.newValues[attr] = elem.getAttribute(attr); } } + return _this4; } - createClass(ChangeElementCommand, [{ - key: 'type', + _createClass(ChangeElementCommand, [{ + key: "type", value: function type() { + // eslint-disable-line class-methods-use-this return 'svgedit.history.ChangeElementCommand'; } - /** - * Performs the stored change action + * Performs the stored change action. * @param {module:history.HistoryEventHandler} handler * @fires module:history~Command#event:history * @returns {true} */ }, { - key: 'apply', + key: "apply", value: function apply(handler) { + var _this5 = this; + if (handler) { handler.handleHistoryEvent(HistoryEventTypes.BEFORE_APPLY, this); } var bChangedTransform = false; - for (var attr in this.newValues) { - if (this.newValues[attr]) { + Object.entries(this.newValues).forEach(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + attr = _ref2[0], + value = _ref2[1]; + + if (value) { if (attr === '#text') { - this.elem.textContent = this.newValues[attr]; + _this5.elem.textContent = value; } else if (attr === '#href') { - setHref(this.elem, this.newValues[attr]); + setHref(_this5.elem, value); } else { - this.elem.setAttribute(attr, this.newValues[attr]); + _this5.elem.setAttribute(attr, value); } + } else if (attr === '#text') { + _this5.elem.textContent = ''; } else { - if (attr === '#text') { - this.elem.textContent = ''; - } else { - this.elem.setAttribute(attr, ''); - this.elem.removeAttribute(attr); - } + _this5.elem.setAttribute(attr, ''); + + _this5.elem.removeAttribute(attr); } if (attr === 'transform') { bChangedTransform = true; } - } + }); // relocate rotational transform, if necessary - // relocate rotational transform, if necessary if (!bChangedTransform) { var angle = getRotationAngle(this.elem); + if (angle) { var bbox = this.elem.getBBox(); var cx = bbox.x + bbox.width / 2, cy = bbox.y + bbox.height / 2; var rotate = ['rotate(', angle, ' ', cx, ',', cy, ')'].join(''); + if (rotate !== this.elem.getAttribute('transform')) { this.elem.setAttribute('transform', rotate); } @@ -3654,57 +4238,63 @@ return true; } - /** - * Reverses the stored change action + * Reverses the stored change action. * @param {module:history.HistoryEventHandler} handler * @fires module:history~Command#event:history * @returns {true} */ }, { - key: 'unapply', + key: "unapply", value: function unapply(handler) { + var _this6 = this; + if (handler) { handler.handleHistoryEvent(HistoryEventTypes.BEFORE_UNAPPLY, this); } var bChangedTransform = false; - for (var attr in this.oldValues) { - if (this.oldValues[attr]) { + Object.entries(this.oldValues).forEach(function (_ref3) { + var _ref4 = _slicedToArray(_ref3, 2), + attr = _ref4[0], + value = _ref4[1]; + + if (value) { if (attr === '#text') { - this.elem.textContent = this.oldValues[attr]; + _this6.elem.textContent = value; } else if (attr === '#href') { - setHref(this.elem, this.oldValues[attr]); + setHref(_this6.elem, value); } else { - this.elem.setAttribute(attr, this.oldValues[attr]); + _this6.elem.setAttribute(attr, value); } + } else if (attr === '#text') { + _this6.elem.textContent = ''; } else { - if (attr === '#text') { - this.elem.textContent = ''; - } else { - this.elem.removeAttribute(attr); - } + _this6.elem.removeAttribute(attr); } + if (attr === 'transform') { bChangedTransform = true; } - } - // relocate rotational transform, if necessary + }); // relocate rotational transform, if necessary + if (!bChangedTransform) { var angle = getRotationAngle(this.elem); + if (angle) { var bbox = this.elem.getBBox(); var cx = bbox.x + bbox.width / 2, cy = bbox.y + bbox.height / 2; var rotate = ['rotate(', angle, ' ', cx, ',', cy, ')'].join(''); + if (rotate !== this.elem.getAttribute('transform')) { this.elem.setAttribute('transform', rotate); } } - } + } // Remove transformlist to prevent confusion that causes bugs like 575. + - // Remove transformlist to prevent confusion that causes bugs like 575. removeElementFromListMap(this.elem); if (handler) { @@ -3713,66 +4303,69 @@ return true; } - /** * @returns {Element[]} Array with element associated with this command */ }, { - key: 'elements', + key: "elements", value: function elements() { return [this.elem]; } }]); + return ChangeElementCommand; }(Command); - ChangeElementCommand.type = ChangeElementCommand.prototype.type; - - // TODO: create a 'typing' command object that tracks changes in text + ChangeElementCommand.type = ChangeElementCommand.prototype.type; // TODO: create a 'typing' command object that tracks changes in text // if a new Typing command is created and the top command on the stack is also a Typing // and they both affect the same element, then collapse the two commands into one /** - * History command that can contain/execute multiple other commands + * History command that can contain/execute multiple other commands. * @implements {module:history.HistoryCommand} */ - var BatchCommand = function (_Command5) { - inherits(BatchCommand, _Command5); + + var BatchCommand = + /*#__PURE__*/ + function (_Command5) { + _inherits(BatchCommand, _Command5); /** * @param {string} [text] - An optional string visible to user related to this change */ function BatchCommand(text) { - classCallCheck(this, BatchCommand); + var _this7; - var _this5 = possibleConstructorReturn(this, (BatchCommand.__proto__ || Object.getPrototypeOf(BatchCommand)).call(this)); + _classCallCheck(this, BatchCommand); - _this5.text = text || 'Batch Command'; - _this5.stack = []; - return _this5; + _this7 = _possibleConstructorReturn(this, _getPrototypeOf(BatchCommand).call(this)); + _this7.text = text || 'Batch Command'; + _this7.stack = []; + return _this7; } - createClass(BatchCommand, [{ - key: 'type', + _createClass(BatchCommand, [{ + key: "type", value: function type() { + // eslint-disable-line class-methods-use-this return 'svgedit.history.BatchCommand'; } - /** - * Runs "apply" on all subcommands + * Runs "apply" on all subcommands. * @param {module:history.HistoryEventHandler} handler * @fires module:history~Command#event:history * @returns {undefined} */ }, { - key: 'apply', + key: "apply", value: function apply(handler) { if (handler) { handler.handleHistoryEvent(HistoryEventTypes.BEFORE_APPLY, this); } var len = this.stack.length; + for (var i = 0; i < len; ++i) { this.stack[i].apply(handler); } @@ -3781,16 +4374,15 @@ handler.handleHistoryEvent(HistoryEventTypes.AFTER_APPLY, this); } } - /** - * Runs "unapply" on all subcommands + * Runs "unapply" on all subcommands. * @param {module:history.HistoryEventHandler} handler * @fires module:history~Command#event:history * @returns {undefined} */ }, { - key: 'unapply', + key: "unapply", value: function unapply(handler) { if (handler) { handler.handleHistoryEvent(HistoryEventTypes.BEFORE_UNAPPLY, this); @@ -3804,178 +4396,172 @@ handler.handleHistoryEvent(HistoryEventTypes.AFTER_UNAPPLY, this); } } - /** - * Iterate through all our subcommands + * Iterate through all our subcommands. * @returns {Element[]} All the elements we are changing */ }, { - key: 'elements', + key: "elements", value: function elements() { var elems = []; var cmd = this.stack.length; + while (cmd--) { var thisElems = this.stack[cmd].elements(); var elem = thisElems.length; + while (elem--) { if (!elems.includes(thisElems[elem])) { elems.push(thisElems[elem]); } } } + return elems; } - /** - * Adds a given command to the history stack + * Adds a given command to the history stack. * @param {Command} cmd - The undo command object to add + * @returns {undefined} */ }, { - key: 'addSubCommand', + key: "addSubCommand", value: function addSubCommand(cmd) { this.stack.push(cmd); } - /** * @returns {boolean} Indicates whether or not the batch command is empty */ }, { - key: 'isEmpty', + key: "isEmpty", value: function isEmpty() { return !this.stack.length; } }]); + return BatchCommand; }(Command); BatchCommand.type = BatchCommand.prototype.type; - /** * */ - var UndoManager = function () { + + var UndoManager = + /*#__PURE__*/ + function () { /** * @param {module:history.HistoryEventHandler} historyEventHandler */ function UndoManager(historyEventHandler) { - classCallCheck(this, UndoManager); + _classCallCheck(this, UndoManager); this.handler_ = historyEventHandler || null; this.undoStackPointer = 0; - this.undoStack = []; - - // this is the stack that stores the original values, the elements and + this.undoStack = []; // this is the stack that stores the original values, the elements and // the attribute name for begin/finish + this.undoChangeStackPointer = -1; this.undoableChangeStack = []; } - /** - * Resets the undo stack, effectively clearing the undo/redo history + * Resets the undo stack, effectively clearing the undo/redo history. * @returns {undefined} */ - createClass(UndoManager, [{ - key: 'resetUndoStack', + _createClass(UndoManager, [{ + key: "resetUndoStack", value: function resetUndoStack() { this.undoStack = []; this.undoStackPointer = 0; } - /** * @returns {Integer} Current size of the undo history stack */ }, { - key: 'getUndoStackSize', + key: "getUndoStackSize", value: function getUndoStackSize() { return this.undoStackPointer; } - /** * @returns {Integer} Current size of the redo history stack */ }, { - key: 'getRedoStackSize', + key: "getRedoStackSize", value: function getRedoStackSize() { return this.undoStack.length - this.undoStackPointer; } - /** * @returns {string} String associated with the next undo command */ }, { - key: 'getNextUndoCommandText', + key: "getNextUndoCommandText", value: function getNextUndoCommandText() { return this.undoStackPointer > 0 ? this.undoStack[this.undoStackPointer - 1].getText() : ''; } - /** * @returns {string} String associated with the next redo command */ }, { - key: 'getNextRedoCommandText', + key: "getNextRedoCommandText", value: function getNextRedoCommandText() { return this.undoStackPointer < this.undoStack.length ? this.undoStack[this.undoStackPointer].getText() : ''; } - /** - * Performs an undo step + * Performs an undo step. * @returns {undefined} */ }, { - key: 'undo', + key: "undo", value: function undo() { if (this.undoStackPointer > 0) { var cmd = this.undoStack[--this.undoStackPointer]; cmd.unapply(this.handler_); } } - /** - * Performs a redo step + * Performs a redo step. * @returns {undefined} */ }, { - key: 'redo', + key: "redo", value: function redo() { if (this.undoStackPointer < this.undoStack.length && this.undoStack.length > 0) { var cmd = this.undoStack[this.undoStackPointer++]; cmd.apply(this.handler_); } } - /** - * Adds a command object to the undo history stack + * Adds a command object to the undo history stack. * @param {Command} cmd - The command object to add * @returns {undefined} */ }, { - key: 'addCommandToHistory', + key: "addCommandToHistory", value: function addCommandToHistory(cmd) { // FIXME: we MUST compress consecutive text changes to the same element // (right now each keystroke is saved as a separate command that includes the // entire text contents of the text element) // TODO: consider limiting the history that we store here (need to do some slicing) - // if our stack pointer is not at the end, then we have to remove // all commands after the pointer and insert the new command if (this.undoStackPointer < this.undoStack.length && this.undoStack.length > 0) { this.undoStack = this.undoStack.splice(0, this.undoStackPointer); } + this.undoStack.push(cmd); this.undoStackPointer = this.undoStack.length; } - /** * This function tells the canvas to remember the old values of the * `attrName` attribute for each element sent in. The elements and values @@ -3988,62 +4574,70 @@ */ }, { - key: 'beginUndoableChange', + key: "beginUndoableChange", value: function beginUndoableChange(attrName, elems) { var p = ++this.undoChangeStackPointer; var i = elems.length; var oldValues = new Array(i), elements = new Array(i); + while (i--) { var elem = elems[i]; - if (elem == null) { + + if (isNullish(elem)) { continue; } + elements[i] = elem; oldValues[i] = elem.getAttribute(attrName); } + this.undoableChangeStack[p] = { attrName: attrName, oldValues: oldValues, elements: elements }; } - /** * This function returns a `BatchCommand` object which summarizes the * change since `beginUndoableChange` was called. The command can then - * be added to the command history + * be added to the command history. * @returns {BatchCommand} Batch command object with resulting changes */ }, { - key: 'finishUndoableChange', + key: "finishUndoableChange", value: function finishUndoableChange() { var p = this.undoChangeStackPointer--; var changeset = this.undoableChangeStack[p]; var attrName = changeset.attrName; - var batchCmd = new BatchCommand('Change ' + attrName); var i = changeset.elements.length; + while (i--) { var elem = changeset.elements[i]; - if (elem == null) { + + if (isNullish(elem)) { continue; } + var changes = {}; changes[attrName] = changeset.oldValues[i]; + if (changes[attrName] !== elem.getAttribute(attrName)) { batchCmd.addSubCommand(new ChangeElementCommand(elem, changes, attrName)); } } + this.undoableChangeStack[p] = null; return batchCmd; } }]); + return UndoManager; }(); - var history = /*#__PURE__*/Object.freeze({ + var hstry = /*#__PURE__*/Object.freeze({ HistoryEventTypes: HistoryEventTypes, MoveElementCommand: MoveElementCommand, InsertElementCommand: InsertElementCommand, @@ -4061,45 +4655,46 @@ * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller */ - // Constants - var NEAR_ZERO = 1e-14; + var NEAR_ZERO = 1e-14; // Throw away SVGSVGElement used for creating matrices/transforms. - // Throw away SVGSVGElement used for creating matrices/transforms. var svg$1 = document.createElementNS(NS.SVG, 'svg'); - /** * A (hopefully) quicker function to transform a point by a matrix - * (this function avoids any DOM calls and just does the math) + * (this function avoids any DOM calls and just does the math). * @function module:math.transformPoint * @param {Float} x - Float representing the x coordinate * @param {Float} y - Float representing the y coordinate * @param {SVGMatrix} m - Matrix object to transform the point with * @returns {module:math.XYObject} An x, y object representing the transformed point */ - var transformPoint = function transformPoint(x, y, m) { - return { x: m.a * x + m.c * y + m.e, y: m.b * x + m.d * y + m.f }; - }; + var transformPoint = function transformPoint(x, y, m) { + return { + x: m.a * x + m.c * y + m.e, + y: m.b * x + m.d * y + m.f + }; + }; /** * Helper function to check if the matrix performs no actual transform - * (i.e. exists for identity purposes) + * (i.e. exists for identity purposes). * @function module:math.isIdentity * @param {SVGMatrix} m - The matrix object to check * @returns {boolean} Indicates whether or not the matrix is 1,0,0,1,0,0 */ + var isIdentity = function isIdentity(m) { return m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && m.e === 0 && m.f === 0; }; - /** * This function tries to return a `SVGMatrix` that is the multiplication `m1 * m2`. - * We also round to zero when it's near zero + * We also round to zero when it's near zero. * @function module:math.matrixMultiply * @param {...SVGMatrix} args - Matrix objects to multiply * @returns {SVGMatrix} The matrix object resulting from the calculation */ + var matrixMultiply = function matrixMultiply() { - for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } @@ -4110,45 +4705,46 @@ if (Math.abs(m.a) < NEAR_ZERO) { m.a = 0; } + if (Math.abs(m.b) < NEAR_ZERO) { m.b = 0; } + if (Math.abs(m.c) < NEAR_ZERO) { m.c = 0; } + if (Math.abs(m.d) < NEAR_ZERO) { m.d = 0; } + if (Math.abs(m.e) < NEAR_ZERO) { m.e = 0; } + if (Math.abs(m.f) < NEAR_ZERO) { m.f = 0; } return m; }; - - /** - * See if the given transformlist includes a non-indentity matrix transform - * @function module:math.hasMatrixTransform - * @param {SVGTransformList} [tlist] - The transformlist to check - * @returns {boolean} Whether or not a matrix transform was found - */ var hasMatrixTransform = function hasMatrixTransform(tlist) { if (!tlist) { return false; } + var num = tlist.numberOfItems; + while (num--) { var xform = tlist.getItem(num); + if (xform.type === 1 && !isIdentity(xform.matrix)) { return true; } } + return false; }; - /** * @typedef {PlainObject} module:math.TransformedBox An object with the following values * @property {module:math.XYObject} tl - The top left coordinate @@ -4163,7 +4759,7 @@ */ /** - * Transforms a rectangle based on the given matrix + * Transforms a rectangle based on the given matrix. * @function module:math.transformBox * @param {Float} l - Float with the box's left coordinate * @param {Float} t - Float with the box's top coordinate @@ -4172,6 +4768,7 @@ * @param {SVGMatrix} m - Matrix object to transform the box by * @returns {module:math.TransformedBox} */ + var transformBox = function transformBox(l, t, w, h, m) { var tl = transformPoint(l, t, m), tr = transformPoint(l + w, t, m), @@ -4181,7 +4778,6 @@ maxx = Math.max(tl.x, tr.x, bl.x, br.x), miny = Math.min(tl.y, tr.y, bl.y, br.y), maxy = Math.max(tl.y, tr.y, bl.y, br.y); - return { tl: tl, tr: tr, @@ -4195,12 +4791,11 @@ } }; }; - /** * This returns a single matrix Transform for a given Transform List * (this is the equivalent of `SVGTransformList.consolidate()` but unlike * that method, this one does not modify the actual `SVGTransformList`). - * This function is very liberal with its `min`, `max` arguments + * This function is very liberal with its `min`, `max` arguments. * @function module:math.transformListToTransform * @param {SVGTransformList} tlist - The transformlist object * @param {Integer} [min=0] - Optional integer indicating start transform position @@ -4208,90 +4803,103 @@ * defaults to one less than the tlist's `numberOfItems` * @returns {SVGTransform} A single matrix transform object */ + var transformListToTransform = function transformListToTransform(tlist, min, max) { - if (tlist == null) { + if (isNullish(tlist)) { // Or should tlist = null have been prevented before this? return svg$1.createSVGTransformFromMatrix(svg$1.createSVGMatrix()); } + min = min || 0; max = max || tlist.numberOfItems - 1; - min = parseInt(min, 10); - max = parseInt(max, 10); + min = parseInt(min); + max = parseInt(max); + if (min > max) { - var temp = max;max = min;min = temp; + var temp = max; + max = min; + min = temp; } + var m = svg$1.createSVGMatrix(); + for (var i = min; i <= max; ++i) { // if our indices are out of range, just use a harmless identity matrix var mtom = i >= 0 && i < tlist.numberOfItems ? tlist.getItem(i).matrix : svg$1.createSVGMatrix(); m = matrixMultiply(m, mtom); } + return svg$1.createSVGTransformFromMatrix(m); }; - /** - * Get the matrix object for a given element + * Get the matrix object for a given element. * @function module:math.getMatrix * @param {Element} elem - The DOM element to check * @returns {SVGMatrix} The matrix object associated with the element's transformlist */ + var getMatrix = function getMatrix(elem) { var tlist = getTransformList(elem); return transformListToTransform(tlist).matrix; }; - /** * Returns a 45 degree angle coordinate associated with the two given - * coordinates + * coordinates. * @function module:math.snapToAngle * @param {Integer} x1 - First coordinate's x value - * @param {Integer} x2 - Second coordinate's x value * @param {Integer} y1 - First coordinate's y value + * @param {Integer} x2 - Second coordinate's x value * @param {Integer} y2 - Second coordinate's y value * @returns {module:math.AngleCoord45} */ + var snapToAngle = function snapToAngle(x1, y1, x2, y2) { var snap = Math.PI / 4; // 45 degrees + var dx = x2 - x1; var dy = y2 - y1; var angle = Math.atan2(dy, dx); var dist = Math.sqrt(dx * dx + dy * dy); var snapangle = Math.round(angle / snap) * snap; - return { x: x1 + dist * Math.cos(snapangle), y: y1 + dist * Math.sin(snapangle), a: snapangle }; }; - /** - * Check if two rectangles (BBoxes objects) intersect each other + * Check if two rectangles (BBoxes objects) intersect each other. * @function module:math.rectsIntersect * @param {SVGRect} r1 - The first BBox-like object * @param {SVGRect} r2 - The second BBox-like object * @returns {boolean} True if rectangles intersect */ + var rectsIntersect = function rectsIntersect(r1, r2) { return r2.x < r1.x + r1.width && r2.x + r2.width > r1.x && r2.y < r1.y + r1.height && r2.y + r2.height > r1.y; }; - /* globals jQuery */ - var $$1 = jQuery; - var segData = { - 2: ['x', 'y'], // PATHSEG_MOVETO_ABS - 4: ['x', 'y'], // PATHSEG_LINETO_ABS - 6: ['x', 'y', 'x1', 'y1', 'x2', 'y2'], // PATHSEG_CURVETO_CUBIC_ABS - 8: ['x', 'y', 'x1', 'y1'], // PATHSEG_CURVETO_QUADRATIC_ABS - 10: ['x', 'y', 'r1', 'r2', 'angle', 'largeArcFlag', 'sweepFlag'], // PATHSEG_ARC_ABS - 12: ['x'], // PATHSEG_LINETO_HORIZONTAL_ABS - 14: ['y'], // PATHSEG_LINETO_VERTICAL_ABS - 16: ['x', 'y', 'x2', 'y2'], // PATHSEG_CURVETO_CUBIC_SMOOTH_ABS + 2: ['x', 'y'], + // PATHSEG_MOVETO_ABS + 4: ['x', 'y'], + // PATHSEG_LINETO_ABS + 6: ['x', 'y', 'x1', 'y1', 'x2', 'y2'], + // PATHSEG_CURVETO_CUBIC_ABS + 8: ['x', 'y', 'x1', 'y1'], + // PATHSEG_CURVETO_QUADRATIC_ABS + 10: ['x', 'y', 'r1', 'r2', 'angle', 'largeArcFlag', 'sweepFlag'], + // PATHSEG_ARC_ABS + 12: ['x'], + // PATHSEG_LINETO_HORIZONTAL_ABS + 14: ['y'], + // PATHSEG_LINETO_VERTICAL_ABS + 16: ['x', 'y', 'x2', 'y2'], + // PATHSEG_CURVETO_CUBIC_SMOOTH_ABS 18: ['x', 'y'] // PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS - }; + }; /** * @tutorial LocaleDocs * @typedef {module:locale.LocaleStrings|PlainObject} module:path.uiStrings @@ -4304,36 +4912,33 @@ * @param {module:path.uiStrings} strs * @returns {undefined} */ + var setUiStrings = function setUiStrings(strs) { Object.assign(uiStrings, strs.ui); }; - var pathFuncs = []; - - var linkControlPts = true; - - // Stores references to paths via IDs. + var linkControlPts = true; // Stores references to paths via IDs. // TODO: Make this cross-document happy. - var pathData = {}; + var pathData = {}; /** * @function module:path.setLinkControlPoints * @param {boolean} lcp * @returns {undefined} */ + var setLinkControlPoints = function setLinkControlPoints(lcp) { linkControlPts = lcp; }; - /** * @name module:path.path * @type {null|module:path.Path} * @memberof module:path */ - var path = null; + + var path = null; // eslint-disable-line import/no-mutable-exports var editorContext_ = null; - /** * @external MouseEvent */ @@ -4347,44 +4952,52 @@ * @property {module:path.SVGElementJSON[]} [children] - Data objects to be added recursively as children * @property {string} [namespace="http://www.w3.org/2000/svg"] - Indicate a (non-SVG) namespace */ + /** * @interface module:path.EditorContext * @property {module:select.SelectorManager} selectorManager * @property {module:svgcanvas.SvgCanvas} canvas */ + /** * @function module:path.EditorContext#call * @param {"selected"|"changed"} ev - String with the event name * @param {module:svgcanvas.SvgCanvas#event:selected|module:svgcanvas.SvgCanvas#event:changed} arg - Argument to pass through to the callback function. If the event is "changed", an array of `Element`s is passed; if "selected", a single-item array of `Element` is passed. * @returns {undefined} */ + /** * @function module:path.EditorContext#resetD * @param {SVGPathElement} p * @returns {undefined} */ + /** * Note: This doesn't round to an integer necessarily * @function module:path.EditorContext#round * @param {Float} val * @returns {Float} Rounded value to nearest value based on `currentZoom` */ + /** * @function module:path.EditorContext#clearSelection * @param {boolean} [noCall] - When `true`, does not call the "selected" handler * @returns {undefined} */ + /** * @function module:path.EditorContext#addToSelection * @param {Element[]} elemsToAdd - An array of DOM elements to add to the selection * @param {boolean} showGrips - Indicates whether the resize grips should be shown * @returns {undefined} */ + /** * @function module:path.EditorContext#addCommandToHistory * @param {Command} cmd * @returns {undefined} */ + /** * @function module:path.EditorContext#remapElement * @param {Element} selected - DOM element to be changed @@ -4392,41 +5005,50 @@ * @param {SVGMatrix} m - Matrix object to use for remapping coordinates * @returns {undefined} */ + /** * @function module:path.EditorContext#addSVGElementFromJson * @param {module:path.SVGElementJSON} data * @returns {Element} The new element */ + /** * @function module:path.EditorContext#getGridSnapping * @returns {boolean} */ + /** * @function module:path.EditorContext#getOpacity * @returns {Float} */ + /** * @function module:path.EditorContext#getSelectedElements * @returns {Element[]} the array with selected DOM elements */ + /** * @function module:path.EditorContext#getContainer * @returns {Element} */ + /** * @function module:path.EditorContext#setStarted * @param {boolean} s * @returns {undefined} */ + /** * @function module:path.EditorContext#getRubberBox * @returns {SVGRectElement} */ + /** * @function module:path.EditorContext#setRubberBox * @param {SVGRectElement} rb * @returns {SVGRectElement} Same as parameter passed in */ + /** * @function module:path.EditorContext#addPtsToSelection * @param {PlainObject} cfg @@ -4434,6 +5056,7 @@ * @param {SVGCircleElement[]} cfg.grips * @returns {undefined} */ + /** * @function module:path.EditorContext#endChanges * @param {PlainObject} cfg @@ -4441,44 +5064,53 @@ * @param {Element} cfg.elem * @returns {undefined} */ + /** * @function module:path.EditorContext#getCurrentZoom * @returns {Float} The current zoom level */ + /** * Returns the last created DOM element ID string * @function module:path.EditorContext#getId * @returns {string} */ + /** * Creates and returns a unique ID string for a DOM element * @function module:path.EditorContext#getNextId * @returns {string} */ + /** * Gets the desired element from a mouse event * @function module:path.EditorContext#getMouseTarget * @param {external:MouseEvent} evt - Event object from the mouse event * @returns {Element} DOM element we want */ + /** * @function module:path.EditorContext#getCurrentMode * @returns {string} */ + /** * @function module:path.EditorContext#setCurrentMode * @param {string} cm The mode * @returns {string} The same mode as passed in */ + /** * @function module:path.EditorContext#getDrawnPath * @returns {SVGPathElement|null} */ + /** * @function module:path.EditorContext#setDrawnPath * @param {SVGPathElement|null} dp * @returns {SVGPathElement|null} The same value as passed in */ + /** * @function module:path.EditorContext#getSVGRoot * @returns {SVGSVGElement} @@ -4489,9 +5121,9 @@ * @param {module:path.EditorContext} editorContext * @returns {undefined} */ - var init$1 = function init$$1(editorContext) { - editorContext_ = editorContext; + var init$1 = function init(editorContext) { + editorContext_ = editorContext; pathFuncs = [0, 'ClosePath']; var pathFuncsStrs = ['Moveto', 'Lineto', 'CurvetoCubic', 'CurvetoQuadratic', 'Arc', 'LinetoHorizontal', 'LinetoVertical', 'CurvetoCubicSmooth', 'CurvetoQuadraticSmooth']; $$1.each(pathFuncsStrs, function (i, s) { @@ -4499,7 +5131,6 @@ pathFuncs.push(s + 'Rel'); }); }; - /** * @function module:path.insertItemBefore * @param {Element} elem @@ -4507,6 +5138,7 @@ * @param {Integer} index * @returns {undefined} */ + var insertItemBefore = function insertItemBefore(elem, newseg, index) { // Support insertItemBefore on paths for FF2 var list = elem.pathSegList; @@ -4515,22 +5147,26 @@ list.insertItemBefore(newseg, index); return; } + var len = list.numberOfItems; var arr = []; + for (var i = 0; i < len; i++) { var curSeg = list.getItem(i); arr.push(curSeg); } + list.clear(); + for (var _i = 0; _i < len; _i++) { if (_i === index) { // index + 1 list.appendItem(newseg); } + list.appendItem(arr[_i]); } }; - /** * @function module:path.ptObjToArr * @todo See if this should just live in `replacePathSeg` @@ -4538,53 +5174,52 @@ * @param {SVGPathSegMovetoAbs|SVGPathSegLinetoAbs|SVGPathSegCurvetoCubicAbs|SVGPathSegCurvetoQuadraticAbs|SVGPathSegArcAbs|SVGPathSegLinetoHorizontalAbs|SVGPathSegLinetoVerticalAbs|SVGPathSegCurvetoCubicSmoothAbs|SVGPathSegCurvetoQuadraticSmoothAbs} segItem * @returns {ArgumentsArray} */ + var ptObjToArr = function ptObjToArr(type, segItem) { var props = segData[type]; return props.map(function (prop) { return segItem[prop]; }); }; - /** * @function module:path.getGripPt * @param {Segment} seg * @param {module:math.XYObject} altPt * @returns {module:math.XYObject} */ - var getGripPt = function getGripPt(seg, altPt) { - var path = seg.path; + var getGripPt = function getGripPt(seg, altPt) { + var pth = seg.path; var out = { x: altPt ? altPt.x : seg.item.x, y: altPt ? altPt.y : seg.item.y }; - if (path.matrix) { - var pt = transformPoint(out.x, out.y, path.matrix); + if (pth.matrix) { + var pt = transformPoint(out.x, out.y, pth.matrix); out = pt; } var currentZoom = editorContext_.getCurrentZoom(); out.x *= currentZoom; out.y *= currentZoom; - return out; }; - /** * @function module:path.getPointFromGrip * @param {module:math.XYObject} pt - * @param {module:path.Path} path + * @param {module:path.Path} pth * @returns {module:math.XYObject} */ - var getPointFromGrip = function getPointFromGrip(pt, path) { + + var getPointFromGrip = function getPointFromGrip(pt, pth) { var out = { x: pt.x, y: pt.y }; - if (path.matrix) { - pt = transformPoint(out.x, out.y, path.imatrix); + if (pth.matrix) { + pt = transformPoint(out.x, out.y, pth.imatrix); out.x = pt.x; out.y = pt.y; } @@ -4592,25 +5227,23 @@ var currentZoom = editorContext_.getCurrentZoom(); out.x /= currentZoom; out.y /= currentZoom; - return out; }; - /** * Requires prior call to `setUiStrings` if `xlink:title` - * to be set on the grip + * to be set on the grip. * @function module:path.addPointGrip * @param {Integer} index * @param {Integer} x * @param {Integer} y * @returns {SVGCircleElement} */ + var addPointGrip = function addPointGrip(index, x, y) { // create the container of all the point grips var pointGripContainer = getGripContainer(); + var pointGrip = getElem('pathpointgrip_' + index); // create it - var pointGrip = getElem('pathpointgrip_' + index); - // create it if (!pointGrip) { pointGrip = document.createElementNS(NS.SVG, 'circle'); var atts = { @@ -4623,13 +5256,14 @@ cursor: 'move', style: 'pointer-events:all' }; + if ('pathNodeTooltip' in uiStrings) { // May be empty if running path.js without svg-editor atts['xlink:title'] = uiStrings.pathNodeTooltip; } + assignAttributes(pointGrip, atts); pointGrip = pointGripContainer.appendChild(pointGrip); - var grip = $$1('#pathpointgrip_' + index); grip.dblclick(function () { if (path) { @@ -4637,6 +5271,7 @@ } }); } + if (x && y) { // set up the point grip element and display it assignAttributes(pointGrip, { @@ -4645,32 +5280,36 @@ display: 'inline' }); } + return pointGrip; }; - /** * @function module:path.getGripContainer * @returns {Element} */ + var getGripContainer = function getGripContainer() { var c = getElem('pathpointgrip_container'); + if (!c) { - var parent = getElem('selectorParentGroup'); - c = parent.appendChild(document.createElementNS(NS.SVG, 'g')); + var parentElement = getElem('selectorParentGroup'); + c = parentElement.appendChild(document.createElementNS(NS.SVG, 'g')); c.id = 'pathpointgrip_container'; } + return c; }; - /** * Requires prior call to `setUiStrings` if `xlink:title` - * to be set on the grip + * to be set on the grip. * @function module:path.addCtrlGrip * @param {string} id * @returns {SVGCircleElement} */ + var addCtrlGrip = function addCtrlGrip(id) { var pointGrip = getElem('ctrlpointgrip_' + id); + if (pointGrip) { return pointGrip; } @@ -4686,22 +5325,25 @@ cursor: 'move', style: 'pointer-events:all' }; + if ('pathCtrlPtTooltip' in uiStrings) { // May be empty if running path.js without svg-editor atts['xlink:title'] = uiStrings.pathCtrlPtTooltip; } + assignAttributes(pointGrip, atts); getGripContainer().append(pointGrip); return pointGrip; }; - /** * @function module:path.getCtrlLine * @param {string} id * @returns {SVGLineElement} */ + var getCtrlLine = function getCtrlLine(id) { var ctrlLine = getElem('ctrlLine_' + id); + if (ctrlLine) { return ctrlLine; } @@ -4716,16 +5358,15 @@ getGripContainer().append(ctrlLine); return ctrlLine; }; - /** * @function module:path.getPointGrip * @param {Segment} seg * @param {boolean} update * @returns {SVGCircleElement} */ + var getPointGrip = function getPointGrip(seg, update) { var index = seg.index; - var pointGrip = addPointGrip(index); if (update) { @@ -4739,12 +5380,12 @@ return pointGrip; }; - /** * @function module:path.getControlPoints * @param {Segment} seg * @returns {PlainObject.} */ + var getControlPoints = function getControlPoints(seg) { var item = seg.item, index = seg.index; @@ -4752,22 +5393,26 @@ if (!('x1' in item) || !('x2' in item)) { return null; } + var cpt = {}; - /* const pointGripContainer = */getGripContainer(); + /* const pointGripContainer = */ + + getGripContainer(); // Note that this is intentionally not seg.prev.item - // Note that this is intentionally not seg.prev.item var prev = path.segs[index - 1].item; - var segItems = [prev, item]; for (var i = 1; i < 3; i++) { var id = index + 'c' + i; - var ctrlLine = cpt['c' + i + '_line'] = getCtrlLine(id); - - var pt = getGripPt(seg, { x: item['x' + i], y: item['y' + i] }); - var gpt = getGripPt(seg, { x: segItems[i - 1].x, y: segItems[i - 1].y }); - + var pt = getGripPt(seg, { + x: item['x' + i], + y: item['y' + i] + }); + var gpt = getGripPt(seg, { + x: segItems[i - 1].x, + y: segItems[i - 1].y + }); assignAttributes(ctrlLine, { x1: pt.x, y1: pt.y, @@ -4775,12 +5420,9 @@ y2: gpt.y, display: 'inline' }); + cpt['c' + i + '_line'] = ctrlLine; // create it - cpt['c' + i + '_line'] = ctrlLine; - - // create it var pointGrip = cpt['c' + i] = addCtrlGrip(id); - assignAttributes(pointGrip, { cx: pt.x, cy: pt.y, @@ -4788,9 +5430,9 @@ }); cpt['c' + i] = pointGrip; } + return cpt; }; - /** * This replaces the segment at the given index. Type is given as number. * @function module:path.replacePathSeg @@ -4798,12 +5440,13 @@ * @param {Integer} index * @param {ArgumentsArray} pts * @param {SVGPathElement} elem + * @returns {undefined} */ + var replacePathSeg = function replacePathSeg(type, index, pts, elem) { var pth = elem || path.elem; - var func = 'createSVGPathSeg' + pathFuncs[type]; - var seg = pth[func].apply(pth, pts); + var seg = pth[func].apply(pth, _toConsumableArray(pts)); if (supportsPathReplaceItem()) { pth.pathSegList.replaceItem(seg, index); @@ -4811,11 +5454,14 @@ var segList = pth.pathSegList; var len = segList.numberOfItems; var arr = []; + for (var i = 0; i < len; i++) { var curSeg = segList.getItem(i); arr.push(curSeg); } + segList.clear(); + for (var _i2 = 0; _i2 < len; _i2++) { if (_i2 === index) { segList.appendItem(seg); @@ -4825,20 +5471,20 @@ } } }; - /** * @function module:path.getSegSelector * @param {Segment} seg * @param {boolean} update * @returns {SVGPathElement} */ + var getSegSelector = function getSegSelector(seg, update) { var index = seg.index; - var segLine = getElem('segline_' + index); + if (!segLine) { - var pointGripContainer = getGripContainer(); - // create segline + var pointGripContainer = getGripContainer(); // create segline + segLine = document.createElementNS(NS.SVG, 'path'); assignAttributes(segLine, { id: 'segline_' + index, @@ -4860,22 +5506,25 @@ return segLine; } - var pt = getGripPt(prev); - // Set start point - replacePathSeg(2, 0, [pt.x, pt.y], segLine); + var pt = getGripPt(prev); // Set start point + + replacePathSeg(2, 0, [pt.x, pt.y], segLine); + var pts = ptObjToArr(seg.type, seg.item); // , true); - var pts = ptObjToArr(seg.type, seg.item, true); for (var i = 0; i < pts.length; i += 2) { - var _pt = getGripPt(seg, { x: pts[i], y: pts[i + 1] }); - pts[i] = _pt.x; - pts[i + 1] = _pt.y; + var point = getGripPt(seg, { + x: pts[i], + y: pts[i + 1] + }); + pts[i] = point.x; + pts[i + 1] = point.y; } replacePathSeg(seg.type, 1, pts, segLine); } + return segLine; }; - /** * @typedef {PlainObject} Point * @property {Integer} x The x value @@ -4883,13 +5532,14 @@ */ /** - * Takes three points and creates a smoother line based on them + * Takes three points and creates a smoother line based on them. * @function module:path.smoothControlPoints * @param {Point} ct1 - Object with x and y values (first control point) * @param {Point} ct2 - Object with x and y values (second control point) * @param {Point} pt - Object with x and y values (third point) * @returns {Point[]} Array of two "smoothed" point objects */ + var smoothControlPoints = function smoothControlPoints(ct1, ct2, pt) { // each point must not be the origin var x1 = ct1.x - pt.x, @@ -4904,139 +5554,138 @@ nct2 = editorContext_.getSVGRoot().createSVGPoint(); var anglea = Math.atan2(y1, x1), angleb = Math.atan2(y2, x2); + if (anglea < 0) { anglea += 2 * Math.PI; } + if (angleb < 0) { angleb += 2 * Math.PI; } var angleBetween = Math.abs(anglea - angleb), angleDiff = Math.abs(Math.PI - angleBetween) / 2; + var newAnglea, newAngleb; - var newAnglea = void 0, - newAngleb = void 0; if (anglea - angleb > 0) { newAnglea = angleBetween < Math.PI ? anglea + angleDiff : anglea - angleDiff; newAngleb = angleBetween < Math.PI ? angleb - angleDiff : angleb + angleDiff; } else { newAnglea = angleBetween < Math.PI ? anglea - angleDiff : anglea + angleDiff; newAngleb = angleBetween < Math.PI ? angleb + angleDiff : angleb - angleDiff; - } + } // rotate the points + - // rotate the points nct1.x = r1 * Math.cos(newAnglea) + pt.x; nct1.y = r1 * Math.sin(newAnglea) + pt.y; nct2.x = r2 * Math.cos(newAngleb) + pt.x; nct2.y = r2 * Math.sin(newAngleb) + pt.y; - return [nct1, nct2]; } + return undefined; }; - /** * */ - var Segment = function () { + + var Segment = + /*#__PURE__*/ + function () { /** * @param {Integer} index * @param {SVGPathSeg} item * @todo Is `item` be more constrained here? */ function Segment(index, item) { - classCallCheck(this, Segment); + _classCallCheck(this, Segment); this.selected = false; this.index = index; this.item = item; this.type = item.pathSegType; - this.ctrlpts = []; this.ptgrip = null; this.segsel = null; } - /** * @param {boolean} y * @returns {undefined} */ - createClass(Segment, [{ - key: 'showCtrlPts', + _createClass(Segment, [{ + key: "showCtrlPts", value: function showCtrlPts(y) { for (var i in this.ctrlpts) { - if (this.ctrlpts.hasOwnProperty(i)) { + if ({}.hasOwnProperty.call(this.ctrlpts, i)) { this.ctrlpts[i].setAttribute('display', y ? 'inline' : 'none'); } } } - /** * @param {boolean} y * @returns {undefined} */ }, { - key: 'selectCtrls', + key: "selectCtrls", value: function selectCtrls(y) { $$1('#ctrlpointgrip_' + this.index + 'c1, #ctrlpointgrip_' + this.index + 'c2').attr('fill', y ? '#0FF' : '#EEE'); } - /** * @param {boolean} y * @returns {undefined} */ }, { - key: 'show', + key: "show", value: function show(y) { if (this.ptgrip) { this.ptgrip.setAttribute('display', y ? 'inline' : 'none'); - this.segsel.setAttribute('display', y ? 'inline' : 'none'); - // Show/hide all control points if available + this.segsel.setAttribute('display', y ? 'inline' : 'none'); // Show/hide all control points if available + this.showCtrlPts(y); } } - /** * @param {boolean} y * @returns {undefined} */ }, { - key: 'select', + key: "select", value: function select(y) { if (this.ptgrip) { this.ptgrip.setAttribute('stroke', y ? '#0FF' : '#00F'); this.segsel.setAttribute('display', y ? 'inline' : 'none'); + if (this.ctrlpts) { this.selectCtrls(y); } + this.selected = y; } } - /** * @returns {undefined} */ }, { - key: 'addGrip', + key: "addGrip", value: function addGrip() { this.ptgrip = getPointGrip(this, true); - this.ctrlpts = getControlPoints(this, true); + this.ctrlpts = getControlPoints(this); // , true); + this.segsel = getSegSelector(this, true); } - /** * @param {boolean} full * @returns {undefined} */ }, { - key: 'update', + key: "update", value: function update(full) { if (this.ptgrip) { var pt = getGripPt(this); @@ -5044,7 +5693,6 @@ cx: pt.x, cy: pt.y }); - getSegSelector(this, true); if (this.ctrlpts) { @@ -5052,12 +5700,12 @@ this.item = path.elem.pathSegList.getItem(this.index); this.type = this.item.pathSegType; } + getControlPoints(this); - } - // this.segsel.setAttribute('display', y ? 'inline' : 'none'); + } // this.segsel.setAttribute('display', y ? 'inline' : 'none'); + } } - /** * @param {Integer} dx * @param {Integer} dy @@ -5065,13 +5713,10 @@ */ }, { - key: 'move', + key: "move", value: function move(dx, dy) { var item = this.item; - - var curPts = this.ctrlpts ? [item.x += dx, item.y += dy, item.x1, item.y1, item.x2 += dx, item.y2 += dy] : [item.x += dx, item.y += dy]; - replacePathSeg(this.type, this.index, curPts); if (this.next && this.next.ctrlpts) { @@ -5083,58 +5728,55 @@ if (this.mate) { // The last point of a closed subpath has a 'mate', // which is the 'M' segment of the subpath - var _item = this.mate.item; - - var pts = [_item.x += dx, _item.y += dy]; - replacePathSeg(this.mate.type, this.mate.index, pts); - // Has no grip, so does not need 'updating'? + var itm = this.mate.item; + var pts = [itm.x += dx, itm.y += dy]; + replacePathSeg(this.mate.type, this.mate.index, pts); // Has no grip, so does not need 'updating'? } this.update(true); + if (this.next) { this.next.update(true); } } - /** * @param {Integer} num * @returns {undefined} */ }, { - key: 'setLinked', + key: "setLinked", value: function setLinked(num) { - var seg = void 0, - anum = void 0, - pt = void 0; + var seg, anum, pt; + if (num === 2) { anum = 1; seg = this.next; + if (!seg) { return; } + pt = this.item; } else { anum = 2; seg = this.prev; + if (!seg) { return; } + pt = seg.item; } var _seg = seg, item = _seg.item; - item['x' + anum] = pt.x + (pt.x - this.item['x' + num]); item['y' + anum] = pt.y + (pt.y - this.item['y' + num]); - var pts = [item.x, item.y, item.x1, item.y1, item.x2, item.y2]; - replacePathSeg(seg.type, seg.index, pts); seg.update(true); } - /** * @param {Integer} num * @param {Integer} dx @@ -5143,26 +5785,23 @@ */ }, { - key: 'moveCtrl', + key: "moveCtrl", value: function moveCtrl(num, dx, dy) { var item = this.item; - item['x' + num] += dx; item['y' + num] += dy; - var pts = [item.x, item.y, item.x1, item.y1, item.x2, item.y2]; - replacePathSeg(this.type, this.index, pts); this.update(true); } - /** * @param {Integer} newType Possible values set during {@link module:path.init} * @param {ArgumentsArray} pts + * @returns {undefined} */ }, { - key: 'setType', + key: "setType", value: function setType(newType, pts) { replacePathSeg(newType, this.index, pts); this.type = newType; @@ -5172,19 +5811,22 @@ this.update(true); } }]); + return Segment; }(); - /** * */ - var Path = function () { + + var Path = + /*#__PURE__*/ + function () { /** - * @param {SVGPathElement} + * @param {SVGPathElement} elem * @throws {Error} If constructed without a path element */ function Path(elem) { - classCallCheck(this, Path); + _classCallCheck(this, Path); if (!elem || elem.tagName !== 'path') { throw new Error('svgedit.path.Path constructed without a element'); @@ -5193,34 +5835,30 @@ this.elem = elem; this.segs = []; this.selected_pts = []; - path = this; + path = this; // eslint-disable-line consistent-this this.init(); } - /** - * Reset path data + * Reset path data. * @returns {module:path.Path} */ - createClass(Path, [{ - key: 'init', - value: function init$$1() { + _createClass(Path, [{ + key: "init", + value: function init() { // Hide all grips, etc - // fixed, needed to work on all found elements, not just first $$1(getGripContainer()).find('*').each(function () { $$1(this).attr('display', 'none'); }); - var segList = this.elem.pathSegList; var len = segList.numberOfItems; this.segs = []; this.selected_pts = []; - this.first_seg = null; + this.first_seg = null; // Set up segs array - // Set up segs array for (var i = 0; i < len; i++) { var item = segList.getItem(i); var segment = new Segment(i, item); @@ -5229,13 +5867,13 @@ } var segs = this.segs; - - var startI = null; + for (var _i3 = 0; _i3 < len; _i3++) { var seg = segs[_i3]; var nextSeg = _i3 + 1 >= len ? null : segs[_i3 + 1]; var prevSeg = _i3 - 1 < 0 ? null : segs[_i3 - 1]; + if (seg.type === 2) { if (prevSeg && prevSeg.type !== 1) { // New sub-path, last one is open, @@ -5244,19 +5882,20 @@ startSeg.next = segs[startI + 1]; startSeg.next.prev = startSeg; startSeg.addGrip(); - } - // Remember that this is a starter seg + } // Remember that this is a starter seg + + startI = _i3; } else if (nextSeg && nextSeg.type === 1) { // This is the last real segment of a closed sub-path // Next is first seg after "M" - seg.next = segs[startI + 1]; + seg.next = segs[startI + 1]; // First seg after "M"'s prev is this - // First seg after "M"'s prev is this seg.next.prev = seg; seg.mate = segs[startI]; seg.addGrip(); - if (this.first_seg == null) { + + if (isNullish(this.first_seg)) { this.first_seg = seg; } } else if (!nextSeg) { @@ -5266,7 +5905,9 @@ var _startSeg = segs[startI]; _startSeg.next = segs[startI + 1]; _startSeg.next.prev = _startSeg; + _startSeg.addGrip(); + seg.addGrip(); if (!this.first_seg) { @@ -5276,60 +5917,60 @@ } } else if (seg.type !== 1) { // Regular segment, so add grip and its "next" - seg.addGrip(); + seg.addGrip(); // Don't set its "next" if it's an "M" - // Don't set its "next" if it's an "M" if (nextSeg && nextSeg.type !== 2) { seg.next = nextSeg; seg.next.prev = seg; } } } + return this; } - /** * @callback module:path.PathEachSegCallback * @this module:path.Segment * @param {Integer} i The index of the seg being iterated - * @returns {boolean} Will stop execution of `eachSeg` if returns `false` + * @returns {boolean|undefined} Will stop execution of `eachSeg` if returns `false` */ + /** * @param {module:path.PathEachSegCallback} fn * @returns {undefined} */ }, { - key: 'eachSeg', + key: "eachSeg", value: function eachSeg(fn) { var len = this.segs.length; + for (var i = 0; i < len; i++) { var ret = fn.call(this.segs[i], i); + if (ret === false) { break; } } } - /** * @param {Integer} index * @returns {undefined} */ }, { - key: 'addSeg', + key: "addSeg", value: function addSeg(index) { // Adds a new segment var seg = this.segs[index]; + if (!seg.prev) { return; } var prev = seg.prev; + var newseg, newX, newY; - var newseg = void 0, - newX = void 0, - newY = void 0; switch (seg.item.pathSegType) { case 4: { @@ -5337,7 +5978,9 @@ newY = (seg.item.y + prev.item.y) / 2; newseg = this.elem.createSVGPathSegLinetoAbs(newX, newY); break; - }case 6: + } + + case 6: { // make it a curved segment to preserve the shape (WRS) // https://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm#Geometric_interpretation @@ -5362,91 +6005,59 @@ insertItemBefore(this.elem, newseg, index); } - /** * @param {Integer} index * @returns {undefined} */ }, { - key: 'deleteSeg', + key: "deleteSeg", value: function deleteSeg(index) { var seg = this.segs[index]; var list = this.elem.pathSegList; - seg.show(false); var next = seg.next; if (seg.mate) { // Make the next point be the "M" point var pt = [next.item.x, next.item.y]; - replacePathSeg(2, next.index, pt); + replacePathSeg(2, next.index, pt); // Reposition last node - // Reposition last node replacePathSeg(4, seg.index, pt); - list.removeItem(seg.mate.index); } else if (!seg.prev) { // First node of open path, make next point the M // const {item} = seg; - var _pt2 = [next.item.x, next.item.y]; - replacePathSeg(2, seg.next.index, _pt2); + var _pt = [next.item.x, next.item.y]; + replacePathSeg(2, seg.next.index, _pt); list.removeItem(index); } else { list.removeItem(index); } } - - /** - * @param {Integer} index - * @returns {boolean} - */ - - }, { - key: 'subpathIsClosed', - value: function subpathIsClosed(index) { - var closed = false; - // Check if subpath is already open - path.eachSeg(function (i) { - if (i <= index) { - return true; - } - if (this.type === 2) { - // Found M first, so open - return false; - } - if (this.type === 1) { - // Found Z first, so closed - closed = true; - return false; - } - }); - - return closed; - } - /** * @param {Integer} index * @returns {undefined} */ }, { - key: 'removePtFromSelection', + key: "removePtFromSelection", value: function removePtFromSelection(index) { var pos = this.selected_pts.indexOf(index); + if (pos === -1) { return; } + this.segs[index].select(false); this.selected_pts.splice(pos, 1); } - /** * @returns {undefined} */ }, { - key: 'clearSelection', + key: "clearSelection", value: function clearSelection() { this.eachSeg(function () { // 'this' is the segment here @@ -5454,53 +6065,52 @@ }); this.selected_pts = []; } - /** * @returns {undefined} */ }, { - key: 'storeD', + key: "storeD", value: function storeD() { this.last_d = this.elem.getAttribute('d'); } - /** * @param {Integer} y * @returns {undefined} */ }, { - key: 'show', + key: "show", value: function show(y) { // Shows this path's segment grips this.eachSeg(function () { // 'this' is the segment here this.show(y); }); + if (y) { this.selectPt(this.first_seg.index); } + return this; } - /** - * Move selected points + * Move selected points. * @param {Integer} dx * @param {Integer} dy * @returns {undefined} */ }, { - key: 'movePts', + key: "movePts", value: function movePts(dx, dy) { var i = this.selected_pts.length; + while (i--) { var seg = this.segs[this.selected_pts[i]]; seg.move(dx, dy); } } - /** * @param {Integer} dx * @param {Integer} dy @@ -5508,30 +6118,30 @@ */ }, { - key: 'moveCtrl', + key: "moveCtrl", value: function moveCtrl(dx, dy) { var seg = this.segs[this.selected_pts[0]]; seg.moveCtrl(this.dragctrl, dx, dy); + if (linkControlPts) { seg.setLinked(this.dragctrl); } } - /** * @param {?Integer} newType See {@link https://www.w3.org/TR/SVG/single-page.html#paths-InterfaceSVGPathSeg} * @returns {undefined} */ }, { - key: 'setSegType', + key: "setSegType", value: function setSegType(newType) { this.storeD(); var i = this.selected_pts.length; - var text = void 0; - while (i--) { - var selPt = this.selected_pts[i]; + var text; + + while (i--) { + var selPt = this.selected_pts[i]; // Selected seg - // Selected seg var cur = this.segs[selPt]; var prev = cur.prev; @@ -5541,21 +6151,19 @@ if (!newType) { // double-click, so just toggle - text = 'Toggle Path Segment Type'; + text = 'Toggle Path Segment Type'; // Toggle segment to curve/straight line - // Toggle segment to curve/straight line var oldType = cur.type; - newType = oldType === 6 ? 4 : 6; } newType = Number(newType); - var curX = cur.item.x; var curY = cur.item.y; var prevX = prev.item.x; var prevY = prev.item.y; var points = void 0; + switch (newType) { case 6: { @@ -5564,8 +6172,8 @@ points = [curX, curY, old.x1, old.y1, old.x2, old.y2]; } else { var diffX = curX - prevX; - var diffY = curY - prevY; - // get control points from straight line segment + var diffY = curY - prevY; // get control points from straight line segment + /* const ct1x = (prevX + (diffY/2)); const ct1y = (prevY - (diffX/2)); @@ -5573,18 +6181,21 @@ const ct2y = (curY - (diffX/2)); */ // create control points on the line to preserve the shape (WRS) + var ct1x = prevX + diffX / 3; var ct1y = prevY + diffY / 3; var ct2x = curX - diffX / 3; var ct2y = curY - diffY / 3; points = [curX, curY, ct1x, ct1y, ct2x, ct2y]; } - break; - }case 4: - { - points = [curX, curY]; - // Store original prevve segment nums + break; + } + + case 4: + { + points = [curX, curY]; // Store original prevve segment nums + cur.olditem = cur.item; break; } @@ -5592,9 +6203,9 @@ cur.setType(newType, points); } + path.endChanges(text); } - /** * @param {Integer} pt * @param {Integer} ctrlNum @@ -5602,10 +6213,11 @@ */ }, { - key: 'selectPt', + key: "selectPt", value: function selectPt(pt, ctrlNum) { this.clearSelection(); - if (pt == null) { + + if (isNullish(pt)) { this.eachSeg(function (i) { // 'this' is the segment here. if (this.prev) { @@ -5613,7 +6225,9 @@ } }); } + this.addPtsToSelection(pt); + if (ctrlNum) { this.dragctrl = ctrlNum; @@ -5622,14 +6236,13 @@ } } } - /** - * Update position of all points + * Update position of all points. * @returns {Path} */ }, { - key: 'update', + key: "update", value: function update() { var elem = this.elem; @@ -5645,119 +6258,152 @@ this.item = elem.pathSegList.getItem(i); this.update(); }); - return this; } - /** * @param {string} text * @returns {undefined} */ }, { - key: 'endChanges', + key: "endChanges", value: function endChanges(text) { if (isWebkit()) { editorContext_.resetD(this.elem); } - var cmd = new ChangeElementCommand(this.elem, { d: this.last_d }, text); - editorContext_.endChanges({ cmd: cmd, elem: this.elem }); - } + var cmd = new ChangeElementCommand(this.elem, { + d: this.last_d + }, text); + editorContext_.endChanges({ + cmd: cmd, + elem: this.elem + }); + } /** * @param {Integer|Integer[]} indexes * @returns {undefined} */ }, { - key: 'addPtsToSelection', + key: "addPtsToSelection", value: function addPtsToSelection(indexes) { if (!Array.isArray(indexes)) { indexes = [indexes]; } + for (var _i4 = 0; _i4 < indexes.length; _i4++) { var index = indexes[_i4]; var seg = this.segs[index]; + if (seg.ptgrip) { if (!this.selected_pts.includes(index) && index >= 0) { this.selected_pts.push(index); } } } + this.selected_pts.sort(); var i = this.selected_pts.length; var grips = []; - grips.length = i; - // Loop through points to be selected and highlight each + grips.length = i; // Loop through points to be selected and highlight each + while (i--) { var pt = this.selected_pts[i]; var _seg2 = this.segs[pt]; + _seg2.select(true); + grips[i] = _seg2.ptgrip; } - var closedSubpath = this.subpathIsClosed(this.selected_pts[0]); - editorContext_.addPtsToSelection({ grips: grips, closedSubpath: closedSubpath }); + var closedSubpath = Path.subpathIsClosed(this.selected_pts[0]); + editorContext_.addPtsToSelection({ + grips: grips, + closedSubpath: closedSubpath + }); } }]); + return Path; }(); + /** + * @param {Integer} index + * @returns {boolean} + */ + Path.subpathIsClosed = function (index) { + var clsd = false; // Check if subpath is already open + + path.eachSeg(function (i) { + if (i <= index) { + return true; + } + + if (this.type === 2) { + // Found M first, so open + return false; + } + + if (this.type === 1) { + // Found Z first, so closed + clsd = true; + return false; + } + + return true; + }); + return clsd; + }; /** * @function module:path.getPath_ * @param {SVGPathElement} elem * @returns {module:path.Path} */ + + var getPath_ = function getPath_(elem) { var p = pathData[elem.id]; + if (!p) { p = pathData[elem.id] = new Path(elem); } + return p; }; - /** * @function module:path.removePath_ * @param {string} id * @returns {undefined} */ + var removePath_ = function removePath_(id) { if (id in pathData) { delete pathData[id]; } }; - - var newcx = void 0, - newcy = void 0, - oldcx = void 0, - oldcy = void 0, - angle = void 0; + var newcx, newcy, oldcx, oldcy, angle; var getRotVals = function getRotVals(x, y) { var dx = x - oldcx; - var dy = y - oldcy; + var dy = y - oldcy; // rotate the point around the old center - // rotate the point around the old center var r = Math.sqrt(dx * dx + dy * dy); var theta = Math.atan2(dy, dx) + angle; dx = r * Math.cos(theta) + oldcx; - dy = r * Math.sin(theta) + oldcy; - - // dx,dy should now hold the actual coordinates of each + dy = r * Math.sin(theta) + oldcy; // dx,dy should now hold the actual coordinates of each // point after being rotated - // now we want to rotate them around the new center in the reverse direction + dx -= newcx; dy -= newcy; - r = Math.sqrt(dx * dx + dy * dy); theta = Math.atan2(dy, dx) - angle; - - return { x: r * Math.cos(theta) + newcx, - y: r * Math.sin(theta) + newcy }; - }; - - // If the path was rotated, we must now pay the piper: + return { + x: r * Math.cos(theta) + newcx, + y: r * Math.sin(theta) + newcy + }; + }; // If the path was rotated, we must now pay the piper: // Every path point must be rotated into the rotated coordinate system of // its old center, then determine the new center, then rotate it back // This is because we want the path to remember its rotation @@ -5768,113 +6414,116 @@ * be optimized or even taken care of by `recalculateDimensions` * @returns {undefined} */ + + var recalcRotatedPath = function recalcRotatedPath() { var currentPath = path.elem; angle = getRotationAngle(currentPath, true); + if (!angle) { return; - } - // selectedBBoxes[0] = path.oldbbox; + } // selectedBBoxes[0] = path.oldbbox; + + var oldbox = path.oldbbox; // selectedBBoxes[0], + oldcx = oldbox.x + oldbox.width / 2; oldcy = oldbox.y + oldbox.height / 2; var box = getBBox(currentPath); newcx = box.x + box.width / 2; - newcy = box.y + box.height / 2; + newcy = box.y + box.height / 2; // un-rotate the new center to the proper position - // un-rotate the new center to the proper position var dx = newcx - oldcx, dy = newcy - oldcy, r = Math.sqrt(dx * dx + dy * dy), theta = Math.atan2(dy, dx) + angle; - newcx = r * Math.cos(theta) + oldcx; newcy = r * Math.sin(theta) + oldcy; - var list = currentPath.pathSegList; - var i = list.numberOfItems; + while (i) { i -= 1; var seg = list.getItem(i), type = seg.pathSegType; + if (type === 1) { continue; } var rvals = getRotVals(seg.x, seg.y), points = [rvals.x, rvals.y]; - if (seg.x1 != null && seg.x2 != null) { + + if (!isNullish(seg.x1) && !isNullish(seg.x2)) { var cVals1 = getRotVals(seg.x1, seg.y1); var cVals2 = getRotVals(seg.x2, seg.y2); points.splice(points.length, 0, cVals1.x, cVals1.y, cVals2.x, cVals2.y); } + replacePathSeg(type, i, points); } // loop for each point - box = getBBox(currentPath); - // selectedBBoxes[0].x = box.x; selectedBBoxes[0].y = box.y; - // selectedBBoxes[0].width = box.width; selectedBBoxes[0].height = box.height; + /* box = */ + + getBBox(currentPath); // selectedBBoxes[0].x = box.x; selectedBBoxes[0].y = box.y; + // selectedBBoxes[0].width = box.width; selectedBBoxes[0].height = box.height; // now we must set the new transform to be rotated around the new center + var Rnc = editorContext_.getSVGRoot().createSVGTransform(), tlist = getTransformList(currentPath); Rnc.setRotate(angle * 180.0 / Math.PI, newcx, newcy); tlist.replaceItem(Rnc, 0); - }; - - // ==================================== + }; // ==================================== // Public API starts here /** * @function module:path.clearData * @returns {undefined} */ + var clearData = function clearData() { pathData = {}; - }; + }; // Making public for mocking - // Making public for mocking /** * @function module:path.reorientGrads * @param {Element} elem * @param {SVGMatrix} m * @returns {undefined} */ + var reorientGrads = function reorientGrads(elem, m) { var bb = getBBox(elem); + for (var i = 0; i < 2; i++) { var type = i === 0 ? 'fill' : 'stroke'; var attrVal = elem.getAttribute(type); + if (attrVal && attrVal.startsWith('url(')) { var grad = getRefElem(attrVal); + if (grad.tagName === 'linearGradient') { var x1 = grad.getAttribute('x1') || 0; var y1 = grad.getAttribute('y1') || 0; var x2 = grad.getAttribute('x2') || 1; - var y2 = grad.getAttribute('y2') || 0; + var y2 = grad.getAttribute('y2') || 0; // Convert to USOU points - // Convert to USOU points x1 = bb.width * x1 + bb.x; y1 = bb.height * y1 + bb.y; x2 = bb.width * x2 + bb.x; - y2 = bb.height * y2 + bb.y; + y2 = bb.height * y2 + bb.y; // Transform those points - // Transform those points var pt1 = transformPoint(x1, y1, m); - var pt2 = transformPoint(x2, y2, m); + var pt2 = transformPoint(x2, y2, m); // Convert back to BB points - // Convert back to BB points var gCoords = {}; - gCoords.x1 = (pt1.x - bb.x) / bb.width; gCoords.y1 = (pt1.y - bb.y) / bb.height; gCoords.x2 = (pt2.x - bb.x) / bb.width; gCoords.y2 = (pt2.y - bb.y) / bb.height; - var newgrad = grad.cloneNode(true); $$1(newgrad).attr(gCoords); - newgrad.id = editorContext_.getNextId(); findDefs().append(newgrad); elem.setAttribute(type, 'url(#' + newgrad.id + ')'); @@ -5882,40 +6531,39 @@ } } }; - /** * This is how we map paths to our preferred relative segment types * @name module:path.pathMap * @type {GenericArray} */ - var pathMap = [0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a', 'H', 'h', 'V', 'v', 'S', 's', 'T', 't']; + var pathMap = [0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a', 'H', 'h', 'V', 'v', 'S', 's', 'T', 't']; /** - * Convert a path to one with only absolute or relative values + * Convert a path to one with only absolute or relative values. * @todo move to pathActions.js * @function module:path.convertPath - * @param {SVGPathElement} path - the path to convert + * @param {SVGPathElement} pth - the path to convert * @param {boolean} toRel - true of convert to relative * @returns {string} */ - var convertPath = function convertPath(path, toRel) { - var segList = path.pathSegList; - var len = segList.numberOfItems; + + var convertPath = function convertPath(pth, toRel) { + var pathSegList = pth.pathSegList; + var len = pathSegList.numberOfItems; var curx = 0, cury = 0; var d = ''; var lastM = null; for (var i = 0; i < len; ++i) { - var seg = segList.getItem(i); - // if these properties are not in the segment, set them to zero + var seg = pathSegList.getItem(i); // if these properties are not in the segment, set them to zero + var x = seg.x || 0, y = seg.y || 0, x1 = seg.x1 || 0, y1 = seg.y1 || 0, x2 = seg.x2 || 0, y2 = seg.y2 || 0; - var type = seg.pathSegType; var letter = pathMap[type]['to' + (toRel ? 'Lower' : 'Upper') + 'Case'](); @@ -5923,15 +6571,19 @@ case 1: // z,Z closepath (Z/z) d += 'z'; + if (lastM && !toRel) { curx = lastM[0]; cury = lastM[1]; } + break; + case 12: // absolute horizontal line (H) x -= curx; // Fallthrough + case 13: // relative horizontal line (h) if (toRel) { @@ -5941,14 +6593,17 @@ x += curx; curx = x; letter = 'L'; - } - // Convert to "line" for easier editing + } // Convert to "line" for easier editing + + d += pathDSegment(letter, [[x, cury]]); break; + case 14: // absolute vertical line (V) y -= cury; // Fallthrough + case 15: // relative vertical line (v) if (toRel) { @@ -5958,19 +6613,26 @@ y += cury; cury = y; letter = 'L'; - } - // Convert to "line" for easier editing + } // Convert to "line" for easier editing + + d += pathDSegment(letter, [[curx, y]]); break; + case 2: // absolute move (M) + case 4: // absolute line (L) + case 18: // absolute smooth quad (T) x -= curx; y -= cury; // Fallthrough + case 5: // relative line (l) + case 3: // relative move (m) + case 19: // relative smooth quad (t) if (toRel) { @@ -5982,53 +6644,74 @@ curx = x; cury = y; } + if (type === 2 || type === 3) { lastM = [curx, cury]; } d += pathDSegment(letter, [[x, y]]); break; + case 6: // absolute cubic (C) - x -= curx;x1 -= curx;x2 -= curx; - y -= cury;y1 -= cury;y2 -= cury; + x -= curx; + x1 -= curx; + x2 -= curx; + y -= cury; + y1 -= cury; + y2 -= cury; // Fallthrough + case 7: // relative cubic (c) if (toRel) { curx += x; cury += y; } else { - x += curx;x1 += curx;x2 += curx; - y += cury;y1 += cury;y2 += cury; + x += curx; + x1 += curx; + x2 += curx; + y += cury; + y1 += cury; + y2 += cury; curx = x; cury = y; } + d += pathDSegment(letter, [[x1, y1], [x2, y2], [x, y]]); break; + case 8: // absolute quad (Q) - x -= curx;x1 -= curx; - y -= cury;y1 -= cury; + x -= curx; + x1 -= curx; + y -= cury; + y1 -= cury; // Fallthrough + case 9: // relative quad (q) if (toRel) { curx += x; cury += y; } else { - x += curx;x1 += curx; - y += cury;y1 += cury; + x += curx; + x1 += curx; + y += cury; + y1 += cury; curx = x; cury = y; } + d += pathDSegment(letter, [[x1, y1], [x, y]]); break; + case 10: // absolute elliptical arc (A) x -= curx; y -= cury; // Fallthrough + case 11: // relative elliptical arc (a) if (toRel) { @@ -6040,84 +6723,97 @@ curx = x; cury = y; } + d += pathDSegment(letter, [[seg.r1, seg.r2]], [seg.angle, seg.largeArcFlag ? 1 : 0, seg.sweepFlag ? 1 : 0], [x, y]); break; + case 16: // absolute smooth cubic (S) - x -= curx;x2 -= curx; - y -= cury;y2 -= cury; + x -= curx; + x2 -= curx; + y -= cury; + y2 -= cury; // Fallthrough + case 17: // relative smooth cubic (s) if (toRel) { curx += x; cury += y; } else { - x += curx;x2 += curx; - y += cury;y2 += cury; + x += curx; + x2 += curx; + y += cury; + y2 += cury; curx = x; cury = y; } + d += pathDSegment(letter, [[x2, y2], [x, y]]); break; } // switch on path segment type + } // for each segment + + return d; }; - /** - * TODO: refactor callers in convertPath to use getPathDFromSegments instead of this function. - * Legacy code refactored from svgcanvas.pathActions.convertPath + * TODO: refactor callers in `convertPath` to use `getPathDFromSegments` instead of this function. + * Legacy code refactored from `svgcanvas.pathActions.convertPath`. * @param {string} letter - path segment command (letter in potentially either case from {@link module:path.pathMap}; see [SVGPathSeg#pathSegTypeAsLetter]{@link https://www.w3.org/TR/SVG/single-page.html#paths-__svg__SVGPathSeg__pathSegTypeAsLetter}) - * @param {Integer[][]} points - x,y points - * @param {Integer[][]} [morePoints] - x,y points + * @param {GenericArray>} points - x,y points + * @param {GenericArray>} [morePoints] - x,y points * @param {Integer[]} [lastPoint] - x,y point * @returns {string} */ + function pathDSegment(letter, points, morePoints, lastPoint) { $$1.each(points, function (i, pnt) { points[i] = shortFloat(pnt); }); var segment = letter + points.join(' '); + if (morePoints) { segment += ' ' + morePoints.join(' '); } + if (lastPoint) { segment += ' ' + shortFloat(lastPoint); } + return segment; } - /** * Group: Path edit functions * Functions relating to editing path elements * @namespace {PlainObject} pathActions * @memberof module:path */ + + var pathActions = function () { var subpath = false; - var newPoint = void 0, - firstCtrl = void 0; - + var newPoint, firstCtrl; var currentPath = null; - var hasMoved = false; - // No `editorContext_` yet but should be ok as is `null` by default + var hasMoved = false; // No `editorContext_` yet but should be ok as is `null` by default // editorContext_.setDrawnPath(null); /** * This function converts a polyline (created by the fh_path tool) into * a path element and coverts every three line segments into a single bezier - * curve in an attempt to smooth out the free-hand + * curve in an attempt to smooth out the free-hand. * @function smoothPolylineIntoPath * @param {Element} element * @returns {Element} */ + var smoothPolylineIntoPath = function smoothPolylineIntoPath(element) { - var i = void 0; + var i; var _element = element, points = _element.points; - var N = points.numberOfItems; + if (N >= 4) { // loop through every 3 points and convert to a cubic bezier curve segment // @@ -6136,15 +6832,16 @@ prevCtlPt = null; var d = []; d.push(['M', curpos.x, ',', curpos.y, ' C'].join('')); + for (i = 1; i <= N - 4; i += 3) { var ct1 = points.getItem(i); var ct2 = points.getItem(i + 1); - var end = points.getItem(i + 2); - - // if the previous segment had a control point, we want to smooth out + var end = points.getItem(i + 2); // if the previous segment had a control point, we want to smooth out // the control points on both sides + if (prevCtlPt) { var newpts = smoothControlPoints(prevCtlPt, ct1, curpos); + if (newpts && newpts.length === 2) { var prevArr = d[d.length - 1].split(','); prevArr[2] = newpts[0].x; @@ -6155,20 +6852,21 @@ } d.push([ct1.x, ct1.y, ct2.x, ct2.y, end.x, end.y].join(',')); - curpos = end; prevCtlPt = ct2; - } - // handle remaining line segments + } // handle remaining line segments + + d.push('L'); + while (i < N) { var pt = points.getItem(i); d.push([pt.x, pt.y].join(',')); i++; } - d = d.join(' '); - // create new path element + d = d.join(' '); // create new path element + element = editorContext_.addSVGElementFromJson({ element: 'path', curStyles: true, @@ -6177,24 +6875,28 @@ d: d, fill: 'none' } - }); - // No need to call "changed", as this is already done under mouseUp + }); // No need to call "changed", as this is already done under mouseUp } + return element; }; - return (/** @lends module:path.pathActions */{ + return ( + /** @lends module:path.pathActions */ + { /** * @param {MouseEvent} evt * @param {Element} mouseTarget * @param {Float} startX * @param {Float} startY - * @returns {undefined} + * @returns {boolean|undefined} */ mouseDown: function mouseDown(evt, mouseTarget, startX, startY) { - var id = void 0; + var id; + if (editorContext_.getCurrentMode() === 'path') { var mouseX = startX; // Was this meant to work with the other `mouseX`? (was defined globally so adding `let` to at least avoid a global) + var mouseY = startY; // Was this meant to work with the other `mouseY`? (was defined globally so adding `let` to at least avoid a global) var currentZoom = editorContext_.getCurrentZoom(); @@ -6220,15 +6922,19 @@ }); stretchy = getElem('selectorParentGroup').appendChild(stretchy); } - stretchy.setAttribute('display', 'inline'); + stretchy.setAttribute('display', 'inline'); var keep = null; - var index = void 0; - // if pts array is empty, create path element with M at current point + var index; // if pts array is empty, create path element with M at current point + var drawnPath = editorContext_.getDrawnPath(); + if (!drawnPath) { var dAttr = 'M' + x + ',' + y + ' '; // Was this meant to work with the other `dAttr`? (was defined globally so adding `var` to at least avoid a global) - drawnPath = editorContext_.setDrawnPath(editorContext_.addSVGElementFromJson({ + + /* drawnPath = */ + + editorContext_.setDrawnPath(editorContext_.addSVGElementFromJson({ element: 'path', curStyles: true, attr: { @@ -6236,8 +6942,8 @@ id: editorContext_.getNextId(), opacity: editorContext_.getOpacity() / 2 } - })); - // set stretchy line to first point + })); // set stretchy line to first point + stretchy.setAttribute('d', ['M', mouseX, mouseY, mouseX, mouseY].join(' ')); index = subpath ? path.segs.length : 0; addPointGrip(index, mouseX, mouseY); @@ -6247,30 +6953,29 @@ var i = seglist.numberOfItems; var FUZZ = 6 / currentZoom; var clickOnPoint = false; + while (i) { i--; var item = seglist.getItem(i); var px = item.x, - py = item.y; - // found a matching point + py = item.y; // found a matching point + if (x >= px - FUZZ && x <= px + FUZZ && y >= py - FUZZ && y <= py + FUZZ) { clickOnPoint = true; break; } - } + } // get path element that we are in the process of creating - // get path element that we are in the process of creating - id = editorContext_.getId(); - // Remove previous path object if previously created + id = editorContext_.getId(); // Remove previous path object if previously created + removePath_(id); - var newpath = getElem(id); - var newseg = void 0; - var sSeg = void 0; - var len = seglist.numberOfItems; - // if we clicked on an existing point, then we are done this path, commit it + var newseg; + var sSeg; + var len = seglist.numberOfItems; // if we clicked on an existing point, then we are done this path, commit it // (i, i+1) are the x,y that were clicked on + if (clickOnPoint) { // if clicked on any other point but the first OR // the first point was clicked on and there are less than 3 points @@ -6280,8 +6985,8 @@ // Create end segment var absX = seglist.getItem(0).x; var absY = seglist.getItem(0).y; - sSeg = stretchy.pathSegList.getItem(1); + if (sSeg.pathSegType === 4) { newseg = drawnPath.createSVGPathSegLinetoAbs(absX, absY); } else { @@ -6295,11 +7000,13 @@ keep = false; return keep; } - $$1(stretchy).remove(); - // This will signal to commit the path + $$1(stretchy).remove(); // This will signal to commit the path // const element = newpath; // Other event handlers define own `element`, so this was probably not meant to interact with them or one which shares state (as there were none); I therefore adding a missing `var` to avoid a global - drawnPath = editorContext_.setDrawnPath(null); + + /* drawnPath = */ + + editorContext_.setDrawnPath(null); editorContext_.setStarted(false); if (subpath) { @@ -6311,20 +7018,22 @@ var origD = $$1(path.elem).attr('d'); $$1(path.elem).attr('d', origD + newD); $$1(newpath).remove(); + if (path.matrix) { recalcRotatedPath(); } + init$1(); pathActions.toEditMode(path.elem); path.selectPt(); return false; - } - // else, create a new point, update path element + } // else, create a new point, update path element + } else { // Checks if current target or parents are #svgcontent if (!$$1.contains(editorContext_.getContainer(), editorContext_.getMouseTarget(evt))) { // Clicked outside canvas, so don't make point - console.log('Clicked outside canvas'); + // console.log('Clicked outside canvas'); return false; } @@ -6337,10 +7046,11 @@ var xya = snapToAngle(lastx, lasty, x, y); x = xya.x; y = xya.y; - } + } // Use the segment defined by stretchy + - // Use the segment defined by stretchy sSeg = stretchy.pathSegList.getItem(1); + if (sSeg.pathSegType === 4) { newseg = drawnPath.createSVGPathSegLinetoAbs(editorContext_.round(x), editorContext_.round(y)); } else { @@ -6348,46 +7058,45 @@ } drawnPath.pathSegList.appendItem(newseg); - x *= currentZoom; - y *= currentZoom; + y *= currentZoom; // set stretchy line to latest point - // set stretchy line to latest point stretchy.setAttribute('d', ['M', x, y, x, y].join(' ')); index = num; + if (subpath) { index += path.segs.length; } + addPointGrip(index, x, y); - } - // 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; + return undefined; } path.storeD(); - id = evt.target.id; + var curPt; - var curPt = void 0; if (id.substr(0, 14) === 'pathpointgrip_') { // Select this point - curPt = path.cur_pt = parseInt(id.substr(14), 10); + curPt = path.cur_pt = parseInt(id.substr(14)); path.dragging = [startX, startY]; - var seg = path.segs[curPt]; - - // only clear selection if shift is not pressed (otherwise, add + var seg = path.segs[curPt]; // only clear selection if shift is not pressed (otherwise, add // node to selection) + if (!evt.shiftKey) { if (path.selected_pts.length <= 1 || !seg.selected) { path.clearSelection(); } + path.addPtsToSelection(curPt); } else if (seg.selected) { path.removePtFromSelection(curPt); @@ -6396,20 +7105,22 @@ } } else if (id.startsWith('ctrlpointgrip_')) { path.dragging = [startX, startY]; - var parts = id.split('_')[1].split('c'); curPt = Number(parts[0]); var ctrlNum = Number(parts[1]); path.selectPt(curPt, ctrlNum); - } + } // Start selection box + - // Start selection box if (!path.dragging) { var rubberBox = editorContext_.getRubberBox(); - if (rubberBox == null) { + + if (isNullish(rubberBox)) { rubberBox = editorContext_.setRubberBox(editorContext_.selectorManager.getRubberBandBox()); } + var _currentZoom = editorContext_.getCurrentZoom(); + assignAttributes(rubberBox, { x: startX * _currentZoom, y: startY * _currentZoom, @@ -6418,6 +7129,8 @@ display: 'inline' }, 100); } + + return undefined; }, /** @@ -6429,40 +7142,36 @@ var currentZoom = editorContext_.getCurrentZoom(); hasMoved = true; var drawnPath = editorContext_.getDrawnPath(); + if (editorContext_.getCurrentMode() === 'path') { if (!drawnPath) { return; } + var seglist = drawnPath.pathSegList; var index = seglist.numberOfItems - 1; if (newPoint) { // First point // if (!index) { return; } - // Set control points var pointGrip1 = addCtrlGrip('1c1'); - var pointGrip2 = addCtrlGrip('0c2'); + var pointGrip2 = addCtrlGrip('0c2'); // dragging pointGrip1 - // dragging pointGrip1 pointGrip1.setAttribute('cx', mouseX); pointGrip1.setAttribute('cy', mouseY); pointGrip1.setAttribute('display', 'inline'); - var ptX = newPoint[0]; - var ptY = newPoint[1]; - - // set curve + var ptY = newPoint[1]; // set curve // const seg = seglist.getItem(index); + var curX = mouseX / currentZoom; var curY = mouseY / currentZoom; var altX = ptX + (ptX - curX); var altY = ptY + (ptY - curY); - pointGrip2.setAttribute('cx', altX * currentZoom); pointGrip2.setAttribute('cy', altY * currentZoom); pointGrip2.setAttribute('display', 'inline'); - var ctrlLine = getCtrlLine(1); assignAttributes(ctrlLine, { x1: mouseX, @@ -6486,12 +7195,15 @@ lastX = firstCtrl[0] / currentZoom; lastY = firstCtrl[1] / currentZoom; } + replacePathSeg(6, index, [ptX, ptY, lastX, lastY, altX, altY], drawnPath); } } else { var stretchy = getElem('path_stretch_line'); + if (stretchy) { var prev = seglist.getItem(index); + if (prev.pathSegType === 6) { var prevX = prev.x + (prev.x - prev.x2); var prevY = prev.y + (prev.y - prev.y2); @@ -6503,9 +7215,11 @@ } } } + return; - } - // if we are dragging a point, let's move it + } // if we are dragging a point, let's move it + + if (path.dragging) { var pt = getPointFromGrip({ x: path.dragging[0], @@ -6527,15 +7241,15 @@ } else { path.selected_pts = []; path.eachSeg(function (i) { - var seg = this; + var seg = this; // eslint-disable-line consistent-this + if (!seg.next && !seg.prev) { return; - } + } // const {item} = seg; + - // const {item} = seg; var rubberBox = editorContext_.getRubberBox(); var rbb = rubberBox.getBBox(); - var pt = getGripPt(seg); var ptBb = { x: pt.x, @@ -6543,11 +7257,9 @@ width: 0, height: 0 }; - var sel = rectsIntersect(rbb, ptBb); + this.select(sel); // Note that addPtsToSelection is not being run - this.select(sel); - // Note that addPtsToSelection is not being run if (sel) { path.selected_pts.push(seg.index); } @@ -6555,18 +7267,26 @@ } }, + /** + * @typedef module:path.keepElement + * @type {PlainObject} + * @property {boolean} keep + * @property {Element} element + */ + /** * @param {Event} evt * @param {Element} element * @param {Float} mouseX * @param {Float} mouseY - * @returns {undefined} + * @returns {module:path.keepElement|undefined} */ mouseUp: function mouseUp(evt, element, mouseX, mouseY) { - var drawnPath = editorContext_.getDrawnPath(); - // Create mode + var drawnPath = editorContext_.getDrawnPath(); // Create mode + if (editorContext_.getCurrentMode() === 'path') { newPoint = null; + if (!drawnPath) { element = getElem(editorContext_.getId()); editorContext_.setStarted(false); @@ -6577,13 +7297,13 @@ keep: true, element: element }; - } + } // Edit mode + - // Edit mode var rubberBox = editorContext_.getRubberBox(); + if (path.dragging) { var lastPt = path.cur_pt; - path.dragging = false; path.dragctrl = false; path.update(); @@ -6601,13 +7321,14 @@ if (rubberBox.getAttribute('width') <= 2 && rubberBox.getAttribute('height') <= 2) { pathActions.toSelectMode(evt.target); - } + } // else, move back to select mode - // else, move back to select mode } else { pathActions.toSelectMode(evt.target); } + hasMoved = false; + return undefined; }, /** @@ -6624,7 +7345,7 @@ }, /** - * @param {Element} element + * @param {Element} elem * @fires module:svgcanvas.SvgCanvas#event:selected * @returns {undefined} */ @@ -6669,8 +7390,7 @@ select: function select(target) { if (currentPath === target) { pathActions.toEditMode(target); - editorContext_.setCurrentMode('pathedit'); - // going into pathedit mode + editorContext_.setCurrentMode('pathedit'); // going into pathedit mode } else { currentPath = target; } @@ -6682,11 +7402,14 @@ */ reorient: function reorient() { var elem = editorContext_.getSelectedElements()[0]; + if (!elem) { return; } - var angle = getRotationAngle(elem); - if (angle === 0) { + + var angl = getRotationAngle(elem); + + if (angl === 0) { return; } @@ -6698,19 +7421,14 @@ batchCmd.addSubCommand(new ChangeElementCommand(elem, changes)); editorContext_.clearSelection(); this.resetOrientation(elem); + editorContext_.addCommandToHistory(batchCmd); // Set matrix to null - editorContext_.addCommandToHistory(batchCmd); - - // Set matrix to null getPath_(elem).show(false).matrix = null; - this.clear(); - editorContext_.addToSelection([elem], true); editorContext_.call('changed', editorContext_.getSelectedElements()); }, - /** * @param {boolean} remove Not in use * @returns {undefined} @@ -6718,6 +7436,7 @@ clear: function clear(remove) { var drawnPath = editorContext_.getDrawnPath(); currentPath = null; + if (drawnPath) { var elem = getElem(editorContext_.getId()); $$1(getElem('path_stretch_line')).remove(); @@ -6729,6 +7448,7 @@ } else if (editorContext_.getCurrentMode() === 'pathedit') { this.toSelectMode(); } + if (path) { path.init().show(false); } @@ -6739,22 +7459,20 @@ * @returns {false|undefined} */ resetOrientation: function resetOrientation(pth) { - if (pth == null || pth.nodeName !== 'path') { + if (isNullish(pth) || pth.nodeName !== 'path') { return false; } + var tlist = getTransformList(pth); var m = transformListToTransform(tlist).matrix; tlist.clear(); pth.removeAttribute('transform'); - var segList = pth.pathSegList; - - // Opera/win/non-EN throws an error here. + var segList = pth.pathSegList; // Opera/win/non-EN throws an error here. // TODO: Find out why! // Presumed fixed in Opera 10.5, so commented out for now - // try { - var len = segList.numberOfItems; - // } catch(err) { + + var len = segList.numberOfItems; // } catch(err) { // const fixed_d = pathActions.convertPath(pth); // pth.setAttribute('d', fixed_d); // segList = pth.pathSegList; @@ -6765,13 +7483,16 @@ var _loop = function _loop(i) { var seg = segList.getItem(i); var type = seg.pathSegType; + if (type === 1) { - return 'continue'; + return "continue"; } + var pts = []; $$1.each(['', 1, 2], function (j, n) { var x = seg['x' + n], y = seg['y' + n]; + if (x !== undefined && y !== undefined) { var pt = transformPoint(x, y, m); pts.splice(pts.length, 0, pt.x, pt.y); @@ -6783,10 +7504,11 @@ for (var i = 0; i < len; ++i) { var _ret = _loop(i); - if (_ret === 'continue') continue; + if (_ret === "continue") continue; } reorientGrads(pth, m); + return undefined; }, /** @@ -6804,12 +7526,12 @@ * @property {Float} y * @property {Integer} type */ + /** * @returns {module:path.NodePoint} */ getNodePoint: function getNodePoint() { var selPt = path.selected_pts.length ? path.selected_pts[0] : 1; - var seg = path.segs[selPt]; return { x: seg.item.x, @@ -6831,9 +7553,7 @@ */ clonePathNode: function clonePathNode() { path.storeD(); - - var selPts = path.selected_pts; - // const {segs} = path; + var selPts = path.selected_pts; // const {segs} = path; var i = selPts.length; var nums = []; @@ -6841,12 +7561,11 @@ while (i--) { var pt = selPts[i]; path.addSeg(pt); - nums.push(pt + i); nums.push(pt + i + 1); } - path.init().addPtsToSelection(nums); + path.init().addPtsToSelection(nums); path.endChanges('Clone path node(s)'); }, @@ -6854,56 +7573,55 @@ * @returns {undefined} */ opencloseSubPath: function opencloseSubPath() { - var selPts = path.selected_pts; - // Only allow one selected node for now + var selPts = path.selected_pts; // Only allow one selected node for now + if (selPts.length !== 1) { return; } var _path = path, elem = _path.elem; - - var list = elem.pathSegList; - - // const len = list.numberOfItems; + var list = elem.pathSegList; // const len = list.numberOfItems; var index = selPts[0]; - var openPt = null; - var startItem = null; + var startItem = null; // Check if subpath is already open - // Check if subpath is already open path.eachSeg(function (i) { if (this.type === 2 && i <= index) { startItem = this.item; } + if (i <= index) { return true; } + if (this.type === 2) { // Found M first, so open openPt = i; return false; } + if (this.type === 1) { // Found Z first, so closed openPt = false; return false; } + + return true; }); - if (openPt == null) { + if (isNullish(openPt)) { // Single path, so close last seg openPt = path.segs.length - 1; } if (openPt !== false) { // Close this path - // Create a line going to the previous "M" var newseg = elem.createSVGPathSegLinetoAbs(startItem.x, startItem.y); - var closer = elem.createSVGPathSegClosePath(); + if (openPt === path.segs.length - 1) { list.appendItem(newseg); list.appendItem(closer); @@ -6914,27 +7632,25 @@ path.init().selectPt(openPt + 1); return; - } - - // M 1,1 L 2,2 L 3,3 L 1,1 z // open at 2,2 + } // M 1,1 L 2,2 L 3,3 L 1,1 z // open at 2,2 // M 2,2 L 3,3 L 1,1 - // M 1,1 L 2,2 L 1,1 z M 4,4 L 5,5 L6,6 L 5,5 z // M 1,1 L 2,2 L 1,1 z [M 4,4] L 5,5 L(M)6,6 L 5,5 z + var seg = path.segs[index]; if (seg.mate) { list.removeItem(index); // Removes last "L" + list.removeItem(index); // Removes the "Z" + path.init().selectPt(index - 1); return; } - var lastM = void 0, - zSeg = void 0; + var lastM, zSeg; // Find this sub-path's closing point and remove - // Find this sub-path's closing point and remove for (var i = 0; i < list.numberOfItems; i++) { var item = list.getItem(i); @@ -6943,8 +7659,7 @@ lastM = i; } else if (i === index) { // Remove it - list.removeItem(lastM); - // index--; + list.removeItem(lastM); // index--; } else if (item.pathSegType === 1 && index < i) { // Remove the closing seg of this subpath zSeg = i - 1; @@ -6959,12 +7674,9 @@ insertItemBefore(elem, list.getItem(lastM), zSeg); } - var pt = list.getItem(lastM); + var pt = list.getItem(lastM); // Make this point the new "M" - // Make this point the new "M" - replacePathSeg(2, lastM, [pt.x, pt.y]); - - // i = index; // i is local here, so has no effect; what was the intent for this? + replacePathSeg(2, lastM, [pt.x, pt.y]); // i = index; // i is local here, so has no effect; what was the intent for this? path.init().selectPt(0); }, @@ -6976,17 +7688,17 @@ if (!pathActions.canDeleteNodes) { return; } + path.storeD(); - var selPts = path.selected_pts; - var i = selPts.length; + while (i--) { var pt = selPts[i]; path.deleteSeg(pt); - } + } // Cleanup + - // Cleanup var cleanup = function cleanup() { var segList = path.elem.pathSegList; var len = segList.numberOfItems; @@ -7003,9 +7715,11 @@ while (len--) { var item = segList.getItem(len); + if (item.pathSegType === 1) { var prev = segList.getItem(len - 1); var nprev = segList.getItem(len - 2); + if (prev.pathSegType === 2) { remItems(len - 1, 2); cleanup(); @@ -7017,13 +7731,12 @@ } } else if (item.pathSegType === 2) { if (len > 0) { - var prevType = segList.getItem(len - 1).pathSegType; - // Path has M M + var prevType = segList.getItem(len - 1).pathSegType; // Path has M M + if (prevType === 2) { remItems(len - 1, 1); cleanup(); - break; - // Entire path ends with Z M + break; // Entire path ends with Z M } else if (prevType === 1 && segList.numberOfItems - 1 === len) { remItems(len, 1); cleanup(); @@ -7032,12 +7745,12 @@ } } } + return false; }; - cleanup(); + cleanup(); // Completely delete a path with 1 or 0 segments - // Completely delete a path with 1 or 0 segments if (path.elem.pathSegList.numberOfItems <= 1) { pathActions.toSelectMode(path.elem); editorContext_.canvas.deleteSelectedElements(); @@ -7045,26 +7758,28 @@ } path.init(); - path.clearSelection(); - - // TODO: Find right way to select point now + path.clearSelection(); // TODO: Find right way to select point now // path.selectPt(selPt); + if (window.opera) { // Opera repaints incorrectly var cp = $$1(path.elem); cp.attr('d', cp.attr('d')); } + path.endChanges('Delete path node(s)'); }, - // Can't seem to use `@borrows` here, so using `@see` + /** * Smooth polyline into path * @function module:path.pathActions.smoothPolylineIntoPath * @see module:path~smoothPolylineIntoPath */ smoothPolylineIntoPath: smoothPolylineIntoPath, + /** + * @param {?Integer} v See {@link https://www.w3.org/TR/SVG/single-page.html#paths-InterfaceSVGPathSeg} * @returns {undefined} */ setSegType: function setSegType(v) { @@ -7078,17 +7793,19 @@ */ moveNode: function moveNode(attr, newValue) { var selPts = path.selected_pts; + if (!selPts.length) { return; } - path.storeD(); + path.storeD(); // Get first selected point - // Get first selected point var seg = path.segs[selPts[0]]; - var diff = { x: 0, y: 0 }; + var diff = { + x: 0, + y: 0 + }; diff[attr] = newValue - seg.item[attr]; - seg.move(diff.x, diff.y); path.endChanges('Move path point'); }, @@ -7103,31 +7820,35 @@ // M0,0 L0,100 L100,100 z var segList = elem.pathSegList; var len = segList.numberOfItems; - var lastM = void 0; + var lastM; + for (var i = 0; i < len; ++i) { var item = segList.getItem(i); + if (item.pathSegType === 2) { lastM = item; } if (item.pathSegType === 1) { var prev = segList.getItem(i - 1); + if (prev.x !== lastM.x || prev.y !== lastM.y) { // Add an L segment here var newseg = elem.createSVGPathSegLinetoAbs(lastM.x, lastM.y); - insertItemBefore(elem, newseg, i); - // Can this be done better? + insertItemBefore(elem, newseg, i); // Can this be done better? + pathActions.fixEnd(elem); break; } } } + if (isWebkit()) { editorContext_.resetD(elem); } }, - // Can't seem to use `@borrows` here, so using `@see` + /** * Convert a path to one with only absolute or relative values * @function module:path.pathActions.convertPath @@ -7136,26 +7857,19 @@ convertPath: convertPath } ); - }(); + }(); // end pathActions - /* globals jQuery */ + var $$2 = jQueryPluginSVG(jQuery); // String used to encode base64. - // Constants - var $$2 = jqPluginSVG(jQuery); + var KEYSTR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; // Much faster than running getBBox() every time - // String used to encode base64. - var KEYSTR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; - - // Much faster than running getBBox() every time var visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use'; - var visElemsArr = visElems.split(','); - // const hidElems = 'clipPath,defs,desc,feGaussianBlur,filter,linearGradient,marker,mask,metadata,pattern,radialGradient,stop,switch,symbol,title,textPath'; + var visElemsArr = visElems.split(','); // const hidElems = 'clipPath,defs,desc,feGaussianBlur,filter,linearGradient,marker,mask,metadata,pattern,radialGradient,stop,switch,symbol,title,textPath'; var editorContext_$1 = null; var domdoc_ = null; var domcontainer_ = null; var svgroot_ = null; - /** * Object with the following keys/values * @typedef {PlainObject} module:utilities.SVGElementJSON @@ -7172,10 +7886,12 @@ * @interface module:utilities.EditorContext * @property {module:path.pathActions} pathActions */ + /** * @function module:utilities.EditorContext#getSVGContent * @returns {SVGSVGElement} */ + /** * Create a new SVG element based on the given object keys/values and add it * to the current layer. @@ -7184,26 +7900,32 @@ * @param {module:utilities.SVGElementJSON} data * @returns {Element} The new element */ + /** * @function module:utilities.EditorContext#getSelectedElements * @returns {Element[]} the array with selected DOM elements */ + /** * @function module:utilities.EditorContext#getDOMDocument * @returns {HTMLDocument} */ + /** * @function module:utilities.EditorContext#getDOMContainer * @returns {HTMLElement} */ + /** * @function module:utilities.EditorContext#getSVGRoot * @returns {SVGSVGElement} */ + /** * @function module:utilities.EditorContext#getBaseUnit * @returns {string} */ + /** * @function module:utilities.EditorContext#getSnappingStep * @returns {Float|string} @@ -7214,13 +7936,24 @@ * @param {module:utilities.EditorContext} editorContext * @returns {undefined} */ - var init$2 = function init$$1(editorContext) { + + var init$2 = function init(editorContext) { editorContext_$1 = editorContext; domdoc_ = editorContext.getDOMDocument(); domcontainer_ = editorContext.getDOMContainer(); svgroot_ = editorContext.getSVGRoot(); }; + /** + * Used to prevent the [Billion laughs attack]{@link https://en.wikipedia.org/wiki/Billion_laughs_attack}. + * @function module:utilities.dropXMLInteralSubset + * @param {string} str String to be processed + * @returns {string} The string with entity declarations in the internal subset removed + * @todo This might be needed in other places `parseFromString` is used even without LGTM flagging + */ + var dropXMLInteralSubset = function dropXMLInteralSubset(str) { + return str.replace(/()/, '$1$2'); + }; /** * Converts characters in a string to XML-friendly entities. * @function module:utilities.toXml @@ -7228,50 +7961,52 @@ * @param {string} str - The string to be converted * @returns {string} The converted string */ + var toXml = function toXml(str) { // ' is ok in XML, but not HTML // > does not normally need escaping, though it can if within a CDATA expression (and preceded by "]]") - return str.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/, '''); + return str.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, '''); // Note: `'` is XML only }; - - // 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. // Base64 code from Tyler Akins -- http://rumkin.com - // schiller: Removed string concatenation in favour of Array.join() optimization, // also precalculate the size of the array needed. /** - * Converts a string to base64 + * Converts a string to base64. * @function module:utilities.encode64 * @param {string} input * @returns {string} Base64 output */ - var encode64 = function encode64(input) { + + function encode64(input) { // base64 strings are 4/3 larger than the original string input = encodeUTF8(input); // convert non-ASCII characters // input = convertToXMLReferences(input); + if (window.btoa) { return window.btoa(input); // Use native if available } - var output = []; - output.length = Math.floor((input.length + 2) / 3) * 4; + var output = new Array(Math.floor((input.length + 2) / 3) * 4); var i = 0, p = 0; + do { var chr1 = input.charCodeAt(i++); var chr2 = input.charCodeAt(i++); var chr3 = input.charCodeAt(i++); + /* eslint-disable no-bitwise */ var enc1 = chr1 >> 2; var enc2 = (chr1 & 3) << 4 | chr2 >> 4; - var enc3 = (chr2 & 15) << 2 | chr3 >> 6; var enc4 = chr3 & 63; + /* eslint-enable no-bitwise */ if (isNaN(chr2)) { - enc3 = enc4 = 64; + enc3 = 64; + enc4 = 64; } else if (isNaN(chr3)) { enc4 = 64; } @@ -7283,22 +8018,21 @@ } while (i < input.length); return output.join(''); - }; - + } /** - * Converts a string from base64 + * Converts a string from base64. * @function module:utilities.decode64 * @param {string} input Base64-encoded input * @returns {string} Decoded output */ - var decode64 = function decode64(input) { + + function decode64(input) { if (window.atob) { return decodeUTF8(window.atob(input)); - } + } // remove all characters that are not A-Z, a-z, 0-9, +, /, or = + - // remove all characters that are not A-Z, a-z, 0-9, +, /, or = input = input.replace(/[^A-Za-z0-9+/=]/g, ''); - var output = ''; var i = 0; @@ -7307,109 +8041,123 @@ var enc2 = KEYSTR.indexOf(input.charAt(i++)); var enc3 = KEYSTR.indexOf(input.charAt(i++)); var enc4 = KEYSTR.indexOf(input.charAt(i++)); + /* eslint-disable no-bitwise */ var chr1 = enc1 << 2 | enc2 >> 4; var chr2 = (enc2 & 15) << 4 | enc3 >> 2; var chr3 = (enc3 & 3) << 6 | enc4; + /* eslint-enable no-bitwise */ output += String.fromCharCode(chr1); if (enc3 !== 64) { - output = output + String.fromCharCode(chr2); + output += String.fromCharCode(chr2); } + if (enc4 !== 64) { - output = output + String.fromCharCode(chr3); + output += String.fromCharCode(chr3); } } while (i < input.length); - return decodeUTF8(output); - }; + return decodeUTF8(output); + } /** * @function module:utilities.decodeUTF8 * @param {string} argString * @returns {string} */ - var decodeUTF8 = function decodeUTF8(argString) { - return decodeURIComponent(escape(argString)); - }; - // codedread:does not seem to work with webkit-based browsers on OSX // Brettz9: please test again as function upgraded + function decodeUTF8(argString) { + return decodeURIComponent(escape(argString)); + } // codedread:does not seem to work with webkit-based browsers on OSX // Brettz9: please test again as function upgraded + /** * @function module:utilities.encodeUTF8 * @param {string} argString * @returns {string} */ + var encodeUTF8 = function encodeUTF8(argString) { return unescape(encodeURIComponent(argString)); }; - /** - * convert dataURL to object URL + * Convert dataURL to object URL. * @function module:utilities.dataURLToObjectURL * @param {string} dataurl * @returns {string} object URL or empty string */ + var dataURLToObjectURL = function dataURLToObjectURL(dataurl) { if (typeof Uint8Array === 'undefined' || typeof Blob === 'undefined' || typeof URL === 'undefined' || !URL.createObjectURL) { return ''; } + var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]); var n = bstr.length; var u8arr = new Uint8Array(n); + while (n--) { u8arr[n] = bstr.charCodeAt(n); } - var blob = new Blob([u8arr], { type: mime }); + + var blob = new Blob([u8arr], { + type: mime + }); return URL.createObjectURL(blob); }; - /** - * get object URL for a blob object + * Get object URL for a blob object. * @function module:utilities.createObjectURL * @param {Blob} blob A Blob object or File object * @returns {string} object URL or empty string */ + var createObjectURL = function createObjectURL(blob) { if (!blob || typeof URL === 'undefined' || !URL.createObjectURL) { return ''; } + return URL.createObjectURL(blob); }; - /** * @property {string} blankPageObjectURL */ + var blankPageObjectURL = function () { if (typeof Blob === 'undefined') { return ''; } - var blob = new Blob(['SVG-edit '], { type: 'text/html' }); + + var blob = new Blob(['SVG-edit '], { + type: 'text/html' + }); return createObjectURL(blob); }(); - /** - * Cross-browser compatible method of converting a string to an XML tree - * found this function [here]{@link http://groups.google.com/group/jquery-dev/browse_thread/thread/c6d11387c580a77f} + * Cross-browser compatible method of converting a string to an XML tree. + * Found this function [here]{@link http://groups.google.com/group/jquery-dev/browse_thread/thread/c6d11387c580a77f}. * @function module:utilities.text2xml * @param {string} sXML * @throws {Error} * @returns {XMLDocument} */ + var text2xml = function text2xml(sXML) { if (sXML.includes('` element, creating it first if necessary */ + var findDefs = function findDefs() { var svgElement = editorContext_$1.getSVGContent(); var defs = svgElement.getElementsByTagNameNS(NS.SVG, 'defs'); + if (defs.length > 0) { defs = defs[0]; } else { defs = svgElement.ownerDocument.createElementNS(NS.SVG, 'defs'); + if (svgElement.firstChild) { // first child is a comment, so call nextSibling - svgElement.insertBefore(defs, svgElement.firstChild.nextSibling); - // svgElement.firstChild.nextSibling.before(defs); // Not safe + svgElement.insertBefore(defs, svgElement.firstChild.nextSibling); // svgElement.firstChild.nextSibling.before(defs); // Not safe } else { svgElement.append(defs); } } - return defs; - }; - // TODO(codedread): Consider moving the next to functions to bbox.js + return defs; + }; // TODO(codedread): Consider moving the next to functions to bbox.js /** * Get correct BBox for a path in Webkit. - * Converted from code found [here]{@link http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html} + * Converted from code found [here]{@link http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html}. * @function module:utilities.getPathBBox * @param {SVGPathElement} path - The path DOM element to get the BBox for * @returns {module:utilities.BBoxObject} A BBox-like object */ - var getPathBBox = function getPathBBox(path$$1) { - var seglist = path$$1.pathSegList; - var tot = seglist.numberOfItems; + var getPathBBox = function getPathBBox(path) { + var seglist = path.pathSegList; + var tot = seglist.numberOfItems; var bounds = [[], []]; var start = seglist.getItem(0); var P0 = [start.x, start.y]; + var getCalc = function getCalc(j, P1, P2, P3) { + return function (t) { + return 1 - Math.pow(t, 3) * P0[j] + 3 * 1 - Math.pow(t, 2) * t * P1[j] + 3 * (1 - t) * Math.pow(t, 2) * P2[j] + Math.pow(t, 3) * P3[j]; + }; + }; + for (var i = 0; i < tot; i++) { var seg = seglist.getItem(i); if (seg.x === undefined) { continue; - } + } // Add actual points to limits + - // Add actual points to limits bounds[0].push(P0[0]); bounds[1].push(P0[1]); if (seg.x1) { - (function () { - var P1 = [seg.x1, seg.y1], - P2 = [seg.x2, seg.y2], - P3 = [seg.x, seg.y]; + var P1 = [seg.x1, seg.y1], + P2 = [seg.x2, seg.y2], + P3 = [seg.x, seg.y]; - var _loop = function _loop(j) { - var calc = function calc(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 (var j = 0; j < 2; j++) { + var calc = getCalc(j, P1, P2, P3); + var b = 6 * P0[j] - 12 * P1[j] + 6 * P2[j]; + var a = -3 * P0[j] + 9 * P1[j] - 9 * P2[j] + 3 * P3[j]; + var c = 3 * P1[j] - 3 * P0[j]; - var b = 6 * P0[j] - 12 * P1[j] + 6 * P2[j]; - var a = -3 * P0[j] + 9 * P1[j] - 9 * P2[j] + 3 * P3[j]; - var c = 3 * P1[j] - 3 * P0[j]; - - if (a === 0) { - if (b === 0) { - return 'continue'; - } - var t = -c / b; - if (t > 0 && t < 1) { - bounds[j].push(calc(t)); - } - return 'continue'; + if (a === 0) { + if (b === 0) { + continue; } - var b2ac = Math.pow(b, 2) - 4 * c * a; - if (b2ac < 0) { - return 'continue'; - } - var t1 = (-b + Math.sqrt(b2ac)) / (2 * a); - if (t1 > 0 && t1 < 1) { - bounds[j].push(calc(t1)); - } - var t2 = (-b - Math.sqrt(b2ac)) / (2 * a); - if (t2 > 0 && t2 < 1) { - bounds[j].push(calc(t2)); - } - }; - for (var j = 0; j < 2; j++) { - var _ret2 = _loop(j); + var t = -c / b; - if (_ret2 === 'continue') continue; + if (t > 0 && t < 1) { + bounds[j].push(calc(t)); + } + + continue; } - P0 = P3; - })(); + + var b2ac = Math.pow(b, 2) - 4 * c * a; + + if (b2ac < 0) { + continue; + } + + var t1 = (-b + Math.sqrt(b2ac)) / (2 * a); + + if (t1 > 0 && t1 < 1) { + bounds[j].push(calc(t1)); + } + + var t2 = (-b - Math.sqrt(b2ac)) / (2 * a); + + if (t2 > 0 && t2 < 1) { + bounds[j].push(calc(t2)); + } + } + + P0 = P3; } else { bounds[0].push(seg.x); bounds[1].push(seg.y); @@ -7646,7 +8412,6 @@ height: h }; }; - /** * Get the given/selected element's bounding box object, checking for * horizontal/vertical lines (see issue 717) @@ -7655,16 +8420,17 @@ * @param {Element} selected - Container or `` DOM element * @returns {DOMRect} Bounding box object */ + function groupBBFix(selected) { if (supportsHVLineContainerBBox()) { try { return selected.getBBox(); } catch (e) {} } + var ref = $$2.data(selected, 'ref'); var matched = null; - var ret = void 0, - copy = void 0; + var ret, copy; if (ref) { copy = $$2(ref).children().clone().attr('visibility', 'hidden'); @@ -7675,13 +8441,16 @@ } var issue = false; + if (matched.length) { matched.each(function () { var bb = this.getBBox(); + if (!bb.width || !bb.height) { issue = true; } }); + if (issue) { var elems = ref ? copy : $$2(selected).children(); ret = getStrokedBBox(elems); @@ -7691,64 +8460,72 @@ } else { ret = selected.getBBox(); } + if (ref) { copy.remove(); } + return ret; } - /** * Get the given/selected element's bounding box object, convert it to be more - * usable when necessary + * usable when necessary. * @function module:utilities.getBBox * @param {Element} elem - Optional DOM element to get the BBox for * @returns {module:utilities.BBoxObject} Bounding box object */ + + var getBBox = function getBBox(elem) { var selected = elem || editorContext_$1.geSelectedElements()[0]; + if (elem.nodeType !== 1) { return null; } - var elname = selected.nodeName; + var elname = selected.nodeName; var ret = null; + switch (elname) { case 'text': if (selected.textContent === '') { selected.textContent = 'a'; // Some character needed for the selector to use. + ret = selected.getBBox(); selected.textContent = ''; - } else { - if (selected.getBBox) { - ret = selected.getBBox(); - } + } else if (selected.getBBox) { + ret = selected.getBBox(); } + break; + case 'path': if (!supportsPathBBox()) { ret = getPathBBox(selected); - } else { - if (selected.getBBox) { - ret = selected.getBBox(); - } + } else if (selected.getBBox) { + ret = selected.getBBox(); } + break; + case 'g': case 'a': ret = groupBBFix(selected); break; - default: + default: if (elname === 'use') { - ret = groupBBFix(selected, true); + ret = groupBBFix(selected); // , true); } + if (elname === 'use' || elname === 'foreignObject' && isWebkit()) { if (!ret) { ret = selected.getBBox(); - } - // This is resolved in later versions of webkit, perhaps we should + } // This is resolved in later versions of webkit, perhaps we should // have a featured detection for correct 'use' behavior? // —————————— + + if (!isWebkit()) { var bb = {}; bb.width = ret.width; @@ -7765,7 +8542,9 @@ // tspan (and textPath apparently) have no `getBBox` in Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=937268 // Re: Chrome returning bbox for containing text element, see: https://bugs.chromium.org/p/chromium/issues/detail?id=349835 var extent = selected.getExtentOfChar(0); // pos+dimensions of the first glyph + var width = selected.getComputedTextLength(); // width of the tspan + ret = { x: extent.x, y: extent.y, @@ -7776,6 +8555,7 @@ } else { // Check if element is child of a foreignObject var fo = $$2(selected).closest('foreignObject'); + if (fo.length) { if (fo[0].getBBox) { ret = fo[0].getBBox(); @@ -7783,15 +8563,16 @@ } } } + } + if (ret) { ret = bboxToObj(ret); - } + } // get the bounding box from the DOM (which is in that element's coordinate system) + - // get the bounding box from the DOM (which is in that element's coordinate system) return ret; }; - /** * @typedef {GenericArray} module:utilities.PathSegmentArray * @property {Integer} length 2 @@ -7806,157 +8587,168 @@ * @param {module:utilities.PathSegmentArray[]} pathSegments - An array of path segments to be converted * @returns {string} The converted path d attribute. */ + var getPathDFromSegments = function getPathDFromSegments(pathSegments) { var d = ''; - $$2.each(pathSegments, function (j, _ref2) { - var _ref3 = slicedToArray(_ref2, 2), + var _ref3 = _slicedToArray(_ref2, 2), singleChar = _ref3[0], pts = _ref3[1]; d += singleChar; + for (var i = 0; i < pts.length; i += 2) { d += pts[i] + ',' + pts[i + 1] + ' '; } }); - return d; }; - /** * Make a path 'd' attribute from a simple SVG element shape. * @function module:utilities.getPathDFromElement * @param {Element} elem - The element to be converted * @returns {string} The path d attribute or `undefined` if the element type is unknown. */ + var getPathDFromElement = function getPathDFromElement(elem) { // Possibly the cubed root of 6, but 1.81 works best var num = 1.81; - var d = void 0, - a = void 0, - rx = void 0, - ry = void 0; + var d, a, rx, ry; + switch (elem.tagName) { case 'ellipse': case 'circle': - a = $$2(elem).attr(['rx', 'ry', 'cx', 'cy']); - var _a = a, - cx = _a.cx, - cy = _a.cy; - var _a2 = a; - rx = _a2.rx; - ry = _a2.ry; + { + a = $$2(elem).attr(['rx', 'ry', 'cx', 'cy']); + var _a = a, + cx = _a.cx, + cy = _a.cy; + var _a2 = a; + rx = _a2.rx; + ry = _a2.ry; - if (elem.tagName === 'circle') { - rx = ry = $$2(elem).attr('r'); + if (elem.tagName === 'circle') { + ry = $$2(elem).attr('r'); + rx = ry; + } + + d = getPathDFromSegments([['M', [cx - rx, cy]], ['C', [cx - rx, cy - ry / num, cx - rx / num, cy - ry, cx, cy - ry]], ['C', [cx + rx / num, cy - ry, cx + rx, cy - ry / num, cx + rx, cy]], ['C', [cx + rx, cy + ry / num, cx + rx / num, cy + ry, cx, cy + ry]], ['C', [cx - rx / num, cy + ry, cx - rx, cy + ry / num, cx - rx, cy]], ['Z', []]]); + break; } - d = getPathDFromSegments([['M', [cx - rx, cy]], ['C', [cx - rx, cy - ry / num, cx - rx / num, cy - ry, cx, cy - ry]], ['C', [cx + rx / num, cy - ry, cx + rx, cy - ry / num, cx + rx, cy]], ['C', [cx + rx, cy + ry / num, cx + rx / num, cy + ry, cx, cy + ry]], ['C', [cx - rx / num, cy + ry, cx - rx, cy + ry / num, cx - rx, cy]], ['Z', []]]); - break; case 'path': d = elem.getAttribute('d'); break; + case 'line': a = $$2(elem).attr(['x1', 'y1', 'x2', 'y2']); d = 'M' + a.x1 + ',' + a.y1 + 'L' + a.x2 + ',' + a.y2; break; + case 'polyline': d = 'M' + elem.getAttribute('points'); break; + case 'polygon': d = 'M' + elem.getAttribute('points') + ' Z'; break; + case 'rect': - var r = $$2(elem).attr(['rx', 'ry']); - rx = r.rx; - ry = r.ry; + { + var r = $$2(elem).attr(['rx', 'ry']); + rx = r.rx; + ry = r.ry; + var b = elem.getBBox(); + var x = b.x, + y = b.y, + w = b.width, + h = b.height; + num = 4 - num; // Why? Because! - var _b = elem.getBBox(); - var x = _b.x, - y = _b.y, - w = _b.width, - h = _b.height; + if (!rx && !ry) { + // Regular rect + d = getPathDFromSegments([['M', [x, y]], ['L', [x + w, y]], ['L', [x + w, y + h]], ['L', [x, y + h]], ['L', [x, y]], ['Z', []]]); + } else { + d = getPathDFromSegments([['M', [x, y + ry]], ['C', [x, y + ry / num, x + rx / num, y, x + rx, y]], ['L', [x + w - rx, y]], ['C', [x + w - rx / num, y, x + w, y + ry / num, x + w, y + ry]], ['L', [x + w, y + h - ry]], ['C', [x + w, y + h - ry / num, x + w - rx / num, y + h, x + w - rx, y + h]], ['L', [x + rx, y + h]], ['C', [x + rx / num, y + h, x, y + h - ry / num, x, y + h - ry]], ['L', [x, y + ry]], ['Z', []]]); + } - num = 4 - num; // Why? Because! - - if (!rx && !ry) { - // Regular rect - d = getPathDFromSegments([['M', [x, y]], ['L', [x + w, y]], ['L', [x + w, y + h]], ['L', [x, y + h]], ['L', [x, y]], ['Z', []]]); - } else { - d = getPathDFromSegments([['M', [x, y + ry]], ['C', [x, y + ry / num, x + rx / num, y, x + rx, y]], ['L', [x + w - rx, y]], ['C', [x + w - rx / num, y, x + w, y + ry / num, x + w, y + ry]], ['L', [x + w, y + h - ry]], ['C', [x + w, y + h - ry / num, x + w - rx / num, y + h, x + w - rx, y + h]], ['L', [x + rx, y + h]], ['C', [x + rx / num, y + h, x, y + h - ry / num, x, y + h - ry]], ['L', [x, y + ry]], ['Z', []]]); + break; } - break; + default: break; } return d; }; - /** * Get a set of attributes from an element that is useful for convertToPath. * @function module:utilities.getExtraAttributesForConvertToPath * @param {Element} elem - The element to be probed * @returns {PlainObject.<"marker-start"|"marker-end"|"marker-mid"|"filter"|"clip-path", string>} An object with attributes. */ + var getExtraAttributesForConvertToPath = function getExtraAttributesForConvertToPath(elem) { - var attrs = {}; - // TODO: make this list global so that we can properly maintain it + var attrs = {}; // TODO: make this list global so that we can properly maintain it // TODO: what about @transform, @clip-rule, @fill-rule, etc? + $$2.each(['marker-start', 'marker-end', 'marker-mid', 'filter', 'clip-path'], function () { var a = elem.getAttribute(this); + if (a) { attrs[this] = a; } }); return attrs; }; - /** - * Get the BBox of an element-as-path + * Get the BBox of an element-as-path. * @function module:utilities.getBBoxOfElementAsPath * @param {Element} elem - The DOM element to be probed * @param {module:utilities.EditorContext#addSVGElementFromJson} addSVGElementFromJson - Function to add the path element to the current layer. See canvas.addSVGElementFromJson * @param {module:path.pathActions} pathActions - If a transform exists, `pathActions.resetOrientation()` is used. See: canvas.pathActions. * @returns {DOMRect|false} The resulting path's bounding box object. */ - var getBBoxOfElementAsPath = function getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions$$1) { - var path$$1 = addSVGElementFromJson({ + + var getBBoxOfElementAsPath = function getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions) { + var path = addSVGElementFromJson({ element: 'path', attr: getExtraAttributesForConvertToPath(elem) }); - var eltrans = elem.getAttribute('transform'); + if (eltrans) { - path$$1.setAttribute('transform', eltrans); + path.setAttribute('transform', eltrans); } - var parent = elem.parentNode; + var parentNode = elem.parentNode; + if (elem.nextSibling) { - elem.before(path$$1); + elem.before(path); } else { - parent.append(path$$1); + parentNode.append(path); } var d = getPathDFromElement(elem); + if (d) { - path$$1.setAttribute('d', d); + path.setAttribute('d', d); } else { - path$$1.remove(); + path.remove(); + } // Get the correct BBox of the new path, then discard it + + + pathActions.resetOrientation(path); + var bb = false; + + try { + bb = path.getBBox(); + } catch (e) {// Firefox fails } - // Get the correct BBox of the new path, then discard it - pathActions$$1.resetOrientation(path$$1); - var bb = false; - try { - bb = path$$1.getBBox(); - } catch (e) { - // Firefox fails - } - path$$1.remove(); + path.remove(); return bb; }; - /** * Convert selected element to a path. * @function module:utilities.convertToPath @@ -7966,69 +8758,64 @@ * @param {module:path.pathActions} pathActions - If a transform exists, pathActions.resetOrientation() is used. See: canvas.pathActions. * @param {module:draw.DrawCanvasInit#clearSelection|module:path.EditorContext#clearSelection} clearSelection - see [canvas.clearSelection]{@link module:svgcanvas.SvgCanvas#clearSelection} * @param {module:path.EditorContext#addToSelection} addToSelection - see [canvas.addToSelection]{@link module:svgcanvas.SvgCanvas#addToSelection} - * @param {module:history} history - see history module + * @param {module:history} hstry - see history module * @param {module:path.EditorContext#addCommandToHistory|module:draw.DrawCanvasInit#addCommandToHistory} addCommandToHistory - see [canvas.addCommandToHistory]{@link module:svgcanvas~addCommandToHistory} * @returns {SVGPathElement|null} The converted path element or null if the DOM element was not recognized. */ - var convertToPath = function convertToPath(elem, attrs, addSVGElementFromJson, pathActions$$1, clearSelection, addToSelection, history, addCommandToHistory) { - var batchCmd = new history.BatchCommand('Convert element to Path'); - // Any attribute on the element not covered by the passed-in attributes + var convertToPath = function convertToPath(elem, attrs, addSVGElementFromJson, pathActions, clearSelection, addToSelection, hstry, addCommandToHistory) { + var batchCmd = new hstry.BatchCommand('Convert element to Path'); // Any attribute on the element not covered by the passed-in attributes + attrs = $$2.extend({}, attrs, getExtraAttributesForConvertToPath(elem)); - - var path$$1 = addSVGElementFromJson({ + var path = addSVGElementFromJson({ element: 'path', attr: attrs }); - var eltrans = elem.getAttribute('transform'); + if (eltrans) { - path$$1.setAttribute('transform', eltrans); + path.setAttribute('transform', eltrans); } var id = elem.id; + var parentNode = elem.parentNode; - var parent = elem.parentNode; if (elem.nextSibling) { - elem.before(path$$1); + elem.before(path); } else { - parent.append(path$$1); + parentNode.append(path); } var d = getPathDFromElement(elem); + if (d) { - path$$1.setAttribute('d', d); - - // Replace the current element with the converted one - + path.setAttribute('d', d); // Replace the current element with the converted one // Reorient if it has a matrix + if (eltrans) { - var tlist = getTransformList(path$$1); + var tlist = getTransformList(path); + if (hasMatrixTransform(tlist)) { - pathActions$$1.resetOrientation(path$$1); + pathActions.resetOrientation(path); } } var nextSibling = elem.nextSibling; - - batchCmd.addSubCommand(new history.RemoveElementCommand(elem, nextSibling, parent)); - batchCmd.addSubCommand(new history.InsertElementCommand(path$$1)); - + batchCmd.addSubCommand(new hstry.RemoveElementCommand(elem, nextSibling, parent)); + batchCmd.addSubCommand(new hstry.InsertElementCommand(path)); clearSelection(); elem.remove(); - path$$1.setAttribute('id', id); - path$$1.removeAttribute('visibility'); - addToSelection([path$$1], true); - + path.setAttribute('id', id); + path.removeAttribute('visibility'); + addToSelection([path], true); addCommandToHistory(batchCmd); + return path; + } // the elem.tagName was not recognized, so no "d" attribute. Remove it, so we've haven't changed anything. - return path$$1; - } - // the elem.tagName was not recognized, so no "d" attribute. Remove it, so we've haven't changed anything. - path$$1.remove(); + + path.remove(); return null; }; - /** * Can the bbox be optimized over the native getBBox? The optimized bbox is the same as the native getBBox when * the rotation angle is a multiple of 90 degrees and there are no complex transforms. @@ -8046,16 +8833,16 @@ * getBBox then apply the angle and any transforms. * * @param {Float} angle - The rotation angle in degrees - * @param {boolean} hasMatrixTransform - True if there is a matrix transform + * @param {boolean} hasAMatrixTransform - True if there is a matrix transform * @returns {boolean} True if the bbox can be optimized. */ - function bBoxCanBeOptimizedOverNativeGetBBox(angle, hasMatrixTransform$$1) { + + function bBoxCanBeOptimizedOverNativeGetBBox(angle, hasAMatrixTransform) { var angleModulo90 = angle % 90; var closeTo90 = angleModulo90 < -89.99 || angleModulo90 > 89.99; var closeTo0 = angleModulo90 > -0.001 && angleModulo90 < 0.001; - return hasMatrixTransform$$1 || !(closeTo0 || closeTo90); + return hasAMatrixTransform || !(closeTo0 || closeTo90); } - /** * Get bounding box that includes any transforms. * @function module:utilities.getBBoxWithTransform @@ -8064,11 +8851,12 @@ * @param {module:path.pathActions} pathActions - If a transform exists, pathActions.resetOrientation() is used. See: canvas.pathActions. * @returns {module:utilities.BBoxObject|module:math.TransformedBox|DOMRect} A single bounding box object */ - var getBBoxWithTransform = function getBBoxWithTransform(elem, addSVGElementFromJson, pathActions$$1) { + + + var getBBoxWithTransform = function getBBoxWithTransform(elem, addSVGElementFromJson, pathActions) { // TODO: Fix issue with rotated groups. Currently they work // fine in FF, but not in other browsers (same problem mentioned // in Issue 339 comment #2). - var bb = getBBox(elem); if (!bb) { @@ -8081,18 +8869,23 @@ if (angle || hasMatrixXForm) { var goodBb = false; + if (bBoxCanBeOptimizedOverNativeGetBBox(angle, hasMatrixXForm)) { // Get the BBox from the raw path for these elements // TODO: why ellipse and not circle var elemNames = ['ellipse', 'path', 'line', 'polyline', 'polygon']; + if (elemNames.includes(elem.tagName)) { - bb = goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions$$1); + goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions); + bb = goodBb; } else if (elem.tagName === 'rect') { // Look for radius var rx = elem.getAttribute('rx'); var ry = elem.getAttribute('ry'); + if (rx || ry) { - bb = goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions$$1); + goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions); + bb = goodBb; } } } @@ -8101,9 +8894,7 @@ var _transformListToTrans = transformListToTransform(tlist), matrix = _transformListToTrans.matrix; - bb = transformBox(bb.x, bb.y, bb.width, bb.height, matrix).aabox; - - // Old technique that was exceedingly slow with large documents. + bb = transformBox(bb.x, bb.y, bb.width, bb.height, matrix).aabox; // Old technique that was exceedingly slow with large documents. // // Accurate way to get BBox of rotated element in Firefox: // Put element in group and get its BBox @@ -8118,15 +8909,20 @@ // g.remove(); } } + return bb; }; + /** + * @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. + */ - // 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) { var sw = elem.getAttribute('stroke-width'); return !isNaN(sw) && elem.getAttribute('stroke') !== 'none' ? sw / 2 : 0; } - /** * @typedef {PlainObject} BBox * @property {Integer} x The x value @@ -8136,43 +8932,44 @@ */ /** - * Get the bounding box for one or more stroked and/or transformed elements + * Get the bounding box for one or more stroked and/or transformed elements. * @function module:utilities.getStrokedBBox * @param {Element[]} elems - Array with DOM elements to check * @param {module:utilities.EditorContext#addSVGElementFromJson} addSVGElementFromJson - Function to add the path element to the current layer. See canvas.addSVGElementFromJson * @param {module:path.pathActions} pathActions - If a transform exists, pathActions.resetOrientation() is used. See: canvas.pathActions. * @returns {module:utilities.BBoxObject|module:math.TransformedBox|DOMRect} A single bounding box object */ - var getStrokedBBox = function getStrokedBBox(elems, addSVGElementFromJson, pathActions$$1) { + + + var getStrokedBBox = function getStrokedBBox(elems, addSVGElementFromJson, pathActions) { if (!elems || !elems.length) { return false; } - var fullBb = void 0; + var fullBb; $$2.each(elems, function () { if (fullBb) { return; } + if (!this.parentNode) { return; } - fullBb = getBBoxWithTransform(this, addSVGElementFromJson, pathActions$$1); - }); - // This shouldn't ever happen... + fullBb = getBBoxWithTransform(this, addSVGElementFromJson, pathActions); + }); // This shouldn't ever happen... + if (fullBb === undefined) { return null; - } - - // fullBb doesn't include the stoke, so this does no good! + } // fullBb doesn't include the stoke, so this does no good! // if (elems.length == 1) return fullBb; + var maxX = fullBb.x + fullBb.width; var maxY = fullBb.y + fullBb.height; var minX = fullBb.x; - var minY = fullBb.y; + var minY = fullBb.y; // If only one elem, don't call the potentially slow getBBoxWithTransform method again. - // If only one elem, don't call the potentially slow getBBoxWithTransform method again. if (elems.length === 1) { var offset = getStrokeOffsetForBBox(elems[0]); minX -= offset; @@ -8181,12 +8978,14 @@ maxY += offset; } else { $$2.each(elems, function (i, elem) { - var curBb = getBBoxWithTransform(elem, addSVGElementFromJson, pathActions$$1); + var curBb = getBBoxWithTransform(elem, addSVGElementFromJson, pathActions); + if (curBb) { var _offset = getStrokeOffsetForBBox(elem); + minX = Math.min(minX, curBb.x - _offset); - minY = Math.min(minY, curBb.y - _offset); - // TODO: The old code had this test for max, but not min. I suspect this test should be for both min and max + minY = Math.min(minY, curBb.y - _offset); // TODO: The old code had this test for max, but not min. I suspect this test should be for both min and max + if (elem.nodeType === 1) { maxX = Math.max(maxX, curBb.x + curBb.width + _offset); maxY = Math.max(maxY, curBb.y + curBb.height + _offset); @@ -8201,42 +9000,42 @@ fullBb.height = maxY - minY; return fullBb; }; - /** * Get all elements that have a BBox (excludes ``, ``, etc). * Note that 0-opacity, off-screen etc elements are still considered "visible" - * for this function + * for this function. * @function module:utilities.getVisibleElements - * @param {Element} parent - The parent DOM element to search within + * @param {Element} parentElement - The parent DOM element to search within * @returns {Element[]} All "visible" elements. */ - var getVisibleElements = function getVisibleElements(parent) { - if (!parent) { - parent = $$2(editorContext_$1.getSVGContent()).children(); // Prevent layers from being included + + var getVisibleElements = function getVisibleElements(parentElement) { + if (!parentElement) { + parentElement = $$2(editorContext_$1.getSVGContent()).children(); // Prevent layers from being included } var contentElems = []; - $$2(parent).children().each(function (i, elem) { + $$2(parentElement).children().each(function (i, elem) { if (elem.getBBox) { contentElems.push(elem); } }); return contentElems.reverse(); }; - /** - * Get the bounding box for one or more stroked and/or transformed elements + * Get the bounding box for one or more stroked and/or transformed elements. * @function module:utilities.getStrokedBBoxDefaultVisible * @param {Element[]} elems - Array with DOM elements to check * @returns {module:utilities.BBoxObject} A single bounding box object */ + var getStrokedBBoxDefaultVisible = function getStrokedBBoxDefaultVisible(elems) { if (!elems) { elems = getVisibleElements(); } + return getStrokedBBox(elems, editorContext_$1.addSVGElementFromJson, editorContext_$1.pathActions); }; - /** * Get the rotation angle of the given transform list. * @function module:utilities.getRotationAngleFromTransformList @@ -8244,50 +9043,57 @@ * @param {boolean} toRad - When true returns the value in radians rather than degrees * @returns {Float} The angle in degrees or radians */ + var getRotationAngleFromTransformList = function getRotationAngleFromTransformList(tlist, toRad) { if (!tlist) { return 0; } // <svg> elements have no tlist + + var N = tlist.numberOfItems; + for (var i = 0; i < N; ++i) { var xform = tlist.getItem(i); + if (xform.type === 4) { return toRad ? xform.angle * Math.PI / 180.0 : xform.angle; } } + return 0.0; }; - /** - * Get the rotation angle of the given/selected DOM element + * Get the rotation angle of the given/selected DOM element. * @function module:utilities.getRotationAngle * @param {Element} [elem] - DOM element to get the angle for. Default to first of selected elements. * @param {boolean} [toRad=false] - When true returns the value in radians rather than degrees * @returns {Float} The angle in degrees or radians */ + var getRotationAngle = function getRotationAngle(elem, toRad) { - var selected = elem || editorContext_$1.getSelectedElements()[0]; - // find the rotation transform (if any) and set it + // eslint-disable-line import/no-mutable-exports + var selected = elem || editorContext_$1.getSelectedElements()[0]; // find the rotation transform (if any) and set it + var tlist = getTransformList(selected); return getRotationAngleFromTransformList(tlist, toRad); }; - /** - * Get the reference element associated with the given attribute value + * Get the reference element associated with the given attribute value. * @function module:utilities.getRefElem * @param {string} attrVal - The attribute value as a string * @returns {Element} Reference element */ + var getRefElem = function getRefElem(attrVal) { return getElem(getUrlFromAttr(attrVal).substr(1)); }; - /** * Get a DOM element by ID within the SVG root element. * @function module:utilities.getElem * @param {string} id - String with the element's new ID - * @returns {Element} + * @returns {?Element} */ + var getElem = supportsSelectors() ? function (id) { // querySelector lookup return svgroot_.querySelector('#' + id); @@ -8300,7 +9106,6 @@ // jQuery lookup: twice as slow as xpath in FF return $$2(svgroot_).find('[id=' + id + ']')[0]; }; - /** * Assigns multiple attributes to an element. * @function module:utilities.assignAttributes @@ -8310,54 +9115,35 @@ * @param {boolean} [unitCheck=false] - Boolean to indicate the need to use units.setUnitAttr * @returns {undefined} */ + var assignAttributes = function assignAttributes(elem, attrs, suspendLength, unitCheck) { - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; + var _arr = Object.entries(attrs); - try { - for (var _iterator = Object.entries(attrs)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var _ref4 = _step.value; + for (var _i = 0; _i < _arr.length; _i++) { + var _arr$_i = _slicedToArray(_arr[_i], 2), + key = _arr$_i[0], + value = _arr$_i[1]; - var _ref5 = slicedToArray(_ref4, 2); + var ns = key.substr(0, 4) === 'xml:' ? NS.XML : key.substr(0, 6) === 'xlink:' ? NS.XLINK : null; - var key = _ref5[0]; - var value = _ref5[1]; - - var ns = key.substr(0, 4) === 'xml:' ? NS.XML : key.substr(0, 6) === 'xlink:' ? NS.XLINK : null; - - if (ns) { - elem.setAttributeNS(ns, key, value); - } else if (!unitCheck) { - elem.setAttribute(key, value); - } else { - setUnitAttr(elem, key, value); - } - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } + if (ns) { + elem.setAttributeNS(ns, key, value); + } else if (!unitCheck) { + elem.setAttribute(key, value); + } else { + setUnitAttr(elem, key, value); } } }; - /** - * Remove unneeded (default) attributes, makes resulting SVG smaller + * Remove unneeded (default) attributes, making resulting SVG smaller. * @function module:utilities.cleanupElement * @param {Element} element - DOM element to clean up * @returns {undefined} */ + var cleanupElement = function cleanupElement(element) { - var defaults$$1 = { + var defaults = { 'fill-opacity': 1, 'stop-opacity': 1, opacity: 1, @@ -8373,68 +9159,74 @@ if (element.nodeName === 'ellipse') { // Ellipse elements require rx and ry attributes - delete defaults$$1.rx; - delete defaults$$1.ry; + delete defaults.rx; + delete defaults.ry; } - for (var attr in defaults$$1) { - var val = defaults$$1[attr]; + Object.entries(defaults).forEach(function (_ref4) { + var _ref5 = _slicedToArray(_ref4, 2), + attr = _ref5[0], + val = _ref5[1]; + if (element.getAttribute(attr) === String(val)) { element.removeAttribute(attr); } - } + }); }; - /** - * Round value to for snapping + * Round value to for snapping. * @function module:utilities.snapToGrid * @param {Float} value * @returns {Integer} */ + var snapToGrid = function snapToGrid(value) { var unit = editorContext_$1.getBaseUnit(); var stepSize = editorContext_$1.getSnappingStep(); + if (unit !== 'px') { stepSize *= getTypeMap()[unit]; } + value = Math.round(value / stepSize) * stepSize; return value; }; - /** - * Escapes special characters in a regular expression + * Escapes special characters in a regular expression. * @function module:utilities.regexEscape * @param {string} str * @returns {string} */ + var regexEscape = function regexEscape(str) { // From: http://phpjs.org/functions return String(str).replace(new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\-]', 'g'), '\\$&'); }; - /** - * Prevents default browser click behaviour on the given element + * Prevents default browser click behaviour on the given element. * @function module:utilities.preventClickDefault * @param {Element} img - The DOM element to prevent the click on * @returns {undefined} */ + var preventClickDefault = function preventClickDefault(img) { $$2(img).click(function (e) { e.preventDefault(); }); }; - /** * @callback module:utilities.GetNextID * @returns {string} The ID */ + /** - * Create a clone of an element, updating its ID and its children's IDs when needed + * Create a clone of an element, updating its ID and its children's IDs when needed. * @function module:utilities.copyElem * @param {Element} el - DOM element to clone * @param {module:utilities.GetNextID} getNextId - The getter of the next unique ID. * @returns {Element} The cloned element */ + var copyElem = function copyElem(el, getNextId) { // manually create a copy of the element var newEl = document.createElementNS(el.namespaceURI, el.nodeName); @@ -8442,29 +9234,30 @@ if (attr.localName !== '-moz-math-font-style') { newEl.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value); } - }); - // set the copied element's new id - newEl.removeAttribute('id'); - newEl.id = getNextId(); + }); // set the copied element's new id - // Opera's "d" value needs to be reset for Opera/Win/non-EN + newEl.removeAttribute('id'); + newEl.id = getNextId(); // Opera's "d" value needs to be reset for Opera/Win/non-EN // Also needed for webkit (else does not keep curved segments on clone) + if (isWebkit() && el.nodeName === 'path') { var fixedD = convertPath(el); newEl.setAttribute('d', fixedD); - } + } // now create copies of all children + - // now create copies of all children $$2.each(el.childNodes, function (i, child) { switch (child.nodeType) { case 1: // element node newEl.append(copyElem(child, getNextId)); break; + case 3: // text node newEl.textContent = child.nodeValue; break; + default: break; } @@ -8481,8 +9274,18 @@ return newEl; }; + /** + * Whether a value is `null` or `undefined`. + * @param {Any} val + * @returns {boolean} + */ + + var isNullish = function isNullish(val) { + return val === null || val === undefined; + }; /* globals jQuery */ + /** * Adds context menu functionality * @module contextmenu @@ -8491,51 +9294,51 @@ */ // Dependencies: // 1) jQuery (for dom injection of context menus) - var $$3 = jQuery; - var contextMenuExtensions = {}; - /** * @function module:contextmenu.hasCustomHandler * @param {string} handlerKey * @returns {boolean} */ + var hasCustomHandler = function hasCustomHandler(handlerKey) { return Boolean(contextMenuExtensions[handlerKey]); }; - /** * @function module:contextmenu.getCustomHandler * @param {string} handlerKey * @returns {module:contextmenu.MenuItemAction} */ + var getCustomHandler = function getCustomHandler(handlerKey) { return contextMenuExtensions[handlerKey].action; }; - /** * @param {module:contextmenu.MenuItem} menuItem * @returns {undefined} */ + var injectExtendedContextMenuItemIntoDom = function injectExtendedContextMenuItemIntoDom(menuItem) { if (!Object.keys(contextMenuExtensions).length) { // all menuItems appear at the bottom of the menu in their own container. // if this is the first extension menu we need to add the separator. $$3('#cmenu_canvas').append("<li class='separator'>"); } + var shortcut = menuItem.shortcut || ''; $$3('#cmenu_canvas').append("<li class='disabled'><a href='#" + menuItem.id + "'>" + menuItem.label + "<span class='shortcut'>" + shortcut + '</span></a></li>'); }; - /** * @function module:contextmenu.injectExtendedContextMenuItemsIntoDom * @returns {undefined} */ + + var injectExtendedContextMenuItemsIntoDom = function injectExtendedContextMenuItemsIntoDom() { - for (var menuItem in contextMenuExtensions) { - injectExtendedContextMenuItemIntoDom(contextMenuExtensions[menuItem]); - } + Object.values(contextMenuExtensions).forEach(function (menuItem) { + injectExtendedContextMenuItemIntoDom(menuItem); + }); }; // MIT License @@ -8545,11 +9348,24 @@ * @module importModule */ + /** + * Converts a possible relative URL into an absolute one. + * @param {string} url + * @returns {string} + */ function toAbsoluteURL(url) { var a = document.createElement('a'); a.setAttribute('href', url); // <a href="hoge.html"> + return a.cloneNode(false).href; // -> "http://example.com/hoge.html" } + /** + * Add any of the whitelisted attributes to the script tag. + * @param {HTMLScriptElement} script + * @param {PlainObject.<string, string>} atts + * @returns {undefined} + */ + function addScriptAtts(script, atts) { ['id', 'class', 'type'].forEach(function (prop) { @@ -8557,85 +9373,86 @@ script[prop] = atts[prop]; } }); - } + } // Additions by Brett - // Additions by Brett /** * @typedef {PlainObject} module:importModule.ImportConfig * @property {string} global The variable name to set on `window` (when not using the modular version) * @property {boolean} [returnDefault=false] */ + /** * @function module:importModule.importSetGlobalDefault - * @param {string} url + * @param {string|string[]} url * @param {module:importModule.ImportConfig} config - * @returns {*} The return depends on the export of the targeted module. + * @returns {Promise} The value to which it resolves depends on the export of the targeted module. */ - var importSetGlobalDefault = function () { - var _ref = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(url, config) { + + + function importSetGlobalDefault(url, config) { + return importSetGlobal(url, _extends({}, config, { + returnDefault: true + })); + } + /** + * @function module:importModule.importSetGlobal + * @param {string|string[]} url + * @param {module:importModule.ImportConfig} config + * @returns {Promise} The promise resolves to either an `ArbitraryModule` or + * any other value depends on the export of the targeted module. + */ + + function importSetGlobal(_x, _x2) { + return _importSetGlobal.apply(this, arguments); + } + /** + * + * @author Brett Zamir (other items are from `dynamic-import-polyfill`) + * @param {string|string[]} url + * @param {PlainObject} [atts={}] + * @returns {Promise} Resolves to `undefined` or rejects with an `Error` upon a + * script loading error + */ + + function _importSetGlobal() { + _importSetGlobal = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee(url, _ref) { + var glob, returnDefault, modularVersion; return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: - return _context.abrupt('return', importSetGlobal(url, _extends({}, config, { returnDefault: true }))); + glob = _ref.global, returnDefault = _ref.returnDefault; + // Todo: Replace calls to this function with `import()` when supported + modularVersion = !('svgEditor' in window) || !window.svgEditor || window.svgEditor.modules !== false; - case 1: - case 'end': + if (!modularVersion) { + _context.next = 4; + break; + } + + return _context.abrupt("return", importModule(url, undefined, { + returnDefault: returnDefault + })); + + case 4: + _context.next = 6; + return importScript(url); + + case 6: + return _context.abrupt("return", window[glob]); + + case 7: + case "end": return _context.stop(); } } }, _callee, this); })); + return _importSetGlobal.apply(this, arguments); + } - return function importSetGlobalDefault(_x, _x2) { - return _ref.apply(this, arguments); - }; - }(); - /** - * @function module:importModule.importSetGlobal - * @param {string} url - * @param {module:importModule.ImportConfig} config - * @returns {ArbitraryModule|*} The return depends on the export of the targeted module. - */ - var importSetGlobal = function () { - var _ref3 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(url, _ref2) { - var global = _ref2.global, - returnDefault = _ref2.returnDefault; - var modularVersion; - return regeneratorRuntime.wrap(function _callee2$(_context2) { - while (1) { - switch (_context2.prev = _context2.next) { - case 0: - // Todo: Replace calls to this function with `import()` when supported - modularVersion = !('svgEditor' in window) || !window.svgEditor || window.svgEditor.modules !== false; - - if (!modularVersion) { - _context2.next = 3; - break; - } - - return _context2.abrupt('return', importModule(url, undefined, { returnDefault: returnDefault })); - - case 3: - _context2.next = 5; - return importScript(url); - - case 5: - return _context2.abrupt('return', window[global]); - - case 6: - case 'end': - return _context2.stop(); - } - } - }, _callee2, this); - })); - - return function importSetGlobal(_x3, _x4) { - return _ref3.apply(this, arguments); - }; - }(); - // Addition by Brett function importScript(url) { var atts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; @@ -8644,77 +9461,314 @@ return importScript(u, atts); })); } + return new Promise(function (resolve, reject) { + // eslint-disable-line promise/avoid-new var script = document.createElement('script'); + /** + * + * @returns {undefined} + */ + + function scriptOnError() { + reject(new Error("Failed to import: ".concat(url))); + destructor(); + } + /** + * + * @returns {undefined} + */ + + + function scriptOnLoad() { + resolve(); + destructor(); + } + var destructor = function destructor() { - script.onerror = null; - script.onload = null; + script.removeEventListener('error', scriptOnError); + script.removeEventListener('load', scriptOnLoad); script.remove(); script.src = ''; }; + script.defer = 'defer'; addScriptAtts(script, atts); - script.onerror = function () { - reject(new Error('Failed to import: ' + url)); - destructor(); - }; - script.onload = function () { - resolve(); - destructor(); - }; + script.addEventListener('error', scriptOnError); + script.addEventListener('load', scriptOnLoad); script.src = url; - document.head.append(script); }); } + /** + * + * @param {string|string[]} url + * @param {PlainObject} [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. + */ function importModule(url) { var atts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - var _ref4 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, - _ref4$returnDefault = _ref4.returnDefault, - returnDefault = _ref4$returnDefault === undefined ? false : _ref4$returnDefault; + var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, + _ref2$returnDefault = _ref2.returnDefault, + returnDefault = _ref2$returnDefault === void 0 ? false : _ref2$returnDefault; if (Array.isArray(url)) { return Promise.all(url.map(function (u) { return importModule(u, atts); })); } + return new Promise(function (resolve, reject) { + // eslint-disable-line promise/avoid-new var vector = '$importModule$' + Math.random().toString(32).slice(2); var script = document.createElement('script'); + /** + * + * @returns {undefined} + */ + + function scriptOnError() { + reject(new Error("Failed to import: ".concat(url))); + destructor(); + } + /** + * + * @returns {undefined} + */ + + + function scriptOnLoad() { + resolve(window[vector]); + destructor(); + } + var destructor = function destructor() { delete window[vector]; - script.onerror = null; - script.onload = null; + script.removeEventListener('error', scriptOnError); + script.removeEventListener('load', scriptOnLoad); script.remove(); URL.revokeObjectURL(script.src); script.src = ''; }; + addScriptAtts(script, atts); script.defer = 'defer'; script.type = 'module'; - script.onerror = function () { - reject(new Error('Failed to import: ' + url)); - destructor(); - }; - script.onload = function () { - resolve(window[vector]); - destructor(); - }; + script.addEventListener('error', scriptOnError); + script.addEventListener('load', scriptOnLoad); var absURL = toAbsoluteURL(url); - var loader = 'import * as m from \'' + absURL.replace(/'/g, "\\'") + '\'; window.' + vector + ' = ' + (returnDefault ? 'm.default || ' : '') + 'm;'; // export Module - var blob = new Blob([loader], { type: 'text/javascript' }); - script.src = URL.createObjectURL(blob); + var loader = "import * as m from '".concat(absURL.replace(/'/g, "\\'"), "'; window.").concat(vector, " = ").concat(returnDefault ? 'm.default || ' : '', "m;"); // export Module + var blob = new Blob([loader], { + type: 'text/javascript' + }); + script.src = URL.createObjectURL(blob); document.head.append(script); }); } - /* globals jQuery */ + /** + * @module jQueryPluginDBox + */ + + /** + * @param {external:jQuery} $ + * @param {PlainObject} [strings] + * @param {PlainObject} [strings.ok] + * @param {PlainObject} [strings.cancel] + * @returns {external:jQuery} + */ + function jQueryPluginDBox($) { + var strings = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { + ok: 'Ok', + cancel: 'Cancel' + }; + // This sets up alternative dialog boxes. They mostly work the same way as + // their UI counterparts, expect instead of returning the result, a callback + // needs to be included that returns the result as its first parameter. + // In the future we may want to add additional types of dialog boxes, since + // they should be easy to handle this way. + $('#dialog_container').draggable({ + cancel: '#dialog_content, #dialog_buttons *', + containment: 'window' + }).css('position', 'absolute'); + var box = $('#dialog_box'), + btnHolder = $('#dialog_buttons'), + dialogContent = $('#dialog_content'); + /** + * Resolves to `false` (if cancelled), for prompts and selects + * without checkboxes, it resolves to the value of the form control. For other + * types without checkboxes, it resolves to `true`. For checkboxes, it resolves + * to an object with the `response` key containing the same value as the previous + * mentioned (string or `true`) and a `checked` (boolean) property. + * @typedef {Promise} module:jQueryPluginDBox.PromiseResult + */ + + /** + * @typedef {PlainObject} module:jQueryPluginDBox.SelectOption + * @property {string} text + * @property {string} value + */ + + /** + * @typedef {PlainObject} module:jQueryPluginDBox.CheckboxInfo + * @property {string} label Label for the checkbox + * @property {string} value Value of the checkbox + * @property {string} tooltip Tooltip on the checkbox label + * @property {boolean} checked Whether the checkbox is checked by default + */ + + /** + * Triggered upon a change of value for the select pull-down. + * @callback module:jQueryPluginDBox.SelectChangeListener + * @returns {undefined} + */ + + /** + * @param {"alert"|"prompt"|"select"|"process"} type + * @param {string} msg + * @param {string} [defaultVal] + * @param {module:jQueryPluginDBox.SelectOption[]} [opts] + * @param {module:jQueryPluginDBox.SelectChangeListener} [changeListener] + * @param {module:jQueryPluginDBox.CheckboxInfo} [checkbox] + * @returns {jQueryPluginDBox.PromiseResult} + */ + + function dbox(type, msg, defaultVal, opts, changeListener, checkbox) { + dialogContent.html('<p>' + msg.replace(/\n/g, '</p><p>') + '</p>').toggleClass('prompt', type === 'prompt'); + btnHolder.empty(); + var ok = $('<input type="button" value="' + strings.ok + '">').appendTo(btnHolder); + return new Promise(function (resolve, reject) { + // eslint-disable-line promise/avoid-new + if (type !== 'alert') { + $('<input type="button" value="' + strings.cancel + '">').appendTo(btnHolder).click(function () { + box.hide(); + resolve(false); + }); + } + + var ctrl, chkbx; + + if (type === 'prompt') { + ctrl = $('<input type="text">').prependTo(btnHolder); + ctrl.val(defaultVal || ''); + ctrl.bind('keydown', 'return', function () { + ok.click(); + }); + } else if (type === 'select') { + var div = $('<div style="text-align:center;">'); + ctrl = $('<select>').appendTo(div); + + if (checkbox) { + var label = $('<label>').text(checkbox.label); + chkbx = $('<input type="checkbox">').appendTo(label); + chkbx.val(checkbox.value); + + if (checkbox.tooltip) { + label.attr('title', checkbox.tooltip); + } + + chkbx.prop('checked', Boolean(checkbox.checked)); + div.append($('<div>').append(label)); + } + + $.each(opts || [], function (opt, val) { + if (_typeof(val) === 'object') { + ctrl.append($('<option>').val(val.value).html(val.text)); + } else { + ctrl.append($('<option>').html(val)); + } + }); + dialogContent.append(div); + + if (defaultVal) { + ctrl.val(defaultVal); + } + + if (changeListener) { + ctrl.bind('change', 'return', changeListener); + } + + ctrl.bind('keydown', 'return', function () { + ok.click(); + }); + } else if (type === 'process') { + ok.hide(); + } + + box.show(); + ok.click(function () { + box.hide(); + var response = type === 'prompt' || type === 'select' ? ctrl.val() : true; + + if (chkbx) { + resolve({ + response: response, + checked: chkbx.prop('checked') + }); + return; + } + + resolve(response); + }).focus(); + + if (type === 'prompt' || type === 'select') { + ctrl.focus(); + } + }); + } + /** + * @param {string} msg Message to alert + * @returns {jQueryPluginDBox.PromiseResult} + */ + + + $.alert = function (msg) { + return dbox('alert', msg); + }; + /** + * @param {string} msg Message for which to ask confirmation + * @returns {jQueryPluginDBox.PromiseResult} + */ + + + $.confirm = function (msg) { + return dbox('confirm', msg); + }; + /** + * @param {string} msg Message to indicate upon cancelable indicator + * @returns {jQueryPluginDBox.PromiseResult} + */ + + + $.process_cancel = function (msg) { + return dbox('process', msg); + }; + /** + * @param {string} msg Message to accompany the prompt + * @param {string} [defaultText=''] The default text to show for the prompt + * @returns {jQueryPluginDBox.PromiseResult} + */ + + + $.prompt = function (msg) { + var defaultText = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + return dbox('prompt', msg, defaultText); + }; + + $.select = function (msg, opts, changeListener, txt, checkbox) { + return dbox('select', msg, txt, opts, changeListener, checkbox); + }; + + return $; + } var $$4 = jQuery; - /** * This class encapsulates the concept of a layer in the drawing. It can be constructed with * an existing group element or, with three parameters, will create a new layer group element. @@ -8726,7 +9780,9 @@ * @memberof module:layer */ - var Layer = function () { + var Layer = + /*#__PURE__*/ + function () { /** * @param {string} name - Layer name * @param {SVGGElement|null} group - An existing SVG group element or null. @@ -8737,7 +9793,7 @@ * a new layer to the document. */ function Layer(name, group, svgElem) { - classCallCheck(this, Layer); + _classCallCheck(this, Layer); this.name_ = name; this.group_ = svgElem ? null : group; @@ -8749,6 +9805,7 @@ var layerTitle = svgdoc.createElementNS(NS.SVG, 'title'); layerTitle.textContent = name; this.group_.append(layerTitle); + if (group) { $$4(group).after(this.group_); } else { @@ -8760,55 +9817,49 @@ walkTree(this.group_, function (e) { e.setAttribute('style', 'pointer-events:inherit'); }); - this.group_.setAttribute('style', svgElem ? 'pointer-events:all' : 'pointer-events:none'); } - /** * Get the layer's name. * @returns {string} The layer name */ - createClass(Layer, [{ - key: 'getName', + _createClass(Layer, [{ + key: "getName", value: function getName() { return this.name_; } - /** * Get the group element for this layer. * @returns {SVGGElement} The layer SVG group */ }, { - key: 'getGroup', + key: "getGroup", value: function getGroup() { return this.group_; } - /** * Active this layer so it takes pointer events. * @returns {undefined} */ }, { - key: 'activate', + key: "activate", value: function activate() { this.group_.setAttribute('style', 'pointer-events:all'); } - /** * Deactive this layer so it does NOT take pointer events. * @returns {undefined} */ }, { - key: 'deactivate', + key: "deactivate", value: function deactivate() { this.group_.setAttribute('style', 'pointer-events:none'); } - /** * Set this layer visible or hidden based on 'visible' parameter. * @param {boolean} visible - If true, make visible; otherwise, hide it. @@ -8816,41 +9867,41 @@ */ }, { - key: 'setVisible', + key: "setVisible", value: function setVisible(visible) { var expected = visible === undefined || visible ? 'inline' : 'none'; var oldDisplay = this.group_.getAttribute('display'); + if (oldDisplay !== expected) { this.group_.setAttribute('display', expected); } } - /** * Is this layer visible? * @returns {boolean} True if visible. */ }, { - key: 'isVisible', + key: "isVisible", value: function isVisible() { return this.group_.getAttribute('display') !== 'none'; } - /** * Get layer opacity. * @returns {Float} Opacity value. */ }, { - key: 'getOpacity', + key: "getOpacity", value: function getOpacity() { var opacity = this.group_.getAttribute('opacity'); - if (opacity === null || opacity === undefined) { + + if (isNullish(opacity)) { return 1; } + return parseFloat(opacity); } - /** * Sets the opacity of this layer. If opacity is not a value between 0.0 and 1.0, * nothing happens. @@ -8859,13 +9910,12 @@ */ }, { - key: 'setOpacity', + key: "setOpacity", value: function setOpacity(opacity) { if (typeof opacity === 'number' && opacity >= 0.0 && opacity <= 1.0) { this.group_.setAttribute('opacity', opacity); } } - /** * Append children to this layer. * @param {SVGGElement} children - The children to append to this layer. @@ -8873,30 +9923,31 @@ */ }, { - key: 'appendChildren', + key: "appendChildren", value: function appendChildren(children) { for (var i = 0; i < children.length; ++i) { this.group_.append(children[i]); } } - /** * @returns {SVGTitleElement|null} */ }, { - key: 'getTitleElement', + key: "getTitleElement", value: function getTitleElement() { var len = this.group_.childNodes.length; + for (var i = 0; i < len; ++i) { var child = this.group_.childNodes.item(i); + if (child && child.tagName === 'title') { return child; } } + return null; } - /** * Set the name of this layer. * @param {string} name - The new name. @@ -8905,32 +9956,36 @@ */ }, { - key: 'setName', + key: "setName", value: function setName(name, hrService) { var previousName = this.name_; - name = toXml(name); - // now change the underlying title element contents + name = toXml(name); // now change the underlying title element contents + var title = this.getTitleElement(); + if (title) { $$4(title).empty(); title.textContent = name; this.name_ = name; + if (hrService) { - hrService.changeElement(title, { '#text': previousName }); + hrService.changeElement(title, { + '#text': previousName + }); } + return this.name_; } + return null; } - /** * Remove this layer's group from the DOM. No more functions on group can be called after this. - * @param {SVGGElement} children - The children to append to this layer. * @returns {SVGGElement} The layer SVG group that was just removed. */ }, { - key: 'removeGroup', + key: "removeGroup", value: function removeGroup() { var parent = this.group_.parentNode; var group = parent.removeChild(this.group_); @@ -8938,6 +9993,7 @@ return group; } }]); + return Layer; }(); /** @@ -8946,34 +10002,28 @@ Layer.CLASS_NAME = 'layer'; - /** * @property {RegExp} CLASS_REGEX - Used to test presence of class Layer.CLASS_NAME */ - Layer.CLASS_REGEX = new RegExp('(\\s|^)' + Layer.CLASS_NAME + '(\\s|$)'); + Layer.CLASS_REGEX = new RegExp('(\\s|^)' + Layer.CLASS_NAME + '(\\s|$)'); /** * Add class `Layer.CLASS_NAME` to the element (usually `class='layer'`). * * @param {SVGGElement} elem - The SVG element to update * @returns {undefined} */ + function addLayerClass(elem) { var classes = elem.getAttribute('class'); - if (classes === null || classes === undefined || !classes.length) { + + if (isNullish(classes) || !classes.length) { elem.setAttribute('class', Layer.CLASS_NAME); } else if (!Layer.CLASS_REGEX.test(classes)) { elem.setAttribute('class', classes + ' ' + Layer.CLASS_NAME); } } - /** - * HistoryRecordingService component of history - * @module history - * @license MIT - * @copyright 2016 Flint O'Brien - */ - /** * History recording service. * @@ -9007,20 +10057,21 @@ * @memberof module:history */ - var HistoryRecordingService = function () { + var HistoryRecordingService = + /*#__PURE__*/ + function () { /** * @param {history.UndoManager|null} undoManager - The undo manager. * A value of `null` is valid for cases where no history recording is required. * See singleton: {@link module:history.HistoryRecordingService.HistoryRecordingService.NO_HISTORY} */ function HistoryRecordingService(undoManager) { - classCallCheck(this, HistoryRecordingService); + _classCallCheck(this, HistoryRecordingService); this.undoManager_ = undoManager; this.currentBatchCommand_ = null; this.batchCommandStack_ = []; } - /** * Start a batch command so multiple commands can recorded as a single history command. * Requires a corresponding call to endBatchCommand. Start and end commands can be nested. @@ -9030,41 +10081,41 @@ */ - createClass(HistoryRecordingService, [{ - key: 'startBatchCommand', + _createClass(HistoryRecordingService, [{ + key: "startBatchCommand", value: function startBatchCommand(text) { if (!this.undoManager_) { return this; } + this.currentBatchCommand_ = new BatchCommand(text); this.batchCommandStack_.push(this.currentBatchCommand_); return this; } - /** * End a batch command and add it to the history or a parent batch command. * @returns {module:history.HistoryRecordingService} */ }, { - key: 'endBatchCommand', + key: "endBatchCommand", value: function endBatchCommand() { if (!this.undoManager_) { return this; } + if (this.currentBatchCommand_) { var batchCommand = this.currentBatchCommand_; this.batchCommandStack_.pop(); - var length = this.batchCommandStack_.length; - - this.currentBatchCommand_ = length ? this.batchCommandStack_[length - 1] : null; + var len = this.batchCommandStack_.length; + this.currentBatchCommand_ = len ? this.batchCommandStack_[len - 1] : null; this.addCommand_(batchCommand); } + return this; } - /** - * Add a MoveElementCommand to the history or current batch command + * Add a `MoveElementCommand` to the history or current batch command. * @param {Element} elem - The DOM element that was moved * @param {Element} oldNextSibling - The element's next sibling before it was moved * @param {Element} oldParent - The element's parent before it was moved @@ -9073,34 +10124,34 @@ */ }, { - key: 'moveElement', + key: "moveElement", value: function moveElement(elem, oldNextSibling, oldParent, text) { if (!this.undoManager_) { return this; } + this.addCommand_(new MoveElementCommand(elem, oldNextSibling, oldParent, text)); return this; } - /** - * Add an InsertElementCommand to the history or current batch command + * Add an `InsertElementCommand` to the history or current batch command. * @param {Element} elem - The DOM element that was added * @param {string} [text] - An optional string visible to user related to this change * @returns {module:history.HistoryRecordingService} */ }, { - key: 'insertElement', + key: "insertElement", value: function insertElement(elem, text) { if (!this.undoManager_) { return this; } + this.addCommand_(new InsertElementCommand(elem, text)); return this; } - /** - * Add a RemoveElementCommand to the history or current batch command + * Add a `RemoveElementCommand` to the history or current batch command. * @param {Element} elem - The DOM element that was removed * @param {Element} oldNextSibling - The element's next sibling before it was removed * @param {Element} oldParent - The element's parent before it was removed @@ -9109,17 +10160,17 @@ */ }, { - key: 'removeElement', + key: "removeElement", value: function removeElement(elem, oldNextSibling, oldParent, text) { if (!this.undoManager_) { return this; } + this.addCommand_(new RemoveElementCommand(elem, oldNextSibling, oldParent, text)); return this; } - /** - * Add a ChangeElementCommand to the history or current batch command + * Add a `ChangeElementCommand` to the history or current batch command. * @param {Element} elem - The DOM element that was changed * @param {module:history.CommandAttributes} attrs - An object with the attributes to be changed and the values they had *before* the change * @param {string} [text] - An optional string visible to user related to this change @@ -9127,35 +10178,39 @@ */ }, { - key: 'changeElement', + key: "changeElement", value: function changeElement(elem, attrs, text) { if (!this.undoManager_) { return this; } + this.addCommand_(new ChangeElementCommand(elem, attrs, text)); return this; } - /** * Private function to add a command to the history or current batch command. * @private * @param {Command} cmd - * @returns {module:history.HistoryRecordingService} + * @returns {module:history.HistoryRecordingService|undefined} */ }, { - key: 'addCommand_', + key: "addCommand_", value: function addCommand_(cmd) { if (!this.undoManager_) { return this; } + if (this.currentBatchCommand_) { this.currentBatchCommand_.addSubCommand(cmd); } else { this.undoManager_.addCommandToHistory(cmd); } + + return undefined; } }]); + return HistoryRecordingService; }(); /** @@ -9166,59 +10221,60 @@ HistoryRecordingService.NO_HISTORY = new HistoryRecordingService(); - /* globals jQuery */ - var $$5 = jQuery; - var visElems$1 = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use'.split(','); - var RandomizeModes = { LET_DOCUMENT_DECIDE: 0, ALWAYS_RANDOMIZE: 1, NEVER_RANDOMIZE: 2 }; - var randIds = RandomizeModes.LET_DOCUMENT_DECIDE; - // Array with current disabled elements (for in-group editing) - var disabledElems = []; + var randIds = RandomizeModes.LET_DOCUMENT_DECIDE; // Array with current disabled elements (for in-group editing) + var disabledElems = []; /** * Get a HistoryRecordingService. * @param {module:history.HistoryRecordingService} [hrService] - if exists, return it instead of creating a new service. * @returns {module:history.HistoryRecordingService} */ + function historyRecordingService(hrService) { return hrService || new HistoryRecordingService(canvas_.undoMgr); } - /** * Find the layer name in a group element. * @param {Element} group The group element to search in. * @returns {string} The layer name or empty string. */ + + function findLayerNameInGroup(group) { - return $$5('title', group).text() || (isOpera() && group.querySelectorAll - // Hack for Opera 10.60 + return $$5('title', group).text() || (isOpera() && group.querySelectorAll // Hack for Opera 10.60 ? $$5(group.querySelectorAll('title')).text() : ''); } - /** * Given a set of names, return a new unique name. * @param {string[]} existingLayerNames - Existing layer names. * @returns {string} - The new name. */ + + function getNewLayerName(existingLayerNames) { - var i = 1; - // TODO(codedread): What about internationalization of "Layer"? + var i = 1; // TODO(codedread): What about internationalization of "Layer"? + while (existingLayerNames.includes('Layer ' + i)) { i++; } + return 'Layer ' + i; } - /** - * This class encapsulates the concept of a SVG-edit drawing + * This class encapsulates the concept of a SVG-edit drawing. */ - var Drawing = function () { + + + var Drawing = + /*#__PURE__*/ + function () { /** * @param {SVGSVGElement} svgElem - The SVG DOM Element that this JS object * encapsulates. If the svgElem has a se:nonce attribute on it, then @@ -9227,44 +10283,44 @@ * @throws {Error} If not initialized with an SVG element */ function Drawing(svgElem, optIdPrefix) { - classCallCheck(this, Drawing); + _classCallCheck(this, Drawing); if (!svgElem || !svgElem.tagName || !svgElem.namespaceURI || svgElem.tagName !== 'svg' || svgElem.namespaceURI !== NS.SVG) { throw new Error('Error: svgedit.draw.Drawing instance initialized without a <svg> element'); } - /** * The SVG DOM Element that represents this drawing. * @type {SVGSVGElement} */ - this.svgElem_ = svgElem; + + this.svgElem_ = svgElem; /** * The latest object number used in this drawing. * @type {Integer} */ - this.obj_num = 0; + this.obj_num = 0; /** * The prefix to prepend to each element id in the drawing. * @type {string} */ - this.idPrefix = optIdPrefix || 'svg_'; + this.idPrefix = optIdPrefix || 'svg_'; /** * An array of released element ids to immediately reuse. * @type {Integer[]} */ - this.releasedNums = []; + this.releasedNums = []; /** * The z-ordered array of Layer objects. Each layer has a name * and group element. * The first layer is the one at the bottom of the rendering. * @type {Layer[]} */ - this.all_layers = []; + this.all_layers = []; /** * Map of all_layers by name. * @@ -9273,142 +10329,139 @@ * * @type {PlainObject.<string, Layer>} */ - this.layer_map = {}; + this.layer_map = {}; /** * The current layer being used. * @type {Layer} */ - this.current_layer = null; + this.current_layer = null; /** * The nonce to use to uniquely identify elements across drawings. * @type {!String} */ + this.nonce_ = ''; - var n = this.svgElem_.getAttributeNS(NS.SE, 'nonce'); - // If already set in the DOM, use the nonce throughout the document + var n = this.svgElem_.getAttributeNS(NS.SE, 'nonce'); // If already set in the DOM, use the nonce throughout the document // else, if randomizeIds(true) has been called, create and set the nonce. - if (!!n && randIds !== RandomizeModes.NEVER_RANDOMIZE) { + + if (n && randIds !== RandomizeModes.NEVER_RANDOMIZE) { this.nonce_ = n; } else if (randIds === RandomizeModes.ALWAYS_RANDOMIZE) { this.setNonce(Math.floor(Math.random() * 100001)); } } - /** * @param {string} id Element ID to retrieve * @returns {Element} SVG element within the root SVGSVGElement */ - createClass(Drawing, [{ - key: 'getElem_', + _createClass(Drawing, [{ + key: "getElem_", value: function getElem_(id) { if (this.svgElem_.querySelector) { // querySelector lookup return this.svgElem_.querySelector('#' + id); - } - // jQuery lookup: twice as slow as xpath in FF + } // jQuery lookup: twice as slow as xpath in FF + + return $$5(this.svgElem_).find('[id=' + id + ']')[0]; } - /** * @returns {SVGSVGElement} */ }, { - key: 'getSvgElem', + key: "getSvgElem", value: function getSvgElem() { return this.svgElem_; } - /** * @returns {!(string|Integer)} The previously set nonce */ }, { - key: 'getNonce', + key: "getNonce", value: function getNonce() { return this.nonce_; } - /** * @param {!(string|Integer)} n The nonce to set * @returns {undefined} */ }, { - key: 'setNonce', + key: "setNonce", value: function setNonce(n) { this.svgElem_.setAttributeNS(NS.XMLNS, 'xmlns:se', NS.SE); this.svgElem_.setAttributeNS(NS.SE, 'se:nonce', n); this.nonce_ = n; } - /** - * Clears any previously set nonce + * Clears any previously set nonce. * @returns {undefined} */ }, { - key: 'clearNonce', + key: "clearNonce", value: function clearNonce() { // We deliberately leave any se:nonce attributes alone, // we just don't use it to randomize ids. this.nonce_ = ''; } - /** * Returns the latest object id as a string. * @returns {string} The latest object Id. */ }, { - key: 'getId', + key: "getId", value: function getId() { return this.nonce_ ? this.idPrefix + this.nonce_ + '_' + this.obj_num : this.idPrefix + this.obj_num; } - /** * Returns the next object Id as a string. * @returns {string} The next object Id to use. */ }, { - key: 'getNextId', + key: "getNextId", value: function getNextId() { var oldObjNum = this.obj_num; - var restoreOldObjNum = false; - - // If there are any released numbers in the release stack, + var restoreOldObjNum = false; // If there are any released numbers in the release stack, // use the last one instead of the next obj_num. // We need to temporarily use obj_num as that is what getId() depends on. + if (this.releasedNums.length > 0) { this.obj_num = this.releasedNums.pop(); restoreOldObjNum = true; } else { // If we are not using a released id, then increment the obj_num. this.obj_num++; - } + } // Ensure the ID does not exist. + - // Ensure the ID does not exist. var id = this.getId(); + while (this.getElem_(id)) { if (restoreOldObjNum) { this.obj_num = oldObjNum; restoreOldObjNum = false; } + this.obj_num++; id = this.getId(); - } - // Restore the old object number if required. + } // Restore the old object number if required. + + if (restoreOldObjNum) { this.obj_num = oldObjNum; } + return id; } - /** * Releases the object Id, letting it be used as the next id in getNextId(). * This method DOES NOT remove any elements from the DOM, it is expected @@ -9418,51 +10471,48 @@ */ }, { - key: 'releaseId', + key: "releaseId", value: function releaseId(id) { // confirm if this is a valid id for this Document, else return false var front = this.idPrefix + (this.nonce_ ? this.nonce_ + '_' : ''); + if (typeof id !== 'string' || !id.startsWith(front)) { return false; - } - // extract the obj_num of this id - var num = parseInt(id.substr(front.length), 10); + } // extract the obj_num of this id - // if we didn't get a positive number or we already released this number + + var num = parseInt(id.substr(front.length)); // if we didn't get a positive number or we already released this number // then return false. + if (typeof num !== 'number' || num <= 0 || this.releasedNums.includes(num)) { return false; - } + } // push the released number into the released queue + - // push the released number into the released queue this.releasedNums.push(num); - return true; } - /** * Returns the number of layers in the current drawing. * @returns {Integer} The number of layers in the current drawing. */ }, { - key: 'getNumLayers', + key: "getNumLayers", value: function getNumLayers() { return this.all_layers.length; } - /** - * Check if layer with given name already exists + * Check if layer with given name already exists. * @param {string} name - The layer name to check * @returns {boolean} */ }, { - key: 'hasLayer', + key: "hasLayer", value: function hasLayer(name) { return this.layer_map[name] !== undefined; } - /** * Returns the name of the ith layer. If the index is out of range, an empty string is returned. * @param {Integer} i - The zero-based index of the layer you are querying. @@ -9470,33 +10520,31 @@ */ }, { - key: 'getLayerName', + key: "getLayerName", value: function getLayerName(i) { return i >= 0 && i < this.getNumLayers() ? this.all_layers[i].getName() : ''; } - /** * @returns {SVGGElement|null} The SVGGElement representing the current layer. */ }, { - key: 'getCurrentLayer', + key: "getCurrentLayer", value: function getCurrentLayer() { return this.current_layer ? this.current_layer.getGroup() : null; } - /** * Get a layer by name. + * @param {string} name * @returns {SVGGElement} The SVGGElement representing the named layer or null. */ }, { - key: 'getLayerByName', + key: "getLayerByName", value: function getLayerByName(name) { var layer = this.layer_map[name]; return layer ? layer.getGroup() : null; } - /** * Returns the name of the currently selected layer. If an error occurs, an empty string * is returned. @@ -9504,11 +10552,10 @@ */ }, { - key: 'getCurrentLayerName', + key: "getCurrentLayerName", value: function getCurrentLayerName() { return this.current_layer ? this.current_layer.getName() : ''; } - /** * Set the current layer's name. * @param {string} name - The new name. @@ -9517,20 +10564,22 @@ */ }, { - key: 'setCurrentLayerName', + key: "setCurrentLayerName", value: function setCurrentLayerName(name, hrService) { var finalName = null; + if (this.current_layer) { var oldName = this.current_layer.getName(); finalName = this.current_layer.setName(name, hrService); + if (finalName) { delete this.layer_map[oldName]; this.layer_map[finalName] = this.current_layer; } } + return finalName; } - /** * Set the current layer's position. * @param {Integer} newpos - The zero-based index of the new position of the layer. Range should be 0 to layers-1 @@ -9538,20 +10587,23 @@ */ }, { - key: 'setCurrentLayerPosition', + key: "setCurrentLayerPosition", value: function setCurrentLayerPosition(newpos) { var layerCount = this.getNumLayers(); + if (!this.current_layer || newpos < 0 || newpos >= layerCount) { return null; } - var oldpos = void 0; + var oldpos; + for (oldpos = 0; oldpos < layerCount; ++oldpos) { if (this.all_layers[oldpos] === this.current_layer) { break; } - } - // some unknown error condition (current_layer not in all_layers) + } // some unknown error condition (current_layer not in all_layers) + + if (oldpos === layerCount) { return null; } @@ -9560,66 +10612,70 @@ // if our new position is below us, we need to insert before the node after newpos var currentGroup = this.current_layer.getGroup(); var oldNextSibling = currentGroup.nextSibling; - var refGroup = null; + if (newpos > oldpos) { if (newpos < layerCount - 1) { refGroup = this.all_layers[newpos + 1].getGroup(); - } - // if our new position is above us, we need to insert before the node at newpos + } // if our new position is above us, we need to insert before the node at newpos + } else { refGroup = this.all_layers[newpos].getGroup(); } + this.svgElem_.insertBefore(currentGroup, refGroup); // Ok to replace with `refGroup.before(currentGroup);`? this.identifyLayers(); this.setCurrentLayer(this.getLayerName(newpos)); - return { currentGroup: currentGroup, oldNextSibling: oldNextSibling }; } + return null; } - /** * @param {module:history.HistoryRecordingService} hrService * @returns {undefined} */ }, { - key: 'mergeLayer', + key: "mergeLayer", value: function mergeLayer(hrService) { var currentGroup = this.current_layer.getGroup(); var prevGroup = $$5(currentGroup).prev()[0]; + if (!prevGroup) { return; } hrService.startBatchCommand('Merge Layer'); - var layerNextSibling = currentGroup.nextSibling; hrService.removeElement(currentGroup, layerNextSibling, this.svgElem_); while (currentGroup.firstChild) { var child = currentGroup.firstChild; + if (child.localName === 'title') { hrService.removeElement(child, child.nextSibling, currentGroup); child.remove(); continue; } + var oldNextSibling = child.nextSibling; prevGroup.append(child); hrService.moveElement(child, oldNextSibling, currentGroup); - } + } // Remove current layer's group + + + this.current_layer.removeGroup(); // Remove the current layer and set the previous layer as the new current layer - // Remove current layer's group - this.current_layer.removeGroup(); - // Remove the current layer and set the previous layer as the new current layer var index = this.all_layers.indexOf(this.current_layer); + if (index > 0) { var _name = this.current_layer.getName(); + this.current_layer = this.all_layers[index - 1]; this.all_layers.splice(index, 1); delete this.layer_map[_name]; @@ -9627,25 +10683,24 @@ hrService.endBatchCommand(); } - /** * @param {module:history.HistoryRecordingService} hrService * @returns {undefined} */ }, { - key: 'mergeAllLayers', + key: "mergeAllLayers", value: function mergeAllLayers(hrService) { // Set the current layer to the last layer. this.current_layer = this.all_layers[this.all_layers.length - 1]; - hrService.startBatchCommand('Merge all Layers'); + while (this.all_layers.length > 1) { this.mergeLayer(hrService); } + hrService.endBatchCommand(); } - /** * Sets the current layer. If the name is not a valid layer name, then this * function returns `false`. Otherwise it returns `true`. This is not an @@ -9655,20 +10710,22 @@ */ }, { - key: 'setCurrentLayer', + key: "setCurrentLayer", value: function setCurrentLayer(name) { var layer = this.layer_map[name]; + if (layer) { if (this.current_layer) { this.current_layer.deactivate(); } + this.current_layer = layer; this.current_layer.activate(); return true; } + return false; } - /** * Deletes the current layer from the drawing and then clears the selection. * This function then calls the 'changed' handler. This is an undoable action. @@ -9677,16 +10734,16 @@ */ }, { - key: 'deleteCurrentLayer', + key: "deleteCurrentLayer", value: function deleteCurrentLayer() { if (this.current_layer && this.getNumLayers() > 1) { var oldLayerGroup = this.current_layer.removeGroup(); this.identifyLayers(); return oldLayerGroup; } + return null; } - /** * Updates layer system and sets the current layer to the * top-most layer (last `<g>` child of this drawing). @@ -9694,23 +10751,26 @@ */ }, { - key: 'identifyLayers', + key: "identifyLayers", value: function identifyLayers() { this.all_layers = []; this.layer_map = {}; - var numchildren = this.svgElem_.childNodes.length; - // loop through all children of SVG element + var numchildren = this.svgElem_.childNodes.length; // loop through all children of SVG element + var orphans = [], layernames = []; var layer = null; var childgroups = false; + for (var i = 0; i < numchildren; ++i) { - var child = this.svgElem_.childNodes.item(i); - // for each g, find its layer name + var child = this.svgElem_.childNodes.item(i); // for each g, find its layer name + if (child && child.nodeType === 1) { if (child.tagName === 'g') { childgroups = true; + var _name2 = findLayerNameInGroup(child); + if (_name2) { layernames.push(_name2); layer = new Layer(_name2, child); @@ -9725,9 +10785,9 @@ orphans.push(child); } } - } + } // If orphans or no layers found, create a new layer and add all the orphans to it + - // If orphans or no layers found, create a new layer and add all the orphans to it if (orphans.length > 0 || !childgroups) { layer = new Layer(getNewLayerName(layernames), null, this.svgElem_); layer.appendChildren(orphans); @@ -9736,9 +10796,9 @@ } else { layer.activate(); } + this.current_layer = layer; } - /** * Creates a new top-level layer in the drawing with the given name and * makes it the current layer. @@ -9749,19 +10809,20 @@ */ }, { - key: 'createLayer', + key: "createLayer", value: function createLayer(name, hrService) { if (this.current_layer) { this.current_layer.deactivate(); - } - // Check for duplicate name. + } // Check for duplicate name. + + if (name === undefined || name === null || name === '' || this.layer_map[name]) { name = getNewLayerName(Object.keys(this.layer_map)); - } + } // Crate new layer and add to DOM as last layer + + + var layer = new Layer(name, null, this.svgElem_); // Like to assume hrService exists, but this is backwards compatible with old version of createLayer. - // Crate new layer and add to DOM as last layer - var layer = new Layer(name, null, this.svgElem_); - // Like to assume hrService exists, but this is backwards compatible with old version of createLayer. if (hrService) { hrService.startBatchCommand('Create Layer'); hrService.insertElement(layer.getGroup()); @@ -9773,7 +10834,6 @@ this.current_layer = layer; return layer.getGroup(); } - /** * Creates a copy of the current layer with the given name and makes it the current layer. * @param {string} name - The given name. If the layer name exists, a new name will be generated. @@ -9783,29 +10843,32 @@ */ }, { - key: 'cloneLayer', + key: "cloneLayer", value: function cloneLayer(name, hrService) { if (!this.current_layer) { return null; } - this.current_layer.deactivate(); - // Check for duplicate name. + + this.current_layer.deactivate(); // Check for duplicate name. + if (name === undefined || name === null || name === '' || this.layer_map[name]) { name = getNewLayerName(Object.keys(this.layer_map)); - } + } // Create new group and add to DOM just after current_layer + - // Create new group and add to DOM just after current_layer var currentGroup = this.current_layer.getGroup(); var layer = new Layer(name, currentGroup, this.svgElem_); - var group = layer.getGroup(); + var group = layer.getGroup(); // Clone children - // Clone children var children = currentGroup.childNodes; + for (var _index = 0; _index < children.length; _index++) { var ch = children[_index]; + if (ch.localName === 'title') { continue; } + group.append(this.copyElem(ch)); } @@ -9813,20 +10876,21 @@ hrService.startBatchCommand('Duplicate Layer'); hrService.insertElement(group); hrService.endBatchCommand(); - } + } // Update layer containers and current_layer. + - // Update layer containers and current_layer. var index = this.all_layers.indexOf(this.current_layer); + if (index >= 0) { this.all_layers.splice(index + 1, 0, layer); } else { this.all_layers.push(layer); } + this.layer_map[name] = layer; this.current_layer = layer; return group; } - /** * Returns whether the layer is visible. If the layer name is not valid, * then this function returns `false`. @@ -9835,12 +10899,11 @@ */ }, { - key: 'getLayerVisibility', + key: "getLayerVisibility", value: function getLayerVisibility(layerName) { var layer = this.layer_map[layerName]; return layer ? layer.isVisible() : false; } - /** * Sets the visibility of the layer. If the layer name is not valid, this * function returns `null`, otherwise it returns the `SVGElement` representing @@ -9852,19 +10915,21 @@ */ }, { - key: 'setLayerVisibility', + key: "setLayerVisibility", value: function setLayerVisibility(layerName, bVisible) { if (typeof bVisible !== 'boolean') { return null; } + var layer = this.layer_map[layerName]; + if (!layer) { return null; } + layer.setVisible(bVisible); return layer.getGroup(); } - /** * Returns the opacity of the given layer. If the input name is not a layer, `null` is returned. * @param {string} layerName - name of the layer on which to get the opacity @@ -9873,15 +10938,16 @@ */ }, { - key: 'getLayerOpacity', + key: "getLayerOpacity", value: function getLayerOpacity(layerName) { var layer = this.layer_map[layerName]; + if (!layer) { return null; } + return layer.getOpacity(); } - /** * Sets the opacity of the given layer. If the input name is not a layer, * nothing happens. If opacity is not a value between 0.0 and 1.0, then @@ -9896,36 +10962,39 @@ */ }, { - key: 'setLayerOpacity', + key: "setLayerOpacity", value: function setLayerOpacity(layerName, opacity) { if (typeof opacity !== 'number' || opacity < 0.0 || opacity > 1.0) { return; } + var layer = this.layer_map[layerName]; + if (layer) { layer.setOpacity(opacity); } } - /** - * Create a clone of an element, updating its ID and its children's IDs when needed + * Create a clone of an element, updating its ID and its children's IDs when needed. * @param {Element} el - DOM element to clone * @returns {Element} */ }, { - key: 'copyElem', - value: function copyElem$$1(el) { - var self = this; + key: "copyElem", + value: function copyElem$1(el) { + var that = this; + var getNextIdClosure = function getNextIdClosure() { - return self.getNextId(); + return that.getNextId(); }; + return copyElem(el, getNextIdClosure); } }]); + return Drawing; }(); - /** * Called to ensure that drawings will or will not have randomized ids. * The currentDrawing will have its nonce set if it doesn't already. @@ -9934,6 +11003,7 @@ * @param {draw.Drawing} currentDrawing * @returns {undefined} */ + var randomizeIds = function randomizeIds(enableRandomization, currentDrawing) { randIds = enableRandomization === false ? RandomizeModes.NEVER_RANDOMIZE : RandomizeModes.ALWAYS_RANDOMIZE; @@ -9942,9 +11012,7 @@ } else if (randIds === RandomizeModes.NEVER_RANDOMIZE && currentDrawing.getNonce()) { currentDrawing.clearNonce(); } - }; - - // Layer API Functions + }; // Layer API Functions /** * Group: Layers @@ -9961,32 +11029,39 @@ * @property {external:jQuery.data} elData * @property {module:history.UndoManager} undoMgr */ + /** * @function module:draw.DrawCanvasInit#getCurrentGroup * @returns {Element} */ + /** * @function module:draw.DrawCanvasInit#setCurrentGroup * @param {Element} cg * @returns {undefined} */ + /** * @function module:draw.DrawCanvasInit#getSelectedElements * @returns {Element[]} the array with selected DOM elements */ + /** * @function module:draw.DrawCanvasInit#getSVGContent * @returns {SVGSVGElement} */ + /** * @function module:draw.DrawCanvasInit#getCurrentDrawing * @returns {module:draw.Drawing} */ + /** * @function module:draw.DrawCanvasInit#clearSelection * @param {boolean} [noCall] - When `true`, does not call the "selected" handler * @returns {undefined} */ + /** * Run the callback function associated with the given event * @function module:draw.DrawCanvasInit#call @@ -9996,36 +11071,38 @@ * passed. If the event is "contextset", the arg is `null` or `Element`. * @returns {undefined} */ + /** * @function module:draw.DrawCanvasInit#addCommandToHistory * @param {Command} cmd * @returns {undefined} */ + /** * @function module:draw.DrawCanvasInit#changeSVGContent * @returns {undefined} */ - var canvas_ = void 0; + var canvas_; /** * @function module:draw.init * @param {module:draw.DrawCanvasInit} canvas * @returns {undefined} */ + var init$3 = function init(canvas) { canvas_ = canvas; }; - /** - * Updates layer system + * Updates layer system. * @function module:draw.identifyLayers * @returns {undefined} */ + var identifyLayers = function identifyLayers() { leaveContext(); canvas_.getCurrentDrawing().identifyLayers(); }; - /** * Creates a new top-level layer in the drawing with the given name, sets the current layer * to it, and then clears the selection. This function then calls the 'changed' handler. @@ -10036,12 +11113,12 @@ * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + var createLayer = function createLayer(name, hrService) { var newLayer = canvas_.getCurrentDrawing().createLayer(name, historyRecordingService(hrService)); canvas_.clearSelection(); canvas_.call('changed', [newLayer]); }; - /** * Creates a new top-level layer in the drawing with the given name, copies all the current layer's contents * to it, and then clears the selection. This function then calls the 'changed' handler. @@ -10052,15 +11129,14 @@ * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + var cloneLayer = function cloneLayer(name, hrService) { // Clone the current layer and make the cloned layer the new current layer var newLayer = canvas_.getCurrentDrawing().cloneLayer(name, historyRecordingService(hrService)); - canvas_.clearSelection(); leaveContext(); canvas_.call('changed', [newLayer]); }; - /** * Deletes the current layer from the drawing and then clears the selection. This function * then calls the 'changed' handler. This is an undoable action. @@ -10068,25 +11144,26 @@ * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {boolean} `true` if an old layer group was found to delete */ + var deleteCurrentLayer = function deleteCurrentLayer() { var currentLayer = canvas_.getCurrentDrawing().getCurrentLayer(); var _currentLayer = currentLayer, nextSibling = _currentLayer.nextSibling; - var parent = currentLayer.parentNode; currentLayer = canvas_.getCurrentDrawing().deleteCurrentLayer(); + if (currentLayer) { - var batchCmd = new BatchCommand('Delete Layer'); - // store in our Undo History + var batchCmd = new BatchCommand('Delete Layer'); // store in our Undo History + batchCmd.addSubCommand(new RemoveElementCommand(currentLayer, nextSibling, parent)); canvas_.addCommandToHistory(batchCmd); canvas_.clearSelection(); canvas_.call('changed', [parent]); return true; } + return false; }; - /** * Sets the current layer. If the name is not a valid layer name, then this function returns * false. Otherwise it returns true. This is not an undo-able action. @@ -10094,14 +11171,16 @@ * @param {string} name - The name of the layer you want to switch to. * @returns {boolean} true if the current layer was switched, otherwise false */ + var setCurrentLayer = function setCurrentLayer(name) { var result = canvas_.getCurrentDrawing().setCurrentLayer(toXml(name)); + if (result) { canvas_.clearSelection(); } + return result; }; - /** * Renames the current layer. If the layer name is not valid (i.e. unique), then this function * does nothing and returns `false`, otherwise it returns `true`. This is an undo-able action. @@ -10111,19 +11190,22 @@ * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {boolean} Whether the rename succeeded */ + var renameCurrentLayer = function renameCurrentLayer(newName) { var drawing = canvas_.getCurrentDrawing(); var layer = drawing.getCurrentLayer(); + if (layer) { var result = drawing.setCurrentLayerName(newName, historyRecordingService()); + if (result) { canvas_.call('changed', [layer]); return true; } } + return false; }; - /** * Changes the position of the current layer to the new value. If the new index is not valid, * this function does nothing and returns false, otherwise it returns true. This is an @@ -10133,16 +11215,18 @@ * 0 and (number of layers - 1) * @returns {boolean} `true` if the current layer position was changed, `false` otherwise. */ + var setCurrentLayerPosition = function setCurrentLayerPosition(newPos) { var drawing = canvas_.getCurrentDrawing(); var result = drawing.setCurrentLayerPosition(newPos); + if (result) { canvas_.addCommandToHistory(new MoveElementCommand(result.currentGroup, result.oldNextSibling, canvas_.getSVGContent())); return true; } + return false; }; - /** * Sets the visibility of the layer. If the layer name is not valid, this function return * `false`, otherwise it returns `true`. This is an undo-able action. @@ -10151,13 +11235,17 @@ * @param {boolean} bVisible - Whether the layer should be visible * @returns {boolean} true if the layer's visibility was set, false otherwise */ + var setLayerVisibility = function setLayerVisibility(layerName, bVisible) { var drawing = canvas_.getCurrentDrawing(); var prevVisibility = drawing.getLayerVisibility(layerName); var layer = drawing.setLayerVisibility(layerName, bVisible); + if (layer) { var oldDisplay = prevVisibility ? 'inline' : 'none'; - canvas_.addCommandToHistory(new ChangeElementCommand(layer, { display: oldDisplay }, 'Layer Visibility')); + canvas_.addCommandToHistory(new ChangeElementCommand(layer, { + display: oldDisplay + }, 'Layer Visibility')); } else { return false; } @@ -10165,11 +11253,11 @@ if (layer === drawing.getCurrentLayer()) { canvas_.clearSelection(); canvas_.pathActions.clear(); - } - // call('changed', [selected]); + } // call('changed', [selected]); + + return true; }; - /** * Moves the selected elements to layerName. If the name is not a valid layer name, then `false` * is returned. Otherwise it returns `true`. This is an undo-able action. @@ -10177,148 +11265,132 @@ * @param {string} layerName - The name of the layer you want to which you want to move the selected elements * @returns {boolean} Whether the selected elements were moved to the layer. */ + var moveSelectedToLayer = function moveSelectedToLayer(layerName) { // find the layer var drawing = canvas_.getCurrentDrawing(); var layer = drawing.getLayerByName(layerName); + if (!layer) { return false; } - var batchCmd = new BatchCommand('Move Elements to Layer'); + var batchCmd = new BatchCommand('Move Elements to Layer'); // loop for each selected element and move it - // loop for each selected element and move it var selElems = canvas_.getSelectedElements(); var i = selElems.length; + while (i--) { var elem = selElems[i]; + if (!elem) { continue; } - var oldNextSibling = elem.nextSibling; - // TODO: this is pretty brittle! + + var oldNextSibling = elem.nextSibling; // TODO: this is pretty brittle! + var oldLayer = elem.parentNode; layer.append(elem); batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldLayer)); } canvas_.addCommandToHistory(batchCmd); - return true; }; - /** * @function module:draw.mergeLayer * @param {module:history.HistoryRecordingService} hrService * @returns {undefined} */ + var mergeLayer = function mergeLayer(hrService) { canvas_.getCurrentDrawing().mergeLayer(historyRecordingService(hrService)); canvas_.clearSelection(); leaveContext(); canvas_.changeSVGContent(); }; - /** * @function module:draw.mergeAllLayers * @param {module:history.HistoryRecordingService} hrService * @returns {undefined} */ + var mergeAllLayers = function mergeAllLayers(hrService) { canvas_.getCurrentDrawing().mergeAllLayers(historyRecordingService(hrService)); canvas_.clearSelection(); leaveContext(); canvas_.changeSVGContent(); }; - /** * Return from a group context to the regular kind, make any previously - * disabled elements enabled again + * disabled elements enabled again. * @function module:draw.leaveContext * @fires module:svgcanvas.SvgCanvas#event:contextset * @returns {undefined} */ + var leaveContext = function leaveContext() { var len = disabledElems.length; + if (len) { for (var i = 0; i < len; i++) { var elem = disabledElems[i]; var orig = canvas_.elData(elem, 'orig_opac'); + if (orig !== 1) { elem.setAttribute('opacity', orig); } else { elem.removeAttribute('opacity'); } + elem.setAttribute('style', 'pointer-events: inherit'); } + disabledElems = []; canvas_.clearSelection(true); canvas_.call('contextset', null); } + canvas_.setCurrentGroup(null); }; - /** - * Set the current context (for in-group editing) + * Set the current context (for in-group editing). * @function module:draw.setContext * @param {Element} elem * @fires module:svgcanvas.SvgCanvas#event:contextset * @returns {undefined} */ + var setContext = function setContext(elem) { leaveContext(); + if (typeof elem === 'string') { elem = getElem(elem); - } + } // Edit inside this group - // Edit inside this group - canvas_.setCurrentGroup(elem); - // Disable other elements + canvas_.setCurrentGroup(elem); // Disable other elements + $$5(elem).parentsUntil('#svgcontent').andSelf().siblings().each(function () { - var opac = this.getAttribute('opacity') || 1; - // Store the original's opacity + var opac = this.getAttribute('opacity') || 1; // Store the original's opacity + canvas_.elData(this, 'orig_opac', opac); this.setAttribute('opacity', opac * 0.33); this.setAttribute('style', 'pointer-events: none'); disabledElems.push(this); }); - canvas_.clearSelection(); canvas_.call('contextset', canvas_.getCurrentGroup()); }; - var draw = /*#__PURE__*/Object.freeze({ - Drawing: Drawing, - randomizeIds: randomizeIds, - init: init$3, - identifyLayers: identifyLayers, - createLayer: createLayer, - cloneLayer: cloneLayer, - deleteCurrentLayer: deleteCurrentLayer, - setCurrentLayer: setCurrentLayer, - renameCurrentLayer: renameCurrentLayer, - setCurrentLayerPosition: setCurrentLayerPosition, - setLayerVisibility: setLayerVisibility, - moveSelectedToLayer: moveSelectedToLayer, - mergeLayer: mergeLayer, - mergeAllLayers: mergeAllLayers, - leaveContext: leaveContext, - setContext: setContext, - Layer: Layer - }); + var REVERSE_NS = getReverseNS(); // Todo: Split out into core attributes, presentation attributes, etc. so consistent /** - * Tools for SVG sanitization - * @module sanitize - * @license MIT - * - * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller + * This defines which elements and attributes that we support (or at least + * don't remove) + * @type {PlainObject} */ - var REVERSE_NS = getReverseNS(); - - // this defines which elements and attributes that we support var svgWhiteList_ = { // SVG Elements a: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'xlink:href', 'xlink:title'], @@ -10329,6 +11401,7 @@ desc: [], ellipse: ['class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'], feGaussianBlur: ['class', 'color-interpolation-filters', 'id', 'requiredFeatures', 'stdDeviation'], + feMorphology: ['class', 'in', 'operator', 'radius'], filter: ['class', 'color-interpolation-filters', 'filterRes', 'filterUnits', 'height', 'id', 'primitiveUnits', 'requiredFeatures', 'width', 'x', 'xlink:href', 'y'], foreignObject: ['class', 'font-size', 'height', 'id', 'opacity', 'requiredFeatures', 'style', 'transform', 'width', 'x', 'y'], g: ['class', 'clip-path', 'clip-rule', 'id', 'display', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'font-family', 'font-size', 'font-style', 'font-weight', 'text-anchor'], @@ -10353,7 +11426,6 @@ title: [], tspan: ['class', 'clip-path', 'clip-rule', 'dx', 'dy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'rotate', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'textLength', 'transform', 'x', 'xml:space', 'y'], use: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'transform', 'width', 'x', 'xlink:href', 'y'], - // MathML Elements annotation: ['encoding'], 'annotation-xml': ['encoding'], @@ -10386,18 +11458,17 @@ munderover: [], none: [], semantics: [] - }; + }; // Produce a Namespace-aware version of svgWhitelist - // Produce a Namespace-aware version of svgWhitelist var svgWhiteListNS_ = {}; Object.entries(svgWhiteList_).forEach(function (_ref) { - var _ref2 = slicedToArray(_ref, 2), + var _ref2 = _slicedToArray(_ref, 2), elt = _ref2[0], atts = _ref2[1]; var attNS = {}; Object.entries(atts).forEach(function (_ref3) { - var _ref4 = slicedToArray(_ref3, 2), + var _ref4 = _slicedToArray(_ref3, 2), i = _ref4[0], att = _ref4[1]; @@ -10410,7 +11481,6 @@ }); svgWhiteListNS_[elt] = attNS; }); - /** * Sanitizes the input node and its children. * It only keeps what is allowed from our whitelist defined above. @@ -10418,101 +11488,110 @@ * @param {Text|Element} node - The DOM element to be checked (we'll also check its children) or text node to be cleaned up * @returns {undefined} */ + var sanitizeSvg = function sanitizeSvg(node) { // Cleanup text nodes if (node.nodeType === 3) { // 3 === TEXT_NODE // Trim whitespace - node.nodeValue = node.nodeValue.replace(/^\s+|\s+$/g, ''); - // Remove if empty + node.nodeValue = node.nodeValue.replace(/^\s+|\s+$/g, ''); // Remove if empty + if (!node.nodeValue.length) { node.remove(); } - } - - // We only care about element nodes. + } // We only care about element nodes. // Automatically return for all non-element nodes, such as comments, etc. + + if (node.nodeType !== 1) { // 1 == ELEMENT_NODE return; } var doc = node.ownerDocument; - var parent = node.parentNode; - // can parent ever be null here? I think the root node's parent is the document... + var parent = node.parentNode; // can parent ever be null here? I think the root node's parent is the document... + if (!doc || !parent) { return; } var allowedAttrs = svgWhiteList_[node.nodeName]; - var allowedAttrsNS = svgWhiteListNS_[node.nodeName]; - // if this element is supported, sanitize it + var allowedAttrsNS = svgWhiteListNS_[node.nodeName]; // if this element is supported, sanitize it + if (typeof allowedAttrs !== 'undefined') { var seAttrs = []; var i = node.attributes.length; + while (i--) { // if the attribute is not in our whitelist, then remove it // could use jQuery's inArray(), but I don't know if that's any better var attr = node.attributes.item(i); var attrName = attr.nodeName; var attrLocalName = attr.localName; - var attrNsURI = attr.namespaceURI; - // Check that an attribute with the correct localName in the correct namespace is on + var attrNsURI = attr.namespaceURI; // Check that an attribute with the correct localName in the correct namespace is on // our whitelist or is a namespace declaration for one of our allowed namespaces - if (!(allowedAttrsNS.hasOwnProperty(attrLocalName) && attrNsURI === allowedAttrsNS[attrLocalName] && attrNsURI !== NS.XMLNS) && !(attrNsURI === NS.XMLNS && REVERSE_NS[attr.value])) { + + if (!({}.hasOwnProperty.call(allowedAttrsNS, attrLocalName) && attrNsURI === allowedAttrsNS[attrLocalName] && attrNsURI !== NS.XMLNS) && !(attrNsURI === NS.XMLNS && REVERSE_NS[attr.value])) { // TODO(codedread): Programmatically add the se: attributes to the NS-aware whitelist. // Bypassing the whitelist to allow se: prefixes. // Is there a more appropriate way to do this? if (attrName.startsWith('se:') || attrName.startsWith('data-')) { seAttrs.push([attrName, attr.value]); } - node.removeAttributeNS(attrNsURI, attrLocalName); - } - // Add spaces before negative signs where necessary + node.removeAttributeNS(attrNsURI, attrLocalName); + } // Add spaces before negative signs where necessary + + if (isGecko()) { switch (attrName) { case 'transform': case 'gradientTransform': case 'patternTransform': - var val = attr.value.replace(/(\d)-/g, '$1 -'); - node.setAttribute(attrName, val); - break; + { + var val = attr.value.replace(/(\d)-/g, '$1 -'); + node.setAttribute(attrName, val); + 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 if (attrName === 'style') { var props = attr.value.split(';'); var p = props.length; + while (p--) { var _props$p$split = props[p].split(':'), - _props$p$split2 = slicedToArray(_props$p$split, 2), + _props$p$split2 = _slicedToArray(_props$p$split, 2), name = _props$p$split2[0], _val = _props$p$split2[1]; var styleAttrName = (name || '').trim(); - var styleAttrVal = (_val || '').trim(); - // Now check that this attribute is supported + + var styleAttrVal = (_val || '').trim(); // Now check that this attribute is supported + + if (allowedAttrs.includes(styleAttrName)) { node.setAttribute(styleAttrName, styleAttrVal); } } + node.removeAttribute('style'); } } Object.values(seAttrs).forEach(function (_ref5) { - var _ref6 = slicedToArray(_ref5, 2), + var _ref6 = _slicedToArray(_ref5, 2), att = _ref6[0], val = _ref6[1]; node.setAttributeNS(NS.SE, att, val); - }); - - // for some elements that have a xlink:href, ensure the URI refers to a local element + }); // for some elements that have a xlink:href, ensure the URI refers to a local element // (but not for links) + var href = getHref(node); + if (href && ['filter', 'linearGradient', 'pattern', 'radialGradient', 'textPath', 'use'].includes(node.nodeName)) { // TODO: we simply check if the first character is a #, is this bullet-proof? if (href[0] !== '#') { @@ -10520,90 +11599,93 @@ setHref(node, ''); node.removeAttributeNS(NS.XLINK, 'href'); } - } + } // Safari crashes on a <use> without a xlink:href, so we just remove the node here + - // Safari crashes on a <use> without a xlink:href, so we just remove the node here if (node.nodeName === 'use' && !getHref(node)) { node.remove(); return; - } - // if the element has attributes pointing to a non-local reference, + } // if the element has attributes pointing to a non-local reference, // need to remove the attribute + + Object.values(['clip-path', 'fill', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'stroke'], function (attr) { var val = node.getAttribute(attr); + if (val) { - val = getUrlFromAttr(val); - // simply check for first character being a '#' + val = getUrlFromAttr(val); // simply check for first character being a '#' + if (val && val[0] !== '#') { node.setAttribute(attr, ''); node.removeAttribute(attr); } } - }); + }); // recurse to children - // recurse to children i = node.childNodes.length; + while (i--) { sanitizeSvg(node.childNodes.item(i)); - } - // else (element not supported), remove it + } // else (element not supported), remove it + } else { // remove all children from this node and insert them before this node // FIXME: in the case of animation elements this will hardly ever be correct var children = []; + while (node.hasChildNodes()) { children.push(parent.insertBefore(node.firstChild, node)); - } + } // remove this node from the document altogether - // remove this node from the document altogether - node.remove(); - // call sanitizeSvg on each of those children + node.remove(); // call sanitizeSvg on each of those children + var _i = children.length; + while (_i--) { sanitizeSvg(children[_i]); } } }; - /* globals jQuery */ + var $$6 = jQuery; // this is how we map paths to our preferred relative segment types - var $$6 = jQuery; - - // this is how we map paths to our preferred relative segment types var pathMap$1 = [0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a', 'H', 'h', 'V', 'v', 'S', 's', 'T', 't']; - /** * @interface module:coords.EditorContext */ + /** * @function module:coords.EditorContext#getGridSnapping * @returns {boolean} */ + /** * @function module:coords.EditorContext#getDrawing * @returns {module:draw.Drawing} */ + /** * @function module:coords.EditorContext#getSVGRoot * @returns {SVGSVGElement} */ var editorContext_$2 = null; - /** * @function module:coords.init * @param {module:coords.EditorContext} editorContext + * @returns {undefined} */ + var init$4 = function init(editorContext) { editorContext_$2 = editorContext; }; - /** - * Applies coordinate changes to an element based on the given matrix + * Applies coordinate changes to an element based on the given matrix. * @function module:coords.remapElement * @implements {module:path.EditorContext#remapElement} */ + var remapElement = function remapElement(selected, changes, m) { var remap = function remap(x, y) { return transformPoint(x, y, m); @@ -10617,10 +11699,15 @@ doSnapping = editorContext_$2.getGridSnapping() && selected.parentNode.parentNode.localName === 'svg', finishUp = function finishUp() { if (doSnapping) { - for (var o in changes) { - changes[o] = snapToGrid(changes[o]); - } + Object.entries(changes).forEach(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + o = _ref2[0], + value = _ref2[1]; + + changes[o] = snapToGrid(value); + }); } + assignAttributes(selected, changes, 1000, true); }, box = getBBox(selected); @@ -10628,10 +11715,12 @@ for (var i = 0; i < 2; i++) { var type = i === 0 ? 'fill' : 'stroke'; var attrVal = selected.getAttribute(type); + if (attrVal && attrVal.startsWith('url(')) { if (m.a < 0 || m.d < 0) { var grad = getRefElem(attrVal); var newgrad = grad.cloneNode(true); + if (m.a < 0) { // flip x var x1 = newgrad.getAttribute('x1'); @@ -10647,19 +11736,20 @@ newgrad.setAttribute('y1', -(y1 - 1)); newgrad.setAttribute('y2', -(y2 - 1)); } + newgrad.id = editorContext_$2.getDrawing().getNextId(); findDefs().append(newgrad); selected.setAttribute(type, 'url(#' + newgrad.id + ')'); - } - - // Not really working :( + } // Not really working :( // if (selected.tagName === 'path') { // reorientGrads(selected, m); // } + } } var elName = selected.tagName; + if (elName === 'g' || elName === 'text' || elName === 'tspan' || elName === 'use') { // if it was a translate, then just update x,y if (m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && (m.e !== 0 || m.f !== 0)) { @@ -10677,10 +11767,10 @@ chlist.clear(); chlist.appendItem(mt); } - } - - // now we have a set of changes and an applied reduced transform list + } // now we have a set of changes and an applied reduced transform list // we apply the changes directly to the DOM + + switch (elName) { case 'foreignObject': case 'rect': @@ -10690,9 +11780,13 @@ if (elName === 'image' && (m.a < 0 || m.d < 0)) { // Convert to matrix var _chlist = getTransformList(selected); + var _mt = editorContext_$2.getSVGRoot().createSVGTransform(); + _mt.setMatrix(matrixMultiply(transformListToTransform(_chlist).matrix, m)); + _chlist.clear(); + _chlist.appendItem(_mt); } else { var pt1 = remap(changes.x, changes.y); @@ -10703,9 +11797,12 @@ changes.width = Math.abs(changes.width); changes.height = Math.abs(changes.height); } + finishUp(); break; - }case 'ellipse': + } + + case 'ellipse': { var c = remap(changes.cx, changes.cy); changes.cx = c.x; @@ -10716,12 +11813,15 @@ changes.ry = Math.abs(changes.ry); finishUp(); break; - }case 'circle': + } + + case 'circle': { var _c = remap(changes.cx, changes.cy); + changes.cx = _c.x; - changes.cy = _c.y; - // take the minimum of the new selected box's dimensions for the new circle radius + changes.cy = _c.y; // take the minimum of the new selected box's dimensions for the new circle radius + var tbox = transformBox(box.x, box.y, box.width, box.height, m); var w = tbox.tr.x - tbox.tl.x, h = tbox.bl.y - tbox.tl.y; @@ -10730,34 +11830,47 @@ if (changes.r) { changes.r = Math.abs(changes.r); } + finishUp(); break; - }case 'line': + } + + case 'line': { var _pt = remap(changes.x1, changes.y1); + var pt2 = remap(changes.x2, changes.y2); changes.x1 = _pt.x; changes.y1 = _pt.y; changes.x2 = pt2.x; changes.y2 = pt2.y; - } // Fallthrough + } + // Fallthrough + case 'text': case 'tspan': case 'use': { finishUp(); break; - }case 'g': + } + + case 'g': { var gsvg = $$6(selected).data('gsvg'); + if (gsvg) { assignAttributes(gsvg, changes, 1000, true); } + break; - }case 'polyline': + } + + case 'polyline': case 'polygon': { var len = changes.points.length; + for (var _i = 0; _i < len; ++_i) { var pt = changes.points[_i]; @@ -10767,21 +11880,26 @@ changes.points[_i].x = x; changes.points[_i].y = y; - } + } // const len = changes.points.length; + - // const len = changes.points.length; var pstr = ''; + for (var _i2 = 0; _i2 < len; ++_i2) { var _pt2 = changes.points[_i2]; pstr += _pt2.x + ',' + _pt2.y + ' '; } + selected.setAttribute('points', pstr); break; - }case 'path': + } + + case 'path': { var segList = selected.pathSegList; var _len = segList.numberOfItems; changes.d = []; + for (var _i3 = 0; _i3 < _len; ++_i3) { var seg = segList.getItem(_i3); changes.d[_i3] = { @@ -10805,10 +11923,10 @@ currentpt = remap(firstseg.x, firstseg.y); changes.d[0].x = currentpt.x; changes.d[0].y = currentpt.y; + for (var _i4 = 1; _i4 < _len; ++_i4) { var _seg = changes.d[_i4]; - var _type = _seg.type; - // if absolute or first segment, we want to remap x, y, x1, y1, x2, y2 + var _type = _seg.type; // if absolute or first segment, we want to remap x, y, x1, y1, x2, y2 // if relative, we want to scalew, scaleh if (_type % 2 === 0) { @@ -10816,9 +11934,13 @@ var thisx = _seg.x !== undefined ? _seg.x : currentpt.x, // for V commands thisy = _seg.y !== undefined ? _seg.y : currentpt.y; // for H commands + var _pt3 = remap(thisx, thisy); + var _pt4 = remap(_seg.x1, _seg.y1); + var _pt5 = remap(_seg.x2, _seg.y2); + _seg.x = _pt3.x; _seg.y = _pt3.y; _seg.x1 = _pt4.x; @@ -10840,49 +11962,68 @@ } } // for each segment + var dstr = ''; _len = changes.d.length; + for (var _i5 = 0; _i5 < _len; ++_i5) { var _seg2 = changes.d[_i5]; var _type2 = _seg2.type; - dstr += pathMap$1[_type2]; + switch (_type2) { case 13: // relative horizontal line (h) + case 12: // absolute horizontal line (H) dstr += _seg2.x + ' '; break; + case 15: // relative vertical line (v) + case 14: // absolute vertical line (V) dstr += _seg2.y + ' '; break; + case 3: // relative move (m) + case 5: // relative line (l) + case 19: // relative smooth quad (t) + case 2: // absolute move (M) + case 4: // absolute line (L) + case 18: // absolute smooth quad (T) dstr += _seg2.x + ',' + _seg2.y + ' '; break; + case 7: // relative cubic (c) + case 6: // absolute cubic (C) dstr += _seg2.x1 + ',' + _seg2.y1 + ' ' + _seg2.x2 + ',' + _seg2.y2 + ' ' + _seg2.x + ',' + _seg2.y + ' '; break; + case 9: // relative quad (q) + case 8: // absolute quad (Q) dstr += _seg2.x1 + ',' + _seg2.y1 + ' ' + _seg2.x + ',' + _seg2.y + ' '; break; + case 11: // relative elliptical arc (a) + case 10: // absolute elliptical arc (A) - dstr += _seg2.r1 + ',' + _seg2.r2 + ' ' + _seg2.angle + ' ' + +_seg2.largeArcFlag + ' ' + +_seg2.sweepFlag + ' ' + _seg2.x + ',' + _seg2.y + ' '; + dstr += _seg2.r1 + ',' + _seg2.r2 + ' ' + _seg2.angle + ' ' + Number(_seg2.largeArcFlag) + ' ' + Number(_seg2.sweepFlag) + ' ' + _seg2.x + ',' + _seg2.y + ' '; break; + case 17: // relative smooth cubic (s) + case 16: // absolute smooth cubic (S) dstr += _seg2.x2 + ',' + _seg2.y2 + ' ' + _seg2.x + ',' + _seg2.y + ' '; @@ -10897,22 +12038,22 @@ }; /* globals jQuery */ - - var $$7 = jqPluginSVG(jQuery); - - var context_ = void 0; - + var $$7 = jQueryPluginSVG(jQuery); + var context_; /** * @interface module:recalculate.EditorContext */ + /** * @function module:recalculate.EditorContext#getSVGRoot * @returns {SVGSVGElement} The root DOM element */ + /** * @function module:recalculate.EditorContext#getStartTransform * @returns {string} */ + /** * @function module:recalculate.EditorContext#setStartTransform * @param {string} transform @@ -10924,58 +12065,57 @@ * @param {module:recalculate.EditorContext} editorContext * @returns {undefined} */ - var init$5 = function init$$1(editorContext) { + + var init$5 = function init(editorContext) { context_ = editorContext; }; - /** - * Updates a `<clipPath>`s values based on the given translation of an element + * Updates a `<clipPath>`s values based on the given translation of an element. * @function module:recalculate.updateClipPath * @param {string} attr - The clip-path attribute value with the clipPath's ID * @param {Float} tx - The translation's x value * @param {Float} ty - The translation's y value * @returns {undefined} */ + var updateClipPath = function updateClipPath(attr, tx, ty) { var path = getRefElem(attr).firstChild; var cpXform = getTransformList(path); var newxlate = context_.getSVGRoot().createSVGTransform(); newxlate.setTranslate(tx, ty); + cpXform.appendItem(newxlate); // Update clipPath's dimensions - cpXform.appendItem(newxlate); - - // Update clipPath's dimensions recalculateDimensions(path); }; - /** - * Decides the course of action based on the element's transform list + * Decides the course of action based on the element's transform list. * @function module:recalculate.recalculateDimensions * @param {Element} selected - The DOM element to recalculate * @returns {Command} Undo command object with the resulting change */ - var recalculateDimensions = function recalculateDimensions(selected) { - if (selected == null) { - return null; - } - // Firefox Issue - 1081 + var recalculateDimensions = function recalculateDimensions(selected) { + if (isNullish(selected)) { + return null; + } // Firefox Issue - 1081 + + if (selected.nodeName === 'svg' && navigator.userAgent.includes('Firefox/20')) { return null; } var svgroot = context_.getSVGRoot(); - var tlist = getTransformList(selected); + var tlist = getTransformList(selected); // remove any unnecessary transforms - // remove any unnecessary transforms if (tlist && tlist.numberOfItems > 0) { var k = tlist.numberOfItems; var noi = k; + while (k--) { var xform = tlist.getItem(k); + if (xform.type === 0) { - tlist.removeItem(k); - // remove identity matrices + tlist.removeItem(k); // remove identity matrices } else if (xform.type === 1) { if (isIdentity(xform.matrix)) { if (noi === 1) { @@ -10986,64 +12126,69 @@ selected.removeAttribute('transform'); return null; } + tlist.removeItem(k); - } - // remove zero-degree rotations + } // remove zero-degree rotations + } else if (xform.type === 4) { if (xform.angle === 0) { tlist.removeItem(k); } } - } - // End here if all it has is a rotation + } // End here if all it has is a rotation + + if (tlist.numberOfItems === 1 && getRotationAngle(selected)) { return null; } - } + } // if this element had no transforms, we are done + - // if this element had no transforms, we are done if (!tlist || tlist.numberOfItems === 0) { // Chrome apparently had a bug that requires clearing the attribute first. - selected.setAttribute('transform', ''); - // However, this still next line currently doesn't work at all in Chrome - selected.removeAttribute('transform'); - // selected.transform.baseVal.clear(); // Didn't help for Chrome bug - return null; - } + selected.setAttribute('transform', ''); // However, this still next line currently doesn't work at all in Chrome + + selected.removeAttribute('transform'); // selected.transform.baseVal.clear(); // Didn't help for Chrome bug + + return null; + } // TODO: Make this work for more than 2 + - // TODO: Make this work for more than 2 if (tlist) { var mxs = []; var _k = tlist.numberOfItems; + while (_k--) { var _xform = tlist.getItem(_k); + if (_xform.type === 1) { mxs.push([_xform.matrix, _k]); } else if (mxs.length) { mxs = []; } } + if (mxs.length === 2) { var mNew = svgroot.createSVGTransformFromMatrix(matrixMultiply(mxs[1][0], mxs[0][0])); tlist.removeItem(mxs[0][1]); tlist.removeItem(mxs[1][1]); tlist.insertItemBefore(mNew, mxs[1][1]); - } + } // combine matrix + translate + - // combine matrix + translate _k = tlist.numberOfItems; + if (_k >= 2 && tlist.getItem(_k - 2).type === 1 && tlist.getItem(_k - 1).type === 2) { var mt = svgroot.createSVGTransform(); - var m = matrixMultiply(tlist.getItem(_k - 2).matrix, tlist.getItem(_k - 1).matrix); mt.setMatrix(m); tlist.removeItem(_k - 2); tlist.removeItem(_k - 2); tlist.appendItem(mt); } - } + } // If it still has a single [M] or [R][M], return null too (prevents BatchCommand from being returned). + - // If it still has a single [M] or [R][M], return null too (prevents BatchCommand from being returned). switch (selected.tagName) { // Ignore these elements, as they can absorb the [M] case 'line': @@ -11051,42 +12196,48 @@ case 'polygon': case 'path': break; + default: if (tlist.numberOfItems === 1 && tlist.getItem(0).type === 1 || tlist.numberOfItems === 2 && tlist.getItem(0).type === 1 && tlist.getItem(0).type === 4) { return null; } - } - // Grouped SVG element - var gsvg = $$7(selected).data('gsvg'); + } // Grouped SVG element - // we know we have some transforms, so set up return variable - var batchCmd = new BatchCommand('Transform'); - // store initial values that will be affected by reducing the transform list + var gsvg = $$7(selected).data('gsvg'); // we know we have some transforms, so set up return variable + + var batchCmd = new BatchCommand('Transform'); // store initial values that will be affected by reducing the transform list + var changes = {}; var initial = null; var attrs = []; + switch (selected.tagName) { case 'line': attrs = ['x1', 'y1', 'x2', 'y2']; break; + case 'circle': attrs = ['cx', 'cy', 'r']; break; + case 'ellipse': attrs = ['cx', 'cy', 'rx', 'ry']; break; + case 'foreignObject': case 'rect': case 'image': attrs = ['width', 'height', 'x', 'y']; break; + case 'use': case 'text': case 'tspan': attrs = ['x', 'y']; break; + case 'polygon': case 'polyline': { @@ -11095,18 +12246,26 @@ var list = selected.points; var len = list.numberOfItems; changes.points = new Array(len); + for (var i = 0; i < len; ++i) { var pt = list.getItem(i); - changes.points[i] = { x: pt.x, y: pt.y }; + changes.points[i] = { + x: pt.x, + y: pt.y + }; } + break; - }case 'path': + } + + case 'path': initial = {}; initial.d = selected.getAttribute('d'); changes.d = selected.getAttribute('d'); break; } // switch on element type to get initial values + if (attrs.length) { changes = $$7(selected).attr(attrs); $$7.each(changes, function (attr, val) { @@ -11118,43 +12277,46 @@ x: $$7(gsvg).attr('x') || 0, y: $$7(gsvg).attr('y') || 0 }; - } - - // 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 - if (initial == null) { + + + if (isNullish(initial)) { initial = $$7.extend(true, {}, changes); $$7.each(initial, function (attr, val) { initial[attr] = convertToNum(attr, val); }); - } - // save the start transform value too + } // save the start transform value too + + initial.transform = context_.getStartTransform() || ''; + var oldcenter, newcenter; // if it's a regular group, we have special processing to flatten transforms - var oldcenter = void 0, - newcenter = void 0; - - // if it's a regular group, we have special processing to flatten transforms if (selected.tagName === 'g' && !gsvg || selected.tagName === 'a') { var box = getBBox(selected); - - oldcenter = { x: box.x + box.width / 2, y: box.y + box.height / 2 }; - newcenter = transformPoint(box.x + box.width / 2, box.y + box.height / 2, transformListToTransform(tlist).matrix); - var _m = svgroot.createSVGMatrix(); - + oldcenter = { + x: box.x + box.width / 2, + y: box.y + box.height / 2 + }; + newcenter = transformPoint(box.x + box.width / 2, box.y + box.height / 2, transformListToTransform(tlist).matrix); // let m = svgroot.createSVGMatrix(); // temporarily strip off the rotate and save the old center + var gangle = getRotationAngle(selected); + if (gangle) { var a = gangle * Math.PI / 180; - var s = void 0; + var s; + if (Math.abs(a) > 1.0e-10) { s = Math.sin(a) / (1 - Math.cos(a)); } else { // FIXME: This blows up if the angle is exactly 0! s = 2 / a; } + for (var _i = 0; _i < tlist.numberOfItems; ++_i) { var _xform2 = tlist.getItem(_i); + if (_xform2.type === 4) { // extract old center through mystical arts var rm = _xform2.matrix; @@ -11165,44 +12327,43 @@ } } } + var N = tlist.numberOfItems; var tx = 0, ty = 0, operation = 0; + var firstM; - var firstM = void 0; if (N) { firstM = tlist.getItem(0).matrix; } - var oldStartTransform = void 0; - // first, if it was a scale then the second-last transform will be it + var oldStartTransform; // first, if it was a scale then the second-last transform will be it + if (N >= 3 && tlist.getItem(N - 2).type === 3 && tlist.getItem(N - 3).type === 2 && tlist.getItem(N - 1).type === 2) { operation = 3; // scale - // if the children are unrotated, pass the scale down directly // otherwise pass the equivalent matrix() down directly + var tm = tlist.getItem(N - 3).matrix, sm = tlist.getItem(N - 2).matrix, tmn = tlist.getItem(N - 1).matrix; - var children = selected.childNodes; var c = children.length; + while (c--) { var child = children.item(c); tx = 0; ty = 0; - if (child.nodeType === 1) { - var childTlist = getTransformList(child); - // some children might not have a transform (<metadata>, <defs>, etc) + if (child.nodeType === 1) { + var childTlist = getTransformList(child); // some children might not have a transform (<metadata>, <defs>, etc) + if (!childTlist) { continue; } - var _m2 = transformListToTransform(childTlist).matrix; - - // Convert a matrix to a scale if applicable + var _m = transformListToTransform(childTlist).matrix; // Convert a matrix to a scale if applicable // if (hasMatrixTransform(childTlist) && childTlist.numberOfItems == 1) { // if (m.b==0 && m.c==0 && m.e==0 && m.f==0) { // childTlist.removeItem(0); @@ -11220,32 +12381,30 @@ var angle = getRotationAngle(child); oldStartTransform = context_.getStartTransform(); + var childxforms = []; context_.setStartTransform(child.getAttribute('transform')); + if (angle || hasMatrixTransform(childTlist)) { var e2t = svgroot.createSVGTransform(); - e2t.setMatrix(matrixMultiply(tm, sm, tmn, _m2)); + e2t.setMatrix(matrixMultiply(tm, sm, tmn, _m)); childTlist.clear(); childTlist.appendItem(e2t); - // if not rotated or skewed, push the [T][S][-T] down to the child + childxforms.push(e2t); // if not rotated or skewed, push the [T][S][-T] down to the child } else { // update the transform list with translate,scale,translate - // slide the [T][S][-T] from the front to the back // [T][S][-T][M] = [M][T2][S2][-T2] - // (only bringing [-T] to the right of [M]) // [T][S][-T][M] = [T][S][M][-T2] // [-T2] = [M_inv][-T][M] - var t2n = matrixMultiply(_m2.inverse(), tmn, _m2); - // [T2] is always negative translation of [-T2] + var t2n = matrixMultiply(_m.inverse(), tmn, _m); // [T2] is always negative translation of [-T2] + var t2 = svgroot.createSVGMatrix(); t2.e = -t2n.e; - t2.f = -t2n.f; - - // [T][S][-T][M] = [M][T2][S2][-T2] + t2.f = -t2n.f; // [T][S][-T][M] = [M][T2][S2][-T2] // [S2] = [T2_inv][M_inv][T][S][-T][M][-T2_inv] - var s2 = matrixMultiply(t2.inverse(), _m2.inverse(), tm, sm, tmn, _m2, t2n.inverse()); + var s2 = matrixMultiply(t2.inverse(), _m.inverse(), tm, sm, tmn, _m, t2n.inverse()); var translateOrigin = svgroot.createSVGTransform(), scale = svgroot.createSVGTransform(), translateBack = svgroot.createSVGTransform(); @@ -11255,11 +12414,14 @@ childTlist.appendItem(translateBack); childTlist.appendItem(scale); childTlist.appendItem(translateOrigin); - // logMatrix(translateBack.matrix); + childxforms.push(translateBack); + childxforms.push(scale); + childxforms.push(translateOrigin); // logMatrix(translateBack.matrix); // logMatrix(scale.matrix); } // not rotated - batchCmd.addSubCommand(recalculateDimensions(child)); - // TODO: If any <use> have this group as a parent and are + + + batchCmd.addSubCommand(recalculateDimensions(child)); // TODO: If any <use> have this group as a parent and are // referencing this child, then we need to impose a reverse // scale on it so that when it won't get double-translated // const uses = selected.getElementsByTagNameNS(NS.SVG, 'use'); @@ -11274,30 +12436,37 @@ // batchCmd.addSubCommand( recalculateDimensions(useElem) ); // } // } + context_.setStartTransform(oldStartTransform); } // element + } // for each child // Remove these transforms from group + + tlist.removeItem(N - 1); tlist.removeItem(N - 2); tlist.removeItem(N - 3); } else if (N >= 3 && tlist.getItem(N - 1).type === 1) { operation = 3; // scale - _m = transformListToTransform(tlist).matrix; + + var _m2 = transformListToTransform(tlist).matrix; + var _e2t = svgroot.createSVGTransform(); - _e2t.setMatrix(_m); + + _e2t.setMatrix(_m2); + tlist.clear(); - tlist.appendItem(_e2t); - // next, check if the first transform was a translate + tlist.appendItem(_e2t); // next, check if the first transform was a translate // if we had [ T1 ] [ M ] we want to transform this into [ M ] [ T2 ] // therefore [ T2 ] = [ M_inv ] [ T1 ] [ M ] } else if ((N === 1 || N > 1 && tlist.getItem(1).type !== 3) && tlist.getItem(0).type === 2) { operation = 2; // translate + var T_M = transformListToTransform(tlist).matrix; tlist.removeItem(0); var mInv = transformListToTransform(tlist).matrix.inverse(); var M2 = matrixMultiply(mInv, T_M); - tx = M2.e; ty = M2.f; @@ -11305,16 +12474,17 @@ // we pass the translates down to the individual children var _children = selected.childNodes; var _c = _children.length; - var clipPathsDone = []; while (_c--) { var _child = _children.item(_c); + if (_child.nodeType === 1) { // Check if child has clip-path if (_child.getAttribute('clip-path')) { // tx, ty var attr = _child.getAttribute('clip-path'); + if (!clipPathsDone.includes(attr)) { updateClipPath(attr, tx, ty); clipPathsDone.push(attr); @@ -11324,25 +12494,30 @@ oldStartTransform = context_.getStartTransform(); context_.setStartTransform(_child.getAttribute('transform')); - var _childTlist = getTransformList(_child); - // some children might not have a transform (<metadata>, <defs>, etc) + var _childTlist = getTransformList(_child); // some children might not have a transform (<metadata>, <defs>, etc) + + if (_childTlist) { var newxlate = svgroot.createSVGTransform(); newxlate.setTranslate(tx, ty); + if (_childTlist.numberOfItems) { _childTlist.insertItemBefore(newxlate, 0); } else { _childTlist.appendItem(newxlate); } - batchCmd.addSubCommand(recalculateDimensions(_child)); - // If any <use> have this group as a parent and are + + batchCmd.addSubCommand(recalculateDimensions(_child)); // If any <use> have this group as a parent and are // referencing this child, then impose a reverse translate on it // so that when it won't get double-translated + var uses = selected.getElementsByTagNameNS(NS.SVG, 'use'); var href = '#' + _child.id; var u = uses.length; + while (u--) { var useElem = uses.item(u); + if (href === getHref(useElem)) { var usexlate = svgroot.createSVGTransform(); usexlate.setTranslate(-tx, -ty); @@ -11350,26 +12525,29 @@ batchCmd.addSubCommand(recalculateDimensions(useElem)); } } + context_.setStartTransform(oldStartTransform); } } } - clipPathsDone = []; context_.setStartTransform(oldStartTransform); - } - // else, a matrix imposition from a parent group + } // else, a matrix imposition from a parent group // keep pushing it down to the children + } else if (N === 1 && tlist.getItem(0).type === 1 && !gangle) { operation = 1; var _m3 = tlist.getItem(0).matrix, _children2 = selected.childNodes; var _c2 = _children2.length; + while (_c2--) { var _child2 = _children2.item(_c2); + if (_child2.nodeType === 1) { oldStartTransform = context_.getStartTransform(); context_.setStartTransform(_child2.getAttribute('transform')); + var _childTlist2 = getTransformList(_child2); if (!_childTlist2) { @@ -11379,40 +12557,46 @@ var em = matrixMultiply(_m3, transformListToTransform(_childTlist2).matrix); var e2m = svgroot.createSVGTransform(); e2m.setMatrix(em); + _childTlist2.clear(); + _childTlist2.appendItem(e2m, 0); batchCmd.addSubCommand(recalculateDimensions(_child2)); - context_.setStartTransform(oldStartTransform); - - // Convert stroke + context_.setStartTransform(oldStartTransform); // Convert stroke // TODO: Find out if this should actually happen somewhere else + var sw = _child2.getAttribute('stroke-width'); + if (_child2.getAttribute('stroke') !== 'none' && !isNaN(sw)) { var avg = (Math.abs(em.a) + Math.abs(em.d)) / 2; + _child2.setAttribute('stroke-width', sw * avg); } } } - tlist.clear(); - // else it was just a rotate + + tlist.clear(); // else it was just a rotate } else { if (gangle) { var newRot = svgroot.createSVGTransform(); newRot.setRotate(gangle, newcenter.x, newcenter.y); + if (tlist.numberOfItems) { tlist.insertItemBefore(newRot, 0); } else { tlist.appendItem(newRot); } } + if (tlist.numberOfItems === 0) { selected.removeAttribute('transform'); } - return null; - } - // if it was a translate, put back the rotate at the new center + return null; + } // if it was a translate, put back the rotate at the new center + + if (operation === 2) { if (gangle) { newcenter = { @@ -11421,14 +12605,16 @@ }; var _newRot = svgroot.createSVGTransform(); + _newRot.setRotate(gangle, newcenter.x, newcenter.y); + if (tlist.numberOfItems) { tlist.insertItemBefore(_newRot, 0); } else { tlist.appendItem(_newRot); } - } - // if it was a resize + } // if it was a resize + } else if (operation === 3) { var _m4 = transformListToTransform(tlist).matrix; var roldt = svgroot.createSVGTransform(); @@ -11436,6 +12622,7 @@ var rold = roldt.matrix; var rnew = svgroot.createSVGTransform(); rnew.setRotate(gangle, newcenter.x, newcenter.y); + var rnewInv = rnew.matrix.inverse(), _mInv = _m4.inverse(), extrat = matrixMultiply(_mInv, rnewInv, rold, _m4); @@ -11448,14 +12635,20 @@ // we pass the translates down to the individual children var _children3 = selected.childNodes; var _c3 = _children3.length; + while (_c3--) { var _child3 = _children3.item(_c3); + if (_child3.nodeType === 1) { oldStartTransform = context_.getStartTransform(); context_.setStartTransform(_child3.getAttribute('transform')); + var _childTlist3 = getTransformList(_child3); + var _newxlate = svgroot.createSVGTransform(); + _newxlate.setTranslate(tx, ty); + if (_childTlist3.numberOfItems) { _childTlist3.insertItemBefore(_newxlate, 0); } else { @@ -11475,33 +12668,39 @@ tlist.appendItem(rnew); } } - } - // else, it's a non-group + } // else, it's a non-group + } else { // FIXME: box might be null for some elements (<metadata> etc), need to handle this - var _box = getBBox(selected); - - // Paths (and possbly other shapes) will have no BBox while still in <defs>, + var _box = getBBox(selected); // Paths (and possbly other shapes) will have no BBox while still in <defs>, // but we still may need to recalculate them (see issue 595). // TODO: Figure out how to get BBox from these elements in case they // have a rotation transform + if (!_box && selected.tagName !== 'path') return null; - var _m5 = svgroot.createSVGMatrix(); + var _m5; // = svgroot.createSVGMatrix(); // temporarily strip off the rotate and save the old center + + var _angle = getRotationAngle(selected); + if (_angle) { - oldcenter = { x: _box.x + _box.width / 2, y: _box.y + _box.height / 2 }; + oldcenter = { + x: _box.x + _box.width / 2, + y: _box.y + _box.height / 2 + }; newcenter = transformPoint(_box.x + _box.width / 2, _box.y + _box.height / 2, transformListToTransform(tlist).matrix); var _a = _angle * Math.PI / 180; - var _s = Math.abs(_a) > 1.0e-10 ? Math.sin(_a) / (1 - Math.cos(_a)) - // FIXME: This blows up if the angle is exactly 0! + + var _s = Math.abs(_a) > 1.0e-10 ? Math.sin(_a) / (1 - Math.cos(_a)) // FIXME: This blows up if the angle is exactly 0! : 2 / _a; for (var _i2 = 0; _i2 < tlist.numberOfItems; ++_i2) { var _xform3 = tlist.getItem(_i2); + if (_xform3.type === 4) { // extract old center through mystical arts var _rm = _xform3.matrix; @@ -11511,22 +12710,23 @@ break; } } - } + } // 2 = translate, 3 = scale, 4 = rotate, 1 = matrix imposition + - // 2 = translate, 3 = scale, 4 = rotate, 1 = matrix imposition var _operation = 0; - var _N = tlist.numberOfItems; - - // Check if it has a gradient with userSpaceOnUse, in which case + var _N = tlist.numberOfItems; // Check if it has a gradient with userSpaceOnUse, in which case // adjust it by recalculating the matrix transform. // TODO: Make this work in Webkit using transformlist.SVGTransformList + if (!isWebkit()) { var fill = selected.getAttribute('fill'); + if (fill && fill.startsWith('url(')) { var paint = getRefElem(fill); var type = 'pattern'; if (paint.tagName !== type) type = 'gradient'; var attrVal = paint.getAttribute(type + 'Units'); + if (attrVal === 'userSpaceOnUse') { // Update the userSpaceOnUse element _m5 = transformListToTransform(tlist).matrix; @@ -11537,79 +12737,94 @@ paint.setAttribute(type + 'Transform', mStr); } } - } - - // first, if it was a scale of a non-skewed element, then the second-last + } // first, if it was a scale of a non-skewed element, then the second-last // transform will be the [S] // if we had [M][T][S][T] we want to extract the matrix equivalent of // [T][S][T] and push it down to the element + + if (_N >= 3 && tlist.getItem(_N - 2).type === 3 && tlist.getItem(_N - 3).type === 2 && tlist.getItem(_N - 1).type === 2) { // Removed this so a <use> with a given [T][S][T] would convert to a matrix. // Is that bad? // && selected.nodeName != 'use' _operation = 3; // scale + _m5 = transformListToTransform(tlist, _N - 3, _N - 1).matrix; tlist.removeItem(_N - 1); tlist.removeItem(_N - 2); - tlist.removeItem(_N - 3); - // if we had [T][S][-T][M], then this was a skewed element being resized + tlist.removeItem(_N - 3); // if we had [T][S][-T][M], then this was a skewed element being resized // Thus, we simply combine it all into one matrix } else if (_N === 4 && tlist.getItem(_N - 1).type === 1) { _operation = 3; // scale + _m5 = transformListToTransform(tlist).matrix; + var _e2t2 = svgroot.createSVGTransform(); + _e2t2.setMatrix(_m5); + tlist.clear(); - tlist.appendItem(_e2t2); - // reset the matrix so that the element is not re-mapped - _m5 = svgroot.createSVGMatrix(); - // if we had [R][T][S][-T][M], then this was a rotated matrix-element + tlist.appendItem(_e2t2); // reset the matrix so that the element is not re-mapped + + _m5 = svgroot.createSVGMatrix(); // if we had [R][T][S][-T][M], then this was a rotated matrix-element // if we had [T1][M] we want to transform this into [M][T2] // therefore [ T2 ] = [ M_inv ] [ T1 ] [ M ] and we can push [T2] // down to the element } else if ((_N === 1 || _N > 1 && tlist.getItem(1).type !== 3) && tlist.getItem(0).type === 2) { _operation = 2; // translate + var oldxlate = tlist.getItem(0).matrix, meq = transformListToTransform(tlist, 1).matrix, meqInv = meq.inverse(); _m5 = matrixMultiply(meqInv, oldxlate, meq); - tlist.removeItem(0); - // else if this child now has a matrix imposition (from a parent group) + tlist.removeItem(0); // else if this child now has a matrix imposition (from a parent group) // we might be able to simplify } else if (_N === 1 && tlist.getItem(0).type === 1 && !_angle) { // Remap all point-based elements _m5 = transformListToTransform(tlist).matrix; + switch (selected.tagName) { case 'line': changes = $$7(selected).attr(['x1', 'y1', 'x2', 'y2']); // Fallthrough + case 'polyline': case 'polygon': changes.points = selected.getAttribute('points'); + if (changes.points) { var _list = selected.points; var _len = _list.numberOfItems; changes.points = new Array(_len); + for (var _i3 = 0; _i3 < _len; ++_i3) { var _pt = _list.getItem(_i3); - changes.points[_i3] = { x: _pt.x, y: _pt.y }; + + changes.points[_i3] = { + x: _pt.x, + y: _pt.y + }; } } + // Fallthrough + case 'path': changes.d = selected.getAttribute('d'); _operation = 1; tlist.clear(); break; + default: break; - } - // if it was a rotation, put the rotate back and return without a command + } // if it was a rotation, put the rotate back and return without a command // (this function has zero work to do for a rotate()) + } else { - _operation = 4; // rotation + // operation = 4; // rotation if (_angle) { var _newRot2 = svgroot.createSVGTransform(); + _newRot2.setRotate(_angle, newcenter.x, newcenter.y); if (tlist.numberOfItems) { @@ -11618,18 +12833,21 @@ tlist.appendItem(_newRot2); } } + if (tlist.numberOfItems === 0) { selected.removeAttribute('transform'); } - return null; - } - // if it was a translate or resize, we need to remap the element and absorb the xform + return null; + } // if it was a translate or resize, we need to remap the element and absorb the xform + + if (_operation === 1 || _operation === 2 || _operation === 3) { remapElement(selected, changes, _m5); } // if we are remapping - // if it was a translate, put back the rotate at the new center + + if (_operation === 2) { if (_angle) { if (!hasMatrixTransform(tlist)) { @@ -11638,22 +12856,28 @@ y: oldcenter.y + _m5.f }; } + var _newRot3 = svgroot.createSVGTransform(); + _newRot3.setRotate(_angle, newcenter.x, newcenter.y); + if (tlist.numberOfItems) { tlist.insertItemBefore(_newRot3, 0); } else { tlist.appendItem(_newRot3); } - } - // We have special processing for tspans: Tspans are not transformable + } // We have special processing for tspans: Tspans are not transformable // but they can have x,y coordinates (sigh). Thus, if this was a translate, // on a text element, also translate any tspan children. + + if (selected.tagName === 'text') { var _children4 = selected.childNodes; var _c4 = _children4.length; + while (_c4--) { var _child4 = _children4.item(_c4); + if (_child4.tagName === 'tspan') { var tspanChanges = { x: $$7(_child4).attr('x') || 0, @@ -11662,23 +12886,33 @@ remapElement(_child4, tspanChanges, _m5); } } - } - // [Rold][M][T][S][-T] became [Rold][M] + } // [Rold][M][T][S][-T] became [Rold][M] // we want it to be [Rnew][M][Tr] where Tr is the // translation required to re-center it // Therefore, [Tr] = [M_inv][Rnew_inv][Rold][M] + } else if (_operation === 3 && _angle) { - var _m6 = transformListToTransform(tlist).matrix; + var _transformListToTrans = transformListToTransform(tlist), + matrix = _transformListToTrans.matrix; + var _roldt = svgroot.createSVGTransform(); + _roldt.setRotate(_angle, oldcenter.x, oldcenter.y); + var _rold = _roldt.matrix; + var _rnew = svgroot.createSVGTransform(); + _rnew.setRotate(_angle, newcenter.x, newcenter.y); + var _rnewInv = _rnew.matrix.inverse(); - var _mInv2 = _m6.inverse(); - var _extrat = matrixMultiply(_mInv2, _rnewInv, _rold, _m6); + + var _mInv2 = matrix.inverse(); + + var _extrat = matrixMultiply(_mInv2, _rnewInv, _rold, matrix); remapElement(selected, changes, _extrat); + if (_angle) { if (tlist.numberOfItems) { tlist.insertItemBefore(_rnew, 0); @@ -11688,54 +12922,52 @@ } } } // a non-group - // if the transform list has been emptied, remove it + + if (tlist.numberOfItems === 0) { selected.removeAttribute('transform'); } batchCmd.addSubCommand(new ChangeElementCommand(selected, initial)); - return batchCmd; }; - /* globals jQuery */ - var $$8 = jQuery; + var svgFactory_; + var config_; + var selectorManager_; // A Singleton - var svgFactory_ = void 0; - var config_ = void 0; - var selectorManager_ = void 0; // A Singleton var gripRadius = isTouch() ? 10 : 4; - /** - * Private class for DOM element selection boxes + * Private class for DOM element selection boxes. */ - var Selector = function () { + + var Selector = + /*#__PURE__*/ + function () { /** * @param {Integer} id - Internally identify the selector * @param {Element} elem - DOM element associated with this selector * @param {module:utilities.BBoxObject} [bbox] - Optional bbox to use for initialization (prevents duplicate `getBBox` call). */ function Selector(id, elem, bbox) { - classCallCheck(this, Selector); + _classCallCheck(this, Selector); // this is the selector's unique number - this.id = id; + this.id = id; // this holds a reference to the element for which this selector is being used - // this holds a reference to the element for which this selector is being used - this.selectedElement = elem; + this.selectedElement = elem; // this is a flag used internally to track whether the selector is being used or not - // this is a flag used internally to track whether the selector is being used or not - this.locked = true; + this.locked = true; // this holds a reference to the <g> element that holds all visual elements of the selector - // this holds a reference to the <g> element that holds all visual elements of the selector this.selectorGroup = svgFactory_.createSVGElement({ element: 'g', - attr: { id: 'selectorGroup' + this.id } - }); + attr: { + id: 'selectorGroup' + this.id + } + }); // this holds a reference to the path rect - // this holds a reference to the path rect this.selectorRect = this.selectorGroup.appendChild(svgFactory_.createSVGElement({ element: 'path', attr: { @@ -11747,9 +12979,8 @@ // need to specify this so that the rect is not selectable style: 'pointer-events:none' } - })); + })); // this holds a reference to the grip coordinates for this selector - // this holds a reference to the grip coordinates for this selector this.gripCoords = { nw: null, n: null, @@ -11760,80 +12991,51 @@ sw: null, w: null }; - this.reset(this.selectedElement, bbox); } - /** - * Used to reset the id and element that the selector is attached to + * Used to reset the id and element that the selector is attached to. * @param {Element} e - DOM element associated with this selector * @param {module:utilities.BBoxObject} bbox - Optional bbox to use for reset (prevents duplicate getBBox call). + * @returns {undefined} */ - createClass(Selector, [{ - key: 'reset', + _createClass(Selector, [{ + key: "reset", value: function reset(e, bbox) { this.locked = true; this.selectedElement = e; this.resize(bbox); 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 - */ - - }, { - key: 'updateGripCursors', - value: function updateGripCursors(angle) { - var dir = void 0; - var dirArr = []; - var 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--; - } - var 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 + * @returns {undefined} */ }, { - key: 'showGrips', + key: "showGrips", value: function showGrips(show) { var bShow = show ? 'inline' : 'none'; selectorManager_.selectorGripsGroup.setAttribute('display', bShow); var elem = this.selectedElement; this.hasGrips = show; + if (elem && show) { this.selectorGroup.append(selectorManager_.selectorGripsGroup); - this.updateGripCursors(getRotationAngle(elem)); + Selector.updateGripCursors(getRotationAngle(elem)); } } - /** - * Updates the selector to match the element's size + * Updates the selector to match the element's size. * @param {module:utilities.BBoxObject} [bbox] - BBox to use for resize (prevents duplicate getBBox call). + * @returns {undefined} */ }, { - key: 'resize', + key: "resize", value: function resize(bbox) { var selectedBox = this.selectorRect, mgr = selectorManager_, @@ -11842,6 +13044,7 @@ sw = selected.getAttribute('stroke-width'), currentZoom = svgFactory_.getCurrentZoom(); var offset = 1 / currentZoom; + if (selected.getAttribute('stroke') !== 'none' && !isNaN(sw)) { offset += sw / 2; } @@ -11850,57 +13053,53 @@ if (tagName === 'text') { offset += 2 / currentZoom; - } + } // loop and transform our bounding box until we reach our first rotation + - // loop and transform our bounding box until we reach our first rotation var tlist = getTransformList(selected); - var m = transformListToTransform(tlist).matrix; - - // This should probably be handled somewhere else, but for now + var m = transformListToTransform(tlist).matrix; // This should probably be handled somewhere else, but for now // it keeps the selection box correctly positioned when zoomed + m.e *= currentZoom; m.f *= currentZoom; if (!bbox) { bbox = getBBox(selected); - } - // TODO: getBBox (previous line) already knows to call getStrokedBBox when tagName === 'g'. Remove this? + } // TODO: getBBox (previous line) already knows to call getStrokedBBox when tagName === 'g'. Remove this? // TODO: getBBox doesn't exclude 'gsvg' and calls getStrokedBBox for any 'g'. Should getBBox be updated? + + if (tagName === 'g' && !$$8.data(selected, 'gsvg')) { // The bbox for a group does not include stroke vals, so we // get the bbox based on its children. var strokedBbox = getStrokedBBox([selected.childNodes]); + if (strokedBbox) { bbox = strokedBbox; } - } + } // apply the transforms + - // apply the transforms var l = bbox.x, t = bbox.y, w = bbox.width, - h = bbox.height; - bbox = { x: l, y: t, width: w, height: h }; - + h = bbox.height; // bbox = {x: l, y: t, width: w, height: h}; // Not in use // we need to handle temporary transforms too // if skewed, get its transformed box, then find its axis-aligned bbox - // * - offset *= currentZoom; + offset *= currentZoom; var nbox = transformBox(l * currentZoom, t * currentZoom, w * currentZoom, h * currentZoom, m), aabox = nbox.aabox; - var nbax = aabox.x - offset, nbay = aabox.y - offset, nbaw = aabox.width + offset * 2, - nbah = aabox.height + offset * 2; + nbah = aabox.height + offset * 2; // now if the shape is rotated, un-rotate it - // now if the shape is rotated, un-rotate it var cx = nbax + nbaw / 2, cy = nbay + nbah / 2; - var angle = getRotationAngle(selected); + if (angle) { var rot = svgFactory_.svgRoot().createSVGTransform(); rot.setRotate(-angle, cx, cy); @@ -11908,25 +13107,19 @@ nbox.tl = transformPoint(nbox.tl.x, nbox.tl.y, rotm); nbox.tr = transformPoint(nbox.tr.x, nbox.tr.y, rotm); nbox.bl = transformPoint(nbox.bl.x, nbox.bl.y, rotm); - nbox.br = transformPoint(nbox.br.x, nbox.br.y, rotm); + nbox.br = transformPoint(nbox.br.x, nbox.br.y, rotm); // calculate the axis-aligned bbox - // calculate the axis-aligned bbox var tl = nbox.tl; - var minx = tl.x, miny = tl.y, maxx = tl.x, maxy = tl.y; - var min = Math.min, max = Math.max; - - minx = min(minx, min(nbox.tr.x, min(nbox.bl.x, nbox.br.x))) - offset; miny = min(miny, min(nbox.tr.y, min(nbox.bl.y, nbox.br.y))) - offset; maxx = max(maxx, max(nbox.tr.x, max(nbox.bl.x, nbox.br.x))) + offset; maxy = max(maxy, max(nbox.tr.y, max(nbox.bl.y, nbox.br.y))) + offset; - nbax = minx; nbay = miny; nbaw = maxx - minx; @@ -11935,12 +13128,10 @@ var dstr = 'M' + nbax + ',' + nbay + ' L' + (nbax + nbaw) + ',' + nbay + ' ' + (nbax + nbaw) + ',' + (nbay + nbah) + ' ' + nbax + ',' + (nbay + nbah) + 'z'; selectedBox.setAttribute('d', dstr); - var xform = angle ? 'rotate(' + [angle, cx, cy].join(',') + ')' : ''; - this.selectorGroup.setAttribute('transform', xform); - - // TODO(codedread): Is this needed? + this.selectorGroup.setAttribute('transform', xform); // TODO(codedread): Is this needed? // if (selected === selectedElements[0]) { + this.gripCoords = { nw: [nbax, nbay], ne: [nbax + nbaw, nbay], @@ -11951,46 +13142,69 @@ e: [nbax + nbaw, nbay + nbah / 2], s: [nbax + nbaw / 2, nbay + nbah] }; - for (var dir in this.gripCoords) { - var coords = this.gripCoords[dir]; + Object.entries(this.gripCoords).forEach(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + dir = _ref2[0], + coords = _ref2[1]; + selectedGrips[dir].setAttribute('cx', coords[0]); selectedGrips[dir].setAttribute('cy', coords[1]); - } + }); // we want to go 20 pixels in the negative transformed y direction, ignoring scale - // we want to go 20 pixels in the negative transformed y direction, ignoring scale mgr.rotateGripConnector.setAttribute('x1', nbax + nbaw / 2); mgr.rotateGripConnector.setAttribute('y1', nbay); mgr.rotateGripConnector.setAttribute('x2', nbax + nbaw / 2); mgr.rotateGripConnector.setAttribute('y2', nbay - gripRadius * 5); - mgr.rotateGrip.setAttribute('cx', nbax + nbaw / 2); - mgr.rotateGrip.setAttribute('cy', nbay - gripRadius * 5); - // } + mgr.rotateGrip.setAttribute('cy', nbay - gripRadius * 5); // } } }]); + return Selector; }(); - /** - * Manage all selector objects (selection boxes) + * Updates cursors for corner grips on rotation so arrows point the right way. + * @param {Float} angle - Current rotation angle in degrees + * @returns {undefined} */ - var SelectorManager = function () { + + Selector.updateGripCursors = function (angle) { + var dirArr = Object.keys(selectorManager_.selectorGrips); + var steps = Math.round(angle / 45); + + if (steps < 0) { + steps += 8; + } + + while (steps > 0) { + dirArr.push(dirArr.shift()); + steps--; + } + + Object.values(selectorManager_.selectorGrips).forEach(function (gripElement, i) { + gripElement.setAttribute('style', 'cursor:' + dirArr[i] + '-resize'); + }); + }; + /** + * Manage all selector objects (selection boxes). + */ + + + var SelectorManager = + /*#__PURE__*/ + function () { function SelectorManager() { - classCallCheck(this, SelectorManager); + _classCallCheck(this, SelectorManager); // this will hold the <g> element that contains all selector rects/grips - this.selectorParentGroup = null; + this.selectorParentGroup = null; // this is a special rect that is used for multi-select - // this is a special rect that is used for multi-select - this.rubberBandBox = null; + this.rubberBandBox = null; // this will hold objects of type Selector (see above) - // this will hold objects of type Selector (see above) - this.selectors = []; + this.selectors = []; // this holds a map of SVG elements to their Selector object - // this holds a map of SVG elements to their Selector object - this.selectorMap = {}; + this.selectorMap = {}; // this holds a reference to the grip elements - // this holds a reference to the grip elements this.selectorGrips = { nw: null, n: null, @@ -12001,45 +13215,47 @@ sw: null, w: null }; - this.selectorGripsGroup = null; this.rotateGripConnector = null; this.rotateGrip = null; - this.initGroup(); } - /** - * Resets the parent selector group element + * Resets the parent selector group element. + * @returns {undefined} */ - createClass(SelectorManager, [{ - key: 'initGroup', + _createClass(SelectorManager, [{ + key: "initGroup", value: function initGroup() { + var _this = this; + // remove old selector parent group if it existed if (this.selectorParentGroup && this.selectorParentGroup.parentNode) { this.selectorParentGroup.remove(); - } + } // create parent selector group and add it to svgroot + - // create parent selector group and add it to svgroot this.selectorParentGroup = svgFactory_.createSVGElement({ element: 'g', - attr: { id: 'selectorParentGroup' } + attr: { + id: 'selectorParentGroup' + } }); this.selectorGripsGroup = svgFactory_.createSVGElement({ element: 'g', - attr: { display: 'none' } + attr: { + display: 'none' + } }); this.selectorParentGroup.append(this.selectorGripsGroup); svgFactory_.svgRoot().append(this.selectorParentGroup); - this.selectorMap = {}; this.selectors = []; - this.rubberBandBox = null; + this.rubberBandBox = null; // add the corner grips - // add the corner grips - for (var dir in this.selectorGrips) { + Object.keys(this.selectorGrips).forEach(function (dir) { var grip = svgFactory_.createSVGElement({ element: 'circle', attr: { @@ -12055,13 +13271,11 @@ 'pointer-events': 'all' } }); - $$8.data(grip, 'dir', dir); $$8.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(svgFactory_.createSVGElement({ element: 'line', attr: { @@ -12070,7 +13284,6 @@ 'stroke-width': '1' } })); - this.rotateGrip = this.selectorGripsGroup.appendChild(svgFactory_.createSVGElement({ element: 'circle', attr: { @@ -12088,7 +13301,7 @@ return; } - var _config_$dimensions = slicedToArray(config_.dimensions, 2), + var _config_$dimensions = _slicedToArray(config_.dimensions, 2), width = _config_$dimensions[0], height = _config_$dimensions[1]; @@ -12100,11 +13313,11 @@ height: height, x: 0, y: 0, - overflow: isWebkit() ? 'none' : 'visible', // Chrome 7 has a problem with this when zooming out + overflow: isWebkit() ? 'none' : 'visible', + // Chrome 7 has a problem with this when zooming out style: 'pointer-events:none' } }); - var rect = svgFactory_.createSVGElement({ element: 'rect', attr: { @@ -12117,16 +13330,13 @@ fill: '#FFF', style: 'pointer-events:none' } - }); - - // Both Firefox and WebKit are too slow with this filter region (especially at higher + }); // Both Firefox and WebKit are too slow with this filter region (especially at higher // zoom levels) and Opera has at least one bug // if (!isOpera()) rect.setAttribute('filter', 'url(#canvashadow)'); - canvasbg.append(rect); - svgFactory_.svgRoot().insertBefore(canvasbg, svgFactory_.svgContent()); - // Ok to replace above with `svgFactory_.svgContent().before(canvasbg);`? - } + canvasbg.append(rect); + svgFactory_.svgRoot().insertBefore(canvasbg, svgFactory_.svgContent()); // Ok to replace above with `svgFactory_.svgContent().before(canvasbg);`? + } /** * * @param {Element} elem - DOM element to get the selector for @@ -12135,18 +13345,19 @@ */ }, { - key: 'requestSelector', + key: "requestSelector", value: function requestSelector(elem, bbox) { - if (elem == null) { + if (isNullish(elem)) { return null; } - var N = this.selectors.length; - // If we've already acquired one for this element, return it. + var N = this.selectors.length; // If we've already acquired one for this element, return it. + if (_typeof(this.selectorMap[elem.id]) === 'object') { this.selectorMap[elem.id].locked = true; return this.selectorMap[elem.id]; } + for (var i = 0; i < N; ++i) { if (this.selectors[i] && !this.selectors[i].locked) { this.selectors[i].locked = true; @@ -12154,40 +13365,43 @@ this.selectorMap[elem.id] = this.selectors[i]; return this.selectors[i]; } - } - // if we reached here, no available selectors were found, we create one + } // if we reached here, no available selectors were found, we create one + + this.selectors[N] = new Selector(N, elem, bbox); this.selectorParentGroup.append(this.selectors[N].selectorGroup); this.selectorMap[elem.id] = this.selectors[N]; return this.selectors[N]; } - /** - * Removes the selector of the given element (hides selection box) + * Removes the selector of the given element (hides selection box). * * @param {Element} elem - DOM element to remove the selector for + * @returns {undefined} */ }, { - key: 'releaseSelector', + key: "releaseSelector", value: function releaseSelector(elem) { - if (elem == null) { + if (isNullish(elem)) { return; } + var N = this.selectors.length, sel = this.selectorMap[elem.id]; + if (!sel.locked) { // TODO(codedread): Ensure this exists in this module. - console.log('WARNING! selector was released but was already unlocked'); + console.log('WARNING! selector was released but was already unlocked'); // eslint-disable-line no-console } + for (var i = 0; i < N; ++i) { if (this.selectors[i] && this.selectors[i] === sel) { delete this.selectorMap[elem.id]; sel.locked = false; sel.selectedElement = null; - sel.showGrips(false); + sel.showGrips(false); // remove from DOM and store reference in JS but only if it exists in the DOM - // remove from DOM and store reference in JS but only if it exists in the DOM try { sel.selectorGroup.setAttribute('display', 'none'); } catch (e) {} @@ -12196,14 +13410,13 @@ } } } - /** * @returns {SVGRectElement} The rubberBandBox DOM element. This is the rectangle drawn by * the user for selecting/zooming */ }, { - key: 'getRubberBandBox', + key: "getRubberBandBox", value: function getRubberBandBox() { if (!this.rubberBandBox) { this.rubberBandBox = this.selectorParentGroup.appendChild(svgFactory_.createSVGElement({ @@ -12219,30 +13432,35 @@ } })); } + return this.rubberBandBox; } }]); + return SelectorManager; }(); - /** * An object that creates SVG elements for the canvas. * * @interface module:select.SVGFactory */ + /** * @function module:select.SVGFactory#createSVGElement * @param {module:utilities.EditorContext#addSVGElementFromJson} jsonMap * @returns {SVGElement} */ + /** * @function module:select.SVGFactory#svgRoot * @returns {SVGSVGElement} */ + /** * @function module:select.SVGFactory#svgContent * @returns {SVGSVGElement} */ + /** * @function module:select.SVGFactory#getCurrentZoom * @returns {Float} @@ -12254,6 +13472,7 @@ * @property {Float} 0 Width * @property {Float} 1 Height */ + /** * @typedef {PlainObject} module:select.Config * @property {string} imgPath @@ -12267,23 +13486,22 @@ * @param {module:select.SVGFactory} svgFactory - An object implementing the SVGFactory interface. * @returns {undefined} */ + var init$6 = function init(config, svgFactory) { config_ = config; svgFactory_ = svgFactory; selectorManager_ = new SelectorManager(); }; - /** * @function module:select.getSelectorManager * @returns {module:select.SelectorManager} The SelectorManager instance. */ + var getSelectorManager = function getSelectorManager() { return selectorManager_; }; - /* eslint-disable indent */ - - var $$9 = jqPluginSVG(jQuery); + var $$9 = jQueryPluginSVG(jQuery); var MoveElementCommand$1 = MoveElementCommand, InsertElementCommand$1 = InsertElementCommand, RemoveElementCommand$1 = RemoveElementCommand, @@ -12292,22 +13510,29 @@ UndoManager$1 = UndoManager, HistoryEventTypes$1 = HistoryEventTypes; - if (!window.console) { window.console = {}; - window.console.log = function (str) {}; - window.console.dir = function (str) {}; + + window.console.log = function (str) { + /* */ + }; + + window.console.dir = function (str) { + /* */ + }; } if (window.opera) { window.console.log = function (str) { window.opera.postError(str); }; - window.console.dir = function (str) {}; - } + window.console.dir = function (str) { + /* */ + }; + } /** - * The main SvgCanvas class that manages all SVG-related functions + * The main SvgCanvas class that manages all SVG-related functions. * @memberof module:svgcanvas * * @borrows module:coords.remapElement as #remapElement @@ -12335,62 +13560,58 @@ * @borrows module:path.pathActions.linkControlPoints as #linkControlPoints */ + var SvgCanvas = /** * @param {HTMLElement} container - The container HTML element that should hold the SVG root element * @param {module:SVGEditor.curConfig} config - An object that contains configuration data */ function SvgCanvas(container, config) { - classCallCheck(this, SvgCanvas); + _classCallCheck(this, SvgCanvas); // Alias Namespace constants - // Default configuration options var curConfig = { show_outside_canvas: true, selectNew: true, dimensions: [640, 480] - }; + }; // Update config with new one if given - // Update config with new one if given if (config) { $$9.extend(curConfig, config); - } + } // Array with width/height of canvas + - // Array with width/height of canvas var dimensions = curConfig.dimensions; - - - var canvas = this; - + var canvas = this; // eslint-disable-line consistent-this // "document" element associated with the container (same as window.document using default svg-editor.js) // NOTE: This is not actually a SVG document, but an HTML document. - var svgdoc = container.ownerDocument; - // This is a container for the document being edited, not the document itself. + var svgdoc = container.ownerDocument; // This is a container for the document being edited, not the document itself. + /** * @name module:svgcanvas~svgroot * @type {SVGSVGElement} */ + var svgroot = svgdoc.importNode(text2xml('<svg id="svgroot" xmlns="' + NS.SVG + '" xlinkns="' + NS.XLINK + '" ' + 'width="' + dimensions[0] + '" height="' + dimensions[1] + '" x="' + dimensions[0] + '" y="' + dimensions[1] + '" overflow="visible">' + '<defs>' + '<filter id="canvashadow" filterUnits="objectBoundingBox">' + '<feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur"/>' + '<feOffset in="blur" dx="5" dy="5" result="offsetBlur"/>' + '<feMerge>' + '<feMergeNode in="offsetBlur"/>' + '<feMergeNode in="SourceGraphic"/>' + '</feMerge>' + '</filter>' + '</defs>' + '</svg>').documentElement, true); container.append(svgroot); - /** * The actual element that represents the final output SVG element * @name module:svgcanvas~svgcontent * @type {SVGSVGElement} */ - var svgcontent = svgdoc.createElementNS(NS.SVG, 'svg'); + var svgcontent = svgdoc.createElementNS(NS.SVG, 'svg'); /** * This function resets the svgcontent element while keeping it in the DOM. * @function module:svgcanvas.SvgCanvas#clearSvgContentElement * @returns {undefined} */ - var clearSvgContentElement = canvas.clearSvgContentElement = function () { - $$9(svgcontent).empty(); - // TODO: Clear out all other attributes first? + var clearSvgContentElement = canvas.clearSvgContentElement = function () { + $$9(svgcontent).empty(); // TODO: Clear out all other attributes first? + $$9(svgcontent).attr({ id: 'svgcontent', width: dimensions[0], @@ -12401,53 +13622,52 @@ xmlns: NS.SVG, 'xmlns:se': NS.SE, 'xmlns:xlink': NS.XLINK - }).appendTo(svgroot); + }).appendTo(svgroot); // TODO: make this string optional and set by the client - // TODO: make this string optional and set by the client var comment = svgdoc.createComment(' Created with SVG-edit - https://github.com/SVG-Edit/svgedit'); svgcontent.append(comment); }; - clearSvgContentElement(); - // Prefix string for element IDs + clearSvgContentElement(); // Prefix string for element IDs + var idprefix = 'svg_'; - /** - * Changes the ID prefix to the given value + * Changes the ID prefix to the given value. * @function module:svgcanvas.SvgCanvas#setIdPrefix * @param {string} p - String with the new prefix * @returns {undefined} */ + canvas.setIdPrefix = function (p) { idprefix = p; }; - /** * Current draw.Drawing object * @type {module:draw.Drawing} * @name module:svgcanvas.SvgCanvas#current_drawing_ */ - canvas.current_drawing_ = new Drawing(svgcontent, idprefix); + + canvas.current_drawing_ = new Drawing(svgcontent, idprefix); /** * Returns the current Drawing. * @function module:svgcanvas.SvgCanvas#getCurrentDrawing * @implements {module:draw.DrawCanvasInit#getCurrentDrawing} */ + var getCurrentDrawing = canvas.getCurrentDrawing = function () { return canvas.current_drawing_; }; - /** * Float displaying the current zoom level (1 = 100%, .5 = 50%, etc) * @type {Float} */ - var currentZoom = 1; - // pointer to current group (for in-group editing) - var currentGroup = null; - // Object containing data for the currently selected styles + var currentZoom = 1; // pointer to current group (for in-group editing) + + var currentGroup = null; // Object containing data for the currently selected styles + var allProperties = { shape: { fill: (curConfig.initFill.color === 'none' ? '' : '#') + curConfig.initFill.color, @@ -12463,22 +13683,18 @@ opacity: curConfig.initOpacity } }; - allProperties.text = $$9.extend(true, {}, allProperties.shape); $$9.extend(allProperties.text, { fill: '#000000', stroke_width: curConfig.text && curConfig.text.stroke_width, font_size: curConfig.text && curConfig.text.font_size, font_family: curConfig.text && curConfig.text.font_family - }); + }); // Current shape style properties - // Current shape style properties - var curShape = allProperties.shape; - - // Array with all the currently selected elements + var curShape = allProperties.shape; // Array with all the currently selected elements // default size of 1 until it needs to grow bigger - var selectedElements = []; + var selectedElements = []; /** * @typedef {PlainObject} module:svgcanvas.SVGAsJSON * @property {string} element @@ -12491,52 +13707,55 @@ * @param {Text|Element} data * @returns {module:svgcanvas.SVGAsJSON} */ + var getJsonFromSvgElement = this.getJsonFromSvgElement = function (data) { // Text node if (data.nodeType === 3) return data.nodeValue; - var retval = { element: data.tagName, // namespace: nsMap[data.namespaceURI], attr: {}, children: [] - }; + }; // Iterate attributes - // Iterate attributes for (var i = 0, attr; attr = data.attributes[i]; i++) { retval.attr[attr.name] = attr.value; - } + } // Iterate children + - // Iterate children for (var _i = 0, node; node = data.childNodes[_i]; _i++) { retval.children[_i] = getJsonFromSvgElement(node); } return retval; }; - /** - * This should really be an intersection implementing all rather than a union + * This should really be an intersection implementing all rather than a union. * @function module:svgcanvas.SvgCanvas#addSVGElementFromJson * @implements {module:utilities.EditorContext#addSVGElementFromJson|module:path.EditorContext#addSVGElementFromJson} */ + + var addSVGElementFromJson = this.addSVGElementFromJson = function (data) { if (typeof data === 'string') return svgdoc.createTextNode(data); + var shape = getElem(data.attr.id); // if shape is a path but we need to create a rect/ellipse, then remove the path - var shape = getElem(data.attr.id); - // if shape is a path but we need to create a rect/ellipse, then remove the path var currentLayer = getCurrentDrawing().getCurrentLayer(); + if (shape && data.element !== shape.tagName) { shape.remove(); shape = null; } + if (!shape) { var ns = data.namespace || NS.SVG; shape = svgdoc.createElementNS(ns, data.element); + if (currentLayer) { (currentGroup || currentLayer).append(shape); } } + if (data.curStyles) { assignAttributes(shape, { fill: curShape.fill, @@ -12551,10 +13770,10 @@ style: 'pointer-events:inherit' }, 100); } - assignAttributes(shape, data.attr, 100); - cleanupElement(shape); - // Children + assignAttributes(shape, data.attr, 100); + cleanupElement(shape); // Children + if (data.children) { data.children.forEach(function (child) { shape.append(addSVGElementFromJson(child)); @@ -12565,22 +13784,22 @@ }; canvas.getTransformList = getTransformList; - canvas.matrixMultiply = matrixMultiply; canvas.hasMatrixTransform = hasMatrixTransform; canvas.transformListToTransform = transformListToTransform; - /** * @implements {module:utilities.EditorContext#getBaseUnit} */ + var getBaseUnit = function getBaseUnit() { return curConfig.baseUnit; }; - /** * initialize from units.js. * Send in an object implementing the ElementContainer interface (see units.js) */ + + init( /** * @implements {module:units.ElementContainer} @@ -12598,32 +13817,32 @@ return saveOptions.round_digits; } }); - canvas.convertToNum = convertToNum; - /** - * This should really be an intersection implementing all rather than a union + * This should really be an intersection implementing all rather than a union. * @implements {module:draw.DrawCanvasInit#getSVGContent|module:utilities.EditorContext#getSVGContent} */ + var getSVGContent = function getSVGContent() { return svgcontent; }; - /** - * Should really be an intersection with all needing to apply rather than a union + * Should really be an intersection with all needing to apply rather than a union. * @function module:svgcanvas.SvgCanvas#getSelectedElements * @implements {module:utilities.EditorContext#getSelectedElements|module:draw.DrawCanvasInit#getSelectedElements|module:path.EditorContext#getSelectedElements} */ + + var getSelectedElements = this.getSelectedElems = function () { return selectedElements; }; - var pathActions$$1 = pathActions; - + var pathActions$1 = pathActions; /** - * This should actually be an intersection as all interfaces should be met + * This should actually be an intersection as all interfaces should be met. * @implements {module:utilities.EditorContext#getSVGRoot|module:recalculate.EditorContext#getSVGRoot|module:coords.EditorContext#getSVGRoot|module:path.EditorContext#getSVGRoot} */ + var getSVGRoot = function getSVGRoot() { return svgroot; }; @@ -12633,7 +13852,8 @@ * @implements {module:utilities.EditorContext} */ { - pathActions: pathActions$$1, // Ok since not modifying + pathActions: pathActions$1, + // Ok since not modifying getSVGContent: getSVGContent, addSVGElementFromJson: addSVGElementFromJson, getSelectedElements: getSelectedElements, @@ -12643,7 +13863,6 @@ getDOMContainer: function getDOMContainer() { return container; }, - getSVGRoot: getSVGRoot, // TODO: replace this mostly with a way to get the current drawing. getBaseUnit: getBaseUnit, @@ -12651,23 +13870,23 @@ return curConfig.snappingStep; } }); - canvas.findDefs = findDefs; canvas.getUrlFromAttr = getUrlFromAttr; canvas.getHref = getHref; canvas.setHref = setHref; - /* const getBBox = */canvas.getBBox = getBBox; + /* const getBBox = */ + + canvas.getBBox = getBBox; canvas.getRotationAngle = getRotationAngle; canvas.getElem = getElem; canvas.getRefElem = getRefElem; canvas.assignAttributes = assignAttributes; - this.cleanupElement = cleanupElement; - /** - * This should actually be an intersection not a union as all should apply + * This should actually be an intersection not a union as all should apply. * @implements {module:coords.EditorContext|module:path.EditorContext} */ + var getGridSnapping = function getGridSnapping() { return curConfig.gridSnapping; }; @@ -12680,12 +13899,10 @@ getDrawing: function getDrawing() { return getCurrentDrawing(); }, - getSVGRoot: getSVGRoot, getGridSnapping: getGridSnapping }); this.remapElement = remapElement; - init$5( /** * @implements {module:recalculate.EditorContext} @@ -12699,17 +13916,16 @@ startTransform = transform; } }); - this.recalculateDimensions = recalculateDimensions; + this.recalculateDimensions = recalculateDimensions; // import from sanitize.js - // import from sanitize.js var nsMap = getReverseNS(); canvas.sanitizeSvg = sanitizeSvg; - /** * @name undoMgr * @memberof module:svgcanvas.SvgCanvas# * @type {module:history.HistoryEventHandler} */ + var undoMgr = canvas.undoMgr = new UndoManager$1({ /** * @param {string} eventType One of the HistoryEvent types @@ -12718,8 +13934,8 @@ * @returns {undefined} */ handleHistoryEvent: function handleHistoryEvent(eventType, cmd) { - var EventTypes = HistoryEventTypes$1; - // TODO: handle setBlurOffsets. + var EventTypes = HistoryEventTypes$1; // TODO: handle setBlurOffsets. + if (eventType === EventTypes.BEFORE_UNAPPLY || eventType === EventTypes.BEFORE_APPLY) { canvas.clearSelection(); } else if (eventType === EventTypes.AFTER_APPLY || eventType === EventTypes.AFTER_UNAPPLY) { @@ -12728,8 +13944,10 @@ call('changed', elems); var cmdType = cmd.type(); var isApply = eventType === EventTypes.AFTER_APPLY; + if (cmdType === MoveElementCommand$1.type()) { var parent = isApply ? cmd.newParent : cmd.oldParent; + if (parent === svgcontent) { identifyLayers(); } @@ -12737,15 +13955,15 @@ if (cmd.parent === svgcontent) { identifyLayers(); } + if (cmdType === InsertElementCommand$1.type()) { if (isApply) { restoreRefElems(cmd.elem); } - } else { - if (!isApply) { - restoreRefElems(cmd.elem); - } + } else if (!isApply) { + restoreRefElems(cmd.elem); } + if (cmd.elem.tagName === 'use') { setUseData(cmd.elem); } @@ -12754,12 +13972,12 @@ if (cmd.elem.tagName === 'title' && cmd.elem.parentNode.parentNode === svgcontent) { identifyLayers(); } - var values = isApply ? cmd.newValues : cmd.oldValues; - // If stdDeviation was changed, update the blur. + + var values = isApply ? cmd.newValues : cmd.oldValues; // If stdDeviation was changed, update the blur. + if (values.stdDeviation) { canvas.setBlurOffsets(cmd.elem.parentNode, values.stdDeviation); - } - // This is resolved in later versions of webkit, perhaps we should + } // This is resolved in later versions of webkit, perhaps we should // have a featured detection for correct 'use' behavior? // —————————— // Remove & Re-add hack for Webkit (issue 775) @@ -12773,36 +13991,39 @@ // // Ok to replace above with this? `sib.before(elem);` // } // } + } } } }); - /** - * This should really be an intersection applying to all types rather than a union + * This should really be an intersection applying to all types rather than a union. * @function module:svgcanvas~addCommandToHistory * @implements {module:path.EditorContext#addCommandToHistory|module:draw.DrawCanvasInit#addCommandToHistory} */ + var addCommandToHistory = function addCommandToHistory(cmd) { canvas.undoMgr.addCommandToHistory(cmd); }; - /** - * This should really be an intersection applying to all types rather than a union + * This should really be an intersection applying to all types rather than a union. * @function module:svgcanvas.SvgCanvas#getZoom * @implements {module:path.EditorContext#getCurrentZoom|module:select.SVGFactory#getCurrentZoom} */ + + var getCurrentZoom = this.getZoom = function () { return currentZoom; }; - /** * This method rounds the incoming value to the nearest value based on the `currentZoom` * @function module:svgcanvas.SvgCanvas#round * @implements {module:path.EditorContext#round} */ + + var round = this.round = function (val) { - return parseInt(val * currentZoom, 10) / currentZoom; + return parseInt(val * currentZoom) / currentZoom; }; init$6(curConfig, @@ -12820,7 +14041,6 @@ svgContent: function svgContent() { return svgcontent; }, - getCurrentZoom: getCurrentZoom }); /** @@ -12828,50 +14048,57 @@ * @name module:svgcanvas.SvgCanvas#selectorManager * @type {module:select.SelectorManager} */ - var selectorManager = this.selectorManager = getSelectorManager(); + var selectorManager = this.selectorManager = getSelectorManager(); /** * @function module:svgcanvas.SvgCanvas#getNextId * @implements {module:path.EditorContext#getNextId} */ + var getNextId = canvas.getNextId = function () { return getCurrentDrawing().getNextId(); }; - /** * @function module:svgcanvas.SvgCanvas#getId * @implements {module:path.EditorContext#getId} */ + + var getId = canvas.getId = function () { return getCurrentDrawing().getId(); }; - /** - * The "implements" should really be an intersection applying to all types rather than a union + * The "implements" should really be an intersection applying to all types rather than a union. * @function module:svgcanvas.SvgCanvas#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 {module:svgcanvas.SvgCanvas#event:GenericCanvasEvent} arg - Argument to pass through to the callback function. - * @returns {undefined} + * @returns {module:svgcanvas.EventHandlerReturn|undefined} */ + + var call = function call(ev, arg) { if (events[ev]) { return events[ev](window, arg); } - }; + return undefined; + }; /** * Clears the selection. The 'selected' handler is then optionally called. - * This should really be an intersection applying to all types rather than a union + * This should really be an intersection applying to all types rather than a union. * @function module:svgcanvas.SvgCanvas#clearSelection * @implements {module:draw.DrawCanvasInit#clearSelection|module:path.EditorContext#clearSelection} * @fires module:svgcanvas.SvgCanvas#event:selected */ + + var clearSelection = this.clearSelection = function (noCall) { selectedElements.forEach(function (elem) { - if (elem == null) { + if (isNullish(elem)) { return; } + selectorManager.releaseSelector(elem); }); selectedElements = []; @@ -12880,35 +14107,42 @@ call('selected', selectedElements); } }; - /** * Adds a list of elements to the selection. The 'selected' handler is then called. * @function module:svgcanvas.SvgCanvas#addToSelection * @implements {module:path.EditorContext#addToSelection} * @fires module:svgcanvas.SvgCanvas#event:selected */ + + var addToSelection = this.addToSelection = function (elemsToAdd, showGrips) { if (!elemsToAdd.length) { return; - } - // find the first null in our selectedElements array + } // find the first null in our selectedElements array + var j = 0; + while (j < selectedElements.length) { - if (selectedElements[j] == null) { + if (isNullish(selectedElements[j])) { break; } - ++j; - } - // now add each element consecutively + ++j; + } // now add each element consecutively + + var i = elemsToAdd.length; + while (i--) { var elem = elemsToAdd[i]; + if (!elem) { continue; } + var bbox = getBBox(elem); + if (!bbox) { continue; } @@ -12916,14 +14150,13 @@ if (elem.tagName === 'a' && elem.childNodes.length === 1) { // Make "a" element's child be the selected element elem = elem.firstChild; - } + } // if it's not already there, add it + - // if it's not already there, add it if (!selectedElements.includes(elem)) { - selectedElements[j] = elem; - - // only the first selectedBBoxes element is ever used in the codebase these days + selectedElements[j] = elem; // only the first selectedBBoxes element is ever used in the codebase these days // if (j === 0) selectedBBoxes[0] = utilsGetBBox(elem); + j++; var sel = selectorManager.requestSelector(elem, bbox); @@ -12932,75 +14165,80 @@ } } } + call('selected', selectedElements); if (showGrips || selectedElements.length === 1) { selectorManager.requestSelector(selectedElements[0]).showGrips(true); } else { selectorManager.requestSelector(selectedElements[0]).showGrips(false); - } - - // make sure the elements are in the correct order + } // make sure the elements are in the correct order // See: https://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-compareDocumentPosition + selectedElements.sort(function (a, b) { if (a && b && a.compareDocumentPosition) { - return 3 - (b.compareDocumentPosition(a) & 6); + return 3 - (b.compareDocumentPosition(a) & 6); // eslint-disable-line no-bitwise } - if (a == null) { + + if (isNullish(a)) { return 1; } - }); - // Make sure first elements are not null - while (selectedElements[0] == null) { + return 0; + }); // Make sure first elements are not null + + while (isNullish(selectedElements[0])) { selectedElements.shift(0); } }; - /** * @implements {module:path.EditorContext#getOpacity} */ + + var getOpacity = function getOpacity() { return curShape.opacity; }; - /** * @function module:svgcanvas.SvgCanvas#getMouseTarget * @implements {module:path.EditorContext#getMouseTarget} */ + + var getMouseTarget = this.getMouseTarget = function (evt) { - if (evt == null) { + if (isNullish(evt)) { return null; } - var mouseTarget = evt.target; - // if it was a <use>, Opera and WebKit return the SVGElementInstance + var mouseTarget = evt.target; // if it was a <use>, Opera and WebKit return the SVGElementInstance + if (mouseTarget.correspondingUseElement) { mouseTarget = mouseTarget.correspondingUseElement; - } - - // for foreign content, go up until we find the foreignObject + } // for foreign content, go up until we find the foreignObject // WebKit browsers set the mouse target to the svgcanvas div + + if ([NS.MATH, NS.HTML].includes(mouseTarget.namespaceURI) && mouseTarget.id !== 'svgcanvas') { while (mouseTarget.nodeName !== 'foreignObject') { mouseTarget = mouseTarget.parentNode; + if (!mouseTarget) { return svgroot; } } - } - - // Get the desired mouseTarget with jQuery selector-fu + } // Get the desired mouseTarget with jQuery selector-fu // If it's root-like, select the root + + var currentLayer = getCurrentDrawing().getCurrentLayer(); + if ([svgroot, container, svgcontent, currentLayer].includes(mouseTarget)) { return svgroot; } - var $target = $$9(mouseTarget); + var $target = $$9(mouseTarget); // If it's a selection grip, return the grip parent - // If it's a selection grip, return the grip parent if ($target.closest('#selectorParentGroup').length) { // While we could instead have just returned mouseTarget, // this makes it easier to indentify as being a selector grip @@ -13009,9 +14247,7 @@ while (mouseTarget.parentNode !== (currentGroup || currentLayer)) { mouseTarget = mouseTarget.parentNode; - } - - // + } // // // go up until we hit a child of a layer // while (mouseTarget.parentNode.parentNode.tagName == 'g') { // mouseTarget = mouseTarget.parentNode; @@ -13022,28 +14258,34 @@ // mouseTarget = svgroot; // } + return mouseTarget; }; - /** * @namespace {module:path.pathActions} pathActions * @memberof module:svgcanvas.SvgCanvas# * @see module:path.pathActions */ - canvas.pathActions = pathActions$$1; + + + canvas.pathActions = pathActions$1; /** * @implements {module:path.EditorContext#resetD} */ + function resetD(p) { - p.setAttribute('d', pathActions$$1.convertPath(p)); + p.setAttribute('d', pathActions$1.convertPath(p)); } + init$1( /** * @implements {module:path.EditorContext} */ { - selectorManager: selectorManager, // Ok since not changing - canvas: canvas, // Ok since not changing + selectorManager: selectorManager, + // Ok since not changing + canvas: canvas, + // Ok since not changing call: call, resetD: resetD, round: round, @@ -13070,36 +14312,39 @@ }, /** - * @param {boolean} closedSubpath - * @param {SVGCircleElement[]} grips + * @param {PlainObject} ptsInfo + * @param {boolean} ptsInfo.closedSubpath + * @param {SVGCircleElement[]} ptsInfo.grips * @fires module:svgcanvas.SvgCanvas#event:pointsAdded * @fires module:svgcanvas.SvgCanvas#event:selected + * @returns {undefined} */ addPtsToSelection: function addPtsToSelection(_ref) { var closedSubpath = _ref.closedSubpath, grips = _ref.grips; - // TODO: Correct this: - pathActions$$1.canDeleteNodes = true; - pathActions$$1.closed_subpath = closedSubpath; - call('pointsAdded', { closedSubpath: closedSubpath, grips: grips }); + pathActions$1.canDeleteNodes = true; + pathActions$1.closed_subpath = closedSubpath; + call('pointsAdded', { + closedSubpath: closedSubpath, + grips: grips + }); call('selected', grips); }, /** - * @param {ChangeElementCommand} cmd - * @param {SVGPathElement} elem + * @param {PlainObject} changes + * @param {ChangeElementCommand} changes.cmd + * @param {SVGPathElement} changes.elem * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ endChanges: function endChanges(_ref2) { var cmd = _ref2.cmd, elem = _ref2.elem; - addCommandToHistory(cmd); call('changed', [elem]); }, - getCurrentZoom: getCurrentZoom, getId: getId, getNextId: getNextId, @@ -13118,19 +14363,14 @@ drawnPath = dp; return drawnPath; }, - getSVGRoot: getSVGRoot - }); + }); // Interface strings, usually for title elements - // Interface strings, usually for title elements var uiStrings = {}; - var visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use'; var refAttrs = ['clip-path', 'fill', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'stroke']; + var elData = $$9.data; // Animation element to change the opacity of any newly created element - var elData = $$9.data; - - // Animation element to change the opacity of any newly created element var opacAni = document.createElementNS(NS.SVG, 'animate'); $$9(opacAni).attr({ attributeName: 'opacity', @@ -13142,18 +14382,17 @@ var restoreRefElems = function restoreRefElems(elem) { // Look for missing reference elements, restore any found var attrs = $$9(elem).attr(refAttrs); - for (var o in attrs) { - var val = attrs[o]; + Object.values(attrs).forEach(function (val) { if (val && val.startsWith('url(')) { var id = getUrlFromAttr(val).substr(1); var ref = getElem(id); + if (!ref) { findDefs().append(removedElements[id]); delete removedElements[id]; } } - } - + }); var childs = elem.getElementsByTagName('*'); if (childs.length) { @@ -13161,9 +14400,7 @@ restoreRefElems(childs[i]); } } - }; - - // (function () { + }; // (function () { // TODO For Issue 208: this is a start on a thumbnail // const svgthumb = svgdoc.createElementNS(NS.SVG, 'use'); // svgthumb.setAttribute('width', '100'); @@ -13178,84 +14415,71 @@ * @property {"embed"} [image] * @property {Integer} round_digits */ - // Object to contain image data for raster images that were found encodable + + var encodableImages = {}, + // Object with save options - - // Object with save options /** * @type {module:svgcanvas.SaveOptions} */ - saveOptions = { round_digits: 5 }, - - - // Object with IDs for imported files, to see if one was already added + saveOptions = { + round_digits: 5 + }, + // Object with IDs for imported files, to see if one was already added importIds = {}, - - - // Current text style properties + // Current text style properties curText = allProperties.text, - - - // Object to contain all included extensions + // Object to contain all included extensions extensions = {}, - - - // Map of deleted reference elements + // Map of deleted reference elements removedElements = {}; - - var - // String with image URL of last loadable image + var // String with image URL of last loadable image lastGoodImgUrl = curConfig.imgPath + 'logo.png', - - - // Boolean indicating whether or not a draw action has been started + // Boolean indicating whether or not a draw action has been started started = false, - - - // String with an element's initial transform attribute value + // String with an element's initial transform attribute value startTransform = null, - - - // String indicating the current editor mode + // String indicating the current editor mode currentMode = 'select', - - - // String with the current direction in which an element is being resized + // String with the current direction in which an element is being resized currentResizeMode = 'none', - - - // Current general properties + // Current general properties curProperties = curShape, - - - // Array with selected elements' Bounding box object + // Array with selected elements' Bounding box object // selectedBBoxes = new Array(1), - // The DOM element that was just selected justSelected = null, - - - // DOM element for selection rectangle drawn by the user + // DOM element for selection rectangle drawn by the user rubberBox = null, - - - // Array of current BBoxes, used in getIntersectionList(). + // Array of current BBoxes, used in getIntersectionList(). curBBoxes = [], - - - // Canvas point for the most recent right click + // Canvas point for the most recent right click lastClickPoint = null; + this.runExtension = function (name, action, vars) { + return this.runExtensions(action, vars, false, function (n) { + return n === name; + }); + }; /** * @typedef {module:svgcanvas.ExtensionMouseDownStatus|module:svgcanvas.ExtensionMouseUpStatus|module:svgcanvas.ExtensionIDsUpdatedStatus|module:locale.ExtensionLocaleData[]|undefined} module:svgcanvas.ExtensionStatus * @tutorial ExtensionDocs */ + /** * @callback module:svgcanvas.ExtensionVarBuilder * @param {string} name The name of the extension + * @returns {module:svgcanvas.SvgCanvas#event:ext-addLangData} */ + + /** + * @callback module:svgcanvas.ExtensionNameFilter + * @param {string} name + * @returns {boolean} + */ + /** * @todo Consider: Should this return an array by default, so extension results aren't overwritten? * @todo Would be easier to document if passing in object with key of action and vars as value; could then define an interface which tied both together @@ -13263,15 +14487,23 @@ * @param {"mouseDown"|"mouseMove"|"mouseUp"|"zoomChanged"|"IDsUpdated"|"canvasUpdated"|"toolButtonStateUpdate"|"selectedChanged"|"elementTransition"|"elementChanged"|"langReady"|"langChanged"|"addLangData"|"onNewDocument"|"workareaResized"} action * @param {module:svgcanvas.SvgCanvas#event:ext-mouseDown|module:svgcanvas.SvgCanvas#event:ext-mouseMove|module:svgcanvas.SvgCanvas#event:ext-mouseUp|module:svgcanvas.SvgCanvas#event:ext-zoomChanged|module:svgcanvas.SvgCanvas#event:ext-IDsUpdated|module:svgcanvas.SvgCanvas#event:ext-canvasUpdated|module:svgcanvas.SvgCanvas#event:ext-toolButtonStateUpdate|module:svgcanvas.SvgCanvas#event:ext-selectedChanged|module:svgcanvas.SvgCanvas#event:ext-elementTransition|module:svgcanvas.SvgCanvas#event:ext-elementChanged|module:svgcanvas.SvgCanvas#event:ext-langReady|module:svgcanvas.SvgCanvas#event:ext-langChanged|module:svgcanvas.SvgCanvas#event:ext-addLangData|module:svgcanvas.SvgCanvas#event:ext-onNewDocument|module:svgcanvas.SvgCanvas#event:ext-workareaResized|module:svgcanvas.ExtensionVarBuilder} [vars] * @param {boolean} [returnArray] + * @param {module:svgcanvas.ExtensionNameFilter} nameFilter * @returns {GenericArray.<module:svgcanvas.ExtensionStatus>|module:svgcanvas.ExtensionStatus|false} See {@tutorial ExtensionDocs} on the ExtensionStatus. */ - var runExtensions = this.runExtensions = function (action, vars, returnArray) { + + + var runExtensions = this.runExtensions = function (action, vars, returnArray, nameFilter) { var result = returnArray ? [] : false; $$9.each(extensions, function (name, ext) { + if (nameFilter && !nameFilter(name)) { + return; + } + if (ext && action in ext) { if (typeof vars === 'function') { vars = vars(name); // ext, action } + if (returnArray) { result.push(ext[action](vars)); } else { @@ -13281,17 +14513,18 @@ }); return result; }; - /** * @typedef {PlainObject} module:svgcanvas.ExtensionMouseDownStatus * @property {boolean} started Indicates that creating/editing has started */ + /** * @typedef {PlainObject} module:svgcanvas.ExtensionMouseUpStatus * @property {boolean} keep Indicates if the current element should be kept * @property {boolean} started Indicates if editing should still be considered as "started" * @property {Element} element The element being affected */ + /** * @typedef {PlainObject} module:svgcanvas.ExtensionIDsUpdatedStatus * @property {string[]} remove Contains string IDs (used by `ext-connector.js`) @@ -13303,83 +14536,100 @@ * @property {module:SVGEditor.Button[]|PlainObject.<Integer, module:SVGEditor.Button>} [buttons] * @property {string} [svgicons] The location of a local SVG or SVGz file */ + /** * @function module:svgcanvas.ExtensionInitResponse#mouseDown * @param {module:svgcanvas.SvgCanvas#event:ext-mouseDown} arg * @returns {undefined|module:svgcanvas.ExtensionMouseDownStatus} */ + /** * @function module:svgcanvas.ExtensionInitResponse#mouseMove * @param {module:svgcanvas.SvgCanvas#event:ext-mouseMove} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#mouseUp * @param {module:svgcanvas.SvgCanvas#event:ext-mouseUp} arg * @returns {module:svgcanvas.ExtensionMouseUpStatus} */ + /** * @function module:svgcanvas.ExtensionInitResponse#zoomChanged * @param {module:svgcanvas.SvgCanvas#event:ext-zoomChanged} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#IDsUpdated * @param {module:svgcanvas.SvgCanvas#event:ext-IDsUpdated} arg * @returns {module:svgcanvas.ExtensionIDsUpdatedStatus} */ + /** * @function module:svgcanvas.ExtensionInitResponse#canvasUpdated * @param {module:svgcanvas.SvgCanvas#event:ext-canvasUpdated} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#toolButtonStateUpdate * @param {module:svgcanvas.SvgCanvas#event:ext-toolButtonStateUpdate} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#selectedChanged * @param {module:svgcanvas.SvgCanvas#event:ext-selectedChanged} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#elementTransition * @param {module:svgcanvas.SvgCanvas#event:ext-elementTransition} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#elementChanged * @param {module:svgcanvas.SvgCanvas#event:ext-elementChanged} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#langReady * @param {module:svgcanvas.SvgCanvas#event:ext-langReady} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#langChanged * @param {module:svgcanvas.SvgCanvas#event:ext-langChanged} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#addLangData * @param {module:svgcanvas.SvgCanvas#event:ext-addLangData} arg * @returns {Promise} Resolves to {@link module:locale.ExtensionLocaleData} */ + /** * @function module:svgcanvas.ExtensionInitResponse#onNewDocument * @param {module:svgcanvas.SvgCanvas#event:ext-onNewDocument} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#workareaResized * @param {module:svgcanvas.SvgCanvas#event:ext-workareaResized} arg * @returns {undefined} */ + /** * @function module:svgcanvas.ExtensionInitResponse#callback + * @this module:SVGEditor * @param {module:svgcanvas.SvgCanvas#event:ext-callback} arg * @returns {undefined} */ @@ -13390,39 +14640,57 @@ * @param {module:svgcanvas.ExtensionArgumentObject} arg * @returns {Promise} Resolves to [ExtensionInitResponse]{@link module:svgcanvas.ExtensionInitResponse} or `undefined` */ + /** - * Add an extension to the editor + * @typedef {PlainObject} module:svgcanvas.ExtensionInitArgs + * @param {external:jQuery} initArgs.$ + * @param {module:SVGEditor~ImportLocale} initArgs.importLocale + */ + + /** + * Add an extension to the editor. * @function module:svgcanvas.SvgCanvas#addExtension * @param {string} name - String with the ID of the extension. Used internally; no need for i18n. * @param {module:svgcanvas.ExtensionInitCallback} [extInitFunc] - Function supplied by the extension with its data - * @param {module:SVGEditor~ImportLocale} importLocale + * @param {module:svgcanvas.ExtensionInitArgs} initArgs * @fires module:svgcanvas.SvgCanvas#event:extension_added - * @throws {TypeError} If `extInitFunc` is not a function + * @throws {TypeError|Error} `TypeError` if `extInitFunc` is not a function, `Error` + * if extension of supplied name already exists * @returns {Promise} Resolves to `undefined` */ - this.addExtension = function () { - var _ref3 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(name, extInitFunc, importLocale) { - var extObj, argObj; + + + this.addExtension = + /*#__PURE__*/ + function () { + var _ref4 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee(name, extInitFunc, _ref3) { + var jq, importLocale, argObj, extObj; return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: + jq = _ref3.$, importLocale = _ref3.importLocale; + if (!(typeof extInitFunc !== 'function')) { - _context.next = 2; + _context.next = 3; break; } throw new TypeError('Function argument expected for `svgcanvas.addExtension`'); - case 2: - extObj = {}; - - if (name in extensions) { - _context.next = 14; + case 3: + if (!(name in extensions)) { + _context.next = 5; break; } + throw new Error('Cannot add extension "' + name + '", an extension by that name already exists.'); + + case 5: // Provide private vars/funcs here. Is there a better way to do this? + /** * @typedef {module:svgcanvas.PrivateMethods} module:svgcanvas.ExtensionArgumentObject * @property {SVGSVGElement} svgroot See {@link module:svgcanvas~svgroot} @@ -13431,42 +14699,34 @@ * @property {module:select.SelectorManager} selectorManager * @property {module:SVGEditor~ImportLocale} importLocale */ + /** * @type {module:svgcanvas.ExtensionArgumentObject} * @see {@link module:svgcanvas.PrivateMethods} source for the other methods/properties */ argObj = $$9.extend(canvas.getPrivateMethods(), { + $: jq, importLocale: importLocale, svgroot: svgroot, svgcontent: svgcontent, nonce: getCurrentDrawing().getNonce(), selectorManager: selectorManager }); - - if (!extInitFunc) { - _context.next = 9; - break; - } - _context.next = 8; return extInitFunc(argObj); case 8: extObj = _context.sent; - case 9: if (extObj) { extObj.name = name; } extensions[name] = extObj; - return _context.abrupt('return', call('extension_added', extObj)); + return _context.abrupt("return", call('extension_added', extObj)); - case 14: - console.log('Cannot add extension "' + name + '", an extension by that name already exists.'); - - case 15: - case 'end': + case 12: + case "end": return _context.stop(); } } @@ -13474,10 +14734,9 @@ })); return function (_x, _x2, _x3) { - return _ref3.apply(this, arguments); + return _ref4.apply(this, arguments); }; }(); - /** * This method sends back an array or a NodeList full of elements that * intersect the multi-select rubber-band-box on the currentLayer only. @@ -13485,26 +14744,27 @@ * We brute-force `getIntersectionList` for browsers that do not support it (Firefox). * * Reference: - * Firefox does not implement `getIntersectionList()`, see {@link https://bugzilla.mozilla.org/show_bug.cgi?id=501421} + * Firefox does not implement `getIntersectionList()`, see {@link https://bugzilla.mozilla.org/show_bug.cgi?id=501421}. * @function module:svgcanvas.SvgCanvas#getIntersectionList * @param {SVGRect} rect * @returns {Element[]|NodeList} Bbox elements */ + + var getIntersectionList = this.getIntersectionList = function (rect) { - if (rubberBox == null) { + if (isNullish(rubberBox)) { return null; } var parent = currentGroup || getCurrentDrawing().getCurrentLayer(); + var rubberBBox; - var rubberBBox = void 0; if (!rect) { rubberBBox = rubberBox.getBBox(); var bb = svgcontent.createSVGRect(); - - for (var o in rubberBBox) { + ['x', 'y', 'width', 'height', 'top', 'right', 'bottom', 'left'].forEach(function (o) { bb[o] = rubberBBox[o] / currentZoom; - } + }); rubberBBox = bb; } else { rubberBBox = svgcontent.createSVGRect(); @@ -13515,44 +14775,45 @@ } var resultList = null; - if (!isIE) { + + if (!isIE()) { if (typeof svgroot.getIntersectionList === 'function') { // Offset the bbox of the rubber box by the offset of the svgcontent element. - rubberBBox.x += parseInt(svgcontent.getAttribute('x'), 10); - rubberBBox.y += parseInt(svgcontent.getAttribute('y'), 10); - + rubberBBox.x += parseInt(svgcontent.getAttribute('x')); + rubberBBox.y += parseInt(svgcontent.getAttribute('y')); resultList = svgroot.getIntersectionList(rubberBBox, parent); } } - if (resultList == null || typeof resultList.item !== 'function') { + if (isNullish(resultList) || typeof resultList.item !== 'function') { resultList = []; if (!curBBoxes.length) { // Cache all bboxes curBBoxes = getVisibleElementsAndBBoxes(parent); } + var i = curBBoxes.length; + while (i--) { if (!rubberBBox.width) { continue; } + if (rectsIntersect(rubberBBox, curBBoxes[i].bbox)) { resultList.push(curBBoxes[i].elem); } } - } - - // addToSelection expects an array, but it's ok to pass a NodeList + } // addToSelection expects an array, but it's ok to pass a NodeList // because using square-bracket notation is allowed: // https://www.w3.org/TR/DOM-Level-2-Core/ecma-script-binding.html + + return resultList; }; this.getStrokedBBox = getStrokedBBoxDefaultVisible; - this.getVisibleElements = getVisibleElements; - /** * @typedef {PlainObject} ElementAndBBox * @property {Element} elem - The element @@ -13562,63 +14823,71 @@ /** * Get all elements that have a BBox (excludes `<defs>`, `<title>`, etc). * Note that 0-opacity, off-screen etc elements are still considered "visible" - * for this function + * for this function. * @function module:svgcanvas.SvgCanvas#getVisibleElementsAndBBoxes * @param {Element} parent - The parent DOM element to search within * @returns {ElementAndBBox[]} An array with objects that include: */ + var getVisibleElementsAndBBoxes = this.getVisibleElementsAndBBoxes = function (parent) { if (!parent) { parent = $$9(svgcontent).children(); // Prevent layers from being included } + var contentElems = []; $$9(parent).children().each(function (i, elem) { if (elem.getBBox) { - contentElems.push({ elem: elem, bbox: getStrokedBBoxDefaultVisible([elem]) }); + contentElems.push({ + elem: elem, + bbox: getStrokedBBoxDefaultVisible([elem]) + }); } }); return contentElems.reverse(); }; - /** - * Wrap an SVG element into a group element, mark the group as 'gsvg' + * Wrap an SVG element into a group element, mark the group as 'gsvg'. * @function module:svgcanvas.SvgCanvas#groupSvgElem * @param {Element} elem - SVG element to wrap * @returns {undefined} */ + + var groupSvgElem = this.groupSvgElem = function (elem) { var g = document.createElementNS(NS.SVG, 'g'); elem.replaceWith(g); $$9(g).append(elem).data('gsvg', elem)[0].id = getNextId(); - }; - - // Set scope for these functions - + }; // Set scope for these functions // Object to contain editor event names and callback functions - var events = {}; + + var events = {}; canvas.call = call; /** * Array of what was changed (elements, layers) * @event module:svgcanvas.SvgCanvas#event:changed * @type {Element[]} */ + /** * Array of selected elements * @event module:svgcanvas.SvgCanvas#event:selected * @type {Element[]} */ + /** * Array of selected elements * @event module:svgcanvas.SvgCanvas#event:transition * @type {Element[]} */ + /** * The Element is always `SVGGElement`? * If not `null`, will be the set current group element * @event module:svgcanvas.SvgCanvas#event:contextset * @type {null|Element} */ + /** * @event module:svgcanvas.SvgCanvas#event:pointsAdded * @type {PlainObject} @@ -13636,17 +14905,20 @@ * @property {0.5|2} factor * @see module:SVGEditor.BBoxObjectWithFactor */ + /** * @event module:svgcanvas.SvgCanvas#event:updateCanvas * @type {PlainObject} * @property {false} center * @property {module:math.XYObject} newCtr */ + /** * @typedef {PlainObject} module:svgcanvas.ExtensionInitResponsePlusName * @implements {module:svgcanvas.ExtensionInitResponse} * @property {string} name The extension's resolved ID (whether explicit or based on file name) */ + /** * Generalized extension object response of * [`init()`]{@link module:svgcanvas.ExtensionInitCallback} @@ -13654,36 +14926,44 @@ * @event module:svgcanvas.SvgCanvas#event:extension_added * @type {module:svgcanvas.ExtensionInitResponsePlusName|undefined} */ + /** * @event module:svgcanvas.SvgCanvas#event:extensions_added * @type {undefined} */ + /** * @typedef {PlainObject} module:svgcanvas.Message * @property {Any} data The data * @property {string} origin The origin */ + /** * @event module:svgcanvas.SvgCanvas#event:message * @type {module:svgcanvas.Message} */ + /** * SVG canvas converted to string * @event module:svgcanvas.SvgCanvas#event:saved * @type {string} */ + /** * @event module:svgcanvas.SvgCanvas#event:setnonce * @type {!(string|Integer)} */ + /** * @event module:svgcanvas.SvgCanvas#event:unsetnonce * @type {undefined} */ + /** * @event module:svgcanvas.SvgCanvas#event:zoomDone * @type {undefined} */ + /** * @event module:svgcanvas.SvgCanvas#event:cleared * @type {undefined} @@ -13693,10 +14973,12 @@ * @event module:svgcanvas.SvgCanvas#event:exported * @type {module:svgcanvas.ImageExportedResults} */ + /** * @event module:svgcanvas.SvgCanvas#event:exportedPDF * @type {module:svgcanvas.PDFExportedResults} */ + /** * Creating a cover-all class until {@link https://github.com/jsdoc3/jsdoc/issues/1545} may be supported. * `undefined` may be returned by {@link module:svgcanvas.SvgCanvas#event:extension_added} if the extension's `init` returns `undefined` It is also the type for the following events "zoomDone", "unsetnonce", "cleared", and "extensions_added". @@ -13704,43 +14986,51 @@ * @type {module:svgcanvas.SvgCanvas#event:selected|module:svgcanvas.SvgCanvas#event:changed|module:svgcanvas.SvgCanvas#event:contextset|module:svgcanvas.SvgCanvas#event:pointsAdded|module:svgcanvas.SvgCanvas#event:extension_added|module:svgcanvas.SvgCanvas#event:extensions_added|module:svgcanvas.SvgCanvas#event:message|module:svgcanvas.SvgCanvas#event:transition|module:svgcanvas.SvgCanvas#event:zoomed|module:svgcanvas.SvgCanvas#event:updateCanvas|module:svgcanvas.SvgCanvas#event:saved|module:svgcanvas.SvgCanvas#event:exported|module:svgcanvas.SvgCanvas#event:exportedPDF|module:svgcanvas.SvgCanvas#event:setnonce|module:svgcanvas.SvgCanvas#event:unsetnonce|undefined} */ + /** + * The promise return, if present, resolves to `undefined` + * (`extension_added`, `exported`, `saved`) + * @typedef {Promise|undefined} module:svgcanvas.EventHandlerReturn + */ + /** * @callback module:svgcanvas.EventHandler * @param {external:Window} win * @param {module:svgcanvas.SvgCanvas#event:GenericCanvasEvent} arg * @listens module:svgcanvas.SvgCanvas#event:GenericCanvasEvent + * @returns {module:svgcanvas.EventHandlerReturn} */ /** - * Attaches a callback function to an event + * Attaches a callback function to an event. * @function module:svgcanvas.SvgCanvas#bind * @param {"changed"|"contextset"|"selected"|"pointsAdded"|"extension_added"|"extensions_added"|"message"|"transition"|"zoomed"|"updateCanvas"|"zoomDone"|"saved"|"exported"|"exportedPDF"|"setnonce"|"unsetnonce"|"cleared"} ev - String indicating the name of the event * @param {module:svgcanvas.EventHandler} f - The callback function to bind to the event * @returns {module:svgcanvas.EventHandler} The previous event */ + canvas.bind = function (ev, f) { var old = events[ev]; events[ev] = f; return old; }; - /** * Runs the SVG Document through the sanitizer and then updates its paths. * @function module:svgcanvas.SvgCanvas#prepareSvg * @param {XMLDocument} newDoc - The SVG DOM document * @returns {undefined} */ - this.prepareSvg = function (newDoc) { - this.sanitizeSvg(newDoc.documentElement); - // convert paths into absolute commands - var paths = [].concat(toConsumableArray(newDoc.getElementsByTagNameNS(NS.SVG, 'path'))); - paths.forEach(function (path$$1) { - path$$1.setAttribute('d', pathActions$$1.convertPath(path$$1)); - pathActions$$1.fixEnd(path$$1); + + this.prepareSvg = function (newDoc) { + this.sanitizeSvg(newDoc.documentElement); // convert paths into absolute commands + + var paths = _toConsumableArray(newDoc.getElementsByTagNameNS(NS.SVG, 'path')); + + paths.forEach(function (path) { + path.setAttribute('d', pathActions$1.convertPath(path)); + pathActions$1.fixEnd(path); }); }; - /** * Hack for Firefox bugs where text element features aren't updated or get * messed up. See issue 136 and issue 137. @@ -13751,10 +15041,13 @@ * @param {Element} elem - The (text) DOM element to clone * @returns {Element} Cloned element */ + + var ffClone = function ffClone(elem) { if (!isGecko()) { return elem; } + var clone = elem.cloneNode(true); elem.before(clone); elem.remove(); @@ -13762,9 +15055,7 @@ selectedElements[0] = clone; selectorManager.requestSelector(clone).showGrips(true); return clone; - }; - - // `this.each` is deprecated, if any extension used this it can be recreated by doing this: + }; // `this.each` is deprecated, if any extension used this it can be recreated by doing this: // * @example $(canvas.getRootElem()).children().each(...) // * @function module:svgcanvas.SvgCanvas#each // this.each = function (cb) { @@ -13773,13 +15064,15 @@ /** * Removes any old rotations if present, prepends a new rotation at the - * transformed center + * transformed center. * @function module:svgcanvas.SvgCanvas#setRotationAngle * @param {string|Float} val - The new rotation angle in degrees * @param {boolean} preventUndo - Indicates whether the action should be undoable or not * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + this.setRotationAngle = function (val, preventUndo) { // ensure val is the proper type val = parseFloat(val); @@ -13788,20 +15081,22 @@ var bbox = getBBox(elem); var cx = bbox.x + bbox.width / 2, cy = bbox.y + bbox.height / 2; - var tlist = getTransformList(elem); + var tlist = getTransformList(elem); // only remove the real rotational transform if present (i.e. at index=0) - // only remove the real rotational transform if present (i.e. at index=0) if (tlist.numberOfItems > 0) { var xform = tlist.getItem(0); + if (xform.type === 4) { tlist.removeItem(0); } - } - // find Rnc and insert it + } // find Rnc and insert it + + if (val !== 0) { var center = transformPoint(cx, cy, transformListToTransform(tlist).matrix); var Rnc = svgroot.createSVGTransform(); Rnc.setRotate(val, center.x, center.y); + if (tlist.numberOfItems) { tlist.insertItemBefore(Rnc, 0); } else { @@ -13818,32 +15113,35 @@ elem.setAttribute('transform', oldTransform); changeSelectedAttribute('transform', newTransform, selectedElements); call('changed', selectedElements); - } - // const pointGripContainer = getElem('pathpointgrip_container'); + } // const pointGripContainer = getElem('pathpointgrip_container'); // if (elem.nodeName === 'path' && pointGripContainer) { // pathActions.setPointContainerTransform(elem.getAttribute('transform')); // } + + var selector = selectorManager.requestSelector(selectedElements[0]); selector.resize(); - selector.updateGripCursors(val); + Selector.updateGripCursors(val); }; - /** * Runs `recalculateDimensions` on the selected elements, - * adding the changes to a single batch command + * adding the changes to a single batch command. * @function module:svgcanvas.SvgCanvas#recalculateAllSelectedDimensions * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + var recalculateAllSelectedDimensions = this.recalculateAllSelectedDimensions = function () { var text = currentResizeMode === 'none' ? 'position' : 'size'; var batchCmd = new BatchCommand$1(text); - var i = selectedElements.length; + while (i--) { - var elem = selectedElements[i]; - // if (getRotationAngle(elem) && !hasMatrixTransform(getTransformList(elem))) { continue; } + var elem = selectedElements[i]; // if (getRotationAngle(elem) && !hasMatrixTransform(getTransformList(elem))) { continue; } + var cmd = recalculateDimensions(elem); + if (cmd) { batchCmd.addSubCommand(cmd); } @@ -13854,39 +15152,37 @@ call('changed', selectedElements); } }; - /** - * Debug tool to easily see the current matrix in the browser's console + * Debug tool to easily see the current matrix in the browser's console. * @function module:svgcanvas~logMatrix * @param {SVGMatrix} m The matrix * @returns {undefined} */ + + var logMatrix = function logMatrix(m) { - console.log([m.a, m.b, m.c, m.d, m.e, m.f]); - }; + console.log([m.a, m.b, m.c, m.d, m.e, m.f]); // eslint-disable-line no-console + }; // Root Current Transformation Matrix in user units + - // Root Current Transformation Matrix in user units var rootSctm = null; - /** * Group: Selection */ - // TODO: do we need to worry about selectedBBoxes here? /** - * Selects only the given elements, shortcut for clearSelection(); addToSelection() + * Selects only the given elements, shortcut for `clearSelection(); addToSelection()`. * @function module:svgcanvas.SvgCanvas#selectOnly * @param {Element[]} elems - an array of DOM elements to be selected * @param {boolean} showGrips - Indicates whether the resize grips should be shown * @returns {undefined} */ + var selectOnly = this.selectOnly = function (elems, showGrips) { clearSelection(true); addToSelection(elems, showGrips); - }; - - // TODO: could use slice here to make this faster? + }; // TODO: could use slice here to make this faster? // TODO: should the 'selected' handler /** @@ -13895,19 +15191,26 @@ * @param {Element[]} elemsToRemove - An array of elements to remove from selection * @returns {undefined} */ - /* const removeFromSelection = */this.removeFromSelection = function (elemsToRemove) { - if (selectedElements[0] == null) { - return; - } - if (!elemsToRemove.length) { + + /* const removeFromSelection = */ + + + this.removeFromSelection = function (elemsToRemove) { + if (isNullish(selectedElements[0])) { return; } - // find every element and remove it from our array copy + if (!elemsToRemove.length) { + return; + } // find every element and remove it from our array copy + + var newSelectedItems = [], len = selectedElements.length; + for (var i = 0; i < len; ++i) { var elem = selectedElements[i]; + if (elem) { // keep the item if (!elemsToRemove.includes(elem)) { @@ -13917,27 +15220,29 @@ selectorManager.releaseSelector(elem); } } - } - // the copy becomes the master now + } // the copy becomes the master now + + selectedElements = newSelectedItems; }; - /** * Clears the selection, then adds all elements in the current layer to the selection. * @function module:svgcanvas.SvgCanvas#selectAllInCurrentLayer * @returns {undefined} */ + + this.selectAllInCurrentLayer = function () { var currentLayer = getCurrentDrawing().getCurrentLayer(); + if (currentLayer) { currentMode = 'select'; selectOnly($$9(currentGroup || currentLayer).children()); } }; - var drawnPath = null; + var drawnPath = null; // Mouse events - // Mouse events (function () { var freehand = { minx: null, @@ -13954,17 +15259,38 @@ rStartY = null, initBbox = {}, sumDistance = 0, - controllPoint2 = { x: 0, y: 0 }, - controllPoint1 = { x: 0, y: 0 }, - start = { x: 0, y: 0 }, - end = { x: 0, y: 0 }, - bSpline = { x: 0, y: 0 }, - nextPos = { x: 0, y: 0 }, - parameter = void 0, - nextParameter = void 0; + controllPoint2 = { + x: 0, + y: 0 + }, + controllPoint1 = { + x: 0, + y: 0 + }, + start = { + x: 0, + y: 0 + }, + end = { + x: 0, + y: 0 + }, + bSpline = { + x: 0, + y: 0 + }, + nextPos = { + x: 0, + y: 0 + }, + parameter, + nextParameter; var getBsplinePoint = function getBsplinePoint(t) { - var spline = { x: 0, y: 0 }, + var spline = { + x: 0, + y: 0 + }, p0 = controllPoint2, p1 = controllPoint1, p2 = start, @@ -13972,26 +15298,26 @@ S = 1.0 / 6.0, t2 = t * t, t3 = t2 * t; - var m = [[-1, 3, -3, 1], [3, -6, 3, 0], [-3, 0, 3, 0], [1, 4, 1, 0]]; - spline.x = S * ((p0.x * m[0][0] + p1.x * m[0][1] + p2.x * m[0][2] + p3.x * m[0][3]) * t3 + (p0.x * m[1][0] + p1.x * m[1][1] + p2.x * m[1][2] + p3.x * m[1][3]) * t2 + (p0.x * m[2][0] + p1.x * m[2][1] + p2.x * m[2][2] + p3.x * m[2][3]) * t + (p0.x * m[3][0] + p1.x * m[3][1] + p2.x * m[3][2] + p3.x * m[3][3])); spline.y = S * ((p0.y * m[0][0] + p1.y * m[0][1] + p2.y * m[0][2] + p3.y * m[0][3]) * t3 + (p0.y * m[1][0] + p1.y * m[1][1] + p2.y * m[1][2] + p3.y * m[1][3]) * t2 + (p0.y * m[2][0] + p1.y * m[2][1] + p2.y * m[2][2] + p3.y * m[2][3]) * t + (p0.y * m[3][0] + p1.y * m[3][1] + p2.y * m[3][2] + p3.y * m[3][3])); - return { x: spline.x, y: spline.y }; }; /** + * Follows these conditions: * - When we are in a create mode, the element is added to the canvas but the * action is not recorded until mousing up. * - When we are in select mode, select the element, remember the position - * and do nothing else + * and do nothing else. * @param {MouseEvent} evt * @fires module:svgcanvas.SvgCanvas#event:ext-mouseDown * @returns {undefined} */ + + var mouseDown = function mouseDown(evt) { if (canvas.spaceKey || evt.button === 1) { return; @@ -14005,32 +15331,29 @@ } rootSctm = $$9('#svgcontent g')[0].getScreenCTM().inverse(); - var pt = transformPoint(evt.pageX, evt.pageY, rootSctm), mouseX = pt.x * currentZoom, mouseY = pt.y * currentZoom; - evt.preventDefault(); if (rightClick) { currentMode = 'select'; lastClickPoint = pt; - } - - // This would seem to be unnecessary... + } // This would seem to be unnecessary... // if (!['select', 'resize'].includes(currentMode)) { // setGradient(); // } + var x = mouseX / currentZoom, y = mouseY / currentZoom; var mouseTarget = getMouseTarget(evt); if (mouseTarget.tagName === 'a' && mouseTarget.childNodes.length === 1) { mouseTarget = mouseTarget.firstChild; - } + } // realX/y ignores grid-snap value + - // realX/y ignores grid-snap value var realX = x; rStartX = startX = x; var realY = y; @@ -14041,33 +15364,32 @@ y = snapToGrid(y); startX = snapToGrid(startX); startY = snapToGrid(startY); - } - - // 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 - if (mouseTarget === selectorManager.selectorParentGroup && selectedElements[0] != null) { + + if (mouseTarget === selectorManager.selectorParentGroup && !isNullish(selectedElements[0])) { var grip = evt.target; - var griptype = elData(grip, 'type'); - // rotating + var griptype = elData(grip, 'type'); // rotating + if (griptype === 'rotate') { - currentMode = 'rotate'; - // resizing + currentMode = 'rotate'; // resizing } else if (griptype === 'resize') { currentMode = 'resize'; currentResizeMode = elData(grip, 'dir'); } + mouseTarget = selectedElements[0]; } startTransform = mouseTarget.getAttribute('transform'); - var i = void 0, - strokeW = void 0; var tlist = getTransformList(mouseTarget); + switch (currentMode) { case 'select': started = true; currentResizeMode = 'none'; + if (rightClick) { started = false; } @@ -14081,20 +15403,23 @@ // No need to do the call here as it will be done on addToSelection clearSelection(true); } + addToSelection([mouseTarget]); justSelected = mouseTarget; - pathActions$$1.clear(); - } - // else if it's a path, go into pathedit mode in mouseup + pathActions$1.clear(); + } // else if it's a path, go into pathedit mode in mouseup + if (!rightClick) { // insert a dummy transform so if the element(s) are moved it will have // a transform to use for its translate - for (i = 0; i < selectedElements.length; ++i) { - if (selectedElements[i] == null) { + for (var i = 0; i < selectedElements.length; ++i) { + if (isNullish(selectedElements[i])) { continue; } + var slist = getTransformList(selectedElements[i]); + if (slist.numberOfItems) { slist.insertItemBefore(svgroot.createSVGTransform(), 0); } else { @@ -14105,12 +15430,13 @@ } else if (!rightClick) { clearSelection(); currentMode = 'multiselect'; - if (rubberBox == null) { + + if (isNullish(rubberBox)) { rubberBox = selectorManager.getRubberBandBox(); } + rStartX *= currentZoom; - rStartY *= currentZoom; - // console.log('p',[evt.pageX, evt.pageY]); + rStartY *= currentZoom; // console.log('p',[evt.pageX, evt.pageY]); // console.log('c',[evt.clientX, evt.clientY]); // console.log('o',[evt.offsetX, evt.offsetY]); // console.log('s',[startX, startY]); @@ -14123,12 +15449,16 @@ display: 'inline' }, 100); } + break; + case 'zoom': started = true; - if (rubberBox == null) { + + if (isNullish(rubberBox)) { rubberBox = selectorManager.getRubberBandBox(); } + assignAttributes(rubberBox, { x: realX * currentZoom, y: realX * currentZoom, @@ -14137,79 +15467,88 @@ display: 'inline' }, 100); break; + case 'resize': - started = true; - startX = x; - startY = y; + { + started = true; + startX = x; + startY = y; // Getting the BBox from the selection box, since we know we + // want to orient around it - // Getting the BBox from the selection box, since we know we - // want to orient around it - initBbox = getBBox($$9('#selectedBox0')[0]); - var bb = {}; - $$9.each(initBbox, function (key, val) { - bb[key] = val / currentZoom; - }); - initBbox = bb; + initBbox = getBBox($$9('#selectedBox0')[0]); + var bb = {}; + $$9.each(initBbox, function (key, val) { + bb[key] = val / currentZoom; + }); + initBbox = bb; // append three dummy transforms to the tlist so that + // we can translate,scale,translate in mousemove - // append three dummy transforms to the tlist so that - // we can translate,scale,translate in mousemove - var pos = getRotationAngle(mouseTarget) ? 1 : 0; + var pos = getRotationAngle(mouseTarget) ? 1 : 0; - if (hasMatrixTransform(tlist)) { - tlist.insertItemBefore(svgroot.createSVGTransform(), pos); - tlist.insertItemBefore(svgroot.createSVGTransform(), pos); - tlist.insertItemBefore(svgroot.createSVGTransform(), pos); - } else { - tlist.appendItem(svgroot.createSVGTransform()); - tlist.appendItem(svgroot.createSVGTransform()); - tlist.appendItem(svgroot.createSVGTransform()); + if (hasMatrixTransform(tlist)) { + tlist.insertItemBefore(svgroot.createSVGTransform(), pos); + tlist.insertItemBefore(svgroot.createSVGTransform(), pos); + tlist.insertItemBefore(svgroot.createSVGTransform(), pos); + } else { + tlist.appendItem(svgroot.createSVGTransform()); + tlist.appendItem(svgroot.createSVGTransform()); + tlist.appendItem(svgroot.createSVGTransform()); - if (supportsNonScalingStroke()) { - // Handle crash for newer Chrome and Safari 6 (Mobile and Desktop): - // https://code.google.com/p/svg-edit/issues/detail?id=904 - // Chromium issue: https://code.google.com/p/chromium/issues/detail?id=114625 - // TODO: Remove this workaround once vendor fixes the issue - var iswebkit = isWebkit(); + if (supportsNonScalingStroke()) { + // Handle crash for newer Chrome and Safari 6 (Mobile and Desktop): + // https://code.google.com/p/svg-edit/issues/detail?id=904 + // Chromium issue: https://code.google.com/p/chromium/issues/detail?id=114625 + // TODO: Remove this workaround once vendor fixes the issue + var iswebkit = isWebkit(); + var delayedStroke; - var delayedStroke = void 0; - if (iswebkit) { - delayedStroke = function delayedStroke(ele) { - var _stroke = ele.getAttributeNS(null, 'stroke'); - ele.removeAttributeNS(null, 'stroke'); - // Re-apply stroke after delay. Anything higher than 1 seems to cause flicker - if (_stroke !== null) setTimeout(function () { - ele.setAttributeNS(null, 'stroke', _stroke); - }, 0); - }; - } - mouseTarget.style.vectorEffect = 'non-scaling-stroke'; - if (iswebkit) { - delayedStroke(mouseTarget); - } - - var all = mouseTarget.getElementsByTagName('*'), - len = all.length; - for (i = 0; i < len; i++) { - if (!all[i].style) { - // mathML - continue; - } - all[i].style.vectorEffect = 'non-scaling-stroke'; if (iswebkit) { - delayedStroke(all[i]); + delayedStroke = function delayedStroke(ele) { + var stroke_ = ele.getAttribute('stroke'); + ele.removeAttribute('stroke'); // Re-apply stroke after delay. Anything higher than 1 seems to cause flicker + + if (stroke_ !== null) setTimeout(function () { + ele.setAttribute('stroke', stroke_); + }, 0); + }; + } + + mouseTarget.style.vectorEffect = 'non-scaling-stroke'; + + if (iswebkit) { + delayedStroke(mouseTarget); + } + + var all = mouseTarget.getElementsByTagName('*'), + len = all.length; + + for (var _i2 = 0; _i2 < len; _i2++) { + if (!all[_i2].style) { + // mathML + continue; + } + + all[_i2].style.vectorEffect = 'non-scaling-stroke'; + + if (iswebkit) { + delayedStroke(all[_i2]); + } } } } + + break; } - break; + case 'fhellipse': case 'fhrect': case 'fhpath': start.x = realX; start.y = realY; started = true; - dAttr = realX + ',' + realY + ' '; - strokeW = parseFloat(curShape.stroke_width) === 0 ? 1 : curShape.stroke_width; + dAttr = realX + ',' + realY + ' '; // Commented out as doing nothing now: + // strokeW = parseFloat(curShape.stroke_width) === 0 ? 1 : curShape.stroke_width; + addSVGElementFromJson({ element: 'polyline', curStyles: true, @@ -14227,27 +15566,31 @@ freehand.miny = realY; freehand.maxy = realY; break; + case 'image': - started = true; - var newImage = addSVGElementFromJson({ - element: 'image', - attr: { - x: x, - y: y, - width: 0, - height: 0, - id: getNextId(), - opacity: curShape.opacity / 2, - style: 'pointer-events:inherit' - } - }); - setHref(newImage, lastGoodImgUrl); - preventClickDefault(newImage); - break; - case 'square': - // FIXME: once we create the rect, we lose information that this was a square + { + started = true; + var newImage = addSVGElementFromJson({ + element: 'image', + attr: { + x: x, + y: y, + width: 0, + height: 0, + id: getNextId(), + opacity: curShape.opacity / 2, + style: 'pointer-events:inherit' + } + }); + setHref(newImage, lastGoodImgUrl); + preventClickDefault(newImage); + break; + } + + case 'square': // FIXME: once we create the rect, we lose information that this was a square // (for resizing purposes this could be important) // Fallthrough + case 'rect': started = true; startX = x; @@ -14265,30 +15608,34 @@ } }); break; + case 'line': - started = true; - strokeW = Number(curShape.stroke_width) === 0 ? 1 : curShape.stroke_width; - addSVGElementFromJson({ - element: 'line', - curStyles: true, - attr: { - x1: x, - y1: y, - x2: x, - y2: y, - id: getNextId(), - stroke: curShape.stroke, - 'stroke-width': strokeW, - 'stroke-dasharray': curShape.stroke_dasharray, - 'stroke-linejoin': curShape.stroke_linejoin, - 'stroke-linecap': curShape.stroke_linecap, - 'stroke-opacity': curShape.stroke_opacity, - fill: 'none', - opacity: curShape.opacity / 2, - style: 'pointer-events:none' - } - }); - break; + { + started = true; + var strokeW = Number(curShape.stroke_width) === 0 ? 1 : curShape.stroke_width; + addSVGElementFromJson({ + element: 'line', + curStyles: true, + attr: { + x1: x, + y1: y, + x2: x, + y2: y, + id: getNextId(), + stroke: curShape.stroke, + 'stroke-width': strokeW, + 'stroke-dasharray': curShape.stroke_dasharray, + 'stroke-linejoin': curShape.stroke_linejoin, + 'stroke-linecap': curShape.stroke_linecap, + 'stroke-opacity': curShape.stroke_opacity, + fill: 'none', + opacity: curShape.opacity / 2, + style: 'pointer-events:none' + } + }); + break; + } + case 'circle': started = true; addSVGElementFromJson({ @@ -14303,6 +15650,7 @@ } }); break; + case 'ellipse': started = true; addSVGElementFromJson({ @@ -14318,9 +15666,12 @@ } }); break; + case 'text': started = true; - /* const newText = */addSVGElementFromJson({ + /* const newText = */ + + addSVGElementFromJson({ element: 'text', curStyles: true, attr: { @@ -14335,33 +15686,36 @@ 'xml:space': 'preserve', opacity: curShape.opacity } - }); - // newText.textContent = 'text'; + }); // newText.textContent = 'text'; + break; - case 'path': - // Fall through + + case 'path': // Fall through + case 'pathedit': startX *= currentZoom; startY *= currentZoom; - pathActions$$1.mouseDown(evt, mouseTarget, startX, startY); + pathActions$1.mouseDown(evt, mouseTarget, startX, startY); started = true; break; + case 'textedit': startX *= currentZoom; startY *= currentZoom; textActions.mouseDown(evt, mouseTarget, startX, startY); started = true; break; + case 'rotate': - started = true; - // we are starting an undoable change (a drag-rotation) + started = true; // we are starting an undoable change (a drag-rotation) + canvas.undoMgr.beginUndoableChange('transform', selectedElements); break; + default: // This could occur in an extension break; } - /** * The main (left) mouse button is held down on the canvas area * @event module:svgcanvas.SvgCanvas#event:ext-mouseDown @@ -14371,22 +15725,24 @@ * @property {Float} start_y y coordinate on canvas * @property {Element[]} selectedElements An array of the selected Elements */ - var extResult = runExtensions('mouseDown', /** @type {module:svgcanvas.SvgCanvas#event:ext-mouseDown} */{ + + + var extResult = runExtensions('mouseDown', + /** @type {module:svgcanvas.SvgCanvas#event:ext-mouseDown} */ + { event: evt, start_x: startX, start_y: startY, selectedElements: selectedElements }, true); - $$9.each(extResult, function (i, r) { if (r && r.started) { started = true; } }); - }; - - // in this function we do not record any state changes yet (but we do update + }; // in this function we do not record any state changes yet (but we do update // any elements that are still being created, moved or resized on the canvas) + /** * * @param {MouseEvent} evt @@ -14394,30 +15750,32 @@ * @fires module:svgcanvas.SvgCanvas#event:ext-mouseMove * @returns {undefined} */ + + var mouseMove = function mouseMove(evt) { if (!started) { return; } + if (evt.button === 1 || canvas.spaceKey) { return; } - var i = void 0, - xya = void 0, - c = void 0, - cx = void 0, - cy = void 0, - dx = void 0, - dy = void 0, - len = void 0, - angle = void 0, - box = void 0, + var i, + xya, + c, + cx, + cy, + dx, + dy, + len, + angle, + box, selected = selectedElements[0]; var pt = transformPoint(evt.pageX, evt.pageY, rootSctm), mouseX = pt.x * currentZoom, mouseY = pt.y * currentZoom, shape = getElem(getId()); - var realX = mouseX / currentZoom; var x = realX; var realY = mouseY / currentZoom; @@ -14429,7 +15787,8 @@ } evt.preventDefault(); - var tlist = void 0; + var tlist; + switch (currentMode) { case 'select': { @@ -14444,51 +15803,57 @@ dx = snapToGrid(dx); dy = snapToGrid(dy); } - + /* + // Commenting out as currently has no effect if (evt.shiftKey) { xya = snapToAngle(startX, startY, x, y); - var _xya = xya; - x = _xya.x; - y = _xya.y; + ({x, y} = xya); } + */ + if (dx !== 0 || dy !== 0) { len = selectedElements.length; + for (i = 0; i < len; ++i) { selected = selectedElements[i]; - if (selected == null) { + + if (isNullish(selected)) { break; - } - // if (i === 0) { + } // if (i === 0) { // const box = utilsGetBBox(selected); // selectedBBoxes[i].x = box.x + dx; // selectedBBoxes[i].y = box.y + dy; // } - // update the dummy transform in our transform list // to be a translate + + var xform = svgroot.createSVGTransform(); - tlist = getTransformList(selected); - // Note that if Webkit and there's no ID for this + tlist = getTransformList(selected); // Note that if Webkit and there's no ID for this // element, the dummy transform may have gotten lost. // This results in unexpected behaviour xform.setTranslate(dx, dy); + if (tlist.numberOfItems) { tlist.replaceItem(xform, 0); } else { tlist.appendItem(xform); - } + } // update our internal bbox that we're tracking while dragging + - // update our internal bbox that we're tracking while dragging selectorManager.requestSelector(selected).resize(); } call('transition', selectedElements); } } + break; - }case 'multiselect': + } + + case 'multiselect': { realX *= currentZoom; realY *= currentZoom; @@ -14497,26 +15862,27 @@ y: Math.min(rStartY, realY), width: Math.abs(realX - rStartX), height: Math.abs(realY - rStartY) - }, 100); - - // for each selected: + }, 100); // for each selected: // - if newList contains selected, do nothing // - if newList doesn't contain selected, remove it from selected // - for any newList that was not in selectedElements, add it to selected + var elemsToRemove = selectedElements.slice(), elemsToAdd = [], - newList = getIntersectionList(); + newList = getIntersectionList(); // For every element in the intersection, add if not present in selectedElements. - // For every element in the intersection, add if not present in selectedElements. len = newList.length; + for (i = 0; i < len; ++i) { - var intElem = newList[i]; - // Found an element that was not selected before, so we should add it. + var intElem = newList[i]; // Found an element that was not selected before, so we should add it. + if (!selectedElements.includes(intElem)) { elemsToAdd.push(intElem); - } - // Found an element that was already selected, so we shouldn't remove it. + } // Found an element that was already selected, so we shouldn't remove it. + + var foundInd = elemsToRemove.indexOf(intElem); + if (foundInd !== -1) { elemsToRemove.splice(foundInd, 1); } @@ -14531,7 +15897,9 @@ } break; - }case 'resize': + } + + case 'resize': { // we track the resize bounding box and translate/scale the selected element // while the mouse is down, when mouse goes up, we use this to recalculate @@ -14544,7 +15912,6 @@ _box = box, width = _box.width, height = _box.height; - dx = x - startX; dy = y - startY; @@ -14553,22 +15920,24 @@ dy = snapToGrid(dy); height = snapToGrid(height); width = snapToGrid(width); - } + } // if rotated, adjust the dx,dy values + - // if rotated, adjust the dx,dy values angle = getRotationAngle(selected); + if (angle) { var r = Math.sqrt(dx * dx + dy * dy), theta = Math.atan2(dy, dx) - angle * Math.PI / 180.0; dx = r * Math.cos(theta); dy = r * Math.sin(theta); - } - - // if not stretching in y direction, set dy to 0 + } // if not stretching in y direction, set dy to 0 // if not stretching in x direction, set dx to 0 + + if (!currentResizeMode.includes('n') && !currentResizeMode.includes('s')) { dy = 0; } + if (!currentResizeMode.includes('e') && !currentResizeMode.includes('w')) { dx = 0; } @@ -14577,20 +15946,20 @@ tx = 0, ty = 0, sy = height ? (height + dy) / height : 1, - sx = width ? (width + dx) / width : 1; - // if we are dragging on the north side, then adjust the scale factor and ty + sx = width ? (width + dx) / width : 1; // if we are dragging on the north side, then adjust the scale factor and ty + if (currentResizeMode.includes('n')) { sy = height ? (height - dy) / height : 1; ty = height; - } + } // if we dragging on the east side, then adjust the scale factor and tx + - // if we dragging on the east side, then adjust the scale factor and tx if (currentResizeMode.includes('w')) { sx = width ? (width - dx) / width : 1; tx = width; - } + } // update the transform list with translate,scale,translate + - // update the transform list with translate,scale,translate var translateOrigin = svgroot.createSVGTransform(), scale = svgroot.createSVGTransform(), translateBack = svgroot.createSVGTransform(); @@ -14603,6 +15972,7 @@ } translateOrigin.setTranslate(-(left + tx), -(top + ty)); + if (evt.shiftKey) { if (sx === 1) { sx = sy; @@ -14610,9 +15980,10 @@ sy = sx; } } - scale.setScale(sx, sy); + scale.setScale(sx, sy); translateBack.setTranslate(left + tx, top + ty); + if (hasMatrix) { var diff = angle ? 1 : 0; tlist.replaceItem(translateOrigin, 2 + diff); @@ -14626,11 +15997,11 @@ } selectorManager.requestSelector(selected).resize(); - call('transition', selectedElements); - break; - }case 'zoom': + } + + case 'zoom': { realX *= currentZoom; realY *= currentZoom; @@ -14641,14 +16012,18 @@ height: Math.abs(realY - rStartY * currentZoom) }, 100); break; - }case 'text': + } + + case 'text': { assignAttributes(shape, { x: x, y: y }, 1000); break; - }case 'line': + } + + case 'line': { if (curConfig.gridSnapping) { x = snapToGrid(x); @@ -14664,22 +16039,24 @@ y2 = xya.y; } - shape.setAttributeNS(null, 'x2', x2); - shape.setAttributeNS(null, 'y2', y2); + shape.setAttribute('x2', x2); + shape.setAttribute('y2', y2); break; - }case 'foreignObject': - // fall through - case 'square': - // fall through - case 'rect': - // fall through + } + + case 'foreignObject': // fall through + + case 'square': // fall through + + case 'rect': // fall through + case 'image': { var square = currentMode === 'square' || evt.shiftKey; var w = Math.abs(x - startX), h = Math.abs(y - startY); - var newX = void 0, - newY = void 0; + var newX, newY; + if (square) { w = h = Math.max(w, h); newX = startX < x ? startX : startX - w; @@ -14702,22 +16079,26 @@ x: newX, y: newY }, 1000); - break; - }case 'circle': + } + + case 'circle': { c = $$9(shape).attr(['cx', 'cy']); var _c = c; cx = _c.cx; cy = _c.cy; - var rad = Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy)); + if (curConfig.gridSnapping) { rad = snapToGrid(rad); } - shape.setAttributeNS(null, 'r', rad); + + shape.setAttribute('r', rad); break; - }case 'ellipse': + } + + case 'ellipse': { c = $$9(shape).attr(['cx', 'cy']); var _c2 = c; @@ -14730,11 +16111,13 @@ y = snapToGrid(y); cy = snapToGrid(cy); } - shape.setAttributeNS(null, 'rx', Math.abs(x - cx)); + + shape.setAttribute('rx', Math.abs(x - cx)); var ry = Math.abs(evt.shiftKey ? x - cx : y - cy); - shape.setAttributeNS(null, 'ry', ry); + shape.setAttribute('ry', ry); break; } + case 'fhellipse': case 'fhrect': { @@ -14744,11 +16127,14 @@ freehand.maxy = Math.max(realY, freehand.maxy); } // Fallthrough + case 'fhpath': { // dAttr += + realX + ',' + realY + ' '; - // shape.setAttributeNS(null, 'points', dAttr); - end.x = realX;end.y = realY; + // shape.setAttribute('points', dAttr); + end.x = realX; + end.y = realY; + if (controllPoint2.x && controllPoint2.y) { for (i = 0; i < STEP_COUNT - 1; i++) { parameter = i / STEP_COUNT; @@ -14757,10 +16143,10 @@ nextPos = bSpline; bSpline = getBsplinePoint(parameter); sumDistance += Math.sqrt((nextPos.x - bSpline.x) * (nextPos.x - bSpline.x) + (nextPos.y - bSpline.y) * (nextPos.y - bSpline.y)); - if (sumDistance > THRESHOLD_DIST) { - sumDistance -= THRESHOLD_DIST; - // Faster than completely re-writing the points attribute. + if (sumDistance > THRESHOLD_DIST) { + sumDistance -= THRESHOLD_DIST; // Faster than completely re-writing the points attribute. + var point = svgcontent.createSVGPoint(); point.x = bSpline.x; point.y = bSpline.y; @@ -14768,14 +16154,24 @@ } } } - controllPoint2 = { x: controllPoint1.x, y: controllPoint1.y }; - controllPoint1 = { x: start.x, y: start.y }; - start = { x: end.x, y: end.y }; - break; - // update path stretch line coordinates - }case 'path': - // fall through + controllPoint2 = { + x: controllPoint1.x, + y: controllPoint1.y + }; + controllPoint1 = { + x: start.x, + y: start.y + }; + start = { + x: end.x, + y: end.y + }; + break; // update path stretch line coordinates + } + + case 'path': // fall through + case 'pathedit': { x *= currentZoom; @@ -14787,22 +16183,23 @@ startX = snapToGrid(startX); startY = snapToGrid(startY); } - if (evt.shiftKey) { - var path$$1 = path; - var x1 = void 0, - y1 = void 0; - if (path$$1) { - x1 = path$$1.dragging ? path$$1.dragging[0] : startX; - y1 = path$$1.dragging ? path$$1.dragging[1] : startY; + if (evt.shiftKey) { + var path$1 = path; + var x1, y1; + + if (path$1) { + x1 = path$1.dragging ? path$1.dragging[0] : startX; + y1 = path$1.dragging ? path$1.dragging[1] : startY; } else { x1 = startX; y1 = startY; } + xya = snapToAngle(x1, y1, x, y); - var _xya2 = xya; - x = _xya2.x; - y = _xya2.y; + var _xya = xya; + x = _xya.x; + y = _xya.y; } if (rubberBox && rubberBox.getAttribute('display') !== 'none') { @@ -14815,14 +16212,15 @@ height: Math.abs(realY - rStartY * currentZoom) }, 100); } - pathActions$$1.mouseMove(x, y); + pathActions$1.mouseMove(x, y); break; - }case 'textedit': + } + + case 'textedit': { x *= currentZoom; - y *= currentZoom; - // if (rubberBox && rubberBox.getAttribute('display') !== 'none') { + y *= currentZoom; // if (rubberBox && rubberBox.getAttribute('display') !== 'none') { // assignAttributes(rubberBox, { // x: Math.min(startX, x), // y: Math.min(startY, y), @@ -14832,9 +16230,10 @@ // } textActions.mouseMove(mouseX, mouseY); - break; - }case 'rotate': + } + + case 'rotate': { box = getBBox(selected); cx = box.x + box.width / 2; @@ -14844,9 +16243,11 @@ cx = center.x; cy = center.y; angle = (Math.atan2(cy - y, cx - x) * (180 / Math.PI) - 90) % 360; + if (curConfig.gridSnapping) { angle = snapToGrid(angle); } + if (evt.shiftKey) { // restrict rotations to nice angles (WRS) var snap = 45; @@ -14856,10 +16257,11 @@ canvas.setRotationAngle(angle < -180 ? 360 + angle : angle, true); call('transition', selectedElements); break; - }default: + } + + default: break; } - /** * The mouse has moved on the canvas area * @event module:svgcanvas.SvgCanvas#event:ext-mouseMove @@ -14869,19 +16271,23 @@ * @property {Float} mouse_y y coordinate on canvas * @property {Element} selected Refers to the first selected element */ - runExtensions('mouseMove', /** @type {module:svgcanvas.SvgCanvas#event:ext-mouseMove} */{ + + + runExtensions('mouseMove', + /** @type {module:svgcanvas.SvgCanvas#event:ext-mouseMove} */ + { event: evt, mouse_x: mouseX, mouse_y: mouseY, selected: selected }); }; // mouseMove() - // - in create mode, the element's opacity is set properly, we create an InsertElementCommand // and store it on the Undo stack // - in move/resize mode, the element's attributes which were affected by the move/resize are // identified, a ChangeElementCommand is created and stored on the stack for those attrs // this is done in when we recalculate the selected dimensions() + /** * * @param {MouseEvent} evt @@ -14890,51 +16296,59 @@ * @fires module:svgcanvas.SvgCanvas#event:ext-mouseUp * @returns {undefined} */ + + var mouseUp = function mouseUp(evt) { if (evt.button === 2) { return; } + var tempJustSelected = justSelected; justSelected = null; + if (!started) { return; } + var pt = transformPoint(evt.pageX, evt.pageY, rootSctm), mouseX = pt.x * currentZoom, mouseY = pt.y * currentZoom, x = mouseX / currentZoom, y = mouseY / currentZoom; - var element = getElem(getId()); var keep = false; - var realX = x; - var realY = y; + var realY = y; // TODO: Make true when in multi-unit mode + started = false; - var attrs = void 0, - t = void 0; + var attrs, t; + switch (currentMode) { // intentionally fall-through to select here case 'resize': case 'multiselect': - if (rubberBox != null) { + if (!isNullish(rubberBox)) { rubberBox.setAttribute('display', 'none'); curBBoxes = []; } + currentMode = 'select'; // Fallthrough + case 'select': - if (selectedElements[0] != null) { + if (!isNullish(selectedElements[0])) { // if we only have one selected element - if (selectedElements[1] == null) { + if (isNullish(selectedElements[1])) { // set our current stroke/fill properties to the element's var selected = selectedElements[0]; + switch (selected.tagName) { case 'g': case 'use': case 'image': case 'foreignObject': break; + default: curProperties.fill = selected.getAttribute('fill'); curProperties.fill_opacity = selected.getAttribute('fill-opacity'); @@ -14950,31 +16364,33 @@ curText.font_size = selected.getAttribute('font-size'); curText.font_family = selected.getAttribute('font-family'); } - selectorManager.requestSelector(selected).showGrips(true); - // This shouldn't be necessary as it was done on mouseDown... + selectorManager.requestSelector(selected).showGrips(true); // This shouldn't be necessary as it was done on mouseDown... // call('selected', [selected]); - } - // always recalculate dimensions to strip off stray identity transforms - recalculateAllSelectedDimensions(); - // if it was being dragged/resized + } // always recalculate dimensions to strip off stray identity transforms + + + recalculateAllSelectedDimensions(); // if it was being dragged/resized + if (realX !== rStartX || realY !== rStartY) { var len = selectedElements.length; + for (var i = 0; i < len; ++i) { - if (selectedElements[i] == null) { + if (isNullish(selectedElements[i])) { break; } + if (!selectedElements[i].firstChild) { // Not needed for groups (incorrectly resizes elems), possibly not needed at all? selectorManager.requestSelector(selectedElements[i]).resize(); } - } - // 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 { t = evt.target; - if (selectedElements[0].nodeName === 'path' && selectedElements[1] == null) { - pathActions$$1.select(selectedElements[0]); - // if it was a path + + if (selectedElements[0].nodeName === 'path' && isNullish(selectedElements[1])) { + pathActions$1.select(selectedElements[0]); // if it was a path // else, if it was selected and this is a shift-click, remove it from selection } else if (evt.shiftKey) { if (tempJustSelected !== t) { @@ -14982,72 +16398,102 @@ } } } // no change in mouse position - // Remove non-scaling stroke + + if (supportsNonScalingStroke()) { var elem = selectedElements[0]; + if (elem) { elem.removeAttribute('style'); - walkTree(elem, function (elem) { - elem.removeAttribute('style'); + walkTree(elem, function (el) { + el.removeAttribute('style'); }); } } } + return; + case 'zoom': - if (rubberBox != null) { - rubberBox.setAttribute('display', 'none'); + { + if (!isNullish(rubberBox)) { + rubberBox.setAttribute('display', 'none'); + } + + var factor = evt.shiftKey ? 0.5 : 2; + call('zoomed', { + x: Math.min(rStartX, realX), + y: Math.min(rStartY, realY), + width: Math.abs(realX - rStartX), + height: Math.abs(realY - rStartY), + factor: factor + }); + return; } - var factor = evt.shiftKey ? 0.5 : 2; - call('zoomed', { - x: Math.min(rStartX, realX), - y: Math.min(rStartY, realY), - width: Math.abs(realX - rStartX), - height: Math.abs(realY - rStartY), - factor: factor - }); - return; + case 'fhpath': - // Check that the path contains at least 2 points; a degenerate one-point path - // causes problems. - // Webkit ignores how we set the points attribute with commas and uses space - // to separate all coordinates, see https://bugs.webkit.org/show_bug.cgi?id=29870 - sumDistance = 0; - controllPoint2 = { x: 0, y: 0 }; - controllPoint1 = { x: 0, y: 0 }; - start = { x: 0, y: 0 }; - end = { x: 0, y: 0 }; - var coords = element.getAttribute('points'); - var commaIndex = coords.indexOf(','); - if (commaIndex >= 0) { - keep = coords.indexOf(',', commaIndex + 1) >= 0; - } else { - keep = coords.indexOf(' ', coords.indexOf(' ') + 1) >= 0; + { + // Check that the path contains at least 2 points; a degenerate one-point path + // causes problems. + // Webkit ignores how we set the points attribute with commas and uses space + // to separate all coordinates, see https://bugs.webkit.org/show_bug.cgi?id=29870 + sumDistance = 0; + controllPoint2 = { + x: 0, + y: 0 + }; + controllPoint1 = { + x: 0, + y: 0 + }; + start = { + x: 0, + y: 0 + }; + end = { + x: 0, + y: 0 + }; + var coords = element.getAttribute('points'); + var commaIndex = coords.indexOf(','); + + if (commaIndex >= 0) { + keep = coords.indexOf(',', commaIndex + 1) >= 0; + } else { + keep = coords.indexOf(' ', coords.indexOf(' ') + 1) >= 0; + } + + if (keep) { + element = pathActions$1.smoothPolylineIntoPath(element); + } + + break; } - if (keep) { - element = pathActions$$1.smoothPolylineIntoPath(element); - } - break; + case 'line': attrs = $$9(element).attr(['x1', 'x2', 'y1', 'y2']); keep = attrs.x1 !== attrs.x2 || attrs.y1 !== attrs.y2; break; + case 'foreignObject': case 'square': case 'rect': case 'image': - attrs = $$9(element).attr(['width', 'height']); - // Image should be kept regardless of size (use inherit dimensions later) + attrs = $$9(element).attr(['width', 'height']); // Image should be kept regardless of size (use inherit dimensions later) + keep = attrs.width || attrs.height || currentMode === 'image'; break; + case 'circle': keep = element.getAttribute('r') !== '0'; break; + case 'ellipse': attrs = $$9(element).attr(['rx', 'ry']); keep = attrs.rx || attrs.ry; break; + case 'fhellipse': if (freehand.maxx - freehand.minx > 0 && freehand.maxy - freehand.miny > 0) { element = addSVGElementFromJson({ @@ -15064,7 +16510,9 @@ call('changed', [element]); keep = true; } + break; + case 'fhrect': if (freehand.maxx - freehand.minx > 0 && freehand.maxy - freehand.miny > 0) { element = addSVGElementFromJson({ @@ -15081,50 +16529,60 @@ call('changed', [element]); keep = true; } + break; + case 'text': keep = true; selectOnly([element]); textActions.start(element); break; + case 'path': - // set element to null here so that it is not removed nor finalized - element = null; - // continue to be set to true so that mouseMove happens - started = true; + { + // set element to null here so that it is not removed nor finalized + element = null; // continue to be set to true so that mouseMove happens - var res = pathActions$$1.mouseUp(evt, element, mouseX, mouseY); - element = res.element; - keep = res.keep; + started = true; + var res = pathActions$1.mouseUp(evt, element, mouseX, mouseY); + element = res.element; + keep = res.keep; + break; + } - break; case 'pathedit': keep = true; element = null; - pathActions$$1.mouseUp(evt); + pathActions$1.mouseUp(evt); break; + case 'textedit': keep = false; element = null; textActions.mouseUp(evt, mouseX, mouseY); break; + case 'rotate': - keep = true; - element = null; - currentMode = 'select'; - var batchCmd = canvas.undoMgr.finishUndoableChange(); - if (!batchCmd.isEmpty()) { - addCommandToHistory(batchCmd); + { + keep = true; + element = null; + currentMode = 'select'; + var batchCmd = canvas.undoMgr.finishUndoableChange(); + + if (!batchCmd.isEmpty()) { + addCommandToHistory(batchCmd); + } // perform recalculation to weed out any stray identity transforms that might get stuck + + + recalculateAllSelectedDimensions(); + call('changed', selectedElements); + break; } - // perform recalculation to weed out any stray identity transforms that might get stuck - recalculateAllSelectedDimensions(); - call('changed', selectedElements); - break; + default: // This could occur in an extension break; } - /** * The main (left) mouse button is released (anywhere) * @event module:svgcanvas.SvgCanvas#event:ext-mouseUp @@ -15133,43 +16591,44 @@ * @property {Float} mouse_x x coordinate on canvas * @property {Float} mouse_y y coordinate on canvas */ - var extResult = runExtensions('mouseUp', /** @type {module:svgcanvas.SvgCanvas#event:ext-mouseUp} */{ + + + var extResult = runExtensions('mouseUp', + /** @type {module:svgcanvas.SvgCanvas#event:ext-mouseUp} */ + { event: evt, mouse_x: mouseX, mouse_y: mouseY }, true); - $$9.each(extResult, function (i, r) { if (r) { keep = r.keep || keep; element = r.element; - started = r.started || started; } }); - if (!keep && element != null) { + if (!keep && !isNullish(element)) { getCurrentDrawing().releaseId(getId()); element.remove(); element = null; - - t = evt.target; - - // if this element is in a group, go up until we reach the top-level group + t = evt.target; // if this element is in a group, go up until we reach the top-level group // just below the layer groups // TODO: once we implement links, we also would have to check for <a> elements + while (t && t.parentNode && t.parentNode.parentNode && t.parentNode.parentNode.tagName === 'g') { t = t.parentNode; - } - // if we are not in the middle of creating a path, and we've clicked on some shape, + } // if we are not in the middle of creating a path, and we've clicked on some shape, // then go to Select mode. // WebKit returns <div> when the canvas is clicked, Firefox/Opera return <svg> + + if ((currentMode !== 'path' || !drawnPath) && t && t.parentNode && t.parentNode.id !== 'selectorParentGroup' && t.id !== 'svgcanvas' && t.id !== 'svgroot') { // switch into "select" mode if we've clicked on an element canvas.setMode('select'); selectOnly([t], true); } - } else if (element != null) { + } else if (!isNullish(element)) { /** * @name module:svgcanvas.SvgCanvas#addedNew * @type {boolean} @@ -15177,38 +16636,42 @@ canvas.addedNew = true; var aniDur = 0.2; - var cAni = void 0; + var cAni; + if (opacAni.beginElement && parseFloat(element.getAttribute('opacity')) !== curShape.opacity) { cAni = $$9(opacAni).clone().attr({ to: curShape.opacity, dur: aniDur }).appendTo(element); + try { // Fails in FF4 on foreignObject cAni[0].beginElement(); } catch (e) {} } else { aniDur = 0; - } - - // Ideally this would be done on the endEvent of the animation, + } // Ideally this would be done on the endEvent of the animation, // but that doesn't seem to be supported in Webkit + + setTimeout(function () { if (cAni) { cAni.remove(); } + element.setAttribute('opacity', curShape.opacity); element.setAttribute('style', 'pointer-events:inherit'); cleanupElement(element); + if (currentMode === 'path') { - pathActions$$1.toEditMode(element); + pathActions$1.toEditMode(element); } else if (curConfig.selectNew) { selectOnly([element], true); - } - // we create the insert command that is stored on the stack + } // we create the insert command that is stored on the stack // undo means to call cmd.unapply(), redo means to call cmd.apply() - addCommandToHistory(new InsertElementCommand$1(element)); + + addCommandToHistory(new InsertElementCommand$1(element)); call('changed', [element]); }, aniDur * 1000); } @@ -15218,9 +16681,8 @@ var dblClick = function dblClick(evt) { var evtTarget = evt.target; - var parent = evtTarget.parentNode; + var parent = evtTarget.parentNode; // Do nothing if already in current group - // Do nothing if already in current group if (parent === currentGroup) { return; } @@ -15229,7 +16691,6 @@ var _mouseTarget = mouseTarget, tagName = _mouseTarget.tagName; - if (tagName === 'text' && currentMode !== 'textedit') { var pt = transformPoint(evt.pageX, evt.pageY, rootSctm); textActions.select(mouseTarget, pt.x, pt.y); @@ -15238,13 +16699,13 @@ if ((tagName === 'g' || tagName === 'a') && getRotationAngle(mouseTarget)) { // TODO: Allow method of in-group editing without having to do // this (similar to editing rotated paths) - // Ungroup and regroup pushGroupProperties(mouseTarget); mouseTarget = selectedElements[0]; clearSelection(true); - } - // Reset context + } // Reset context + + if (currentGroup) { leaveContext(); } @@ -15253,21 +16714,21 @@ // Escape from in-group edit return; } - setContext(mouseTarget); - }; - // prevent links from being followed in the canvas + setContext(mouseTarget); + }; // prevent links from being followed in the canvas + + var handleLinkInCanvas = function handleLinkInCanvas(e) { e.preventDefault(); return false; - }; - - // Added mouseup to the container here. + }; // Added mouseup to the container here. // TODO(codedread): Figure out why after the Closure compiler, the window mouseup is ignored. - $$9(container).mousedown(mouseDown).mousemove(mouseMove).click(handleLinkInCanvas).dblclick(dblClick).mouseup(mouseUp); - // $(window).mouseup(mouseUp); + + $$9(container).mousedown(mouseDown).mousemove(mouseMove).click(handleLinkInCanvas).dblclick(dblClick).mouseup(mouseUp); // $(window).mouseup(mouseUp); // TODO(rafaelcastrocouto): User preference for shift key and zoom factor + $$9(container).bind('mousewheel DOMMouseScroll', /** * @param {Event} e @@ -15282,42 +16743,34 @@ e.preventDefault(); var evt = e.originalEvent; - rootSctm = $$9('#svgcontent g')[0].getScreenCTM().inverse(); - var workarea = $$9('#workarea'); var scrbar = 15; - var rulerwidth = curConfig.showRulers ? 16 : 0; + var rulerwidth = curConfig.showRulers ? 16 : 0; // mouse relative to content area in content pixels - // mouse relative to content area in content pixels - var pt = transformPoint(evt.pageX, evt.pageY, rootSctm); + var pt = transformPoint(evt.pageX, evt.pageY, rootSctm); // full work area width in screen pixels - // full work area width in screen pixels var editorFullW = workarea.width(); - var editorFullH = workarea.height(); + var editorFullH = workarea.height(); // work area width minus scroll and ruler in screen pixels - // work area width minus scroll and ruler in screen pixels var editorW = editorFullW - scrbar - rulerwidth; - var editorH = editorFullH - scrbar - rulerwidth; + var editorH = editorFullH - scrbar - rulerwidth; // work area width in content pixels - // work area width in content pixels var workareaViewW = editorW * rootSctm.a; - var workareaViewH = editorH * rootSctm.d; + var workareaViewH = editorH * rootSctm.d; // content offset from canvas in screen pixels - // content offset from canvas in screen pixels var wOffset = workarea.offset(); - var wOffsetLeft = wOffset['left'] + rulerwidth; - var wOffsetTop = wOffset['top'] + rulerwidth; - + var wOffsetLeft = wOffset.left + rulerwidth; + var wOffsetTop = wOffset.top + rulerwidth; var delta = evt.wheelDelta ? evt.wheelDelta : evt.detail ? -evt.detail : 0; + if (!delta) { return; } var factor = Math.max(3 / 4, Math.min(4 / 3, delta)); + var wZoom, hZoom; - var wZoom = void 0, - hZoom = void 0; if (factor > 1) { wZoom = Math.ceil(editorW / workareaViewW * factor * 100) / 100; hZoom = Math.ceil(editorH / workareaViewH * factor * 100) / 100; @@ -15325,60 +16778,66 @@ wZoom = Math.floor(editorW / workareaViewW * factor * 100) / 100; hZoom = Math.floor(editorH / workareaViewH * factor * 100) / 100; } + var zoomlevel = Math.min(wZoom, hZoom); zoomlevel = Math.min(10, Math.max(0.01, zoomlevel)); + if (zoomlevel === currentZoom) { return; } - factor = zoomlevel / currentZoom; - // top left of workarea in content pixels before zoom - var topLeftOld = transformPoint(wOffsetLeft, wOffsetTop, rootSctm); + factor = zoomlevel / currentZoom; // top left of workarea in content pixels before zoom + + var topLeftOld = transformPoint(wOffsetLeft, wOffsetTop, rootSctm); // top left of workarea in content pixels after zoom - // top left of workarea in content pixels after zoom var topLeftNew = { x: pt.x - (pt.x - topLeftOld.x) / factor, y: pt.y - (pt.y - topLeftOld.y) / factor - }; + }; // top left of workarea in canvas pixels relative to content after zoom - // top left of workarea in canvas pixels relative to content after zoom var topLeftNewCanvas = { x: topLeftNew.x * zoomlevel, y: topLeftNew.y * zoomlevel - }; + }; // new center in canvas pixels - // new center in canvas pixels var newCtr = { x: topLeftNewCanvas.x - rulerwidth + editorFullW / 2, y: topLeftNewCanvas.y - rulerwidth + editorFullH / 2 }; - canvas.setZoom(zoomlevel); $$9('#zoom').val((zoomlevel * 100).toFixed(1)); - - call('updateCanvas', { center: false, newCtr: newCtr }); + call('updateCanvas', { + center: false, + newCtr: newCtr + }); call('zoomDone'); }); })(); - /** * Group: Text edit functions * Functions relating to editing text elements * @namespace {PlainObject} textActions * @memberof module:svgcanvas.SvgCanvas# */ + + var textActions = canvas.textActions = function () { - var curtext = void 0; - var textinput = void 0; - var cursor = void 0; - var selblock = void 0; - var blinker = void 0; + var curtext; + var textinput; + var cursor; + var selblock; + var blinker; var chardata = []; - var textbb = void 0; // , transbb; - var matrix = void 0; - var lastX = void 0, - lastY = void 0; - var allowDbl = void 0; + var textbb; // , transbb; + + var matrix; + var lastX, lastY; + var allowDbl; + /** + * + * @param {Integer} index + * @returns {undefined} + */ function setCursor(index) { var empty = textinput.value === ''; @@ -15391,15 +16850,19 @@ if (textinput.selectionEnd !== textinput.selectionStart) { return; } + index = textinput.selectionEnd; } } var charbb = chardata[index]; + if (!empty) { textinput.setSelectionRange(index, index); } + cursor = getElem('text_cursor'); + if (!cursor) { cursor = document.createElementNS(NS.SVG, 'line'); assignAttributes(cursor, { @@ -15419,7 +16882,6 @@ var startPt = ptToScreen(charbb.x, textbb.y); var endPt = ptToScreen(charbb.x, textbb.y + textbb.height); - assignAttributes(cursor, { x1: startPt.x, y1: startPt.y, @@ -15433,6 +16895,14 @@ selblock.setAttribute('d', ''); } } + /** + * + * @param {Integer} start + * @param {Integer} end + * @param {boolean} skipInput + * @returns {undefined} + */ + function setSelection(start, end, skipInput) { if (start === end) { @@ -15445,6 +16915,7 @@ } selblock = getElem('text_selectblock'); + if (!selblock) { selblock = document.createElementNS(NS.SVG, 'path'); assignAttributes(selblock, { @@ -15458,70 +16929,98 @@ var startbb = chardata[start]; var endbb = chardata[end]; - cursor.setAttribute('visibility', 'hidden'); - var tl = ptToScreen(startbb.x, textbb.y), tr = ptToScreen(startbb.x + (endbb.x - startbb.x), textbb.y), bl = ptToScreen(startbb.x, textbb.y + textbb.height), br = ptToScreen(startbb.x + (endbb.x - startbb.x), textbb.y + textbb.height); - var dstr = 'M' + tl.x + ',' + tl.y + ' L' + tr.x + ',' + tr.y + ' ' + br.x + ',' + br.y + ' ' + bl.x + ',' + bl.y + 'z'; - assignAttributes(selblock, { d: dstr, display: 'inline' }); } + /** + * + * @param {Float} mouseX + * @param {Float} mouseY + * @returns {Integer} + */ + function getIndexFromPoint(mouseX, mouseY) { // Position cursor here var pt = svgroot.createSVGPoint(); pt.x = mouseX; - pt.y = mouseY; + pt.y = mouseY; // No content, so return 0 - // No content, so return 0 if (chardata.length === 1) { return 0; - } - // Determine if cursor should be on left or right of character + } // Determine if cursor should be on left or right of character + + var charpos = curtext.getCharNumAtPosition(pt); + if (charpos < 0) { // Out of text range, look at mouse coords charpos = chardata.length - 2; + if (mouseX <= chardata[0].x) { charpos = 0; } } else if (charpos >= chardata.length - 2) { charpos = chardata.length - 2; } + var charbb = chardata[charpos]; var mid = charbb.x + charbb.width / 2; + if (mouseX > mid) { charpos++; } + return charpos; } + /** + * + * @param {Float} mouseX + * @param {Float} mouseY + * @returns {undefined} + */ + function setCursorFromPoint(mouseX, mouseY) { setCursor(getIndexFromPoint(mouseX, mouseY)); } + /** + * + * @param {Float} x + * @param {Float} y + * @param {boolean} apply + * @returns {undefined} + */ + function setEndSelectionFromPoint(x, y, apply) { var i1 = textinput.selectionStart; var i2 = getIndexFromPoint(x, y); - var start = Math.min(i1, i2); var end = Math.max(i1, i2); setSelection(start, end, !apply); } + /** + * + * @param {Float} xIn + * @param {Float} yIn + * @returns {module:math.XYObject} + */ + function screenToPt(xIn, yIn) { var out = { x: xIn, y: yIn }; - out.x /= currentZoom; out.y /= currentZoom; @@ -15533,6 +17032,13 @@ return out; } + /** + * + * @param {Float} xIn + * @param {Float} yIn + * @returns {module:math.XYObject} + */ + function ptToScreen(xIn, yIn) { var out = { @@ -15548,10 +17054,8 @@ out.x *= currentZoom; out.y *= currentZoom; - return out; } - /* // Not currently in use function hideCursor () { @@ -15561,10 +17065,23 @@ } */ + /** + * + * @param {Event} evt + * @returns {undefined} + */ + + function selectAll(evt) { setSelection(0, curtext.textContent.length); $$9(this).unbind(evt); } + /** + * + * @param {Event} evt + * @returns {undefined} + */ + function selectWord(evt) { if (!allowDbl || !curtext) { @@ -15575,22 +17092,22 @@ mouseX = ept.x * currentZoom, mouseY = ept.y * currentZoom; var pt = screenToPt(mouseX, mouseY); - var index = getIndexFromPoint(pt.x, pt.y); var str = curtext.textContent; var first = str.substr(0, index).replace(/[a-z0-9]+$/i, '').length; var m = str.substr(index).match(/^[a-z0-9]+/i); var last = (m ? m[0].length : 0) + index; - setSelection(first, last); + setSelection(first, last); // Set tripleclick - // Set tripleclick $$9(evt.target).click(selectAll); setTimeout(function () { $$9(evt.target).unbind('click', selectAll); }, 300); } - return (/** @lends module:svgcanvas.SvgCanvas#textActions */{ + return ( + /** @lends module:svgcanvas.SvgCanvas#textActions */ + { /** * @param {Element} target * @param {Float} x @@ -15620,13 +17137,10 @@ */ mouseDown: function mouseDown(evt, mouseTarget, startX, startY) { var pt = screenToPt(startX, startY); - textinput.focus(); setCursorFromPoint(pt.x, pt.y); lastX = startX; - lastY = startY; - - // TODO: Find way to block native selection + lastY = startY; // TODO: Find way to block native selection }, /** @@ -15640,17 +17154,14 @@ }, /** - * @param {external:MouseEvent} + * @param {external:MouseEvent} evt * @param {Float} mouseX * @param {Float} mouseY * @returns {undefined} */ mouseUp: function mouseUp(evt, mouseX, mouseY) { var pt = screenToPt(mouseX, mouseY); - - setEndSelectionFromPoint(pt.x, pt.y, true); - - // TODO: Find a way to make this work: Use transformed BBox instead of evt.target + setEndSelectionFromPoint(pt.x, pt.y, true); // TODO: Find a way to make this work: Use transformed BBox instead of evt.target // if (lastX === mouseX && lastY === mouseY // && !rectsIntersect(transbb, {x: pt.x, y: pt.y, width: 0, height: 0})) { // textActions.toSelectMode(true); @@ -15667,6 +17178,7 @@ * @returns {undefined} */ setCursor: setCursor, + /** * @param {Float} x * @param {Float} y @@ -15675,16 +17187,15 @@ toEditMode: function toEditMode(x, y) { allowDbl = false; currentMode = 'textedit'; - selectorManager.requestSelector(curtext).showGrips(false); - // Make selector group accept clicks - /* const selector = */selectorManager.requestSelector(curtext); // Do we need this? Has side effect of setting lock, so keeping for now, but next line wasn't being used + selectorManager.requestSelector(curtext).showGrips(false); // Make selector group accept clicks + + /* const selector = */ + + selectorManager.requestSelector(curtext); // Do we need this? Has side effect of setting lock, so keeping for now, but next line wasn't being used // const sel = selector.selectorRect; textActions.init(); - - $$9(curtext).css('cursor', 'text'); - - // if (supportsEditableText()) { + $$9(curtext).css('cursor', 'text'); // if (supportsEditableText()) { // curtext.setAttribute('editable', 'simple'); // return; // } @@ -15710,31 +17221,31 @@ currentMode = 'select'; clearInterval(blinker); blinker = null; + if (selblock) { $$9(selblock).attr('display', 'none'); } + if (cursor) { $$9(cursor).attr('visibility', 'hidden'); } + $$9(curtext).css('cursor', 'move'); if (selectElem) { clearSelection(); $$9(curtext).css('cursor', 'move'); - call('selected', [curtext]); addToSelection([curtext], true); } + if (curtext && !curtext.textContent.length) { // No content, so delete canvas.deleteSelectedElements(); } $$9(textinput).blur(); - - curtext = false; - - // if (supportsEditableText()) { + curtext = false; // if (supportsEditableText()) { // curtext.removeAttribute('editable'); // } }, @@ -15744,8 +17255,7 @@ * @returns {undefined} */ setInputElem: function setInputElem(elem) { - textinput = elem; - // $(textinput).blur(hideCursor); + textinput = elem; // $(textinput).blur(hideCursor); }, /** @@ -15761,13 +17271,12 @@ * @param {Element} inputElem Not in use * @returns {undefined} */ - init: function init$$1(inputElem) { + init: function init(inputElem) { if (!curtext) { return; } - var i = void 0, - end = void 0; - // if (supportsEditableText()) { + + var i, end; // if (supportsEditableText()) { // curtext.select(); // return; // } @@ -15780,21 +17289,19 @@ var str = curtext.textContent; var len = str.length; - var xform = curtext.getAttribute('transform'); - textbb = getBBox(curtext); - matrix = xform ? getMatrix(curtext) : null; - chardata = []; chardata.length = len; textinput.focus(); - $$9(curtext).unbind('dblclick', selectWord).dblclick(selectWord); if (!len) { - end = { x: textbb.x + textbb.width / 2, width: 0 }; + end = { + x: textbb.x + textbb.width / 2, + width: 0 + }; } for (i = 0; i < len; i++) { @@ -15805,24 +17312,23 @@ var offset = canvas.contentW * currentZoom; start.x -= offset; end.x -= offset; - start.x /= currentZoom; end.x /= currentZoom; - } - - // Get a "bbox" equivalent for each character. Uses the + } // Get a "bbox" equivalent for each character. Uses the // bbox data of the actual text for y, height purposes - // TODO: Decide if y, width and height are actually necessary + + chardata[i] = { x: start.x, - y: textbb.y, // start.y? + y: textbb.y, + // start.y? width: end.x - start.x, height: textbb.height }; - } + } // Add a last bbox for cursor at end of text + - // Add a last bbox for cursor at end of text chardata.push({ x: end.x, width: 0 @@ -15832,7 +17338,6 @@ } ); }(); - /** * Group: Serialization */ @@ -15843,35 +17348,38 @@ * @function module:svgcanvas.SvgCanvas#removeUnusedDefElems * @returns {Integer} The number of elements that were removed */ + + var removeUnusedDefElems = this.removeUnusedDefElems = function () { var defs = svgcontent.getElementsByTagNameNS(NS.SVG, 'defs'); + if (!defs || !defs.length) { return 0; - } + } // if (!defs.firstChild) { return; } - // if (!defs.firstChild) { return; } var defelemUses = []; var numRemoved = 0; var attrs = ['fill', 'stroke', 'filter', 'marker-start', 'marker-mid', 'marker-end']; var alen = attrs.length; - var allEls = svgcontent.getElementsByTagNameNS(NS.SVG, '*'); var allLen = allEls.length; + var i, j; - var i = void 0, - j = void 0; for (i = 0; i < allLen; i++) { var el = allEls[i]; + for (j = 0; j < alen; j++) { var ref = getUrlFromAttr(el.getAttribute(attrs[j])); + if (ref) { defelemUses.push(ref.substr(1)); } - } + } // gradients can refer to other gradients + - // gradients can refer to other gradients var href = getHref(el); + if (href && href.startsWith('#')) { defelemUses.push(href.substr(1)); } @@ -15879,6 +17387,7 @@ var defelems = $$9(defs).find('linearGradient, radialGradient, filter, marker, svg, symbol'); i = defelems.length; + while (i--) { var defelem = defelems[i]; var id = defelem.id; @@ -15893,52 +17402,52 @@ return numRemoved; }; - /** - * Main function to set up the SVG content for output + * Main function to set up the SVG content for output. * @function module:svgcanvas.SvgCanvas#svgCanvasToString * @returns {string} The SVG image for output */ + + this.svgCanvasToString = function () { // keep calling it until there are none to remove - while (removeUnusedDefElems() > 0) {} + while (removeUnusedDefElems() > 0) {} // eslint-disable-line no-empty - pathActions$$1.clear(true); - // Keep SVG-Edit comment on top + pathActions$1.clear(true); // Keep SVG-Edit comment on top + $$9.each(svgcontent.childNodes, function (i, node) { if (i && node.nodeType === 8 && node.data.includes('Created with')) { svgcontent.firstChild.before(node); } - }); + }); // Move out of in-group editing mode - // Move out of in-group editing mode if (currentGroup) { leaveContext(); selectOnly([currentGroup]); } - var nakedSvgs = []; + var nakedSvgs = []; // Unwrap gsvg if it has no special attributes (only id and style) - // Unwrap gsvg if it has no special attributes (only id and style) $$9(svgcontent).find('g:data(gsvg)').each(function () { var attrs = this.attributes; var len = attrs.length; + for (var i = 0; i < len; i++) { if (attrs[i].nodeName === 'id' || attrs[i].nodeName === 'style') { len--; } - } - // No significant attributes, so ungroup + } // No significant attributes, so ungroup + + if (len <= 0) { var svg = this.firstChild; nakedSvgs.push(svg); $$9(this).replaceWith(svg); } }); - var output = this.svgToString(svgcontent, 0); + var output = this.svgToString(svgcontent, 0); // Rewrap gsvg - // Rewrap gsvg if (nakedSvgs.length) { $$9(nakedSvgs).each(function () { groupSvgElem(this); @@ -15947,14 +17456,15 @@ return output; }; - /** - * Sub function ran on each SVG element to convert it to a string as desired + * Sub function ran on each SVG element to convert it to a string as desired. * @function module:svgcanvas.SvgCanvas#svgToString * @param {Element} elem - The SVG element to convert * @param {Integer} indent - Number of spaces to indent this tag * @returns {string} The given element as an SVG tag */ + + this.svgToString = function (elem, indent) { var out = []; var unit = curConfig.baseUnit; @@ -15962,23 +17472,25 @@ if (elem) { cleanupElement(elem); - var attrs = Array.from(elem.attributes); - var i = void 0; + + var attrs = _toConsumableArray(elem.attributes); + var childs = elem.childNodes; attrs.sort(function (a, b) { return a.name > b.name ? -1 : 1; }); - for (i = 0; i < indent; i++) { + for (var i = 0; i < indent; i++) { out.push(' '); } - out.push('<');out.push(elem.nodeName); + + out.push('<'); + out.push(elem.nodeName); + if (elem.id === 'svgcontent') { // Process root element separately var res = getResolution(); - - var vb = ''; - // TODO: Allow this by dividing all values by current baseVal + var vb = ''; // TODO: Allow this by dividing all values by current baseVal // Note that this also means we should properly deal with this on import // if (curConfig.baseUnit !== 'px') { // const unit = curConfig.baseUnit; @@ -15996,92 +17508,104 @@ } out.push(' width="' + res.w + '" height="' + res.h + '"' + vb + ' xmlns="' + NS.SVG + '"'); + var nsuris = {}; // Check elements for namespaces, add if found - var nsuris = {}; - - // Check elements for namespaces, add if found $$9(elem).find('*').andSelf().each(function () { // const el = this; // for some elements have no attribute var uri = this.namespaceURI; + if (uri && !nsuris[uri] && nsMap[uri] && nsMap[uri] !== 'xmlns' && nsMap[uri] !== 'xml') { nsuris[uri] = true; out.push(' xmlns:' + nsMap[uri] + '="' + uri + '"'); } $$9.each(this.attributes, function (i, attr) { - var uri = attr.namespaceURI; - if (uri && !nsuris[uri] && nsMap[uri] !== 'xmlns' && nsMap[uri] !== 'xml') { - nsuris[uri] = true; - out.push(' xmlns:' + nsMap[uri] + '="' + uri + '"'); + var u = attr.namespaceURI; + + if (u && !nsuris[u] && nsMap[u] !== 'xmlns' && nsMap[u] !== 'xml') { + nsuris[u] = true; + out.push(' xmlns:' + nsMap[u] + '="' + u + '"'); } }); }); - - i = attrs.length; + var _i3 = attrs.length; var attrNames = ['width', 'height', 'xmlns', 'x', 'y', 'viewBox', 'id', 'overflow']; - while (i--) { - var attr = attrs[i]; - var attrVal = toXml(attr.value); - // Namespaces have already been dealt with, so skip + while (_i3--) { + var attr = attrs[_i3]; + var attrVal = toXml(attr.value); // Namespaces have already been dealt with, so skip + if (attr.nodeName.startsWith('xmlns:')) { continue; - } + } // only serialize attributes we don't use internally + - // only serialize attributes we don't use internally if (attrVal !== '' && !attrNames.includes(attr.localName)) { if (!attr.namespaceURI || nsMap[attr.namespaceURI]) { out.push(' '); - out.push(attr.nodeName);out.push('="'); - out.push(attrVal);out.push('"'); + out.push(attr.nodeName); + out.push('="'); + out.push(attrVal); + out.push('"'); } } } } else { // Skip empty defs if (elem.nodeName === 'defs' && !elem.firstChild) { - return; + return ''; } var mozAttrs = ['-moz-math-font-style', '_moz-math-font-style']; - for (i = attrs.length - 1; i >= 0; i--) { - var _attr = attrs[i]; - var _attrVal = toXml(_attr.value); - // remove bogus attributes added by Gecko + + for (var _i4 = attrs.length - 1; _i4 >= 0; _i4--) { + var _attr = attrs[_i4]; + + var _attrVal = toXml(_attr.value); // remove bogus attributes added by Gecko + + if (mozAttrs.includes(_attr.localName)) { continue; } + if (_attrVal !== '') { if (_attrVal.startsWith('pointer-events')) { continue; } + if (_attr.localName === 'class' && _attrVal.startsWith('se_')) { continue; } + out.push(' '); + if (_attr.localName === 'd') { - _attrVal = pathActions$$1.convertPath(elem, true); + _attrVal = pathActions$1.convertPath(elem, true); } + if (!isNaN(_attrVal)) { _attrVal = shortFloat(_attrVal); } else if (unitRe.test(_attrVal)) { _attrVal = shortFloat(_attrVal) + unit; - } + } // Embed images when saving + - // Embed images when saving if (saveOptions.apply && elem.nodeName === 'image' && _attr.localName === 'href' && saveOptions.images && saveOptions.images === 'embed') { var img = encodableImages[_attrVal]; + if (img) { _attrVal = img; } - } - - // map various namespaces to our fixed namespace prefixes + } // map various namespaces to our fixed namespace prefixes // (the default xmlns attribute itself does not get a prefix) + + if (!_attr.namespaceURI || _attr.namespaceURI === NS.SVG || nsMap[_attr.namespaceURI]) { - out.push(_attr.nodeName);out.push('="'); - out.push(_attrVal);out.push('"'); + out.push(_attr.nodeName); + out.push('="'); + out.push(_attrVal); + out.push('"'); } } } @@ -16092,22 +17616,29 @@ indent++; var bOneLine = false; - for (i = 0; i < childs.length; i++) { - var child = childs.item(i); + for (var _i5 = 0; _i5 < childs.length; _i5++) { + var child = childs.item(_i5); + switch (child.nodeType) { case 1: // element node out.push('\n'); - out.push(this.svgToString(childs.item(i), indent)); + out.push(this.svgToString(childs.item(_i5), indent)); break; + case 3: - // text node - var str = child.nodeValue.replace(/^\s+|\s+$/g, ''); - if (str !== '') { - bOneLine = true; - out.push(String(toXml(str))); + { + // text node + var str = child.nodeValue.replace(/^\s+|\s+$/g, ''); + + if (str !== '') { + bOneLine = true; + out.push(String(toXml(str))); + } + + break; } - break; + case 4: // cdata node out.push('\n'); @@ -16116,6 +17647,7 @@ out.push(child.nodeValue); out.push(']]>'); break; + case 8: // comment out.push('\n'); @@ -16125,19 +17657,27 @@ out.push('-->'); break; } // switch on node type + } + indent--; + if (!bOneLine) { out.push('\n'); - for (i = 0; i < indent; i++) { + + for (var _i6 = 0; _i6 < indent; _i6++) { out.push(' '); } } - out.push('</');out.push(elem.nodeName);out.push('>'); + + out.push('</'); + out.push(elem.nodeName); + out.push('>'); } else { out.push('/>'); } } + return out.join(''); }; // end svgToString() @@ -16147,28 +17687,33 @@ * @param {string|false} result Data URL * @returns {undefined} */ + /** - * Converts a given image file to a data URL when possible, then runs a given callback + * Converts a given image file to a data URL when possible, then runs a given callback. * @function module:svgcanvas.SvgCanvas#embedImage * @param {string} src - The path/URL of the image - * @param {module:svgcanvas.ImageEmbeddedCallback} [callback] - Function to run when image data is found * @returns {Promise} Resolves to Data URL (string|false) */ - this.embedImage = function (src, callback) { + + + this.embedImage = function (src) { + // Todo: Remove this Promise in favor of making an async/await `Image.load` utility return new Promise(function (resolve, reject) { + // eslint-disable-line promise/avoid-new // load in the image and once it's loaded, get the dimensions $$9(new Image()).load(function (response, status, xhr) { if (status === 'error') { reject(new Error('Error loading image: ' + xhr.status + ' ' + xhr.statusText)); return; - } - // create a canvas the same size as the raster image + } // create a canvas the same size as the raster image + + var cvs = document.createElement('canvas'); cvs.width = this.width; - cvs.height = this.height; - // load the raster image into the canvas - cvs.getContext('2d').drawImage(this, 0, 0); - // retrieve the data: URL + cvs.height = this.height; // load the raster image into the canvas + + cvs.getContext('2d').drawImage(this, 0, 0); // retrieve the data: URL + try { var urldata = ';svgedit_url=' + encodeURIComponent(src); urldata = cvs.toDataURL().replace(';base64', urldata + ';base64'); @@ -16176,32 +17721,33 @@ } catch (e) { encodableImages[src] = false; } + lastGoodImgUrl = src; - if (callback) { - callback(encodableImages[src]); - } resolve(encodableImages[src]); }).attr('src', src); }); }; - /** - * Sets a given URL to be a "last good image" URL + * Sets a given URL to be a "last good image" URL. * @function module:svgcanvas.SvgCanvas#setGoodImage * @param {string} val * @returns {undefined} */ + + this.setGoodImage = function (val) { lastGoodImgUrl = val; }; - /** - * Does nothing by default, handled by optional widget/extension + * Does nothing by default, handled by optional widget/extension. * @function module:svgcanvas.SvgCanvas#open * @returns {undefined} */ - this.open = function () {}; + + this.open = function () { + /* */ + }; /** * Serializes the current drawing into SVG XML text and passes it to the 'saved' handler. * This function also includes the XML prolog. Clients of the `SvgCanvas` bind their save @@ -16211,40 +17757,47 @@ * @fires module:svgcanvas.SvgCanvas#event:saved * @returns {undefined} */ + + this.save = function (opts) { // remove the selected outline before serializing - clearSelection(); - // Update save options if provided + clearSelection(); // Update save options if provided + if (opts) { $$9.extend(saveOptions, opts); } - saveOptions.apply = true; - // no need for doctype, see https://jwatt.org/svg/authoring/#doctype-declaration + saveOptions.apply = true; // no need for doctype, see https://jwatt.org/svg/authoring/#doctype-declaration + var str = this.svgCanvasToString(); call('saved', str); }; + /** + * @typedef {PlainObject} module:svgcanvas.IssuesAndCodes + * @property {string[]} issueCodes The locale-independent code names + * @property {string[]} issues The localized descriptions + */ /** - * Codes only is useful for locale-independent detection + * Codes only is useful for locale-independent detection. + * @returns {module:svgcanvas.IssuesAndCodes} */ + + function getIssues() { // remove the selected outline before serializing - clearSelection(); + clearSelection(); // Check for known CanVG issues - // Check for known CanVG issues var issues = []; - var issueCodes = []; + var issueCodes = []; // Selector and notice - // Selector and notice var issueList = { feGaussianBlur: uiStrings.exportNoBlur, foreignObject: uiStrings.exportNoforeignObject, '[stroke-dasharray]': uiStrings.exportNoDashArray }; - var content = $$9(svgcontent); + var content = $$9(svgcontent); // Add font/text check if Canvas Text API is not implemented - // Add font/text check if Canvas Text API is not implemented if (!('font' in $$9('<canvas>')[0].getContext('2d'))) { issueList.text = uiStrings.exportNoText; } @@ -16255,13 +17808,17 @@ issues.push(descr); } }); - return { issues: issues, issueCodes: issueCodes }; + return { + issues: issues, + issueCodes: issueCodes + }; } - var canvg = void 0; + var canvg; /** * @typedef {"feGaussianBlur"|"foreignObject"|"[stroke-dasharray]"|"text"} module:svgcanvas.IssueCode */ + /** * @typedef {PlainObject} module:svgcanvas.ImageExportedResults * @property {string} datauri Contents as a Data URL @@ -16275,123 +17832,139 @@ * @property {string} exportWindowName A convenience for passing along a `window.name` to target a window on which the export could be added */ - /** - * Function to run when image data is found - * @callback module:svgcanvas.ImageExportedCallback - * @param {module:svgcanvas.ImageExportedResults} obj - * @returns {undefined} - */ /** * Generates a PNG (or JPG, BMP, WEBP) Data URL based on the current image, * then calls "exported" with an object including the string, image - * information, and any issues found + * information, and any issues found. * @function module:svgcanvas.SvgCanvas#rasterExport * @param {"PNG"|"JPEG"|"BMP"|"WEBP"|"ICO"} [imgType="PNG"] * @param {Float} [quality] Between 0 and 1 * @param {string} [exportWindowName] - * @param {module:svgcanvas.ImageExportedCallback} [cb] + * @param {PlainObject} [opts] + * @param {boolean} [opts.avoidEvent] * @fires module:svgcanvas.SvgCanvas#event:exported * @todo Confirm/fix ICO type * @returns {Promise} Resolves to {@link module:svgcanvas.ImageExportedResults} */ - this.rasterExport = function (imgType, quality, exportWindowName, cb) { - var _this = this; - var type = imgType === 'ICO' ? 'BMP' : imgType || 'PNG'; - var mimeType = 'image/' + type.toLowerCase(); + this.rasterExport = + /*#__PURE__*/ + function () { + var _ref5 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee2(imgType, quality, exportWindowName) { + var opts, + type, + mimeType, + _getIssues, + issues, + issueCodes, + svg, + _ref6, + c, + _args2 = arguments; - var _getIssues = getIssues(), - issues = _getIssues.issues, - issueCodes = _getIssues.issueCodes; + return regeneratorRuntime.wrap(function _callee2$(_context2) { + while (1) { + switch (_context2.prev = _context2.next) { + case 0: + opts = _args2.length > 3 && _args2[3] !== undefined ? _args2[3] : {}; + type = imgType === 'ICO' ? 'BMP' : imgType || 'PNG'; + mimeType = 'image/' + type.toLowerCase(); + _getIssues = getIssues(), issues = _getIssues.issues, issueCodes = _getIssues.issueCodes; + svg = this.svgCanvasToString(); - var svg = this.svgCanvasToString(); + if (canvg) { + _context2.next = 10; + break; + } - return new Promise(function () { - var _ref4 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(resolve, reject) { - var _ref5, c, dataURLType, datauri, bloburl, done; + _context2.next = 8; + return importSetGlobal(curConfig.canvgPath + 'canvg.js', { + global: 'canvg' + }); - return regeneratorRuntime.wrap(function _callee2$(_context2) { - while (1) { - switch (_context2.prev = _context2.next) { - case 0: - done = function done() { + case 8: + _ref6 = _context2.sent; + canvg = _ref6.canvg; + + case 10: + if (!$$9('#export_canvas').length) { + $$9('<canvas>', { + id: 'export_canvas' + }).hide().appendTo('body'); + } + + c = $$9('#export_canvas')[0]; + c.width = canvas.contentW; + c.height = canvas.contentH; + _context2.next = 16; + return canvg(c, svg); + + case 16: + return _context2.abrupt("return", new Promise(function (resolve, reject) { + // eslint-disable-line promise/avoid-new + var dataURLType = type.toLowerCase(); + var datauri = quality ? c.toDataURL('image/' + dataURLType, quality) : c.toDataURL('image/' + dataURLType); + var bloburl; + /** + * Called when `bloburl` is available for export. + * @returns {undefined} + */ + + function done() { var obj = { - datauri: datauri, bloburl: bloburl, svg: svg, issues: issues, issueCodes: issueCodes, type: imgType, - mimeType: mimeType, quality: quality, exportWindowName: exportWindowName + datauri: datauri, + bloburl: bloburl, + svg: svg, + issues: issues, + issueCodes: issueCodes, + type: imgType, + mimeType: mimeType, + quality: quality, + exportWindowName: exportWindowName }; - call('exported', obj); - if (cb) { - cb(obj); + + if (!opts.avoidEvent) { + call('exported', obj); } + resolve(obj); - }; - - if (canvg) { - _context2.next = 6; - break; } - _context2.next = 4; - return importSetGlobal(curConfig.canvgPath + 'canvg.js', { - global: 'canvg' - }); - - case 4: - _ref5 = _context2.sent; - canvg = _ref5.canvg; - - case 6: - if (!$$9('#export_canvas').length) { - $$9('<canvas>', { id: 'export_canvas' }).hide().appendTo('body'); - } - c = $$9('#export_canvas')[0]; - - c.width = canvas.contentW; - c.height = canvas.contentH; - - _context2.next = 12; - return canvg(c, svg); - - case 12: - dataURLType = type.toLowerCase(); - datauri = quality ? c.toDataURL('image/' + dataURLType, quality) : c.toDataURL('image/' + dataURLType); - bloburl = void 0; - - if (!c.toBlob) { - _context2.next = 18; - break; + if (c.toBlob) { + c.toBlob(function (blob) { + bloburl = createObjectURL(blob); + done(); + }, mimeType, quality); + return; } - c.toBlob(function (blob) { - bloburl = createObjectURL(blob); - done(); - }, mimeType, quality); - return _context2.abrupt('return'); - - case 18: bloburl = dataURLToObjectURL(datauri); done(); + })); - case 20: - case 'end': - return _context2.stop(); - } + case 17: + case "end": + return _context2.stop(); } - }, _callee2, _this); - })); + } + }, _callee2, this); + })); - return function (_x4, _x5) { - return _ref4.apply(this, arguments); - }; - }()); - }; + return function (_x4, _x5, _x6) { + return _ref5.apply(this, arguments); + }; + }(); /** * @external jsPDF */ + /** * @typedef {undefined|"save"|"arraybuffer"|"blob"|"datauristring"|"dataurlstring"|"dataurlnewwindow"|"datauri"|"dataurl"} external:jsPDF.OutputType * @todo Newer version to add also allows these `outputType` values "bloburi"|"bloburl" which return strings, so document here and for `outputType` of `module:svgcanvas.PDFExportedResults` below if added */ + /** * @typedef {PlainObject} module:svgcanvas.PDFExportedResults * @property {string} svg The SVG PDF output @@ -16411,129 +17984,137 @@ * @property {string} exportWindowName */ - /** - * Function to run when PDF data is found - * @callback module:svgcanvas.PDFExportedCallback - * @param {module:svgcanvas.PDFExportedResults} obj - * @returns {undefined} - */ /** * Generates a PDF based on the current image, then calls "exportedPDF" with - * an object including the string, the data URL, and any issues found + * an object including the string, the data URL, and any issues found. * @function module:svgcanvas.SvgCanvas#exportPDF - * @param {string} exportWindowName Will also be used for the download file name here + * @param {string} [exportWindowName] Will also be used for the download file name here * @param {external:jsPDF.OutputType} [outputType="dataurlstring"] - * @param {module:svgcanvas.PDFExportedCallback} cb * @fires module:svgcanvas.SvgCanvas#event:exportedPDF * @returns {Promise} Resolves to {@link module:svgcanvas.PDFExportedResults} */ - this.exportPDF = function (exportWindowName, outputType, cb) { - var _this2 = this; - var that = this; - return new Promise(function () { - var _ref6 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(resolve, reject) { - var modularVersion, res, orientation, unit, doc, docTitle, _getIssues2, issues, issueCodes, svg, obj; - return regeneratorRuntime.wrap(function _callee3$(_context3) { - while (1) { - switch (_context3.prev = _context3.next) { - case 0: - if (window.jsPDF) { - _context3.next = 6; - break; - } + this.exportPDF = + /*#__PURE__*/ + function () { + var _ref7 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee3(exportWindowName) { + var outputType, + modularVersion, + res, + orientation, + unit, + doc, + docTitle, + _getIssues2, + issues, + issueCodes, + svg, + obj, + _args3 = arguments; - _context3.next = 3; - return importScript([ - // We do not currently have these paths configurable as they are - // currently global-only, so not Rolled-up - 'jspdf/underscore-min.js', 'jspdf/jspdf.min.js']); + return regeneratorRuntime.wrap(function _callee3$(_context3) { + while (1) { + switch (_context3.prev = _context3.next) { + case 0: + outputType = _args3.length > 1 && _args3[1] !== undefined ? _args3[1] : isChrome() ? 'save' : undefined; - case 3: - modularVersion = !('svgEditor' in window) || !window.svgEditor || window.svgEditor.modules !== false; - // Todo: Switch to `import()` when widely supported and available (also allow customization of path) + if (window.jsPDF) { + _context3.next = 7; + break; + } - _context3.next = 6; - return importScript(curConfig.jspdfPath + 'jspdf.plugin.svgToPdf.js', { - type: modularVersion ? 'module' : 'text/javascript' - }); + _context3.next = 4; + return importScript([// We do not currently have these paths configurable as they are + // currently global-only, so not Rolled-up + 'jspdf/underscore-min.js', 'jspdf/jspdf.min.js']); - case 6: - res = getResolution(); - orientation = res.w > res.h ? 'landscape' : 'portrait'; - unit = 'pt'; // curConfig.baseUnit; // We could use baseUnit, but that is presumably not intended for export purposes + case 4: + modularVersion = !('svgEditor' in window) || !window.svgEditor || window.svgEditor.modules !== false; // Todo: Switch to `import()` when widely supported and available (also allow customization of path) - // Todo: Give options to use predefined jsPDF formats like "a4", etc. from pull-down (with option to keep customizable) + _context3.next = 7; + return importScript(curConfig.jspdfPath + 'jspdf.plugin.svgToPdf.js', { + type: modularVersion ? 'module' : 'text/javascript' + }); - doc = jsPDF({ - orientation: orientation, - unit: unit, - format: [res.w, res.h] - // , compressPdf: true - }); - docTitle = getDocumentTitle(); + case 7: + res = getResolution(); + orientation = res.w > res.h ? 'landscape' : 'portrait'; + unit = 'pt'; // curConfig.baseUnit; // We could use baseUnit, but that is presumably not intended for export purposes + // Todo: Give options to use predefined jsPDF formats like "a4", etc. from pull-down (with option to keep customizable) - doc.setProperties({ - title: docTitle /* , - subject: '', - author: '', - keywords: '', - creator: '' */ - }); - _getIssues2 = getIssues(), issues = _getIssues2.issues, issueCodes = _getIssues2.issueCodes; - svg = that.svgCanvasToString(); + doc = jsPDF({ + orientation: orientation, + unit: unit, + format: [res.w, res.h] // , compressPdf: true - doc.addSVG(svg, 0, 0); + }); + docTitle = getDocumentTitle(); + doc.setProperties({ + title: docTitle + /* , + subject: '', + author: '', + keywords: '', + creator: '' */ - // doc.output('save'); // Works to open in a new - // window; todo: configure this and other export - // options to optionally work in this manner as - // opposed to opening a new tab - outputType = outputType || 'dataurlstring'; - obj = { svg: svg, issues: issues, issueCodes: issueCodes, exportWindowName: exportWindowName, outputType: outputType }; + }); + _getIssues2 = getIssues(), issues = _getIssues2.issues, issueCodes = _getIssues2.issueCodes; + svg = this.svgCanvasToString(); + doc.addSVG(svg, 0, 0); // doc.output('save'); // Works to open in a new + // window; todo: configure this and other export + // options to optionally work in this manner as + // opposed to opening a new tab - obj.output = doc.output(outputType, outputType === 'save' ? exportWindowName || 'svg.pdf' : undefined); - if (cb) { - cb(obj); - } - resolve(obj); - call('exportedPDF', obj); + outputType = outputType || 'dataurlstring'; + obj = { + svg: svg, + issues: issues, + issueCodes: issueCodes, + exportWindowName: exportWindowName, + outputType: outputType + }; + obj.output = doc.output(outputType, outputType === 'save' ? exportWindowName || 'svg.pdf' : undefined); + call('exportedPDF', obj); + return _context3.abrupt("return", obj); - case 21: - case 'end': - return _context3.stop(); - } + case 21: + case "end": + return _context3.stop(); } - }, _callee3, _this2); - })); - - return function (_x6, _x7) { - return _ref6.apply(this, arguments); - }; - }()); - }; + } + }, _callee3, this); + })); + return function (_x7) { + return _ref7.apply(this, arguments); + }; + }(); /** * Returns the current drawing as raw SVG XML text. * @function module:svgcanvas.SvgCanvas#getSvgString * @returns {string} The current drawing as raw SVG XML text. */ + + this.getSvgString = function () { saveOptions.apply = false; return this.svgCanvasToString(); }; - /** * This function determines whether to use a nonce in the prefix, when * generating IDs for future documents in SVG-Edit. * If you're controlling SVG-Edit externally, and want randomized IDs, call - * this BEFORE calling svgCanvas.setSvgString + * this BEFORE calling `svgCanvas.setSvgString`. * @function module:svgcanvas.SvgCanvas#randomizeIds * @param {boolean} [enableRandomization] If true, adds a nonce to the prefix. Thus * `svgCanvas.randomizeIds() <==> svgCanvas.randomizeIds(true)` * @returns {undefined} */ + + this.randomizeIds = function (enableRandomization) { if (arguments.length > 0 && enableRandomization === false) { randomizeIds(false, getCurrentDrawing()); @@ -16541,16 +18122,16 @@ randomizeIds(true, getCurrentDrawing()); } }; - /** - * Ensure each element has a unique ID + * Ensure each element has a unique ID. * @function module:svgcanvas.SvgCanvas#uniquifyElems * @param {Element} g - The parent element of the tree to give unique IDs * @returns {undefined} */ + + var uniquifyElems = this.uniquifyElems = function (g) { - var ids = {}; - // TODO: Handle markers and connectors. These are not yet re-identified properly + var ids = {}; // TODO: Handle markers and connectors. These are not yet re-identified properly // as their referring elements do not get remapped. // // <marker id='se_marker_end_svg_7'/> @@ -16558,8 +18139,8 @@ // // Problem #1: if svg_1 gets renamed, we do not update the polyline's se:connector attribute // Problem #2: if the polyline svg_7 gets renamed, we do not update the marker id nor the polyline's marker-end attribute - var refElems = ['filter', 'linearGradient', 'pattern', 'radialGradient', 'symbol', 'textPath', 'use']; + var refElems = ['filter', 'linearGradient', 'pattern', 'radialGradient', 'symbol', 'textPath', 'use']; walkTree(g, function (n) { // if it's an element node if (n.nodeType === 1) { @@ -16568,70 +18149,86 @@ // and we haven't tracked this ID yet if (!(n.id in ids)) { // add this id to our map - ids[n.id] = { elem: null, attrs: [], hrefs: [] }; + ids[n.id] = { + elem: null, + attrs: [], + hrefs: [] + }; } - ids[n.id].elem = n; - } - // now search for all attributes on this element that might refer + ids[n.id].elem = n; + } // now search for all attributes on this element that might refer // to other elements + + $$9.each(refAttrs, function (i, attr) { var attrnode = n.getAttributeNode(attr); + if (attrnode) { // the incoming file has been sanitized, so we should be able to safely just strip off the leading # var url = getUrlFromAttr(attrnode.value), refid = url ? url.substr(1) : null; + if (refid) { if (!(refid in ids)) { // add this id to our map - ids[refid] = { elem: null, attrs: [], hrefs: [] }; + ids[refid] = { + elem: null, + attrs: [], + hrefs: [] + }; } + ids[refid].attrs.push(attrnode); } } - }); + }); // check xlink:href now + + var href = getHref(n); // TODO: what if an <image> or <a> element refers to an element internally? - // check xlink:href now - var href = getHref(n); - // TODO: what if an <image> or <a> element refers to an element internally? if (href && refElems.includes(n.nodeName)) { var refid = href.substr(1); + if (refid) { if (!(refid in ids)) { // add this id to our map - ids[refid] = { elem: null, attrs: [], hrefs: [] }; + ids[refid] = { + elem: null, + attrs: [], + hrefs: [] + }; } + ids[refid].hrefs.push(n); } } } - }); + }); // in ids, we now have a map of ids, elements and attributes, let's re-identify - // in ids, we now have a map of ids, elements and attributes, let's re-identify for (var oldid in ids) { if (!oldid) { continue; } + var elem = ids[oldid].elem; if (elem) { - var newid = getNextId(); + var newid = getNextId(); // assign element its new id - // assign element its new id - elem.id = newid; + elem.id = newid; // remap all url() attributes - // remap all url() attributes var attrs = ids[oldid].attrs; - var j = attrs.length; + while (j--) { var attr = attrs[j]; attr.ownerElement.setAttribute(attr.name, 'url(#' + newid + ')'); - } + } // remap all href attributes + - // remap all href attributes var hreffers = ids[oldid].hrefs; var k = hreffers.length; + while (k--) { var hreffer = hreffers[k]; setHref(hreffer, '#' + newid); @@ -16639,13 +18236,14 @@ } } }; - /** - * Assigns reference data for each use element + * Assigns reference data for each use element. * @function module:svgcanvas.SvgCanvas#setUseData * @param {Element} parent * @returns {undefined} */ + + var setUseData = this.setUseData = function (parent) { var elems = $$9(parent); @@ -16656,24 +18254,29 @@ elems.each(function () { var id = getHref(this).substr(1); var refElem = getElem(id); + if (!refElem) { return; } + $$9(this).data('ref', refElem); + if (refElem.tagName === 'symbol' || refElem.tagName === 'svg') { $$9(this).data('symbol', refElem).data('ref', refElem); } }); }; - /** - * Converts gradients from userSpaceOnUse to objectBoundingBox + * Converts gradients from userSpaceOnUse to objectBoundingBox. * @function module:svgcanvas.SvgCanvas#convertGradients * @param {Element} elem * @returns {undefined} */ + + var convertGradients = this.convertGradients = function (elem) { var elems = $$9(elem).find('linearGradient, radialGradient'); + if (!elems.length && isWebkit()) { // Bug in webkit prevents regular *Gradient selector search elems = $$9(elem).find('*').filter(function () { @@ -16682,33 +18285,33 @@ } elems.each(function () { - var grad = this; + var grad = this; // eslint-disable-line consistent-this + if ($$9(grad).attr('gradientUnits') === 'userSpaceOnUse') { // TODO: Support more than one element with this ref by duplicating parent grad - var _elems = $$9(svgcontent).find('[fill="url(#' + grad.id + ')"],[stroke="url(#' + grad.id + ')"]'); - if (!_elems.length) { + var fillStrokeElems = $$9(svgcontent).find('[fill="url(#' + grad.id + ')"],[stroke="url(#' + grad.id + ')"]'); + + if (!fillStrokeElems.length) { return; - } + } // get object's bounding box - // get object's bounding box - var bb = getBBox(_elems[0]); - // This will occur if the element is inside a <defs> or a <symbol>, + var bb = getBBox(fillStrokeElems[0]); // This will occur if the element is inside a <defs> or a <symbol>, // in which we shouldn't need to convert anyway. + if (!bb) { return; } if (grad.tagName === 'linearGradient') { - var gCoords = $$9(grad).attr(['x1', 'y1', 'x2', 'y2']); + var gCoords = $$9(grad).attr(['x1', 'y1', 'x2', 'y2']); // If has transform, convert - // If has transform, convert var tlist = grad.gradientTransform.baseVal; + if (tlist && tlist.numberOfItems > 0) { var m = transformListToTransform(tlist).matrix; var pt1 = transformPoint(gCoords.x1, gCoords.y1, m); var pt2 = transformPoint(gCoords.x2, gCoords.y2, m); - gCoords.x1 = pt1.x; gCoords.y1 = pt1.y; gCoords.x2 = pt2.x; @@ -16723,8 +18326,7 @@ y2: (gCoords.y2 - bb.y) / bb.height }); grad.removeAttribute('gradientUnits'); - } - // else { + } // else { // Note: radialGradient elements cannot be easily converted // because userSpaceOnUse will keep circular gradients, while // objectBoundingBox will x/y scale the gradient according to @@ -16744,33 +18346,34 @@ // // grad.removeAttribute('gradientUnits'); // } + } }); }; - /** - * Converts selected/given `<use>` or child SVG element to a group + * Converts selected/given `<use>` or child SVG element to a group. * @function module:svgcanvas.SvgCanvas#convertToGroup * @param {Element} elem * @fires module:svgcanvas.SvgCanvas#event:selected * @returns {undefined} */ + + var convertToGroup = this.convertToGroup = function (elem) { if (!elem) { elem = selectedElements[0]; } + var $elem = $$9(elem); var batchCmd = new BatchCommand$1(); - var ts = void 0; + var ts; if ($elem.data('gsvg')) { // Use the gsvg as the new group var svg = elem.firstChild; var pt = $$9(svg).attr(['x', 'y']); - $$9(elem.firstChild.firstChild).unwrap(); $$9(elem).removeData('gsvg'); - var tlist = getTransformList(elem); var xform = svgroot.createSVGTransform(); xform.setTranslate(pt.x, pt.y); @@ -16779,39 +18382,33 @@ call('selected', [elem]); } else if ($elem.data('symbol')) { elem = $elem.data('symbol'); - ts = $elem.attr('transform'); var pos = $elem.attr(['x', 'y']); - var vb = elem.getAttribute('viewBox'); if (vb) { var nums = vb.split(' '); - pos.x -= +nums[0]; - pos.y -= +nums[1]; - } + pos.x -= Number(nums[0]); + pos.y -= Number(nums[1]); + } // Not ideal, but works + - // Not ideal, but works ts += ' translate(' + (pos.x || 0) + ',' + (pos.y || 0) + ')'; + var prev = $elem.prev(); // Remove <use> element - var prev = $elem.prev(); - - // Remove <use> element batchCmd.addSubCommand(new RemoveElementCommand$1($elem[0], $elem[0].nextSibling, $elem[0].parentNode)); - $elem.remove(); + $elem.remove(); // See if other elements reference this symbol - // See if other elements reference this symbol var hasMore = $$9(svgcontent).find('use:data(symbol)').length; - var g = svgdoc.createElementNS(NS.SVG, 'g'); var childs = elem.childNodes; + var i; - var i = void 0; for (i = 0; i < childs.length; i++) { g.append(childs[i].cloneNode(true)); - } + } // Duplicate the gradients for Gecko, since they weren't included in the <symbol> + - // Duplicate the gradients for Gecko, since they weren't included in the <symbol> if (isGecko()) { var dupeGrads = $$9(findDefs()).children('linearGradient,radialGradient,pattern').clone(); $$9(g).append(dupeGrads); @@ -16822,17 +18419,14 @@ } var parent = elem.parentNode; + uniquifyElems(g); // Put the dupe gradients back into <defs> (after uniquifying them) - uniquifyElems(g); - - // Put the dupe gradients back into <defs> (after uniquifying them) if (isGecko()) { $$9(findDefs()).append($$9(g).find('linearGradient,radialGradient,pattern')); - } + } // now give the g itself a new id + - // now give the g itself a new id g.id = getNextId(); - prev.after(g); if (parent) { @@ -16840,10 +18434,10 @@ // remove symbol/svg element var _elem = elem, nextSibling = _elem.nextSibling; - elem.remove(); batchCmd.addSubCommand(new RemoveElementCommand$1(elem, nextSibling, parent)); } + batchCmd.addSubCommand(new InsertElementCommand$1(g)); } @@ -16853,38 +18447,35 @@ convertGradients(findDefs()); } else { convertGradients(g); - } - - // recalculate dimensions on the top-level children so that unnecessary transforms + } // recalculate dimensions on the top-level children so that unnecessary transforms // are removed + + walkTreePost(g, function (n) { try { recalculateDimensions(n); } catch (e) { - console.log(e); + console.log(e); // eslint-disable-line no-console } - }); + }); // Give ID for any visible element missing one - // Give ID for any visible element missing one $$9(g).find(visElems).each(function () { if (!this.id) { this.id = getNextId(); } }); - selectOnly([g]); - var cm = pushGroupProperties(g, true); + if (cm) { batchCmd.addSubCommand(cm); } addCommandToHistory(batchCmd); } else { - console.log('Unexpected element to ungroup:', elem); + console.log('Unexpected element to ungroup:', elem); // eslint-disable-line no-console } }; - /** * This function sets the current drawing as the input SVG XML. * @function module:svgcanvas.SvgCanvas#setSvgString @@ -16898,27 +18489,26 @@ * @returns {boolean} This function returns `false` if the set was * unsuccessful, `true` otherwise. */ + + this.setSvgString = function (xmlString, preventUndo) { try { // convert string into XML document var newDoc = text2xml(xmlString); + if (newDoc.firstElementChild && newDoc.firstElementChild.namespaceURI !== NS.SVG) { return false; } this.prepareSvg(newDoc); + var batchCmd = new BatchCommand$1('Change Source'); // remove old svg document - var batchCmd = new BatchCommand$1('Change Source'); - - // remove old svg document var _svgcontent = svgcontent, nextSibling = _svgcontent.nextSibling; - var oldzoom = svgroot.removeChild(svgcontent); - batchCmd.addSubCommand(new RemoveElementCommand$1(oldzoom, nextSibling, svgroot)); - - // set new svg document + batchCmd.addSubCommand(new RemoveElementCommand$1(oldzoom, nextSibling, svgroot)); // set new svg document // If DOM3 adoptNode() available, use it. Otherwise fall back to DOM2 importNode() + if (svgdoc.adoptNode) { svgcontent = svgdoc.adoptNode(newDoc.documentElement); } else { @@ -16927,82 +18517,77 @@ svgroot.append(svgcontent); var content = $$9(svgcontent); + canvas.current_drawing_ = new Drawing(svgcontent, idprefix); // retrieve or set the nonce - canvas.current_drawing_ = new Drawing(svgcontent, idprefix); - - // retrieve or set the nonce var nonce = getCurrentDrawing().getNonce(); + if (nonce) { call('setnonce', nonce); } else { call('unsetnonce'); - } + } // change image href vals if possible + - // change image href vals if possible content.find('image').each(function () { - var image = this; + var image = this; // eslint-disable-line consistent-this + preventClickDefault(image); var val = getHref(this); + if (val) { if (val.startsWith('data:')) { // Check if an SVG-edit data URI var m = val.match(/svgedit_url=(.*?);/); + if (m) { var url = decodeURIComponent(m[1]); $$9(new Image()).load(function () { image.setAttributeNS(NS.XLINK, 'xlink:href', url); }).attr('src', url); } - } - // Add to encodableImages if it loads + } // Add to encodableImages if it loads + + canvas.embedImage(val); } - }); + }); // Wrap child SVGs in group elements - // Wrap child SVGs in group elements content.find('svg').each(function () { // Skip if it's in a <defs> if ($$9(this).closest('defs').length) { return; } - uniquifyElems(this); + uniquifyElems(this); // Check if it already has a gsvg group - // Check if it already has a gsvg group var pa = this.parentNode; + if (pa.childNodes.length === 1 && pa.nodeName === 'g') { $$9(pa).data('gsvg', this); pa.id = pa.id || getNextId(); } else { groupSvgElem(this); } - }); + }); // For Firefox: Put all paint elems in defs - // For Firefox: Put all paint elems in defs if (isGecko()) { content.find('linearGradient, radialGradient, pattern').appendTo(findDefs()); - } - - // Set ref element for <use> elements - + } // Set ref element for <use> elements // TODO: This should also be done if the object is re-added through "redo" + + setUseData(content); - convertGradients(content[0]); - var attrs = { id: 'svgcontent', overflow: curConfig.show_outside_canvas ? 'visible' : 'hidden' }; + var percs = false; // determine proper size - var percs = false; - - // determine proper size if (content.attr('viewBox')) { var vb = content.attr('viewBox').split(' '); attrs.width = vb[2]; - attrs.height = vb[3]; - // handle content that doesn't have a viewBox + attrs.height = vb[3]; // handle content that doesn't have a viewBox } else { $$9.each(['width', 'height'], function (i, dim) { // Set to 100 if not given @@ -17015,30 +18600,29 @@ attrs[dim] = convertToNum(dim, val); } }); - } + } // identify layers - // identify layers - identifyLayers(); - // Give ID for any visible layer children missing one + identifyLayers(); // Give ID for any visible layer children missing one + content.children().find(visElems).each(function () { if (!this.id) { this.id = getNextId(); } - }); + }); // Percentage width/height, so let's base it on visible elements - // Percentage width/height, so let's base it on visible elements if (percs) { var bb = getStrokedBBoxDefaultVisible(); attrs.width = bb.width + bb.x; attrs.height = bb.height + bb.y; - } - - // Just in case negative numbers are given or + } // Just in case negative numbers are given or // result from the percs calculation + + if (attrs.width <= 0) { attrs.width = 100; } + if (attrs.height <= 0) { attrs.height = 100; } @@ -17046,31 +18630,27 @@ content.attr(attrs); this.contentW = attrs.width; this.contentH = attrs.height; + batchCmd.addSubCommand(new InsertElementCommand$1(svgcontent)); // update root to the correct size - batchCmd.addSubCommand(new InsertElementCommand$1(svgcontent)); - // update root to the correct size var changes = content.attr(['width', 'height']); - batchCmd.addSubCommand(new ChangeElementCommand$1(svgroot, changes)); + batchCmd.addSubCommand(new ChangeElementCommand$1(svgroot, changes)); // reset zoom - // reset zoom - currentZoom = 1; + currentZoom = 1; // reset transform lists - // reset transform lists resetListMap(); clearSelection(); clearData(); svgroot.append(selectorManager.selectorParentGroup); - if (!preventUndo) addCommandToHistory(batchCmd); call('changed', [svgcontent]); } catch (e) { - console.log(e); + console.log(e); // eslint-disable-line no-console + return false; } return true; }; - /** * This function imports the input SVG XML as a `<symbol>` in the `<defs>`, then adds a * `<use>` to the current layer. @@ -17085,16 +18665,16 @@ * arbitrary transform lists, but makes some assumptions about how the transform list * was obtained */ + + this.importSvgString = function (xmlString) { - var j = void 0, - ts = void 0, - useEl = void 0; + var j, ts, useEl; + try { // Get unique ID var uid = encode64(xmlString.length + xmlString).substr(0, 32); + var useExisting = false; // Look for symbol and make sure symbol exists in image - var useExisting = false; - // Look for symbol and make sure symbol exists in image if (importIds[uid]) { if ($$9(importIds[uid].symbol).parents('#svgroot').length) { useExisting = true; @@ -17102,20 +18682,18 @@ } var batchCmd = new BatchCommand$1('Import Image'); - var symbol = void 0; + var symbol; + if (useExisting) { symbol = importIds[uid].symbol; - ts = importIds[uid].xform; } else { // convert string into XML document var newDoc = text2xml(xmlString); + this.prepareSvg(newDoc); // import new svg document into our document - this.prepareSvg(newDoc); + var svg; // If DOM3 adoptNode() available, use it. Otherwise fall back to DOM2 importNode() - // import new svg document into our document - var svg = void 0; - // If DOM3 adoptNode() available, use it. Otherwise fall back to DOM2 importNode() if (svgdoc.adoptNode) { svg = svgdoc.adoptNode(newDoc.documentElement); } else { @@ -17123,31 +18701,28 @@ } uniquifyElems(svg); - var innerw = convertToNum('width', svg.getAttribute('width')), innerh = convertToNum('height', svg.getAttribute('height')), innervb = svg.getAttribute('viewBox'), - - // 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]; - for (j = 0; j < 4; ++j) { - vb[j] = +vb[j]; - } - // TODO: properly handle preserveAspectRatio + for (j = 0; j < 4; ++j) { + vb[j] = Number(vb[j]); + } // TODO: properly handle preserveAspectRatio + + var // canvasw = +svgcontent.getAttribute('width'), - canvash = +svgcontent.getAttribute('height'); - // imported content should be 1/3 of the canvas on its largest dimension + canvash = Number(svgcontent.getAttribute('height')); // imported content should be 1/3 of the canvas on its largest dimension if (innerh > innerw) { ts = 'scale(' + canvash / 3 / vb[3] + ')'; } else { ts = 'scale(' + canvash / 3 / vb[2] + ')'; - } + } // Hack to make recalculateDimensions understand how to scale + - // Hack to make recalculateDimensions understand how to scale ts = 'translate(0) ' + ts + ' translate(0)'; - symbol = svgdoc.createElementNS(NS.SVG, 'symbol'); var defs = findDefs(); @@ -17162,19 +18737,20 @@ var first = svg.firstChild; symbol.append(first); } + var attrs = svg.attributes; + for (var i = 0; i < attrs.length; i++) { var attr = attrs[i]; symbol.setAttribute(attr.nodeName, attr.value); } - symbol.id = getNextId(); - // Store data + symbol.id = getNextId(); // Store data + importIds[uid] = { symbol: symbol, xform: ts }; - findDefs().append(symbol); batchCmd.addSubCommand(new InsertElementCommand$1(symbol)); } @@ -17182,49 +18758,65 @@ useEl = svgdoc.createElementNS(NS.SVG, 'use'); useEl.id = getNextId(); setHref(useEl, '#' + symbol.id); - (currentGroup || getCurrentDrawing().getCurrentLayer()).append(useEl); batchCmd.addSubCommand(new InsertElementCommand$1(useEl)); clearSelection(); - useEl.setAttribute('transform', ts); recalculateDimensions(useEl); $$9(useEl).data('symbol', symbol).data('ref', symbol); - addToSelection([useEl]); - - // TODO: Find way to add this in a recalculateDimensions-parsable way + addToSelection([useEl]); // TODO: Find way to add this in a recalculateDimensions-parsable way // if (vb[0] !== 0 || vb[1] !== 0) { // ts = 'translate(' + (-vb[0]) + ',' + (-vb[1]) + ') ' + ts; // } + addCommandToHistory(batchCmd); call('changed', [svgcontent]); } catch (e) { - console.log(e); + console.log(e); // eslint-disable-line no-console + return null; - } + } // we want to return the element so we can automatically select it + - // we want to return the element so we can automatically select it return useEl; - }; - - // Could deprecate, but besides external uses, their usage makes clear that + }; // Could deprecate, but besides external uses, their usage makes clear that // canvas is a dependency for all of these - ['identifyLayers', 'createLayer', 'cloneLayer', 'deleteCurrentLayer', 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', 'setLayerVisibility', 'moveSelectedToLayer', 'mergeLayer', 'mergeAllLayers', 'leaveContext', 'setContext'].forEach(function (prop) { - canvas[prop] = draw[prop]; + + + var dr = { + identifyLayers: identifyLayers, + createLayer: createLayer, + cloneLayer: cloneLayer, + deleteCurrentLayer: deleteCurrentLayer, + setCurrentLayer: setCurrentLayer, + renameCurrentLayer: renameCurrentLayer, + setCurrentLayerPosition: setCurrentLayerPosition, + setLayerVisibility: setLayerVisibility, + moveSelectedToLayer: moveSelectedToLayer, + mergeLayer: mergeLayer, + mergeAllLayers: mergeAllLayers, + leaveContext: leaveContext, + setContext: setContext + }; + Object.entries(dr).forEach(function (_ref8) { + var _ref9 = _slicedToArray(_ref8, 2), + prop = _ref9[0], + propVal = _ref9[1]; + + canvas[prop] = propVal; }); init$3( /** * @implements {module:draw.DrawCanvasInit} */ { - pathActions: pathActions$$1, + pathActions: pathActions$1, getCurrentGroup: function getCurrentGroup() { return currentGroup; }, setCurrentGroup: function setCurrentGroup(cg) { currentGroup = cg; }, - getSelectedElements: getSelectedElements, getSVGContent: getSVGContent, undoMgr: undoMgr, @@ -17233,6 +18825,7 @@ clearSelection: clearSelection, call: call, addCommandToHistory: addCommandToHistory, + /** * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} @@ -17241,7 +18834,6 @@ call('changed', [svgcontent]); } }); - /** * Group: Document functions */ @@ -17252,51 +18844,44 @@ * @fires module:svgcanvas.SvgCanvas#event:cleared * @returns {undefined} */ + this.clear = function () { - pathActions$$1.clear(); + pathActions$1.clear(); + clearSelection(); // clear the svgcontent node - clearSelection(); + canvas.clearSvgContentElement(); // create new document - // clear the svgcontent node - canvas.clearSvgContentElement(); + canvas.current_drawing_ = new Drawing(svgcontent); // create empty first layer - // create new document - canvas.current_drawing_ = new Drawing(svgcontent); + canvas.createLayer('Layer 1'); // clear the undo stack - // create empty first layer - canvas.createLayer('Layer 1'); + canvas.undoMgr.resetUndoStack(); // reset the selector manager - // clear the undo stack - canvas.undoMgr.resetUndoStack(); + selectorManager.initGroup(); // reset the rubber band box - // reset the selector manager - selectorManager.initGroup(); - - // reset the rubber band box rubberBox = selectorManager.getRubberBandBox(); - call('cleared'); - }; + }; // Alias function - // Alias function - this.linkControlPoints = pathActions$$1.linkControlPoints; + this.linkControlPoints = pathActions$1.linkControlPoints; /** * @function module:svgcanvas.SvgCanvas#getContentElem * @returns {Element} The content DOM element */ + this.getContentElem = function () { return svgcontent; }; - /** * @function module:svgcanvas.SvgCanvas#getRootElem * @returns {SVGSVGElement} The root DOM element */ + + this.getRootElem = function () { return svgroot; }; - /** * @typedef {PlainObject} DimensionsAndZoom * @property {Float} w Width @@ -17308,93 +18893,103 @@ * @function module:svgcanvas.SvgCanvas#getResolution * @returns {DimensionsAndZoom} The current dimensions and zoom level in an object */ + + var getResolution = this.getResolution = function () { // const vb = svgcontent.getAttribute('viewBox').split(' '); // return {w:vb[2], h:vb[3], zoom: currentZoom}; - var w = svgcontent.getAttribute('width') / currentZoom; var h = svgcontent.getAttribute('height') / currentZoom; - return { w: w, h: h, zoom: currentZoom }; }; - /** * @function module:svgcanvas.SvgCanvas#getSnapToGrid * @returns {boolean} The current snap to grid setting */ + + this.getSnapToGrid = function () { return curConfig.gridSnapping; }; - /** * @function module:svgcanvas.SvgCanvas#getVersion * @returns {string} A string which describes the revision number of SvgCanvas. */ + + this.getVersion = function () { return 'svgcanvas.js ($Rev$)'; }; - /** - * Update interface strings with given values + * Update interface strings with given values. * @function module:svgcanvas.SvgCanvas#setUiStrings * @param {module:path.uiStrings} strs - Object with strings (see the [locales API]{@link module:locale.LocaleStrings} and the [tutorial]{@tutorial LocaleDocs}) * @returns {undefined} */ + + this.setUiStrings = function (strs) { Object.assign(uiStrings, strs.notification); + $$9 = jQueryPluginDBox($$9, strs.common); setUiStrings(strs); }; - /** - * Update configuration options with given values + * Update configuration options with given values. * @function module:svgcanvas.SvgCanvas#setConfig * @param {module:SVGEditor.Config} opts - Object with options * @returns {undefined} */ + + this.setConfig = function (opts) { Object.assign(curConfig, opts); }; - /** * @function module:svgcanvas.SvgCanvas#getTitle - * @param {Element} elem - * @returns {string|undefined} the current group/SVG's title contents + * @param {Element} [elem] + * @returns {string|undefined} the current group/SVG's title contents or + * `undefined` if no element is passed nd there are no selected elements. */ + + this.getTitle = function (elem) { elem = elem || selectedElements[0]; + if (!elem) { - return; + return undefined; } + elem = $$9(elem).data('gsvg') || $$9(elem).data('symbol') || elem; var childs = elem.childNodes; + for (var i = 0; i < childs.length; i++) { if (childs[i].nodeName === 'title') { return childs[i].textContent; } } + return ''; }; - /** - * Sets the group/SVG's title content + * Sets the group/SVG's title content. * @function module:svgcanvas.SvgCanvas#setGroupTitle * @param {string} val * @todo Combine this with `setDocumentTitle` * @returns {undefined} */ + + this.setGroupTitle = function (val) { var elem = selectedElements[0]; elem = $$9(elem).data('gsvg') || elem; - var ts = $$9(elem).children('title'); - var batchCmd = new BatchCommand$1('Set Label'); + var title; - var title = void 0; if (!val.length) { // Remove title element var tsNextSibling = ts.nextSibling; @@ -17403,7 +18998,9 @@ } else if (ts.length) { // Change title contents title = ts[0]; - batchCmd.addSubCommand(new ChangeElementCommand$1(title, { '#text': title.textContent })); + batchCmd.addSubCommand(new ChangeElementCommand$1(title, { + '#text': title.textContent + })); title.textContent = val; } else { // Add title element @@ -17415,27 +19012,28 @@ addCommandToHistory(batchCmd); }; - /** * @function module:svgcanvas.SvgCanvas#getDocumentTitle * @returns {string|undefined} The current document title or an empty string if not found */ + + var getDocumentTitle = this.getDocumentTitle = function () { return canvas.getTitle(svgcontent); }; - /** * Adds/updates a title element for the document with the given name. - * This is an undoable action + * This is an undoable action. * @function module:svgcanvas.SvgCanvas#setDocumentTitle * @param {string} newTitle - String with the new title * @returns {undefined} */ + + this.setDocumentTitle = function (newTitle) { var childs = svgcontent.childNodes; var docTitle = false, oldTitle = ''; - var batchCmd = new BatchCommand$1('Change Image Title'); for (var i = 0; i < childs.length; i++) { @@ -17445,10 +19043,10 @@ break; } } + if (!docTitle) { docTitle = svgdoc.createElementNS(NS.SVG, 'title'); - svgcontent.insertBefore(docTitle, svgcontent.firstChild); - // svgcontent.firstChild.before(docTitle); // Ok to replace above with this? + svgcontent.insertBefore(docTitle, svgcontent.firstChild); // svgcontent.firstChild.before(docTitle); // Ok to replace above with this? } if (newTitle.length) { @@ -17457,39 +19055,44 @@ // No title given, so element is not necessary docTitle.remove(); } - batchCmd.addSubCommand(new ChangeElementCommand$1(docTitle, { '#text': oldTitle })); + + batchCmd.addSubCommand(new ChangeElementCommand$1(docTitle, { + '#text': oldTitle + })); addCommandToHistory(batchCmd); }; - /** - * Returns the editor's namespace URL, optionally adding it to the root element + * Returns the editor's namespace URL, optionally adding it to the root element. * @function module:svgcanvas.SvgCanvas#getEditorNS * @param {boolean} [add] - Indicates whether or not to add the namespace value * @returns {string} The editor's namespace URL */ + + this.getEditorNS = function (add) { if (add) { svgcontent.setAttribute('xmlns:se', NS.SE); } + return NS.SE; }; - /** - * Changes the document's dimensions to the given size + * Changes the document's dimensions to the given size. * @function module:svgcanvas.SvgCanvas#setResolution * @param {Float|"fit"} x - Number with the width of the new dimensions in user units. - * Can also be the string "fit" to indicate "fit to content" + * Can also be the string "fit" to indicate "fit to content". * @param {Float} y - Number with the height of the new dimensions in user units. * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {boolean} Indicates if resolution change was successful. * It will fail on "fit to content" option with no content to fit to. */ + + this.setResolution = function (x, y) { var res = getResolution(); var w = res.w, h = res.h; - - var batchCmd = void 0; + var batchCmd; if (x === 'fit') { // Get bounding box @@ -17505,17 +19108,16 @@ dx.push(bbox.x * -1); dy.push(bbox.y * -1); }); - var cmd = canvas.moveSelectedElements(dx, dy, true); batchCmd.addSubCommand(cmd); clearSelection(); - x = Math.round(bbox.width); y = Math.round(bbox.height); } else { return false; } } + if (x !== w || y !== h) { if (!batchCmd) { batchCmd = new BatchCommand$1('Change Image Dimensions'); @@ -17523,23 +19125,24 @@ x = convertToNum('width', x); y = convertToNum('height', y); - svgcontent.setAttribute('width', x); svgcontent.setAttribute('height', y); - this.contentW = x; this.contentH = y; - batchCmd.addSubCommand(new ChangeElementCommand$1(svgcontent, { width: w, height: h })); - + batchCmd.addSubCommand(new ChangeElementCommand$1(svgcontent, { + width: w, + height: h + })); svgcontent.setAttribute('viewBox', [0, 0, x / currentZoom, y / currentZoom].join(' ')); - batchCmd.addSubCommand(new ChangeElementCommand$1(svgcontent, { viewBox: ['0 0', w, h].join(' ') })); - + batchCmd.addSubCommand(new ChangeElementCommand$1(svgcontent, { + viewBox: ['0 0', w, h].join(' ') + })); addCommandToHistory(batchCmd); call('changed', [svgcontent]); } + return true; }; - /** * @typedef {module:jQueryAttr.Attributes} module:svgcanvas.ElementPositionInCanvas * @property {Float} x @@ -17551,81 +19154,113 @@ * @returns {module:svgcanvas.ElementPositionInCanvas} An object with `x`, `y` values indicating the svgcontent element's * position in the editor's canvas. */ + + this.getOffset = function () { return $$9(svgcontent).attr(['x', 'y']); }; - /** * @typedef {PlainObject} module:svgcanvas.ZoomAndBBox * @property {Float} zoom * @property {module:utilities.BBoxObject} bbox */ + /** - * Sets the zoom level on the canvas-side based on the given value + * Sets the zoom level on the canvas-side based on the given value. * @function module:svgcanvas.SvgCanvas#setBBoxZoom * @param {"selection"|"canvas"|"content"|"layer"|module:SVGEditor.BBoxObjectWithFactor} val - Bounding box object to zoom to or string indicating zoom option. Note: the object value type is defined in `svg-editor.js` * @param {Integer} editorW - The editor's workarea box's width * @param {Integer} editorH - The editor's workarea box's height * @returns {module:svgcanvas.ZoomAndBBox|undefined} */ + + this.setBBoxZoom = function (val, editorW, editorH) { var spacer = 0.85; - var bb = void 0; + var bb; + var calcZoom = function calcZoom(bb) { + // eslint-disable-line no-shadow if (!bb) { return false; } + var wZoom = Math.round(editorW / bb.width * 100 * spacer) / 100; var hZoom = Math.round(editorH / bb.height * 100 * spacer) / 100; var zoom = Math.min(wZoom, hZoom); canvas.setZoom(zoom); - return { zoom: zoom, bbox: bb }; + return { + zoom: zoom, + bbox: bb + }; }; - if ((typeof val === 'undefined' ? 'undefined' : _typeof(val)) === 'object') { + if (_typeof(val) === 'object') { bb = val; + if (bb.width === 0 || bb.height === 0) { var newzoom = bb.zoom ? bb.zoom : currentZoom * bb.factor; canvas.setZoom(newzoom); - return { zoom: currentZoom, bbox: bb }; + return { + zoom: currentZoom, + bbox: bb + }; } + return calcZoom(bb); } switch (val) { case 'selection': - if (!selectedElements[0]) { - return; - } - var selectedElems = $$9.map(selectedElements, function (n) { - if (n) { - return n; + { + if (!selectedElements[0]) { + return undefined; } - }); - bb = getStrokedBBoxDefaultVisible(selectedElems); - break; + + var selectedElems = $$9.map(selectedElements, function (n) { + if (n) { + return n; + } + + return undefined; + }); + bb = getStrokedBBoxDefaultVisible(selectedElems); + break; + } + case 'canvas': - var res = getResolution(); - spacer = 0.95; - bb = { width: res.w, height: res.h, x: 0, y: 0 }; - break; + { + var res = getResolution(); + spacer = 0.95; + bb = { + width: res.w, + height: res.h, + x: 0, + y: 0 + }; + break; + } + case 'content': bb = getStrokedBBoxDefaultVisible(); break; + case 'layer': bb = getStrokedBBoxDefaultVisible(getVisibleElements(getCurrentDrawing().getCurrentLayer())); break; + default: - return; + return undefined; } + return calcZoom(bb); }; - /** * The zoom level has changed. Supplies the new zoom level as a number (not percentage). * @event module:svgcanvas.SvgCanvas#event:ext-zoomChanged * @type {Float} */ + /** * The bottom panel was updated * @event module:svgcanvas.SvgCanvas#event:ext-toolButtonStateUpdate @@ -17633,6 +19268,7 @@ * @property {boolean} nofill Indicates fill is disabled * @property {boolean} nostroke Indicates stroke is disabled */ + /** * The element selection has changed (elements were added/removed from selection) * @event module:svgcanvas.SvgCanvas#event:ext-selectedChanged @@ -17641,6 +19277,7 @@ * @property {Element|null} selectedElement The single selected element * @property {boolean} multiselected Indicates whether one or more elements were selected */ + /** * Called when part of element is in process of changing, generally on * mousemove actions like rotate, move, etc. @@ -17648,12 +19285,14 @@ * @type {PlainObject} * @property {Element[]} elems Array of transitioning elements */ + /** * One or more elements were changed * @event module:svgcanvas.SvgCanvas#event:ext-elementChanged * @type {PlainObject} * @property {Element[]} elems Array of the affected elements */ + /** * Invoked as soon as the locale is ready * @event module:svgcanvas.SvgCanvas#event:ext-langReady @@ -17662,11 +19301,13 @@ * @property {module:SVGEditor.uiStrings} uiStrings * @property {module:SVGEditor~ImportLocale} importLocale */ + /** * The language was changed. Two-letter code of the new language. * @event module:svgcanvas.SvgCanvas#event:ext-langChanged * @type {string} */ + /** * Means for an extension to add locale data. The two-letter language code. * @event module:svgcanvas.SvgCanvas#event:ext-addLangData @@ -17674,16 +19315,19 @@ * @property {string} lang * @property {module:SVGEditor~ImportLocale} importLocale */ + /** * Called when new image is created * @event module:svgcanvas.SvgCanvas#event:ext-onNewDocument * @type {undefined} */ + /** * Called when sidepanel is resized or toggled * @event module:svgcanvas.SvgCanvas#event:ext-workareaResized * @type {undefined} */ + /** * Called upon addition of the extension, or, if svgicons are set, * after the icons are ready when extension SVG icons have loaded. @@ -17692,12 +19336,14 @@ */ /** - * Sets the zoom to the given level + * Sets the zoom to the given level. * @function module:svgcanvas.SvgCanvas#setZoom * @param {Float} zoomLevel - Float indicating the zoom level to change to * @fires module:svgcanvas.SvgCanvas#event:ext-zoomChanged * @returns {undefined} */ + + this.setZoom = function (zoomLevel) { var res = getResolution(); svgcontent.setAttribute('viewBox', '0 0 ' + res.w / zoomLevel + ' ' + res.h / zoomLevel); @@ -17706,33 +19352,37 @@ if (!elem) { return; } + selectorManager.requestSelector(elem).resize(); }); - pathActions$$1.zoomChange(); - runExtensions('zoomChanged', /** @type {module:svgcanvas.SvgCanvas#event:ext-zoomChanged} */zoomLevel); + pathActions$1.zoomChange(); + runExtensions('zoomChanged', + /** @type {module:svgcanvas.SvgCanvas#event:ext-zoomChanged} */ + zoomLevel); }; - /** * @function module:svgcanvas.SvgCanvas#getMode * @returns {string} The current editor mode string */ + + this.getMode = function () { return currentMode; }; - /** - * Sets the editor's mode to the given string + * Sets the editor's mode to the given string. * @function module:svgcanvas.SvgCanvas#setMode * @param {string} name - String with the new mode to change to * @returns {undefined} */ + + this.setMode = function (name) { - pathActions$$1.clear(true); + pathActions$1.clear(true); textActions.clear(); curProperties = selectedElements[0] && selectedElements[0].nodeName === 'text' ? curText : curShape; currentMode = name; }; - /** * Group: Element Styling */ @@ -17747,12 +19397,13 @@ * @param {string} type * @returns {string|module:svgcanvas.PaintOptions|Float|module:jGraduate~Paint} The current fill/stroke option */ + + this.getColor = function (type) { return curProperties[type]; }; - /** - * Change the current stroke/fill color/gradient value + * Change the current stroke/fill color/gradient value. * @function module:svgcanvas.SvgCanvas#setColor * @param {string} type - String indicating fill or stroke * @param {string} val - The value to set the stroke attribute to @@ -17760,32 +19411,44 @@ * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + this.setColor = function (type, val, preventUndo) { curShape[type] = val; - curProperties[type + '_paint'] = { type: 'solidColor' }; + curProperties[type + '_paint'] = { + type: 'solidColor' + }; var elems = []; + /** + * + * @param {Element} e + * @returns {undefined} + */ + function addNonG(e) { if (e.nodeName !== 'g') { elems.push(e); } } + var i = selectedElements.length; + while (i--) { var elem = selectedElements[i]; + if (elem) { if (elem.tagName === 'g') { walkTree(elem, addNonG); - } else { - if (type === 'fill') { - if (elem.tagName !== 'polyline' && elem.tagName !== 'line') { - elems.push(elem); - } - } else { + } else if (type === 'fill') { + if (elem.tagName !== 'polyline' && elem.tagName !== 'line') { elems.push(elem); } + } else { + elems.push(elem); } } } + if (elems.length > 0) { if (!preventUndo) { changeSelectedAttribute(type, val, elems); @@ -17795,47 +19458,53 @@ } } }; - /** - * Apply the current gradient to selected element's fill or stroke + * Apply the current gradient to selected element's fill or stroke. * @function module:svgcanvas.SvgCanvas#setGradient * @param {"fill"|"stroke"} type - String indicating "fill" or "stroke" to apply to an element * @returns {undefined} */ + + var setGradient = this.setGradient = function (type) { if (!curProperties[type + '_paint'] || curProperties[type + '_paint'].type === 'solidColor') { return; } - var grad = canvas[type + 'Grad']; - // find out if there is a duplicate gradient already in the defs + + var grad = canvas[type + 'Grad']; // find out if there is a duplicate gradient already in the defs + var duplicateGrad = findDuplicateGradient(grad); - var defs = findDefs(); - // no duplicate found, so import gradient into defs + var defs = findDefs(); // no duplicate found, so import gradient into defs + if (!duplicateGrad) { // const origGrad = grad; - grad = defs.appendChild(svgdoc.importNode(grad, true)); - // get next id and set it on the grad + grad = defs.appendChild(svgdoc.importNode(grad, true)); // get next id and set it on the grad + grad.id = getNextId(); } else { // use existing gradient grad = duplicateGrad; } + canvas.setColor(type, 'url(#' + grad.id + ')'); }; - /** - * Check if exact gradient already exists + * Check if exact gradient already exists. * @function module:svgcanvas~findDuplicateGradient * @param {SVGGradientElement} grad - The gradient DOM element to compare to others * @returns {SVGGradientElement} The existing gradient if found, `null` if not */ + + var findDuplicateGradient = function findDuplicateGradient(grad) { var defs = findDefs(); var existingGrads = $$9(defs).find('linearGradient, radialGradient'); var i = existingGrads.length; var radAttrs = ['r', 'cx', 'cy', 'fx', 'fy']; + while (i--) { var og = existingGrads[i]; + if (grad.tagName === 'linearGradient') { if (grad.getAttribute('x1') !== og.getAttribute('x1') || grad.getAttribute('y1') !== og.getAttribute('y1') || grad.getAttribute('x2') !== og.getAttribute('x2') || grad.getAttribute('y2') !== og.getAttribute('y2')) { continue; @@ -17844,23 +19513,22 @@ var _ret = function () { var gradAttrs = $$9(grad).attr(radAttrs); var ogAttrs = $$9(og).attr(radAttrs); - var diff = false; - $$9.each(radAttrs, function (i, attr) { + $$9.each(radAttrs, function (j, attr) { if (gradAttrs[attr] !== ogAttrs[attr]) { diff = true; } }); if (diff) { - return 'continue'; + return "continue"; } }(); - if (_ret === 'continue') continue; - } + if (_ret === "continue") continue; + } // else could be a duplicate, iterate through stops + - // else could be a duplicate, iterate through stops var stops = grad.getElementsByTagNameNS(NS.SVG, 'stop'); var ostops = og.getElementsByTagNameNS(NS.SVG, 'stop'); @@ -17869,6 +19537,7 @@ } var j = stops.length; + while (j--) { var stop = stops[j]; var ostop = ostops[j]; @@ -17883,27 +19552,30 @@ } } // for each gradient in defs + return null; }; - /** - * Set a color/gradient to a fill/stroke + * Set a color/gradient to a fill/stroke. * @function module:svgcanvas.SvgCanvas#setPaint * @param {"fill"|"stroke"} type - String with "fill" or "stroke" * @param {module:jGraduate.jGraduatePaintOptions} paint - The jGraduate paint object to apply * @returns {undefined} */ + + this.setPaint = function (type, paint) { // make a copy var p = new $$9.jGraduate.Paint(paint); - this.setPaintOpacity(type, p.alpha / 100, true); + this.setPaintOpacity(type, p.alpha / 100, true); // now set the current paint object - // now set the current paint object curProperties[type + '_paint'] = p; + switch (p.type) { case 'solidColor': this.setColor(type, p.solidColor !== 'none' ? '#' + p.solidColor : 'none'); break; + case 'linearGradient': case 'radialGradient': canvas[type + 'Grad'] = p[p.type]; @@ -17911,57 +19583,70 @@ break; } }; - /** * @function module:svgcanvas.SvgCanvas#setStrokePaint * @param {module:jGraduate~Paint} paint * @returns {undefined} */ + + this.setStrokePaint = function (paint) { this.setPaint('stroke', paint); }; - /** * @function module:svgcanvas.SvgCanvas#setFillPaint * @param {module:jGraduate~Paint} paint * @returns {undefined} */ + + this.setFillPaint = function (paint) { this.setPaint('fill', paint); }; - /** * @function module:svgcanvas.SvgCanvas#getStrokeWidth * @returns {Float|string} The current stroke-width value */ + + this.getStrokeWidth = function () { return curProperties.stroke_width; }; - /** * Sets the stroke width for the current selected elements. - * When attempting to set a line's width to 0, this changes it to 1 instead + * When attempting to set a line's width to 0, this changes it to 1 instead. * @function module:svgcanvas.SvgCanvas#setStrokeWidth * @param {Float} val - A Float indicating the new stroke width value * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + this.setStrokeWidth = function (val) { if (val === 0 && ['line', 'path'].includes(currentMode)) { canvas.setStrokeWidth(1); return; } - curProperties.stroke_width = val; + curProperties.stroke_width = val; var elems = []; + /** + * + * @param {Element} e + * @returns {undefined} + */ + function addNonG(e) { if (e.nodeName !== 'g') { elems.push(e); } } + var i = selectedElements.length; + while (i--) { var elem = selectedElements[i]; + if (elem) { if (elem.tagName === 'g') { walkTree(elem, addNonG); @@ -17970,27 +19655,30 @@ } } } + if (elems.length > 0) { changeSelectedAttribute('stroke-width', val, elems); call('changed', selectedElements); } }; - /** - * Set the given stroke-related attribute the given value for selected elements + * Set the given stroke-related attribute the given value for selected elements. * @function module:svgcanvas.SvgCanvas#setStrokeAttr * @param {string} attr - String with the attribute name * @param {string|Float} val - String or number with the attribute value * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + this.setStrokeAttr = function (attr, val) { curShape[attr.replace('-', '_')] = val; var elems = []; - var i = selectedElements.length; + while (i--) { var elem = selectedElements[i]; + if (elem) { if (elem.tagName === 'g') { walkTree(elem, function (e) { @@ -18003,12 +19691,12 @@ } } } + if (elems.length > 0) { changeSelectedAttribute(attr, val, elems); call('changed', selectedElements); } }; - /** * @typedef {PlainObject} module:svgcanvas.StyleOptions * @property {string} fill @@ -18026,89 +19714,100 @@ * @function module:svgcanvas.SvgCanvas#getStyle * @returns {module:svgcanvas.StyleOptions} current style options */ + + this.getStyle = function () { return curShape; }; - /** * @function module:svgcanvas.SvgCanvas#getOpacity * @returns {Float} the current opacity */ - this.getOpacity = getOpacity; + + this.getOpacity = getOpacity; /** - * Sets the given opacity to the current selected elements + * Sets the given opacity on the current selected elements. * @function module:svgcanvas.SvgCanvas#setOpacity * @param {string} val * @returns {undefined} */ + this.setOpacity = function (val) { curShape.opacity = val; changeSelectedAttribute('opacity', val); }; - /** * @function module:svgcanvas.SvgCanvas#getFillOpacity * @returns {Float} the current fill opacity */ + + this.getFillOpacity = function () { return curShape.fill_opacity; }; - /** * @function module:svgcanvas.SvgCanvas#getStrokeOpacity * @returns {string} the current stroke opacity */ + + this.getStrokeOpacity = function () { return curShape.stroke_opacity; }; - /** - * Sets the current fill/stroke opacity + * Sets the current fill/stroke opacity. * @function module:svgcanvas.SvgCanvas#setPaintOpacity * @param {string} type - String with "fill" or "stroke" * @param {Float} val - Float with the new opacity value * @param {boolean} preventUndo - Indicates whether or not this should be an undoable action * @returns {undefined} */ + + this.setPaintOpacity = function (type, val, preventUndo) { curShape[type + '_opacity'] = val; + if (!preventUndo) { changeSelectedAttribute(type + '-opacity', val); } else { changeSelectedAttributeNoUndo(type + '-opacity', val); } }; - /** - * Gets the current fill/stroke opacity + * Gets the current fill/stroke opacity. * @function module:svgcanvas.SvgCanvas#getPaintOpacity * @param {"fill"|"stroke"} type - String with "fill" or "stroke" * @returns {Float} Fill/stroke opacity */ + + this.getPaintOpacity = function (type) { return type === 'fill' ? this.getFillOpacity() : this.getStrokeOpacity(); }; - /** - * Gets the `stdDeviation` blur value of the given element + * Gets the `stdDeviation` blur value of the given element. * @function module:svgcanvas.SvgCanvas#getBlur * @param {Element} elem - The element to check the blur value for * @returns {string} stdDeviation blur attribute value */ + + this.getBlur = function (elem) { - var val = 0; - // const elem = selectedElements[0]; + var val = 0; // const elem = selectedElements[0]; if (elem) { var filterUrl = elem.getAttribute('filter'); + if (filterUrl) { var blur = getElem(elem.id + '_blur'); + if (blur) { val = blur.firstChild.getAttribute('stdDeviation'); } } } + return val; }; @@ -18116,18 +19815,19 @@ var curCommand = null; var filter = null; var filterHidden = false; - /** - * Sets the `stdDeviation` blur value on the selected element without being undoable + * Sets the `stdDeviation` blur value on the selected element without being undoable. * @function module:svgcanvas.SvgCanvas#setBlurNoUndo * @param {Float} val - The new `stdDeviation` value * @returns {undefined} */ + canvas.setBlurNoUndo = function (val) { if (!filter) { canvas.setBlur(val); return; } + if (val === 0) { // Don't change the StdDev, as that will hide the element. // Instead, just remove the value for "filter" @@ -18135,18 +19835,26 @@ filterHidden = true; } else { var elem = selectedElements[0]; + if (filterHidden) { changeSelectedAttributeNoUndo('filter', 'url(#' + elem.id + '_blur)'); } + if (isWebkit()) { - console.log('e', elem); + // console.log('e', elem); // eslint-disable-line no-console elem.removeAttribute('filter'); elem.setAttribute('filter', 'url(#' + elem.id + '_blur)'); } + changeSelectedAttributeNoUndo('stdDeviation', val, [filter.firstChild]); canvas.setBlurOffsets(filter, val); } }; + /** + * + * @returns {undefined} + */ + function finishChange() { var bCmd = canvas.undoMgr.finishUndoableChange(); @@ -18155,84 +19863,81 @@ curCommand = null; filter = null; } - /** * Sets the `x`, `y`, `width`, `height` values of the filter element in order to - * make the blur not be clipped. Removes them if not neeeded + * make the blur not be clipped. Removes them if not neeeded. * @function module:svgcanvas.SvgCanvas#setBlurOffsets - * @param {Element} filter - The filter DOM element to update + * @param {Element} filterElem - The filter DOM element to update * @param {Float} stdDev - The standard deviation value on which to base the offset size * @returns {undefined} */ - canvas.setBlurOffsets = function (filter, stdDev) { + + + canvas.setBlurOffsets = function (filterElem, stdDev) { if (stdDev > 3) { // TODO: Create algorithm here where size is based on expected blur - assignAttributes(filter, { + assignAttributes(filterElem, { x: '-50%', y: '-50%', width: '200%', height: '200%' - }, 100); - } else { - // Removing these attributes hides text in Chrome (see Issue 579) - if (!isWebkit()) { - filter.removeAttribute('x'); - filter.removeAttribute('y'); - filter.removeAttribute('width'); - filter.removeAttribute('height'); - } + }, 100); // Removing these attributes hides text in Chrome (see Issue 579) + } else if (!isWebkit()) { + filterElem.removeAttribute('x'); + filterElem.removeAttribute('y'); + filterElem.removeAttribute('width'); + filterElem.removeAttribute('height'); } }; - /** - * Adds/updates the blur filter to the selected element + * Adds/updates the blur filter to the selected element. * @function module:svgcanvas.SvgCanvas#setBlur * @param {Float} val - Float with the new `stdDeviation` blur value * @param {boolean} complete - Whether or not the action should be completed (to add to the undo manager) * @returns {undefined} */ + + canvas.setBlur = function (val, complete) { if (curCommand) { finishChange(); return; - } + } // Looks for associated blur, creates one if not found + - // Looks for associated blur, creates one if not found var elem = selectedElements[0]; var elemId = elem.id; filter = getElem(elemId + '_blur'); - val -= 0; + var batchCmd = new BatchCommand$1(); // Blur found! - var batchCmd = new BatchCommand$1(); - - // Blur found! if (filter) { if (val === 0) { filter = null; } } else { // Not found, so create - var newblur = addSVGElementFromJson({ element: 'feGaussianBlur', + var newblur = addSVGElementFromJson({ + element: 'feGaussianBlur', attr: { in: 'SourceGraphic', stdDeviation: val } }); - - filter = addSVGElementFromJson({ element: 'filter', + filter = addSVGElementFromJson({ + element: 'filter', attr: { id: elemId + '_blur' } }); - filter.append(newblur); findDefs().append(filter); - batchCmd.addSubCommand(new InsertElementCommand$1(filter)); } - var changes = { filter: elem.getAttribute('filter') }; + var changes = { + filter: elem.getAttribute('filter') + }; if (val === 0) { elem.removeAttribute('filter'); @@ -18243,229 +19948,246 @@ changeSelectedAttribute('filter', 'url(#' + elemId + '_blur)'); batchCmd.addSubCommand(new ChangeElementCommand$1(elem, changes)); canvas.setBlurOffsets(filter, val); - curCommand = batchCmd; canvas.undoMgr.beginUndoableChange('stdDeviation', [filter ? filter.firstChild : null]); + if (complete) { canvas.setBlurNoUndo(val); finishChange(); } }; })(); - /** - * Check whether selected element is bold or not + * Check whether selected element is bold or not. * @function module:svgcanvas.SvgCanvas#getBold * @returns {boolean} Indicates whether or not element is bold */ + + this.getBold = function () { // should only have one element selected var selected = selectedElements[0]; - if (selected != null && selected.tagName === 'text' && selectedElements[1] == null) { + + if (!isNullish(selected) && selected.tagName === 'text' && isNullish(selectedElements[1])) { return selected.getAttribute('font-weight') === 'bold'; } + return false; }; - /** - * Make the selected element bold or normal + * Make the selected element bold or normal. * @function module:svgcanvas.SvgCanvas#setBold * @param {boolean} b - Indicates bold (`true`) or normal (`false`) * @returns {undefined} */ + + this.setBold = function (b) { var selected = selectedElements[0]; - if (selected != null && selected.tagName === 'text' && selectedElements[1] == null) { + + if (!isNullish(selected) && selected.tagName === 'text' && isNullish(selectedElements[1])) { changeSelectedAttribute('font-weight', b ? 'bold' : 'normal'); } + if (!selectedElements[0].textContent) { textActions.setCursor(); } }; - /** - * Check whether selected element is italic or not + * Check whether selected element is in italics or not. * @function module:svgcanvas.SvgCanvas#getItalic * @returns {boolean} Indicates whether or not element is italic */ + + this.getItalic = function () { var selected = selectedElements[0]; - if (selected != null && selected.tagName === 'text' && selectedElements[1] == null) { + + if (!isNullish(selected) && selected.tagName === 'text' && isNullish(selectedElements[1])) { return selected.getAttribute('font-style') === 'italic'; } + return false; }; - /** - * Make the selected element italic or normal + * Make the selected element italic or normal. * @function module:svgcanvas.SvgCanvas#setItalic - * @param {boolean} b - Indicates italic (`true`) or normal (`false`) + * @param {boolean} i - Indicates italic (`true`) or normal (`false`) * @returns {undefined} */ + + this.setItalic = function (i) { var selected = selectedElements[0]; - if (selected != null && selected.tagName === 'text' && selectedElements[1] == null) { + + if (!isNullish(selected) && selected.tagName === 'text' && isNullish(selectedElements[1])) { changeSelectedAttribute('font-style', i ? 'italic' : 'normal'); } + if (!selectedElements[0].textContent) { textActions.setCursor(); } }; - /** * @function module:svgcanvas.SvgCanvas#getFontFamily * @returns {string} The current font family */ + + this.getFontFamily = function () { return curText.font_family; }; - /** - * Set the new font family + * Set the new font family. * @function module:svgcanvas.SvgCanvas#setFontFamily * @param {string} val - String with the new font family * @returns {undefined} */ + + this.setFontFamily = function (val) { curText.font_family = val; changeSelectedAttribute('font-family', val); + if (selectedElements[0] && !selectedElements[0].textContent) { textActions.setCursor(); } }; - /** - * Set the new font color + * Set the new font color. * @function module:svgcanvas.SvgCanvas#setFontColor * @param {string} val - String with the new font color * @returns {undefined} */ + + this.setFontColor = function (val) { curText.fill = val; changeSelectedAttribute('fill', val); }; - /** * @function module:svgcanvas.SvgCanvas#getFontColor * @returns {string} The current font color */ + + this.getFontColor = function () { return curText.fill; }; - /** * @function module:svgcanvas.SvgCanvas#getFontSize * @returns {Float} The current font size */ + + this.getFontSize = function () { return curText.font_size; }; - /** - * Applies the given font size to the selected element + * Applies the given font size to the selected element. * @function module:svgcanvas.SvgCanvas#setFontSize * @param {Float} val - Float with the new font size * @returns {undefined} */ + + this.setFontSize = function (val) { curText.font_size = val; changeSelectedAttribute('font-size', val); + if (!selectedElements[0].textContent) { textActions.setCursor(); } }; - /** * @function module:svgcanvas.SvgCanvas#getText * @returns {string} The current text (`textContent`) of the selected element */ + + this.getText = function () { var selected = selectedElements[0]; - if (selected == null) { + + if (isNullish(selected)) { return ''; } + return selected.textContent; }; - /** - * Updates the text element with the given string + * Updates the text element with the given string. * @function module:svgcanvas.SvgCanvas#setTextContent * @param {string} val - String with the new text * @returns {undefined} */ + + this.setTextContent = function (val) { changeSelectedAttribute('#text', val); textActions.init(val); textActions.setCursor(); }; - /** * Sets the new image URL for the selected image element. Updates its size if - * a new URL is given + * a new URL is given. * @function module:svgcanvas.SvgCanvas#setImageURL * @param {string} val - String with the image URL/path * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + this.setImageURL = function (val) { var elem = selectedElements[0]; + if (!elem) { return; } var attrs = $$9(elem).attr(['width', 'height']); var setsize = !attrs.width || !attrs.height; + var curHref = getHref(elem); // Do nothing if no URL change or size change - var curHref = getHref(elem); - - // Do nothing if no URL change or size change - if (curHref !== val) { - setsize = true; - } else if (!setsize) { + if (curHref === val && !setsize) { return; } var batchCmd = new BatchCommand$1('Change Image URL'); - setHref(elem, val); batchCmd.addSubCommand(new ChangeElementCommand$1(elem, { '#href': curHref })); - - if (setsize) { - $$9(new Image()).load(function () { - var changes = $$9(elem).attr(['width', 'height']); - - $$9(elem).attr({ - width: this.width, - height: this.height - }); - - selectorManager.requestSelector(elem).resize(); - - batchCmd.addSubCommand(new ChangeElementCommand$1(elem, changes)); - addCommandToHistory(batchCmd); - call('changed', [elem]); - }).attr('src', val); - } else { + $$9(new Image()).load(function () { + var changes = $$9(elem).attr(['width', 'height']); + $$9(elem).attr({ + width: this.width, + height: this.height + }); + selectorManager.requestSelector(elem).resize(); + batchCmd.addSubCommand(new ChangeElementCommand$1(elem, changes)); addCommandToHistory(batchCmd); - } + call('changed', [elem]); + }).attr('src', val); }; - /** * Sets the new link URL for the selected anchor element. * @function module:svgcanvas.SvgCanvas#setLinkURL * @param {string} val - String with the link URL/path * @returns {undefined} */ + + this.setLinkURL = function (val) { var elem = selectedElements[0]; + if (!elem) { return; } + if (elem.tagName !== 'a') { // See if parent is an anchor var parentsA = $$9(elem).parents('a'); + if (parentsA.length) { elem = parentsA[0]; } else { @@ -18480,56 +20202,60 @@ } var batchCmd = new BatchCommand$1('Change Link URL'); - setHref(elem, val); batchCmd.addSubCommand(new ChangeElementCommand$1(elem, { '#href': curHref })); - addCommandToHistory(batchCmd); }; - /** - * Sets the `rx` and `ry` values to the selected `rect` element to change its corner radius + * Sets the `rx` and `ry` values to the selected `rect` element + * to change its corner radius. * @function module:svgcanvas.SvgCanvas#setRectRadius * @param {string|Float} val - The new radius * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + this.setRectRadius = function (val) { var selected = selectedElements[0]; - if (selected != null && selected.tagName === 'rect') { + + if (!isNullish(selected) && selected.tagName === 'rect') { var r = selected.getAttribute('rx'); + if (r !== String(val)) { selected.setAttribute('rx', val); selected.setAttribute('ry', val); - addCommandToHistory(new ChangeElementCommand$1(selected, { rx: r, ry: r }, 'Radius')); + addCommandToHistory(new ChangeElementCommand$1(selected, { + rx: r, + ry: r + }, 'Radius')); call('changed', [selected]); } } }; - /** - * Wraps the selected element(s) in an anchor element or converts group to one + * Wraps the selected element(s) in an anchor element or converts group to one. * @function module:svgcanvas.SvgCanvas#makeHyperlink * @param {string} url * @returns {undefined} */ - this.makeHyperlink = function (url) { - canvas.groupSelectedElements('a', url); - // TODO: If element is a single "g", convert to "a" + + this.makeHyperlink = function (url) { + canvas.groupSelectedElements('a', url); // TODO: If element is a single "g", convert to "a" // if (selectedElements.length > 1 && selectedElements[1]) { }; - /** * @function module:svgcanvas.SvgCanvas#removeHyperlink * @returns {undefined} */ + + this.removeHyperlink = function () { canvas.ungroupSelectedElement(); }; - /** * Group: Element manipulation */ @@ -18540,12 +20266,13 @@ * @param {Integer} newType - New segment type. See {@link https://www.w3.org/TR/SVG/paths.html#InterfaceSVGPathSeg} for list * @returns {undefined} */ - this.setSegType = function (newType) { - pathActions$$1.setSegType(newType); - }; + + this.setSegType = function (newType) { + pathActions$1.setSegType(newType); + }; /** - * Convert selected element to a path, or get the BBox of an element-as-path + * Convert selected element to a path, or get the BBox of an element-as-path. * @function module:svgcanvas.SvgCanvas#convertToPath * @todo (codedread): Remove the getBBox argument and split this function into two. * @param {Element} elem - The DOM element to be converted @@ -18553,21 +20280,25 @@ * @returns {undefined|DOMRect|false|SVGPathElement|null} If the getBBox flag is true, the resulting path's bounding box object. * Otherwise the resulting path element is returned. */ - this.convertToPath = function (elem, getBBox$$1) { - if (elem == null) { + + + this.convertToPath = function (elem, getBBox) { + if (isNullish(elem)) { var elems = selectedElements; - $$9.each(elems, function (i, elem) { - if (elem) { - canvas.convertToPath(elem); + $$9.each(elems, function (i, el) { + if (el) { + canvas.convertToPath(el); } }); - return; + return undefined; } - if (getBBox$$1) { - return getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions$$1); - } - // TODO: Why is this applying attributes from curShape, then inside utilities.convertToPath it's pulling addition attributes from elem? + + if (getBBox) { + return getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions$1); + } // TODO: Why is this applying attributes from curShape, then inside utilities.convertToPath it's pulling addition attributes from elem? // TODO: If convertToPath is called with one elem, curShape and elem are probably the same; but calling with multiple is a bug or cool feature. + + var attrs = { fill: curShape.fill, 'fill-opacity': curShape.fill_opacity, @@ -18580,9 +20311,8 @@ opacity: curShape.opacity, visibility: 'hidden' }; - return convertToPath(elem, attrs, addSVGElementFromJson, pathActions$$1, clearSelection, addToSelection, history, addCommandToHistory); + return convertToPath(elem, attrs, addSVGElementFromJson, pathActions$1, clearSelection, addToSelection, hstry, addCommandToHistory); }; - /** * This function makes the changes to the elements. It does not add the change * to the history stack. @@ -18591,48 +20321,51 @@ * @param {Element[]} elems - The DOM elements to apply the change to * @returns {undefined} */ + + var changeSelectedAttributeNoUndo = function changeSelectedAttributeNoUndo(attr, newValue, elems) { if (currentMode === 'pathedit') { // Editing node - pathActions$$1.moveNode(attr, newValue); + pathActions$1.moveNode(attr, newValue); } + elems = elems || selectedElements; var i = elems.length; - var noXYElems = ['g', 'polyline', 'path']; - var goodGAttrs = ['transform', 'opacity', 'filter']; + var noXYElems = ['g', 'polyline', 'path']; // const goodGAttrs = ['transform', 'opacity', 'filter']; var _loop = function _loop() { var elem = elems[i]; - if (elem == null) { - return 'continue'; - } - // Set x,y vals on elements that don't have them + if (isNullish(elem)) { + return "continue"; + } // Set x,y vals on elements that don't have them + + if ((attr === 'x' || attr === 'y') && noXYElems.includes(elem.tagName)) { var bbox = getStrokedBBoxDefaultVisible([elem]); var diffX = attr === 'x' ? newValue - bbox.x : 0; var diffY = attr === 'y' ? newValue - bbox.y : 0; canvas.moveSelectedElements(diffX * currentZoom, diffY * currentZoom, true); - return 'continue'; - } + return "continue"; + } // only allow the transform/opacity/filter attribute to change on <g> elements, slightly hacky + // TODO: FIXME: Missing statement body + // if (elem.tagName === 'g' && goodGAttrs.includes(attr)) {} + - // only allow the transform/opacity/filter attribute to change on <g> elements, slightly hacky - // TODO: FIXME: This doesn't seem right. Where's the body of this if statement? - if (elem.tagName === 'g' && goodGAttrs.includes(attr)) ; var oldval = attr === '#text' ? elem.textContent : elem.getAttribute(attr); - if (oldval == null) { + + if (isNullish(oldval)) { oldval = ''; } + if (oldval !== String(newValue)) { if (attr === '#text') { // const oldW = utilsGetBBox(elem).width; - elem.textContent = newValue; + elem.textContent = newValue; // FF bug occurs on on rotated elements - // FF bug occurs on on rotated elements if (/rotate/.test(elem.getAttribute('transform'))) { elem = ffClone(elem); - } - // Hoped to solve the issue of moving text with text-anchor="start", + } // Hoped to solve the issue of moving text with text-anchor="start", // but this doesn't actually fix it. Hopefully on the right track, though. -Fyrd // const box = getBBox(elem), left = box.x, top = box.y, {width, height} = box, // dx = width - oldW, dy = 0; @@ -18646,35 +20379,36 @@ // elem.setAttribute('x', elem.getAttribute('x') - dx); // elem.setAttribute('y', elem.getAttribute('y') - dy); // } + } else if (attr === '#href') { setHref(elem, newValue); } else { elem.setAttribute(attr, newValue); - } - - // Go into "select" mode for text changes + } // Go into "select" mode for text changes // NOTE: Important that this happens AFTER elem.setAttribute() or else attributes like // font-size can get reset to their old value, ultimately by svgEditor.updateContextPanel(), // after calling textActions.toSelectMode() below + + if (currentMode === 'textedit' && attr !== '#text' && elem.textContent.length) { textActions.toSelectMode(elem); - } - - // if (i === 0) { + } // if (i === 0) { // selectedBBoxes[0] = utilsGetBBox(elem); // } - // Use the Firefox ffClone hack for text elements with gradients or // where other text attributes are changed. + + if (isGecko() && elem.nodeName === 'text' && /rotate/.test(elem.getAttribute('transform'))) { if (String(newValue).startsWith('url') || ['font-size', 'font-family', 'x', 'y'].includes(attr) && elem.textContent) { elem = ffClone(elem); } - } - // Timeout needed for Opera & Firefox + } // Timeout needed for Opera & Firefox // codedread: it is now possible for this function to be called with elements // that are not in the selectedElements array, we need to only request a // selector if the element is in that array + + if (selectedElements.includes(elem)) { setTimeout(function () { // Due to element replacement, this element may no longer @@ -18682,21 +20416,25 @@ if (!elem.parentNode) { return; } + selectorManager.requestSelector(elem).resize(); }, 0); - } - // if this element was rotated, and we changed the position of this element + } // if this element was rotated, and we changed the position of this element // we need to update the rotational transform attribute + + var angle = getRotationAngle(elem); + if (angle !== 0 && attr !== 'transform') { var tlist = getTransformList(elem); var n = tlist.numberOfItems; + while (n--) { var xform = tlist.getItem(n); + if (xform.type === 4) { // remove old rotate tlist.removeItem(n); - var box = getBBox(elem); var center = transformPoint(box.x + box.width / 2, box.y + box.height / 2, transformListToTransform(tlist).matrix); var cx = center.x, @@ -18709,15 +20447,16 @@ } } } // if oldValue != newValue + }; while (i--) { var _ret2 = _loop(); - if (_ret2 === 'continue') continue; + if (_ret2 === "continue") continue; } // for each elem - }; + }; /** * Change the given/selected element and add the original value to the history stack. * If you want to change all `selectedElements`, ignore the `elems` argument. @@ -18725,30 +20464,32 @@ * subset to this function in the `elems` argument. * @function module:svgcanvas.SvgCanvas#changeSelectedAttribute * @param {string} attr - String with the attribute name - * @param {string|Float} newValue - String or number with the new attribute value + * @param {string|Float} val - String or number with the new attribute value * @param {Element[]} elems - The DOM elements to apply the change to * @returns {undefined} */ + + var changeSelectedAttribute = this.changeSelectedAttribute = function (attr, val, elems) { elems = elems || selectedElements; - canvas.undoMgr.beginUndoableChange(attr, elems); - // const i = elems.length; + canvas.undoMgr.beginUndoableChange(attr, elems); // const i = elems.length; changeSelectedAttributeNoUndo(attr, val, elems); - var batchCmd = canvas.undoMgr.finishUndoableChange(); + if (!batchCmd.isEmpty()) { addCommandToHistory(batchCmd); } }; - /** * Removes all selected elements from the DOM and adds the change to the - * history stack + * history stack. * @function module:svgcanvas.SvgCanvas#deleteSelectedElements * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + this.deleteSelectedElements = function () { var batchCmd = new BatchCommand$1('Delete Elements'); var len = selectedElements.length; @@ -18756,20 +20497,18 @@ for (var i = 0; i < len; ++i) { var selected = selectedElements[i]; - if (selected == null) { + + if (isNullish(selected)) { break; } var parent = selected.parentNode; - var t = selected; + var t = selected; // this will unselect the element and remove the selectedOutline - // this will unselect the element and remove the selectedOutline - selectorManager.releaseSelector(t); + selectorManager.releaseSelector(t); // Remove the path if present. - // Remove the path if present. - removePath_(t.id); + removePath_(t.id); // Get the parent if it's a single-child anchor - // Get the parent if it's a single-child anchor if (parent.tagName === 'a' && parent.childNodes.length === 1) { t = parent; parent = parent.parentNode; @@ -18777,44 +20516,46 @@ var _t = t, nextSibling = _t.nextSibling; - - var _elem2 = parent.removeChild(t); + var elem = parent.removeChild(t); selectedCopy.push(selected); // for the copy - batchCmd.addSubCommand(new RemoveElementCommand$1(_elem2, nextSibling, parent)); + + batchCmd.addSubCommand(new RemoveElementCommand$1(elem, nextSibling, parent)); } + selectedElements = []; if (!batchCmd.isEmpty()) { addCommandToHistory(batchCmd); } + call('changed', selectedCopy); clearSelection(); }; - /** * Removes all selected elements from the DOM and adds the change to the - * history stack. Remembers removed elements on the clipboard + * history stack. Remembers removed elements on the clipboard. * @function module:svgcanvas.SvgCanvas#cutSelectedElements * @returns {undefined} */ + + this.cutSelectedElements = function () { canvas.copySelectedElements(); canvas.deleteSelectedElements(); }; - /** - * Remembers the current selected elements on the clipboard + * Remembers the current selected elements on the clipboard. * @function module:svgcanvas.SvgCanvas#copySelectedElements * @returns {undefined} */ + + this.copySelectedElements = function () { localStorage.setItem('svgedit_clipboard', JSON.stringify(selectedElements.map(function (x) { return getJsonFromSvgElement(x); }))); - $$9('#cmenu_canvas').enableContextMenuItems('#paste,#paste_in_place'); }; - /** * @function module:svgcanvas.SvgCanvas#pasteElements * @param {"in_place"|"point"|undefined} type @@ -18824,35 +20565,46 @@ * @fires module:svgcanvas.SvgCanvas#event:ext-IDsUpdated * @returns {undefined} */ + + this.pasteElements = function (type, x, y) { var clipb = JSON.parse(localStorage.getItem('svgedit_clipboard')); var len = clipb.length; + if (!len) { return; } var pasted = []; - var batchCmd = new BatchCommand$1('Paste elements'); - // const drawing = getCurrentDrawing(); + var batchCmd = new BatchCommand$1('Paste elements'); // const drawing = getCurrentDrawing(); + /** * @typedef {PlainObject.<string, string>} module:svgcanvas.ChangedIDs */ + /** * @type {module:svgcanvas.ChangedIDs} */ - var changedIDs = {}; - // Recursively replace IDs and record the changes + var changedIDs = {}; // Recursively replace IDs and record the changes + + /** + * + * @param {module:svgcanvas.SVGAsJSON} elem + * @returns {undefined} + */ + function checkIDs(elem) { if (elem.attr && elem.attr.id) { changedIDs[elem.attr.id] = getNextId(); elem.attr.id = changedIDs[elem.attr.id]; } + if (elem.children) elem.children.forEach(checkIDs); } - clipb.forEach(checkIDs); - // Give extensions like the connector extension a chance to reflect new IDs and remove invalid elements + clipb.forEach(checkIDs); // Give extensions like the connector extension a chance to reflect new IDs and remove invalid elements + /** * Triggered when `pasteElements` is called from a paste action (context menu or key) * @event module:svgcanvas.SvgCanvas#event:ext-IDsUpdated @@ -18860,37 +20612,38 @@ * @property {module:svgcanvas.SVGAsJSON[]} elems * @property {module:svgcanvas.ChangedIDs} changes Maps past ID (on attribute) to current ID */ + runExtensions('IDsUpdated', /** @type {module:svgcanvas.SvgCanvas#event:ext-IDsUpdated} */ - { elems: clipb, changes: changedIDs }, true).forEach(function (extChanges) { + { + elems: clipb, + changes: changedIDs + }, true).forEach(function (extChanges) { if (!extChanges || !('remove' in extChanges)) return; - extChanges.remove.forEach(function (removeID) { clipb = clipb.filter(function (clipBoardItem) { return clipBoardItem.attr.id !== removeID; }); }); - }); + }); // Move elements to lastClickPoint - // Move elements to lastClickPoint while (len--) { - var _elem3 = clipb[len]; - if (!_elem3) { + var elem = clipb[len]; + + if (!elem) { continue; } - var copy = addSVGElementFromJson(_elem3); + var copy = addSVGElementFromJson(elem); pasted.push(copy); batchCmd.addSubCommand(new InsertElementCommand$1(copy)); - restoreRefElems(copy); } selectOnly(pasted); if (type !== 'in_place') { - var ctrX = void 0, - ctrY = void 0; + var ctrX, ctrY; if (!type) { ctrX = lastClickPoint.x; @@ -18905,12 +20658,10 @@ cy = ctrY - (bbox.y + bbox.height / 2), dx = [], dy = []; - $$9.each(pasted, function (i, item) { dx.push(cx); dy.push(cy); }); - var cmd = canvas.moveSelectedElements(dx, dy, false); if (cmd) batchCmd.addSubCommand(cmd); } @@ -18918,20 +20669,22 @@ addCommandToHistory(batchCmd); call('changed', pasted); }; - /** - * Wraps all the selected elements in a group (`g`) element + * Wraps all the selected elements in a group (`g`) element. * @function module:svgcanvas.SvgCanvas#groupSelectedElements * @param {"a"|"g"} [type="g"] - type of element to group into, defaults to `<g>` * @param {string} [urlArg] * @returns {undefined} */ + + this.groupSelectedElements = function (type, urlArg) { if (!type) { type = 'g'; } + var cmdStr = ''; - var url = void 0; + var url; switch (type) { case 'a': @@ -18939,7 +20692,9 @@ cmdStr = 'Make hyperlink'; url = urlArg || ''; break; - }default: + } + + default: { type = 'g'; cmdStr = 'Group Elements'; @@ -18947,64 +20702,64 @@ } } - var batchCmd = new BatchCommand$1(cmdStr); + var batchCmd = new BatchCommand$1(cmdStr); // create and insert the group element - // create and insert the group element var g = addSVGElementFromJson({ element: type, attr: { id: getNextId() } }); + if (type === 'a') { setHref(g, url); } - batchCmd.addSubCommand(new InsertElementCommand$1(g)); - // now move all children into the group + batchCmd.addSubCommand(new InsertElementCommand$1(g)); // now move all children into the group + var i = selectedElements.length; + while (i--) { - var _elem4 = selectedElements[i]; - if (_elem4 == null) { + var elem = selectedElements[i]; + + if (isNullish(elem)) { continue; } - if (_elem4.parentNode.tagName === 'a' && _elem4.parentNode.childNodes.length === 1) { - _elem4 = _elem4.parentNode; + if (elem.parentNode.tagName === 'a' && elem.parentNode.childNodes.length === 1) { + elem = elem.parentNode; } - var oldNextSibling = _elem4.nextSibling; - var oldParent = _elem4.parentNode; - g.append(_elem4); - batchCmd.addSubCommand(new MoveElementCommand$1(_elem4, oldNextSibling, oldParent)); + var oldNextSibling = elem.nextSibling; + var oldParent = elem.parentNode; + g.append(elem); + batchCmd.addSubCommand(new MoveElementCommand$1(elem, oldNextSibling, oldParent)); } + if (!batchCmd.isEmpty()) { addCommandToHistory(batchCmd); - } + } // update selection + - // update selection selectOnly([g], true); }; - /** * Pushes all appropriate parent group properties down to its children, then - * removes them from the group + * removes them from the group. * @function module:svgcanvas.SvgCanvas#pushGroupProperties * @param {SVGAElement|SVGGElement} g * @param {boolean} undoable - * @returns {undefined} + * @returns {BatchCommand|undefined} */ + + var pushGroupProperties = this.pushGroupProperties = function (g, undoable) { var children = g.childNodes; var len = children.length; var xform = g.getAttribute('transform'); - var glist = getTransformList(g); var m = transformListToTransform(glist).matrix; - - var batchCmd = new BatchCommand$1('Push group properties'); - - // TODO: get all fill/stroke properties from the group that we are about to destroy + var batchCmd = new BatchCommand$1('Push group properties'); // TODO: get all fill/stroke properties from the group that we are about to destroy // "fill", "fill-opacity", "fill-rule", "stroke", "stroke-dasharray", "stroke-dashoffset", // "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", // "stroke-width" @@ -19012,40 +20767,39 @@ // then set the child's attribute var gangle = getRotationAngle(g); - var gattrs = $$9(g).attr(['filter', 'opacity']); - var gfilter = void 0, - gblur = void 0, - changes = void 0; + var gfilter, gblur, changes; var drawing = getCurrentDrawing(); for (var i = 0; i < len; i++) { - var _elem5 = children[i]; + var elem = children[i]; - if (_elem5.nodeType !== 1) { + if (elem.nodeType !== 1) { continue; } if (gattrs.opacity !== null && gattrs.opacity !== 1) { // const c_opac = elem.getAttribute('opacity') || 1; - var newOpac = Math.round((_elem5.getAttribute('opacity') || 1) * gattrs.opacity * 100) / 100; - changeSelectedAttribute('opacity', newOpac, [_elem5]); + var newOpac = Math.round((elem.getAttribute('opacity') || 1) * gattrs.opacity * 100) / 100; + changeSelectedAttribute('opacity', newOpac, [elem]); } if (gattrs.filter) { - var cblur = this.getBlur(_elem5); + var cblur = this.getBlur(elem); var origCblur = cblur; + if (!gblur) { gblur = this.getBlur(g); } + if (cblur) { // Is this formula correct? cblur = Number(gblur) + Number(cblur); } else if (cblur === 0) { cblur = gblur; - } + } // If child has no current filter, get group's filter or clone it. + - // If child has no current filter, get group's filter or clone it. if (!origCblur) { // Set group's filter to use first child's ID if (!gfilter) { @@ -19056,35 +20810,33 @@ findDefs().append(gfilter); } } else { - gfilter = getRefElem(_elem5.getAttribute('filter')); - } + gfilter = getRefElem(elem.getAttribute('filter')); + } // Change this in future for different filters + - // Change this in future for different filters var suffix = gfilter.firstChild.tagName === 'feGaussianBlur' ? 'blur' : 'filter'; - gfilter.id = _elem5.id + '_' + suffix; - changeSelectedAttribute('filter', 'url(#' + gfilter.id + ')', [_elem5]); + gfilter.id = elem.id + '_' + suffix; + changeSelectedAttribute('filter', 'url(#' + gfilter.id + ')', [elem]); // Update blur value - // Update blur value if (cblur) { changeSelectedAttribute('stdDeviation', cblur, [gfilter.firstChild]); canvas.setBlurOffsets(gfilter, cblur); } } - var chtlist = getTransformList(_elem5); + var chtlist = getTransformList(elem); // Don't process gradient transforms - // Don't process gradient transforms - if (_elem5.tagName.includes('Gradient')) { + if (elem.tagName.includes('Gradient')) { chtlist = null; - } + } // Hopefully not a problem to add this. Necessary for elements like <desc/> + - // Hopefully not a problem to add this. Necessary for elements like <desc/> if (!chtlist) { continue; - } + } // Apparently <defs> can get get a transformlist, but we don't want it to have one! - // Apparently <defs> can get get a transformlist, but we don't want it to have one! - if (_elem5.tagName === 'defs') { + + if (elem.tagName === 'defs') { continue; } @@ -19099,35 +20851,29 @@ // sum of the group and child's rotation angles // - [Tr] is the equivalent translation that this child // undergoes if the group wasn't there - // [Tr] = [Rg] [Rc] [Rc2_inv] - // get group's rotation matrix (Rg) - var rgm = glist.getItem(0).matrix; + var rgm = glist.getItem(0).matrix; // get child's rotation matrix (Rc) - // get child's rotation matrix (Rc) var rcm = svgroot.createSVGMatrix(); - var cangle = getRotationAngle(_elem5); + var cangle = getRotationAngle(elem); + if (cangle) { rcm = chtlist.getItem(0).matrix; - } + } // get child's old center of rotation - // get child's old center of rotation - var cbox = getBBox(_elem5); + + var cbox = getBBox(elem); var ceqm = transformListToTransform(chtlist).matrix; - var coldc = transformPoint(cbox.x + cbox.width / 2, cbox.y + cbox.height / 2, ceqm); + var coldc = transformPoint(cbox.x + cbox.width / 2, cbox.y + cbox.height / 2, ceqm); // sum group and child's angles - // sum group and child's angles - var sangle = gangle + cangle; + var sangle = gangle + cangle; // get child's rotation at the old center (Rc2_inv) - // get child's rotation at the old center (Rc2_inv) var r2 = svgroot.createSVGTransform(); - r2.setRotate(sangle, coldc.x, coldc.y); + r2.setRotate(sangle, coldc.x, coldc.y); // calculate equivalent translate - // calculate equivalent translate - var trm = matrixMultiply(rgm, rcm, r2.matrix.inverse()); + var trm = matrixMultiply(rgm, rcm, r2.matrix.inverse()); // set up tlist - // set up tlist if (cangle) { chtlist.removeItem(0); } @@ -19143,6 +20889,7 @@ if (trm.e || trm.f) { var tr = svgroot.createSVGTransform(); tr.setTranslate(trm.e, trm.f); + if (chtlist.numberOfItems) { chtlist.insertItemBefore(tr, 0); } else { @@ -19153,28 +20900,28 @@ // more complicated than just a rotate // transfer the group's transform down to each child and then // call recalculateDimensions() - var oldxform = _elem5.getAttribute('transform'); + var oldxform = elem.getAttribute('transform'); changes = {}; changes.transform = oldxform || ''; - - var newxform = svgroot.createSVGTransform(); - - // [ gm ] [ chm ] = [ chm ] [ gm' ] + var newxform = svgroot.createSVGTransform(); // [ gm ] [ chm ] = [ chm ] [ gm' ] // [ gm' ] = [ chmInv ] [ gm ] [ chm ] + var chm = transformListToTransform(chtlist).matrix, chmInv = chm.inverse(); var gm = matrixMultiply(chmInv, m, chm); newxform.setMatrix(gm); chtlist.appendItem(newxform); } - var cmd = recalculateDimensions(_elem5); + + var cmd = recalculateDimensions(elem); + if (cmd) { batchCmd.addSubCommand(cmd); } } - } + } // remove transform and make it undo-able + - // remove transform and make it undo-able if (xform) { changes = {}; changes.transform = xform; @@ -19186,24 +20933,30 @@ if (undoable && !batchCmd.isEmpty()) { return batchCmd; } - }; + return undefined; + }; /** * Unwraps all the elements in a selected group (`g`) element. This requires - * significant recalculations to apply group's transforms, etc. to its children + * significant recalculations to apply group's transforms, etc. to its children. * @function module:svgcanvas.SvgCanvas#ungroupSelectedElement * @returns {undefined} */ + + this.ungroupSelectedElement = function () { var g = selectedElements[0]; + if (!g) { return; } + if ($$9(g).data('gsvg') || $$9(g).data('symbol')) { // Is svg, so actually convert to group convertToGroup(g); return; } + if (g.tagName === 'use') { // Somehow doesn't have data set, so retrieve var symbol = getElem(getHref(g).substr(1)); @@ -19211,15 +20964,18 @@ convertToGroup(g); return; } + var parentsA = $$9(g).parents('a'); + if (parentsA.length) { g = parentsA[0]; - } + } // Look for parent "a" + - // Look for parent "a" if (g.tagName === 'g' || g.tagName === 'a') { var batchCmd = new BatchCommand$1('Ungroup Elements'); var cmd = pushGroupProperties(g, true); + if (cmd) { batchCmd.addSubCommand(cmd); } @@ -19227,83 +20983,82 @@ var parent = g.parentNode; var anchor = g.nextSibling; var children = new Array(g.childNodes.length); - var i = 0; + while (g.firstChild) { - var _elem6 = g.firstChild; - var oldNextSibling = _elem6.nextSibling; - var oldParent = _elem6.parentNode; + var elem = g.firstChild; + var oldNextSibling = elem.nextSibling; + var oldParent = elem.parentNode; // Remove child title elements - // Remove child title elements - if (_elem6.tagName === 'title') { - var _elem7 = _elem6, - nextSibling = _elem7.nextSibling; - - batchCmd.addSubCommand(new RemoveElementCommand$1(_elem6, nextSibling, oldParent)); - _elem6.remove(); + if (elem.tagName === 'title') { + var _elem2 = elem, + nextSibling = _elem2.nextSibling; + batchCmd.addSubCommand(new RemoveElementCommand$1(elem, nextSibling, oldParent)); + elem.remove(); continue; } - children[i++] = _elem6 = parent.insertBefore(_elem6, anchor); - batchCmd.addSubCommand(new MoveElementCommand$1(_elem6, oldNextSibling, oldParent)); - } + children[i++] = elem = parent.insertBefore(elem, anchor); + batchCmd.addSubCommand(new MoveElementCommand$1(elem, oldNextSibling, oldParent)); + } // remove the group from the selection - // remove the group from the selection - clearSelection(); - // delete the group element (but make undo-able) + clearSelection(); // delete the group element (but make undo-able) + var gNextSibling = g.nextSibling; g = parent.removeChild(g); batchCmd.addSubCommand(new RemoveElementCommand$1(g, gNextSibling, parent)); if (!batchCmd.isEmpty()) { addCommandToHistory(batchCmd); - } + } // update selection + - // update selection addToSelection(children); } }; - /** * Repositions the selected element to the bottom in the DOM to appear on top of - * other elements + * other elements. * @function module:svgcanvas.SvgCanvas#moveToTopSelectedElement * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + this.moveToTopSelectedElement = function () { var _selectedElements = selectedElements, - _selectedElements2 = slicedToArray(_selectedElements, 1), + _selectedElements2 = _slicedToArray(_selectedElements, 1), selected = _selectedElements2[0]; - if (selected != null) { + if (!isNullish(selected)) { var t = selected; var oldParent = t.parentNode; var oldNextSibling = t.nextSibling; - t = t.parentNode.appendChild(t); - // If the element actually moved position, add the command and fire the changed + t = t.parentNode.appendChild(t); // If the element actually moved position, add the command and fire the changed // event handler. + if (oldNextSibling !== t.nextSibling) { addCommandToHistory(new MoveElementCommand$1(t, oldNextSibling, oldParent, 'top')); call('changed', [t]); } } }; - /** * Repositions the selected element to the top in the DOM to appear under - * other elements + * other elements. * @function module:svgcanvas.SvgCanvas#moveToBottomSelectedElement * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + this.moveToBottomSelectedElement = function () { var _selectedElements3 = selectedElements, - _selectedElements4 = slicedToArray(_selectedElements3, 1), + _selectedElements4 = _slicedToArray(_selectedElements3, 1), selected = _selectedElements4[0]; - if (selected != null) { + if (!isNullish(selected)) { var t = selected; var oldParent = t.parentNode; var oldNextSibling = t.nextSibling; @@ -19311,41 +21066,45 @@ if (firstChild.tagName === 'title') { firstChild = firstChild.nextSibling; - } - // This can probably be removed, as the defs should not ever apppear + } // This can probably be removed, as the defs should not ever apppear // inside a layer group + + if (firstChild.tagName === 'defs') { firstChild = firstChild.nextSibling; } - t = t.parentNode.insertBefore(t, firstChild); - // If the element actually moved position, add the command and fire the changed + + t = t.parentNode.insertBefore(t, firstChild); // If the element actually moved position, add the command and fire the changed // event handler. + if (oldNextSibling !== t.nextSibling) { addCommandToHistory(new MoveElementCommand$1(t, oldNextSibling, oldParent, 'bottom')); call('changed', [t]); } } }; - /** * Moves the select element up or down the stack, based on the visibly - * intersecting elements + * intersecting elements. * @function module:svgcanvas.SvgCanvas#moveUpDownSelected * @param {"Up"|"Down"} dir - String that's either 'Up' or 'Down' * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ + + this.moveUpDownSelected = function (dir) { var selected = selectedElements[0]; + if (!selected) { return; } curBBoxes = []; - var closest = void 0, - foundCur = void 0; - // jQuery sorts this list + var closest, foundCur; // jQuery sorts this list + var list = $$9(getIntersectionList(getStrokedBBoxDefaultVisible([selected]))).toArray(); + if (dir === 'Down') { list.reverse(); } @@ -19355,11 +21114,15 @@ if (this === selected) { foundCur = true; } - return; + + return true; } - closest = this; + + closest = this; // eslint-disable-line consistent-this + return false; }); + if (!closest) { return; } @@ -19367,24 +21130,25 @@ var t = selected; var oldParent = t.parentNode; var oldNextSibling = t.nextSibling; - $$9(closest)[dir === 'Down' ? 'before' : 'after'](t); - // If the element actually moved position, add the command and fire the changed + $$9(closest)[dir === 'Down' ? 'before' : 'after'](t); // If the element actually moved position, add the command and fire the changed // event handler. + if (oldNextSibling !== t.nextSibling) { addCommandToHistory(new MoveElementCommand$1(t, oldNextSibling, oldParent, 'Move ' + dir)); call('changed', [t]); } }; - /** - * Moves selected elements on the X/Y axis + * Moves selected elements on the X/Y axis. * @function module:svgcanvas.SvgCanvas#moveSelectedElements * @param {Float} dx - Float with the distance to move on the x-axis * @param {Float} dy - Float with the distance to move on the y-axis * @param {boolean} undoable - Boolean indicating whether or not the action should be undoable * @fires module:svgcanvas.SvgCanvas#event:changed - * @returns {BatchCommand} Batch command for the move + * @returns {BatchCommand|undefined} Batch command for the move */ + + this.moveSelectedElements = function (dx, dy, undoable) { // if undoable is not sent, default to true // if single values, scale them to the zoom @@ -19392,23 +21156,24 @@ dx /= currentZoom; dy /= currentZoom; } + undoable = undoable || true; var batchCmd = new BatchCommand$1('position'); var i = selectedElements.length; + while (i--) { var selected = selectedElements[i]; - if (selected != null) { + + if (!isNullish(selected)) { // if (i === 0) { // selectedBBoxes[0] = utilsGetBBox(selected); // } // const b = {}; // for (const j in selectedBBoxes[i]) b[j] = selectedBBoxes[i][j]; // selectedBBoxes[i] = b; - var xform = svgroot.createSVGTransform(); - var tlist = getTransformList(selected); + var tlist = getTransformList(selected); // dx and dy could be arrays - // dx and dy could be arrays if (dx.constructor === Array) { // if (i === 0) { // selectedBBoxes[0].x += dx[0]; @@ -19430,6 +21195,7 @@ } var cmd = recalculateDimensions(selected); + if (cmd) { batchCmd.addSubCommand(cmd); } @@ -19437,46 +21203,62 @@ selectorManager.requestSelector(selected).resize(); } } + if (!batchCmd.isEmpty()) { if (undoable) { addCommandToHistory(batchCmd); } + call('changed', selectedElements); return batchCmd; } - }; + return undefined; + }; /** * Create deep DOM copies (clones) of all selected elements and move them slightly - * from their originals + * from their originals. * @function module:svgcanvas.SvgCanvas#cloneSelectedElements * @param {Float} x Float with the distance to move on the x-axis * @param {Float} y Float with the distance to move on the y-axis * @returns {undefined} */ + + this.cloneSelectedElements = function (x, y) { - var i = void 0, - elem = void 0; - var batchCmd = new BatchCommand$1('Clone Elements'); - // find all the elements selected (stop at first null) + var i, elem; + var batchCmd = new BatchCommand$1('Clone Elements'); // find all the elements selected (stop at first null) + var len = selectedElements.length; + /** + * Sorts an array numerically and ascending. + * @param {Element} a + * @param {Element} b + * @returns {Integer} + */ + function sortfunction(a, b) { - return $$9(b).index() - $$9(a).index(); // causes an array to be sorted numerically and ascending + return $$9(b).index() - $$9(a).index(); } + selectedElements.sort(sortfunction); + for (i = 0; i < len; ++i) { elem = selectedElements[i]; - if (elem == null) { + + 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 + + var copiedElements = selectedElements.slice(0, i); - this.clearSelection(true); - // note that we loop in the reverse way because of the way elements are added + this.clearSelection(true); // note that we loop in the reverse way because of the way elements are added // to the selectedElements array (top-first) + var drawing = getCurrentDrawing(); i = copiedElements.length; + while (i--) { // clone each element and replace it within copiedElements elem = copiedElements[i] = drawing.copyElem(copiedElements[i]); @@ -19486,38 +21268,44 @@ if (!batchCmd.isEmpty()) { addToSelection(copiedElements.reverse()); // Need to reverse for correct selection-adding + this.moveSelectedElements(x, y, false); addCommandToHistory(batchCmd); } }; - /** - * Aligns selected elements + * Aligns selected elements. * @function module:svgcanvas.SvgCanvas#alignSelectedElements * @param {string} type - String with single character indicating the alignment type * @param {"selected"|"largest"|"smallest"|"page"} relativeTo * @returns {undefined} */ + + this.alignSelectedElements = function (type, relativeTo) { var bboxes = []; // angles = []; + var len = selectedElements.length; + if (!len) { return; } + var minx = Number.MAX_VALUE, maxx = Number.MIN_VALUE, miny = Number.MAX_VALUE, maxy = Number.MIN_VALUE; var curwidth = Number.MIN_VALUE, curheight = Number.MIN_VALUE; + for (var i = 0; i < len; ++i) { - if (selectedElements[i] == null) { + if (isNullish(selectedElements[i])) { break; } - var _elem8 = selectedElements[i]; - bboxes[i] = getStrokedBBoxDefaultVisible([_elem8]); - // now bbox is axis-aligned and handles rotation + var elem = selectedElements[i]; + bboxes[i] = getStrokedBBoxDefaultVisible([elem]); // now bbox is axis-aligned and handles rotation + switch (relativeTo) { case 'smallest': if ((type === 'l' || type === 'c' || type === 'r') && (curwidth === Number.MIN_VALUE || curwidth > bboxes[i].width) || (type === 't' || type === 'm' || type === 'b') && (curheight === Number.MIN_VALUE || curheight > bboxes[i].height)) { @@ -19528,7 +21316,9 @@ curwidth = bboxes[i].width; curheight = bboxes[i].height; } + break; + case 'largest': if ((type === 'l' || type === 'c' || type === 'r') && (curwidth === Number.MIN_VALUE || curwidth < bboxes[i].width) || (type === 't' || type === 'm' || type === 'b') && (curheight === Number.MIN_VALUE || curheight < bboxes[i].height)) { minx = bboxes[i].x; @@ -19538,25 +21328,32 @@ curwidth = bboxes[i].width; curheight = bboxes[i].height; } + break; + default: // 'selected' if (bboxes[i].x < minx) { minx = bboxes[i].x; } + if (bboxes[i].y < miny) { miny = bboxes[i].y; } + if (bboxes[i].x + bboxes[i].width > maxx) { maxx = bboxes[i].x + bboxes[i].width; } + if (bboxes[i].y + bboxes[i].height > maxy) { maxy = bboxes[i].y + bboxes[i].height; } + break; } } // loop for each element to find the bbox and adjust min/max + if (relativeTo === 'page') { minx = 0; miny = 0; @@ -19566,44 +21363,52 @@ var dx = new Array(len); var dy = new Array(len); - for (var _i2 = 0; _i2 < len; ++_i2) { - if (selectedElements[_i2] == null) { + + for (var _i7 = 0; _i7 < len; ++_i7) { + if (isNullish(selectedElements[_i7])) { break; - } - // const elem = selectedElements[i]; - var bbox = bboxes[_i2]; - dx[_i2] = 0; - dy[_i2] = 0; + } // const elem = selectedElements[i]; + + + var bbox = bboxes[_i7]; + dx[_i7] = 0; + dy[_i7] = 0; + switch (type) { case 'l': // left (horizontal) - dx[_i2] = minx - bbox.x; + dx[_i7] = minx - bbox.x; break; + case 'c': // center (horizontal) - dx[_i2] = (minx + maxx) / 2 - (bbox.x + bbox.width / 2); + dx[_i7] = (minx + maxx) / 2 - (bbox.x + bbox.width / 2); break; + case 'r': // right (horizontal) - dx[_i2] = maxx - (bbox.x + bbox.width); + dx[_i7] = maxx - (bbox.x + bbox.width); break; + case 't': // top (vertical) - dy[_i2] = miny - bbox.y; + dy[_i7] = miny - bbox.y; break; + case 'm': // middle (vertical) - dy[_i2] = (miny + maxy) / 2 - (bbox.y + bbox.height / 2); + dy[_i7] = (miny + maxy) / 2 - (bbox.y + bbox.height / 2); break; + case 'b': // bottom (vertical) - dy[_i2] = maxy - (bbox.y + bbox.height); + dy[_i7] = maxy - (bbox.y + bbox.height); break; } } + this.moveSelectedElements(dx, dy); }; - /** * Group: Additional editor tools */ @@ -19612,13 +21417,15 @@ * @name module:svgcanvas.SvgCanvas#contentW * @type {Float} */ + + this.contentW = getResolution().w; /** * @name module:svgcanvas.SvgCanvas#contentH * @type {Float} */ - this.contentH = getResolution().h; + this.contentH = getResolution().h; /** * @typedef {PlainObject} module:svgcanvas.CanvasInfo * @property {Float} x - The canvas' new x coordinate @@ -19630,22 +21437,22 @@ */ /** - * Updates the editor canvas width/height/position after a zoom has occurred + * Updates the editor canvas width/height/position after a zoom has occurred. * @function module:svgcanvas.SvgCanvas#updateCanvas * @param {Float} w - Float with the new width * @param {Float} h - Float with the new height * @fires module:svgcanvas.SvgCanvas#event:ext-canvasUpdated * @returns {module:svgcanvas.CanvasInfo} */ + this.updateCanvas = function (w, h) { svgroot.setAttribute('width', w); svgroot.setAttribute('height', h); var bg = $$9('#canvasBackground')[0]; var oldX = svgcontent.getAttribute('x'); var oldY = svgcontent.getAttribute('y'); - var x = w / 2 - this.contentW * currentZoom / 2; - var y = h / 2 - this.contentH * currentZoom / 2; - + var x = (w - this.contentW * currentZoom) / 2; + var y = (h - this.contentH * currentZoom) / 2; assignAttributes(svgcontent, { width: this.contentW * currentZoom, height: this.contentH * currentZoom, @@ -19653,15 +21460,14 @@ y: y, viewBox: '0 0 ' + this.contentW + ' ' + this.contentH }); - assignAttributes(bg, { width: svgcontent.getAttribute('width'), height: svgcontent.getAttribute('height'), x: x, y: y }); - var bgImg = getElem('background_image'); + if (bgImg) { assignAttributes(bgImg, { width: '100%', @@ -19681,26 +21487,43 @@ * @property {Integer} d_x * @property {Integer} d_y */ + runExtensions('canvasUpdated', /** * @type {module:svgcanvas.SvgCanvas#event:ext-canvasUpdated} */ - { new_x: x, new_y: y, old_x: oldX, old_y: oldY, d_x: x - oldX, d_y: y - oldY }); - return { x: x, y: y, old_x: oldX, old_y: oldY, d_x: x - oldX, d_y: y - oldY }; + { + new_x: x, + new_y: y, + old_x: oldX, + old_y: oldY, + d_x: x - oldX, + d_y: y - oldY + }); + return { + x: x, + y: y, + old_x: oldX, + old_y: oldY, + d_x: x - oldX, + d_y: y - oldY + }; }; - /** - * Set the background of the editor (NOT the actual document) + * Set the background of the editor (NOT the actual document). * @function module:svgcanvas.SvgCanvas#setBackground * @param {string} color - String with fill color to apply * @param {string} url - URL or path to image to use * @returns {undefined} */ + + this.setBackground = function (color, url) { var bg = getElem('canvasBackground'); var border = $$9(bg).find('rect')[0]; var bgImg = getElem('background_image'); border.setAttribute('fill', color); + if (url) { if (!bgImg) { bgImg = svgdoc.createElementNS(NS.SVG, 'image'); @@ -19712,52 +21535,59 @@ style: 'pointer-events:none' }); } + setHref(bgImg, url); bg.append(bgImg); } else if (bgImg) { bgImg.remove(); } }; - /** - * Select the next/previous element within the current layer + * Select the next/previous element within the current layer. * @function module:svgcanvas.SvgCanvas#cycleElement * @param {boolean} next - true = next and false = previous element * @fires module:svgcanvas.SvgCanvas#event:selected * @returns {undefined} */ + + this.cycleElement = function (next) { - var num = void 0; + var num; var curElem = selectedElements[0]; var elem = false; var allElems = getVisibleElements(currentGroup || getCurrentDrawing().getCurrentLayer()); + if (!allElems.length) { return; } - if (curElem == null) { + + if (isNullish(curElem)) { num = next ? allElems.length - 1 : 0; elem = allElems[num]; } else { var i = allElems.length; + while (i--) { if (allElems[i] === curElem) { num = next ? i - 1 : i + 1; + if (num >= allElems.length) { num = 0; } else if (num < 0) { num = allElems.length - 1; } + elem = allElems[num]; break; } } } + selectOnly([elem], true); call('selected', selectedElements); }; this.clear(); - /** * @interface module:svgcanvas.PrivateMethods * @type {PlainObject} @@ -19765,6 +21595,7 @@ * @property {module:history.HistoryCommand} BatchCommand * @property {module:history.HistoryCommand} ChangeElementCommand * @property {module:utilities.decode64} decode64 + * @property {module:utilities.dropXMLInteralSubset} dropXMLInteralSubset * @property {module:utilities.encode64} encode64 * @property {module:svgcanvas~ffClone} ffClone * @property {module:svgcanvas~findDuplicateGradient} findDuplicateGradient @@ -19786,6 +21617,7 @@ * @property {module:math.transformPoint} transformPoint * @property {module:utilities.walkTree} walkTree */ + /** * @deprecated getPrivateMethods * Since all methods are/should be public somehow, this function should be removed; @@ -19798,12 +21630,14 @@ * @function module:svgcanvas.SvgCanvas#getPrivateMethods * @returns {module:svgcanvas.PrivateMethods} */ + this.getPrivateMethods = function () { var obj = { addCommandToHistory: addCommandToHistory, BatchCommand: BatchCommand$1, ChangeElementCommand: ChangeElementCommand$1, decode64: decode64, + dropXMLInteralSubset: dropXMLInteralSubset, encode64: encode64, ffClone: ffClone, findDefs: findDefs, @@ -19834,6 +21668,7 @@ ; // End class // Todo: Update: https://github.com/jeresig/jquery.hotkeys + /* * jQuery Hotkeys Plugin * Copyright 2010, John Resig @@ -19847,42 +21682,146 @@ * Original idea by: * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/ */ + // We *do* want to allow the escape key within textareas (and possibly tab too), so add the condition `n.which !== 27` + function jQueryPluginJSHotkeys (b) { + b.hotkeys = { + version: "0.8", + specialKeys: { + 8: "backspace", + 9: "tab", + 13: "return", + 16: "shift", + 17: "ctrl", + 18: "alt", + 19: "pause", + 20: "capslock", + 27: "esc", + 32: "space", + 33: "pageup", + 34: "pagedown", + 35: "end", + 36: "home", + 37: "left", + 38: "up", + 39: "right", + 40: "down", + 45: "insert", + 46: "del", + 96: "0", + 97: "1", + 98: "2", + 99: "3", + 100: "4", + 101: "5", + 102: "6", + 103: "7", + 104: "8", + 105: "9", + 106: "*", + 107: "+", + 109: "-", + 110: ".", + 111: "/", + 112: "f1", + 113: "f2", + 114: "f3", + 115: "f4", + 116: "f5", + 117: "f6", + 118: "f7", + 119: "f8", + 120: "f9", + 121: "f10", + 122: "f11", + 123: "f12", + 144: "numlock", + 145: "scroll", + 191: "/", + 224: "meta", + 219: "[", + 221: "]" + }, + shiftNums: { + "`": "~", + "1": "!", + "2": "@", + "3": "#", + "4": "$", + "5": "%", + "6": "^", + "7": "&", + "8": "*", + "9": "(", + "0": ")", + "-": "_", + "=": "+", + ";": ": ", + "'": '"', + ",": "<", + ".": ">", + "/": "?", + "\\": "|" + } + }; - function jqPluginJSHotkeys (b) { - b.hotkeys = { version: "0.8", specialKeys: { 8: "backspace", 9: "tab", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause", 20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home", 37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del", 96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7", 104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111: "/", 112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8", 120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 191: "/", 224: "meta", 219: "[", 221: "]" }, shiftNums: { "`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&", "8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": '"', ",": "<", ".": ">", "/": "?", "\\": "|" } };function a(d) { + function a(d) { if (typeof d.data !== "string") { return; - }var c = d.handler, - e = d.data.toLowerCase().split(" ");d.handler = function (n) { - if (this !== n.target && (/textarea|select/i.test(n.target.nodeName) || n.target.type === "text")) { + } + + var c = d.handler, + e = d.data.toLowerCase().split(" "); + + d.handler = function (n) { + if (this !== n.target && n.which !== 27 && (/textarea|select/i.test(n.target.nodeName) || n.target.type === "text")) { return; - }var h = n.type !== "keypress" && b.hotkeys.specialKeys[n.which], + } + + var h = n.type !== "keypress" && b.hotkeys.specialKeys[n.which], o = String.fromCharCode(n.which).toLowerCase(), m = "", - g = {};if (n.altKey && h !== "alt") { + g = {}; + + if (n.altKey && h !== "alt") { m += "alt+"; - }if (n.ctrlKey && h !== "ctrl") { + } + + if (n.ctrlKey && h !== "ctrl") { m += "ctrl+"; - }if (n.metaKey && !n.ctrlKey && h !== "meta") { + } + + if (n.metaKey && !n.ctrlKey && h !== "meta") { m += "meta+"; - }if (n.shiftKey && h !== "shift") { + } + + if (n.shiftKey && h !== "shift") { m += "shift+"; - }if (h) { + } + + if (h) { g[m + h] = true; } else { - g[m + o] = true;g[m + b.hotkeys.shiftNums[o]] = true;if (m === "shift+") { + g[m + o] = true; + g[m + b.hotkeys.shiftNums[o]] = true; + + if (m === "shift+") { g[b.hotkeys.shiftNums[o]] = true; } - }for (var j = 0, f = e.length; j < f; j++) { + } + + for (var j = 0, f = e.length; j < f; j++) { if (g[e[j]]) { return c.apply(this, arguments); } } }; - }b.each(["keydown", "keyup", "keypress"], function () { - b.event.special[this] = { add: a }; - }); + } + b.each(["keydown", "keyup", "keypress"], function () { + b.event.special[this] = { + add: a + }; + }); return b; } @@ -19895,10 +21834,8 @@ * Dual licensed under the MIT and GPL licenses. * http://benalman.com/about/license/ */ - // For sake of modules, added this wrapping export and changed `this` to `window` - function jqPluginBBQ (jQuery) { - + function jQueryPluginBBQ (jQuery) { (function ($, p) { var i, m = Array.prototype.slice, @@ -19922,49 +21859,101 @@ x = /^.*\?|#.*$/g, w = /^.*\#/, h, - C = {};function E(F) { + C = {}; + + function E(F) { return typeof F === "string"; - }function B(G) { - var F = m.call(arguments, 1);return function () { + } + + function B(G) { + var F = m.call(arguments, 1); + return function () { return G.apply(this, F.concat(m.call(arguments))); }; - }function n(F) { + } + + function n(F) { return F.replace(/^[^#]*#?(.*)$/, "$1"); - }function o(F) { + } + + function o(F) { return F.replace(/(?:^[^?#]*\?([^#]*).*$)?.*/, "$1"); - }function f(H, M, F, I, G) { - var O, L, K, N, J;if (I !== i) { - K = F.match(H ? /^([^#]*)\#?(.*)$/ : /^([^#?]*)\??([^#]*)(#?.*)/);J = K[3] || "";if (G === 2 && E(I)) { + } + + function f(H, M, F, I, G) { + var O, L, K, N, J; + + if (I !== i) { + K = F.match(H ? /^([^#]*)\#?(.*)$/ : /^([^#?]*)\??([^#]*)(#?.*)/); + J = K[3] || ""; + + if (G === 2 && E(I)) { L = I.replace(H ? w : x, ""); } else { - N = l(K[2]);I = E(I) ? l[H ? D : A](I) : I;L = G === 2 ? I : G === 1 ? $.extend({}, I, N) : $.extend({}, N, I);L = a(L);if (H) { + N = l(K[2]); + I = E(I) ? l[H ? D : A](I) : I; + L = G === 2 ? I : G === 1 ? $.extend({}, I, N) : $.extend({}, N, I); + L = a(L); + + if (H) { L = L.replace(h, r); } - }O = K[1] + (H ? "#" : L || !K[1] ? "?" : "") + L + J; + } + + O = K[1] + (H ? "#" : L || !K[1] ? "?" : "") + L + J; } else { O = M(F !== i ? F : p[g][k]); - }return O; - }a[A] = B(f, 0, o);a[D] = c = B(f, 1, n);c.noEscape = function (G) { - G = G || "";var F = $.map(G.split(""), encodeURIComponent);h = new RegExp(F.join("|"), "g"); - };c.noEscape(",/");$.deparam = l = function l(I, F) { + } + + return O; + } + + a[A] = B(f, 0, o); + a[D] = c = B(f, 1, n); + + c.noEscape = function (G) { + G = G || ""; + var F = $.map(G.split(""), encodeURIComponent); + h = new RegExp(F.join("|"), "g"); + }; + + c.noEscape(",/"); + + $.deparam = l = function l(I, F) { var H = {}, - G = { "true": !0, "false": !1, "null": null };$.each(I.replace(/\+/g, " ").split("&"), function (L, Q) { + G = { + "true": !0, + "false": !1, + "null": null + }; + $.each(I.replace(/\+/g, " ").split("&"), function (L, Q) { var K = Q.split("="), P = r(K[0]), J, O = H, M = 0, R = P.split("]["), - N = R.length - 1;if (/\[/.test(R[0]) && /\]$/.test(R[N])) { - R[N] = R[N].replace(/\]$/, "");R = R.shift().split("[").concat(R);N = R.length - 1; + N = R.length - 1; + + if (/\[/.test(R[0]) && /\]$/.test(R[N])) { + R[N] = R[N].replace(/\]$/, ""); + R = R.shift().split("[").concat(R); + N = R.length - 1; } else { N = 0; - }if (K.length === 2) { - J = r(K[1]);if (F) { + } + + if (K.length === 2) { + J = r(K[1]); + + if (F) { J = J && !isNaN(J) ? +J : J === "undefined" ? i : G[J] !== i ? G[J] : J; - }if (N) { + } + + if (N) { for (; M <= N; M++) { - P = R[M] === "" ? O.length : R[M];O = O[P] = M < N ? O[P] || (R[M + 1] && isNaN(R[M + 1]) ? {} : []) : J; + P = R[M] === "" ? O.length : R[M]; + O = O[P] = M < N ? O[P] || (R[M + 1] && isNaN(R[M + 1]) ? {} : []) : J; } } else { if ($.isArray(H[P])) { @@ -19982,47 +21971,105 @@ H[P] = F ? i : ""; } } - });return H; - };function z(H, F, G) { + }); + return H; + }; + + function z(H, F, G) { if (F === i || typeof F === "boolean") { - G = F;F = a[H ? D : A](); + G = F; + F = a[H ? D : A](); } else { F = E(F) ? F.replace(H ? w : x, "") : F; - }return l(F, G); - }l[A] = B(z, 0);l[D] = v = B(z, 1);$[y] || ($[y] = function (F) { + } + + return l(F, G); + } + + l[A] = B(z, 0); + l[D] = v = B(z, 1); + $[y] || ($[y] = function (F) { return $.extend(C, F); - })({ a: k, base: k, iframe: t, img: t, input: t, form: "action", link: k, script: t });j = $[y];function s(I, G, H, F) { - if (!E(H) && (typeof H === "undefined" ? "undefined" : _typeof(H)) !== "object") { - F = H;H = G;G = i; - }return this.each(function () { + })({ + a: k, + base: k, + iframe: t, + img: t, + input: t, + form: "action", + link: k, + script: t + }); + j = $[y]; + + function s(I, G, H, F) { + if (!E(H) && _typeof(H) !== "object") { + F = H; + H = G; + G = i; + } + + return this.each(function () { var L = $(this), J = G || j()[(this.nodeName || "").toLowerCase()] || "", - K = J && L.attr(J) || "";L.attr(J, a[I](K, H, F)); + K = J && L.attr(J) || ""; + L.attr(J, a[I](K, H, F)); }); - }$.fn[A] = B(s, A);$.fn[D] = B(s, D);b.pushState = q = function q(I, F) { + } + + $.fn[A] = B(s, A); + $.fn[D] = B(s, D); + + b.pushState = q = function q(I, F) { if (E(I) && /^#/.test(I) && F === i) { F = 2; - }var H = I !== i, - G = c(p[g][k], H ? I : {}, H ? F : 2);p[g][k] = G + (/#/.test(G) ? "" : "#"); - };b.getState = u = function u(F, G) { + } + + var H = I !== i, + G = c(p[g][k], H ? I : {}, H ? F : 2); + p[g][k] = G + (/#/.test(G) ? "" : "#"); + }; + + b.getState = u = function u(F, G) { return F === i || typeof F === "boolean" ? v(F) : v(G)[F]; - };b.removeState = function (F) { - var G = {};if (F !== i) { - G = u();$.each($.isArray(F) ? F : arguments, function (I, H) { + }; + + b.removeState = function (F) { + var G = {}; + + if (F !== i) { + G = u(); + $.each($.isArray(F) ? F : arguments, function (I, H) { delete G[H]; }); - }q(G, 2); - };e[d] = $.extend(e[d], { add: function add(F) { - var H;function G(J) { - var I = J[D] = c();J.getState = function (K, L) { + } + + q(G, 2); + }; + + e[d] = $.extend(e[d], { + add: function add(F) { + var H; + + function G(J) { + var I = J[D] = c(); + + J.getState = function (K, L) { return K === i || typeof K === "boolean" ? l(I, K) : l(I, L)[K]; - };H.apply(this, arguments); - }if ($.isFunction(F)) { - H = F;return G; - } else { - H = F.handler;F.handler = G; + }; + + H.apply(this, arguments); } - } }); + + if ($.isFunction(F)) { + H = F; + return G; + } else { + H = F.handler; + F.handler = G; + } + } + }); })(jQuery, window); /* * jQuery hashchange event - v1.2 - 2/11/2010 @@ -20032,6 +22079,8 @@ * Dual licensed under the MIT and GPL licenses. * http://benalman.com/about/license/ */ + + (function ($, i, b) { var j, k = $.event.special, @@ -20041,57 +22090,102 @@ f = $.browser, g = document.documentMode, h = f.msie && (g === b || g < 8), - e = "on" + d in i && !h;function a(m) { - m = m || i[c][l];return m.replace(/^[^#]*#?(.*)$/, "$1"); - }$[d + "Delay"] = 100;k[d] = $.extend(k[d], { setup: function setup() { + e = "on" + d in i && !h; + + function a(m) { + m = m || i[c][l]; + return m.replace(/^[^#]*#?(.*)$/, "$1"); + } + + $[d + "Delay"] = 100; + k[d] = $.extend(k[d], { + setup: function setup() { if (e) { return false; - }$(j.start); - }, teardown: function teardown() { + } + + $(j.start); + }, + teardown: function teardown() { if (e) { return false; - }$(j.stop); - } });j = function () { + } + + $(j.stop); + } + }); + + j = function () { var m = {}, r, n, o, - q;function p() { + q; + + function p() { o = q = function q(s) { return s; - };if (h) { - n = $('<iframe src="javascript:0"/>').hide().insertAfter("body")[0].contentWindow;q = function q() { + }; + + if (h) { + n = $('<iframe src="javascript:0"/>').hide().insertAfter("body")[0].contentWindow; + + q = function q() { return a(n.document[c][l]); - };o = function o(u, s) { + }; + + o = function o(u, s) { if (u !== s) { - var t = n.document;t.open().close();t[c].hash = "#" + u; + var t = n.document; + t.open().close(); + t[c].hash = "#" + u; } - };o(a()); + }; + + o(a()); } - }m.start = function () { + } + + m.start = function () { if (r) { return; - }var t = a();o || p();(function s() { + } + + var t = a(); + o || p(); + + (function s() { var v = a(), - u = q(t);if (v !== t) { - o(t = v, u);$(i).trigger(d); + u = q(t); + + if (v !== t) { + o(t = v, u); + $(i).trigger(d); } else { if (u !== t) { i[c][l] = i[c][l].replace(/#.*/, "") + "#" + u; } - }r = setTimeout(s, $[d + "Delay"]); + } + + r = setTimeout(s, $[d + "Delay"]); })(); - };m.stop = function () { + }; + + m.stop = function () { if (!n) { - r && clearTimeout(r);r = 0; + r && clearTimeout(r); + r = 0; } - };return m; + }; + + return m; }(); })(jQuery, window); return jQuery; } + // Todo: Move to own module (and have it import a modular base64 encoder) /** * SVG Icon Loader 2.0 * @@ -20188,58 +22282,65 @@ /** * @function module:jQuerySVGIcons.jQuerySVGIcons * @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 */ - function jqPluginSVGIcons ($) { - var svgIcons = {}; - var fixIDs = void 0; + function jQueryPluginSVGIcons($) { + var svgIcons = {}; + var fixIDs; + /** + * List of raster images with each + * key being the SVG icon ID to replace, and the value the image file name + * @typedef {PlainObject.<string, string>} external:jQuery.svgIcons.Fallback + */ + /** * @function external:jQuery.svgIcons * @param {string} file The location of a local SVG or SVGz file - * @param {PlainObject} [options] - * @param {Float} [options.w] The icon widths - * @param {Float} [options.h] The icon heights - * @param {PlainObject.<string, string>} [options.fallback] List of raster images with each - key being the SVG icon ID to replace, and the value the image file name - * @param {string} [options.fallback_path] The path to use for all images + * @param {PlainObject} [opts] + * @param {Float} [opts.w] The icon widths + * @param {Float} [opts.h] The icon heights + * @param {external:jQuery.svgIcons.Fallback} [opts.fallback] + * @param {string} [opts.fallback_path] The path to use for all images listed under "fallback" - * @param {boolean} [options.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, rather than include the SVG icon. - * @param {PlainObject.<string, string>} [options.placement] List with selectors for keys and SVG icon ids + * @param {PlainObject.<string, string>} [opts.placement] List with selectors for keys and SVG icon ids as values. This provides a custom method of adding icons. - * @param {PlainObject.<string, module:jQuerySVGIcons.Size>} [options.resize] List with selectors for keys and numbers + * @param {PlainObject.<string, module:jQuerySVGIcons.Size>} [opts.resize] List with selectors for keys and numbers as values. This allows an easy way to resize specific icons. - * @param {module:jQuerySVGIcons.SVGIconsLoadedCallback} [options.callback] A function to call when all icons have been loaded. - * @param {boolean} [options.id_match=true] Automatically attempt to match SVG icon ids with + * @param {module:jQuerySVGIcons.SVGIconsLoadedCallback} [opts.callback] A function to call when all icons have been loaded. + * @param {boolean} [opts.id_match=true] Automatically attempt to match SVG icon ids with corresponding HTML id - * @param {boolean} [options.no_img] Prevent attempting to convert the icon into an `<img>` + * @param {boolean} [opts.no_img] Prevent attempting to convert the icon into an `<img>` element (may be faster, help for browser consistency) - * @param {boolean} [options.svgz] Indicate that the file is an SVGZ file, and thus not to + * @param {boolean} [opts.svgz] Indicate that the file is an SVGZ file, and thus not to parse as XML. SVGZ files add compression benefits, but getting data from them fails in Firefox 2 and older. + * @returns {undefined} */ + $.svgIcons = function (file) { var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - var svgns = 'http://www.w3.org/2000/svg', xlinkns = 'http://www.w3.org/1999/xlink', iconW = opts.w || 24, iconH = opts.h || 24; - var elems = void 0, - svgdoc = void 0, - testImg = void 0, + var elems, + svgdoc, + testImg, iconsMade = false, dataLoaded = false, loadAttempts = 0; - var isOpera = !!window.opera, - - // ua = navigator.userAgent, + var isOpera = Boolean(window.opera), + // ua = navigator.userAgent, // isSafari = (ua.includes('Safari/') && !ua.includes('Chrome/')), dataPre = 'data:image/svg+xml;charset=utf-8;base64,'; + var dataEl; - var dataEl = void 0; if (opts.svgz) { dataEl = $('<object data="' + file + '" type=image/svg+xml>').appendTo('body').hide(); + try { svgdoc = dataEl[0].contentDocument; dataEl.load(getIcons); @@ -20257,6 +22358,7 @@ $(useFallback); return; } + svgdoc = parser.parseFromString(data, 'text/xml'); $(function () { getIcons('ajax'); @@ -20268,42 +22370,53 @@ $(function () { useFallback(); }); - } else { - if (err.responseText) { - svgdoc = parser.parseFromString(err.responseText, 'text/xml'); + } else if (err.responseText) { + svgdoc = parser.parseFromString(err.responseText, 'text/xml'); - if (!svgdoc.childNodes.length) { - $(useFallback); - } - $(function () { - getIcons('ajax'); - }); - } else { + if (!svgdoc.childNodes.length) { $(useFallback); } + + $(function () { + getIcons('ajax'); + }); + } else { + $(useFallback); } } }); } + /** + * + * @param {"ajax"|0|undefined} evt + * @param {boolean} [noWait] + * @returns {undefined} + */ + function getIcons(evt, noWait) { if (evt !== 'ajax') { - if (dataLoaded) return; - // Webkit sometimes says svgdoc is undefined, other times + if (dataLoaded) return; // Webkit sometimes says svgdoc is undefined, other times // it fails to load all nodes. Thus we must make sure the "eof" // element is loaded. + svgdoc = dataEl[0].contentDocument; // Needed again for Webkit + var isReady = svgdoc && svgdoc.getElementById('svg_eof'); + if (!isReady && !(noWait && isReady)) { loadAttempts++; + if (loadAttempts < 50) { setTimeout(getIcons, 20); } else { useFallback(); dataLoaded = true; } + return; } + dataLoaded = true; } @@ -20311,7 +22424,6 @@ if (!opts.no_img) { var testSrc = dataPre + 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNzUiIGhlaWdodD0iMjc1Ij48L3N2Zz4%3D'; - testImg = $(new Image()).attr({ src: testSrc, width: 0, @@ -20328,9 +22440,19 @@ }, 500); } } + /** + * + * @param {external:jQuery} target + * @param {external:jQuery} icon A wrapped `defs` or Image + * @param {string} id SVG icon ID + * @param {string} setID + * @returns {undefined} + */ + function setIcon(target, icon, id, setID) { if (isOpera) icon.css('visibility', 'hidden'); + if (opts.replace) { if (setID) icon.attr('id', id); var cl = target.attr('class'); @@ -20339,6 +22461,7 @@ } else { target.append(icon); } + if (isOpera) { setTimeout(function () { icon.removeAttr('style'); @@ -20346,23 +22469,40 @@ } } - var holder = void 0; + var holder; + /** + * @param {external:jQuery} icon A wrapped `defs` or Image + * @param {string} id SVG icon ID + * @returns {undefined} + */ + function addIcon(icon, id) { if (opts.id_match === undefined || opts.id_match !== false) { setIcon(holder, icon, id, true); } + svgIcons[id] = icon; } + /** + * + * @param {boolean} [toImage] + * @param {external:jQuery.svgIcons.Fallback} [fallback] + * @returns {undefined} + */ - function makeIcons(toImage, fallback) { + + function makeIcons() { + var toImage = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var fallback = arguments.length > 1 ? arguments[1] : undefined; if (iconsMade) return; if (opts.no_img) toImage = false; + var tempHolder; - var tempHolder = void 0; if (toImage) { tempHolder = $(document.createElement('div')); tempHolder.hide().appendTo('body'); } + if (fallback) { var path = opts.fallback_path || ''; $.each(fallback, function (id, imgsrc) { @@ -20374,56 +22514,55 @@ height: iconH, alt: 'icon' }); - addIcon(icon, id); }); } else { var len = elems.length; + for (var i = 0; i < len; i++) { var elem = elems[i]; var id = elem.id; - if (id === 'svg_eof') break; holder = $('#' + id); - var svgroot = document.createElementNS(svgns, 'svg'); - // Per https://www.w3.org/TR/xml-names11/#defaulting, the namespace for + var svgroot = document.createElementNS(svgns, 'svg'); // Per https://www.w3.org/TR/xml-names11/#defaulting, the namespace for // attributes should have no value. - svgroot.setAttributeNS(null, 'viewBox', [0, 0, iconW, iconH].join(' ')); - var svg = elem.getElementsByTagNameNS(svgns, 'svg')[0]; + svgroot.setAttribute('viewBox', [0, 0, iconW, iconH].join(' ')); + var svg = elem.getElementsByTagNameNS(svgns, 'svg')[0]; // Make flexible by converting width/height to viewBox - // Make flexible by converting width/height to viewBox var w = svg.getAttribute('width'); var h = svg.getAttribute('height'); svg.removeAttribute('width'); svg.removeAttribute('height'); - var vb = svg.getAttribute('viewBox'); + if (!vb) { svg.setAttribute('viewBox', [0, 0, w, h].join(' ')); - } + } // Not using jQuery to be a bit faster + - // Not using jQuery to be a bit faster svgroot.setAttribute('xmlns', svgns); svgroot.setAttribute('width', iconW); svgroot.setAttribute('height', iconH); svgroot.setAttribute('xmlns:xlink', xlinkns); - svgroot.setAttribute('class', 'svg_icon'); - - // Without cloning, Firefox will make another GET request. + svgroot.setAttribute('class', 'svg_icon'); // Without cloning, Firefox will make another GET request. // With cloning, causes issue in Opera/Win/Non-EN + if (!isOpera) svg = svg.cloneNode(true); - svgroot.append(svg); - var icon = void 0; + if (toImage) { tempHolder.empty().append(svgroot); var str = dataPre + encode64(unescape(encodeURIComponent(new XMLSerializer().serializeToString(svgroot)))); - icon = $(new Image()).attr({ class: 'svg_icon', src: str }); + icon = $(new Image()).attr({ + class: 'svg_icon', + src: str + }); } else { icon = fixIDs($(svgroot), i); } + addIcon(icon, id); } } @@ -20438,25 +22577,26 @@ }); }); } + if (!fallback) { if (toImage) tempHolder.remove(); if (dataEl) dataEl.remove(); if (testImg) testImg.remove(); } + if (opts.resize) $.resizeSvgIcons(opts.resize); iconsMade = true; - if (opts.callback) opts.callback(svgIcons); } fixIDs = function fixIDs(svgEl, svgNum, force) { var defs = svgEl.find('defs'); if (!defs.length) return svgEl; + var idElems; - var idElems = void 0; if (isOpera) { idElems = defs.find('*').filter(function () { - return !!this.id; + return Boolean(this.id); }); } else { idElems = defs.find('[id]'); @@ -20464,7 +22604,6 @@ var allElems = svgEl[0].getElementsByTagName('*'), len = allElems.length; - idElems.each(function (i) { var id = this.id; /* @@ -20475,11 +22614,8 @@ var newId = 'x' + id + svgNum + i; this.id = newId; - var oldVal = 'url(#' + id + ')'; - var newVal = 'url(#' + newId + ')'; - - // Selector method, possibly faster but fails in Opera / jQuery 1.4.3 + var newVal = 'url(#' + newId + ')'; // Selector method, possibly faster but fails in Opera / jQuery 1.4.3 // svgEl.find('[fill="url(#' + id + ')"]').each(function() { // this.setAttribute('fill', 'url(#' + newId + ')'); // }).end().find('[stroke="url(#' + id + ')"]').each(function() { @@ -20494,12 +22630,15 @@ for (i = 0; i < len; i++) { var elem = allElems[i]; + if (elem.getAttribute('fill') === oldVal) { elem.setAttribute('fill', newVal); } + if (elem.getAttribute('stroke') === oldVal) { elem.setAttribute('stroke', newVal); } + if (elem.getAttribute('filter') === oldVal) { elem.setAttribute('filter', newVal); } @@ -20507,67 +22646,42 @@ }); return svgEl; }; + /** + * @returns {undefined} + */ + function useFallback() { if (file.includes('.svgz')) { var regFile = file.replace('.svgz', '.svg'); + if (window.console) { - console.log('.svgz failed, trying with .svg'); + console.log('.svgz failed, trying with .svg'); // eslint-disable-line no-console } + $.svgIcons(regFile, opts); } else if (opts.fallback) { makeIcons(false, opts.fallback); } } - - function encode64(input) { - // base64 strings are 4/3 larger than the original string - if (window.btoa) return window.btoa(input); - var _keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; - var output = new Array(Math.floor((input.length + 2) / 3) * 4); - - var i = 0, - p = 0; - do { - var chr1 = input.charCodeAt(i++); - var chr2 = input.charCodeAt(i++); - var chr3 = input.charCodeAt(i++); - - var enc1 = chr1 >> 2; - var enc2 = (chr1 & 3) << 4 | chr2 >> 4; - - var enc3 = (chr2 & 15) << 2 | chr3 >> 6; - var 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(''); - } }; - /** * @function external:jQuery.getSvgIcon * @param {string} id * @param {boolean} uniqueClone Whether to clone * @returns {external:jQuery} The icon (optionally cloned) */ + + $.getSvgIcon = function (id, uniqueClone) { var icon = svgIcons[id]; + if (uniqueClone && icon) { icon = fixIDs(icon, 0, true).clone(true); } + return icon; }; - /** * @typedef {GenericArray} module:jQuerySVGIcons.Dimensions * @property {Integer} length 2 @@ -20585,6 +22699,8 @@ * @param {PlainObject.<string, module:jQuerySVGIcons.Size>} obj Object with selectors as keys. The values are sizes. * @returns {undefined} */ + + $.resizeSvgIcons = function (obj) { // FF2 and older don't detect .svg_icon, so we change it detect svg elems instead var changeSel = !$('.svg_icon:first').length; @@ -20592,12 +22708,15 @@ var arr = Array.isArray(size); var w = arr ? size[0] : size, h = arr ? size[1] : size; + if (changeSel) { sel = sel.replace(/\.svg_icon/g, 'svg'); } + $(sel).each(function () { this.setAttribute('width', w); this.setAttribute('height', h); + if (window.opera && window.widget) { this.parentNode.style.width = w + 'px'; this.parentNode.style.height = h + 'px'; @@ -20605,6 +22724,7 @@ }); }); }; + return $; } @@ -20632,13 +22752,13 @@ * The jQuery namespace. * @external jQuery */ + /** * The jQuery plugin namespace. * @namespace {PlainObject} fn * @memberof external:jQuery * @see {@link http://learn.jquery.com/plugins/|jQuery Plugins} */ - var ns = { svg: 'http://www.w3.org/2000/svg', xlink: 'http://www.w3.org/1999/xlink' @@ -20646,26 +22766,34 @@ if (!window.console) { window.console = { - log: function log(str) {}, - dir: function dir(str) {} + log: function log(str) { + /* */ + }, + dir: function dir(str) { + /* */ + } }; } - /** - * Adds {@link external:jQuery.jGraduate.Paint}, {@link external:jQuery.fn.jGraduateDefaults}, {@link external:jQuery.fn.jGraduate} + * Adds {@link external:jQuery.jGraduate.Paint}, + * {@link external:jQuery.fn.jGraduateDefaults}, + * {@link external:jQuery.fn.jGraduate}. * @function module:jGraduate.jGraduate * @param {external:jQuery} $ The jQuery instance to wrap * @returns {external:jQuery} */ - function jqPluginJGraduate ($) { + + + function jQueryPluginJGraduate($) { if (!$.loadingStylesheets) { $.loadingStylesheets = []; } + var stylesheet = 'jgraduate/css/jGraduate.css'; + if (!$.loadingStylesheets.includes(stylesheet)) { $.loadingStylesheets.push(stylesheet); } - /** * @typedef {PlainObject} module:jGraduate.jGraduatePaintOptions * @param {Float} [alpha] @@ -20679,16 +22807,17 @@ * @memberof module:jGraduate~ */ + var Paint = /** * @param {module:jGraduate.jGraduatePaintOptions} [opt] */ function Paint(opt) { - classCallCheck(this, Paint); + _classCallCheck(this, Paint); var options = opt || {}; - this.alpha = isNaN(options.alpha) ? 100 : options.alpha; - // copy paint object + this.alpha = isNaN(options.alpha) ? 100 : options.alpha; // copy paint object + if (options.copy) { /** * @name module:jGraduate~Paint#type @@ -20700,54 +22829,58 @@ * @name module:jGraduate~Paint#alpha * @type {Float} */ + this.alpha = options.copy.alpha; /** * Represents #RRGGBB hex of color * @name module:jGraduate~Paint#solidColor * @type {string} */ + this.solidColor = null; /** * @name module:jGraduate~Paint#linearGradient * @type {SVGLinearGradientElement} */ + this.linearGradient = null; /** * @name module:jGraduate~Paint#radialGradient * @type {SVGRadialGradientElement} */ + this.radialGradient = null; switch (this.type) { case 'none': break; + case 'solidColor': this.solidColor = options.copy.solidColor; break; + case 'linearGradient': this.linearGradient = options.copy.linearGradient.cloneNode(true); break; + case 'radialGradient': this.radialGradient = options.copy.radialGradient.cloneNode(true); break; - } - // create linear gradient paint + } // create linear gradient paint + } else if (options.linearGradient) { this.type = 'linearGradient'; this.solidColor = null; this.radialGradient = null; - this.linearGradient = options.linearGradient.cloneNode(true); - // create linear gradient paint + this.linearGradient = options.linearGradient.cloneNode(true); // create linear gradient paint } else if (options.radialGradient) { this.type = 'radialGradient'; this.solidColor = null; this.linearGradient = null; - this.radialGradient = options.radialGradient.cloneNode(true); - // create solid color paint + this.radialGradient = options.radialGradient.cloneNode(true); // create solid color paint } else if (options.solidColor) { this.type = 'solidColor'; - this.solidColor = options.solidColor; - // create empty paint + this.solidColor = options.solidColor; // create empty paint } else { this.type = 'none'; this.solidColor = null; @@ -20761,27 +22894,32 @@ */ - $.jGraduate = /** @lends external:jQuery.jGraduate */{ + $.jGraduate = + /** @lends external:jQuery.jGraduate */ + { /** * @class external:jQuery.jGraduate.Paint * @see module:jGraduate~Paint */ Paint: Paint - }; - - // JSDoc doesn't show this as belonging to our `module:jGraduate.Options` type, + }; // JSDoc doesn't show this as belonging to our `module:jGraduate.Options` type, // so we use `@see` + /** * @namespace {module:jGraduate.Options} jGraduateDefaults * @memberof external:jQuery.fn */ - $.fn.jGraduateDefaults = /** @lends external:jQuery.fn.jGraduateDefaults */{ + + $.fn.jGraduateDefaults = + /** @lends external:jQuery.fn.jGraduateDefaults */ + { /** * Creates an object with a 'none' color * @type {external:jQuery.jGraduate.Paint} * @see module:jGraduate.Options */ paint: new $.jGraduate.Paint(), + /** * @namespace */ @@ -20792,6 +22930,7 @@ */ pickerTitle: 'Drag markers to pick a paint' }, + /** * @namespace */ @@ -20802,47 +22941,74 @@ */ clientPath: 'images/' }, + /** * @type {string} * @see module:jGraduate.Options */ newstop: 'inverse' // same, inverse, black, white - }; + }; var isGecko = navigator.userAgent.includes('Gecko/'); + /** + * @typedef {PlainObject.<string, string>} module:jGraduate.Attrs + */ + + /** + * @param {SVGElement} elem + * @param {module:jGraduate.Attrs} attrs + * @returns {undefined} + */ function setAttrs(elem, attrs) { if (isGecko) { - for (var aname in attrs) { - elem.setAttribute(aname, attrs[aname]); - } + Object.entries(attrs).forEach(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + aname = _ref2[0], + val = _ref2[1]; + + elem.setAttribute(aname, val); + }); } else { - for (var _aname in attrs) { - var val = attrs[_aname], - prop = elem[_aname]; + Object.entries(attrs).forEach(function (_ref3) { + var _ref4 = _slicedToArray(_ref3, 2), + aname = _ref4[0], + val = _ref4[1]; + + var prop = elem[aname]; + if (prop && prop.constructor === 'SVGLength') { prop.baseVal.value = val; } else { - elem.setAttribute(_aname, val); + elem.setAttribute(aname, val); } - } + }); } } + /** + * @param {string} name + * @param {module:jGraduate.Attrs} attrs + * @param {Element} newparent + * @returns {SVGElement} + */ + function mkElem(name, attrs, newparent) { var elem = document.createElementNS(ns.svg, name); setAttrs(elem, attrs); + if (newparent) { newparent.append(elem); } + return elem; } - /** * @typedef {PlainObject} module:jGraduate.ColorOpac Object may have one or both values * @property {string} [color] #Hex color * @property {Float} [opac] 0-1 */ + /** * @typedef {PlainObject} module:jGraduate.Options * @property {module:jGraduate~Paint} [paint] A Paint object object describing the paint to display initially; defaults to a new instance without options (defaults to opaque white) @@ -20858,6 +23024,7 @@ * @param {external:jQuery.jGraduate.Paint} paint * @returns {undefined} */ + /** * @callback external:jQuery.fn.jGraduate.CancelCallback * @returns {undefined} @@ -20870,6 +23037,8 @@ * @param {external:jQuery.fn.jGraduate.CancelCallback} [cancelCallback] Called with no arguments when Cancel is pressed * @returns {external:jQuery} */ + + $.fn.jGraduate = function (options, okCallback, cancelCallback) { return this.each(function () { var $this = $(this), @@ -20878,7 +23047,8 @@ idref = '#' + $this.attr('id') + ' '; if (!idref) { - alert('Container element must have an id attribute to maintain unique id strings for sub-elements.'); + /* await */ + $.alert('Container element must have an id attribute to maintain unique id strings for sub-elements.'); return; } @@ -20887,108 +23057,109 @@ case 'radialGradient': $this.paint.linearGradient = null; break; + case 'linearGradient': $this.paint.radialGradient = null; break; + case 'solidColor': $this.paint.radialGradient = $this.paint.linearGradient = null; break; } + typeof $this.okCallback === 'function' && $this.okCallback($this.paint); $this.hide(); }; + var cancelClicked = function cancelClicked() { typeof $this.cancelCallback === 'function' && $this.cancelCallback(); $this.hide(); }; - $.extend(true, $this, { // public properties, methods, and callbacks + $.extend(true, $this, { + // public properties, methods, and callbacks // make a copy of the incoming paint - paint: new $.jGraduate.Paint({ copy: $settings.paint }), + paint: new $.jGraduate.Paint({ + copy: $settings.paint + }), okCallback: typeof okCallback === 'function' ? okCallback : null, cancelCallback: typeof cancelCallback === 'function' ? cancelCallback : null }); - var // pos = $this.position(), color = null; var $win = $(window); if ($this.paint.type === 'none') { - $this.paint = new $.jGraduate.Paint({ solidColor: 'ffffff' }); + $this.paint = new $.jGraduate.Paint({ + solidColor: 'ffffff' + }); } $this.addClass('jGraduate_Picker'); $this.html('<ul class="jGraduate_tabs">' + '<li class="jGraduate_tab_color jGraduate_tab_current" data-type="col">Solid Color</li>' + '<li class="jGraduate_tab_lingrad" data-type="lg">Linear Gradient</li>' + '<li class="jGraduate_tab_radgrad" data-type="rg">Radial Gradient</li>' + '</ul>' + '<div class="jGraduate_colPick"></div>' + '<div class="jGraduate_gradPick"></div>' + '<div class="jGraduate_LightBox"></div>' + '<div id="' + id + '_jGraduate_stopPicker" class="jGraduate_stopPicker"></div>'); var colPicker = $(idref + '> .jGraduate_colPick'); var gradPicker = $(idref + '> .jGraduate_gradPick'); - - gradPicker.html('<div id="' + id + '_jGraduate_Swatch" class="jGraduate_Swatch">' + '<h2 class="jGraduate_Title">' + $settings.window.pickerTitle + '</h2>' + '<div id="' + id + '_jGraduate_GradContainer" class="jGraduate_GradContainer"></div>' + '<div id="' + id + '_jGraduate_StopSlider" class="jGraduate_StopSlider"></div>' + '</div>' + '<div class="jGraduate_Form jGraduate_Points jGraduate_lg_field">' + '<div class="jGraduate_StopSection">' + '<label class="jGraduate_Form_Heading">Begin Point</label>' + '<div class="jGraduate_Form_Section">' + '<label>x:</label>' + '<input type="text" id="' + id + '_jGraduate_x1" size="3" title="Enter starting x value between 0.0 and 1.0"/>' + '<label>y:</label>' + '<input type="text" id="' + id + '_jGraduate_y1" size="3" title="Enter starting y value between 0.0 and 1.0"/>' + '</div>' + '</div>' + '<div class="jGraduate_StopSection">' + '<label class="jGraduate_Form_Heading">End Point</label>' + '<div class="jGraduate_Form_Section">' + '<label>x:</label>' + '<input type="text" id="' + id + '_jGraduate_x2" size="3" title="Enter ending x value between 0.0 and 1.0"/>' + '<label>y:</label>' + '<input type="text" id="' + id + '_jGraduate_y2" size="3" title="Enter ending y value between 0.0 and 1.0"/>' + '</div>' + '</div>' + '</div>' + '<div class="jGraduate_Form jGraduate_Points jGraduate_rg_field">' + '<div class="jGraduate_StopSection">' + '<label class="jGraduate_Form_Heading">Center Point</label>' + '<div class="jGraduate_Form_Section">' + '<label>x:</label>' + '<input type="text" id="' + id + '_jGraduate_cx" size="3" title="Enter x value between 0.0 and 1.0"/>' + '<label>y:</label>' + '<input type="text" id="' + id + '_jGraduate_cy" size="3" title="Enter y value between 0.0 and 1.0"/>' + '</div>' + '</div>' + '<div class="jGraduate_StopSection">' + '<label class="jGraduate_Form_Heading">Focal Point</label>' + '<div class="jGraduate_Form_Section">' + '<label>Match center: <input type="checkbox" checked="checked" id="' + id + '_jGraduate_match_ctr"/></label><br/>' + '<label>x:</label>' + '<input type="text" id="' + id + '_jGraduate_fx" size="3" title="Enter x value between 0.0 and 1.0"/>' + '<label>y:</label>' + '<input type="text" id="' + id + '_jGraduate_fy" size="3" title="Enter y value between 0.0 and 1.0"/>' + '</div>' + '</div>' + '</div>' + '<div class="jGraduate_StopSection jGraduate_SpreadMethod">' + '<label class="jGraduate_Form_Heading">Spread method</label>' + '<div class="jGraduate_Form_Section">' + '<select class="jGraduate_spreadMethod">' + '<option value=pad selected>Pad</option>' + '<option value=reflect>Reflect</option>' + '<option value=repeat>Repeat</option>' + '</select>' + '</div>' + '</div>' + '<div class="jGraduate_Form">' + '<div class="jGraduate_Slider jGraduate_RadiusField jGraduate_rg_field">' + '<label class="prelabel">Radius:</label>' + '<div id="' + id + '_jGraduate_Radius" class="jGraduate_SliderBar jGraduate_Radius" title="Click to set radius">' + '<img id="' + id + '_jGraduate_RadiusArrows" class="jGraduate_RadiusArrows" src="' + $settings.images.clientPath + 'rangearrows2.gif">' + '</div>' + '<label><input type="text" id="' + id + '_jGraduate_RadiusInput" size="3" value="100"/>%</label>' + '</div>' + '<div class="jGraduate_Slider jGraduate_EllipField jGraduate_rg_field">' + '<label class="prelabel">Ellip:</label>' + '<div id="' + id + '_jGraduate_Ellip" class="jGraduate_SliderBar jGraduate_Ellip" title="Click to set Ellip">' + '<img id="' + id + '_jGraduate_EllipArrows" class="jGraduate_EllipArrows" src="' + $settings.images.clientPath + 'rangearrows2.gif">' + '</div>' + '<label><input type="text" id="' + id + '_jGraduate_EllipInput" size="3" value="0"/>%</label>' + '</div>' + '<div class="jGraduate_Slider jGraduate_AngleField jGraduate_rg_field">' + '<label class="prelabel">Angle:</label>' + '<div id="' + id + '_jGraduate_Angle" class="jGraduate_SliderBar jGraduate_Angle" title="Click to set Angle">' + '<img id="' + id + '_jGraduate_AngleArrows" class="jGraduate_AngleArrows" src="' + $settings.images.clientPath + 'rangearrows2.gif">' + '</div>' + '<label><input type="text" id="' + id + '_jGraduate_AngleInput" size="3" value="0"/>deg</label>' + '</div>' + '<div class="jGraduate_Slider jGraduate_OpacField">' + '<label class="prelabel">Opac:</label>' + '<div id="' + id + '_jGraduate_Opac" class="jGraduate_SliderBar jGraduate_Opac" title="Click to set Opac">' + '<img id="' + id + '_jGraduate_OpacArrows" class="jGraduate_OpacArrows" src="' + $settings.images.clientPath + 'rangearrows2.gif">' + '</div>' + '<label><input type="text" id="' + id + '_jGraduate_OpacInput" size="3" value="100"/>%</label>' + '</div>' + '</div>' + '<div class="jGraduate_OkCancel">' + '<input type="button" id="' + id + '_jGraduate_Ok" class="jGraduate_Ok" value="OK"/>' + '<input type="button" id="' + id + '_jGraduate_Cancel" class="jGraduate_Cancel" value="Cancel"/>' + '</div>'); - - // -------------- + gradPicker.html('<div id="' + id + '_jGraduate_Swatch" class="jGraduate_Swatch">' + '<h2 class="jGraduate_Title">' + $settings.window.pickerTitle + '</h2>' + '<div id="' + id + '_jGraduate_GradContainer" class="jGraduate_GradContainer"></div>' + '<div id="' + id + '_jGraduate_StopSlider" class="jGraduate_StopSlider"></div>' + '</div>' + '<div class="jGraduate_Form jGraduate_Points jGraduate_lg_field">' + '<div class="jGraduate_StopSection">' + '<label class="jGraduate_Form_Heading">Begin Point</label>' + '<div class="jGraduate_Form_Section">' + '<label>x:</label>' + '<input type="text" id="' + id + '_jGraduate_x1" size="3" title="Enter starting x value between 0.0 and 1.0"/>' + '<label>y:</label>' + '<input type="text" id="' + id + '_jGraduate_y1" size="3" title="Enter starting y value between 0.0 and 1.0"/>' + '</div>' + '</div>' + '<div class="jGraduate_StopSection">' + '<label class="jGraduate_Form_Heading">End Point</label>' + '<div class="jGraduate_Form_Section">' + '<label>x:</label>' + '<input type="text" id="' + id + '_jGraduate_x2" size="3" title="Enter ending x value between 0.0 and 1.0"/>' + '<label>y:</label>' + '<input type="text" id="' + id + '_jGraduate_y2" size="3" title="Enter ending y value between 0.0 and 1.0"/>' + '</div>' + '</div>' + '</div>' + '<div class="jGraduate_Form jGraduate_Points jGraduate_rg_field">' + '<div class="jGraduate_StopSection">' + '<label class="jGraduate_Form_Heading">Center Point</label>' + '<div class="jGraduate_Form_Section">' + '<label>x:</label>' + '<input type="text" id="' + id + '_jGraduate_cx" size="3" title="Enter x value between 0.0 and 1.0"/>' + '<label>y:</label>' + '<input type="text" id="' + id + '_jGraduate_cy" size="3" title="Enter y value between 0.0 and 1.0"/>' + '</div>' + '</div>' + '<div class="jGraduate_StopSection">' + '<label class="jGraduate_Form_Heading">Focal Point</label>' + '<div class="jGraduate_Form_Section">' + '<label>Match center: <input type="checkbox" checked="checked" id="' + id + '_jGraduate_match_ctr"/></label><br/>' + '<label>x:</label>' + '<input type="text" id="' + id + '_jGraduate_fx" size="3" title="Enter x value between 0.0 and 1.0"/>' + '<label>y:</label>' + '<input type="text" id="' + id + '_jGraduate_fy" size="3" title="Enter y value between 0.0 and 1.0"/>' + '</div>' + '</div>' + '</div>' + '<div class="jGraduate_StopSection jGraduate_SpreadMethod">' + '<label class="jGraduate_Form_Heading">Spread method</label>' + '<div class="jGraduate_Form_Section">' + '<select class="jGraduate_spreadMethod">' + '<option value=pad selected>Pad</option>' + '<option value=reflect>Reflect</option>' + '<option value=repeat>Repeat</option>' + '</select>' + '</div>' + '</div>' + '<div class="jGraduate_Form">' + '<div class="jGraduate_Slider jGraduate_RadiusField jGraduate_rg_field">' + '<label class="prelabel">Radius:</label>' + '<div id="' + id + '_jGraduate_Radius" class="jGraduate_SliderBar jGraduate_Radius" title="Click to set radius">' + '<img id="' + id + '_jGraduate_RadiusArrows" class="jGraduate_RadiusArrows" src="' + $settings.images.clientPath + 'rangearrows2.gif">' + '</div>' + '<label><input type="text" id="' + id + '_jGraduate_RadiusInput" size="3" value="100"/>%</label>' + '</div>' + '<div class="jGraduate_Slider jGraduate_EllipField jGraduate_rg_field">' + '<label class="prelabel">Ellip:</label>' + '<div id="' + id + '_jGraduate_Ellip" class="jGraduate_SliderBar jGraduate_Ellip" title="Click to set Ellip">' + '<img id="' + id + '_jGraduate_EllipArrows" class="jGraduate_EllipArrows" src="' + $settings.images.clientPath + 'rangearrows2.gif">' + '</div>' + '<label><input type="text" id="' + id + '_jGraduate_EllipInput" size="3" value="0"/>%</label>' + '</div>' + '<div class="jGraduate_Slider jGraduate_AngleField jGraduate_rg_field">' + '<label class="prelabel">Angle:</label>' + '<div id="' + id + '_jGraduate_Angle" class="jGraduate_SliderBar jGraduate_Angle" title="Click to set Angle">' + '<img id="' + id + '_jGraduate_AngleArrows" class="jGraduate_AngleArrows" src="' + $settings.images.clientPath + 'rangearrows2.gif">' + '</div>' + '<label><input type="text" id="' + id + '_jGraduate_AngleInput" size="3" value="0"/>deg</label>' + '</div>' + '<div class="jGraduate_Slider jGraduate_OpacField">' + '<label class="prelabel">Opac:</label>' + '<div id="' + id + '_jGraduate_Opac" class="jGraduate_SliderBar jGraduate_Opac" title="Click to set Opac">' + '<img id="' + id + '_jGraduate_OpacArrows" class="jGraduate_OpacArrows" src="' + $settings.images.clientPath + 'rangearrows2.gif">' + '</div>' + '<label><input type="text" id="' + id + '_jGraduate_OpacInput" size="3" value="100"/>%</label>' + '</div>' + '</div>' + '<div class="jGraduate_OkCancel">' + '<input type="button" id="' + id + '_jGraduate_Ok" class="jGraduate_Ok" value="OK"/>' + '<input type="button" id="' + id + '_jGraduate_Cancel" class="jGraduate_Cancel" value="Cancel"/>' + '</div>'); // -------------- // Set up all the SVG elements (the gradient, stops and rectangle) + var MAX = 256, MARGINX = 0, MARGINY = 0, - - // STOP_RADIUS = 15 / 2, + // STOP_RADIUS = 15 / 2, SIZEX = MAX - 2 * MARGINX, SIZEY = MAX - 2 * MARGINY; - var attrInput = {}; - var SLIDERW = 145; $('.jGraduate_SliderBar').width(SLIDERW); - var container = $('#' + id + '_jGraduate_GradContainer')[0]; - var svg = mkElem('svg', { id: id + '_jgraduate_svg', width: MAX, height: MAX, xmlns: ns.svg - }, container); - - // This wasn't working as designed + }, container); // This wasn't working as designed // let curType; // curType = curType || $this.paint.type; - // if we are sent a gradient, import it - var curType = $this.paint.type; + var curType = $this.paint.type; var grad = $this.paint[curType]; var curGradient = grad; - var gradalpha = $this.paint.alpha; + var isSolid = curType === 'solidColor'; // Make any missing gradients - var isSolid = curType === 'solidColor'; - - // Make any missing gradients switch (curType) { - case 'solidColor': - // fall through + case 'solidColor': // fall through + case 'linearGradient': if (!isSolid) { curGradient.id = id + '_lg_jgraduate_grad'; grad = curGradient = svg.appendChild(curGradient); // .cloneNode(true)); } + mkElem('radialGradient', { id: id + '_rg_jgraduate_grad' }, svg); + if (curType === 'linearGradient') { break; } + // fall through + case 'radialGradient': if (!isSolid) { curGradient.id = id + '_rg_jgraduate_grad'; grad = curGradient = svg.appendChild(curGradient); // .cloneNode(true)); } + mkElem('linearGradient', { id: id + '_lg_jgraduate_grad' }, svg); } - var stopGroup = void 0; // eslint-disable-line prefer-const + var stopGroup; // eslint-disable-line prefer-const + if (isSolid) { grad = curGradient = $('#' + id + '_lg_jgraduate_grad')[0]; color = $this.paint[curType]; @@ -21003,16 +23174,20 @@ break; case 'inverse': - // Invert current color for second stop - var inverted = ''; - for (var i = 0; i < 6; i += 2) { - // const ch = color.substr(i, 2); - var inv = (255 - parseInt(color.substr(i, 2), 16)).toString(16); - if (inv.length < 2) inv = 0 + inv; - inverted += inv; + { + // Invert current color for second stop + var inverted = ''; + + for (var i = 0; i < 6; i += 2) { + // const ch = color.substr(i, 2); + var inv = (255 - parseInt(color.substr(i, 2), 16)).toString(16); + if (inv.length < 2) inv = 0 + inv; + inverted += inv; + } + + mkStop(1, '#' + inverted, 1); + break; } - mkStop(1, '#' + inverted, 1); - break; case 'white': mkStop(1, '#ffffff', 1); @@ -21032,12 +23207,10 @@ y1 = parseFloat(grad.getAttribute('y1') || 0.0), x2 = parseFloat(grad.getAttribute('x2') || 1.0), y2 = parseFloat(grad.getAttribute('y2') || 0.0); - var cx = parseFloat(grad.getAttribute('cx') || 0.5), cy = parseFloat(grad.getAttribute('cy') || 0.5), fx = parseFloat(grad.getAttribute('fx') || cx), fy = parseFloat(grad.getAttribute('fy') || cy); - var previewRect = mkElem('rect', { id: id + '_jgraduate_rect', x: MARGINX, @@ -21046,9 +23219,8 @@ height: SIZEY, fill: 'url(#' + id + '_jgraduate_grad)', 'fill-opacity': gradalpha / 100 - }, svg); + }, svg); // stop visuals created here - // stop visuals created here var beginCoord = $('<div/>').attr({ class: 'grad_coord jGraduate_lg_field', title: 'Begin Stop' @@ -21056,12 +23228,10 @@ top: y1 * MAX, left: x1 * MAX }).data('coord', 'start').appendTo(container); - var endCoord = beginCoord.clone().text(2).css({ top: y2 * MAX, left: x2 * MAX }).attr('title', 'End stop').data('coord', 'end').appendTo(container); - var centerCoord = $('<div/>').attr({ class: 'grad_coord jGraduate_rg_field', title: 'Center stop' @@ -21069,17 +23239,12 @@ top: cy * MAX, left: cx * MAX }).data('coord', 'center').appendTo(container); - var focusCoord = centerCoord.clone().text('F').css({ top: fy * MAX, left: fx * MAX, display: 'none' }).attr('title', 'Focus point').data('coord', 'focus').appendTo(container); - - focusCoord[0].id = id + '_jGraduate_focusCoord'; - - // const coords = $(idref + ' .grad_coord'); - + focusCoord[0].id = id + '_jGraduate_focusCoord'; // const coords = $(idref + ' .grad_coord'); // $(container).hover(function () { // coords.animate({ // opacity: 1 @@ -21090,11 +23255,11 @@ // }, 500); // }); - var showFocus = void 0; + var showFocus; $.each(['x1', 'y1', 'x2', 'y2', 'cx', 'cy', 'fx', 'fy'], function (i, attr) { var isRadial = isNaN(attr[1]); - var attrval = curGradient.getAttribute(attr); + if (!attrval) { // Set defaults if (isRadial) { @@ -21121,41 +23286,50 @@ } var $elem = isRadial ? attr[0] === 'c' ? centerCoord : focusCoord : attr[1] === '1' ? beginCoord : endCoord; - var cssName = attr.includes('x') ? 'left' : 'top'; - $elem.css(cssName, this.value * MAX); }).change(); }); + /** + * + * @param {Float} n + * @param {Float|string} colr + * @param {Float} opac + * @param {boolean} [sel] + * @param {SVGStopElement} [stopElem] + * @returns {SVGStopElement} + */ + + function mkStop(n, colr, opac, sel, stopElem) { + var stop = stopElem || mkElem('stop', { + 'stop-color': colr, + 'stop-opacity': opac, + offset: n + }, curGradient); - function mkStop(n, color, opac, sel, stopElem) { - var stop = stopElem || mkElem('stop', { 'stop-color': color, 'stop-opacity': opac, offset: n }, curGradient); if (stopElem) { - color = stopElem.getAttribute('stop-color'); + colr = stopElem.getAttribute('stop-color'); opac = stopElem.getAttribute('stop-opacity'); n = stopElem.getAttribute('offset'); } else { curGradient.append(stop); } + if (opac === null) opac = 1; - var pickerD = 'M-6.2,0.9c3.6-4,6.7-4.3,6.7-12.4c-0.2,7.9,3.1,8.8,6.5,12.4c3.5,3.8,2.9,9.6,0,12.3c-3.1,2.8-10.4,2.7-13.2,0C-9.6,9.9-9.4,4.4-6.2,0.9z'; - var pathbg = mkElem('path', { d: pickerD, fill: 'url(#jGraduate_trans)', transform: 'translate(' + (10 + n * MAX) + ', 26)' }, stopGroup); - var path = mkElem('path', { d: pickerD, - fill: color, + fill: colr, 'fill-opacity': opac, transform: 'translate(' + (10 + n * MAX) + ', 26)', stroke: '#000', 'stroke-width': 1.5 }, stopGroup); - $(path).mousedown(function (e) { selectStop(this); drag = curStop; @@ -21165,21 +23339,34 @@ return false; }).data('stop', stop).data('bg', pathbg).dblclick(function () { $('div.jGraduate_LightBox').show(); - var colorhandle = this; - var stopOpacity = +stop.getAttribute('stop-opacity') || 1; + var colorhandle = this; // eslint-disable-line consistent-this + + var stopOpacity = Number(stop.getAttribute('stop-opacity')) || 1; var stopColor = stop.getAttribute('stop-color') || 1; var thisAlpha = (parseFloat(stopOpacity) * 255).toString(16); + while (thisAlpha.length < 2) { thisAlpha = '0' + thisAlpha; } - color = stopColor.substr(1) + thisAlpha; - $('#' + id + '_jGraduate_stopPicker').css({ left: 100, bottom: 15 }).jPicker({ - window: { title: 'Pick the start color and opacity for the gradient' }, - images: { clientPath: $settings.images.clientPath }, - color: { active: color, alphaSupport: true } - }, function (color, arg2) { - stopColor = color.val('hex') ? '#' + color.val('hex') : 'none'; - stopOpacity = color.val('a') !== null ? color.val('a') / 256 : 1; + + colr = stopColor.substr(1) + thisAlpha; + $('#' + id + '_jGraduate_stopPicker').css({ + left: 100, + bottom: 15 + }).jPicker({ + window: { + title: 'Pick the start color and opacity for the gradient' + }, + images: { + clientPath: $settings.images.clientPath + }, + color: { + active: colr, + alphaSupport: true + } + }, function (clr, arg2) { + stopColor = clr.val('hex') ? '#' + clr.val('hex') : 'none'; + stopOpacity = clr.val('a') !== null ? clr.val('a') / 256 : 1; colorhandle.setAttribute('fill', stopColor); colorhandle.setAttribute('fill-opacity', stopOpacity); stop.setAttribute('stop-color', stopColor); @@ -21191,11 +23378,11 @@ $('#' + id + '_jGraduate_stopPicker').hide(); }); }); - $(curGradient).find('stop').each(function () { var curS = $(this); - if (+this.getAttribute('offset') > n) { - if (!color) { + + if (Number(this.getAttribute('offset')) > n) { + if (!colr) { var newcolor = this.getAttribute('stop-color'); var newopac = this.getAttribute('stop-opacity'); stop.setAttribute('stop-color', newcolor); @@ -21203,13 +23390,21 @@ stop.setAttribute('stop-opacity', newopac === null ? 1 : newopac); path.setAttribute('fill-opacity', newopac === null ? 1 : newopac); } + curS.before(stop); return false; } + + return true; }); if (sel) selectStop(path); return stop; } + /** + * + * @returns {undefined} + */ + function remStop() { delStop.setAttribute('display', 'none'); @@ -21220,11 +23415,7 @@ } var stopMakerDiv = $('#' + id + '_jGraduate_StopSlider'); - - var stops = void 0, - curStop = void 0, - drag = void 0; - + var stops, curStop, drag; var delStop = mkElem('path', { d: 'm9.75,-6l-19.5,19.5m0,-19.5l19.5,19.5', fill: 'none', @@ -21233,51 +23424,69 @@ display: 'none' }, undefined); // stopMakerSVG); + /** + * @param {Element} item + * @returns {undefined} + */ + function selectStop(item) { if (curStop) curStop.setAttribute('stroke', '#000'); item.setAttribute('stroke', 'blue'); curStop = item; - curStop.parentNode.append(curStop); - // stops = $('stop'); + curStop.parentNode.append(curStop); // stops = $('stop'); // opac_select.val(curStop.attr('fill-opacity') || 1); // root.append(delStop); } - var stopOffset = void 0; + var stopOffset; + /** + * + * @returns {undefined} + */ function remDrags() { $win.unbind('mousemove', dragColor); + if (delStop.getAttribute('display') !== 'none') { remStop(); } + drag = null; } var scaleX = 1, scaleY = 1, angle = 0; - var cX = cx; var cY = cy; + /** + * + * @returns {undefined} + */ + function xform() { var rot = angle ? 'rotate(' + angle + ',' + cX + ',' + cY + ') ' : ''; + if (scaleX === 1 && scaleY === 1) { - curGradient.removeAttribute('gradientTransform'); - // $('#ang').addClass('dis'); + curGradient.removeAttribute('gradientTransform'); // $('#ang').addClass('dis'); } else { var x = -cX * (scaleX - 1); var y = -cY * (scaleY - 1); - curGradient.setAttribute('gradientTransform', rot + 'translate(' + x + ',' + y + ') scale(' + scaleX + ',' + scaleY + ')'); - // $('#ang').removeClass('dis'); + curGradient.setAttribute('gradientTransform', rot + 'translate(' + x + ',' + y + ') scale(' + scaleX + ',' + scaleY + ')'); // $('#ang').removeClass('dis'); } } + /** + * @param {Event} evt + * @returns {undefined} + */ + function dragColor(evt) { var x = evt.pageX - stopOffset.left; var y = evt.pageY - stopOffset.top; x = x < 10 ? 10 : x > MAX + 10 ? MAX + 10 : x; - var xfStr = 'translate(' + x + ', 26)'; + if (y < -60 || y > 130) { delStop.setAttribute('display', 'block'); delStop.setAttribute('transform', xfStr); @@ -21289,17 +23498,17 @@ $.data(drag, 'bg').setAttribute('transform', xfStr); var stop = $.data(drag, 'stop'); var sX = (x - 10) / MAX; - stop.setAttribute('offset', sX); - var last = 0; $(curGradient).find('stop').each(function (i) { var cur = this.getAttribute('offset'); var t = $(this); + if (cur < last) { t.prev().before(t); stops = $(curGradient).find('stop'); } + last = cur; }); } @@ -21308,40 +23517,31 @@ width: '100%', height: 45 }, stopMakerDiv[0]); - var transPattern = mkElem('pattern', { width: 16, height: 16, patternUnits: 'userSpaceOnUse', id: 'jGraduate_trans' }, stopMakerSVG); - var transImg = mkElem('image', { width: 16, height: 16 }, transPattern); - var bgImage = $settings.images.clientPath + 'map-opacity.png'; - transImg.setAttributeNS(ns.xlink, 'xlink:href', bgImage); - $(stopMakerSVG).click(function (evt) { stopOffset = stopMakerDiv.offset(); var target = evt.target; - if (target.tagName === 'path') return; var x = evt.pageX - stopOffset.left - 8; x = x < 10 ? 10 : x > MAX + 10 ? MAX + 10 : x; mkStop(x / MAX, 0, 0, true); evt.stopPropagation(); }); - $(stopMakerSVG).mouseover(function () { stopMakerSVG.append(delStop); }); - stopGroup = mkElem('g', {}, stopMakerSVG); - mkElem('line', { x1: 10, y1: 15, @@ -21350,58 +23550,55 @@ 'stroke-width': 2, stroke: '#000' }, stopMakerSVG); - var spreadMethodOpt = gradPicker.find('.jGraduate_spreadMethod').change(function () { curGradient.setAttribute('spreadMethod', $(this).val()); - }); + }); // handle dragging the stop around the swatch - // handle dragging the stop around the swatch var draggingCoord = null; var onCoordDrag = function onCoordDrag(evt) { var x = evt.pageX - offset.left; - var y = evt.pageY - offset.top; + var y = evt.pageY - offset.top; // clamp stop to the swatch - // clamp stop to the swatch x = x < 0 ? 0 : x > MAX ? MAX : x; y = y < 0 ? 0 : y > MAX ? MAX : y; + draggingCoord.css('left', x).css('top', y); // calculate stop offset - draggingCoord.css('left', x).css('top', y); - - // calculate stop offset var fracx = x / SIZEX; var fracy = y / SIZEY; - var type = draggingCoord.data('coord'); - var grad = curGradient; + var grd = curGradient; switch (type) { case 'start': attrInput.x1.val(fracx); attrInput.y1.val(fracy); - grad.setAttribute('x1', fracx); - grad.setAttribute('y1', fracy); + grd.setAttribute('x1', fracx); + grd.setAttribute('y1', fracy); break; + case 'end': attrInput.x2.val(fracx); attrInput.y2.val(fracy); - grad.setAttribute('x2', fracx); - grad.setAttribute('y2', fracy); + grd.setAttribute('x2', fracx); + grd.setAttribute('y2', fracy); break; + case 'center': attrInput.cx.val(fracx); attrInput.cy.val(fracy); - grad.setAttribute('cx', fracx); - grad.setAttribute('cy', fracy); + grd.setAttribute('cx', fracx); + grd.setAttribute('cy', fracy); cX = fracx; cY = fracy; xform(); break; + case 'focus': attrInput.fx.val(fracx); attrInput.fy.val(fracy); - grad.setAttribute('fx', fracx); - grad.setAttribute('fy', fracy); + grd.setAttribute('fx', fracx); + grd.setAttribute('fy', fracy); xform(); } @@ -21411,20 +23608,19 @@ var onCoordUp = function onCoordUp() { draggingCoord = null; $win.unbind('mousemove', onCoordDrag).unbind('mouseup', onCoordUp); - }; - - // Linear gradient + }; // Linear gradient // (function () { - stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); - var numstops = stops.length; - // if there are not at least two stops, then + stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); + var numstops = stops.length; // if there are not at least two stops, then + if (numstops < 2) { while (numstops < 2) { curGradient.append(document.createElementNS(ns.svg, 'stop')); ++numstops; } + stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); } @@ -21433,23 +23629,18 @@ } spreadMethodOpt.val(curGradient.getAttribute('spreadMethod') || 'pad'); + var offset; // No match, so show focus point - var offset = void 0; - - // No match, so show focus point showFocus = false; - previewRect.setAttribute('fill-opacity', gradalpha / 100); - $('#' + id + ' div.grad_coord').mousedown(function (evt) { evt.preventDefault(); - draggingCoord = $(this); - // const sPos = draggingCoord.offset(); + draggingCoord = $(this); // const sPos = draggingCoord.offset(); + offset = draggingCoord.parent().offset(); $win.mousemove(onCoordDrag).mouseup(onCoordUp); - }); + }); // bind GUI elements - // bind GUI elements $('#' + id + '_jGraduate_Ok').bind('click', function () { $this.paint.type = curType; $this.paint[curType] = curGradient.cloneNode(true); @@ -21471,50 +23662,47 @@ } $('#' + id + '_jGraduate_match_ctr')[0].checked = !showFocus; - - var lastfx = void 0, - lastfy = void 0; - + var lastfx, lastfy; $('#' + id + '_jGraduate_match_ctr').change(function () { showFocus = !this.checked; focusCoord.toggle(showFocus); attrInput.fx.val(''); attrInput.fy.val(''); - var grad = curGradient; + var grd = curGradient; + if (!showFocus) { - lastfx = grad.getAttribute('fx'); - lastfy = grad.getAttribute('fy'); - grad.removeAttribute('fx'); - grad.removeAttribute('fy'); + lastfx = grd.getAttribute('fx'); + lastfy = grd.getAttribute('fy'); + grd.removeAttribute('fx'); + grd.removeAttribute('fy'); } else { - var _fx = lastfx || 0.5; - var _fy = lastfy || 0.5; - grad.setAttribute('fx', _fx); - grad.setAttribute('fy', _fy); - attrInput.fx.val(_fx); - attrInput.fy.val(_fy); + var fX = lastfx || 0.5; + var fY = lastfy || 0.5; + grd.setAttribute('fx', fX); + grd.setAttribute('fy', fY); + attrInput.fx.val(fX); + attrInput.fy.val(fY); } }); - stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); - numstops = stops.length; - // if there are not at least two stops, then + numstops = stops.length; // if there are not at least two stops, then + if (numstops < 2) { while (numstops < 2) { curGradient.append(document.createElementNS(ns.svg, 'stop')); ++numstops; } + stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); } - var slider = void 0; + var slider; var setSlider = function setSlider(e) { var _slider = slider, - offset = _slider.offset; - + left = _slider.offset.left; var div = slider.parent; - var x = e.pageX - offset.left - parseInt(div.css('border-left-width')); + var x = e.pageX - left - parseInt(div.css('border-left-width')); if (x > SLIDERW) x = SLIDERW; if (x <= 0) x = 0; var posx = x - 5; @@ -21527,35 +23715,47 @@ if (x <= 0.01) x = 0.01; curGradient.setAttribute('r', x); break; + case 'opacity': $this.paint.alpha = parseInt(x * 100); previewRect.setAttribute('fill-opacity', x); break; + case 'ellip': scaleX = 1; scaleY = 1; + if (x < 0.5) { x /= 0.5; // 0.001 + scaleX = x <= 0 ? 0.01 : x; } else if (x > 0.5) { x /= 0.5; // 2 + x = 2 - x; scaleY = x <= 0 ? 0.01 : x; } + xform(); x -= 1; + if (scaleY === x + 1) { x = Math.abs(x); } + break; + case 'angle': - x = x - 0.5; + x -= 0.5; angle = x *= 180; xform(); x /= 100; break; } - slider.elem.css({ 'margin-left': posx }); + + slider.elem.css({ + 'margin-left': posx + }); x = Math.round(x * 100); slider.input.val(x); }; @@ -21565,11 +23765,14 @@ if (curType === 'radialGradient') { var tlist = curGradient.gradientTransform.baseVal; + if (tlist.numberOfItems === 2) { var t = tlist.getItem(0); var s = tlist.getItem(1); + if (t.type === 2 && s.type === 3) { var m = s.matrix; + if (m.a !== 1) { ellipVal = Math.round(-(1 - m.a) * 100); } else if (m.d !== 1) { @@ -21579,12 +23782,15 @@ } else if (tlist.numberOfItems === 3) { // Assume [R][T][S] var r = tlist.getItem(0); + var _t = tlist.getItem(1); + var _s = tlist.getItem(2); if (r.type === 4 && _t.type === 2 && _s.type === 3) { angleVal = Math.round(r.angle); var _m = _s.matrix; + if (_m.a !== 1) { ellipVal = Math.round(-(1 - _m.a) * 100); } else if (_m.d !== 1) { @@ -21616,7 +23822,6 @@ val: angleVal } }; - $.each(sliders, function (type, data) { var handle = $(data.handle); handle.mousedown(function (evt) { @@ -21631,11 +23836,11 @@ $win.mousemove(dragSlider).mouseup(stopSlider); evt.preventDefault(); }); - $(data.input).val(data.val).change(function () { var isRad = curType === 'radialGradient'; - var val = +this.value; + var val = Number(this.value); var xpos = 0; + switch (type) { case 'radius': if (isRad) curGradient.setAttribute('r', val / 100); @@ -21650,11 +23855,14 @@ case 'ellip': scaleX = scaleY = 1; + if (val === 0) { xpos = SLIDERW * 0.5; break; } + if (val > 99.5) val = 99.5; + if (val > 0) { scaleY = 1 - val / 100; } else { @@ -21672,12 +23880,16 @@ xpos *= SLIDERW; if (isRad) xform(); } + if (xpos > SLIDERW) { xpos = SLIDERW; } else if (xpos < 0) { xpos = 0; } - handle.css({ 'margin-left': xpos - 5 }); + + handle.css({ + 'margin-left': xpos - 5 + }); }).change(); }); @@ -21689,59 +23901,68 @@ var stopSlider = function stopSlider(evt) { $win.unbind('mousemove', dragSlider).unbind('mouseup', stopSlider); slider = null; - }; + }; // -------------- + - // -------------- var thisAlpha = ($this.paint.alpha * 255 / 100).toString(16); + while (thisAlpha.length < 2) { thisAlpha = '0' + thisAlpha; } + thisAlpha = thisAlpha.split('.')[0]; color = $this.paint.solidColor === 'none' ? '' : $this.paint.solidColor + thisAlpha; if (!isSolid) { color = stops[0].getAttribute('stop-color'); - } + } // This should be done somewhere else, probably + - // This should be done somewhere else, probably $.extend($.fn.jPicker.defaults.window, { - alphaSupport: true, effects: { type: 'show', speed: 0 } + alphaSupport: true, + effects: { + type: 'show', + speed: 0 + } }); - colPicker.jPicker({ - window: { title: $settings.window.pickerTitle }, - images: { clientPath: $settings.images.clientPath }, - color: { active: color, alphaSupport: true } - }, function (color) { + window: { + title: $settings.window.pickerTitle + }, + images: { + clientPath: $settings.images.clientPath + }, + color: { + active: color, + alphaSupport: true + } + }, function (clr) { $this.paint.type = 'solidColor'; - $this.paint.alpha = color.val('ahex') ? Math.round(color.val('a') / 255 * 100) : 100; - $this.paint.solidColor = color.val('hex') ? color.val('hex') : 'none'; + $this.paint.alpha = clr.val('ahex') ? Math.round(clr.val('a') / 255 * 100) : 100; + $this.paint.solidColor = clr.val('hex') ? clr.val('hex') : 'none'; $this.paint.radialGradient = null; okClicked(); }, null, function () { cancelClicked(); }); - var tabs = $(idref + ' .jGraduate_tabs li'); tabs.click(function () { tabs.removeClass('jGraduate_tab_current'); $(this).addClass('jGraduate_tab_current'); $(idref + ' > div').hide(); var type = $(this).attr('data-type'); - /* const container = */$(idref + ' .jGraduate_gradPick').show(); + /* const container = */ + + $(idref + ' .jGraduate_gradPick').show(); + if (type === 'rg' || type === 'lg') { // Show/hide appropriate fields $('.jGraduate_' + type + '_field').show(); $('.jGraduate_' + (type === 'lg' ? 'rg' : 'lg') + '_field').hide(); - - $('#' + id + '_jgraduate_rect')[0].setAttribute('fill', 'url(#' + id + '_' + type + '_jgraduate_grad)'); - - // Copy stops + $('#' + id + '_jgraduate_rect')[0].setAttribute('fill', 'url(#' + id + '_' + type + '_jgraduate_grad)'); // Copy stops curType = type === 'lg' ? 'linearGradient' : 'radialGradient'; - $('#' + id + '_jGraduate_OpacInput').val($this.paint.alpha).change(); - var newGrad = $('#' + id + '_' + type + '_jgraduate_grad')[0]; if (curGradient !== newGrad) { @@ -21751,8 +23972,10 @@ var sm = spreadMethodOpt.val(); curGradient.setAttribute('spreadMethod', sm); } - showFocus = type === 'rg' && curGradient.getAttribute('fx') != null && !(cx === fx && cy === fy); + + showFocus = type === 'rg' && curGradient.getAttribute('fx') !== null && !(cx === fx && cy === fy); $('#' + id + '_jGraduate_focusCoord').toggle(showFocus); + if (showFocus) { $('#' + id + '_jGraduate_match_ctr')[0].checked = false; } @@ -21763,26 +23986,30 @@ }); $(idref + ' > div').hide(); tabs.removeClass('jGraduate_tab_current'); - var tab = void 0; + var tab; + switch ($this.paint.type) { case 'linearGradient': tab = $(idref + ' .jGraduate_tab_lingrad'); break; + case 'radialGradient': tab = $(idref + ' .jGraduate_tab_radgrad'); break; + default: tab = $(idref + ' .jGraduate_tab_color'); break; } - $this.show(); - // jPicker will try to show after a 0ms timeout, so need to fire this after that + $this.show(); // jPicker will try to show after a 0ms timeout, so need to fire this after that + setTimeout(function () { tab.addClass('jGraduate_tab_current').click(); }, 10); }); }; + return $; } @@ -21856,34 +24083,41 @@ $("#myInputElement").SpinButton(myOptions); }); */ + /** * @function module:jQuerySpinButton.jQuerySpinButton * @param {external:jQuery} $ The jQuery object to which to add the plug-in * @returns {external:jQuery} */ - function jqPluginSpinBtn ($) { + function jQueryPluginSpinButton($) { if (!$.loadingStylesheets) { $.loadingStylesheets = []; } + var stylesheet = 'spinbtn/jQuery.SpinButton.css'; + if (!$.loadingStylesheets.includes(stylesheet)) { $.loadingStylesheets.push(stylesheet); } /** * @callback module:jQuerySpinButton.StepCallback * @param {external:jQuery} thisArg Value of `this` + * @param {Float} i Value to adjust + * @returns {Float} */ + /** * @callback module:jQuerySpinButton.ValueCallback - * @param {external:jQuery} thisArg Value of `this` - * @param {Float} value Value that was changed + * @param {external:jQuery.fn.SpinButton} thisArg Spin Button; check its `value` to see how it was changed. + * @returns {undefined} */ + /** * @typedef {PlainObject} module:jQuerySpinButton.SpinButtonConfig * @property {Float} min Set lower limit * @property {Float} max Set upper limit. * @property {Float} step Set increment size. - * @property {module:jQuerySpinButton.StepCallback} stepfunc Custom function to run when changing a value; called with `this` of object and the value to adjust + * @property {module:jQuerySpinButton.StepCallback} stepfunc Custom function to run when changing a value; called with `this` of object and the value to adjust and returns a float. * @property {module:jQuerySpinButton.ValueCallback} callback Called after value adjusted (with `this` of object) * @property {Float} smallStep Set shift-click increment size. * @property {PlainObject} stateObj Object to allow passing in live-updating scale @@ -21896,17 +24130,27 @@ * @property {Float} delay Millisecond delay * @property {Float} interval Millisecond interval */ + /** * @function external:jQuery.fn.SpinButton * @param {module:jQuerySpinButton.SpinButtonConfig} cfg * @returns {external:jQuery} */ + + $.fn.SpinButton = function (cfg) { cfg = cfg || {}; + /** + * + * @param {Element} el + * @param {"offsetLeft"|"offsetTop"} prop + * @returns {Integer} + */ + function coord(el, prop) { var b = document.body; - var c = el[prop]; + while ((el = el.offsetParent) && el !== b) { if (!$.browser.msie || el.currentStyle.position !== 'relative') { c += el[prop]; @@ -21917,14 +24161,14 @@ } return this.each(function () { - this.repeating = false; - - // Apply specified options or defaults: + this.repeating = false; // Apply specified options or defaults: // (Ought to refactor this some day to use $.extend() instead) + this.spinCfg = { // min: cfg.min ? Number(cfg.min) : null, // max: cfg.max ? Number(cfg.max) : null, - min: !isNaN(parseFloat(cfg.min)) ? Number(cfg.min) : null, // Fixes bug with min:0 + min: !isNaN(parseFloat(cfg.min)) ? Number(cfg.min) : null, + // Fixes bug with min:0 max: !isNaN(parseFloat(cfg.max)) ? Number(cfg.max) : null, step: cfg.step ? Number(cfg.step) : 1, stepfunc: cfg.stepfunc || false, @@ -21939,13 +24183,13 @@ _delay: null, _repeat: null, callback: cfg.callback || null - }; + }; // if a smallStep isn't supplied, use half the regular step - // if a smallStep isn't supplied, use half the regular step this.spinCfg.smallStep = cfg.smallStep || this.spinCfg.step / 2; this.adjustValue = function (i) { - var v = void 0; + var v; + if (isNaN(this.value)) { v = this.spinCfg.reset; } else if (typeof this.spinCfg.stepfunc === 'function') { @@ -21954,13 +24198,17 @@ // weirdest JavaScript bug ever: 5.1 + 0.1 = 5.199999999 v = Number((Number(this.value) + Number(i)).toFixed(5)); } + if (this.spinCfg.min !== null) { v = Math.max(v, this.spinCfg.min); } + if (this.spinCfg.max !== null) { v = Math.min(v, this.spinCfg.max); } + this.value = v; + if (typeof this.spinCfg.callback === 'function') { this.spinCfg.callback(this); } @@ -21973,7 +24221,6 @@ var el = e.target; var scale = cfg.stateObj.tool_scale || 1; var height = $(el).height() / 2; - var direction = x > coord(el, 'offsetLeft') + el.offsetWidth * scale - this.spinCfg._btn_width ? y < coord(el, 'offsetTop') + height * scale ? 1 : -1 : 0; if (direction !== this.spinCfg._direction) { @@ -21983,16 +24230,18 @@ // Up arrow: $(this).removeClass(this.spinCfg.downClass).addClass(this.spinCfg.upClass); break; + case -1: // Down arrow: $(this).removeClass(this.spinCfg.upClass).addClass(this.spinCfg.downClass); break; + default: // Mouse is elsewhere in the textbox $(this).removeClass(this.spinCfg.upClass).removeClass(this.spinCfg.downClass); - } + } // Set spin direction: + - // Set spin direction: this.spinCfg._direction = direction; } }).mouseout(function () { @@ -22012,12 +24261,11 @@ _this.adjustValue(_this.spinCfg._direction * stepSize); }; - adjust(); + adjust(); // Initial delay before repeating adjustment - // Initial delay before repeating adjustment this.spinCfg._delay = window.setTimeout(function () { - adjust(); - // Repeat adjust at regular intervals + adjust(); // Repeat adjust at regular intervals + _this.spinCfg._repeat = window.setInterval(adjust, _this.spinCfg.interval); }, this.spinCfg.delay); } @@ -22033,16 +24281,26 @@ // Respond to up/down arrow keys. switch (e.keyCode) { case 38: - this.adjustValue(this.spinCfg.step);break; // Up + this.adjustValue(this.spinCfg.step); + break; + // Up + case 40: - this.adjustValue(-this.spinCfg.step);break; // Down + this.adjustValue(-this.spinCfg.step); + break; + // Down + case 33: - this.adjustValue(this.spinCfg.page);break; // PageUp + this.adjustValue(this.spinCfg.page); + break; + // PageUp + case 34: - this.adjustValue(-this.spinCfg.page);break; // PageDown + this.adjustValue(-this.spinCfg.page); + break; + // PageDown } }) - /* http://unixpapa.com/js/key.html describes the current state-of-affairs for key repeat events: @@ -22054,30 +24312,46 @@ // Respond to up/down arrow keys. switch (e.keyCode) { case 38: - this.adjustValue(this.spinCfg.step);break; // Up + this.adjustValue(this.spinCfg.step); + break; + // Up + case 40: - this.adjustValue(-this.spinCfg.step);break; // Down + this.adjustValue(-this.spinCfg.step); + break; + // Down + case 33: - this.adjustValue(this.spinCfg.page);break; // PageUp + this.adjustValue(this.spinCfg.page); + break; + // PageUp + case 34: - this.adjustValue(-this.spinCfg.page);break; // PageDown - } - // we always ignore the first keypress event (use the keydown instead) + this.adjustValue(-this.spinCfg.page); + break; + // PageDown + } // we always ignore the first keypress event (use the keydown instead) + } else { this.repeating = true; } - }) - - // clear the 'repeating' flag + }) // clear the 'repeating' flag .keyup(function (e) { this.repeating = false; + switch (e.keyCode) { case 38: // Up + case 40: // Down + case 33: // PageUp + case 34: // PageDown + case 13: - this.adjustValue(0);break; // Enter/Return + this.adjustValue(0); + break; + // Enter/Return } }).bind('mousewheel', function (e) { // Respond to mouse wheel in IE. (It returns up/dn motion in multiples of 120) @@ -22102,10 +24376,11 @@ } e.preventDefault(); - }, false); + }); } }); }; + return $; } @@ -22128,9 +24403,8 @@ * and the MIT License and is copyright A Beautiful Site, LLC. * */ - /** - * @callback module:jQueryContextMenu.jQueryContextMenuCallback + * @callback module:jQueryContextMenu.jQueryContextMenuListener * @param {string} href The `href` value after the first character (for bypassing an initial `#`) * @param {external:jQuery} srcElement The wrapped jQuery srcElement * @param {{x: Float, y: Float, docX: Float, docY: Float}} coords @@ -22145,135 +24419,149 @@ */ /** - * Adds {@link external:jQuery.fn.contextMenu}, {@link external:jQuery.fn.disableContextMenuItems}, {@link external:jQuery.fn.enableContextMenuItems}, {@link external:jQuery.fn.disableContextMenu}, {@link external:jQuery.fn.enableContextMenu}, {@link external:jQuery.fn.destroyContextMenu} + * Adds {@link external:jQuery.fn.contextMenu}, + * {@link external:jQuery.fn.disableContextMenuItems}, + * {@link external:jQuery.fn.enableContextMenuItems}, + * {@link external:jQuery.fn.disableContextMenu}, + * {@link external:jQuery.fn.enableContextMenu}, + * {@link external:jQuery.fn.destroyContextMenu}. * @function module:jQueryContextMenu.jQueryContextMenu * @param {external:jQuery} $ The jQuery object to wrap (with `contextMenu`, `disableContextMenuItems`, `enableContextMenuItems`, `disableContextMenu`, `enableContextMenu`, `destroyContextMenu`) * @returns {external:jQuery} */ + function jQueryContextMenu($) { var win = $(window); var doc = $(document); - $.extend($.fn, { /** * @memberof external:jQuery.fn * @param {module:jQueryContextMenu.jQueryContextMenuConfig} o - * @param {module:jQueryContextMenu.jQueryContextMenuCallback} callback + * @param {module:jQueryContextMenu.jQueryContextMenuListener} listener * @returns {external:jQuery} */ - contextMenu: function contextMenu(o, callback) { + contextMenu: function contextMenu(o, listener) { // Defaults if (o.menu === undefined) return false; if (o.inSpeed === undefined) o.inSpeed = 150; - if (o.outSpeed === undefined) o.outSpeed = 75; - // 0 needs to be -1 for expected results (no fade) + if (o.outSpeed === undefined) o.outSpeed = 75; // 0 needs to be -1 for expected results (no fade) + if (o.inSpeed === 0) o.inSpeed = -1; - if (o.outSpeed === 0) o.outSpeed = -1; - // Loop each context menu + if (o.outSpeed === 0) o.outSpeed = -1; // Loop each context menu + $(this).each(function () { var el = $(this); var offset = $(el).offset(); + var menu = $('#' + o.menu); // Add contextMenu class - var menu = $('#' + o.menu); + menu.addClass('contextMenu'); // Simulate a true right click - // Add contextMenu class - menu.addClass('contextMenu'); - // Simulate a true right click - $(this).bind('mousedown', function (e) { - var evt = e; + $(this).bind('mousedown', function (evt) { $(this).mouseup(function (e) { var srcElement = $(this); srcElement.unbind('mouseup'); - if (evt.button === 2 || o.allowLeft || evt.ctrlKey && isMac()) { - e.stopPropagation(); - // Hide context menus that may be showing + + if (!(evt.button === 2 || o.allowLeft || evt.ctrlKey && isMac())) { + return undefined; + } + + e.stopPropagation(); // Hide context menus that may be showing + + $('.contextMenu').hide(); // Get this context menu + + if (el.hasClass('disabled')) return false; // Detect mouse position + + var x = e.pageX, + y = e.pageY; + var xOff = win.width() - menu.width(), + yOff = win.height() - menu.height(); + if (x > xOff - 15) x = xOff - 15; + if (y > yOff - 30) y = yOff - 30; // 30 is needed to prevent scrollbars in FF + // Show the menu + + doc.unbind('click'); + menu.css({ + top: y, + left: x + }).fadeIn(o.inSpeed); // Hover events + + menu.find('A').mouseover(function () { + menu.find('LI.hover').removeClass('hover'); + $(this).parent().addClass('hover'); + }).mouseout(function () { + menu.find('LI.hover').removeClass('hover'); + }); // Keyboard + + doc.keypress(function (ev) { + switch (ev.keyCode) { + case 38: + // up + if (!menu.find('LI.hover').length) { + menu.find('LI:last').addClass('hover'); + } else { + menu.find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover'); + if (!menu.find('LI.hover').length) menu.find('LI:last').addClass('hover'); + } + + break; + + case 40: + // down + if (!menu.find('LI.hover').length) { + menu.find('LI:first').addClass('hover'); + } else { + menu.find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover'); + if (!menu.find('LI.hover').length) menu.find('LI:first').addClass('hover'); + } + + break; + + case 13: + // enter + menu.find('LI.hover A').trigger('click'); + break; + + case 27: + // esc + doc.trigger('click'); + break; + } + }); // When items are selected + + menu.find('A').unbind('mouseup'); + menu.find('LI:not(.disabled) A').mouseup(function () { + doc.unbind('click').unbind('keypress'); $('.contextMenu').hide(); - // Get this context menu - if (el.hasClass('disabled')) return false; + if (listener) { + listener($(this).attr('href').substr(1), $(srcElement), { + x: x - offset.left, + y: y - offset.top, + docX: x, + docY: y + }); + } - // Detect mouse position - var x = e.pageX, - y = e.pageY; + return false; + }); // Hide bindings - var xOff = win.width() - menu.width(), - yOff = win.height() - menu.height(); - - if (x > xOff - 15) x = xOff - 15; - if (y > yOff - 30) y = yOff - 30; // 30 is needed to prevent scrollbars in FF - - // Show the menu - doc.unbind('click'); - menu.css({ top: y, left: x }).fadeIn(o.inSpeed); - // Hover events - menu.find('A').mouseover(function () { - menu.find('LI.hover').removeClass('hover'); - $(this).parent().addClass('hover'); - }).mouseout(function () { - menu.find('LI.hover').removeClass('hover'); - }); - - // Keyboard - doc.keypress(function (e) { - switch (e.keyCode) { - case 38: - // up - if (!menu.find('LI.hover').length) { - menu.find('LI:last').addClass('hover'); - } else { - menu.find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover'); - if (!menu.find('LI.hover').length) menu.find('LI:last').addClass('hover'); - } - break; - case 40: - // down - if (!menu.find('LI.hover').length) { - menu.find('LI:first').addClass('hover'); - } else { - menu.find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover'); - if (!menu.find('LI.hover').length) menu.find('LI:first').addClass('hover'); - } - break; - case 13: - // enter - menu.find('LI.hover A').trigger('click'); - break; - case 27: - // esc - doc.trigger('click'); - break; - } - }); - - // When items are selected - menu.find('A').unbind('mouseup'); - menu.find('LI:not(.disabled) A').mouseup(function () { + setTimeout(function () { + // Delay for Mozilla + doc.click(function () { doc.unbind('click').unbind('keypress'); - $('.contextMenu').hide(); - // Callback - if (callback) { - callback($(this).attr('href').substr(1), $(srcElement), { x: x - offset.left, y: y - offset.top, docX: x, docY: y }); - } + menu.fadeOut(o.outSpeed); return false; }); - - // Hide bindings - setTimeout(function () { - // Delay for Mozilla - doc.click(function () { - doc.unbind('click').unbind('keypress'); - menu.fadeOut(o.outSpeed); - return false; - }); - }, 0); - } + }, 0); + return undefined; }); - }); + }); // Disable text selection - // Disable text selection if ($.browser.mozilla) { $('#' + o.menu).each(function () { - $(this).css({ MozUserSelect: 'none' }); + $(this).css({ + MozUserSelect: 'none' + }); }); } else if ($.browser.msie) { $('#' + o.menu).each(function () { @@ -22287,8 +24575,9 @@ return false; }); }); - } - // Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome) + } // Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome) + + $(el).add($('UL.contextMenu')).bind('contextmenu', function () { return false; }); @@ -22296,9 +24585,8 @@ return $(this); }, - /** - * Disable context menu items on the fly + * Disable context menu items on the fly. * @memberof external:jQuery.fn * @param {undefined|string} o Comma-separated * @returns {external:jQuery} @@ -22309,9 +24597,11 @@ $(this).find('LI').addClass('disabled'); return $(this); } + $(this).each(function () { if (o !== undefined) { var d = o.split(','); + for (var i = 0; i < d.length; i++) { $(this).find('A[href="' + d[i] + '"]').parent().addClass('disabled'); } @@ -22320,9 +24610,8 @@ return $(this); }, - /** - * Enable context menu items on the fly + * Enable context menu items on the fly. * @memberof external:jQuery.fn * @param {undefined|string} o Comma-separated * @returns {external:jQuery} @@ -22333,9 +24622,11 @@ $(this).find('LI.disabled').removeClass('disabled'); return $(this); } + $(this).each(function () { if (o !== undefined) { var d = o.split(','); + for (var i = 0; i < d.length; i++) { $(this).find('A[href="' + d[i] + '"]').parent().removeClass('disabled'); } @@ -22344,9 +24635,8 @@ return $(this); }, - /** - * Disable context menu(s) + * Disable context menu(s). * @memberof external:jQuery.fn * @returns {external:jQuery} */ @@ -22357,9 +24647,8 @@ return $(this); }, - /** - * Enable context menu(s) + * Enable context menu(s). * @memberof external:jQuery.fn * @returns {external:jQuery} */ @@ -22370,9 +24659,8 @@ return $(this); }, - /** - * Destroy context menu(s) + * Destroy context menu(s). * @memberof external:jQuery.fn * @returns {external:jQuery} */ @@ -22388,6 +24676,8 @@ return $; } + /* eslint-disable no-bitwise */ + /** * jPicker (Adapted from version 1.1.6) * @@ -22408,22 +24698,34 @@ /** * @external Math */ + /** * @memberof external:Math * @param {Float} value * @param {Float} precision * @returns {Float} */ - Math.precision = function (value, precision) { + function toFixedNumeric(value, precision) { if (precision === undefined) precision = 0; return Math.round(value * Math.pow(10, precision)) / Math.pow(10, precision); - }; + } + /** + * Whether a value is `null` or `undefined`. + * @param {Any} val + * @returns {boolean} + */ + + var isNullish$1 = function isNullish(val) { + return val === null || val === undefined; + }; /** * @function module:jPicker.jPicker * @param {external:jQuery} $ The jQuery object to wrap (with {@link external:jQuery.loadingStylesheets}, {@link external:jQuery.fn.$.fn.jPicker}, {@link external:jQuery.fn.$.fn.jPicker.defaults}) * @returns {external:jQuery} */ + + var jPicker = function jPicker($) { if (!$.loadingStylesheets) { /** @@ -22433,7 +24735,9 @@ */ $.loadingStylesheets = []; } + var stylesheet = 'jgraduate/css/jPicker.css'; + if (!$.loadingStylesheets.includes(stylesheet)) { $.loadingStylesheets.push(stylesheet); } @@ -22450,59 +24754,107 @@ /** * Encapsulate slider functionality for the ColorMap and ColorBar - - * could be useful to use a jQuery UI draggable for this with certain extensions + * could be useful to use a jQuery UI draggable for this with certain extensions. + * @memberof module:jPicker * @param {external:jQuery} bar * @param {module:jPicker.SliderOptions} options + * @returns {undefined} */ - function Slider(bar, options) { - var $this = this; + + + var Slider = function Slider(bar, options) { + _classCallCheck(this, Slider); + + var that = this; + /** + * Fire events on the supplied `context` + * @param {module:jPicker.JPickerInit} context + * @returns {undefined} + */ + function fireChangeEvents(context) { - for (var i = 0; i < changeEvents.length; i++) { - changeEvents[i].call($this, $this, context); - } + changeEvents.forEach(function (changeEvent) { + changeEvent.call(that, that, context); + }); } - // bind the mousedown to the bar not the arrow for quick snapping to the clicked location + /** + * Bind the mousedown to the bar not the arrow for quick snapping to the clicked location. + * @param {external:jQuery.Event} e + * @returns {undefined} + */ + + function mouseDown(e) { var off = bar.offset(); - offset = { l: off.left | 0, t: off.top | 0 }; - clearTimeout(timeout); - // using setTimeout for visual updates - once the style is updated the browser will re-render internally allowing the next Javascript to run + offset = { + l: off.left | 0, + t: off.top | 0 + }; + clearTimeout(timeout); // using setTimeout for visual updates - once the style is updated the browser will re-render internally allowing the next Javascript to run + timeout = setTimeout(function () { - setValuesFromMousePosition.call($this, e); - }, 0); - // Bind mousemove and mouseup event to the document so it responds when dragged of of the bar - we will unbind these when on mouseup to save processing + setValuesFromMousePosition.call(that, e); + }, 0); // Bind mousemove and mouseup event to the document so it responds when dragged of of the bar - we will unbind these when on mouseup to save processing + $(document).bind('mousemove', mouseMove).bind('mouseup', mouseUp); e.preventDefault(); // don't try to select anything or drag the image to the desktop } - // set the values as the mouse moves + /** + * Set the values as the mouse moves. + * @param {external:jQuery.Event} e + * @returns {false} + */ + + function mouseMove(e) { clearTimeout(timeout); timeout = setTimeout(function () { - setValuesFromMousePosition.call($this, e); + setValuesFromMousePosition.call(that, e); }, 0); e.stopPropagation(); e.preventDefault(); return false; } - // unbind the document events - they aren't needed when not dragging + /** + * Unbind the document events - they aren't needed when not dragging. + * @param {external:jQuery.Event} e + * @returns {false} + */ + + function mouseUp(e) { $(document).unbind('mouseup', mouseUp).unbind('mousemove', mouseMove); e.stopPropagation(); e.preventDefault(); return false; } - // calculate mouse position and set value within the current range + /** + * Calculate mouse position and set value within the current range. + * @param {Event} e + * @returns {undefined} + */ + + function setValuesFromMousePosition(e) { var barW = bar.w, // local copies for YUI compressor barH = bar.h; var locX = e.pageX - offset.l, - locY = e.pageY - offset.t; - // keep the arrow within the bounds of the bar + locY = e.pageY - offset.t; // keep the arrow within the bounds of the bar + if (locX < 0) locX = 0;else if (locX > barW) locX = barW; if (locY < 0) locY = 0;else if (locY > barH) locY = barH; - val.call($this, 'xy', { x: locX / barW * rangeX + minX, y: locY / barH * rangeY + minY }); + val.call(that, 'xy', { + x: locX / barW * rangeX + minX, + y: locY / barH * rangeY + minY + }); } + /** + * + * @returns {undefined} + */ + + function draw() { var barW = bar.w, barH = bar.h, @@ -22516,118 +24868,201 @@ // constrain to bounds if (x === maxX) arrowOffsetX = barW;else arrowOffsetX = x / rangeX * barW | 0; } + if (rangeY > 0) { // range is greater than zero // constrain to bounds if (y === maxY) arrowOffsetY = barH;else arrowOffsetY = y / rangeY * barH | 0; - } - // if arrow width is greater than bar width, center arrow and prevent horizontal dragging + } // if arrow width is greater than bar width, center arrow and prevent horizontal dragging + + if (arrowW >= barW) arrowOffsetX = (barW >> 1) - (arrowW >> 1); // number >> 1 - superfast bitwise divide by two and truncate (move bits over one bit discarding lowest) - else arrowOffsetX -= arrowW >> 1; - // if arrow height is greater than bar height, center arrow and prevent vertical dragging - if (arrowH >= barH) arrowOffsetY = (barH >> 1) - (arrowH >> 1);else arrowOffsetY -= arrowH >> 1; - // set the arrow position based on these offsets - arrow.css({ left: arrowOffsetX + 'px', top: arrowOffsetY + 'px' }); - }, 0); + else arrowOffsetX -= arrowW >> 1; // if arrow height is greater than bar height, center arrow and prevent vertical dragging + + if (arrowH >= barH) arrowOffsetY = (barH >> 1) - (arrowH >> 1);else arrowOffsetY -= arrowH >> 1; // set the arrow position based on these offsets + + arrow.css({ + left: arrowOffsetX + 'px', + top: arrowOffsetY + 'px' + }); + }); } + /** + * Get or set a value. + * @param {?("xy"|"x"|"y")} name + * @param {module:math.XYObject} value + * @param {module:jPicker.Slider} context + * @returns {module:math.XYObject|Float|undefined} + */ + + function val(name, value, context) { - var set$$1 = value !== undefined; - if (!set$$1) { - if (name === undefined || name == null) name = 'xy'; + var set = value !== undefined; + + if (!set) { + if (isNullish$1(name)) name = 'xy'; + switch (name.toLowerCase()) { case 'x': return x; + case 'y': return y; + case 'xy': default: - return { x: x, y: y }; + return { + x: x, + y: y + }; } } - if (context != null && context === $this) return; - var changed = false; - var newX = void 0, - newY = void 0; - if (name == null) name = 'xy'; + if (!isNullish$1(context) && context === that) return undefined; + var changed = false; + var newX, newY; + if (isNullish$1(name)) name = 'xy'; + switch (name.toLowerCase()) { case 'x': newX = value && (value.x && value.x | 0 || value | 0) || 0; break; + case 'y': newY = value && (value.y && value.y | 0 || value | 0) || 0; break; + case 'xy': default: newX = value && value.x && value.x | 0 || 0; newY = value && value.y && value.y | 0 || 0; break; } - if (newX != null) { + + if (!isNullish$1(newX)) { if (newX < minX) newX = minX;else if (newX > maxX) newX = maxX; + if (x !== newX) { x = newX; changed = true; } } - if (newY != null) { + + if (!isNullish$1(newY)) { if (newY < minY) newY = minY;else if (newY > maxY) newY = maxY; + if (y !== newY) { y = newY; changed = true; } } - changed && fireChangeEvents.call($this, context || $this); + + changed && fireChangeEvents.call(that, context || that); + return undefined; } + /** + * @typedef {PlainObject} module:jPicker.MinMaxRangeX + * @property {Float} minX + * @property {Float} maxX + * @property {Float} rangeX + */ + + /** + * @typedef {PlainObject} module:jPicker.MinMaxRangeY + * @property {Float} minY + * @property {Float} maxY + * @property {Float} rangeY + */ + + /** + * @typedef {module:jPicker.MinMaxRangeY|module:jPicker.MinMaxRangeX} module:jPicker.MinMaxRangeXY + */ + + /** + * + * @param {"minx"|"maxx"|"rangex"|"miny"|"maxy"|"rangey"|"all"} name + * @param {module:jPicker.MinMaxRangeXY} value + * @returns {module:jPicker.MinMaxRangeXY|module:jPicker.MinMaxRangeX|module:jPicker.MinMaxRangeY|undefined} + */ + + function range(name, value) { - var set$$1 = value !== undefined; - if (!set$$1) { - if (name === undefined || name == null) name = 'all'; + var set = value !== undefined; + + if (!set) { + if (isNullish$1(name)) name = 'all'; + switch (name.toLowerCase()) { case 'minx': return minX; + case 'maxx': return maxX; + case 'rangex': - return { minX: minX, maxX: maxX, rangeX: rangeX }; + return { + minX: minX, + maxX: maxX, + rangeX: rangeX + }; + case 'miny': return minY; + case 'maxy': return maxY; + case 'rangey': - return { minY: minY, maxY: maxY, rangeY: rangeY }; + return { + minY: minY, + maxY: maxY, + rangeY: rangeY + }; + case 'all': default: - return { minX: minX, maxX: maxX, rangeX: rangeX, minY: minY, maxY: maxY, rangeY: rangeY }; + return { + minX: minX, + maxX: maxX, + rangeX: rangeX, + minY: minY, + maxY: maxY, + rangeY: rangeY + }; } } + var // changed = false, - newMinX = void 0, - newMaxX = void 0, - newMinY = void 0, - newMaxY = void 0; - if (name == null) name = 'all'; + newMinX, newMaxX, newMinY, newMaxY; + if (isNullish$1(name)) name = 'all'; + switch (name.toLowerCase()) { case 'minx': newMinX = value && (value.minX && value.minX | 0 || value | 0) || 0; break; + case 'maxx': newMaxX = value && (value.maxX && value.maxX | 0 || value | 0) || 0; break; + case 'rangex': newMinX = value && value.minX && value.minX | 0 || 0; newMaxX = value && value.maxX && value.maxX | 0 || 0; break; + case 'miny': newMinY = value && (value.minY && value.minY | 0 || value | 0) || 0; break; + case 'maxy': newMaxY = value && (value.maxY && value.maxY | 0 || value | 0) || 0; break; + case 'rangey': newMinY = value && value.minY && value.minY | 0 || 0; newMaxY = value && value.maxY && value.maxY | 0 || 0; break; + case 'all': default: newMinX = value && value.minX && value.minX | 0 || 0; @@ -22636,33 +25071,60 @@ newMaxY = value && value.maxY && value.maxY | 0 || 0; break; } - if (newMinX != null && minX !== newMinX) { + + if (!isNullish$1(newMinX) && minX !== newMinX) { minX = newMinX; rangeX = maxX - minX; } - if (newMaxX != null && maxX !== newMaxX) { + + if (!isNullish$1(newMaxX) && maxX !== newMaxX) { maxX = newMaxX; rangeX = maxX - minX; } - if (newMinY != null && minY !== newMinY) { + + if (!isNullish$1(newMinY) && minY !== newMinY) { minY = newMinY; rangeY = maxY - minY; } - if (newMaxY != null && maxY !== newMaxY) { + + if (!isNullish$1(newMaxY) && maxY !== newMaxY) { maxY = newMaxY; rangeY = maxY - minY; } + + return undefined; } + /** + * @param {GenericCallback} callback + * @returns {undefined} + */ + + function bind(callback) { + // eslint-disable-line promise/prefer-await-to-callbacks if (typeof callback === 'function') changeEvents.push(callback); } + /** + * @param {GenericCallback} callback + * @returns {undefined} + */ + + function unbind(callback) { + // eslint-disable-line promise/prefer-await-to-callbacks if (typeof callback !== 'function') return; - var i = void 0; + var i; + while (i = changeEvents.includes(callback)) { changeEvents.splice(i, 1); } } + /** + * + * @returns {undefined} + */ + + function destroy() { // unbind all possible events and null objects $(document).unbind('mouseup', mouseUp).unbind('mousemove', mouseMove); @@ -22671,8 +25133,9 @@ arrow = null; changeEvents = null; } - var offset = void 0, - timeout = void 0, + + var offset, + timeout, x = 0, y = 0, minX = 0, @@ -22684,197 +25147,285 @@ arrow = bar.find('img:first'), // the arrow image to drag changeEvents = []; - - $.extend(true, $this, // public properties, methods, and event bindings - these we need to access from other controls - { + $.extend(true, // public properties, methods, and event bindings - these we need + // to access from other controls + that, { val: val, range: range, bind: bind, unbind: unbind, destroy: destroy - }); - // initialize this control + }); // initialize this control + arrow.src = options.arrow && options.arrow.image; arrow.w = options.arrow && options.arrow.width || arrow.width(); arrow.h = options.arrow && options.arrow.height || arrow.height(); bar.w = options.map && options.map.width || bar.width(); - bar.h = options.map && options.map.height || bar.height(); - // bind mousedown event + bar.h = options.map && options.map.height || bar.height(); // bind mousedown event + bar.bind('mousedown', mouseDown); - bind.call($this, draw); - } - // controls for all the input elements for the typing in color values - function ColorValuePicker(picker, color, bindedHex, alphaPrecision) { - var $this = this; // private properties and methods - var inputs = picker.find('td.Text input'); - // input box key down - use arrows to alter color + bind.call(that, draw); + }; + /** + * Controls for all the input elements for the typing in color values. + * @param {external:jQuery} picker + * @param {external:jQuery.jPicker.Color} color + * @param {external:jQuery.fn.$.fn.jPicker} bindedHex + * @param {Float} alphaPrecision + * @constructor + */ + + + var ColorValuePicker = function ColorValuePicker(picker, color, bindedHex, alphaPrecision) { + _classCallCheck(this, ColorValuePicker); + + var that = this; // private properties and methods + + var inputs = picker.find('td.Text input'); // input box key down - use arrows to alter color + + /** + * + * @param {Event} e + * @returns {Event|false|undefined} + */ + function keyDown(e) { - if (e.target.value === '' && e.target !== hex.get(0) && (bindedHex != null && e.target !== bindedHex.get(0) || bindedHex == null)) return; + if (e.target.value === '' && e.target !== hex.get(0) && (!isNullish$1(bindedHex) && e.target !== bindedHex.get(0) || isNullish$1(bindedHex))) return undefined; if (!validateKey(e)) return e; + switch (e.target) { case red.get(0): switch (e.keyCode) { case 38: - red.val(setValueInRange.call($this, (red.val() << 0) + 1, 0, 255)); + red.val(setValueInRange.call(that, (red.val() << 0) + 1, 0, 255)); color.val('r', red.val(), e.target); return false; + case 40: - red.val(setValueInRange.call($this, (red.val() << 0) - 1, 0, 255)); + red.val(setValueInRange.call(that, (red.val() << 0) - 1, 0, 255)); color.val('r', red.val(), e.target); return false; } + break; + case green.get(0): switch (e.keyCode) { case 38: - green.val(setValueInRange.call($this, (green.val() << 0) + 1, 0, 255)); + green.val(setValueInRange.call(that, (green.val() << 0) + 1, 0, 255)); color.val('g', green.val(), e.target); return false; + case 40: - green.val(setValueInRange.call($this, (green.val() << 0) - 1, 0, 255)); + green.val(setValueInRange.call(that, (green.val() << 0) - 1, 0, 255)); color.val('g', green.val(), e.target); return false; } + break; + case blue.get(0): switch (e.keyCode) { case 38: - blue.val(setValueInRange.call($this, (blue.val() << 0) + 1, 0, 255)); + blue.val(setValueInRange.call(that, (blue.val() << 0) + 1, 0, 255)); color.val('b', blue.val(), e.target); return false; + case 40: - blue.val(setValueInRange.call($this, (blue.val() << 0) - 1, 0, 255)); + blue.val(setValueInRange.call(that, (blue.val() << 0) - 1, 0, 255)); color.val('b', blue.val(), e.target); return false; } + break; + case alpha && alpha.get(0): switch (e.keyCode) { case 38: - alpha.val(setValueInRange.call($this, parseFloat(alpha.val()) + 1, 0, 100)); - color.val('a', Math.precision(alpha.val() * 255 / 100, alphaPrecision), e.target); + alpha.val(setValueInRange.call(that, parseFloat(alpha.val()) + 1, 0, 100)); + color.val('a', toFixedNumeric(alpha.val() * 255 / 100, alphaPrecision), e.target); return false; + case 40: - alpha.val(setValueInRange.call($this, parseFloat(alpha.val()) - 1, 0, 100)); - color.val('a', Math.precision(alpha.val() * 255 / 100, alphaPrecision), e.target); + alpha.val(setValueInRange.call(that, parseFloat(alpha.val()) - 1, 0, 100)); + color.val('a', toFixedNumeric(alpha.val() * 255 / 100, alphaPrecision), e.target); return false; } + break; + case hue.get(0): switch (e.keyCode) { case 38: - hue.val(setValueInRange.call($this, (hue.val() << 0) + 1, 0, 360)); + hue.val(setValueInRange.call(that, (hue.val() << 0) + 1, 0, 360)); color.val('h', hue.val(), e.target); return false; + case 40: - hue.val(setValueInRange.call($this, (hue.val() << 0) - 1, 0, 360)); + hue.val(setValueInRange.call(that, (hue.val() << 0) - 1, 0, 360)); color.val('h', hue.val(), e.target); return false; } + break; + case saturation.get(0): switch (e.keyCode) { case 38: - saturation.val(setValueInRange.call($this, (saturation.val() << 0) + 1, 0, 100)); + saturation.val(setValueInRange.call(that, (saturation.val() << 0) + 1, 0, 100)); color.val('s', saturation.val(), e.target); return false; + case 40: - saturation.val(setValueInRange.call($this, (saturation.val() << 0) - 1, 0, 100)); + saturation.val(setValueInRange.call(that, (saturation.val() << 0) - 1, 0, 100)); color.val('s', saturation.val(), e.target); return false; } + break; + case value.get(0): switch (e.keyCode) { case 38: - value.val(setValueInRange.call($this, (value.val() << 0) + 1, 0, 100)); + value.val(setValueInRange.call(that, (value.val() << 0) + 1, 0, 100)); color.val('v', value.val(), e.target); return false; + case 40: - value.val(setValueInRange.call($this, (value.val() << 0) - 1, 0, 100)); + value.val(setValueInRange.call(that, (value.val() << 0) - 1, 0, 100)); color.val('v', value.val(), e.target); return false; } + break; } - } - // input box key up - validate value and set color + + return undefined; + } // input box key up - validate value and set color + + /** + * @param {Event} e + * @returns {Event|undefined} + * @todo Why is this returning an event? + */ + + function keyUp(e) { - if (e.target.value === '' && e.target !== hex.get(0) && (bindedHex != null && e.target !== bindedHex.get(0) || bindedHex == null)) return; + if (e.target.value === '' && e.target !== hex.get(0) && (!isNullish$1(bindedHex) && e.target !== bindedHex.get(0) || isNullish$1(bindedHex))) return undefined; if (!validateKey(e)) return e; + switch (e.target) { case red.get(0): - red.val(setValueInRange.call($this, red.val(), 0, 255)); + red.val(setValueInRange.call(that, red.val(), 0, 255)); color.val('r', red.val(), e.target); break; + case green.get(0): - green.val(setValueInRange.call($this, green.val(), 0, 255)); + green.val(setValueInRange.call(that, green.val(), 0, 255)); color.val('g', green.val(), e.target); break; + case blue.get(0): - blue.val(setValueInRange.call($this, blue.val(), 0, 255)); + blue.val(setValueInRange.call(that, blue.val(), 0, 255)); color.val('b', blue.val(), e.target); break; + case alpha && alpha.get(0): - alpha.val(setValueInRange.call($this, alpha.val(), 0, 100)); - color.val('a', Math.precision(alpha.val() * 255 / 100, alphaPrecision), e.target); + alpha.val(setValueInRange.call(that, alpha.val(), 0, 100)); + color.val('a', toFixedNumeric(alpha.val() * 255 / 100, alphaPrecision), e.target); break; + case hue.get(0): - hue.val(setValueInRange.call($this, hue.val(), 0, 360)); + hue.val(setValueInRange.call(that, hue.val(), 0, 360)); color.val('h', hue.val(), e.target); break; + case saturation.get(0): - saturation.val(setValueInRange.call($this, saturation.val(), 0, 100)); + saturation.val(setValueInRange.call(that, saturation.val(), 0, 100)); color.val('s', saturation.val(), e.target); break; + case value.get(0): - value.val(setValueInRange.call($this, value.val(), 0, 100)); + value.val(setValueInRange.call(that, value.val(), 0, 100)); color.val('v', value.val(), e.target); break; + case hex.get(0): hex.val(hex.val().replace(/[^a-fA-F0-9]/g, '').toLowerCase().substring(0, 6)); bindedHex && bindedHex.val(hex.val()); color.val('hex', hex.val() !== '' ? hex.val() : null, e.target); break; + case bindedHex && bindedHex.get(0): bindedHex.val(bindedHex.val().replace(/[^a-fA-F0-9]/g, '').toLowerCase().substring(0, 6)); hex.val(bindedHex.val()); color.val('hex', bindedHex.val() !== '' ? bindedHex.val() : null, e.target); break; + case ahex && ahex.get(0): ahex.val(ahex.val().replace(/[^a-fA-F0-9]/g, '').toLowerCase().substring(0, 2)); - color.val('a', ahex.val() != null ? parseInt(ahex.val(), 16) : null, e.target); + color.val('a', !isNullish$1(ahex.val()) ? parseInt(ahex.val(), 16) : null, e.target); break; } - } - // input box blur - reset to original if value empty + + return undefined; + } // input box blur - reset to original if value empty + + /** + * @param {Event} e + * @returns {undefined} + */ + + function blur(e) { - if (color.val() != null) { + if (!isNullish$1(color.val())) { switch (e.target) { case red.get(0): - red.val(color.val('r'));break; + red.val(color.val('r')); + break; + case green.get(0): - green.val(color.val('g'));break; + green.val(color.val('g')); + break; + case blue.get(0): - blue.val(color.val('b'));break; + blue.val(color.val('b')); + break; + case alpha && alpha.get(0): - alpha.val(Math.precision(color.val('a') * 100 / 255, alphaPrecision));break; + alpha.val(toFixedNumeric(color.val('a') * 100 / 255, alphaPrecision)); + break; + case hue.get(0): - hue.val(color.val('h'));break; + hue.val(color.val('h')); + break; + case saturation.get(0): - saturation.val(color.val('s'));break; + saturation.val(color.val('s')); + break; + case value.get(0): - value.val(color.val('v'));break; + value.val(color.val('v')); + break; + case hex.get(0): case bindedHex && bindedHex.get(0): hex.val(color.val('hex')); bindedHex && bindedHex.val(color.val('hex')); break; + case ahex && ahex.get(0): - ahex.val(color.val('ahex').substring(6));break; + ahex.val(color.val('ahex').substring(6)); + break; } } } + /** + * @param {Event} e + * @returns {boolean} + */ + + function validateKey(e) { switch (e.keyCode) { case 9: @@ -22883,34 +25434,56 @@ case 37: case 39: return false; + case 'c'.charCodeAt(): case 'v'.charCodeAt(): if (e.ctrlKey) return false; } + return true; } - // constrain value within range + /** + * Constrain value within range. + * @param {Float|string} value + * @param {Float} min + * @param {Float} max + * @returns {Float|string} Returns a number or numeric string + */ + + function setValueInRange(value, min, max) { if (value === '' || isNaN(value)) return min; if (value > max) return max; if (value < min) return min; return value; } + /** + * @param {external:jQuery} ui + * @param {Element} context + * @returns {undefined} + */ + + function colorChanged(ui, context) { var all = ui.val('all'); - if (context !== red.get(0)) red.val(all != null ? all.r : ''); - if (context !== green.get(0)) green.val(all != null ? all.g : ''); - if (context !== blue.get(0)) blue.val(all != null ? all.b : ''); - if (alpha && context !== alpha.get(0)) alpha.val(all != null ? Math.precision(all.a * 100 / 255, alphaPrecision) : ''); - if (context !== hue.get(0)) hue.val(all != null ? all.h : ''); - if (context !== saturation.get(0)) saturation.val(all != null ? all.s : ''); - if (context !== value.get(0)) value.val(all != null ? all.v : ''); - if (context !== hex.get(0) && (bindedHex && context !== bindedHex.get(0) || !bindedHex)) hex.val(all != null ? all.hex : ''); - if (bindedHex && context !== bindedHex.get(0) && context !== hex.get(0)) bindedHex.val(all != null ? all.hex : ''); - if (ahex && context !== ahex.get(0)) ahex.val(all != null ? all.ahex.substring(6) : ''); + if (context !== red.get(0)) red.val(!isNullish$1(all) ? all.r : ''); + if (context !== green.get(0)) green.val(!isNullish$1(all) ? all.g : ''); + if (context !== blue.get(0)) blue.val(!isNullish$1(all) ? all.b : ''); + if (alpha && context !== alpha.get(0)) alpha.val(!isNullish$1(all) ? toFixedNumeric(all.a * 100 / 255, alphaPrecision) : ''); + if (context !== hue.get(0)) hue.val(!isNullish$1(all) ? all.h : ''); + if (context !== saturation.get(0)) saturation.val(!isNullish$1(all) ? all.s : ''); + if (context !== value.get(0)) value.val(!isNullish$1(all) ? all.v : ''); + if (context !== hex.get(0) && (bindedHex && context !== bindedHex.get(0) || !bindedHex)) hex.val(!isNullish$1(all) ? all.hex : ''); + if (bindedHex && context !== bindedHex.get(0) && context !== hex.get(0)) bindedHex.val(!isNullish$1(all) ? all.hex : ''); + if (ahex && context !== ahex.get(0)) ahex.val(!isNullish$1(all) ? all.ahex.substring(6) : ''); } + /** + * Unbind all events and null objects. + * @returns {undefined} + */ + + function destroy() { - // unbind all events and null objects red.add(green).add(blue).add(alpha).add(hue).add(saturation).add(value).add(hex).add(bindedHex).add(ahex).unbind('keyup', keyUp).unbind('blur', blur); red.add(green).add(blue).add(alpha).add(hue).add(saturation).add(value).unbind('keydown', keyDown); color.unbind(colorChanged); @@ -22924,6 +25497,7 @@ hex = null; ahex = null; } + var red = inputs.eq(3), green = inputs.eq(4), blue = inputs.eq(5), @@ -22933,38 +25507,42 @@ value = inputs.eq(2), hex = inputs.eq(inputs.length > 7 ? 7 : 6), ahex = inputs.length > 7 ? inputs.eq(8) : null; - $.extend(true, $this, { + $.extend(true, that, { // public properties and methods destroy: destroy }); red.add(green).add(blue).add(alpha).add(hue).add(saturation).add(value).add(hex).add(bindedHex).add(ahex).bind('keyup', keyUp).bind('blur', blur); red.add(green).add(blue).add(alpha).add(hue).add(saturation).add(value).bind('keydown', keyDown); color.bind(colorChanged); - } - + }; /** * @typedef {PlainObject} module:jPicker.JPickerInit - * @property {Integer} a - * @property {Integer} b - * @property {Integer} g - * @property {Integer} h - * @property {Integer} r - * @property {Integer} s - * @property {Integer} v - * @property {string} hex - * @property {string} ahex + * @property {Integer} [a] + * @property {Integer} [b] + * @property {Integer} [g] + * @property {Integer} [h] + * @property {Integer} [r] + * @property {Integer} [s] + * @property {Integer} [v] + * @property {string} [hex] + * @property {string} [ahex] */ /** * @namespace {PlainObject} jPicker * @memberof external:jQuery */ - $.jPicker = /** @lends external:jQuery.jPicker */{ + + + $.jPicker = + /** @lends external:jQuery.jPicker */ + { /** * Array holding references to each active instance of the jPicker control * @type {external:jQuery.fn.$.fn.jPicker[]} */ List: [], + /** * Color object - we will be able to assign by any color space type or * retrieve any color space info. @@ -22977,257 +25555,381 @@ * @param {module:jPicker.JPickerInit} init */ Color: function Color(init) { - var $this = this; + // eslint-disable-line object-shorthand + var that = this; + /** + * + * @param {module:jPicker.Slider} context + * @returns {undefined} + */ + function fireChangeEvents(context) { for (var i = 0; i < changeEvents.length; i++) { - changeEvents[i].call($this, $this, context); + changeEvents[i].call(that, that, context); } } + /** + * @param {string|"ahex"|"hex"|"all"|""|null|undefined} name String composed of letters "r", "g", "b", "a", "h", "s", and/or "v" + * @param {module:jPicker.RGBA|module:jPicker.JPickerInit|string} [value] + * @param {external:jQuery.jPicker.Color} context + * @returns {module:jPicker.JPickerInit|string|null|undefined} + */ + + function val(name, value, context) { // Kind of ugly - var set$$1 = Boolean(value); - if (set$$1 && value.ahex === '') value.ahex = '00000000'; - if (!set$$1) { - if (name === undefined || name == null || name === '') name = 'all'; - if (r == null) return null; + var set = Boolean(value); + if (set && value.ahex === '') value.ahex = '00000000'; + + if (!set) { + var ret; + if (isNullish$1(name) || name === '') name = 'all'; + if (isNullish$1(r)) return null; + switch (name.toLowerCase()) { case 'ahex': - return ColorMethods.rgbaToHex({ r: r, g: g, b: b, a: a }); + return ColorMethods.rgbaToHex({ + r: r, + g: g, + b: b, + a: a + }); + case 'hex': return val('ahex').substring(0, 6); - case 'all': - return { r: r, g: g, b: b, a: a, h: h, s: s, v: v, hex: val.call($this, 'hex'), ahex: val.call($this, 'ahex') }; - default: - var ret = {}; - for (var i = 0; i < name.length; i++) { - switch (name.charAt(i)) { - case 'r': - if (name.length === 1) ret = r;else ret.r = r; - break; - case 'g': - if (name.length === 1) ret = g;else ret.g = g; - break; - case 'b': - if (name.length === 1) ret = b;else ret.b = b; - break; - case 'a': - if (name.length === 1) ret = a;else ret.a = a; - break; - case 'h': - if (name.length === 1) ret = h;else ret.h = h; - break; - case 's': - if (name.length === 1) ret = s;else ret.s = s; - break; - case 'v': - if (name.length === 1) ret = v;else ret.v = v; - break; - } - } - return !name.length ? val.call($this, 'all') : ret; - } - } - if (context != null && context === $this) return; - if (name == null) name = ''; + case 'all': + return { + r: r, + g: g, + b: b, + a: a, + h: h, + s: s, + v: v, + hex: val.call(that, 'hex'), + ahex: val.call(that, 'ahex') + }; + + default: + { + ret = {}; + var nameLength = name.length; + + _toConsumableArray(name).forEach(function (ch) { + switch (ch) { + case 'r': + if (nameLength === 1) ret = r;else ret.r = r; + break; + + case 'g': + if (nameLength === 1) ret = g;else ret.g = g; + break; + + case 'b': + if (nameLength === 1) ret = b;else ret.b = b; + break; + + case 'a': + if (nameLength === 1) ret = a;else ret.a = a; + break; + + case 'h': + if (nameLength === 1) ret = h;else ret.h = h; + break; + + case 's': + if (nameLength === 1) ret = s;else ret.s = s; + break; + + case 'v': + if (nameLength === 1) ret = v;else ret.v = v; + break; + } + }); + } + } + + return _typeof(ret) === 'object' && !Object.keys(ret).length ? val.call(that, 'all') : ret; + } + + if (!isNullish$1(context) && context === that) return undefined; + if (isNullish$1(name)) name = ''; var changed = false; - if (value == null) { - if (r != null) { + + if (isNullish$1(value)) { + if (!isNullish$1(r)) { r = null; changed = true; } - if (g != null) { + + if (!isNullish$1(g)) { g = null; changed = true; } - if (b != null) { + + if (!isNullish$1(b)) { b = null; changed = true; } - if (a != null) { + + if (!isNullish$1(a)) { a = null; changed = true; } - if (h != null) { + + if (!isNullish$1(h)) { h = null; changed = true; } - if (s != null) { + + if (!isNullish$1(s)) { s = null; changed = true; } - if (v != null) { + + if (!isNullish$1(v)) { v = null; changed = true; } - changed && fireChangeEvents.call($this, context || $this); - return; + + changed && fireChangeEvents.call(that, context || that); + return undefined; } + switch (name.toLowerCase()) { case 'ahex': case 'hex': - var _ret = ColorMethods.hexToRgba(value && (value.ahex || value.hex) || value || 'none'); - val.call($this, 'rgba', { r: _ret.r, g: _ret.g, b: _ret.b, a: name === 'ahex' ? _ret.a : a != null ? a : 255 }, context); - break; + { + var _ret = ColorMethods.hexToRgba(value && (value.ahex || value.hex) || value || 'none'); + + val.call(that, 'rgba', { + r: _ret.r, + g: _ret.g, + b: _ret.b, + a: name === 'ahex' ? _ret.a : !isNullish$1(a) ? a : 255 + }, context); + break; + } + default: - if (value && (value.ahex != null || value.hex != null)) { - val.call($this, 'ahex', value.ahex || value.hex || '00000000', context); - return; - } - var newV = {}; - var rgb = false, - hsv = false; - if (value.r !== undefined && !name.includes('r')) name += 'r'; - if (value.g !== undefined && !name.includes('g')) name += 'g'; - if (value.b !== undefined && !name.includes('b')) name += 'b'; - if (value.a !== undefined && !name.includes('a')) name += 'a'; - if (value.h !== undefined && !name.includes('h')) name += 'h'; - if (value.s !== undefined && !name.includes('s')) name += 's'; - if (value.v !== undefined && !name.includes('v')) name += 'v'; - for (var _i = 0; _i < name.length; _i++) { - switch (name.charAt(_i)) { - case 'r': - if (hsv) continue; - rgb = true; - newV.r = value && value.r && value.r | 0 || value && value | 0 || 0; - if (newV.r < 0) newV.r = 0;else if (newV.r > 255) newV.r = 255; - if (r !== newV.r) { - r = newV.r; - - changed = true; - } - break; - case 'g': - if (hsv) continue; - rgb = true; - newV.g = value && value.g && value.g | 0 || value && value | 0 || 0; - if (newV.g < 0) newV.g = 0;else if (newV.g > 255) newV.g = 255; - if (g !== newV.g) { - g = newV.g; - - changed = true; - } - break; - case 'b': - if (hsv) continue; - rgb = true; - newV.b = value && value.b && value.b | 0 || value && value | 0 || 0; - if (newV.b < 0) newV.b = 0;else if (newV.b > 255) newV.b = 255; - if (b !== newV.b) { - b = newV.b; - - changed = true; - } - break; - case 'a': - newV.a = value && value.a != null ? value.a | 0 : value != null ? value | 0 : 255; - if (newV.a < 0) newV.a = 0;else if (newV.a > 255) newV.a = 255; - if (a !== newV.a) { - a = newV.a; - - changed = true; - } - break; - case 'h': - if (rgb) continue; - hsv = true; - newV.h = value && value.h && value.h | 0 || value && value | 0 || 0; - if (newV.h < 0) newV.h = 0;else if (newV.h > 360) newV.h = 360; - if (h !== newV.h) { - h = newV.h; - - changed = true; - } - break; - case 's': - if (rgb) continue; - hsv = true; - newV.s = value && value.s != null ? value.s | 0 : value != null ? value | 0 : 100; - if (newV.s < 0) newV.s = 0;else if (newV.s > 100) newV.s = 100; - if (s !== newV.s) { - s = newV.s; - - changed = true; - } - break; - case 'v': - if (rgb) continue; - hsv = true; - newV.v = value && value.v != null ? value.v | 0 : value != null ? value | 0 : 100; - if (newV.v < 0) newV.v = 0;else if (newV.v > 100) newV.v = 100; - if (v !== newV.v) { - v = newV.v; - - changed = true; - } - break; + { + if (value && (!isNullish$1(value.ahex) || !isNullish$1(value.hex))) { + val.call(that, 'ahex', value.ahex || value.hex || '00000000', context); + return undefined; } - } - if (changed) { - if (rgb) { - r = r || 0; - g = g || 0; - b = b || 0; - var _ret2 = ColorMethods.rgbToHsv({ r: r, g: g, b: b }); - h = _ret2.h; - s = _ret2.s; - v = _ret2.v; - } else if (hsv) { - h = h || 0; - s = s != null ? s : 100; - v = v != null ? v : 100; - var _ret3 = ColorMethods.hsvToRgb({ h: h, s: s, v: v }); - r = _ret3.r; - g = _ret3.g; - b = _ret3.b; + + var newV = {}; + var rgb = false, + hsv = false; + if (value.r !== undefined && !name.includes('r')) name += 'r'; + if (value.g !== undefined && !name.includes('g')) name += 'g'; + if (value.b !== undefined && !name.includes('b')) name += 'b'; + if (value.a !== undefined && !name.includes('a')) name += 'a'; + if (value.h !== undefined && !name.includes('h')) name += 'h'; + if (value.s !== undefined && !name.includes('s')) name += 's'; + if (value.v !== undefined && !name.includes('v')) name += 'v'; + + _toConsumableArray(name).forEach(function (ch) { + switch (ch) { + case 'r': + if (hsv) return; + rgb = true; + newV.r = value.r && value.r | 0 || value | 0 || 0; + if (newV.r < 0) newV.r = 0;else if (newV.r > 255) newV.r = 255; + + if (r !== newV.r) { + r = newV.r; + changed = true; + } + + break; + + case 'g': + if (hsv) return; + rgb = true; + newV.g = value && value.g && value.g | 0 || value && value | 0 || 0; + if (newV.g < 0) newV.g = 0;else if (newV.g > 255) newV.g = 255; + + if (g !== newV.g) { + g = newV.g; + changed = true; + } + + break; + + case 'b': + if (hsv) return; + rgb = true; + newV.b = value && value.b && value.b | 0 || value && value | 0 || 0; + if (newV.b < 0) newV.b = 0;else if (newV.b > 255) newV.b = 255; + + if (b !== newV.b) { + b = newV.b; + changed = true; + } + + break; + + case 'a': + newV.a = value && !isNullish$1(value.a) ? value.a | 0 : value | 0; + if (newV.a < 0) newV.a = 0;else if (newV.a > 255) newV.a = 255; + + if (a !== newV.a) { + a = newV.a; + changed = true; + } + + break; + + case 'h': + if (rgb) return; + hsv = true; + newV.h = value && value.h && value.h | 0 || value && value | 0 || 0; + if (newV.h < 0) newV.h = 0;else if (newV.h > 360) newV.h = 360; + + if (h !== newV.h) { + h = newV.h; + changed = true; + } + + break; + + case 's': + if (rgb) return; + hsv = true; + newV.s = !isNullish$1(value.s) ? value.s | 0 : value | 0; + if (newV.s < 0) newV.s = 0;else if (newV.s > 100) newV.s = 100; + + if (s !== newV.s) { + s = newV.s; + changed = true; + } + + break; + + case 'v': + if (rgb) return; + hsv = true; + newV.v = !isNullish$1(value.v) ? value.v | 0 : value | 0; + if (newV.v < 0) newV.v = 0;else if (newV.v > 100) newV.v = 100; + + if (v !== newV.v) { + v = newV.v; + changed = true; + } + + break; + } + }); + + if (changed) { + if (rgb) { + r = r || 0; + g = g || 0; + b = b || 0; + + var _ret2 = ColorMethods.rgbToHsv({ + r: r, + g: g, + b: b + }); + + h = _ret2.h; + s = _ret2.s; + v = _ret2.v; + } else if (hsv) { + h = h || 0; + s = !isNullish$1(s) ? s : 100; + v = !isNullish$1(v) ? v : 100; + + var _ret3 = ColorMethods.hsvToRgb({ + h: h, + s: s, + v: v + }); + + r = _ret3.r; + g = _ret3.g; + b = _ret3.b; + } + + a = !isNullish$1(a) ? a : 255; + fireChangeEvents.call(that, context || that); } - a = a != null ? a : 255; - fireChangeEvents.call($this, context || $this); + + break; } - break; } + + return undefined; } + /** + * @param {GenericCallback} callback + * @returns {undefined} + */ + + function bind(callback) { + // eslint-disable-line promise/prefer-await-to-callbacks if (typeof callback === 'function') changeEvents.push(callback); } + /** + * @param {GenericCallback} callback + * @returns {undefined} + */ + + function unbind(callback) { + // eslint-disable-line promise/prefer-await-to-callbacks if (typeof callback !== 'function') return; - var i = void 0; + var i; + while (i = changeEvents.includes(callback)) { changeEvents.splice(i, 1); } } + /** + * Unset `changeEvents` + * @returns {undefined} + */ + + function destroy() { changeEvents = null; } - var r = void 0, - g = void 0, - b = void 0, - a = void 0, - h = void 0, - s = void 0, - v = void 0, - changeEvents = []; - $.extend(true, $this, { + var r, + g, + b, + a, + h, + s, + v, + changeEvents = []; + $.extend(true, that, { // public properties and methods val: val, bind: bind, unbind: unbind, destroy: destroy }); + if (init) { - if (init.ahex != null) { + if (!isNullish$1(init.ahex)) { val('ahex', init); - } else if (init.hex != null) { - val((init.a != null ? 'a' : '') + 'hex', init.a != null ? { ahex: init.hex + ColorMethods.intToHex(init.a) } : init); - } else if (init.r != null && init.g != null && init.b != null) { - val('rgb' + (init.a != null ? 'a' : ''), init); - } else if (init.h != null && init.s != null && init.v != null) { - val('hsv' + (init.a != null ? 'a' : ''), init); + } else if (!isNullish$1(init.hex)) { + val((!isNullish$1(init.a) ? 'a' : '') + 'hex', !isNullish$1(init.a) ? { + ahex: init.hex + ColorMethods.intToHex(init.a) + } : init); + } else if (!isNullish$1(init.r) && !isNullish$1(init.g) && !isNullish$1(init.b)) { + val('rgb' + (!isNullish$1(init.a) ? 'a' : ''), init); + } else if (!isNullish$1(init.h) && !isNullish$1(init.s) && !isNullish$1(init.v)) { + val('hsv' + (!isNullish$1(init.a) ? 'a' : ''), init); } } }, + /** * color conversion methods - make public to give use to external scripts * @namespace @@ -23240,24 +25942,32 @@ * @property {Integer} b * @property {Integer} a */ + /** * @typedef {PlainObject} module:jPicker.RGB * @property {Integer} r * @property {Integer} g * @property {Integer} b */ + /** * @param {string} hex * @returns {module:jPicker.RGBA} */ hexToRgba: function hexToRgba(hex) { - if (hex === '' || hex === 'none') return { r: null, g: null, b: null, a: null }; + if (hex === '' || hex === 'none') return { + r: null, + g: null, + b: null, + a: null + }; hex = this.validateHex(hex); var r = '00', g = '00', b = '00', a = '255'; if (hex.length === 6) hex += 'ff'; + if (hex.length > 6) { r = hex.substring(0, 2); g = hex.substring(2, 4); @@ -23268,14 +25978,20 @@ r = hex.substring(4, hex.length); hex = hex.substring(0, 4); } + if (hex.length > 2) { g = hex.substring(2, hex.length); hex = hex.substring(0, 2); } + if (hex.length > 0) b = hex.substring(0, hex.length); } + return { - r: this.hexToInt(r), g: this.hexToInt(g), b: this.hexToInt(b), a: this.hexToInt(a) + r: this.hexToInt(r), + g: this.hexToInt(g), + b: this.hexToInt(b), + a: this.hexToInt(a) }; }, @@ -23322,6 +26038,7 @@ * @property {Integer} s * @property {Integer} v */ + /** * @param {module:jPicker.RGB} rgb * @returns {module:jPicker.HSV} @@ -23330,9 +26047,14 @@ var r = rgb.r / 255, g = rgb.g / 255, b = rgb.b / 255, - hsv = { h: 0, s: 0, v: 0 }; + hsv = { + h: 0, + s: 0, + v: 0 + }; var min = 0, max = 0; + if (r >= g && r >= b) { max = r; min = g > b ? b : g; @@ -23343,9 +26065,10 @@ max = b; min = g > r ? r : g; } + hsv.v = max; hsv.s = max ? (max - min) / max : 0; - var delta = void 0; + var delta; if (!hsv.s) hsv.h = 0;else { delta = max - min; if (r === max) hsv.h = (g - b) / delta;else if (g === max) hsv.h = 2 + (b - r) / delta;else hsv.h = 4 + (r - g) / delta; @@ -23362,7 +26085,12 @@ * @returns {module:jPicker.RGB} */ hsvToRgb: function hsvToRgb(hsv) { - var rgb = { r: 0, g: 0, b: 0, a: 100 }; + var rgb = { + r: 0, + g: 0, + b: 0, + a: 100 + }; var h = hsv.h, s = hsv.s, v = hsv.v; @@ -23372,49 +26100,57 @@ } else { if (h === 360) h = 0; h /= 60; - s = s / 100; - v = v / 100; + s /= 100; + v /= 100; var i = h | 0, f = h - i, p = v * (1 - s), q = v * (1 - s * f), t = v * (1 - s * (1 - f)); + switch (i) { case 0: rgb.r = v; rgb.g = t; rgb.b = p; break; + case 1: rgb.r = q; rgb.g = v; rgb.b = p; break; + case 2: rgb.r = p; rgb.g = v; rgb.b = t; break; + case 3: rgb.r = p; rgb.g = q; rgb.b = v; break; + case 4: rgb.r = t; rgb.g = p; rgb.b = v; break; + case 5: rgb.r = v; rgb.g = p; rgb.b = q; break; } + rgb.r = rgb.r * 255 | 0; rgb.g = rgb.g * 255 | 0; rgb.b = rgb.b * 255 | 0; } + return rgb; } } @@ -23423,10 +26159,34 @@ Color = _$$jPicker.Color, List = _$$jPicker.List, ColorMethods = _$$jPicker.ColorMethods; // local copies for YUI compressor + /** * @function external:jQuery.fn.jPicker * @see {@link external:jQuery.fn.$.fn.jPicker} */ + + /** + * Will be bound to active {@link jQuery.jPicker.Color} + * @callback module:jPicker.LiveCallback + * @param {external:jQuery} ui + * @param {Element} context + * @returns {undefined} + */ + + /** + * @callback module:jPicker.CommitCallback + * @param {external:jQuery.jPicker.Color} activeColor + * @param {external:jQuery} okButton + * @returns {undefined} Return value not used. + */ + + /** + * @callback module:jPicker.CancelCallback + * @param {external:jQuery.jPicker.Color} activeColor + * @param {external:jQuery} cancelButton + * @returns {undefined} Return value not used. + */ + /** * While it would seem this should specify the name `jPicker` for JSDoc, that doesn't * get us treated as a function as well as a namespace (even with `@function name`), @@ -23434,577 +26194,1061 @@ * @namespace * @memberof external:jQuery.fn * @param {external:jQuery.fn.jPickerOptions} options + * @param {module:jPicker.CommitCallback} [commitCallback] + * @param {module:jPicker.LiveCallback} [liveCallback] + * @param {module:jPicker.CancelCallback} [cancelCallback] * @returns {external:jQuery} */ - $.fn.jPicker = function (options) { - var $arguments = arguments; + $.fn.jPicker = function (options, commitCallback, liveCallback, cancelCallback) { return this.each(function () { - var $this = this, + var that = this, settings = $.extend(true, {}, $.fn.jPicker.defaults, options); // local copies for YUI compressor - if ($($this).get(0).nodeName.toLowerCase() === 'input') { + + if ($(that).get(0).nodeName.toLowerCase() === 'input') { // Add color picker icon if binding to an input element and bind the events to the input $.extend(true, settings, { window: { bindToInput: true, expandable: true, - input: $($this) + input: $(that) } }); - if ($($this).val() === '') { - settings.color.active = new Color({ hex: null }); - settings.color.current = new Color({ hex: null }); - } else if (ColorMethods.validateHex($($this).val())) { - settings.color.active = new Color({ hex: $($this).val(), a: settings.color.active.val('a') }); - settings.color.current = new Color({ hex: $($this).val(), a: settings.color.active.val('a') }); + + if ($(that).val() === '') { + settings.color.active = new Color({ + hex: null + }); + settings.color.current = new Color({ + hex: null + }); + } else if (ColorMethods.validateHex($(that).val())) { + settings.color.active = new Color({ + hex: $(that).val(), + a: settings.color.active.val('a') + }); + settings.color.current = new Color({ + hex: $(that).val(), + a: settings.color.active.val('a') + }); } } + if (settings.window.expandable) { - $($this).after('<span class="jPicker"><span class="Icon"><span class="Color"> </span><span class="Alpha"> </span><span class="Image" title="Click To Open Color Picker"> </span><span class="Container"> </span></span></span>'); + $(that).after('<span class="jPicker"><span class="Icon"><span class="Color"> </span><span class="Alpha"> </span><span class="Image" title="Click To Open Color Picker"> </span><span class="Container"> </span></span></span>'); } else { settings.window.liveUpdate = false; // Basic control binding for inline use - You will need to override the liveCallback or commitCallback function to retrieve results } + var isLessThanIE7 = parseFloat(navigator.appVersion.split('MSIE')[1]) < 7 && document.body.filters; // needed to run the AlphaImageLoader function for IE6 // set color mode and update visuals for the new color mode + /** * - * @param {"h"|"s"|"v"|"r"|"g"|"b"|"a"} colorMode [description] + * @param {"h"|"s"|"v"|"r"|"g"|"b"|"a"} colorMode * @throws {Error} Invalid mode + * @returns {undefined} */ + function setColorMode(colorMode) { var active = color.active, hex = active.val('hex'); - var rgbMap = void 0, - rgbBar = void 0; + var rgbMap, rgbBar; settings.color.mode = colorMode; + switch (colorMode) { case 'h': setTimeout(function () { - setBG.call($this, colorMapDiv, 'transparent'); - setImgLoc.call($this, colorMapL1, 0); - setAlpha.call($this, colorMapL1, 100); - setImgLoc.call($this, colorMapL2, 260); - setAlpha.call($this, colorMapL2, 100); - setBG.call($this, colorBarDiv, 'transparent'); - setImgLoc.call($this, colorBarL1, 0); - setAlpha.call($this, colorBarL1, 100); - setImgLoc.call($this, colorBarL2, 260); - setAlpha.call($this, colorBarL2, 100); - setImgLoc.call($this, colorBarL3, 260); - setAlpha.call($this, colorBarL3, 100); - setImgLoc.call($this, colorBarL4, 260); - setAlpha.call($this, colorBarL4, 100); - setImgLoc.call($this, colorBarL6, 260); - setAlpha.call($this, colorBarL6, 100); + setBG.call(that, colorMapDiv, 'transparent'); + setImgLoc.call(that, colorMapL1, 0); + setAlpha.call(that, colorMapL1, 100); + setImgLoc.call(that, colorMapL2, 260); + setAlpha.call(that, colorMapL2, 100); + setBG.call(that, colorBarDiv, 'transparent'); + setImgLoc.call(that, colorBarL1, 0); + setAlpha.call(that, colorBarL1, 100); + setImgLoc.call(that, colorBarL2, 260); + setAlpha.call(that, colorBarL2, 100); + setImgLoc.call(that, colorBarL3, 260); + setAlpha.call(that, colorBarL3, 100); + setImgLoc.call(that, colorBarL4, 260); + setAlpha.call(that, colorBarL4, 100); + setImgLoc.call(that, colorBarL6, 260); + setAlpha.call(that, colorBarL6, 100); }, 0); - colorMap.range('all', { minX: 0, maxX: 100, minY: 0, maxY: 100 }); - colorBar.range('rangeY', { minY: 0, maxY: 360 }); - if (active.val('ahex') == null) break; - colorMap.val('xy', { x: active.val('s'), y: 100 - active.val('v') }, colorMap); + colorMap.range('all', { + minX: 0, + maxX: 100, + minY: 0, + maxY: 100 + }); + colorBar.range('rangeY', { + minY: 0, + maxY: 360 + }); + if (isNullish$1(active.val('ahex'))) break; + colorMap.val('xy', { + x: active.val('s'), + y: 100 - active.val('v') + }, colorMap); colorBar.val('y', 360 - active.val('h'), colorBar); break; + case 's': setTimeout(function () { - setBG.call($this, colorMapDiv, 'transparent'); - setImgLoc.call($this, colorMapL1, -260); - setImgLoc.call($this, colorMapL2, -520); - setImgLoc.call($this, colorBarL1, -260); - setImgLoc.call($this, colorBarL2, -520); - setImgLoc.call($this, colorBarL6, 260); - setAlpha.call($this, colorBarL6, 100); + setBG.call(that, colorMapDiv, 'transparent'); + setImgLoc.call(that, colorMapL1, -260); + setImgLoc.call(that, colorMapL2, -520); + setImgLoc.call(that, colorBarL1, -260); + setImgLoc.call(that, colorBarL2, -520); + setImgLoc.call(that, colorBarL6, 260); + setAlpha.call(that, colorBarL6, 100); }, 0); - colorMap.range('all', { minX: 0, maxX: 360, minY: 0, maxY: 100 }); - colorBar.range('rangeY', { minY: 0, maxY: 100 }); - if (active.val('ahex') == null) break; - colorMap.val('xy', { x: active.val('h'), y: 100 - active.val('v') }, colorMap); + colorMap.range('all', { + minX: 0, + maxX: 360, + minY: 0, + maxY: 100 + }); + colorBar.range('rangeY', { + minY: 0, + maxY: 100 + }); + if (isNullish$1(active.val('ahex'))) break; + colorMap.val('xy', { + x: active.val('h'), + y: 100 - active.val('v') + }, colorMap); colorBar.val('y', 100 - active.val('s'), colorBar); break; + case 'v': setTimeout(function () { - setBG.call($this, colorMapDiv, '000000'); - setImgLoc.call($this, colorMapL1, -780); - setImgLoc.call($this, colorMapL2, 260); - setBG.call($this, colorBarDiv, hex); - setImgLoc.call($this, colorBarL1, -520); - setImgLoc.call($this, colorBarL2, 260); - setAlpha.call($this, colorBarL2, 100); - setImgLoc.call($this, colorBarL6, 260); - setAlpha.call($this, colorBarL6, 100); + setBG.call(that, colorMapDiv, '000000'); + setImgLoc.call(that, colorMapL1, -780); + setImgLoc.call(that, colorMapL2, 260); + setBG.call(that, colorBarDiv, hex); + setImgLoc.call(that, colorBarL1, -520); + setImgLoc.call(that, colorBarL2, 260); + setAlpha.call(that, colorBarL2, 100); + setImgLoc.call(that, colorBarL6, 260); + setAlpha.call(that, colorBarL6, 100); }, 0); - colorMap.range('all', { minX: 0, maxX: 360, minY: 0, maxY: 100 }); - colorBar.range('rangeY', { minY: 0, maxY: 100 }); - if (active.val('ahex') == null) break; - colorMap.val('xy', { x: active.val('h'), y: 100 - active.val('s') }, colorMap); + colorMap.range('all', { + minX: 0, + maxX: 360, + minY: 0, + maxY: 100 + }); + colorBar.range('rangeY', { + minY: 0, + maxY: 100 + }); + if (isNullish$1(active.val('ahex'))) break; + colorMap.val('xy', { + x: active.val('h'), + y: 100 - active.val('s') + }, colorMap); colorBar.val('y', 100 - active.val('v'), colorBar); break; + case 'r': rgbMap = -1040; rgbBar = -780; - colorMap.range('all', { minX: 0, maxX: 255, minY: 0, maxY: 255 }); - colorBar.range('rangeY', { minY: 0, maxY: 255 }); - if (active.val('ahex') == null) break; - colorMap.val('xy', { x: active.val('b'), y: 255 - active.val('g') }, colorMap); + colorMap.range('all', { + minX: 0, + maxX: 255, + minY: 0, + maxY: 255 + }); + colorBar.range('rangeY', { + minY: 0, + maxY: 255 + }); + if (isNullish$1(active.val('ahex'))) break; + colorMap.val('xy', { + x: active.val('b'), + y: 255 - active.val('g') + }, colorMap); colorBar.val('y', 255 - active.val('r'), colorBar); break; + case 'g': rgbMap = -1560; rgbBar = -1820; - colorMap.range('all', { minX: 0, maxX: 255, minY: 0, maxY: 255 }); - colorBar.range('rangeY', { minY: 0, maxY: 255 }); - if (active.val('ahex') == null) break; - colorMap.val('xy', { x: active.val('b'), y: 255 - active.val('r') }, colorMap); + colorMap.range('all', { + minX: 0, + maxX: 255, + minY: 0, + maxY: 255 + }); + colorBar.range('rangeY', { + minY: 0, + maxY: 255 + }); + if (isNullish$1(active.val('ahex'))) break; + colorMap.val('xy', { + x: active.val('b'), + y: 255 - active.val('r') + }, colorMap); colorBar.val('y', 255 - active.val('g'), colorBar); break; + case 'b': rgbMap = -2080; rgbBar = -2860; - colorMap.range('all', { minX: 0, maxX: 255, minY: 0, maxY: 255 }); - colorBar.range('rangeY', { minY: 0, maxY: 255 }); - if (active.val('ahex') == null) break; - colorMap.val('xy', { x: active.val('r'), y: 255 - active.val('g') }, colorMap); + colorMap.range('all', { + minX: 0, + maxX: 255, + minY: 0, + maxY: 255 + }); + colorBar.range('rangeY', { + minY: 0, + maxY: 255 + }); + if (isNullish$1(active.val('ahex'))) break; + colorMap.val('xy', { + x: active.val('r'), + y: 255 - active.val('g') + }, colorMap); colorBar.val('y', 255 - active.val('b'), colorBar); break; + case 'a': setTimeout(function () { - setBG.call($this, colorMapDiv, 'transparent'); - setImgLoc.call($this, colorMapL1, -260); - setImgLoc.call($this, colorMapL2, -520); - setImgLoc.call($this, colorBarL1, 260); - setImgLoc.call($this, colorBarL2, 260); - setAlpha.call($this, colorBarL2, 100); - setImgLoc.call($this, colorBarL6, 0); - setAlpha.call($this, colorBarL6, 100); + setBG.call(that, colorMapDiv, 'transparent'); + setImgLoc.call(that, colorMapL1, -260); + setImgLoc.call(that, colorMapL2, -520); + setImgLoc.call(that, colorBarL1, 260); + setImgLoc.call(that, colorBarL2, 260); + setAlpha.call(that, colorBarL2, 100); + setImgLoc.call(that, colorBarL6, 0); + setAlpha.call(that, colorBarL6, 100); }, 0); - colorMap.range('all', { minX: 0, maxX: 360, minY: 0, maxY: 100 }); - colorBar.range('rangeY', { minY: 0, maxY: 255 }); - if (active.val('ahex') == null) break; - colorMap.val('xy', { x: active.val('h'), y: 100 - active.val('v') }, colorMap); + colorMap.range('all', { + minX: 0, + maxX: 360, + minY: 0, + maxY: 100 + }); + colorBar.range('rangeY', { + minY: 0, + maxY: 255 + }); + if (isNullish$1(active.val('ahex'))) break; + colorMap.val('xy', { + x: active.val('h'), + y: 100 - active.val('v') + }, colorMap); colorBar.val('y', 255 - active.val('a'), colorBar); break; + default: throw new Error('Invalid Mode'); } + switch (colorMode) { case 'h': break; + case 's': case 'v': case 'a': setTimeout(function () { - setAlpha.call($this, colorMapL1, 100); - setAlpha.call($this, colorBarL1, 100); - setImgLoc.call($this, colorBarL3, 260); - setAlpha.call($this, colorBarL3, 100); - setImgLoc.call($this, colorBarL4, 260); - setAlpha.call($this, colorBarL4, 100); + setAlpha.call(that, colorMapL1, 100); + setAlpha.call(that, colorBarL1, 100); + setImgLoc.call(that, colorBarL3, 260); + setAlpha.call(that, colorBarL3, 100); + setImgLoc.call(that, colorBarL4, 260); + setAlpha.call(that, colorBarL4, 100); }, 0); break; + case 'r': case 'g': case 'b': setTimeout(function () { - setBG.call($this, colorMapDiv, 'transparent'); - setBG.call($this, colorBarDiv, 'transparent'); - setAlpha.call($this, colorBarL1, 100); - setAlpha.call($this, colorMapL1, 100); - setImgLoc.call($this, colorMapL1, rgbMap); - setImgLoc.call($this, colorMapL2, rgbMap - 260); - setImgLoc.call($this, colorBarL1, rgbBar - 780); - setImgLoc.call($this, colorBarL2, rgbBar - 520); - setImgLoc.call($this, colorBarL3, rgbBar); - setImgLoc.call($this, colorBarL4, rgbBar - 260); - setImgLoc.call($this, colorBarL6, 260); - setAlpha.call($this, colorBarL6, 100); + setBG.call(that, colorMapDiv, 'transparent'); + setBG.call(that, colorBarDiv, 'transparent'); + setAlpha.call(that, colorBarL1, 100); + setAlpha.call(that, colorMapL1, 100); + setImgLoc.call(that, colorMapL1, rgbMap); + setImgLoc.call(that, colorMapL2, rgbMap - 260); + setImgLoc.call(that, colorBarL1, rgbBar - 780); + setImgLoc.call(that, colorBarL2, rgbBar - 520); + setImgLoc.call(that, colorBarL3, rgbBar); + setImgLoc.call(that, colorBarL4, rgbBar - 260); + setImgLoc.call(that, colorBarL6, 260); + setAlpha.call(that, colorBarL6, 100); }, 0); break; } - if (active.val('ahex') == null) return; - activeColorChanged.call($this, active); + + if (isNullish$1(active.val('ahex'))) return; + activeColorChanged.call(that, active); } - // Update color when user changes text values + /** + * Update color when user changes text values. + * @param {external:jQuery} ui + * @param {?module:jPicker.Slider} context + * @returns {undefined} + */ + + function activeColorChanged(ui, context) { - if (context == null || context !== colorBar && context !== colorMap) positionMapAndBarArrows.call($this, ui, context); + if (isNullish$1(context) || context !== colorBar && context !== colorMap) positionMapAndBarArrows.call(that, ui, context); setTimeout(function () { - updatePreview.call($this, ui); - updateMapVisuals.call($this, ui); - updateBarVisuals.call($this, ui); + updatePreview.call(that, ui); + updateMapVisuals.call(that, ui); + updateBarVisuals.call(that, ui); }, 0); } - // user has dragged the ColorMap pointer + /** + * User has dragged the ColorMap pointer. + * @param {external:jQuery} ui + * @param {?module:jPicker.Slider} context + * @returns {undefined} + */ + + function mapValueChanged(ui, context) { var active = color.active; - - if (context !== colorMap && active.val() == null) return; + if (context !== colorMap && isNullish$1(active.val())) return; var xy = ui.val('all'); + switch (settings.color.mode) { case 'h': - active.val('sv', { s: xy.x, v: 100 - xy.y }, context); + active.val('sv', { + s: xy.x, + v: 100 - xy.y + }, context); break; + case 's': case 'a': - active.val('hv', { h: xy.x, v: 100 - xy.y }, context); + active.val('hv', { + h: xy.x, + v: 100 - xy.y + }, context); break; + case 'v': - active.val('hs', { h: xy.x, s: 100 - xy.y }, context); + active.val('hs', { + h: xy.x, + s: 100 - xy.y + }, context); break; + case 'r': - active.val('gb', { g: 255 - xy.y, b: xy.x }, context); + active.val('gb', { + g: 255 - xy.y, + b: xy.x + }, context); break; + case 'g': - active.val('rb', { r: 255 - xy.y, b: xy.x }, context); + active.val('rb', { + r: 255 - xy.y, + b: xy.x + }, context); break; + case 'b': - active.val('rg', { r: xy.x, g: 255 - xy.y }, context); + active.val('rg', { + r: xy.x, + g: 255 - xy.y + }, context); break; } } - // user has dragged the ColorBar slider + /** + * User has dragged the ColorBar slider. + * @param {external:jQuery} ui + * @param {?module:jPicker.Slider} context + * @returns {undefined} + */ + + function colorBarValueChanged(ui, context) { var active = color.active; + if (context !== colorBar && isNullish$1(active.val())) return; - if (context !== colorBar && active.val() == null) return; switch (settings.color.mode) { case 'h': - active.val('h', { h: 360 - ui.val('y') }, context); + active.val('h', { + h: 360 - ui.val('y') + }, context); break; + case 's': - active.val('s', { s: 100 - ui.val('y') }, context); + active.val('s', { + s: 100 - ui.val('y') + }, context); break; + case 'v': - active.val('v', { v: 100 - ui.val('y') }, context); + active.val('v', { + v: 100 - ui.val('y') + }, context); break; + case 'r': - active.val('r', { r: 255 - ui.val('y') }, context); + active.val('r', { + r: 255 - ui.val('y') + }, context); break; + case 'g': - active.val('g', { g: 255 - ui.val('y') }, context); + active.val('g', { + g: 255 - ui.val('y') + }, context); break; + case 'b': - active.val('b', { b: 255 - ui.val('y') }, context); + active.val('b', { + b: 255 - ui.val('y') + }, context); break; + case 'a': active.val('a', 255 - ui.val('y'), context); break; } } - // position map and bar arrows to match current color + /** + * Position map and bar arrows to match current color. + * @param {external:jQuery} ui + * @param {?module:jPicker.Slider} context + * @returns {undefined} + */ + + function positionMapAndBarArrows(ui, context) { if (context !== colorMap) { switch (settings.color.mode) { case 'h': - var sv = ui.val('sv'); - colorMap.val('xy', { x: sv != null ? sv.s : 100, y: 100 - (sv != null ? sv.v : 100) }, context); - break; - case 's': + { + var sv = ui.val('sv'); + colorMap.val('xy', { + x: !isNullish$1(sv) ? sv.s : 100, + y: 100 - (!isNullish$1(sv) ? sv.v : 100) + }, context); + break; + } + + case 's': // Fall through + case 'a': - var hv = ui.val('hv'); - colorMap.val('xy', { x: hv && hv.h || 0, y: 100 - (hv != null ? hv.v : 100) }, context); - break; + { + var hv = ui.val('hv'); + colorMap.val('xy', { + x: hv && hv.h || 0, + y: 100 - (!isNullish$1(hv) ? hv.v : 100) + }, context); + break; + } + case 'v': - var hs = ui.val('hs'); - colorMap.val('xy', { x: hs && hs.h || 0, y: 100 - (hs != null ? hs.s : 100) }, context); - break; + { + var hs = ui.val('hs'); + colorMap.val('xy', { + x: hs && hs.h || 0, + y: 100 - (!isNullish$1(hs) ? hs.s : 100) + }, context); + break; + } + case 'r': - var bg = ui.val('bg'); - colorMap.val('xy', { x: bg && bg.b || 0, y: 255 - (bg && bg.g || 0) }, context); - break; + { + var bg = ui.val('bg'); + colorMap.val('xy', { + x: bg && bg.b || 0, + y: 255 - (bg && bg.g || 0) + }, context); + break; + } + case 'g': - var br = ui.val('br'); - colorMap.val('xy', { x: br && br.b || 0, y: 255 - (br && br.r || 0) }, context); - break; + { + var br = ui.val('br'); + colorMap.val('xy', { + x: br && br.b || 0, + y: 255 - (br && br.r || 0) + }, context); + break; + } + case 'b': - var rg = ui.val('rg'); - colorMap.val('xy', { x: rg && rg.r || 0, y: 255 - (rg && rg.g || 0) }, context); - break; + { + var rg = ui.val('rg'); + colorMap.val('xy', { + x: rg && rg.r || 0, + y: 255 - (rg && rg.g || 0) + }, context); + break; + } } } + if (context !== colorBar) { switch (settings.color.mode) { case 'h': colorBar.val('y', 360 - (ui.val('h') || 0), context); break; + case 's': - var s = ui.val('s'); - colorBar.val('y', 100 - (s != null ? s : 100), context); - break; + { + var s = ui.val('s'); + colorBar.val('y', 100 - (!isNullish$1(s) ? s : 100), context); + break; + } + case 'v': - var v = ui.val('v'); - colorBar.val('y', 100 - (v != null ? v : 100), context); - break; + { + var v = ui.val('v'); + colorBar.val('y', 100 - (!isNullish$1(v) ? v : 100), context); + break; + } + case 'r': colorBar.val('y', 255 - (ui.val('r') || 0), context); break; + case 'g': colorBar.val('y', 255 - (ui.val('g') || 0), context); break; + case 'b': colorBar.val('y', 255 - (ui.val('b') || 0), context); break; + case 'a': - var a = ui.val('a'); - colorBar.val('y', 255 - (a != null ? a : 255), context); - break; + { + var a = ui.val('a'); + colorBar.val('y', 255 - (!isNullish$1(a) ? a : 255), context); + break; + } } } } + /** + * @param {external:jQuery} ui + * @returns {undefined} + */ + + function updatePreview(ui) { try { var all = ui.val('all'); - activePreview.css({ backgroundColor: all && '#' + all.hex || 'transparent' }); - setAlpha.call($this, activePreview, all && Math.precision(all.a * 100 / 255, 4) || 0); + activePreview.css({ + backgroundColor: all && '#' + all.hex || 'transparent' + }); + setAlpha.call(that, activePreview, all && toFixedNumeric(all.a * 100 / 255, 4) || 0); } catch (e) {} } + /** + * @param {external:jQuery} ui + * @returns {undefined} + */ + + function updateMapVisuals(ui) { switch (settings.color.mode) { case 'h': - setBG.call($this, colorMapDiv, new Color({ h: ui.val('h') || 0, s: 100, v: 100 }).val('hex')); + setBG.call(that, colorMapDiv, new Color({ + h: ui.val('h') || 0, + s: 100, + v: 100 + }).val('hex')); break; + case 's': case 'a': - var s = ui.val('s'); - setAlpha.call($this, colorMapL2, 100 - (s != null ? s : 100)); - break; + { + var s = ui.val('s'); + setAlpha.call(that, colorMapL2, 100 - (!isNullish$1(s) ? s : 100)); + break; + } + case 'v': - var v = ui.val('v'); - setAlpha.call($this, colorMapL1, v != null ? v : 100); - break; + { + var v = ui.val('v'); + setAlpha.call(that, colorMapL1, !isNullish$1(v) ? v : 100); + break; + } + case 'r': - setAlpha.call($this, colorMapL2, Math.precision((ui.val('r') || 0) / 255 * 100, 4)); + setAlpha.call(that, colorMapL2, toFixedNumeric((ui.val('r') || 0) / 255 * 100, 4)); break; + case 'g': - setAlpha.call($this, colorMapL2, Math.precision((ui.val('g') || 0) / 255 * 100, 4)); + setAlpha.call(that, colorMapL2, toFixedNumeric((ui.val('g') || 0) / 255 * 100, 4)); break; + case 'b': - setAlpha.call($this, colorMapL2, Math.precision((ui.val('b') || 0) / 255 * 100)); + setAlpha.call(that, colorMapL2, toFixedNumeric((ui.val('b') || 0) / 255 * 100)); break; } + var a = ui.val('a'); - setAlpha.call($this, colorMapL3, Math.precision((255 - (a || 0)) * 100 / 255, 4)); + setAlpha.call(that, colorMapL3, toFixedNumeric((255 - (a || 0)) * 100 / 255, 4)); } + /** + * @param {external:jQuery} ui + * @returns {undefined} + */ + + function updateBarVisuals(ui) { switch (settings.color.mode) { case 'h': - var a = ui.val('a'); - setAlpha.call($this, colorBarL5, Math.precision((255 - (a || 0)) * 100 / 255, 4)); - break; + { + var a = ui.val('a'); + setAlpha.call(that, colorBarL5, toFixedNumeric((255 - (a || 0)) * 100 / 255, 4)); + break; + } + case 's': - var hva = ui.val('hva'), - saturatedColor = new Color({ h: hva && hva.h || 0, s: 100, v: hva != null ? hva.v : 100 }); - setBG.call($this, colorBarDiv, saturatedColor.val('hex')); - setAlpha.call($this, colorBarL2, 100 - (hva != null ? hva.v : 100)); - setAlpha.call($this, colorBarL5, Math.precision((255 - (hva && hva.a || 0)) * 100 / 255, 4)); - break; + { + var hva = ui.val('hva'), + saturatedColor = new Color({ + h: hva && hva.h || 0, + s: 100, + v: !isNullish$1(hva) ? hva.v : 100 + }); + setBG.call(that, colorBarDiv, saturatedColor.val('hex')); + setAlpha.call(that, colorBarL2, 100 - (!isNullish$1(hva) ? hva.v : 100)); + setAlpha.call(that, colorBarL5, toFixedNumeric((255 - (hva && hva.a || 0)) * 100 / 255, 4)); + break; + } + case 'v': - var hsa = ui.val('hsa'), - valueColor = new Color({ h: hsa && hsa.h || 0, s: hsa != null ? hsa.s : 100, v: 100 }); - setBG.call($this, colorBarDiv, valueColor.val('hex')); - setAlpha.call($this, colorBarL5, Math.precision((255 - (hsa && hsa.a || 0)) * 100 / 255, 4)); - break; + { + var hsa = ui.val('hsa'), + valueColor = new Color({ + h: hsa && hsa.h || 0, + s: !isNullish$1(hsa) ? hsa.s : 100, + v: 100 + }); + setBG.call(that, colorBarDiv, valueColor.val('hex')); + setAlpha.call(that, colorBarL5, toFixedNumeric((255 - (hsa && hsa.a || 0)) * 100 / 255, 4)); + break; + } + case 'r': case 'g': case 'b': - var rgba = ui.val('rgba'); - var hValue = 0, - vValue = 0; - if (settings.color.mode === 'r') { - hValue = rgba && rgba.b || 0; - vValue = rgba && rgba.g || 0; - } else if (settings.color.mode === 'g') { - hValue = rgba && rgba.b || 0; - vValue = rgba && rgba.r || 0; - } else if (settings.color.mode === 'b') { - hValue = rgba && rgba.r || 0; - vValue = rgba && rgba.g || 0; + { + var rgba = ui.val('rgba'); + var hValue = 0, + vValue = 0; + + if (settings.color.mode === 'r') { + hValue = rgba && rgba.b || 0; + vValue = rgba && rgba.g || 0; + } else if (settings.color.mode === 'g') { + hValue = rgba && rgba.b || 0; + vValue = rgba && rgba.r || 0; + } else if (settings.color.mode === 'b') { + hValue = rgba && rgba.r || 0; + vValue = rgba && rgba.g || 0; + } + + var middle = vValue > hValue ? hValue : vValue; + setAlpha.call(that, colorBarL2, hValue > vValue ? toFixedNumeric((hValue - vValue) / (255 - vValue) * 100, 4) : 0); + setAlpha.call(that, colorBarL3, vValue > hValue ? toFixedNumeric((vValue - hValue) / (255 - hValue) * 100, 4) : 0); + setAlpha.call(that, colorBarL4, toFixedNumeric(middle / 255 * 100, 4)); + setAlpha.call(that, colorBarL5, toFixedNumeric((255 - (rgba && rgba.a || 0)) * 100 / 255, 4)); + break; } - var middle = vValue > hValue ? hValue : vValue; - setAlpha.call($this, colorBarL2, hValue > vValue ? Math.precision((hValue - vValue) / (255 - vValue) * 100, 4) : 0); - setAlpha.call($this, colorBarL3, vValue > hValue ? Math.precision((vValue - hValue) / (255 - hValue) * 100, 4) : 0); - setAlpha.call($this, colorBarL4, Math.precision(middle / 255 * 100, 4)); - setAlpha.call($this, colorBarL5, Math.precision((255 - (rgba && rgba.a || 0)) * 100 / 255, 4)); - break; + case 'a': { var _a = ui.val('a'); - setBG.call($this, colorBarDiv, ui.val('hex') || '000000'); - setAlpha.call($this, colorBarL5, _a != null ? 0 : 100); - setAlpha.call($this, colorBarL6, _a != null ? 100 : 0); + + setBG.call(that, colorBarDiv, ui.val('hex') || '000000'); + setAlpha.call(that, colorBarL5, !isNullish$1(_a) ? 0 : 100); + setAlpha.call(that, colorBarL6, !isNullish$1(_a) ? 100 : 0); break; } } } + /** + * @param {external:jQuery} el + * @param {string} [c="transparent"] + * @returns {undefined} + */ + + function setBG(el, c) { - el.css({ backgroundColor: c && c.length === 6 && '#' + c || 'transparent' }); + el.css({ + backgroundColor: c && c.length === 6 && '#' + c || 'transparent' + }); } + /** + * @param {external:jQuery} img + * @param {string} src The image source + * @returns {undefined} + */ + + function setImg(img, src) { if (isLessThanIE7 && (src.includes('AlphaBar.png') || src.includes('Bars.png') || src.includes('Maps.png'))) { img.attr('pngSrc', src); - img.css({ backgroundImage: 'none', filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + src + '\', sizingMethod=\'scale\')' }); - } else img.css({ backgroundImage: 'url(\'' + src + '\')' }); + img.css({ + backgroundImage: 'none', + filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + src + '\', sizingMethod=\'scale\')' + }); + } else img.css({ + backgroundImage: 'url(\'' + src + '\')' + }); } + /** + * @param {external:jQuery} img + * @param {Float} y + * @returns {undefined} + */ + + function setImgLoc(img, y) { - img.css({ top: y + 'px' }); + img.css({ + top: y + 'px' + }); } + /** + * @param {external:jQuery} obj + * @param {Float} alpha + * @returns {undefined} + */ + + function setAlpha(obj, alpha) { - obj.css({ visibility: alpha > 0 ? 'visible' : 'hidden' }); + obj.css({ + visibility: alpha > 0 ? 'visible' : 'hidden' + }); + if (alpha > 0 && alpha < 100) { if (isLessThanIE7) { var src = obj.attr('pngSrc'); - if (src != null && (src.includes('AlphaBar.png') || src.includes('Bars.png') || src.includes('Maps.png'))) { - obj.css({ filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + src + '\', sizingMethod=\'scale\') progid:DXImageTransform.Microsoft.Alpha(opacity=' + alpha + ')' }); - } else obj.css({ opacity: Math.precision(alpha / 100, 4) }); - } else obj.css({ opacity: Math.precision(alpha / 100, 4) }); + + if (!isNullish$1(src) && (src.includes('AlphaBar.png') || src.includes('Bars.png') || src.includes('Maps.png'))) { + obj.css({ + filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + src + '\', sizingMethod=\'scale\') progid:DXImageTransform.Microsoft.Alpha(opacity=' + alpha + ')' + }); + } else obj.css({ + opacity: toFixedNumeric(alpha / 100, 4) + }); + } else obj.css({ + opacity: toFixedNumeric(alpha / 100, 4) + }); } else if (alpha === 0 || alpha === 100) { if (isLessThanIE7) { var _src = obj.attr('pngSrc'); - if (_src != null && (_src.includes('AlphaBar.png') || _src.includes('Bars.png') || _src.includes('Maps.png'))) { - obj.css({ filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + _src + '\', sizingMethod=\'scale\')' }); - } else obj.css({ opacity: '' }); - } else obj.css({ opacity: '' }); - } - } - // revert color to original color when opened - function revertColor() { - color.active.val('ahex', color.current.val('ahex')); - } - // commit the color changes - function commitColor() { - color.current.val('ahex', color.active.val('ahex')); - } - function radioClicked(e) { - $(this).parents('tbody:first').find('input:radio[value!="' + e.target.value + '"]').removeAttr('checked'); - setColorMode.call($this, e.target.value); - } - function currentClicked() { - revertColor.call($this); - } - function cancelClicked() { - revertColor.call($this); - settings.window.expandable && hide.call($this); - typeof cancelCallback === 'function' && cancelCallback.call($this, color.active, cancelButton); - } - function okClicked() { - commitColor.call($this); - settings.window.expandable && hide.call($this); - typeof commitCallback === 'function' && commitCallback.call($this, color.active, okButton); - } - function iconImageClicked() { - show.call($this); - } - function currentColorChanged(ui, context) { - var hex = ui.val('hex'); - currentPreview.css({ backgroundColor: hex && '#' + hex || 'transparent' }); - setAlpha.call($this, currentPreview, Math.precision((ui.val('a') || 0) * 100 / 255, 4)); - } - function expandableColorChanged(ui, context) { - var hex = ui.val('hex'); - var va = ui.val('va'); - iconColor.css({ backgroundColor: hex && '#' + hex || 'transparent' }); - setAlpha.call($this, iconAlpha, Math.precision((255 - (va && va.a || 0)) * 100 / 255, 4)); - if (settings.window.bindToInput && settings.window.updateInputColor) { - settings.window.input.css({ - backgroundColor: hex && '#' + hex || 'transparent', - color: va == null || va.v > 75 ? '#000000' : '#ffffff' + + if (!isNullish$1(_src) && (_src.includes('AlphaBar.png') || _src.includes('Bars.png') || _src.includes('Maps.png'))) { + obj.css({ + filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + _src + '\', sizingMethod=\'scale\')' + }); + } else obj.css({ + opacity: '' + }); + } else obj.css({ + opacity: '' }); } } + /** + * Revert color to original color when opened. + * @returns {undefined} + */ + + + function revertColor() { + color.active.val('ahex', color.current.val('ahex')); + } + /** + * Commit the color changes. + * @returns {undefined} + */ + + + function commitColor() { + color.current.val('ahex', color.active.val('ahex')); + } + /** + * @param {Event} e + * @returns {undefined} + */ + + + function radioClicked(e) { + $(this).parents('tbody:first').find('input:radio[value!="' + e.target.value + '"]').removeAttr('checked'); + setColorMode.call(that, e.target.value); + } + /** + * + * @returns {undefined} + */ + + + function currentClicked() { + revertColor.call(that); + } + /** + * + * @returns {undefined} + */ + + + function cancelClicked() { + revertColor.call(that); + settings.window.expandable && hide.call(that); + typeof cancelCallback === 'function' && cancelCallback.call(that, color.active, cancelButton); + } + /** + * + * @returns {undefined} + */ + + + function okClicked() { + commitColor.call(that); + settings.window.expandable && hide.call(that); + typeof commitCallback === 'function' && commitCallback.call(that, color.active, okButton); + } + /** + * + * @returns {undefined} + */ + + + function iconImageClicked() { + show.call(that); + } + /** + * @param {external:jQuery} ui + * @returns {undefined} + */ + + + function currentColorChanged(ui) { + var hex = ui.val('hex'); + currentPreview.css({ + backgroundColor: hex && '#' + hex || 'transparent' + }); + setAlpha.call(that, currentPreview, toFixedNumeric((ui.val('a') || 0) * 100 / 255, 4)); + } + /** + * @param {external:jQuery} ui + * @returns {undefined} + */ + + + function expandableColorChanged(ui) { + var hex = ui.val('hex'); + var va = ui.val('va'); + iconColor.css({ + backgroundColor: hex && '#' + hex || 'transparent' + }); + setAlpha.call(that, iconAlpha, toFixedNumeric((255 - (va && va.a || 0)) * 100 / 255, 4)); + + if (settings.window.bindToInput && settings.window.updateInputColor) { + settings.window.input.css({ + backgroundColor: hex && '#' + hex || 'transparent', + color: isNullish$1(va) || va.v > 75 ? '#000000' : '#ffffff' + }); + } + } + /** + * @param {Event} e + * @returns {undefined} + */ + + function moveBarMouseDown(e) { // const {element} = settings.window, // local copies for YUI compressor // {page} = settings.window; elementStartX = parseInt(container.css('left')); elementStartY = parseInt(container.css('top')); pageStartX = e.pageX; - pageStartY = e.pageY; - // bind events to document to move window - we will unbind these on mouseup + pageStartY = e.pageY; // bind events to document to move window - we will unbind these on mouseup + $(document).bind('mousemove', documentMouseMove).bind('mouseup', documentMouseUp); e.preventDefault(); // prevent attempted dragging of the column } + /** + * @param {Event} e + * @returns {false} + */ + + function documentMouseMove(e) { - container.css({ left: elementStartX - (pageStartX - e.pageX) + 'px', top: elementStartY - (pageStartY - e.pageY) + 'px' }); - if (settings.window.expandable && !$.support.boxModel) container.prev().css({ left: container.css('left'), top: container.css('top') }); + container.css({ + left: elementStartX - (pageStartX - e.pageX) + 'px', + top: elementStartY - (pageStartY - e.pageY) + 'px' + }); + + if (settings.window.expandable && !$.support.boxModel) { + container.prev().css({ + left: container.css('left'), + top: container.css('top') + }); + } + e.stopPropagation(); e.preventDefault(); return false; } + /** + * @param {Event} e + * @returns {false} + */ + + function documentMouseUp(e) { $(document).unbind('mousemove', documentMouseMove).unbind('mouseup', documentMouseUp); e.stopPropagation(); e.preventDefault(); return false; } + /** + * @param {Event} e + * @returns {false} + */ + + function quickPickClicked(e) { e.preventDefault(); e.stopPropagation(); color.active.val('ahex', $(this).attr('title') || null, e.target); return false; } + /** + * + * @returns {undefined} + */ + + function show() { color.current.val('ahex', color.active.val('ahex')); + /** + * + * @returns {undefined} + */ + function attachIFrame() { if (!settings.window.expandable || $.support.boxModel) return; var table = container.find('table:first'); container.before('<iframe/>'); - container.prev().css({ width: table.width(), height: container.height(), opacity: 0, position: 'absolute', left: container.css('left'), top: container.css('top') }); + container.prev().css({ + width: table.width(), + height: container.height(), + opacity: 0, + position: 'absolute', + left: container.css('left'), + top: container.css('top') + }); } + if (settings.window.expandable) { - $(document.body).children('div.jPicker.Container').css({ zIndex: 10 }); - container.css({ zIndex: 20 }); + $(document.body).children('div.jPicker.Container').css({ + zIndex: 10 + }); + container.css({ + zIndex: 20 + }); } + switch (settings.window.effects.type) { case 'fade': container.fadeIn(settings.window.effects.speed.show, attachIFrame); break; + case 'slide': container.slideDown(settings.window.effects.speed.show, attachIFrame); break; + case 'show': default: container.show(settings.window.effects.speed.show, attachIFrame); break; } } + /** + * + * @returns {undefined} + */ + + function hide() { + /** + * + * @returns {undefined} + */ function removeIFrame() { - if (settings.window.expandable) container.css({ zIndex: 10 }); + if (settings.window.expandable) container.css({ + zIndex: 10 + }); if (!settings.window.expandable || $.support.boxModel) return; container.prev().remove(); } + switch (settings.window.effects.type) { case 'fade': container.fadeOut(settings.window.effects.speed.hide, removeIFrame); break; + case 'slide': container.slideUp(settings.window.effects.speed.hide, removeIFrame); break; + case 'show': default: container.hide(settings.window.effects.speed.hide, removeIFrame); break; } } + /** + * + * @returns {undefined} + */ + + function initialize() { var win = settings.window, - popup = win.expandable ? $($this).next().find('.Container:first') : null; - container = win.expandable ? $('<div/>') : $($this); + popup = win.expandable ? $(that).next().find('.Container:first') : null; + container = win.expandable ? $('<div/>') : $(that); container.addClass('jPicker Container'); if (win.expandable) container.hide(); - container.get(0).onselectstart = function (event) { - if (event.target.nodeName.toLowerCase() !== 'input') return false; - }; - // inject html source code - we are using a single table for this control - I know tables are considered bad, but it takes care of equal height columns and + + container.get(0).onselectstart = function (e) { + if (e.target.nodeName.toLowerCase() !== 'input') return false; + return true; + }; // inject html source code - we are using a single table for this control - I know tables are considered bad, but it takes care of equal height columns and // this control really is tabular data, so I believe it is the right move + + var all = color.active.val('all'); if (win.alphaPrecision < 0) win.alphaPrecision = 0;else if (win.alphaPrecision > 2) win.alphaPrecision = 2; - var controlHtml = '<table class="jPicker" cellpadding="0" cellspacing="0"><tbody>' + (win.expandable ? '<tr><td class="Move" colspan="5"> </td></tr>' : '') + '<tr><td rowspan="9"><h2 class="Title">' + (win.title || localization.text.title) + '</h2><div class="Map"><span class="Map1"> </span><span class="Map2"> </span><span class="Map3"> </span><img src="' + images.clientPath + images.colorMap.arrow.file + '" class="Arrow"/></div></td><td rowspan="9"><div class="Bar"><span class="Map1"> </span><span class="Map2"> </span><span class="Map3"> </span><span class="Map4"> </span><span class="Map5"> </span><span class="Map6"> </span><img src="' + images.clientPath + images.colorBar.arrow.file + '" class="Arrow"/></div></td><td colspan="2" class="Preview">' + localization.text.newColor + '<div><span class="Active" title="' + localization.tooltips.colors.newColor + '"> </span><span class="Current" title="' + localization.tooltips.colors.currentColor + '"> </span></div>' + localization.text.currentColor + '</td><td rowspan="9" class="Button"><input type="button" class="Ok" value="' + localization.text.ok + '" title="' + localization.tooltips.buttons.ok + '"/><input type="button" class="Cancel" value="' + localization.text.cancel + '" title="' + localization.tooltips.buttons.cancel + '"/><hr/><div class="Grid"> </div></td></tr><tr class="Hue"><td class="Radio"><label title="' + localization.tooltips.hue.radio + '"><input type="radio" value="h"' + (settings.color.mode === 'h' ? ' checked="checked"' : '') + '/>H:</label></td><td class="Text"><input type="text" maxlength="3" value="' + (all != null ? all.h : '') + '" title="' + localization.tooltips.hue.textbox + '"/> °</td></tr><tr class="Saturation"><td class="Radio"><label title="' + localization.tooltips.saturation.radio + '"><input type="radio" value="s"' + (settings.color.mode === 's' ? ' checked="checked"' : '') + '/>S:</label></td><td class="Text"><input type="text" maxlength="3" value="' + (all != null ? all.s : '') + '" title="' + localization.tooltips.saturation.textbox + '"/> %</td></tr><tr class="Value"><td class="Radio"><label title="' + localization.tooltips.value.radio + '"><input type="radio" value="v"' + (settings.color.mode === 'v' ? ' checked="checked"' : '') + '/>V:</label><br/><br/></td><td class="Text"><input type="text" maxlength="3" value="' + (all != null ? all.v : '') + '" title="' + localization.tooltips.value.textbox + '"/> %<br/><br/></td></tr><tr class="Red"><td class="Radio"><label title="' + localization.tooltips.red.radio + '"><input type="radio" value="r"' + (settings.color.mode === 'r' ? ' checked="checked"' : '') + '/>R:</label></td><td class="Text"><input type="text" maxlength="3" value="' + (all != null ? all.r : '') + '" title="' + localization.tooltips.red.textbox + '"/></td></tr><tr class="Green"><td class="Radio"><label title="' + localization.tooltips.green.radio + '"><input type="radio" value="g"' + (settings.color.mode === 'g' ? ' checked="checked"' : '') + '/>G:</label></td><td class="Text"><input type="text" maxlength="3" value="' + (all != null ? all.g : '') + '" title="' + localization.tooltips.green.textbox + '"/></td></tr><tr class="Blue"><td class="Radio"><label title="' + localization.tooltips.blue.radio + '"><input type="radio" value="b"' + (settings.color.mode === 'b' ? ' checked="checked"' : '') + '/>B:</label></td><td class="Text"><input type="text" maxlength="3" value="' + (all != null ? all.b : '') + '" title="' + localization.tooltips.blue.textbox + '"/></td></tr><tr class="Alpha"><td class="Radio">' + (win.alphaSupport ? '<label title="' + localization.tooltips.alpha.radio + '"><input type="radio" value="a"' + (settings.color.mode === 'a' ? ' checked="checked"' : '') + '/>A:</label>' : ' ') + '</td><td class="Text">' + (win.alphaSupport ? '<input type="text" maxlength="' + (3 + win.alphaPrecision) + '" value="' + (all != null ? Math.precision(all.a * 100 / 255, win.alphaPrecision) : '') + '" title="' + localization.tooltips.alpha.textbox + '"/> %' : ' ') + '</td></tr><tr class="Hex"><td colspan="2" class="Text"><label title="' + localization.tooltips.hex.textbox + '">#:<input type="text" maxlength="6" class="Hex" value="' + (all != null ? all.hex : '') + '"/></label>' + (win.alphaSupport ? '<input type="text" maxlength="2" class="AHex" value="' + (all != null ? all.ahex.substring(6) : '') + '" title="' + localization.tooltips.hex.alpha + '"/></td>' : ' ') + '</tr></tbody></table>'; + var controlHtml = "<table class=\"jPicker\" cellpadding=\"0\" cellspacing=\"0\">\n <tbody>\n ".concat(win.expandable ? "<tr><td class=\"Move\" colspan=\"5\"> </td></tr>" : '', "\n <tr>\n <td rowspan=\"9\"><h2 class=\"Title\">").concat(win.title || localization.text.title, "</h2><div class=\"Map\"><span class=\"Map1\"> </span><span class=\"Map2\"> </span><span class=\"Map3\"> </span><img src=\"").concat(images.clientPath + images.colorMap.arrow.file, "\" class=\"Arrow\"/></div></td>\n <td rowspan=\"9\"><div class=\"Bar\"><span class=\"Map1\"> </span><span class=\"Map2\"> </span><span class=\"Map3\"> </span><span class=\"Map4\"> </span><span class=\"Map5\"> </span><span class=\"Map6\"> </span><img src=\"").concat(images.clientPath + images.colorBar.arrow.file, "\" class=\"Arrow\"/></div></td>\n <td colspan=\"2\" class=\"Preview\">").concat(localization.text.newColor, "<div><span class=\"Active\" title=\"").concat(localization.tooltips.colors.newColor, "\"> </span><span class=\"Current\" title=\"").concat(localization.tooltips.colors.currentColor, "\"> </span></div>").concat(localization.text.currentColor, "</td>\n <td rowspan=\"9\" class=\"Button\"><input type=\"button\" class=\"Ok\" value=\"").concat(localization.text.ok, "\" title=\"").concat(localization.tooltips.buttons.ok, "\"/><input type=\"button\" class=\"Cancel\" value=\"").concat(localization.text.cancel, "\" title=\"").concat(localization.tooltips.buttons.cancel, "\"/><hr/><div class=\"Grid\"> </div></td>\n </tr>\n <tr class=\"Hue\">\n <td class=\"Radio\"><label title=\"").concat(localization.tooltips.hue.radio, "\"><input type=\"radio\" value=\"h\"").concat(settings.color.mode === 'h' ? ' checked="checked"' : '', "/>H:</label></td>\n <td class=\"Text\"><input type=\"text\" maxlength=\"3\" value=\"").concat(!isNullish$1(all) ? all.h : '', "\" title=\"").concat(localization.tooltips.hue.textbox, "\"/> °</td>\n </tr>\n <tr class=\"Saturation\">\n <td class=\"Radio\"><label title=\"").concat(localization.tooltips.saturation.radio, "\"><input type=\"radio\" value=\"s\"").concat(settings.color.mode === 's' ? ' checked="checked"' : '', "/>S:</label></td>\n <td class=\"Text\"><input type=\"text\" maxlength=\"3\" value=\"").concat(!isNullish$1(all) ? all.s : '', "\" title=\"").concat(localization.tooltips.saturation.textbox, "\"/> %</td>\n </tr>\n <tr class=\"Value\">\n <td class=\"Radio\"><label title=\"").concat(localization.tooltips.value.radio, "\"><input type=\"radio\" value=\"v\"").concat(settings.color.mode === 'v' ? ' checked="checked"' : '', "/>V:</label><br/><br/></td>\n <td class=\"Text\"><input type=\"text\" maxlength=\"3\" value=\"").concat(!isNullish$1(all) ? all.v : '', "\" title=\"").concat(localization.tooltips.value.textbox, "\"/> %<br/><br/></td>\n </tr>\n <tr class=\"Red\">\n <td class=\"Radio\"><label title=\"").concat(localization.tooltips.red.radio, "\"><input type=\"radio\" value=\"r\"").concat(settings.color.mode === 'r' ? ' checked="checked"' : '', "/>R:</label></td>\n <td class=\"Text\"><input type=\"text\" maxlength=\"3\" value=\"").concat(!isNullish$1(all) ? all.r : '', "\" title=\"").concat(localization.tooltips.red.textbox, "\"/></td>\n </tr>\n <tr class=\"Green\">\n <td class=\"Radio\"><label title=\"").concat(localization.tooltips.green.radio, "\"><input type=\"radio\" value=\"g\"").concat(settings.color.mode === 'g' ? ' checked="checked"' : '', "/>G:</label></td>\n <td class=\"Text\"><input type=\"text\" maxlength=\"3\" value=\"").concat(!isNullish$1(all) ? all.g : '', "\" title=\"").concat(localization.tooltips.green.textbox, "\"/></td>\n </tr>\n <tr class=\"Blue\">\n <td class=\"Radio\"><label title=\"").concat(localization.tooltips.blue.radio, "\"><input type=\"radio\" value=\"b\"").concat(settings.color.mode === 'b' ? ' checked="checked"' : '', "/>B:</label></td>\n <td class=\"Text\"><input type=\"text\" maxlength=\"3\" value=\"").concat(!isNullish$1(all) ? all.b : '', "\" title=\"").concat(localization.tooltips.blue.textbox, "\"/></td>\n </tr>\n <tr class=\"Alpha\">\n <td class=\"Radio\">").concat(win.alphaSupport ? "<label title=\"".concat(localization.tooltips.alpha.radio, "\"><input type=\"radio\" value=\"a\"").concat(settings.color.mode === 'a' ? ' checked="checked"' : '', "/>A:</label>") : ' ', "</td>\n <td class=\"Text\">").concat(win.alphaSupport ? "<input type=\"text\" maxlength=\"".concat(3 + win.alphaPrecision, "\" value=\"").concat(!isNullish$1(all) ? toFixedNumeric(all.a * 100 / 255, win.alphaPrecision) : '', "\" title=\"").concat(localization.tooltips.alpha.textbox, "\"/> %") : ' ', "</td>\n </tr>\n <tr class=\"Hex\">\n <td colspan=\"2\" class=\"Text\"><label title=\"").concat(localization.tooltips.hex.textbox, "\">#:<input type=\"text\" maxlength=\"6\" class=\"Hex\" value=\"").concat(!isNullish$1(all) ? all.hex : '', "\"/></label>").concat(win.alphaSupport ? "<input type=\"text\" maxlength=\"2\" class=\"AHex\" value=\"".concat(!isNullish$1(all) ? all.ahex.substring(6) : '', "\" title=\"").concat(localization.tooltips.hex.alpha, "\"/></td>") : ' ', "\n </tr>\n </tbody></table>"); + if (win.expandable) { container.html(controlHtml); + if (!$(document.body).children('div.jPicker.Container').length) { $(document.body).prepend(container); } else { $(document.body).children('div.jPicker.Container:last').after(container); } + container.mousedown(function () { - $(document.body).children('div.jPicker.Container').css({ zIndex: 10 }); - container.css({ zIndex: 20 }); + $(document.body).children('div.jPicker.Container').css({ + zIndex: 10 + }); + container.css({ + zIndex: 20 + }); }); container.css( // positions must be set and display set to absolute before source code injection or IE will size the container to fit the window { @@ -24013,10 +27257,11 @@ top: win.position.y === 'top' ? popup.offset().top - 312 + 'px' : win.position.y === 'center' ? popup.offset().top - 156 + 'px' : win.position.y === 'bottom' ? popup.offset().top + 25 + 'px' : popup.offset().top + parseInt(win.position.y) + 'px' }); } else { - container = $($this); + container = $(that); container.html(controlHtml); - } - // initialize the objects to the source code just injected + } // initialize the objects to the source code just injected + + var tbody = container.find('tbody:first'); colorMapDiv = tbody.find('div.Map:first'); colorBarDiv = tbody.find('div.Bar:first'); @@ -24030,8 +27275,8 @@ colorBarL3 = BarMaps.filter('.Map3:first'); colorBarL4 = BarMaps.filter('.Map4:first'); colorBarL5 = BarMaps.filter('.Map5:first'); - colorBarL6 = BarMaps.filter('.Map6:first'); - // create color pickers and maps + colorBarL6 = BarMaps.filter('.Map6:first'); // create color pickers and maps + colorMap = new Slider(colorMapDiv, { map: { width: images.colorMap.width, @@ -24057,79 +27302,103 @@ }); colorBar.bind(colorBarValueChanged); colorPicker = new ColorValuePicker(tbody, color.active, win.expandable && win.bindToInput ? win.input : null, win.alphaPrecision); - var hex = all != null ? all.hex : null, + var hex = !isNullish$1(all) ? all.hex : null, preview = tbody.find('.Preview'), button = tbody.find('.Button'); - activePreview = preview.find('.Active:first').css({ backgroundColor: hex && '#' + hex || 'transparent' }); - currentPreview = preview.find('.Current:first').css({ backgroundColor: hex && '#' + hex || 'transparent' }).bind('click', currentClicked); - setAlpha.call($this, currentPreview, Math.precision(color.current.val('a') * 100) / 255, 4); + activePreview = preview.find('.Active:first').css({ + backgroundColor: hex && '#' + hex || 'transparent' + }); + currentPreview = preview.find('.Current:first').css({ + backgroundColor: hex && '#' + hex || 'transparent' + }).bind('click', currentClicked); + setAlpha.call(that, currentPreview, toFixedNumeric(color.current.val('a') * 100 / 255, 4)); okButton = button.find('.Ok:first').bind('click', okClicked); cancelButton = button.find('.Cancel:first').bind('click', cancelClicked); grid = button.find('.Grid:first'); setTimeout(function () { - setImg.call($this, colorMapL1, images.clientPath + 'Maps.png'); - setImg.call($this, colorMapL2, images.clientPath + 'Maps.png'); - setImg.call($this, colorMapL3, images.clientPath + 'map-opacity.png'); - setImg.call($this, colorBarL1, images.clientPath + 'Bars.png'); - setImg.call($this, colorBarL2, images.clientPath + 'Bars.png'); - setImg.call($this, colorBarL3, images.clientPath + 'Bars.png'); - setImg.call($this, colorBarL4, images.clientPath + 'Bars.png'); - setImg.call($this, colorBarL5, images.clientPath + 'bar-opacity.png'); - setImg.call($this, colorBarL6, images.clientPath + 'AlphaBar.png'); - setImg.call($this, preview.find('div:first'), images.clientPath + 'preview-opacity.png'); + setImg.call(that, colorMapL1, images.clientPath + 'Maps.png'); + setImg.call(that, colorMapL2, images.clientPath + 'Maps.png'); + setImg.call(that, colorMapL3, images.clientPath + 'map-opacity.png'); + setImg.call(that, colorBarL1, images.clientPath + 'Bars.png'); + setImg.call(that, colorBarL2, images.clientPath + 'Bars.png'); + setImg.call(that, colorBarL3, images.clientPath + 'Bars.png'); + setImg.call(that, colorBarL4, images.clientPath + 'Bars.png'); + setImg.call(that, colorBarL5, images.clientPath + 'bar-opacity.png'); + setImg.call(that, colorBarL6, images.clientPath + 'AlphaBar.png'); + setImg.call(that, preview.find('div:first'), images.clientPath + 'preview-opacity.png'); }, 0); - tbody.find('td.Radio input').bind('click', radioClicked); - // initialize quick list + tbody.find('td.Radio input').bind('click', radioClicked); // initialize quick list + if (color.quickList && color.quickList.length > 0) { var html = ''; + for (var i = 0; i < color.quickList.length; i++) { /* if default colors are hex strings, change them to color objects */ - if (_typeof(color.quickList[i]).toString().toLowerCase() === 'string') color.quickList[i] = new Color({ hex: color.quickList[i] }); - var alpha = color.quickList[i].val('a'); - var ahex = color.quickList[i].val('ahex'); - if (!win.alphaSupport && ahex) ahex = ahex.substring(0, 6) + 'ff'; + if (_typeof(color.quickList[i]).toString().toLowerCase() === 'string') color.quickList[i] = new Color({ + hex: color.quickList[i] + }); + + var _alpha = color.quickList[i].val('a'); + + var _ahex = color.quickList[i].val('ahex'); + + if (!win.alphaSupport && _ahex) _ahex = _ahex.substring(0, 6) + 'ff'; var quickHex = color.quickList[i].val('hex'); - if (!ahex) ahex = '00000000'; - html += '<span class="QuickColor"' + (ahex && ' title="#' + ahex + '"' || 'none') + ' style="background-color:' + (quickHex && '#' + quickHex || '') + ';' + (quickHex ? '' : 'background-image:url(' + images.clientPath + 'NoColor.png)') + (win.alphaSupport && alpha && alpha < 255 ? ';opacity:' + Math.precision(alpha / 255, 4) + ';filter:Alpha(opacity=' + Math.precision(alpha / 2.55, 4) + ')' : '') + '"> </span>'; + if (!_ahex) _ahex = '00000000'; + html += '<span class="QuickColor"' + (' title="#' + _ahex + '"') + ' style="background-color:' + (quickHex && '#' + quickHex || '') + ';' + (quickHex ? '' : 'background-image:url(' + images.clientPath + 'NoColor.png)') + (win.alphaSupport && _alpha && _alpha < 255 ? ';opacity:' + toFixedNumeric(_alpha / 255, 4) + ';filter:Alpha(opacity=' + toFixedNumeric(_alpha / 2.55, 4) + ')' : '') + '"> </span>'; } - setImg.call($this, grid, images.clientPath + 'bar-opacity.png'); + + setImg.call(that, grid, images.clientPath + 'bar-opacity.png'); grid.html(html); grid.find('.QuickColor').click(quickPickClicked); } - setColorMode.call($this, settings.color.mode); + + setColorMode.call(that, settings.color.mode); color.active.bind(activeColorChanged); typeof liveCallback === 'function' && color.active.bind(liveCallback); - color.current.bind(currentColorChanged); - // bind to input + color.current.bind(currentColorChanged); // bind to input + if (win.expandable) { - $this.icon = popup.parents('.Icon:first'); - iconColor = $this.icon.find('.Color:first').css({ backgroundColor: hex && '#' + hex || 'transparent' }); - iconAlpha = $this.icon.find('.Alpha:first'); - setImg.call($this, iconAlpha, images.clientPath + 'bar-opacity.png'); - setAlpha.call($this, iconAlpha, Math.precision((255 - (all != null ? all.a : 0)) * 100 / 255, 4)); - iconImage = $this.icon.find('.Image:first').css({ + that.icon = popup.parents('.Icon:first'); + iconColor = that.icon.find('.Color:first').css({ + backgroundColor: hex && '#' + hex || 'transparent' + }); + iconAlpha = that.icon.find('.Alpha:first'); + setImg.call(that, iconAlpha, images.clientPath + 'bar-opacity.png'); + setAlpha.call(that, iconAlpha, toFixedNumeric((255 - (!isNullish$1(all) ? all.a : 0)) * 100 / 255, 4)); + iconImage = that.icon.find('.Image:first').css({ backgroundImage: 'url(\'' + images.clientPath + images.picker.file + '\')' }).bind('click', iconImageClicked); + if (win.bindToInput && win.updateInputColor) { win.input.css({ backgroundColor: hex && '#' + hex || 'transparent', - color: all == null || all.v > 75 ? '#000000' : '#ffffff' + color: isNullish$1(all) || all.v > 75 ? '#000000' : '#ffffff' }); } + moveBar = tbody.find('.Move:first').bind('mousedown', moveBarMouseDown); color.active.bind(expandableColorChanged); - } else show.call($this); + } else show.call(that); } + /** + * + * @returns {undefined} + */ + + function destroy() { container.find('td.Radio input').unbind('click', radioClicked); currentPreview.unbind('click', currentClicked); cancelButton.unbind('click', cancelClicked); okButton.unbind('click', okClicked); + if (settings.window.expandable) { iconImage.unbind('click', iconImageClicked); moveBar.unbind('mousedown', moveBarMouseDown); - $this.icon = null; + that.icon = null; } + container.find('.QuickColor').unbind('click', quickPickClicked); colorMapDiv = null; colorBarDiv = null; @@ -24157,24 +27426,43 @@ cancelCallback = null; liveCallback = null; container.html(''); + for (var i = 0; i < List.length; i++) { - if (List[i] === $this) { + if (List[i] === that) { List.splice(i, 1); } } } + var images = settings.images, localization = settings.localization; // local copies for YUI compressor var color = { - active: _typeof(settings.color.active).toString().toLowerCase() === 'string' ? new Color({ ahex: !settings.window.alphaSupport && settings.color.active ? settings.color.active.substring(0, 6) + 'ff' : settings.color.active - }) : new Color({ ahex: !settings.window.alphaSupport && settings.color.active.val('ahex') ? settings.color.active.val('ahex').substring(0, 6) + 'ff' : settings.color.active.val('ahex') + active: _typeof(settings.color.active).toString().toLowerCase() === 'string' ? new Color({ + ahex: !settings.window.alphaSupport && settings.color.active ? settings.color.active.substring(0, 6) + 'ff' : settings.color.active + }) : new Color({ + ahex: !settings.window.alphaSupport && settings.color.active.val('ahex') ? settings.color.active.val('ahex').substring(0, 6) + 'ff' : settings.color.active.val('ahex') }), - current: _typeof(settings.color.active).toString().toLowerCase() === 'string' ? new Color({ ahex: !settings.window.alphaSupport && settings.color.active ? settings.color.active.substring(0, 6) + 'ff' : settings.color.active }) : new Color({ ahex: !settings.window.alphaSupport && settings.color.active.val('ahex') ? settings.color.active.val('ahex').substring(0, 6) + 'ff' : settings.color.active.val('ahex') + current: _typeof(settings.color.active).toString().toLowerCase() === 'string' ? new Color({ + ahex: !settings.window.alphaSupport && settings.color.active ? settings.color.active.substring(0, 6) + 'ff' : settings.color.active + }) : new Color({ + ahex: !settings.window.alphaSupport && settings.color.active.val('ahex') ? settings.color.active.val('ahex').substring(0, 6) + 'ff' : settings.color.active.val('ahex') }), quickList: settings.color.quickList }; + if (typeof commitCallback !== 'function') { + commitCallback = null; + } + + if (typeof liveCallback !== 'function') { + liveCallback = null; + } + + if (typeof cancelCallback !== 'function') { + cancelCallback = null; + } + var elementStartX = null, // Used to record the starting css positions for dragging the control elementStartY = null, @@ -24211,25 +27499,25 @@ // iconAlpha for popup icon iconImage = null, // iconImage popup icon - moveBar = null, - // drag bar - commitCallback = typeof $arguments[1] === 'function' ? $arguments[1] : null, - liveCallback = typeof $arguments[2] === 'function' ? $arguments[2] : null, - cancelCallback = typeof $arguments[3] === 'function' ? $arguments[3] : null; + moveBar = null; // drag bar - $.extend(true, $this, { + $.extend(true, that, { // public properties, methods, and callbacks - commitCallback: commitCallback, // commitCallback function can be overridden to return the selected color to a method you specify when the user clicks "OK" - liveCallback: liveCallback, // liveCallback function can be overridden to return the selected color to a method you specify in live mode (continuous update) - cancelCallback: cancelCallback, // cancelCallback function can be overridden to a method you specify when the user clicks "Cancel" + commitCallback: commitCallback, + // commitCallback function can be overridden to return the selected color to a method you specify when the user clicks "OK" + liveCallback: liveCallback, + // liveCallback function can be overridden to return the selected color to a method you specify in live mode (continuous update) + cancelCallback: cancelCallback, + // cancelCallback function can be overridden to a method you specify when the user clicks "Cancel" color: color, show: show, hide: hide, destroy: destroy // destroys this control entirely, removing all events and objects, and removing itself from the List + }); - List.push($this); + List.push(that); setTimeout(function () { - initialize.call($this); + initialize.call(that); }, 0); }); }; @@ -24239,17 +27527,20 @@ * @property {Float} width * @property {Float} height */ + /** * @typedef {PlainObject} external:jQuery.fn.jPickerOptionsImagesDimensionsArrow * @property {Float} width * @property {Float} height * @property {external:jQuery.fn.jPickerOptionsIconInfo} arrow */ + /** * @typedef {PlainObject} external:jQuery.fn.jPickerOptionsRadioTextboxLocale * @property {string} radio * @property {string} textbox */ + /** * @typedef {PlainObject} external:jQuery.fn.jPickerOptions * @property {PlainObject} window @@ -24271,6 +27562,9 @@ * @property {Float} window.alphaPrecision Set decimal precision for alpha percentage display - hex codes do * not map directly to percentage integers - range 0-2 * @property {boolean} window.updateInputColor Set to `false` to prevent binded input colors from changing + * @property {boolean} [window.bindToInput] Added by `$.fn.jPicker` + * @property {boolean} [window.expandable] Added by `$.fn.jPicker` + * @property {external:jQuery} [window.input] Added by `$.fn.jPicker` * @property {PlainObject} color * @property {"h"|"s"|"v"|"r"|"g"|"b"|"a"} color.mode Symbols stand for "h" (hue), "s" (saturation), "v" (value), "r" (red), "g" (green), "b" (blue), "a" (alpha) * @property {Color|string} color.active Strings are HEX values (e.g. #ffc000) WITH OR WITHOUT the "#" prefix @@ -24306,6 +27600,7 @@ * @property {string} localization.tooltips.hex.textbox * @property {string} localization.tooltips.hex.alpha */ + /** * jPicker defaults - you can change anything in this section (such as the * clientPath to your images) without fear of breaking the program @@ -24314,6 +27609,8 @@ * @borrows external:jQuery.fn.jPickerOptions as external:jQuery.fn.jPicker.defaults * @see Source for all of the values */ + + $.fn.jPicker.defaults = { window: { title: null, @@ -24336,8 +27633,294 @@ }, color: { mode: 'h', - active: new Color({ ahex: '#ffcc00ff' }), - quickList: [new Color({ h: 360, s: 33, v: 100 }), new Color({ h: 360, s: 66, v: 100 }), new Color({ h: 360, s: 100, v: 100 }), new Color({ h: 360, s: 100, v: 75 }), new Color({ h: 360, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 100 }), new Color({ h: 30, s: 33, v: 100 }), new Color({ h: 30, s: 66, v: 100 }), new Color({ h: 30, s: 100, v: 100 }), new Color({ h: 30, s: 100, v: 75 }), new Color({ h: 30, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 90 }), new Color({ h: 60, s: 33, v: 100 }), new Color({ h: 60, s: 66, v: 100 }), new Color({ h: 60, s: 100, v: 100 }), new Color({ h: 60, s: 100, v: 75 }), new Color({ h: 60, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 80 }), new Color({ h: 90, s: 33, v: 100 }), new Color({ h: 90, s: 66, v: 100 }), new Color({ h: 90, s: 100, v: 100 }), new Color({ h: 90, s: 100, v: 75 }), new Color({ h: 90, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 70 }), new Color({ h: 120, s: 33, v: 100 }), new Color({ h: 120, s: 66, v: 100 }), new Color({ h: 120, s: 100, v: 100 }), new Color({ h: 120, s: 100, v: 75 }), new Color({ h: 120, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 60 }), new Color({ h: 150, s: 33, v: 100 }), new Color({ h: 150, s: 66, v: 100 }), new Color({ h: 150, s: 100, v: 100 }), new Color({ h: 150, s: 100, v: 75 }), new Color({ h: 150, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 50 }), new Color({ h: 180, s: 33, v: 100 }), new Color({ h: 180, s: 66, v: 100 }), new Color({ h: 180, s: 100, v: 100 }), new Color({ h: 180, s: 100, v: 75 }), new Color({ h: 180, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 40 }), new Color({ h: 210, s: 33, v: 100 }), new Color({ h: 210, s: 66, v: 100 }), new Color({ h: 210, s: 100, v: 100 }), new Color({ h: 210, s: 100, v: 75 }), new Color({ h: 210, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 30 }), new Color({ h: 240, s: 33, v: 100 }), new Color({ h: 240, s: 66, v: 100 }), new Color({ h: 240, s: 100, v: 100 }), new Color({ h: 240, s: 100, v: 75 }), new Color({ h: 240, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 20 }), new Color({ h: 270, s: 33, v: 100 }), new Color({ h: 270, s: 66, v: 100 }), new Color({ h: 270, s: 100, v: 100 }), new Color({ h: 270, s: 100, v: 75 }), new Color({ h: 270, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 10 }), new Color({ h: 300, s: 33, v: 100 }), new Color({ h: 300, s: 66, v: 100 }), new Color({ h: 300, s: 100, v: 100 }), new Color({ h: 300, s: 100, v: 75 }), new Color({ h: 300, s: 100, v: 50 }), new Color({ h: 180, s: 0, v: 0 }), new Color({ h: 330, s: 33, v: 100 }), new Color({ h: 330, s: 66, v: 100 }), new Color({ h: 330, s: 100, v: 100 }), new Color({ h: 330, s: 100, v: 75 }), new Color({ h: 330, s: 100, v: 50 }), new Color()] + active: new Color({ + ahex: '#ffcc00ff' + }), + quickList: [new Color({ + h: 360, + s: 33, + v: 100 + }), new Color({ + h: 360, + s: 66, + v: 100 + }), new Color({ + h: 360, + s: 100, + v: 100 + }), new Color({ + h: 360, + s: 100, + v: 75 + }), new Color({ + h: 360, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 100 + }), new Color({ + h: 30, + s: 33, + v: 100 + }), new Color({ + h: 30, + s: 66, + v: 100 + }), new Color({ + h: 30, + s: 100, + v: 100 + }), new Color({ + h: 30, + s: 100, + v: 75 + }), new Color({ + h: 30, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 90 + }), new Color({ + h: 60, + s: 33, + v: 100 + }), new Color({ + h: 60, + s: 66, + v: 100 + }), new Color({ + h: 60, + s: 100, + v: 100 + }), new Color({ + h: 60, + s: 100, + v: 75 + }), new Color({ + h: 60, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 80 + }), new Color({ + h: 90, + s: 33, + v: 100 + }), new Color({ + h: 90, + s: 66, + v: 100 + }), new Color({ + h: 90, + s: 100, + v: 100 + }), new Color({ + h: 90, + s: 100, + v: 75 + }), new Color({ + h: 90, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 70 + }), new Color({ + h: 120, + s: 33, + v: 100 + }), new Color({ + h: 120, + s: 66, + v: 100 + }), new Color({ + h: 120, + s: 100, + v: 100 + }), new Color({ + h: 120, + s: 100, + v: 75 + }), new Color({ + h: 120, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 60 + }), new Color({ + h: 150, + s: 33, + v: 100 + }), new Color({ + h: 150, + s: 66, + v: 100 + }), new Color({ + h: 150, + s: 100, + v: 100 + }), new Color({ + h: 150, + s: 100, + v: 75 + }), new Color({ + h: 150, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 50 + }), new Color({ + h: 180, + s: 33, + v: 100 + }), new Color({ + h: 180, + s: 66, + v: 100 + }), new Color({ + h: 180, + s: 100, + v: 100 + }), new Color({ + h: 180, + s: 100, + v: 75 + }), new Color({ + h: 180, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 40 + }), new Color({ + h: 210, + s: 33, + v: 100 + }), new Color({ + h: 210, + s: 66, + v: 100 + }), new Color({ + h: 210, + s: 100, + v: 100 + }), new Color({ + h: 210, + s: 100, + v: 75 + }), new Color({ + h: 210, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 30 + }), new Color({ + h: 240, + s: 33, + v: 100 + }), new Color({ + h: 240, + s: 66, + v: 100 + }), new Color({ + h: 240, + s: 100, + v: 100 + }), new Color({ + h: 240, + s: 100, + v: 75 + }), new Color({ + h: 240, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 20 + }), new Color({ + h: 270, + s: 33, + v: 100 + }), new Color({ + h: 270, + s: 66, + v: 100 + }), new Color({ + h: 270, + s: 100, + v: 100 + }), new Color({ + h: 270, + s: 100, + v: 75 + }), new Color({ + h: 270, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 10 + }), new Color({ + h: 300, + s: 33, + v: 100 + }), new Color({ + h: 300, + s: 66, + v: 100 + }), new Color({ + h: 300, + s: 100, + v: 100 + }), new Color({ + h: 300, + s: 100, + v: 75 + }), new Color({ + h: 300, + s: 100, + v: 50 + }), new Color({ + h: 180, + s: 0, + v: 0 + }), new Color({ + h: 330, + s: 33, + v: 100 + }), new Color({ + h: 330, + s: 66, + v: 100 + }), new Color({ + h: 330, + s: 100, + v: 100 + }), new Color({ + h: 330, + s: 100, + v: 75 + }), new Color({ + h: 330, + s: 100, + v: 50 + }), new Color()] }, images: { clientPath: '/jPicker/images/', @@ -24420,45 +28003,47 @@ return $; }; - /* globals jQuery */ - var $$a = jQuery; - - var langParam = void 0; - + var langParam; /** * @param {"content"|"title"} type * @param {module:locale.LocaleSelectorValue} obj * @param {boolean} ids * @returns {undefined} */ + var setStrings = function setStrings(type, obj, ids) { // Root element to look for element from var parent = $$a('#svg_editor').parent(); Object.entries(obj).forEach(function (_ref) { - var _ref2 = slicedToArray(_ref, 2), + var _ref2 = _slicedToArray(_ref, 2), sel = _ref2[0], val = _ref2[1]; if (!val) { - console.log(sel); + console.log(sel); // eslint-disable-line no-console } if (ids) { sel = '#' + sel; } + var $elem = parent.find(sel); + if ($elem.length) { var elem = parent.find(sel)[0]; switch (type) { case 'content': - for (var i = 0, node; node = elem.childNodes[i]; i++) { + _toConsumableArray(elem.childNodes).some(function (node) { if (node.nodeType === 3 && node.textContent.trim()) { node.textContent = val; - break; + return true; } - } + + return false; + }); + break; case 'title': @@ -24466,11 +28051,10 @@ break; } } else { - console.log('Missing: ' + sel); + console.log('Missing element for localization: ' + sel); // eslint-disable-line no-console } }); }; - /** * The "data" property is generally set to an an array of objects with * "id" and "title" or "textContent" properties @@ -24481,23 +28065,24 @@ /** * @interface module:locale.LocaleEditorInit */ + /** * @function module:locale.LocaleEditorInit#addLangData * @param {string} langParam * @returns {module:locale.AddLangExtensionLocaleData} */ - var editor_ = void 0; + var editor_; /** * @function init * @memberof module:locale * @param {module:locale.LocaleEditorInit} editor * @returns {undefined} */ + var init$7 = function init(editor) { editor_ = editor; }; - /** * @typedef {PlainObject} module:locale.LangAndData * @property {string} langParam @@ -24510,8 +28095,13 @@ * @fires module:svgcanvas.SvgCanvas#event:ext-addLangData * @returns {Promise} Resolves to [`LangAndData`]{@link module:locale.LangAndData} */ - var readLang = function () { - var _ref3 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(langData) { + + var readLang = + /*#__PURE__*/ + function () { + var _ref3 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee(langData) { var more, _langData, tools, properties, config, layers, common, ui, opts; return regeneratorRuntime.wrap(function _callee$(_context) { @@ -24523,26 +28113,21 @@ case 2: more = _context.sent; - $$a.each(more, function (i, m) { if (m.data) { langData = $$a.merge(langData, m.data); } - }); - - // Old locale file, do nothing for now. + }); // Old locale file, do nothing for now. if (langData.tools) { _context.next = 6; break; } - return _context.abrupt('return'); + return _context.abrupt("return", undefined); case 6: _langData = langData, tools = _langData.tools, properties = _langData.properties, config = _langData.config, layers = _langData.layers, common = _langData.common, ui = _langData.ui; - - setStrings('content', { // copyrightLabel: misc.powered_by, // Currently commented out in svg-editor.html curve_segments: properties.curve_segments, @@ -24551,7 +28136,6 @@ fit_to_canvas: tools.fit_to_canvas, fit_to_layer_content: tools.fit_to_layer_content, fit_to_sel: tools.fit_to_sel, - icon_large: config.icon_large, icon_medium: config.icon_medium, icon_small: config.icon_small, @@ -24559,19 +28143,15 @@ image_opt_embed: config.image_opt_embed, image_opt_ref: config.image_opt_ref, includedImages: config.included_images, - largest_object: tools.largest_object, - layersLabel: layers.layers, page: tools.page, relativeToLabel: tools.relativeTo, selLayerLabel: layers.move_elems_to, selectedPredefined: config.select_predefined, - selected_objects: tools.selected_objects, smallest_object: tools.smallest_object, straight_segments: properties.straight_segments, - svginfo_bg_url: config.editor_img_url + ':', svginfo_bg_note: config.editor_bg_note, svginfo_change_background: config.background, @@ -24583,50 +28163,37 @@ svginfo_lang: config.language, svginfo_title: config.doc_title, svginfo_width: common.width, - tool_docprops_cancel: common.cancel, tool_docprops_save: common.ok, - tool_source_cancel: common.cancel, tool_source_save: common.ok, - tool_prefs_cancel: common.cancel, tool_prefs_save: common.ok, - sidepanel_handle: layers.layers.split('').join(' '), - tool_clear: tools.new_doc, tool_docprops: tools.docprops, tool_export: tools.export_img, tool_import: tools.import_doc, tool_open: tools.open_doc, tool_save: tools.save_doc, - svginfo_units_rulers: config.units_and_rulers, svginfo_rulers_onoff: config.show_rulers, svginfo_unit: config.base_unit, - svginfo_grid_settings: config.grid, svginfo_snap_onoff: config.snapping_onoff, svginfo_snap_step: config.snapping_stepsize, svginfo_grid_color: config.grid_color - }, true); + }, true); // Context menus - // Context menus opts = {}; - $$a.each(['cut', 'copy', 'paste', 'paste_in_place', 'delete', 'group', 'ungroup', 'move_front', 'move_up', 'move_down', 'move_back'], function () { opts['#cmenu_canvas a[href="#' + this + '"]'] = tools[this]; }); - $$a.each(['dupe', 'merge_down', 'merge_all'], function () { opts['#cmenu_layers a[href="#' + this + '"]'] = layers[this]; }); - opts['#cmenu_layers a[href="#delete"]'] = layers.del; - setStrings('content', opts); - setStrings('title', { align_relative_to: tools.align_relative_to, circle_cx: properties.circle_cx, @@ -24645,7 +28212,7 @@ image_width: properties.image_width, layer_delete: layers.del, layer_down: layers.move_down, - layer_new: layers['new'], + layer_new: layers.new, layer_rename: layers.rename, layer_moreopts: common.more_opts, layer_up: layers.move_up, @@ -24724,13 +28291,14 @@ tool_wireframe: tools.wireframe_mode, tool_zoom: tools.mode_zoom, url_notice: tools.no_embed - }, true); - - return _context.abrupt('return', { langParam: langParam, langData: langData }); + return _context.abrupt("return", { + langParam: langParam, + langData: langData + }); case 15: - case 'end': + case "end": return _context.stop(); } } @@ -24741,7 +28309,6 @@ return _ref3.apply(this, arguments); }; }(); - /** * @function module:locale.putLocale * @param {string} givenParam @@ -24752,8 +28319,13 @@ * @fires module:svgcanvas.SvgCanvas#event:ext-langChanged * @returns {Promise} Resolves to result of {@link module:locale.readLang} */ - var putLocale = function () { - var _ref4 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(givenParam, goodLangs, conf) { + + var putLocale = + /*#__PURE__*/ + function () { + var _ref4 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee2(givenParam, goodLangs, conf) { var url; return regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { @@ -24763,6 +28335,7 @@ langParam = givenParam; } else { langParam = $$a.pref('lang'); + if (!langParam) { if (navigator.userLanguage) { // Explorer @@ -24773,18 +28346,17 @@ } } - console.log('Lang: ' + langParam); - + console.log('Lang: ' + langParam); // eslint-disable-line no-console // Set to English if language is not in list of good langs + if (!goodLangs.includes(langParam) && langParam !== 'test') { langParam = 'en'; - } - - // don't bother on first run if language is English + } // don't bother on first run if language is English // The following line prevents setLang from running // extensions which depend on updated uiStrings, // so commenting it out. // if (langParam.startsWith('en')) {return;} + } url = conf.langPath + 'lang.' + langParam + '.js'; @@ -24796,10 +28368,10 @@ case 5: _context2.t1 = _context2.sent; - return _context2.abrupt('return', (0, _context2.t0)(_context2.t1)); + return _context2.abrupt("return", (0, _context2.t0)(_context2.t1)); case 7: - case 'end': + case "end": return _context2.stop(); } } @@ -24812,109 +28384,119 @@ }(); function loadStylesheets(stylesheets) { - var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, - beforeDefault = _ref.before, - afterDefault = _ref.after, - faviconDefault = _ref.favicon, - canvasDefault = _ref.canvas, - _ref$image = _ref.image, - imageDefault = _ref$image === undefined ? true : _ref$image, - acceptErrors = _ref.acceptErrors; + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + beforeDefault = _ref.before, + afterDefault = _ref.after, + faviconDefault = _ref.favicon, + canvasDefault = _ref.canvas, + _ref$image = _ref.image, + imageDefault = _ref$image === void 0 ? true : _ref$image, + acceptErrors = _ref.acceptErrors; - stylesheets = Array.isArray(stylesheets) ? stylesheets : [stylesheets]; + stylesheets = Array.isArray(stylesheets) ? stylesheets : [stylesheets]; - function setupLink(stylesheetURL) { - var options = {}; - if (Array.isArray(stylesheetURL)) { - var _stylesheetURL = stylesheetURL; + function setupLink(stylesheetURL) { + var options = {}; - var _stylesheetURL2 = slicedToArray(_stylesheetURL, 2); + if (Array.isArray(stylesheetURL)) { + var _stylesheetURL = stylesheetURL; - stylesheetURL = _stylesheetURL2[0]; - var _stylesheetURL2$ = _stylesheetURL2[1]; - options = _stylesheetURL2$ === undefined ? {} : _stylesheetURL2$; - } - var _options = options, - _options$favicon = _options.favicon, - favicon = _options$favicon === undefined ? faviconDefault : _options$favicon; - var _options2 = options, - _options2$before = _options2.before, - before = _options2$before === undefined ? beforeDefault : _options2$before, - _options2$after = _options2.after, - after = _options2$after === undefined ? afterDefault : _options2$after, - _options2$canvas = _options2.canvas, - canvas = _options2$canvas === undefined ? canvasDefault : _options2$canvas, - _options2$image = _options2.image, - image = _options2$image === undefined ? imageDefault : _options2$image; + var _stylesheetURL2 = _slicedToArray(_stylesheetURL, 2); - function addLink() { - if (before) { - before.before(link); - } else if (after) { - after.after(link); - } else { - document.head.appendChild(link); - } - } - - var link = document.createElement('link'); - return new Promise(function (resolve, reject) { - var rej = reject; - if (acceptErrors) { - rej = typeof acceptErrors === 'function' ? function (error) { - acceptErrors({ error: error, stylesheetURL: stylesheetURL, options: options, resolve: resolve, reject: reject }); - } : resolve; - } - if (stylesheetURL.endsWith('.css')) { - favicon = false; - } else if (stylesheetURL.endsWith('.ico')) { - favicon = true; - } - if (favicon) { - link.rel = 'shortcut icon'; - link.type = 'image/x-icon'; - - if (image === false) { - link.href = stylesheetURL; - addLink(); - resolve(link); - return; - } - - var cnv = document.createElement('canvas'); - cnv.width = 16; - cnv.height = 16; - var context = cnv.getContext('2d'); - var img = document.createElement('img'); - img.addEventListener('error', function (error) { - reject(error); - }); - img.addEventListener('load', function () { - context.drawImage(img, 0, 0); - link.href = canvas ? cnv.toDataURL('image/x-icon') : stylesheetURL; - addLink(); - resolve(link); - }); - img.src = stylesheetURL; - return; - } - link.rel = 'stylesheet'; - link.type = 'text/css'; - link.href = stylesheetURL; - addLink(); - link.addEventListener('error', function (error) { - rej(error); - }); - link.addEventListener('load', function () { - resolve(link); - }); - }); + stylesheetURL = _stylesheetURL2[0]; + var _stylesheetURL2$ = _stylesheetURL2[1]; + options = _stylesheetURL2$ === void 0 ? {} : _stylesheetURL2$; } - return Promise.all(stylesheets.map(setupLink)); - } + var _options = options, + _options$favicon = _options.favicon, + favicon = _options$favicon === void 0 ? faviconDefault : _options$favicon; + var _options2 = options, + _options2$before = _options2.before, + before = _options2$before === void 0 ? beforeDefault : _options2$before, + _options2$after = _options2.after, + after = _options2$after === void 0 ? afterDefault : _options2$after, + _options2$canvas = _options2.canvas, + canvas = _options2$canvas === void 0 ? canvasDefault : _options2$canvas, + _options2$image = _options2.image, + image = _options2$image === void 0 ? imageDefault : _options2$image; - /* globals jQuery */ + function addLink() { + if (before) { + before.before(link); + } else if (after) { + after.after(link); + } else { + document.head.appendChild(link); + } + } + + var link = document.createElement('link'); + return new Promise(function (resolve, reject) { + var rej = reject; + + if (acceptErrors) { + rej = typeof acceptErrors === 'function' ? function (error) { + acceptErrors({ + error: error, + stylesheetURL: stylesheetURL, + options: options, + resolve: resolve, + reject: reject + }); + } : resolve; + } + + if (stylesheetURL.endsWith('.css')) { + favicon = false; + } else if (stylesheetURL.endsWith('.ico')) { + favicon = true; + } + + if (favicon) { + link.rel = 'shortcut icon'; + link.type = 'image/x-icon'; + + if (image === false) { + link.href = stylesheetURL; + addLink(); + resolve(link); + return; + } + + var cnv = document.createElement('canvas'); + cnv.width = 16; + cnv.height = 16; + var context = cnv.getContext('2d'); + var img = document.createElement('img'); + img.addEventListener('error', function (error) { + reject(error); + }); + img.addEventListener('load', function () { + context.drawImage(img, 0, 0); + link.href = canvas ? cnv.toDataURL('image/x-icon') : stylesheetURL; + addLink(); + resolve(link); + }); + img.src = stylesheetURL; + return; + } + + link.rel = 'stylesheet'; + link.type = 'text/css'; + link.href = stylesheetURL; + addLink(); + link.addEventListener('error', function (error) { + rej(error); + }); + link.addEventListener('load', function () { + resolve(link); + }); + }); + } + + return Promise.all(stylesheets.map(setupLink)); + } /** * The main module for the visual SVG Editor @@ -24931,58 +28513,70 @@ * @borrows module:locale.readLang as readLang * @borrows module:locale.setStrings as setStrings */ + var editor = {}; - - var $$b = [jqPluginJSHotkeys, jqPluginBBQ, jqPluginSVGIcons, jqPluginJGraduate, jqPluginSpinBtn, jqPluginSVG, jQueryContextMenu, jPicker].reduce(function ($, cb) { - return cb($); + var $$b = [jQueryPluginJSHotkeys, jQueryPluginBBQ, jQueryPluginSVGIcons, jQueryPluginJGraduate, jQueryPluginSpinButton, jQueryPluginSVG, jQueryContextMenu, jPicker].reduce(function (jq, func) { + return func(jq); }, jQuery); - /* if (!$.loadingStylesheets) { $.loadingStylesheets = []; } */ + var stylesheet = 'svg-editor.css'; + if (!$$b.loadingStylesheets.includes(stylesheet)) { $$b.loadingStylesheets.push(stylesheet); } + var favicon = 'images/logo.png'; + if ($$b.loadingStylesheets.some(function (item) { return !Array.isArray(item) || item[0] !== favicon; })) { - $$b.loadingStylesheets.push([favicon, { favicon: true }]); - } - - // EDITOR PROPERTIES: (defined below) + $$b.loadingStylesheets.push([favicon, { + favicon: true + }]); + } // EDITOR PROPERTIES: (defined below) // curPrefs, curConfig, canvas, storage, uiStrings // // STATE MAINTENANCE PROPERTIES + /** * @type {Float} */ + + editor.tool_scale = 1; // Dependent on icon size, so any use to making configurable instead? Used by `jQuery.SpinButton.js` + /** * @type {Integer} */ + editor.exportWindowCt = 0; /** * @type {boolean} */ + editor.langChanged = false; /** * @type {boolean} */ + editor.showSaveWarning = false; /** - * @type {boolean} + * Will be set to a boolean by `ext-storage.js` + * @type {"ignore"|"waiting"|"closed"} */ - editor.storagePromptClosed = false; // For use with ext-storage.js + editor.storagePromptState = 'ignore'; var callbacks = [], /** * @typedef {"s"|"m"|"l"|"xl"|Float} module:SVGEditor.IconSize */ + /** * Preferences * @interface module:SVGEditor.Prefs @@ -24995,18 +28589,23 @@ * @property {boolean} [export_notice_done=false] Used to track alert status * @todo `save_notice_done` and `export_notice_done` should be changed to flags rather than preferences */ + /** * @namespace {module:SVGEditor.Prefs} defaultPrefs * @memberof module:SVGEditor~ * @implements {module:SVGEditor.Prefs} */ // The iteration algorithm for defaultPrefs does not currently support array/objects - defaultPrefs = /** @lends module:SVGEditor~defaultPrefs */{ + defaultPrefs = + /** @lends module:SVGEditor~defaultPrefs */ + { // EDITOR OPTIONS (DIALOG) + /** * Default to "en" if locale.js detection does not detect another language */ lang: '', + /** * Will default to 's' if the window height is smaller than the minimum height and * 'm' otherwise @@ -25031,12 +28630,14 @@ /** * @typedef {"@default"|string} module:SVGEditor.Stylesheet `@default` will automatically load all of the default CSS paths for SVGEditor */ + /** * @typedef {GenericArray} module:SVGEditor.XYDimensions * @property {Integer} length 2 * @property {Float} 0 * @property {Float} 1 */ + /** * @tutorial ConfigOptions * @interface module:SVGEditor.Config @@ -25058,7 +28659,7 @@ * @property {boolean} [emptyStorageOnDecline=false] Used by `ext-storage.js`; empty any prior storage if the user declines to store * @property {string[]} [extensions=module:SVGEditor~defaultExtensions] Extensions to load on startup. Use an array in `setConfig` and comma separated file names in the URL. Extension names must begin with "ext-". Note that as of version 2.7, paths containing "/", "\", or ":", are disallowed for security reasons. Although previous versions of this list would entirely override the default list, as of version 2.7, the defaults will always be added to this explicit list unless the configuration `noDefaultExtensions` is included. * @property {module:SVGEditor.Stylesheet[]} [stylesheets=["@default"]] An array of required stylesheets to load in parallel; include the value `"@default"` within this array to ensure all default stylesheets are loaded. - * @property {string[]} [allowedOrigins=[]] Used by `ext-xdomain-messaging.js` to indicate which origins are permitted for cross-domain messaging (e.g., between the embedded editor and main editor code). Besides explicit domains, one might add '' to allow all domains (not recommended for privacy/data integrity of your user's content!), `window.location.origin` for allowing the same origin (should be safe if you trust all apps on your domain), 'null' to allow `file://` URL usage + * @property {string[]} [allowedOrigins=[]] Used by `ext-xdomain-messaging.js` to indicate which origins are permitted for cross-domain messaging (e.g., between the embedded editor and main editor code). Besides explicit domains, one might add '*' to allow all domains (not recommended for privacy/data integrity of your user's content!), `window.location.origin` for allowing the same origin (should be safe if you trust all apps on your domain), 'null' to allow `file:///` URL usage * @property {null|PlainObject} [colorPickerCSS=null] Object of CSS properties mapped to values (for jQuery) to apply to the color picker. See {@link http://api.jquery.com/css/#css-properties}. A `null` value (the default) will cause the CSS to default to `left` with a position equal to that of the `fill_color` or `stroke_color` element minus 140, and a `bottom` equal to 40 * @property {string} [paramurl] This was available via URL only. Allowed an un-encoded URL within the query string (use "url" or "source" with a data: URI instead) * @property {Float} [canvas_expansion=3] The minimum area visible outside the canvas, as a multiple of the image dimensions. The larger the number, the more one can scroll outside the canvas. @@ -25089,6 +28690,7 @@ * @property {boolean} [selectNew=true] If true, will replace the selection with the current element and automatically select element objects (when not in "path" mode) after they are created, showing their grips (v2.6). Set and used in `svgcanvas.js` (`mouseUp`). * @todo Some others could be preferences as well (e.g., preventing URL changing of extensions, defaultExtensions, stylesheets, colorPickerCSS); Change the following to preferences and add pref controls where missing to the UI (e.g., `canvas_expansion`, `initFill`, `initStroke`, `text`, `initOpacity`, `dimensions`, `initTool`, `wireframe`, `showlayers`, `gridSnapping`, `gridColor`, `baseUnit`, `snappingStep`, `showRulers`, `exportWindowType`, `showGrid`, `show_outside_canvas`, `selectNew`)? */ + /** * @namespace {module:SVGEditor.Config} defaultConfig * @memberof module:SVGEditor~ @@ -25098,12 +28700,14 @@ canvasName: 'default', canvas_expansion: 3, initFill: { - color: 'FF0000', // solid red + color: 'FF0000', + // solid red opacity: 1 }, initStroke: { width: 5, - color: '000000', // solid black + color: '000000', + // solid black opacity: 1 }, text: { @@ -25112,21 +28716,27 @@ font_family: 'serif' }, initOpacity: 1, - colorPickerCSS: null, // Defaults to 'left' with a position equal to that of the fill_color or stroke_color element minus 140, and a 'bottom' equal to 40 + colorPickerCSS: null, + // Defaults to 'left' with a position equal to that of the fill_color or stroke_color element minus 140, and a 'bottom' equal to 40 initTool: 'select', - exportWindowType: 'new', // 'same' (todo: also support 'download') + exportWindowType: 'new', + // 'same' (todo: also support 'download') wireframe: false, showlayers: false, no_save_warning: false, // PATH CONFIGURATION // The following path configuration items are disallowed in the URL (as should any future path configurations) + langPath: 'locale/', + // Default will be changed if this is a non-modular load + extPath: 'extensions/', + // Default will be changed if this is a non-modular load + canvgPath: 'canvg/', + // Default will be changed if this is a non-modular load + jspdfPath: 'jspdf/', + // Default will be changed if this is a non-modular load imgPath: 'images/', - langPath: 'locale/', // Default will be changed if this is a modular load - extPath: 'extensions/', // Default will be changed if this is a modular load - canvgPath: 'canvg/', // Default will be changed if this is a modular load - jspdfPath: 'jspdf/', // Default will be changed if this is a modular load - extIconsPath: 'extensions/', jGraduatePath: 'jgraduate/images/', + extIconsPath: 'extensions/', // DOCUMENT PROPERTIES // Change the following to a preference (already in the Document Properties dialog)? dimensions: [640, 480], @@ -25141,14 +28751,20 @@ preventAllURLConfig: false, preventURLContentLoading: false, // EXTENSION CONFIGURATION (see also preventAllURLConfig) - lockExtensions: false, // Disallowed in URL setting - noDefaultExtensions: false, // noDefaultExtensions can only be meaningfully used in `svgedit-config-iife.js` or in the URL + lockExtensions: false, + // Disallowed in URL setting + noDefaultExtensions: false, + // noDefaultExtensions can only be meaningfully used in `svgedit-config-iife.js` or in the URL // EXTENSION-RELATED (GRID) - showGrid: false, // Set by ext-grid.js + showGrid: false, + // Set by ext-grid.js // EXTENSION-RELATED (STORAGE) - noStorageOnLoad: false, // Some interaction with ext-storage.js; prevent even the loading of previously saved local storage - forceStorage: false, // Some interaction with ext-storage.js; strongly discouraged from modification as it bypasses user privacy by preventing them from choosing whether to keep local storage or not + noStorageOnLoad: false, + // Some interaction with ext-storage.js; prevent even the loading of previously saved local storage + forceStorage: false, + // Some interaction with ext-storage.js; strongly discouraged from modification as it bypasses user privacy by preventing them from choosing whether to keep local storage or not emptyStorageOnDecline: false // Used by ext-storage.js; empty any prior storage if the user declines to store + }, /** @@ -25157,15 +28773,13 @@ * @type {PlainObject} */ uiStrings$1 = editor.uiStrings = {}; - - var svgCanvas = void 0, - urldata = void 0, + var svgCanvas, + urldata, isReady = false, customExportImage = false, customExportPDF = false, curPrefs = {}, - - // Note: The difference between Prefs and Config is that Prefs + // Note: The difference between Prefs and Config is that Prefs // can be changed in the UI and are stored in the browser, // while config cannot curConfig = { @@ -25173,121 +28787,168 @@ // procedures (we obtain instead from defaultExtensions) extensions: [], stylesheets: [], + /** - * Can use window.location.origin to indicate the current + * Can use `location.origin` to indicate the current * origin. Can contain a '*' to allow all domains or 'null' (as - * a string) to support all file:// URLs. Cannot be set by + * a string) to support all `file:///` URLs. Cannot be set by * URL for security reasons (not safe, at least for * privacy or data integrity of SVG content). * Might have been fairly safe to allow - * `new URL(window.location.href).origin` by default but + * `new URL(location.href).origin` by default but * avoiding it ensures some more security that even third * party apps on the same domain also cannot communicate * with this app by default. - * For use with ext-xdomain-messaging.js + * For use with `ext-xdomain-messaging.js` * @todo We might instead make as a user-facing preference. */ allowedOrigins: [] }; + /** + * + * @param {string} str SVG string + * @param {PlainObject} [opts={}] + * @param {boolean} [opts.noAlert] + * @throws {Error} Upon failure to load SVG + * @returns {Promise} Resolves to undefined upon success (or if `noAlert` is + * falsey, though only until after the `alert` is closed); rejects if SVG + * loading fails and `noAlert` is truthy. + */ - function loadSvgString(str, callback) { - var success = svgCanvas.setSvgString(str) !== false; - callback = callback || $$b.noop; - if (success) { - callback(true); // eslint-disable-line standard/no-callback-literal - } else { - $$b.alert(uiStrings$1.notification.errorLoadingSVG, function () { - callback(false); // eslint-disable-line standard/no-callback-literal - }); - } + function loadSvgString(_x) { + return _loadSvgString.apply(this, arguments); } - /** * @function module:SVGEditor~getImportLocale - * @param {string} defaultLang - * @param {string} defaultName + * @param {PlainObject} defaults + * @param {string} defaults.defaultLang + * @param {string} defaults.defaultName * @returns {module:SVGEditor~ImportLocale} */ + + + function _loadSvgString() { + _loadSvgString = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee23(str) { + var _ref45, + noAlert, + success, + _args23 = arguments; + + return regeneratorRuntime.wrap(function _callee23$(_context23) { + while (1) { + switch (_context23.prev = _context23.next) { + case 0: + _ref45 = _args23.length > 1 && _args23[1] !== undefined ? _args23[1] : {}, noAlert = _ref45.noAlert; + success = svgCanvas.setSvgString(str) !== false; + + if (!success) { + _context23.next = 4; + break; + } + + return _context23.abrupt("return"); + + case 4: + if (noAlert) { + _context23.next = 8; + break; + } + + _context23.next = 7; + return $$b.alert(uiStrings$1.notification.errorLoadingSVG); + + case 7: + return _context23.abrupt("return"); + + case 8: + throw new Error('Error loading SVG'); + + case 9: + case "end": + return _context23.stop(); + } + } + }, _callee23, this); + })); + return _loadSvgString.apply(this, arguments); + } + function getImportLocale(_ref) { var defaultLang = _ref.defaultLang, defaultName = _ref.defaultName; /** * @function module:SVGEditor~ImportLocale - * @param {string} [name] Defaults to `defaultName` of {@link module:SVGEditor~getImportLocale} - * @param {string} [lang=defaultLang] Defaults to `defaultLang` of {@link module:SVGEditor~getImportLocale} + * @param {PlainObject} localeInfo + * @param {string} [localeInfo.name] Defaults to `defaultName` 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} */ - return function () { - var _ref2 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2() { - var importLocale = function () { - var _ref4 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(lang) { - var url; - return regeneratorRuntime.wrap(function _callee$(_context) { - while (1) { - switch (_context.prev = _context.next) { - case 0: - url = curConfig.extPath + 'ext-locale/' + name + '/' + lang + '.js'; - return _context.abrupt('return', importSetGlobalDefault(url, { - global: 'svgEditorExtensionLocale_' + name + '_' + lang - })); + return ( + /*#__PURE__*/ + function () { + var _importLocaleDefaulting = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee() { + var _ref2, + _ref2$name, + name, + _ref2$lang, + lang, + importLocale, + _args = arguments; - case 2: - case 'end': - return _context.stop(); - } + return regeneratorRuntime.wrap(function _callee$(_context) { + while (1) { + switch (_context.prev = _context.next) { + case 0: + importLocale = function _ref3(language) { + var url = "".concat(curConfig.extPath, "ext-locale/").concat(name, "/").concat(language, ".js"); + return importSetGlobalDefault(url, { + global: "svgEditorExtensionLocale_".concat(name, "_").concat(language.replace(/-/g, '_')) + }); + }; + + _ref2 = _args.length > 0 && _args[0] !== undefined ? _args[0] : {}, _ref2$name = _ref2.name, name = _ref2$name === void 0 ? defaultName : _ref2$name, _ref2$lang = _ref2.lang, lang = _ref2$lang === void 0 ? defaultLang : _ref2$lang; + _context.prev = 2; + _context.next = 5; + return importLocale(lang); + + case 5: + return _context.abrupt("return", _context.sent); + + case 8: + _context.prev = 8; + _context.t0 = _context["catch"](2); + return _context.abrupt("return", importLocale('en')); + + case 11: + case "end": + return _context.stop(); } - }, _callee, this); - })); - - return function importLocale(_x2) { - return _ref4.apply(this, arguments); - }; - }(); - - var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, - _ref3$name = _ref3.name, - name = _ref3$name === undefined ? defaultName : _ref3$name, - _ref3$lang = _ref3.lang, - lang = _ref3$lang === undefined ? defaultLang : _ref3$lang; - - return regeneratorRuntime.wrap(function _callee2$(_context2) { - while (1) { - switch (_context2.prev = _context2.next) { - case 0: - _context2.prev = 0; - return _context2.abrupt('return', importLocale(lang)); - - case 4: - _context2.prev = 4; - _context2.t0 = _context2['catch'](0); - return _context2.abrupt('return', importLocale('en')); - - case 7: - case 'end': - return _context2.stop(); } - } - }, _callee2, this, [[0, 4]]); - })); + }, _callee, this, [[2, 8]]); + })); - function importLocale() { - return _ref2.apply(this, arguments); - } + function importLocaleDefaulting() { + return _importLocaleDefaulting.apply(this, arguments); + } - return importLocale; - }(); + return importLocaleDefaulting; + }() + ); } - /** * EXPORTS */ /** - * Store and retrieve preferences + * Store and retrieve preferences. * @param {string} key The preference name to be retrieved or set * @param {string} [val] The value. If the value supplied is missing or falsey, no change to the preference will be made. - * @returns {string} If val is missing or falsey, the value of the previously stored preference will be returned. + * @returns {string|undefined} If val is missing or falsey, the value of the previously stored preference will be returned. * @todo Can we change setting on the jQuery namespace (onto editor) to avoid conflicts? * @todo Review whether any remaining existing direct references to * getting `curPrefs` can be changed to use `$.pref()` getting to ensure @@ -25295,6 +28956,8 @@ * the pref dialog has a button to auto-calculate background, but otherwise uses `$.pref()` to be able to get default prefs * or overridable settings */ + + $$b.pref = function (key, val) { if (val) { curPrefs[key] = val; @@ -25303,21 +28966,24 @@ * @memberof module:SVGEditor * @implements {module:SVGEditor.Prefs} */ + editor.curPrefs = curPrefs; // Update exported value - return; + + return undefined; } + return key in curPrefs ? curPrefs[key] : defaultPrefs[key]; }; - /* * EDITOR PUBLIC METHODS // Todo: Sort these methods per invocation order, ideally with init at the end // Todo: Prevent execution until init executes if dependent on it? */ + + editor.putLocale = putLocale; editor.readLang = readLang; editor.setStrings = setStrings; - /** * Where permitted, sets canvas and/or `defaultPrefs` based on previous * storage. This will override URL settings (for security reasons) but @@ -25331,41 +28997,41 @@ * that, it will then be subject to tampering * @returns {undefined} */ - editor.loadContentAndPrefs = function () { - if (!curConfig.forceStorage && (curConfig.noStorageOnLoad || !document.cookie.match(/(?:^|;\s*)store=(?:prefsAndContent|prefsOnly)/))) { - return; - } - // LOAD CONTENT + editor.loadContentAndPrefs = function () { + if (!curConfig.forceStorage && (curConfig.noStorageOnLoad || !document.cookie.match(/(?:^|;\s*)svgeditstore=(?:prefsAndContent|prefsOnly)/))) { + return; + } // LOAD CONTENT + + if (editor.storage && ( // Cookies do not have enough available memory to hold large documents - curConfig.forceStorage || !curConfig.noStorageOnLoad && document.cookie.match(/(?:^|;\s*)store=prefsAndContent/))) { - var _name = 'svgedit-' + curConfig.canvasName; - var cached = editor.storage.getItem(_name); + curConfig.forceStorage || !curConfig.noStorageOnLoad && document.cookie.match(/(?:^|;\s*)svgeditstore=prefsAndContent/))) { + var name = 'svgedit-' + curConfig.canvasName; + var cached = editor.storage.getItem(name); + if (cached) { editor.loadFromString(cached); } - } + } // LOAD PREFS - // LOAD PREFS - for (var key in defaultPrefs) { - if (defaultPrefs.hasOwnProperty(key)) { - // It's our own config, so we don't need to iterate up the prototype chain - var storeKey = 'svg-edit-' + key; - if (editor.storage) { - var val = editor.storage.getItem(storeKey); - if (val) { - defaultPrefs[key] = String(val); // Convert to string for FF (.value fails in Webkit) - } - } else if (window.widget) { - defaultPrefs[key] = window.widget.preferenceForKey(storeKey); - } else { - var result = document.cookie.match(new RegExp('(?:^|;\\s*)' + regexEscape(encodeURIComponent(storeKey)) + '=([^;]+)')); - defaultPrefs[key] = result ? decodeURIComponent(result[1]) : ''; + + Object.keys(defaultPrefs).forEach(function (key) { + var storeKey = 'svg-edit-' + key; + + if (editor.storage) { + var val = editor.storage.getItem(storeKey); + + if (val) { + defaultPrefs[key] = String(val); // Convert to string for FF (.value fails in Webkit) } + } else if (window.widget) { + defaultPrefs[key] = window.widget.preferenceForKey(storeKey); + } else { + var result = document.cookie.match(new RegExp('(?:^|;\\s*)' + regexEscape(encodeURIComponent(storeKey)) + '=([^;]+)')); + defaultPrefs[key] = result ? decodeURIComponent(result[1]) : ''; } - } + }); }; - /** * Allows setting of preferences or configuration (including extensions). * @param {module:SVGEditor.Config|module:SVGEditor.Prefs} opts The preferences or configuration (including extensions). See the tutorial on {@tutorial ConfigOptions} for info on config and preferences. @@ -25386,8 +29052,18 @@ * not be needed in `svgedit-config-iife.js`. * @returns {undefined} */ + + editor.setConfig = function (opts, cfgCfg) { cfgCfg = cfgCfg || {}; + /** + * + * @param {module:SVGEditor.Config|module:SVGEditor.Prefs} cfgObj + * @param {string} key + * @param {Any} val See {@link module:SVGEditor.Config} or {@link module:SVGEditor.Prefs} + * @returns {undefined} + */ + function extendOrAdd(cfgObj, key, val) { if (cfgObj[key] && _typeof(cfgObj[key]) === 'object') { $$b.extend(true, cfgObj[key], val); @@ -25395,13 +29071,15 @@ cfgObj[key] = val; } } + $$b.each(opts, function (key, val) { - if (opts.hasOwnProperty(key)) { + if ({}.hasOwnProperty.call(opts, key)) { // Only allow prefs defined in defaultPrefs - if (defaultPrefs.hasOwnProperty(key)) { - if (cfgCfg.overwrite === false && (curConfig.preventAllURLConfig || curPrefs.hasOwnProperty(key))) { + if ({}.hasOwnProperty.call(defaultPrefs, key)) { + if (cfgCfg.overwrite === false && (curConfig.preventAllURLConfig || {}.hasOwnProperty.call(curPrefs, key))) { return; } + if (cfgCfg.allowInitialUserOverride === true) { defaultPrefs[key] = val; } else { @@ -25411,29 +29089,28 @@ if (cfgCfg.overwrite === false && (curConfig.preventAllURLConfig || ['allowedOrigins', 'stylesheets'].includes(key) || key === 'extensions' && curConfig.lockExtensions)) { return; } + curConfig[key] = curConfig[key].concat(val); // We will handle any dupes later // Only allow other curConfig if defined in defaultConfig - } else if (defaultConfig.hasOwnProperty(key)) { - if (cfgCfg.overwrite === false && (curConfig.preventAllURLConfig || curConfig.hasOwnProperty(key))) { + } else if ({}.hasOwnProperty.call(defaultConfig, key)) { + if (cfgCfg.overwrite === false && (curConfig.preventAllURLConfig || {}.hasOwnProperty.call(curConfig, key))) { return; - } - // Potentially overwriting of previously set config - if (curConfig.hasOwnProperty(key)) { + } // Potentially overwriting of previously set config + + + if ({}.hasOwnProperty.call(curConfig, key)) { if (cfgCfg.overwrite === false) { return; } + extendOrAdd(curConfig, key, val); + } else if (cfgCfg.allowInitialUserOverride === true) { + extendOrAdd(defaultConfig, key, val); + } else if (defaultConfig[key] && _typeof(defaultConfig[key]) === 'object') { + curConfig[key] = Array.isArray(defaultConfig[key]) ? [] : {}; + $$b.extend(true, curConfig[key], val); // Merge properties recursively, e.g., on initFill, initStroke objects } else { - if (cfgCfg.allowInitialUserOverride === true) { - extendOrAdd(defaultConfig, key, val); - } else { - if (defaultConfig[key] && _typeof(defaultConfig[key]) === 'object') { - curConfig[key] = {}; - $$b.extend(true, curConfig[key], val); // Merge properties recursively, e.g., on initFill, initStroke objects - } else { - curConfig[key] = val; - } - } + curConfig[key] = val; } } } @@ -25443,14 +29120,15 @@ * @memberof module:SVGEditor * @implements {module:SVGEditor.Config} */ + editor.curConfig = curConfig; // Update exported value }; - /** * All methods are optional * @interface module:SVGEditor.CustomHandler * @type {PlainObject} */ + /** * Its responsibilities are: * - invoke a file chooser dialog in 'open' mode @@ -25460,6 +29138,7 @@ * @function module:SVGEditor.CustomHandler#open * @returns {undefined} */ + /** * Its responsibilities are: * - accept the string contents of the current document @@ -25471,6 +29150,7 @@ * @listens module:svgcanvas.SvgCanvas#event:saved * @returns {undefined} */ + /** * Its responsibilities (with regard to the object it is supplied in its 2nd argument) are: * - inform user of any issues supplied via the "issues" property @@ -25484,6 +29164,7 @@ * @listens module:svgcanvas.SvgCanvas#event:exported * @returns {undefined} */ + /** * @function module:SVGEditor.CustomHandler#exportPDF * @param {external:Window} win @@ -25498,6 +29179,8 @@ * @param {module:SVGEditor.CustomHandler} opts Extension mechanisms may call `setCustomHandlers` with three functions: `opts.open`, `opts.save`, and `opts.exportImage` * @returns {undefined} */ + + editor.setCustomHandlers = function (opts) { editor.ready(function () { if (opts.open) { @@ -25505,35 +29188,41 @@ $$b('#tool_open').show(); svgCanvas.open = opts.open; } + if (opts.save) { editor.showSaveWarning = false; svgCanvas.bind('saved', opts.save); } + if (opts.exportImage) { customExportImage = opts.exportImage; svgCanvas.bind('exported', customExportImage); // canvg and our RGBColor will be available to the method } + if (opts.exportPDF) { customExportPDF = opts.exportPDF; svgCanvas.bind('exportedPDF', customExportPDF); // jsPDF and our RGBColor will be available to the method } }); }; - /** * @param {boolean} arg * @returns {undefined} */ + + editor.randomizeIds = function (arg) { return svgCanvas.randomizeIds(arg); }; - /** - * Auto-run after a Promise microtask + * Auto-run after a Promise microtask. * @returns {undefined} */ + + editor.init = function () { var modularVersion = !('svgEditor' in window) || !window.svgEditor || window.svgEditor.modules !== false; + if (!modularVersion) { Object.assign(defaultConfig, { langPath: '../dist/locale/', @@ -25541,18 +29230,20 @@ canvgPath: '../dist/', jspdfPath: '../dist/' }); - } - - // const host = location.hostname, + } // const host = location.hostname, // onWeb = host && host.includes('.'); // Some FF versions throw security errors here when directly accessing + + try { if ('localStorage' in window) { // && onWeb removed so Webkit works locally + /** * The built-in interface implemented by `localStorage` * @external Storage */ + /** * @name storage * @memberof module:SVGEditor @@ -25560,41 +29251,54 @@ */ editor.storage = localStorage; } - } catch (err) {} + } catch (err) {} // Todo: Avoid const-defined functions and group functions together, etc. where possible + - // Todo: Avoid const-defined functions and group functions together, etc. where possible var goodLangs = []; $$b('#lang_select option').each(function () { goodLangs.push(this.value); }); + /** + * Sets up current preferences based on defaults. + * @returns {undefined} + */ function setupCurPrefs() { curPrefs = $$b.extend(true, {}, defaultPrefs, curPrefs); // Now safe to merge with priority for curPrefs in the event any are already set // Export updated prefs + editor.curPrefs = curPrefs; } + /** + * Sets up current config based on defaults. + * @returns {undefined} + */ + + function setupCurConfig() { curConfig = $$b.extend(true, {}, defaultConfig, curConfig); // Now safe to merge with priority for curConfig in the event any are already set - // Now deal with extensions and other array config + if (!curConfig.noDefaultExtensions) { curConfig.extensions = curConfig.extensions.concat(defaultExtensions); - } - // ...and remove any dupes + } // ...and remove any dupes + + ['extensions', 'stylesheets', 'allowedOrigins'].forEach(function (cfg) { curConfig[cfg] = $$b.grep(curConfig[cfg], function (n, i) { // Supposedly faster than filter per http://amandeep1986.blogspot.hk/2015/02/jquery-grep-vs-js-filter.html return i === curConfig[cfg].indexOf(n); }); - }); - // Export updated config + }); // Export updated config + editor.curConfig = curConfig; } + (function () { // Load config/data from URL if given - var src = void 0, - qstr = void 0; + var src, qstr; urldata = $$b.deparam.querystring(true); + if (!$$b.isEmptyObject(urldata)) { if (urldata.dimensions) { urldata.dimensions = urldata.dimensions.split(','); @@ -25607,44 +29311,50 @@ if (urldata.extensions) { // For security reasons, disallow cross-domain or cross-folder extensions via URL urldata.extensions = urldata.extensions.match(/[:/\\]/) ? '' : urldata.extensions.split(','); - } - - // Disallowing extension paths via URL for + } // Disallowing extension paths via URL for // security reasons, even for same-domain // ones given potential to interact in undesirable // ways with other script resources - ['extPath', 'imgPath', 'extIconsPath', 'canvgPath', 'langPath', 'jGraduatePath', 'jspdfPath'].forEach(function (pathConfig) { + + + ['langPath', 'extPath', 'canvgPath', 'jspdfPath', 'imgPath', 'jGraduatePath', 'extIconsPath'].forEach(function (pathConfig) { if (urldata[pathConfig]) { delete urldata[pathConfig]; } }); - - editor.setConfig(urldata, { overwrite: false }); // Note: source and url (as with storagePrompt later) are not set on config but are used below + editor.setConfig(urldata, { + overwrite: false + }); // Note: source and url (as with storagePrompt later) are not set on config but are used below setupCurConfig(); if (!curConfig.preventURLContentLoading) { src = urldata.source; qstr = $$b.param.querystring(); + if (!src) { // urldata.source may have been null if it ended with '=' if (qstr.includes('source=data:')) { src = qstr.match(/source=(data:[^&]*)/)[1]; } } + if (src) { if (src.startsWith('data:')) { editor.loadFromDataURI(src); } else { editor.loadFromString(src); } + return; } + if (urldata.url) { editor.loadFromURL(urldata.url); return; } } + if (!urldata.noStorageOnLoad || curConfig.forceStorage) { editor.loadContentAndPrefs(); } @@ -25652,25 +29362,30 @@ setupCurConfig(); editor.loadContentAndPrefs(); } + setupCurPrefs(); })(); - /** - * Called internally + * Called internally. * @param {string|Element|external:jQuery} elem * @param {string|external:jQuery} iconId * @param {Float} forcedSize Not in use * @returns {undefined} */ + + var setIcon = editor.setIcon = function (elem, iconId, forcedSize) { var icon = typeof iconId === 'string' ? $$b.getSvgIcon(iconId, true) : iconId.clone(); + if (!icon) { - console.log('NOTE: Icon image missing: ' + iconId); + // Todo: Investigate why this still occurs in some cases + console.log('NOTE: Icon image missing: ' + iconId); // eslint-disable-line no-console + return; } + $$b(elem).empty().append(icon); }; - /** * @fires module:svgcanvas.SvgCanvas#event:ext-addLangData * @fires module:svgcanvas.SvgCanvas#event:ext-langReady @@ -25678,49 +29393,65 @@ * @fires module:svgcanvas.SvgCanvas#event:extensions_added * @returns {Promise} Resolves to result of {@link module:locale.readLang} */ - var extAndLocaleFunc = function () { - var _ref5 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4() { - var _this = this; - var _ref6, langParam, langData; - return regeneratorRuntime.wrap(function _callee4$(_context4) { + var extAndLocaleFunc = + /*#__PURE__*/ + function () { + var _ref4 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee3() { + var _ref5, langParam, langData, _uiStrings$common, ok, cancel; + + return regeneratorRuntime.wrap(function _callee3$(_context3) { while (1) { - switch (_context4.prev = _context4.next) { + switch (_context3.prev = _context3.next) { case 0: - _context4.next = 2; + _context3.next = 2; return editor.putLocale(null, goodLangs, curConfig); case 2: - _ref6 = _context4.sent; - langParam = _ref6.langParam; - langData = _ref6.langData; + _ref5 = _context3.sent; + langParam = _ref5.langParam; + langData = _ref5.langData; + _context3.next = 7; + return setLang(langParam, langData); - setLang(langParam, langData); + case 7: + _uiStrings$common = uiStrings$1.common, ok = _uiStrings$common.ok, cancel = _uiStrings$common.cancel; + jQueryPluginDBox($$b, { + ok: ok, + cancel: cancel + }); + setIcons(); // Wait for dbox as needed for i18n - _context4.prev = 6; - _context4.next = 9; - return Promise.all(curConfig.extensions.map(function () { - var _ref7 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(extname) { - var extName, url, imported, _imported$name, _name2, init$$1, importLocale; + _context3.prev = 10; + _context3.next = 13; + return Promise.all(curConfig.extensions.map( + /*#__PURE__*/ + function () { + var _ref6 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee2(extname) { + var extName, url, imported, _imported$name, name, init, importLocale; - return regeneratorRuntime.wrap(function _callee3$(_context3) { + return regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { - switch (_context3.prev = _context3.next) { + switch (_context2.prev = _context2.next) { case 0: extName = extname.match(/^ext-(.+)\.js/); if (extName) { - _context3.next = 3; + _context2.next = 3; break; } - return _context3.abrupt('return'); + return _context2.abrupt("return", undefined); case 3: - url = curConfig.extPath + extname; - // Todo: Replace this with `return import(url);` when + url = curConfig.extPath + extname; // Todo: Replace this with `return import(url);` when // `import()` widely supported + /** * @tutorial ExtensionDocs * @typedef {PlainObject} module:SVGEditor.ExtensionObject @@ -25728,39 +29459,48 @@ * @property {module:svgcanvas.ExtensionInitCallback} [init] */ - _context3.prev = 4; - _context3.next = 7; + _context2.prev = 4; + _context2.next = 7; return importSetGlobalDefault(url, { global: 'svgEditorExtension_' + extName[1].replace(/-/g, '_') }); case 7: - imported = _context3.sent; - _imported$name = imported.name, _name2 = _imported$name === undefined ? extName[1] : _imported$name, init$$1 = imported.init; - importLocale = getImportLocale({ defaultLang: langParam, defaultName: _name2 }); - return _context3.abrupt('return', editor.addExtension(_name2, init$$1 && init$$1.bind(editor), importLocale)); + imported = _context2.sent; + _imported$name = imported.name, name = _imported$name === void 0 ? extName[1] : _imported$name, init = imported.init; + importLocale = getImportLocale({ + defaultLang: langParam, + defaultName: name + }); + return _context2.abrupt("return", editor.addExtension(name, init && init.bind(editor), { + $: $$b, + importLocale: importLocale + })); case 13: - _context3.prev = 13; - _context3.t0 = _context3['catch'](4); + _context2.prev = 13; + _context2.t0 = _context2["catch"](4); + // Todo: Add config to alert any errors + console.log(_context2.t0); // eslint-disable-line no-console - console.log(_context3.t0); - console.error('Extension failed to load: ' + extname + '; ' + _context3.t0); + console.error('Extension failed to load: ' + extname + '; ' + _context2.t0); // eslint-disable-line no-console - case 17: - case 'end': - return _context3.stop(); + return _context2.abrupt("return", undefined); + + case 18: + case "end": + return _context2.stop(); } } - }, _callee3, _this, [[4, 13]]); + }, _callee2, this, [[4, 13]]); })); - return function (_x3) { - return _ref7.apply(this, arguments); + return function (_x2) { + return _ref6.apply(this, arguments); }; }())); - case 9: + case 13: svgCanvas.bind('extensions_added', /** * @param {external:Window} win @@ -25771,10 +29511,14 @@ function (win, data) { extensionsAdded = true; Actions.setAll(); - $$b('.flyout_arrow_horiz:empty').each(function () { $$b(this).append($$b.getSvgIcon('arrow_right', true).width(5).height(5)); }); + + if (editor.storagePromptState === 'ignore') { + updateCanvas(true); + } + messageQueue.forEach( /** * @param {module:svgcanvas.SvgCanvas#event:message} messageObj @@ -25786,29 +29530,35 @@ }); }); svgCanvas.call('extensions_added'); - _context4.next = 16; + _context3.next = 20; break; - case 13: - _context4.prev = 13; - _context4.t0 = _context4['catch'](6); + case 17: + _context3.prev = 17; + _context3.t0 = _context3["catch"](10); + // Todo: Report errors through the UI + console.log(_context3.t0); // eslint-disable-line no-console - console.log(_context4.t0); - - case 16: - case 'end': - return _context4.stop(); + case 20: + case "end": + return _context3.stop(); } } - }, _callee4, this, [[6, 13]]); + }, _callee3, this, [[10, 17]]); })); return function extAndLocaleFunc() { - return _ref5.apply(this, arguments); + return _ref4.apply(this, arguments); }; }(); - var stateObj = { tool_scale: editor.tool_scale }; + var stateObj = { + tool_scale: editor.tool_scale + }; + /** + * + * @returns {undefined} + */ var setFlyoutPositions = function setFlyoutPositions() { $$b('.tools_flyout').each(function () { @@ -25819,87 +29569,106 @@ top = _shower$offset.top; var w = shower.outerWidth(); - $$b(this).css({ left: (left + w) * editor.tool_scale, top: top }); + $$b(this).css({ + left: (left + w) * editor.tool_scale, + top: top + }); }); }; + /** + * @type {string} + */ + var uaPrefix = function () { var regex = /^(Moz|Webkit|Khtml|O|ms|Icab)(?=[A-Z])/; var someScript = document.getElementsByTagName('script')[0]; + for (var prop in someScript.style) { if (regex.test(prop)) { // test is faster than match, so it's better to perform // that on the lot and match only when necessary return prop.match(regex)[0]; } - } - // Nothing found so far? + } // Nothing found so far? + + if ('WebkitOpacity' in someScript.style) { return 'Webkit'; } + if ('KhtmlOpacity' in someScript.style) { return 'Khtml'; } return ''; }(); + /** + * @param {external:jQuery} elems + * @param {Float} scale + * @returns {undefined} + */ + var scaleElements = function scaleElements(elems, scale) { // const prefix = '-' + uaPrefix.toLowerCase() + '-'; // Currently unused var sides = ['top', 'left', 'bottom', 'right']; - elems.each(function () { // Handled in CSS // this.style[uaPrefix + 'Transform'] = 'scale(' + scale + ')'; var el = $$b(this); var w = el.outerWidth() * (scale - 1); - var h = el.outerHeight() * (scale - 1); - // const margins = {}; // Currently unused + var h = el.outerHeight() * (scale - 1); // const margins = {}; // Currently unused for (var i = 0; i < 4; i++) { var s = sides[i]; var cur = el.data('orig_margin-' + s); - if (cur == null) { - cur = parseInt(el.css('margin-' + s), 10); - // Cache the original margin + + if (isNullish(cur)) { + cur = parseInt(el.css('margin-' + s)); // Cache the original margin + el.data('orig_margin-' + s, cur); } + var val = cur * scale; + if (s === 'right') { val += w; } else if (s === 'bottom') { val += h; } - el.css('margin-' + s, val); - // el.css('outline', '1px solid red'); + el.css('margin-' + s, val); // el.css('outline', '1px solid red'); } }); }; - /** * Called internally. * @param {module:SVGEditor.IconSize} size * @returns {undefined} */ + + var setIconSize = editor.setIconSize = function (size) { // const elems = $('.tool_button, .push_button, .tool_button_current, .disabled, .icon_label, #url_notice, #tool_open'); var selToscale = '#tools_top .toolset, #editor_panel > *, #history_panel > *,' + ' #main_button, #tools_left > *, #path_node_panel > *, #multiselected_panel > *,' + ' #g_panel > *, #tool_font_size > *, .tools_flyout'; - var elems = $$b(selToscale); - var scale = 1; + if (typeof size === 'number') { scale = size; } else { - var iconSizes = { s: 0.75, m: 1, l: 1.25, xl: 1.5 }; + var iconSizes = { + s: 0.75, + m: 1, + l: 1.25, + xl: 1.5 + }; scale = iconSizes[size]; } stateObj.tool_scale = editor.tool_scale = scale; - - setFlyoutPositions(); - // $('.tools_flyout').each(function () { + setFlyoutPositions(); // $('.tools_flyout').each(function () { // const pos = $(this).position(); // console.log($(this), pos.left+(34 * scale)); // $(this).css({left: pos.left+(34 * scale), top: pos.top+(77 * scale)}); @@ -25911,13 +29680,10 @@ var hiddenPs = elems.parents(':hidden'); hiddenPs.css('visibility', 'hidden').show(); scaleElements(elems, scale); - hiddenPs.css('visibility', 'visible').hide(); - // return; + hiddenPs.css('visibility', 'visible').hide(); // return; $$b.pref('iconsize', size); - $$b('#iconsize').val(size); - - // Change icon size + $$b('#iconsize').val(size); // Change icon size // $('.tool_button, .push_button, .tool_button_current, .disabled, .icon_label, #url_notice, #tool_open') // .find('> svg, > img').each(function () { // this.setAttribute('width',size_num); @@ -25932,8 +29698,8 @@ // if (size != 's') { // $.resizeSvgIcons({'#layerbuttons svg, #layerbuttons img': size_num * .6}); // } - // Note that all rules will be prefixed with '#svg_editor' when parsed + var cssResizeRules = { // '.tool_button,\ // .push_button,\ @@ -25964,8 +29730,7 @@ }, 'div#workarea': { left: 38, - top: 74 - // '#tools_bottom': { + top: 74 // '#tools_bottom': { // left: {s: '27px', l: '46px', xl: '65px'}, // height: {s: '58px', l: '98px', xl: '145px'} // }, @@ -26047,9 +29812,11 @@ // '#position_opts': { // width: {all: (size_num*4) +'px'} // } - } }; + } + }; var ruleElem = $$b('#tool_size_rules'); + if (!ruleElem.length) { ruleElem = $$b('<style id="tool_size_rules"></style>').appendTo('head'); } else { @@ -26062,17 +29829,19 @@ selector = '#svg_editor ' + selector.replace(/,/g, ', #svg_editor'); styleStr += selector + '{'; $$b.each(rules, function (prop, values) { - var val = void 0; + var val; + if (typeof values === 'number') { val = values * scale + 'px'; } else if (values[size] || values.all) { val = values[size] || values.all; } + styleStr += prop + ':' + val + ';'; }); styleStr += '}'; - }); - // this.style[uaPrefix + 'Transform'] = 'scale(' + scale + ')'; + }); // this.style[uaPrefix + 'Transform'] = 'scale(' + scale + ')'; + var prefix = '-' + uaPrefix.toLowerCase() + '-'; styleStr += selToscale + '{' + prefix + 'transform: scale(' + scale + ');}' + ' #svg_editor div.toolset .toolset {' + prefix + 'transform: scale(1); margin: 1px !important;}' + // Hack for markers ' #svg_editor .ui-slider {' + prefix + 'transform: scale(' + 1 / scale + ');}' // Hack for sliders @@ -26082,280 +29851,307 @@ setFlyoutPositions(); }; - $$b.svgIcons(curConfig.imgPath + 'svg_edit_icons.svg', { - w: 24, h: 24, - id_match: false, - no_img: !isWebkit(), // Opera & Firefox 4 gives odd behavior w/images - fallback_path: curConfig.imgPath, - fallback: { - logo: 'logo.png', + /** + * Setup SVG icons + */ - select: 'select.png', - select_node: 'select_node.png', - square: 'square.png', - rect: 'rect.png', - fh_rect: 'freehand-square.png', - circle: 'circle.png', - ellipse: 'ellipse.png', - fh_ellipse: 'freehand-circle.png', - pencil: 'fhpath.png', - pen: 'line.png', - text: 'text.png', - path: 'path.png', - add_subpath: 'add_subpath.png', - close_path: 'closepath.png', - open_path: 'openpath.png', + function setIcons() { + $$b.svgIcons(curConfig.imgPath + 'svg_edit_icons.svg', { + w: 24, + h: 24, + id_match: false, + no_img: !isWebkit(), + // Opera & Firefox 4 gives odd behavior w/images + fallback_path: curConfig.imgPath, + fallback: { + logo: 'logo.png', + select: 'select.png', + select_node: 'select_node.png', + square: 'square.png', + rect: 'rect.png', + fh_rect: 'freehand-square.png', + circle: 'circle.png', + ellipse: 'ellipse.png', + fh_ellipse: 'freehand-circle.png', + pencil: 'fhpath.png', + pen: 'line.png', + text: 'text.png', + path: 'path.png', + add_subpath: 'add_subpath.png', + close_path: 'closepath.png', + open_path: 'openpath.png', + image: 'image.png', + zoom: 'zoom.png', + arrow_right: 'flyouth.png', + arrow_right_big: 'arrow_right_big.png', + arrow_down: 'dropdown.gif', + fill: 'fill.png', + stroke: 'stroke.png', + opacity: 'opacity.png', + new_image: 'clear.png', + save: 'save.png', + export: 'export.png', + open: 'open.png', + import: 'import.png', + docprops: 'document-properties.png', + source: 'source.png', + wireframe: 'wireframe.png', + undo: 'undo.png', + redo: 'redo.png', + clone: 'clone.png', + delete: 'delete.png', + go_up: 'go-up.png', + go_down: 'go-down.png', + context_menu: 'context_menu.png', + move_bottom: 'move_bottom.png', + move_top: 'move_top.png', + to_path: 'to_path.png', + link_controls: 'link_controls.png', + reorient: 'reorient.png', + group_elements: 'shape_group_elements.png', + ungroup: 'shape_ungroup.png', + unlink_use: 'unlink_use.png', + width: 'width.png', + height: 'height.png', + c_radius: 'c_radius.png', + angle: 'angle.png', + blur: 'blur.png', + fontsize: 'fontsize.png', + align: 'align.png', + align_left: 'align-left.png', + align_center: 'align-center.png', + align_right: 'align-right.png', + align_top: 'align-top.png', + align_middle: 'align-middle.png', + align_bottom: 'align-bottom.png', + linecap_butt: 'linecap_butt.png', + linecap_square: 'linecap_square.png', + linecap_round: 'linecap_round.png', + linejoin_miter: 'linejoin_miter.png', + linejoin_bevel: 'linejoin_bevel.png', + linejoin_round: 'linejoin_round.png', + eye: 'eye.png', + no_color: 'no_color.png', + ok: 'save.png', + cancel: 'cancel.png', + warning: 'warning.png', + node_delete: 'node_delete.png', + node_clone: 'node_clone.png', + globe_link: 'globe_link.png' + }, + placement: { + '#logo': 'logo', + '#tool_clear div,#layer_new': 'new_image', + '#tool_save div': 'save', + '#tool_export div': 'export', + '#tool_open div div': 'open', + '#tool_import div div': 'import', + '#tool_source': 'source', + '#tool_docprops > div': 'docprops', + '#tool_wireframe': 'wireframe', + '#tool_undo': 'undo', + '#tool_redo': 'redo', + '#tool_select': 'select', + '#tool_fhpath': 'pencil', + '#tool_line': 'pen', + '#tool_rect,#tools_rect_show': 'rect', + '#tool_square': 'square', + '#tool_fhrect': 'fh_rect', + '#tool_ellipse,#tools_ellipse_show': 'ellipse', + '#tool_circle': 'circle', + '#tool_fhellipse': 'fh_ellipse', + '#tool_path': 'path', + '#tool_text,#layer_rename': 'text', + '#tool_image': 'image', + '#tool_zoom': 'zoom', + '#tool_clone,#tool_clone_multi': 'clone', + '#tool_node_clone': 'node_clone', + '#layer_delete,#tool_delete,#tool_delete_multi': 'delete', + '#tool_node_delete': 'node_delete', + '#tool_add_subpath': 'add_subpath', + '#tool_openclose_path': 'open_path', + '#tool_move_top': 'move_top', + '#tool_move_bottom': 'move_bottom', + '#tool_topath': 'to_path', + '#tool_node_link': 'link_controls', + '#tool_reorient': 'reorient', + '#tool_group_elements': 'group_elements', + '#tool_ungroup': 'ungroup', + '#tool_unlink_use': 'unlink_use', + '#tool_alignleft, #tool_posleft': 'align_left', + '#tool_aligncenter, #tool_poscenter': 'align_center', + '#tool_alignright, #tool_posright': 'align_right', + '#tool_aligntop, #tool_postop': 'align_top', + '#tool_alignmiddle, #tool_posmiddle': 'align_middle', + '#tool_alignbottom, #tool_posbottom': 'align_bottom', + '#cur_position': 'align', + '#linecap_butt,#cur_linecap': 'linecap_butt', + '#linecap_round': 'linecap_round', + '#linecap_square': 'linecap_square', + '#linejoin_miter,#cur_linejoin': 'linejoin_miter', + '#linejoin_round': 'linejoin_round', + '#linejoin_bevel': 'linejoin_bevel', + '#url_notice': 'warning', + '#layer_up': 'go_up', + '#layer_down': 'go_down', + '#layer_moreopts': 'context_menu', + '#layerlist td.layervis': 'eye', + '#tool_source_save,#tool_docprops_save,#tool_prefs_save': 'ok', + '#tool_source_cancel,#tool_docprops_cancel,#tool_prefs_cancel': 'cancel', + '#rwidthLabel, #iwidthLabel': 'width', + '#rheightLabel, #iheightLabel': 'height', + '#cornerRadiusLabel span': 'c_radius', + '#angleLabel': 'angle', + '#linkLabel,#tool_make_link,#tool_make_link_multi': 'globe_link', + '#zoomLabel': 'zoom', + '#tool_fill label': 'fill', + '#tool_stroke .icon_label': 'stroke', + '#group_opacityLabel': 'opacity', + '#blurLabel': 'blur', + '#font_sizeLabel': 'fontsize', + '.flyout_arrow_horiz': 'arrow_right', + '.dropdown button, #main_button .dropdown': 'arrow_down', + '#palette .palette_item:first, #fill_bg, #stroke_bg': 'no_color' + }, + resize: { + '#logo .svg_icon': 28, + '.flyout_arrow_horiz .svg_icon': 5, + '.layer_button .svg_icon, #layerlist td.layervis .svg_icon': 14, + '.dropdown button .svg_icon': 7, + '#main_button .dropdown .svg_icon': 9, + '.palette_item:first .svg_icon': 15, + '#fill_bg .svg_icon, #stroke_bg .svg_icon': 16, + '.toolbar_button button .svg_icon': 16, + '.stroke_tool div div .svg_icon': 20, + '#tools_bottom label .svg_icon': 18 + }, + callback: function () { + var _callback = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee4(icons) { + var tleft, minHeight, size, getStylesheetPriority, stylesheets, idx, _stylesheets; - image: 'image.png', - zoom: 'zoom.png', + return regeneratorRuntime.wrap(function _callee4$(_context4) { + while (1) { + switch (_context4.prev = _context4.next) { + case 0: + getStylesheetPriority = function _ref8(stylesheetFile) { + switch (stylesheetFile) { + case 'jgraduate/css/jPicker.css': + return 1; - arrow_right: 'flyouth.png', - arrow_right_big: 'arrow_right_big.png', - arrow_down: 'dropdown.gif', - fill: 'fill.png', - stroke: 'stroke.png', - opacity: 'opacity.png', + case 'jgraduate/css/jGraduate.css': + return 2; - new_image: 'clear.png', - save: 'save.png', - export: 'export.png', - open: 'open.png', - import: 'import.png', - docprops: 'document-properties.png', - source: 'source.png', - wireframe: 'wireframe.png', + case 'svg-editor.css': + return 3; - undo: 'undo.png', - redo: 'redo.png', + case 'spinbtn/jQuery.SpinButton.css': + return 4; - clone: 'clone.png', - delete: 'delete.png', - go_up: 'go-up.png', - go_down: 'go-down.png', - context_menu: 'context_menu.png', - move_bottom: 'move_bottom.png', - move_top: 'move_top.png', - to_path: 'to_path.png', - link_controls: 'link_controls.png', - reorient: 'reorient.png', - group_elements: 'shape_group_elements.png', + default: + return Infinity; + } + }; - ungroup: 'shape_ungroup.png', - unlink_use: 'unlink_use.png', - width: 'width.png', - height: 'height.png', - c_radius: 'c_radius.png', - angle: 'angle.png', - blur: 'blur.png', - fontsize: 'fontsize.png', - align: 'align.png', + $$b('.toolbar_button button > svg, .toolbar_button button > img').each(function () { + $$b(this).parent().prepend(this); + }); + tleft = $$b('#tools_left'); - align_left: 'align-left.png', - align_center: 'align-center.png', - align_right: 'align-right.png', - align_top: 'align-top.png', - align_middle: 'align-middle.png', - align_bottom: 'align-bottom.png', + if (tleft.length) { + minHeight = tleft.offset().top + tleft.outerHeight(); + } - linecap_butt: 'linecap_butt.png', - linecap_square: 'linecap_square.png', - linecap_round: 'linecap_round.png', - linejoin_miter: 'linejoin_miter.png', - linejoin_bevel: 'linejoin_bevel.png', - linejoin_round: 'linejoin_round.png', - eye: 'eye.png', - no_color: 'no_color.png', + size = $$b.pref('iconsize'); + editor.setIconSize(size || ($$b(window).height() < minHeight ? 's' : 'm')); // Look for any missing flyout icons from plugins - ok: 'save.png', - cancel: 'cancel.png', - warning: 'warning.png', + $$b('.tools_flyout').each(function () { + var shower = $$b('#' + this.id + '_show'); + var sel = shower.attr('data-curopt'); // Check if there's an icon here - node_delete: 'node_delete.png', - node_clone: 'node_clone.png', + if (!shower.children('svg, img').length) { + var clone = $$b(sel).children().clone(); - globe_link: 'globe_link.png' - }, - placement: { - '#logo': 'logo', + if (clone.length) { + clone[0].removeAttribute('style'); // Needed for Opera - '#tool_clear div,#layer_new': 'new_image', - '#tool_save div': 'save', - '#tool_export div': 'export', - '#tool_open div div': 'open', - '#tool_import div div': 'import', - '#tool_source': 'source', - '#tool_docprops > div': 'docprops', - '#tool_wireframe': 'wireframe', + shower.append(clone); + } + } + }); + /** + * 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} + */ - '#tool_undo': 'undo', - '#tool_redo': 'redo', + stylesheets = $$b.loadingStylesheets.sort(function (a, b) { + var priorityA = getStylesheetPriority(a); + var priorityB = getStylesheetPriority(b); - '#tool_select': 'select', - '#tool_fhpath': 'pencil', - '#tool_line': 'pen', - '#tool_rect,#tools_rect_show': 'rect', - '#tool_square': 'square', - '#tool_fhrect': 'fh_rect', - '#tool_ellipse,#tools_ellipse_show': 'ellipse', - '#tool_circle': 'circle', - '#tool_fhellipse': 'fh_ellipse', - '#tool_path': 'path', - '#tool_text,#layer_rename': 'text', - '#tool_image': 'image', - '#tool_zoom': 'zoom', + if (priorityA === priorityB) { + return 0; + } - '#tool_clone,#tool_clone_multi': 'clone', - '#tool_node_clone': 'node_clone', - '#layer_delete,#tool_delete,#tool_delete_multi': 'delete', - '#tool_node_delete': 'node_delete', - '#tool_add_subpath': 'add_subpath', - '#tool_openclose_path': 'open_path', - '#tool_move_top': 'move_top', - '#tool_move_bottom': 'move_bottom', - '#tool_topath': 'to_path', - '#tool_node_link': 'link_controls', - '#tool_reorient': 'reorient', - '#tool_group_elements': 'group_elements', - '#tool_ungroup': 'ungroup', - '#tool_unlink_use': 'unlink_use', + return priorityA > priorityB; + }); - '#tool_alignleft, #tool_posleft': 'align_left', - '#tool_aligncenter, #tool_poscenter': 'align_center', - '#tool_alignright, #tool_posright': 'align_right', - '#tool_aligntop, #tool_postop': 'align_top', - '#tool_alignmiddle, #tool_posmiddle': 'align_middle', - '#tool_alignbottom, #tool_posbottom': 'align_bottom', - '#cur_position': 'align', + if (curConfig.stylesheets.length) { + // Ensure a copy with unique items + stylesheets = _toConsumableArray(new Set(curConfig.stylesheets)); + idx = stylesheets.indexOf('@default'); - '#linecap_butt,#cur_linecap': 'linecap_butt', - '#linecap_round': 'linecap_round', - '#linecap_square': 'linecap_square', + if (idx > -1) { + (_stylesheets = stylesheets).splice.apply(_stylesheets, [idx, 1].concat(_toConsumableArray($$b.loadingStylesheets))); + } + } - '#linejoin_miter,#cur_linejoin': 'linejoin_miter', - '#linejoin_round': 'linejoin_round', - '#linejoin_bevel': 'linejoin_bevel', + _context4.next = 11; + return loadStylesheets(stylesheets, { + acceptErrors: function acceptErrors(_ref7) { + var stylesheetURL = _ref7.stylesheetURL, + reject = _ref7.reject, + resolve = _ref7.resolve; - '#url_notice': 'warning', + if ($$b.loadingStylesheets.includes(stylesheetURL)) { + reject(new Error("Missing expected stylesheet: ".concat(stylesheetURL))); + return; + } - '#layer_up': 'go_up', - '#layer_down': 'go_down', - '#layer_moreopts': 'context_menu', - '#layerlist td.layervis': 'eye', + resolve(); + } + }); - '#tool_source_save,#tool_docprops_save,#tool_prefs_save': 'ok', - '#tool_source_cancel,#tool_docprops_cancel,#tool_prefs_cancel': 'cancel', + case 11: + $$b('#svg_container')[0].style.visibility = 'visible'; + _context4.next = 14; + return editor.runCallbacks(); - '#rwidthLabel, #iwidthLabel': 'width', - '#rheightLabel, #iheightLabel': 'height', - '#cornerRadiusLabel span': 'c_radius', - '#angleLabel': 'angle', - '#linkLabel,#tool_make_link,#tool_make_link_multi': 'globe_link', - '#zoomLabel': 'zoom', - '#tool_fill label': 'fill', - '#tool_stroke .icon_label': 'stroke', - '#group_opacityLabel': 'opacity', - '#blurLabel': 'blur', - '#font_sizeLabel': 'fontsize', + case 14: + case "end": + return _context4.stop(); + } + } + }, _callee4, this); + })); - '.flyout_arrow_horiz': 'arrow_right', - '.dropdown button, #main_button .dropdown': 'arrow_down', - '#palette .palette_item:first, #fill_bg, #stroke_bg': 'no_color' - }, - resize: { - '#logo .svg_icon': 28, - '.flyout_arrow_horiz .svg_icon': 5, - '.layer_button .svg_icon, #layerlist td.layervis .svg_icon': 14, - '.dropdown button .svg_icon': 7, - '#main_button .dropdown .svg_icon': 9, - '.palette_item:first .svg_icon': 15, - '#fill_bg .svg_icon, #stroke_bg .svg_icon': 16, - '.toolbar_button button .svg_icon': 16, - '.stroke_tool div div .svg_icon': 20, - '#tools_bottom label .svg_icon': 18 - }, - callback: function callback(icons) { - $$b('.toolbar_button button > svg, .toolbar_button button > img').each(function () { - $$b(this).parent().prepend(this); - }); - - var tleft = $$b('#tools_left'); - - var minHeight = void 0; - if (tleft.length) { - minHeight = tleft.offset().top + tleft.outerHeight(); - } - - var size = $$b.pref('iconsize'); - editor.setIconSize(size || ($$b(window).height() < minHeight ? 's' : 'm')); - - // Look for any missing flyout icons from plugins - $$b('.tools_flyout').each(function () { - var shower = $$b('#' + this.id + '_show'); - var sel = shower.attr('data-curopt'); - // Check if there's an icon here - if (!shower.children('svg, img').length) { - var clone = $$b(sel).children().clone(); - if (clone.length) { - clone[0].removeAttribute('style'); // Needed for Opera - shower.append(clone); - } + function callback(_x3) { + return _callback.apply(this, arguments); } - }); - - function getStylesheetPriority(stylesheet) { - switch (stylesheet) { - case 'jgraduate/css/jPicker.css': - return 1; - case 'jgraduate/css/jGraduate.css': - return 2; - case 'svg-editor.css': - return 3; - case 'spinbtn/jQuery.SpinButton.css': - return 4; - default: - return Infinity; - } - } - var stylesheets = $$b.loadingStylesheets.sort(function (a, b) { - var priorityA = getStylesheetPriority(a); - var priorityB = getStylesheetPriority(b); - if (priorityA === priorityB) { - return 0; - } - return priorityA > priorityB; - }); - if (curConfig.stylesheets.length) { - // Ensure a copy with unique items - stylesheets = [].concat(toConsumableArray(new Set(curConfig.stylesheets))); - var idx = stylesheets.indexOf('@default'); - if (idx > -1) { - var _stylesheets; - - (_stylesheets = stylesheets).splice.apply(_stylesheets, [idx, 1].concat(toConsumableArray($$b.loadingStylesheets))); - } - } - loadStylesheets(stylesheets, { acceptErrors: function acceptErrors(_ref8) { - var stylesheetURL = _ref8.stylesheetURL, - reject = _ref8.reject, - resolve = _ref8.resolve; - - if ($$b.loadingStylesheets.includes(stylesheetURL)) { - reject(new Error('Missing expected stylesheet: ' + stylesheetURL)); - return; - } - resolve(); - } }).then(function () { - $$b('#svg_container')[0].style.visibility = 'visible'; - editor.runCallbacks(); - }); - } - }); + return callback; + }() + }); + } /** * @name module:SVGEditor.canvas * @type {module:svgcanvas.SvgCanvas} */ + + editor.canvas = svgCanvas = new SvgCanvas(document.getElementById('svgcanvas'), curConfig); var palette = [// Todo: Make into configuration item? '#000000', '#3f3f3f', '#7f7f7f', '#bfbfbf', '#ffffff', '#ff0000', '#ff7f00', '#ffff00', '#7fff00', '#00ff00', '#00ff7f', '#00ffff', '#007fff', '#0000ff', '#7f00ff', '#ff00ff', '#ff007f', '#7f0000', '#7f3f00', '#7f7f00', '#3f7f00', '#007f00', '#007f3f', '#007f7f', '#003f7f', '#00007f', '#3f007f', '#7f007f', '#7f003f', '#ffaaaa', '#ffd4aa', '#ffffaa', '#d4ffaa', '#aaffaa', '#aaffd4', '#aaffff', '#aad4ff', '#aaaaff', '#d4aaff', '#ffaaff', '#ffaad4'], @@ -26365,21 +30161,21 @@ undoMgr = _svgCanvas.undoMgr, workarea = $$b('#workarea'), canvMenu = $$b('#cmenu_canvas'), - paintBox = { fill: null, stroke: null }; - - - var resizeTimer = void 0, - curScrollPos = void 0; + paintBox = { + fill: null, + stroke: null + }; + var resizeTimer, curScrollPos; var exportWindow = null, defaultImageURL = curConfig.imgPath + 'logo.png', zoomInIcon = 'crosshair', zoomOutIcon = 'crosshair', - uiContext = 'toolbars'; + uiContext = 'toolbars'; // For external openers - // For external openers (function () { // let the opener know SVG Edit is ready (now that config is set up) var w = window.opener || window.parent; + if (w) { try { /** @@ -26390,6 +30186,7 @@ * @property {true} bubbles * @property {true} cancelable */ + /** * @name module:SVGEditor.svgEditorReadyEvent * @type {module:SVGEditor#event:svgEditorReadyEvent} @@ -26402,158 +30199,71 @@ } catch (e) {} } })(); + /** + * + * @returns {undefined} + */ - // This sets up alternative dialog boxes. They mostly work the same way as - // their UI counterparts, expect instead of returning the result, a callback - // needs to be included that returns the result as its first parameter. - // In the future we may want to add additional types of dialog boxes, since - // they should be easy to handle this way. - (function () { - $$b('#dialog_container').draggable({ - cancel: '#dialog_content, #dialog_buttons *', - containment: 'window' - }).css('position', 'absolute'); - var box = $$b('#dialog_box'), - btnHolder = $$b('#dialog_buttons'), - dialogContent = $$b('#dialog_content'), - dbox = function dbox(type, msg, callback, defaultVal, opts, changeCb, checkbox) { - dialogContent.html('<p>' + msg.replace(/\n/g, '</p><p>') + '</p>').toggleClass('prompt', type === 'prompt'); - btnHolder.empty(); - - var ok = $$b('<input type="button" value="' + uiStrings$1.common.ok + '">').appendTo(btnHolder); - - if (type !== 'alert') { - $$b('<input type="button" value="' + uiStrings$1.common.cancel + '">').appendTo(btnHolder).click(function () { - box.hide(); - if (callback) { - callback(false); // eslint-disable-line standard/no-callback-literal - } - }); - } - - var ctrl = void 0, - chkbx = void 0; - if (type === 'prompt') { - ctrl = $$b('<input type="text">').prependTo(btnHolder); - ctrl.val(defaultVal || ''); - ctrl.bind('keydown', 'return', function () { - ok.click(); - }); - } else if (type === 'select') { - var div = $$b('<div style="text-align:center;">'); - ctrl = $$b('<select>').appendTo(div); - if (checkbox) { - var label = $$b('<label>').text(checkbox.label); - chkbx = $$b('<input type="checkbox">').appendTo(label); - chkbx.val(checkbox.value); - if (checkbox.tooltip) { - label.attr('title', checkbox.tooltip); - } - chkbx.prop('checked', !!checkbox.checked); - div.append($$b('<div>').append(label)); - } - $$b.each(opts || [], function (opt, val) { - if ((typeof val === 'undefined' ? 'undefined' : _typeof(val)) === 'object') { - ctrl.append($$b('<option>').val(val.value).html(val.text)); - } else { - ctrl.append($$b('<option>').html(val)); - } - }); - dialogContent.append(div); - if (defaultVal) { - ctrl.val(defaultVal); - } - if (changeCb) { - ctrl.bind('change', 'return', changeCb); - } - ctrl.bind('keydown', 'return', function () { - ok.click(); - }); - } else if (type === 'process') { - ok.hide(); - } - - box.show(); - - ok.click(function () { - box.hide(); - var resp = type === 'prompt' || type === 'select' ? ctrl.val() : true; - if (callback) { - if (chkbx) { - callback(resp, chkbx.prop('checked')); - } else { - callback(resp); - } - } - }).focus(); - - if (type === 'prompt' || type === 'select') { - ctrl.focus(); - } - }; - - $$b.alert = function (msg, cb) { - dbox('alert', msg, cb); - }; - $$b.confirm = function (msg, cb) { - dbox('confirm', msg, cb); - }; - $$b.process_cancel = function (msg, cb) { - dbox('process', msg, cb); - }; - $$b.prompt = function (msg, txt, cb) { - dbox('prompt', msg, cb, txt); - }; - $$b.select = function (msg, opts, cb, changeCb, txt, checkbox) { - dbox('select', msg, cb, txt, opts, changeCb, checkbox); - }; - })(); var setSelectMode = function setSelectMode() { var curr = $$b('.tool_button_current'); + if (curr.length && curr[0].id !== 'tool_select') { curr.removeClass('tool_button_current').addClass('tool_button'); $$b('#tool_select').addClass('tool_button_current').removeClass('tool_button'); - $$b('#styleoverrides').text('#svgcanvas svg *{cursor:move;pointer-events:all} #svgcanvas svg{cursor:default}'); + $$b('#styleoverrides').text("\n #svgcanvas svg * {\n cursor: move;\n pointer-events: all;\n }\n #svgcanvas svg {\n cursor: default;\n }\n "); } + svgCanvas.setMode('select'); workarea.css('cursor', 'auto'); - }; - - // used to make the flyouts stay on the screen longer the very first time + }; // used to make the flyouts stay on the screen longer the very first time // const flyoutspeed = 1250; // Currently unused // let textBeingEntered = false; // Currently unused - var origTitle = $$b('title:first').text(); - // Make [1,2,5] array + + + var origTitle = $$b('title:first').text(); // Make [1,2,5] array + var rIntervals = []; + for (var i = 0.1; i < 1E5; i *= 10) { rIntervals.push(i); rIntervals.push(2 * i); rIntervals.push(5 * i); } + /** + * This function highlights the layer passed in (by fading out the other layers). + * If no layer is passed in, this function restores the other layers + * @param {string} [layerNameToHighlight] + * @returns {undefined} + */ + - // This function highlights the layer passed in (by fading out the other layers) - // if no layer is passed in, this function restores the other layers var toggleHighlightLayer = function toggleHighlightLayer(layerNameToHighlight) { - var i = void 0; + var i; var curNames = [], numLayers = svgCanvas.getCurrentDrawing().getNumLayers(); + for (i = 0; i < numLayers; i++) { curNames[i] = svgCanvas.getCurrentDrawing().getLayerName(i); } if (layerNameToHighlight) { - for (i = 0; i < numLayers; ++i) { - if (curNames[i] !== layerNameToHighlight) { - svgCanvas.getCurrentDrawing().setLayerOpacity(curNames[i], 0.5); + curNames.forEach(function (curName) { + if (curName !== layerNameToHighlight) { + svgCanvas.getCurrentDrawing().setLayerOpacity(curName, 0.5); } - } + }); } else { - for (i = 0; i < numLayers; ++i) { - svgCanvas.getCurrentDrawing().setLayerOpacity(curNames[i], 1.0); - } + curNames.forEach(function (curName) { + svgCanvas.getCurrentDrawing().setLayerOpacity(curName, 1.0); + }); } }; + /** + * + * @returns {undefined} + */ + var populateLayers = function populateLayers() { svgCanvas.clearSelection(); @@ -26562,22 +30272,26 @@ var drawing = svgCanvas.getCurrentDrawing(); var currentLayerName = drawing.getCurrentLayerName(); var icon = $$b.getSvgIcon('eye'); - var layer = svgCanvas.getCurrentDrawing().getNumLayers(); - // we get the layers in the reverse z-order (the layer rendered on top is listed first) + var layer = svgCanvas.getCurrentDrawing().getNumLayers(); // we get the layers in the reverse z-order (the layer rendered on top is listed first) + while (layer--) { - var _name3 = drawing.getLayerName(layer); - var layerTr = $$b('<tr class="layer">').toggleClass('layersel', _name3 === currentLayerName); - var layerVis = $$b('<td class="layervis">').toggleClass('layerinvis', !drawing.getLayerVisibility(_name3)); - var layerName = $$b('<td class="layername">' + _name3 + '</td>'); + var name = drawing.getLayerName(layer); + var layerTr = $$b('<tr class="layer">').toggleClass('layersel', name === currentLayerName); + var layerVis = $$b('<td class="layervis">').toggleClass('layerinvis', !drawing.getLayerVisibility(name)); + var layerName = $$b('<td class="layername">' + name + '</td>'); layerlist.append(layerTr.append(layerVis, layerName)); - selLayerNames.append('<option value="' + _name3 + '">' + _name3 + '</option>'); + selLayerNames.append('<option value="' + name + '">' + name + '</option>'); } + if (icon !== undefined) { var copy = icon.clone(); $$b('td.layervis', layerlist).append(copy); - $$b.resizeSvgIcons({ 'td.layervis .svg_icon': 14 }); - } - // handle selection of layer + $$b.resizeSvgIcons({ + 'td.layervis .svg_icon': 14 + }); + } // handle selection of layer + + $$b('#layerlist td.layername').mouseup(function (evt) { $$b('#layerlist tr.layer').removeClass('layersel'); $$b(this.parentNode).addClass('layersel'); @@ -26594,10 +30308,10 @@ var vis = $$b(this).hasClass('layerinvis'); svgCanvas.setLayerVisibility(name, vis); $$b(this).toggleClass('layerinvis'); - }); + }); // if there were too few rows, let's add a few to make it not so lonely - // if there were too few rows, let's add a few to make it not so lonely var num = 5 - $$b('#layerlist tr.layer').size(); + while (num-- > 0) { // FIXME: there must a better way to do this layerlist.append('<tr><td style="color:white">_</td><td/></tr>'); @@ -26606,6 +30320,12 @@ var editingsource = false; var origSource = ''; + /** + * @param {Event} [e] Not used. + * @param {boolean} forSaving + * @returns {undefined} + */ + var showSourceEditor = function showSourceEditor(e, forSaving) { if (editingsource) { return; @@ -26613,7 +30333,7 @@ editingsource = true; origSource = svgCanvas.getSvgString(); - $$b('#save_output_btns').toggle(!!forSaving); + $$b('#save_output_btns').toggle(Boolean(forSaving)); $$b('#tool_source_back').toggle(!forSaving); $$b('#svg_source_textarea').val(origSource); $$b('#svg_source_editor').fadeIn(); @@ -26622,16 +30342,23 @@ var selectedElement = null; var multiselected = false; + /** + * @param {boolean} editmode + * @param {module:svgcanvas.SvgCanvas#event:selected} elems + * @returns {undefined} + */ var togglePathEditMode = function togglePathEditMode(editmode, elems) { $$b('#path_node_panel').toggle(editmode); $$b('#tools_bottom_2,#tools_bottom_3').toggle(!editmode); + if (editmode) { // Change select icon $$b('.tool_button_current').removeClass('tool_button_current').addClass('tool_button'); $$b('#tool_select').addClass('tool_button_current').removeClass('tool_button'); setIcon('#tool_select', 'select_node'); multiselected = false; + if (elems.length) { selectedElement = elems[0]; } @@ -26641,7 +30368,6 @@ }, 1000); } }; - /** * @type {module:svgcanvas.EventHandler} * @param {external:Window} wind @@ -26649,34 +30375,36 @@ * @listens module:svgcanvas.SvgCanvas#event:saved * @returns {undefined} */ + + var saveHandler = function saveHandler(wind, svg) { - editor.showSaveWarning = false; - - // by default, we add the XML prolog back, systems integrating SVG-edit (wikis, CMSs) + editor.showSaveWarning = false; // by default, we add the XML prolog back, systems integrating SVG-edit (wikis, CMSs) // can just provide their own custom save handler and might not want the XML prolog - svg = '<?xml version="1.0"?>\n' + svg; - // IE9 doesn't allow standalone Data URLs + svg = '<?xml version="1.0"?>\n' + svg; // IE9 doesn't allow standalone Data URLs // https://connect.microsoft.com/IE/feedback/details/542600/data-uri-images-fail-when-loaded-by-themselves + if (isIE()) { showSourceEditor(0, true); return; - } - - // Since saving SVGs by opening a new window was removed in Chrome use artificial link-click + } // Since saving SVGs by opening a new window was removed in Chrome use artificial link-click // https://stackoverflow.com/questions/45603201/window-is-not-allowed-to-navigate-top-frame-navigations-to-data-urls + + var a = document.createElement('a'); a.href = 'data:image/svg+xml;base64,' + encode64(svg); a.download = 'icon.svg'; + a.style = 'display: none;'; + document.body.append(a); // Need to append for Firefox - a.click(); - - // Alert will only appear the first time saved OR the + a.click(); // Alert will only appear the first time saved OR the // first time the bug is encountered + var done = $$b.pref('save_notice_done'); + if (done !== 'all') { - var note = uiStrings$1.notification.saveFromBrowser.replace('%s', 'SVG'); - // Check if FF and has <defs/> + var note = uiStrings$1.notification.saveFromBrowser.replace('%s', 'SVG'); // Check if FF and has <defs/> + if (isGecko()) { if (svg.includes('<defs')) { // warning about Mozilla bug #308590 when applicable (seems to be fixed now in Feb 2013) @@ -26689,125 +30417,147 @@ } else { $$b.pref('save_notice_done', 'all'); } + if (done !== 'part') { - alert(note); + $$b.alert(note); } } }; - /** * @param {external:Window} win * @param {module:svgcanvas.SvgCanvas#event:exported} data * @listens module:svgcanvas.SvgCanvas#event:exported * @returns {undefined} */ + + var exportHandler = function exportHandler(win, data) { var issues = data.issues, exportWindowName = data.exportWindowName; - - - if (exportWindowName) { - exportWindow = window.open(blankPageObjectURL || '', exportWindowName); // A hack to get the window via JSON-able name without opening a new one - } + exportWindow = window.open(blankPageObjectURL || '', exportWindowName); // A hack to get the window via JSON-able name without opening a new one if (!exportWindow || exportWindow.closed) { + /* await */ $$b.alert(uiStrings$1.notification.popupWindowBlocked); return; } exportWindow.location.href = data.bloburl || data.datauri; var done = $$b.pref('export_notice_done'); + if (done !== 'all') { - var note = uiStrings$1.notification.saveFromBrowser.replace('%s', data.type); + var note = uiStrings$1.notification.saveFromBrowser.replace('%s', data.type); // Check if there are issues - // Check if there are issues if (issues.length) { - var pre = '\n \u2022 '; + var pre = "\n \u2022 "; note += '\n\n' + uiStrings$1.notification.noteTheseIssues + pre + issues.join(pre); - } - - // Note that this will also prevent the notice even though new issues may appear later. + } // Note that this will also prevent the notice even though new issues may appear later. // May want to find a way to deal with that without annoying the user + + $$b.pref('export_notice_done', 'all'); exportWindow.alert(note); } }; + /** + * + * @returns {undefined} + */ + var operaRepaint = function operaRepaint() { // Repaints canvas in Opera. Needed for stroke-dasharray change as well as fill change if (!window.opera) { return; } + $$b('<p/>').hide().appendTo('body').remove(); }; + /** + * + * @param {Element} opt + * @param {boolean} changeElem + * @returns {undefined} + */ + function setStrokeOpt(opt, changeElem) { var id = opt.id; - var bits = id.split('_'); - var pre = bits[0]; - var val = bits[1]; + + var _bits = _slicedToArray(bits, 2), + pre = _bits[0], + val = _bits[1]; if (changeElem) { svgCanvas.setStrokeAttr('stroke-' + pre, val); } + operaRepaint(); setIcon('#cur_' + pre, id, 20); $$b(opt).addClass('current').siblings().removeClass('current'); } - /** - * This is a common function used when a tool has been clicked (chosen) + * This is a common function used when a tool has been clicked (chosen). * It does several common things: - * - removes the `tool_button_current` class from whatever tool currently has it - * - hides any flyouts - * - adds the `tool_button_current` class to the button passed in + * - Removes the `tool_button_current` class from whatever tool currently has it. + * - Hides any flyouts. + * - Adds the `tool_button_current` class to the button passed in. * @function module:SVGEDitor.toolButtonClick * @param {string|Element} button The DOM element or string selector representing the toolbar button * @param {boolean} noHiding Whether not to hide any flyouts * @returns {boolean} Whether the button was disabled or not */ + + var toolButtonClick = editor.toolButtonClick = function (button, noHiding) { if ($$b(button).hasClass('disabled')) { return false; } + if ($$b(button).parent().hasClass('tools_flyout')) { return true; } + var fadeFlyouts = 'normal'; + if (!noHiding) { $$b('.tools_flyout').fadeOut(fadeFlyouts); } + $$b('#styleoverrides').text(''); workarea.css('cursor', 'auto'); $$b('.tool_button_current').removeClass('tool_button_current').addClass('tool_button'); $$b(button).addClass('tool_button_current').removeClass('tool_button'); return true; }; - /** * Unless the select toolbar button is disabled, sets the button * and sets the select mode and cursor styles. * @function module:SVGEditor.clickSelect * @returns {undefined} */ + + var clickSelect = editor.clickSelect = function () { if (toolButtonClick('#tool_select')) { svgCanvas.setMode('select'); - $$b('#styleoverrides').text('#svgcanvas svg *{cursor:move;pointer-events:all}, #svgcanvas svg{cursor:default}'); + $$b('#styleoverrides').text("\n #svgcanvas svg * {\n cursor: move;\n pointer-events: all;\n }\n #svgcanvas svg {\n cursor: default;\n }\n "); } }; - /** - * Set a selected image's URL + * Set a selected image's URL. * @function module:SVGEditor.setImageURL * @param {string} url * @returns {undefined} */ + + var setImageURL = editor.setImageURL = function (url) { if (!url) { url = defaultImageURL; } + svgCanvas.setImageURL(url); $$b('#image_url').val(url); @@ -26826,68 +30576,116 @@ $$b('#change_image_url').hide(); } }; + /** + * + * @param {string} color + * @param {string} url + * @returns {undefined} + */ + function setBackground(color, url) { // if (color == $.pref('bkgd_color') && url == $.pref('bkgd_url')) { return; } $$b.pref('bkgd_color', color); - $$b.pref('bkgd_url', url); + $$b.pref('bkgd_url', url); // This should be done in svgcanvas.js for the borderRect fill - // This should be done in svgcanvas.js for the borderRect fill svgCanvas.setBackground(color, url); } + /** + * @param {PlainObject} [opts={}] + * @param {boolean} [opts.cancelDeletes=false}] + * @returns {Promise} Resolves to `undefined` + */ + function promptImgURL() { - var _ref9 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, - _ref9$cancelDeletes = _ref9.cancelDeletes, - cancelDeletes = _ref9$cancelDeletes === undefined ? false : _ref9$cancelDeletes; + return _promptImgURL.apply(this, arguments); + } + /** + * @param {Element} elem + * @returns {undefined} + */ - var curhref = svgCanvas.getHref(selectedElement); - curhref = curhref.startsWith('data:') ? '' : curhref; - $$b.prompt(uiStrings$1.notification.enterNewImgURL, curhref, function (url) { - if (url) { - setImageURL(url); - } else if (cancelDeletes) { - svgCanvas.deleteSelectedElements(); - } - }); + + function _promptImgURL() { + _promptImgURL = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee18() { + var _ref31, + _ref31$cancelDeletes, + cancelDeletes, + curhref, + url, + _args18 = arguments; + + return regeneratorRuntime.wrap(function _callee18$(_context18) { + while (1) { + switch (_context18.prev = _context18.next) { + case 0: + _ref31 = _args18.length > 0 && _args18[0] !== undefined ? _args18[0] : {}, _ref31$cancelDeletes = _ref31.cancelDeletes, cancelDeletes = _ref31$cancelDeletes === void 0 ? false : _ref31$cancelDeletes; + curhref = svgCanvas.getHref(selectedElement); + curhref = curhref.startsWith('data:') ? '' : curhref; + _context18.next = 5; + return $$b.prompt(uiStrings$1.notification.enterNewImgURL, curhref); + + case 5: + url = _context18.sent; + + if (url) { + setImageURL(url); + } else if (cancelDeletes) { + svgCanvas.deleteSelectedElements(); + } + + case 7: + case "end": + return _context18.stop(); + } + } + }, _callee18, this); + })); + return _promptImgURL.apply(this, arguments); } var setInputWidth = function setInputWidth(elem) { var w = Math.min(Math.max(12 + elem.value.length * 6, 50), 300); $$b(elem).width(w); }; + /** + * + * @param {HTMLDivElement} [scanvas] + * @param {Float} [zoom] + * @returns {undefined} + */ + function updateRulers(scanvas, zoom) { if (!zoom) { zoom = svgCanvas.getZoom(); } + if (!scanvas) { scanvas = $$b('#svgcanvas'); } - var d = void 0, - i = void 0; + var d, i; var limit = 30000; var contentElem = svgCanvas.getContentElem(); var units = getTypeMap(); var unit = units[curConfig.baseUnit]; // 1 = 1px - // draw x ruler then y ruler + for (d = 0; d < 2; d++) { var isX = d === 0; var dim = isX ? 'x' : 'y'; var lentype = isX ? 'width' : 'height'; var contentDim = Number(contentElem.getAttribute(dim)); + var $hcanvOrig = $$b('#ruler_' + dim + ' canvas:first'); // Bit of a hack to fully clear the canvas in Safari & IE9 - var $hcanvOrig = $$b('#ruler_' + dim + ' canvas:first'); - - // Bit of a hack to fully clear the canvas in Safari & IE9 var $hcanv = $hcanvOrig.clone(); $hcanvOrig.replaceWith($hcanv); + var hcanv = $hcanv[0]; // Set the canvas size to the width of the container - var hcanv = $hcanv[0]; - - // Set the canvas size to the width of the container var rulerLen = scanvas[lentype](); var totalLen = rulerLen; hcanv.parentNode.style[lentype] = totalLen + 'px'; @@ -26895,19 +30693,17 @@ var ctxArr = void 0, num = void 0, ctxArrNum = void 0; - ctx.fillStyle = 'rgb(200,0,0)'; - ctx.fillRect(0, 0, hcanv.width, hcanv.height); + ctx.fillRect(0, 0, hcanv.width, hcanv.height); // Remove any existing canvasses - // Remove any existing canvasses - $hcanv.siblings().remove(); + $hcanv.siblings().remove(); // Create multiple canvases when necessary (due to browser limits) - // Create multiple canvases when necessary (due to browser limits) if (rulerLen >= limit) { - ctxArrNum = parseInt(rulerLen / limit, 10) + 1; + ctxArrNum = parseInt(rulerLen / limit) + 1; ctxArr = []; ctxArr[0] = ctx; var copy = void 0; + for (i = 1; i < ctxArrNum; i++) { hcanv[lentype] = limit; copy = hcanv.cloneNode(true); @@ -26915,40 +30711,38 @@ ctxArr[i] = copy.getContext('2d'); } - copy[lentype] = rulerLen % limit; + copy[lentype] = rulerLen % limit; // set copy width to last - // set copy width to last rulerLen = limit; } hcanv[lentype] = rulerLen; + var uMulti = unit * zoom; // Calculate the main number interval - var uMulti = unit * zoom; - - // Calculate the main number interval var rawM = 50 / uMulti; var multi = 1; + for (i = 0; i < rIntervals.length; i++) { num = rIntervals[i]; multi = num; + if (rawM <= num) { break; } } var bigInt = multi * uMulti; - ctx.font = '9px sans-serif'; - var rulerD = contentDim / uMulti % multi * uMulti; - var labelPos = rulerD - bigInt; - // draw big intervals + var labelPos = rulerD - bigInt; // draw big intervals + var ctxNum = 0; + while (rulerD < totalLen) { - labelPos += bigInt; - // const realD = rulerD - contentDim; // Currently unused + labelPos += bigInt; // const realD = rulerD - contentDim; // Currently unused var curD = Math.round(rulerD) + 0.5; + if (isX) { ctx.moveTo(curD, 15); ctx.lineTo(curD, 0); @@ -26959,14 +30753,15 @@ num = (labelPos - contentDim) / uMulti; var label = void 0; + if (multi >= 1) { label = Math.round(num); } else { var decs = String(multi).split('.')[1].length; label = num.toFixed(decs); - } + } // Change 1000s to Ks + - // Change 1000s to Ks if (label !== 0 && label !== 1000 && label % 1000 === 0) { label = label / 1000 + 'K'; } @@ -26976,30 +30771,35 @@ } else { // draw label vertically var _str = String(label).split(''); + for (i = 0; i < _str.length; i++) { ctx.fillText(_str[i], 1, rulerD + 9 + i * 9); } } - var part = bigInt / 10; - // draw the small intervals + var part = bigInt / 10; // draw the small intervals + for (i = 1; i < 10; i++) { var subD = Math.round(rulerD + part * i) + 0.5; + if (ctxArr && subD > rulerLen) { ctxNum++; ctx.stroke(); + if (ctxNum >= ctxArrNum) { i = 10; rulerD = totalLen; continue; } + ctx = ctxArr[ctxNum]; rulerD -= limit; subD = Math.round(rulerD + part * i) + 0.5; - } + } // odd lines are slighly longer + - // odd lines are slighly longer var lineNum = i % 2 ? 12 : 10; + if (isX) { ctx.moveTo(subD, 15); ctx.lineTo(subD, lineNum); @@ -27008,24 +30808,26 @@ ctx.lineTo(lineNum, subD); } } + rulerD += bigInt; } + ctx.strokeStyle = '#000'; ctx.stroke(); } } - /** * @function module:SVGEditor.updateCanvas * @param {boolean} center * @param {module:math.XYObject} newCtr * @returns {undefined} */ + + var updateCanvas = editor.updateCanvas = function (center, newCtr) { var zoom = svgCanvas.getZoom(); var wArea = workarea; var cnvs = $$b('#svgcanvas'); - var w = workarea.width(), h = workarea.height(); var wOrig = w, @@ -27050,19 +30852,16 @@ var newCanY = h / 2; var newCanX = w / 2; var offset = svgCanvas.updateCanvas(w, h); - var ratio = newCanX / oldCanX; + var scrollX = w / 2 - wOrig / 2; // eslint-disable-line no-shadow - var scrollX = w / 2 - wOrig / 2; - var scrollY = h / 2 - hOrig / 2; + var scrollY = h / 2 - hOrig / 2; // eslint-disable-line no-shadow if (!newCtr) { var oldDistX = oldCtr.x - oldCanX; var newX = newCanX + oldDistX * ratio; - var oldDistY = oldCtr.y - oldCanY; var newY = newCanY + oldDistY * ratio; - newCtr = { x: newX, y: newY @@ -27087,62 +30886,63 @@ wArea[0].scrollLeft = newCtr.x - wOrig / 2; wArea[0].scrollTop = newCtr.y - hOrig / 2; } + if (curConfig.showRulers) { updateRulers(cnvs, zoom); workarea.scroll(); } - if (urldata.storagePrompt !== true && !editor.storagePromptClosed) { + + if (urldata.storagePrompt !== true && editor.storagePromptState === 'ignore') { $$b('#dialog_box').hide(); } }; - /** * @fires module:svgcanvas.SvgCanvas#event:ext-toolButtonStateUpdate * @returns {undefined} */ + + var updateToolButtonState = function updateToolButtonState() { - var index = void 0, - button = void 0; var bNoFill = svgCanvas.getColor('fill') === 'none'; var bNoStroke = svgCanvas.getColor('stroke') === 'none'; var buttonsNeedingStroke = ['#tool_fhpath', '#tool_line']; var buttonsNeedingFillAndStroke = ['#tools_rect .tool_button', '#tools_ellipse .tool_button', '#tool_text', '#tool_path']; + if (bNoStroke) { - for (index in buttonsNeedingStroke) { - button = buttonsNeedingStroke[index]; - if ($$b(button).hasClass('tool_button_current')) { + buttonsNeedingStroke.forEach(function (btn) { + if ($$b(btn).hasClass('tool_button_current')) { clickSelect(); } - $$b(button).addClass('disabled'); - } + + $$b(btn).addClass('disabled'); + }); } else { - for (index in buttonsNeedingStroke) { - button = buttonsNeedingStroke[index]; - $$b(button).removeClass('disabled'); - } + buttonsNeedingStroke.forEach(function (btn) { + $$b(btn).removeClass('disabled'); + }); } if (bNoStroke && bNoFill) { - for (index in buttonsNeedingFillAndStroke) { - button = buttonsNeedingFillAndStroke[index]; - if ($$b(button).hasClass('tool_button_current')) { + buttonsNeedingFillAndStroke.forEach(function (btn) { + if ($$b(btn).hasClass('tool_button_current')) { clickSelect(); } - $$b(button).addClass('disabled'); - } + + $$b(btn).addClass('disabled'); + }); } else { - for (index in buttonsNeedingFillAndStroke) { - button = buttonsNeedingFillAndStroke[index]; - $$b(button).removeClass('disabled'); - } + buttonsNeedingFillAndStroke.forEach(function (btn) { + $$b(btn).removeClass('disabled'); + }); } - svgCanvas.runExtensions('toolButtonStateUpdate', /** @type {module:svgcanvas.SvgCanvas#event:ext-toolButtonStateUpdate} */{ + svgCanvas.runExtensions('toolButtonStateUpdate', + /** @type {module:svgcanvas.SvgCanvas#event:ext-toolButtonStateUpdate} */ + { nofill: bNoFill, nostroke: bNoStroke - }); + }); // Disable flyouts if all inside are disabled - // Disable flyouts if all inside are disabled $$b('.tools_flyout').each(function () { var shower = $$b('#' + this.id + '_show'); var hasEnabled = false; @@ -27153,65 +30953,72 @@ }); shower.toggleClass('disabled', !hasEnabled); }); - operaRepaint(); }; + /** + * Updates the toolbar (colors, opacity, etc) based on the selected element. + * This function also updates the opacity and id elements that are in the + * context panel. + * @returns {undefined} + */ + - // Updates the toolbar (colors, opacity, etc) based on the selected element - // This function also updates the opacity and id elements that are in the context panel var updateToolbar = function updateToolbar() { - var i = void 0, - len = void 0; - if (selectedElement != null) { + var i, len; + + if (!isNullish(selectedElement)) { switch (selectedElement.tagName) { case 'use': case 'image': case 'foreignObject': break; + case 'g': case 'a': - // Look for common styles - var childs = selectedElement.getElementsByTagName('*'); - var gWidth = null; - for (i = 0, len = childs.length; i < len; i++) { - var swidth = childs[i].getAttribute('stroke-width'); + { + // Look for common styles + var childs = selectedElement.getElementsByTagName('*'); + var gWidth = null; - if (i === 0) { - gWidth = swidth; - } else if (gWidth !== swidth) { - gWidth = null; + for (i = 0, len = childs.length; i < len; i++) { + var swidth = childs[i].getAttribute('stroke-width'); + + if (i === 0) { + gWidth = swidth; + } else if (gWidth !== swidth) { + gWidth = null; + } + } + + $$b('#stroke_width').val(gWidth === null ? '' : gWidth); + paintBox.fill.update(true); + paintBox.stroke.update(true); + break; + } + + default: + { + paintBox.fill.update(true); + paintBox.stroke.update(true); + $$b('#stroke_width').val(selectedElement.getAttribute('stroke-width') || 1); + $$b('#stroke_style').val(selectedElement.getAttribute('stroke-dasharray') || 'none'); + var attr = selectedElement.getAttribute('stroke-linejoin') || 'miter'; + + if ($$b('#linejoin_' + attr).length) { + setStrokeOpt($$b('#linejoin_' + attr)[0]); + } + + attr = selectedElement.getAttribute('stroke-linecap') || 'butt'; + + if ($$b('#linecap_' + attr).length) { + setStrokeOpt($$b('#linecap_' + attr)[0]); } } - - $$b('#stroke_width').val(gWidth === null ? '' : gWidth); - - paintBox.fill.update(true); - paintBox.stroke.update(true); - - break; - default: - paintBox.fill.update(true); - paintBox.stroke.update(true); - - $$b('#stroke_width').val(selectedElement.getAttribute('stroke-width') || 1); - $$b('#stroke_style').val(selectedElement.getAttribute('stroke-dasharray') || 'none'); - - var attr = selectedElement.getAttribute('stroke-linejoin') || 'miter'; - - if ($$b('#linejoin_' + attr).length) { - setStrokeOpt($$b('#linejoin_' + attr)[0]); - } - - attr = selectedElement.getAttribute('stroke-linecap') || 'butt'; - - if ($$b('#linecap_' + attr).length) { - setStrokeOpt($$b('#linecap_' + attr)[0]); - } } - } + } // All elements including image and group have opacity - // All elements including image and group have opacity - if (selectedElement != null) { + + if (!isNullish(selectedElement)) { var opacPerc = (selectedElement.getAttribute('opacity') || 1.0) * 100; $$b('#group_opacity').val(opacPerc); $$b('#opac_slider').slider('option', 'value', opacPerc); @@ -27221,24 +31028,29 @@ updateToolButtonState(); }; + /** + * Updates the context panel tools based on the selected element. + * @returns {undefined} + */ + - // updates the context panel tools based on the selected element var updateContextPanel = function updateContextPanel() { - var elem = selectedElement; - // If element has just been deleted, consider it null - if (elem != null && !elem.parentNode) { + var elem = selectedElement; // If element has just been deleted, consider it null + + if (!isNullish(elem) && !elem.parentNode) { elem = null; } + var currentLayerName = svgCanvas.getCurrentDrawing().getCurrentLayerName(); var currentMode = svgCanvas.getMode(); var unit = curConfig.baseUnit !== 'px' ? curConfig.baseUnit : null; - var isNode = currentMode === 'pathedit'; // elem ? (elem.id && elem.id.startsWith('pathpointgrip')) : false; + var menuItems = $$b('#cmenu_canvas li'); $$b('#selected_panel, #multiselected_panel, #g_panel, #rect_panel, #circle_panel,' + '#ellipse_panel, #line_panel, #text_panel, #image_panel, #container_panel,' + ' #use_panel, #a_panel').hide(); - if (elem != null) { - var elname = elem.nodeName; - // If this is a link with no transform and one child, pretend + + if (!isNullish(elem)) { + var elname = elem.nodeName; // If this is a link with no transform and one child, pretend // its child is selected // if (elname === 'a') { // && !$(elem).attr('transform')) { // elem = elem.firstChild; @@ -27246,7 +31058,6 @@ var angle = svgCanvas.getRotationAngle(elem); $$b('#angle').val(angle); - var blurval = svgCanvas.getBlur(elem); $$b('#blur').val(blurval); $$b('#blur_slider').slider('option', 'value', blurval); @@ -27255,26 +31066,29 @@ if (elname === 'image' && svgCanvas.getMode() === 'image') { // Prompt for URL if not a data URL if (!svgCanvas.getHref(elem).startsWith('data:')) { - promptImgURL({ cancelDeletes: true }); + /* await */ + promptImgURL({ + cancelDeletes: true + }); } } /* else if (elname == 'text') { // TODO: Do something here for new text } */ + } if (!isNode && currentMode !== 'pathedit') { - $$b('#selected_panel').show(); - // Elements in this array already have coord fields + $$b('#selected_panel').show(); // Elements in this array already have coord fields + if (['line', 'circle', 'ellipse'].includes(elname)) { $$b('#xy_panel').hide(); } else { - var x = void 0, - y = void 0; + var x, y; // Get BBox vals for g, polyline and path - // Get BBox vals for g, polyline and path if (['g', 'polyline', 'path'].includes(elname)) { var bb = svgCanvas.getStrokedBBox([elem]); + if (bb) { x = bb.x; y = bb.y; @@ -27292,9 +31106,9 @@ $$b('#selected_x').val(x || 0); $$b('#selected_y').val(y || 0); $$b('#xy_panel').show(); - } + } // Elements in this array cannot be converted to a path + - // Elements in this array cannot be converted to a path var noPath = !['image', 'text', 'path', 'g', 'use'].includes(elname); $$b('#tool_topath').toggle(noPath); $$b('#tool_reorient').toggle(elname === 'path'); @@ -27302,29 +31116,32 @@ } else { var point = path.getNodePoint(); $$b('#tool_add_subpath').removeClass('push_button_pressed').addClass('tool_button'); - $$b('#tool_node_delete').toggleClass('disabled', !path.canDeleteNodes); + $$b('#tool_node_delete').toggleClass('disabled', !path.canDeleteNodes); // Show open/close button based on selected point - // Show open/close button based on selected point setIcon('#tool_openclose_path', path.closed_subpath ? 'open_path' : 'close_path'); if (point) { var segType = $$b('#seg_type'); + if (unit) { point.x = convertUnit(point.x); point.y = convertUnit(point.y); } + $$b('#path_node_x').val(point.x); $$b('#path_node_y').val(point.y); + if (point.type) { segType.val(point.type).removeAttr('disabled'); } else { segType.val(4).attr('disabled', 'disabled'); } } - return; - } - // update contextual tools here + return; + } // update contextual tools here + + var panels = { g: [], a: [], @@ -27336,15 +31153,13 @@ text: [], use: [] }; - var _elem = elem, - tagName = _elem.tagName; - - // if ($(elem).data('gsvg')) { + tagName = _elem.tagName; // if ($(elem).data('gsvg')) { // $('#g_panel').show(); // } var linkHref = null; + if (tagName === 'a') { linkHref = svgCanvas.getHref(elem); $$b('#g_panel').show(); @@ -27355,9 +31170,9 @@ $$b('#a_panel').show(); linkHref = svgCanvas.getHref(elem.parentNode); } - } + } // Hide/show the make_link buttons + - // Hide/show the make_link buttons $$b('#tool_make_link, #tool_make_link').toggle(!linkHref); if (linkHref) { @@ -27366,44 +31181,47 @@ if (panels[tagName]) { var curPanel = panels[tagName]; - $$b('#' + tagName + '_panel').show(); - $$b.each(curPanel, function (i, item) { var attrVal = elem.getAttribute(item); + if (curConfig.baseUnit !== 'px' && elem[item]) { var bv = elem[item].baseVal.value; attrVal = convertUnit(bv); } + $$b('#' + tagName + '_' + item).val(attrVal || 0); }); if (tagName === 'text') { $$b('#text_panel').css('display', 'inline'); $$b('#tool_font_size').css('display', 'inline'); + if (svgCanvas.getItalic()) { $$b('#tool_italic').addClass('push_button_pressed').removeClass('tool_button'); } else { $$b('#tool_italic').removeClass('push_button_pressed').addClass('tool_button'); } + if (svgCanvas.getBold()) { $$b('#tool_bold').addClass('push_button_pressed').removeClass('tool_button'); } else { $$b('#tool_bold').removeClass('push_button_pressed').addClass('tool_button'); } + $$b('#font_family').val(elem.getAttribute('font-family')); $$b('#font_size').val(elem.getAttribute('font-size')); $$b('#text').val(elem.textContent); + if (svgCanvas.addedNew) { // Timeout needed for IE9 setTimeout(function () { $$b('#text').focus().select(); }, 100); - } - // text + } // text + } else if (tagName === 'image' && svgCanvas.getMode() === 'image') { - setImageURL(svgCanvas.getHref(elem)); - // image + setImageURL(svgCanvas.getHref(elem)); // image } else if (tagName === 'g' || tagName === 'use') { $$b('#container_panel').show(); var title = svgCanvas.getTitle(); @@ -27413,32 +31231,35 @@ $$b('#g_title').prop('disabled', tagName === 'use'); } } + menuItems[(tagName === 'g' ? 'en' : 'dis') + 'ableContextMenuItems']('#ungroup'); - menuItems[(tagName === 'g' || !multiselected ? 'dis' : 'en') + 'ableContextMenuItems']('#group'); - // if (elem != null) + menuItems[(tagName === 'g' || !multiselected ? 'dis' : 'en') + 'ableContextMenuItems']('#group'); // if (!Utils.isNullish(elem)) } else if (multiselected) { $$b('#multiselected_panel').show(); menuItems.enableContextMenuItems('#group').disableContextMenuItems('#ungroup'); } else { menuItems.disableContextMenuItems('#delete,#cut,#copy,#group,#ungroup,#move_front,#move_up,#move_down,#move_back'); - } + } // update history buttons + - // update history buttons $$b('#tool_undo').toggleClass('disabled', undoMgr.getUndoStackSize() === 0); $$b('#tool_redo').toggleClass('disabled', undoMgr.getRedoStackSize() === 0); - svgCanvas.addedNew = false; if (elem && !isNode || multiselected) { // update the selected elements' layer - $$b('#selLayerNames').removeAttr('disabled').val(currentLayerName); + $$b('#selLayerNames').removeAttr('disabled').val(currentLayerName); // Enable regular menu options - // Enable regular menu options canvMenu.enableContextMenuItems('#delete,#cut,#copy,#move_front,#move_up,#move_down,#move_back'); } else { $$b('#selLayerNames').attr('disabled', 'disabled'); } }; + /** + * + * @returns {undefined} + */ + var updateWireFrame = function updateWireFrame() { // Test support @@ -27446,24 +31267,26 @@ return; } - var rule = '#workarea.wireframe #svgcontent * { stroke-width: ' + 1 / svgCanvas.getZoom() + 'px; }'; + var rule = "\n #workarea.wireframe #svgcontent * {\n stroke-width: ".concat(1 / svgCanvas.getZoom(), "px;\n }\n "); $$b('#wireframe_rules').text(workarea.hasClass('wireframe') ? rule : ''); }; var curContext = ''; + /** + * @param {string} [title=svgCanvas.getDocumentTitle()] + * @returns {undefined} + */ var updateTitle = function updateTitle(title) { title = title || svgCanvas.getDocumentTitle(); - var newTitle = origTitle + (title ? ': ' + title : ''); - - // Remove title update with current context info, isn't really necessary + var newTitle = origTitle + (title ? ': ' + title : ''); // Remove title update with current context info, isn't really necessary // if (curContext) { // new_title = new_title + curContext; // } - $$b('title:first').text(newTitle); - }; - // called when we've selected a different element + $$b('title:first').text(newTitle); + }; // called when we've selected a different element + /** * * @param {external:Window} win @@ -27472,37 +31295,43 @@ * @fires module:svgcanvas.SvgCanvas#event:ext-selectedChanged * @returns {undefined} */ + + var selectedChanged = function selectedChanged(win, elems) { var mode = svgCanvas.getMode(); + if (mode === 'select') { setSelectMode(); } - var isNode = mode === 'pathedit'; - // if elems[1] is present, then we have more than one element - selectedElement = elems.length === 1 || elems[1] == null ? elems[0] : null; - multiselected = elems.length >= 2 && elems[1] != null; - if (selectedElement != null) { + + var isNode = mode === 'pathedit'; // if elems[1] is present, then we have more than one element + + selectedElement = elems.length === 1 || isNullish(elems[1]) ? elems[0] : null; + multiselected = elems.length >= 2 && !isNullish(elems[1]); + + if (!isNullish(selectedElement)) { // unless we're already in always set the mode of the editor to select because // upon creation of a text element the editor is switched into // select mode and this event fires - we need our UI to be in sync - if (!isNode) { updateToolbar(); } - } // if (elem != null) - + } // if (!Utils.isNullish(elem)) // Deal with pathedit mode + + togglePathEditMode(isNode, elems); updateContextPanel(); - svgCanvas.runExtensions('selectedChanged', /** @type {module:svgcanvas.SvgCanvas#event:ext-selectedChanged} */{ + svgCanvas.runExtensions('selectedChanged', + /** @type {module:svgcanvas.SvgCanvas#event:ext-selectedChanged} */ + { elems: elems, selectedElement: selectedElement, multiselected: multiselected }); - }; - - // Call when part of element is in process of changing, generally + }; // Call when part of element is in process of changing, generally // on mousemove actions like rotate, move, etc. + /** * @param {external:Window} win * @param {module:svgcanvas.SvgCanvas#event:transition} elems @@ -27510,6 +31339,8 @@ * @fires module:svgcanvas.SvgCanvas#event:ext-elementTransition * @returns {undefined} */ + + var elementTransition = function elementTransition(win, elems) { var mode = svgCanvas.getMode(); var elem = elems[0]; @@ -27518,37 +31349,41 @@ return; } - multiselected = elems.length >= 2 && elems[1] != null; - // Only updating fields for single elements for now + multiselected = elems.length >= 2 && !isNullish(elems[1]); // Only updating fields for single elements for now + if (!multiselected) { switch (mode) { case 'rotate': - var ang = svgCanvas.getRotationAngle(elem); - $$b('#angle').val(ang); - $$b('#tool_reorient').toggleClass('disabled', ang === 0); - break; - - // TODO: Update values that change on move/resize, etc - // case 'select': - // case 'resize': - // break; + { + var ang = svgCanvas.getRotationAngle(elem); + $$b('#angle').val(ang); + $$b('#tool_reorient').toggleClass('disabled', ang === 0); + break; // TODO: Update values that change on move/resize, etc + // } case 'select': { + // } case 'resize': { + // break; + // } + } } } - svgCanvas.runExtensions('elementTransition', /** @type {module:svgcanvas.SvgCanvas#event:ext-elementTransition} */{ + + svgCanvas.runExtensions('elementTransition', + /** @type {module:svgcanvas.SvgCanvas#event:ext-elementTransition} */ + { elems: elems }); }; - /** * Test whether an element is a layer or not. * @param {SVGGElement} elem - The SVGGElement to test. * @returns {boolean} True if the element is a layer */ + + function isLayer(elem) { return elem && elem.tagName === 'g' && Layer.CLASS_REGEX.test(elem.getAttribute('class')); - } + } // called when any element has changed - // called when any element has changed /** * @param {external:Window} win * @param {module:svgcanvas.SvgCanvas#event:changed} elems @@ -27556,60 +31391,61 @@ * @fires module:svgcanvas.SvgCanvas#event:ext-elementChanged * @returns {undefined} */ + + var elementChanged = function elementChanged(win, elems) { var mode = svgCanvas.getMode(); + if (mode === 'select') { setSelectMode(); } for (var _i = 0; _i < elems.length; ++_i) { var elem = elems[_i]; - var isSvgElem = elem && elem.tagName === 'svg'; + if (isSvgElem || isLayer(elem)) { - populateLayers(); - // if the element changed was the svg, then it could be a resolution change + populateLayers(); // if the element changed was the svg, then it could be a resolution change + if (isSvgElem) { updateCanvas(); - } - // 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 - } else if (elem && selectedElement && selectedElement.parentNode == null) { + + } else if (elem && selectedElement && isNullish(selectedElement.parentNode)) { // || elem && elem.tagName == "path" && !multiselected) { // This was added in r1430, but not sure why selectedElement = elem; } } - editor.showSaveWarning = true; - - // we update the contextual panel with potentially new + editor.showSaveWarning = true; // we update the contextual panel with potentially new // positional/sizing information (we DON'T want to update the // toolbar here as that creates an infinite loop) // also this updates the history buttons - // we tell it to skip focusing the text control if the // text element was previously in focus - updateContextPanel(); - // In the event a gradient was flipped: + updateContextPanel(); // In the event a gradient was flipped: + if (selectedElement && mode === 'select') { paintBox.fill.update(); paintBox.stroke.update(); } - svgCanvas.runExtensions('elementChanged', /** @type {module:svgcanvas.SvgCanvas#event:ext-elementChanged} */{ + svgCanvas.runExtensions('elementChanged', + /** @type {module:svgcanvas.SvgCanvas#event:ext-elementChanged} */ + { elems: elems }); }; - /** * @returns {undefined} */ - var zoomDone = function zoomDone() { - updateWireFrame(); - // updateCanvas(); // necessary? - }; + + var zoomDone = function zoomDone() { + updateWireFrame(); // updateCanvas(); // necessary? + }; /** * @typedef {PlainObject} module:SVGEditor.BBoxObjectWithFactor (like `DOMRect`) * @property {Float} x @@ -27629,21 +31465,26 @@ * @listens module:svgcanvas.SvgCanvas#event:zoomed * @returns {undefined} */ + + var zoomChanged = svgCanvas.zoomChanged = function (win, bbox, autoCenter) { var scrbar = 15, + // res = svgCanvas.getResolution(), // Currently unused + wArea = workarea; // const canvasPos = $('#svgcanvas').position(); // Currently unused - // res = svgCanvas.getResolution(), // Currently unused - wArea = workarea; - // const canvasPos = $('#svgcanvas').position(); // Currently unused var zInfo = svgCanvas.setBBoxZoom(bbox, wArea.width() - scrbar, wArea.height() - scrbar); + if (!zInfo) { return; } + var zoomlevel = zInfo.zoom, bb = zInfo.bbox; if (zoomlevel < 0.001) { - changeZoom({ value: 0.1 }); + changeZoom({ + value: 0.1 + }); return; } @@ -27652,7 +31493,10 @@ if (autoCenter) { updateCanvas(); } else { - updateCanvas(false, { x: bb.x * zoomlevel + bb.width * zoomlevel / 2, y: bb.y * zoomlevel + bb.height * zoomlevel / 2 }); + updateCanvas(false, { + x: bb.x * zoomlevel + bb.width * zoomlevel / 2, + y: bb.y * zoomlevel + bb.height * zoomlevel / 2 + }); } if (svgCanvas.getMode() === 'zoom' && bb.width) { @@ -27662,16 +31506,21 @@ zoomDone(); }; + /** + * @implements {module:jQuerySpinButton.ValueCallback} + */ + var changeZoom = function changeZoom(ctl) { var zoomlevel = ctl.value / 100; + if (zoomlevel < 0.001) { ctl.value = 0.1; return; } + var zoom = svgCanvas.getZoom(); var wArea = workarea; - zoomChanged(window, { width: 0, height: 0, @@ -27684,30 +31533,33 @@ $$b('#cur_context_panel').delegate('a', 'click', function () { var link = $$b(this); + if (link.attr('data-root')) { svgCanvas.leaveContext(); } else { svgCanvas.setContext(link.text()); } + svgCanvas.clearSelection(); return false; }); - /** * @param {external:Window} win * @param {module:svgcanvas.SvgCanvas#event:contextset} context * @listens module:svgcanvas.SvgCanvas#event:contextset * @returns {undefined} */ + var contextChanged = function contextChanged(win, context) { var linkStr = ''; + if (context) { var _str2 = ''; linkStr = '<a href="#" data-root="y">' + svgCanvas.getCurrentDrawing().getCurrentLayerName() + '</a>'; - $$b(context).parentsUntil('#svgcontent > g').andSelf().each(function () { if (this.id) { _str2 += ' > ' + this.id; + if (this !== context) { linkStr += ' > <a href="#">' + this.id + '</a>'; } else { @@ -27715,27 +31567,35 @@ } } }); - curContext = _str2; } else { curContext = null; } - $$b('#cur_context_panel').toggle(!!context).html(linkStr); + $$b('#cur_context_panel').toggle(Boolean(context)).html(linkStr); updateTitle(); }; + /** + * Makes sure the current selected paint is available to work with. + * @returns {undefined} + */ + - // Makes sure the current selected paint is available to work with var prepPaints = function prepPaints() { paintBox.fill.prep(); paintBox.stroke.prep(); }; var flyoutFuncs = {}; + /** + * + * @returns {undefined} + */ var setFlyoutTitles = function setFlyoutTitles() { $$b('.tools_flyout').each(function () { var shower = $$b('#' + this.id + '_show'); + if (shower.data('isLibrary')) { return; } @@ -27749,9 +31609,10 @@ var allHolders = {}; /** - * @param {Object.<string, module:SVGEditor.ToolButton>} holders Key is a selector + * @param {PlainObject.<string, module:SVGEditor.ToolButton>} holders Key is a selector * @returns {undefined} */ + var setupFlyouts = function setupFlyouts(holders) { $$b.each(holders, function (holdSel, btnOpts) { var _allHolders$holdSel; @@ -27759,7 +31620,8 @@ if (!allHolders[holdSel]) { allHolders[holdSel] = []; } - (_allHolders$holdSel = allHolders[holdSel]).push.apply(_allHolders$holdSel, toConsumableArray(btnOpts)); + + (_allHolders$holdSel = allHolders[holdSel]).push.apply(_allHolders$holdSel, _toConsumableArray(btnOpts)); var buttons = $$b(holdSel).children().not('.tool_button_evt_handled'); var showSel = holdSel + '_show'; @@ -27770,18 +31632,16 @@ // Get this button's options var idSel = '#' + this.getAttribute('id'); - var _Object$entries$find = Object.entries(btnOpts).find(function (_ref10) { - var _ref11 = slicedToArray(_ref10, 2), - i = _ref11[0], - sel = _ref11[1].sel; + var _Object$entries$find = Object.entries(btnOpts).find(function (_ref9) { + var _ref10 = _slicedToArray(_ref9, 2), + _ = _ref10[0], + sel = _ref10[1].sel; return sel === idSel; }), - _Object$entries$find2 = slicedToArray(_Object$entries$find, 2), + _Object$entries$find2 = _slicedToArray(_Object$entries$find, 2), i = _Object$entries$find2[0], - opts = _Object$entries$find2[1]; - - // Remember the function that goes with this ID + opts = _Object$entries$find2[1]; // Remember the function that goes with this ID flyoutFuncs[opts.sel] = opts.fn; @@ -27789,44 +31649,51 @@ if (opts.isDefault) { def = i; } - /** - * Clicking the icon in flyout should set this set's icon + * Clicking the icon in flyout should set this set's icon. * @param {Event} ev * @returns {undefined} */ + + var flyoutAction = function flyoutAction(ev) { - var options = opts; - // Find the currently selected tool if comes from keystroke + var options = opts; // Find the currently selected tool if comes from keystroke + if (ev.type === 'keydown') { var flyoutIsSelected = $$b(options.parent + '_show').hasClass('tool_button_current'); var currentOperation = $$b(options.parent + '_show').attr('data-curopt'); - Object.entries(holders[opts.parent]).some(function (_ref12) { - var _ref13 = slicedToArray(_ref12, 2), - i = _ref13[0], - tool = _ref13[1]; + Object.entries(holders[opts.parent]).some(function (_ref11) { + var _ref12 = _slicedToArray(_ref11, 2), + j = _ref12[0], + tool = _ref12[1]; if (tool.sel !== currentOperation) { - return; + return false; } + if (!ev.shiftKey || !flyoutIsSelected) { options = tool; } else { // If flyout is selected, allow shift key to iterate through subitems - i = parseInt(i, 10); - // Use `allHolders` to include both extension `includeWith` and toolbarButtons - options = allHolders[opts.parent][i + 1] || holders[opts.parent][0]; + j = parseInt(j); // Use `allHolders` to include both extension `includeWith` and toolbarButtons + + options = allHolders[opts.parent][j + 1] || holders[opts.parent][0]; } + return true; }); } + if ($$b(this).hasClass('disabled')) { return false; } + if (toolButtonClick(showSel)) { options.fn(); } - var icon = void 0; + + var icon; + if (options.icon) { icon = $$b.getSvgIcon(options.icon, true); } else { @@ -27837,6 +31704,8 @@ icon[0].setAttribute('height', shower.height()); shower.children(':not(.flyout_arrow_horiz)').remove(); shower.append(icon).attr('data-curopt', options.sel); // This sets the current mode + + return true; }; $$b(this).mouseup(flyoutAction); @@ -27844,6 +31713,8 @@ if (opts.key) { $$b(document).bind('keydown', opts.key[0] + ' shift+' + opts.key[0], flyoutAction); } + + return true; }); if (def) { @@ -27853,14 +31724,14 @@ shower.attr('data-curopt', btnOpts[0].sel); } - var timer = void 0; - var pos = $$b(showSel).position(); + var timer; + var pos = $$b(showSel).position(); // Clicking the "show" icon should set the current mode - // Clicking the "show" icon should set the current mode shower.mousedown(function (evt) { if (shower.hasClass('disabled')) { return false; } + var holder = $$b(holdSel); var l = pos.left + 34; var w = holder.width() * -1; @@ -27874,72 +31745,100 @@ } else { holder.css('left', l).show(); } + holder.data('shown_popop', true); }, time); evt.preventDefault(); + return true; }).mouseup(function (evt) { clearTimeout(timer); - var opt = $$b(this).attr('data-curopt'); - // Is library and popped up, so do nothing + var opt = $$b(this).attr('data-curopt'); // Is library and popped up, so do nothing + if (shower.data('isLibrary') && $$b(showSel.replace('_show', '')).is(':visible')) { toolButtonClick(showSel, true); return; } + if (toolButtonClick(showSel) && flyoutFuncs[opt]) { flyoutFuncs[opt](); } - }); - // $('#tools_rect').mouseleave(function () { $('#tools_rect').fadeOut(); }); + }); // $('#tools_rect').mouseleave(function () { $('#tools_rect').fadeOut(); }); }); setFlyoutTitles(); setFlyoutPositions(); }; + /** + * @param {string} id + * @param {external:jQuery} child + * @returns {undefined} + */ + var makeFlyoutHolder = function makeFlyoutHolder(id, child) { var div = $$b('<div>', { class: 'tools_flyout', id: id }).appendTo('#svg_editor').append(child); - return div; }; + /** + * @param {string} elemSel + * @param {string} listSel + * @param {external:jQuery.Function} callback + * @param {PlainObject} opts + * @param {boolean} opts.dropUp + * @param {boolean} opts.seticon + * @param {boolean} opts.multiclick + * @todo Combine this with `addDropDown` or find other way to optimize. + * @returns {undefined} + */ - // TODO: Combine this with addDropDown or find other way to optimize - var addAltDropDown = function addAltDropDown(elem, list, callback, opts) { - var button = $$b(elem); + + var addAltDropDown = function addAltDropDown(elemSel, listSel, callback, opts) { + var button = $$b(elemSel); var dropUp = opts.dropUp; + var list = $$b(listSel); - list = $$b(list); if (dropUp) { - $$b(elem).addClass('dropup'); + $$b(elemSel).addClass('dropup'); } + list.find('li').bind('mouseup', function () { if (opts.seticon) { setIcon('#cur_' + button[0].id, $$b(this).children()); $$b(this).addClass('current').siblings().removeClass('current'); } - callback.apply(this, arguments); - }); + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + callback.apply.apply(callback, [this].concat(args)); + }); var onButton = false; $$b(window).mouseup(function (evt) { if (!onButton) { button.removeClass('down'); list.hide(); - list.css({ top: 0, left: 0 }); + list.css({ + top: 0, + left: 0 + }); } - onButton = false; - }); - // const height = list.height(); // Currently unused + onButton = false; + }); // const height = list.height(); // Currently unused + button.bind('mousedown', function () { var off = button.offset(); + if (dropUp) { off.top -= list.height(); off.left += 8; } else { off.top += button.height(); } + list.offset(off); if (!button.hasClass('down')) { @@ -27948,8 +31847,12 @@ } else { // CSS position must be reset for Webkit list.hide(); - list.css({ top: 0, left: 0 }); + list.css({ + top: 0, + left: 0 + }); } + button.toggleClass('down'); }).hover(function () { onButton = true; @@ -27969,437 +31872,536 @@ * @param {external:Window} win * @param {module:svgcanvas.SvgCanvas#event:extension_added} ext * @listens module:svgcanvas.SvgCanvas#event:extension_added - * @returns {Promise} Resolves to `undefined` + * @returns {Promise|undefined} Resolves to `undefined` */ - var extAdded = function extAdded(win, ext) { - if (!ext) { - return; - } - var cbCalled = false; - var resizeDone = false; - if (ext.langReady) { - if (editor.langChanged) { - // We check for this since the "lang" pref could have been set by storage - var lang = $$b.pref('lang'); - ext.langReady({ - lang: lang, - uiStrings: uiStrings$1, - importLocale: getImportLocale({ defaultLang: lang, defaultName: ext.name }) - }); - } else { - extsPreLang.push(ext); - } - } + var extAdded = + /*#__PURE__*/ + function () { + var _ref13 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee5(win, ext) { + var cbCalled, resizeDone, lang, prepResize, runCallback, btnSelects, svgicons, fallbackObj, placementObj, holders; + return regeneratorRuntime.wrap(function _callee5$(_context5) { + while (1) { + switch (_context5.prev = _context5.next) { + case 0: + prepResize = function _ref14() { + if (resizeTimer) { + clearTimeout(resizeTimer); + resizeTimer = null; + } - function prepResize() { - if (resizeTimer) { - clearTimeout(resizeTimer); - resizeTimer = null; - } - if (!resizeDone) { - resizeTimer = setTimeout(function () { - resizeDone = true; - setIconSize($$b.pref('iconsize')); - }, 50); - } - } + if (!resizeDone) { + resizeTimer = setTimeout(function () { + resizeDone = true; + setIconSize($$b.pref('iconsize')); + }, 50); + } + }; - var runCallback = function runCallback() { - if (ext.callback && !cbCalled) { - cbCalled = true; - ext.callback.call(editor); - } - }; + if (ext) { + _context5.next = 3; + break; + } - var btnSelects = []; + return _context5.abrupt("return", undefined); - /** - * @typedef {PlainObject} module:SVGEditor.ContextTool - * @property {string} panel The ID of the existing panel to which the tool is being added. Required. - * @property {string} id The ID of the actual tool element. Required. - * @property {PlainObject.<string, external:jQuery.Function>|PlainObject.<"change", external:jQuery.Function>} events DOM event names keyed to associated functions. Example: `{change () { alert('Option was changed') } }`. "change" event is one specifically handled for the "button-select" type. Required. - * @property {string} title The tooltip text that will appear when the user hovers over the tool. Required. - * @property {"tool_button"|"select"|"button-select"|"input"|string} type The type of tool being added. Expected. - * @property {PlainObject.<string, string>} [options] List of options and their labels for select tools. Example: `{1: 'One', 2: 'Two', all: 'All' }`. Required by "select" tools. - * @property {string} [container_id] The ID to be given to the tool's container element. - * @property {string} [defval] Default value - * @property {string|Integer} [colnum] Added as part of the option list class. - * @property {string} [label] Label associated with the tool, visible in the UI - * @property {Integer} [size] Value of the "size" attribute of the tool input - * @property {module:jQuerySpinButton.SpinButtonConfig} [spindata] When added to a tool of type "input", this tool becomes a "spinner" which allows the number to be in/decreased. - */ - if (ext.context_tools) { - $$b.each(ext.context_tools, function (i, tool) { - // Add select tool - var contId = tool.container_id ? ' id="' + tool.container_id + '"' : ''; + case 3: + cbCalled = false; + resizeDone = false; - var panel = $$b('#' + tool.panel); - // create the panel if it doesn't exist - if (!panel.length) { - panel = $$b('<div>', { id: tool.panel }).appendTo('#tools_top'); - } + if (!ext.langReady) { + _context5.next = 14; + break; + } - var html = void 0; - // TODO: Allow support for other types, or adding to existing tool - switch (tool.type) { - case 'tool_button': - html = '<div class="tool_button">' + tool.id + '</div>'; - var div = $$b(html).appendTo(panel); - if (tool.events) { - $$b.each(tool.events, function (evt, func) { - $$b(div).bind(evt, func); + if (!editor.langChanged) { + _context5.next = 13; + break; + } + + // We check for this since the "lang" pref could have been set by storage + lang = $$b.pref('lang'); + _context5.next = 10; + return ext.langReady({ + lang: lang, + uiStrings: uiStrings$1, + importLocale: getImportLocale({ + defaultLang: lang, + defaultName: ext.name + }) }); - } - break; - case 'select': - html = '<label' + contId + '>' + '<select id="' + tool.id + '">'; - $$b.each(tool.options, function (val, text) { - var sel = val === tool.defval ? ' selected' : ''; - html += '<option value="' + val + '"' + sel + '>' + text + '</option>'; - }); - html += '</select></label>'; - // Creates the tool, hides & adds it, returns the select element - var sel = $$b(html).appendTo(panel).find('select'); - $$b.each(tool.events, function (evt, func) { - $$b(sel).bind(evt, func); - }); - break; - case 'button-select': - html = '<div id="' + tool.id + '" class="dropdown toolset" title="' + tool.title + '">' + '<div id="cur_' + tool.id + '" class="icon_label"></div><button></button></div>'; + case 10: + loadedExtensionNames.push(ext.name); + _context5.next = 14; + break; - var list = $$b('<ul id="' + tool.id + '_opts"></ul>').appendTo('#option_lists'); + case 13: + extsPreLang.push(ext); - if (tool.colnum) { - list.addClass('optcols' + tool.colnum); - } + case 14: + /** + * + * @returns {undefined} + */ + runCallback = function runCallback() { + if (ext.callback && !cbCalled) { + cbCalled = true; + ext.callback.call(editor); + } + }; - // Creates the tool, hides & adds it, returns the select element - /* const dropdown = */$$b(html).appendTo(panel).children(); + btnSelects = []; + /** + * @typedef {PlainObject} module:SVGEditor.ContextTool + * @property {string} panel The ID of the existing panel to which the tool is being added. Required. + * @property {string} id The ID of the actual tool element. Required. + * @property {PlainObject.<string, external:jQuery.Function>|PlainObject.<"change", external:jQuery.Function>} events DOM event names keyed to associated functions. Example: `{change () { alert('Option was changed') } }`. "change" event is one specifically handled for the "button-select" type. Required. + * @property {string} title The tooltip text that will appear when the user hovers over the tool. Required. + * @property {"tool_button"|"select"|"button-select"|"input"|string} type The type of tool being added. Expected. + * @property {PlainObject.<string, string>} [options] List of options and their labels for select tools. Example: `{1: 'One', 2: 'Two', all: 'All' }`. Required by "select" tools. + * @property {string} [container_id] The ID to be given to the tool's container element. + * @property {string} [defval] Default value + * @property {string|Integer} [colnum] Added as part of the option list class. + * @property {string} [label] Label associated with the tool, visible in the UI + * @property {Integer} [size] Value of the "size" attribute of the tool input + * @property {module:jQuerySpinButton.SpinButtonConfig} [spindata] When added to a tool of type "input", this tool becomes a "spinner" which allows the number to be in/decreased. + */ - btnSelects.push({ - elem: '#' + tool.id, - list: '#' + tool.id + '_opts', - title: tool.title, - callback: tool.events.change, - cur: '#cur_' + tool.id - }); + if (ext.context_tools) { + $$b.each(ext.context_tools, function (i, tool) { + // Add select tool + var contId = tool.container_id ? ' id="' + tool.container_id + '"' : ''; + var panel = $$b('#' + tool.panel); // create the panel if it doesn't exist - break; - case 'input': - html = '<label' + contId + '>' + '<span id="' + tool.id + '_label">' + tool.label + ':</span>' + '<input id="' + tool.id + '" title="' + tool.title + '" size="' + (tool.size || '4') + '" value="' + (tool.defval || '') + '" type="text"/></label>'; + if (!panel.length) { + panel = $$b('<div>', { + id: tool.panel + }).appendTo('#tools_top'); + } - // Creates the tool, hides & adds it, returns the select element + var html; // TODO: Allow support for other types, or adding to existing tool - // Add to given tool.panel - var inp = $$b(html).appendTo(panel).find('input'); + switch (tool.type) { + case 'tool_button': + { + html = '<div class="tool_button">' + tool.id + '</div>'; + var div = $$b(html).appendTo(panel); - if (tool.spindata) { - inp.SpinButton(tool.spindata); - } + if (tool.events) { + $$b.each(tool.events, function (evt, func) { + $$b(div).bind(evt, func); + }); + } - if (tool.events) { - $$b.each(tool.events, function (evt, func) { - inp.bind(evt, func); - }); - } - break; + break; + } - default: - break; - } - }); - } + case 'select': + { + html = '<label' + contId + '>' + '<select id="' + tool.id + '">'; + $$b.each(tool.options, function (val, text) { + var sel = val === tool.defval ? ' selected' : ''; + html += '<option value="' + val + '"' + sel + '>' + text + '</option>'; + }); + html += '</select></label>'; // Creates the tool, hides & adds it, returns the select element - var svgicons = ext.svgicons; + var sel = $$b(html).appendTo(panel).find('select'); + $$b.each(tool.events, function (evt, func) { + $$b(sel).bind(evt, func); + }); + break; + } - if (ext.buttons) { - var fallbackObj = {}, - placementObj = {}, - holders = {}; + case 'button-select': + { + html = '<div id="' + tool.id + '" class="dropdown toolset" title="' + tool.title + '">' + '<div id="cur_' + tool.id + '" class="icon_label"></div><button></button></div>'; + var list = $$b('<ul id="' + tool.id + '_opts"></ul>').appendTo('#option_lists'); - /** - * @typedef {GenericArray} module:SVGEditor.KeyArray - * @property {string} 0 The key to bind (on `keydown`) - * @property {boolean} 1 Whether to `preventDefault` on the `keydown` event - * @property {boolean} 2 Not apparently in use (NoDisableInInput) - */ - /** - * @typedef {string|module:SVGEditor.KeyArray} module:SVGEditor.Key - */ - /** - * @typedef {PlainObject} module:SVGEditor.Button - * @property {string} id A unique identifier for this button. If SVG icons are used, this must match the ID used in the icon file. Required. - * @property {"mode_flyout"|"mode"|"context"|"app_menu"} type Type of button. Required. - * @property {string} title The tooltip text that will appear when the user hovers over the icon. Required. - * @property {PlainObject.<string, external:jQuery.Function>|PlainObject.<"click", external:jQuery.Function>} events DOM event names with associated functions. Example: `{click () { alert('Button was clicked') } }`. Click is used with `includeWith` and `type` of "mode_flyout" (and "mode"); any events may be added if `list` is not present. Expected. - * @property {string} panel The ID of the context panel to be included, if type is "context". Required only if type is "context". - * @property {string} icon The file path to the raster version of the icon image source. Required only if no `svgicons` is supplied from [ExtensionInitResponse]{@link module:svgcanvas.ExtensionInitResponse}. - * @property {string} [svgicon] If absent, will utilize the button "id"; used to set "placement" on the `svgIcons` call - * @property {string} [list] Points to the "id" of a `context_tools` item of type "button-select" into which the button will be added as a panel list item - * @property {Integer} [position] The numeric index for placement; defaults to last position (as of the time of extension addition) if not present. For use with {@link http://api.jquery.com/eq/}. - * @property {boolean} [isDefault] Whether or not the button is the default. Used with `list`. - * @property {PlainObject} [includeWith] Object with flyout menu data - * @property {boolean} [includeWith.isDefault] Indicates whether button is default in flyout list or not. - * @property {string} includeWith.button jQuery selector of the existing button to be joined. Example: '#tool_line'. Required if `includeWith` is used. - * @property {"last"|Integer} [includeWith.position] Position of icon in flyout list; will be added to end if not indicated. Integer is for use with {@link http://api.jquery.com/eq/}. - * @property {module:SVGEditor.Key} [key] The key to bind to the button - */ - // Add buttons given by extension - $$b.each(ext.buttons, function (i, /** @type {module:SVGEditor.Button} */btn) { - var id = btn.id; + if (tool.colnum) { + list.addClass('optcols' + tool.colnum); + } // Creates the tool, hides & adds it, returns the select element - var num = i; - // Give button a unique ID - while ($$b('#' + id).length) { - id = btn.id + '_' + ++num; - } + /* const dropdown = */ - var icon = void 0; - if (!svgicons) { - icon = $$b('<img src="' + btn.icon + '">'); - } else { - fallbackObj[id] = btn.icon; - var svgicon = btn.svgicon || btn.id; - if (btn.type === 'app_menu') { - placementObj['#' + id + ' > div'] = svgicon; - } else { - placementObj['#' + id] = svgicon; - } - } - var cls = void 0, - parent = void 0; + $$b(html).appendTo(panel).children(); + btnSelects.push({ + elem: '#' + tool.id, + list: '#' + tool.id + '_opts', + title: tool.title, + callback: tool.events.change, + cur: '#cur_' + tool.id + }); + break; + } - // Set button up according to its type - switch (btn.type) { - case 'mode_flyout': - case 'mode': - cls = 'tool_button'; - parent = '#tools_left'; - break; - case 'context': - cls = 'tool_button'; - parent = '#' + btn.panel; - // create the panel if it doesn't exist - if (!$$b(parent).length) { - $$b('<div>', { id: btn.panel }).appendTo('#tools_top'); - } - break; - case 'app_menu': - cls = ''; - parent = '#main_menu ul'; - break; - } - var flyoutHolder = void 0, - curH = void 0, - showBtn = void 0, - refData = void 0, - refBtn = void 0; - var button = $$b(btn.list || btn.type === 'app_menu' ? '<li/>' : '<div/>').attr('id', id).attr('title', btn.title).addClass(cls); - if (!btn.includeWith && !btn.list) { - if ('position' in btn) { - if ($$b(parent).children().eq(btn.position).length) { - $$b(parent).children().eq(btn.position).before(button); - } else { - $$b(parent).children().last().before(button); - } - } else { - button.appendTo(parent); - } + case 'input': + { + html = '<label' + contId + '>' + '<span id="' + tool.id + '_label">' + tool.label + ':</span>' + '<input id="' + tool.id + '" title="' + tool.title + '" size="' + (tool.size || '4') + '" value="' + (tool.defval || '') + '" type="text"/></label>'; // Creates the tool, hides & adds it, returns the select element + // Add to given tool.panel - if (btn.type === 'mode_flyout') { - // Add to flyout menu / make flyout menu - // const opts = btn.includeWith; - // // opts.button, default, position - refBtn = $$b(button); + var inp = $$b(html).appendTo(panel).find('input'); - flyoutHolder = refBtn.parent(); - // Create a flyout menu if there isn't one already - var tlsId = void 0; - if (!refBtn.parent().hasClass('tools_flyout')) { - // Create flyout placeholder - tlsId = refBtn[0].id.replace('tool_', 'tools_'); - showBtn = refBtn.clone().attr('id', tlsId + '_show').append($$b('<div>', { class: 'flyout_arrow_horiz' })); + if (tool.spindata) { + inp.SpinButton(tool.spindata); + } - refBtn.before(showBtn); + if (tool.events) { + $$b.each(tool.events, function (evt, func) { + inp.bind(evt, func); + }); + } - // Create a flyout div - flyoutHolder = makeFlyoutHolder(tlsId, refBtn); - flyoutHolder.data('isLibrary', true); - showBtn.data('isLibrary', true); - } - // refData = Actions.getButtonData(opts.button); + break; + } - placementObj['#' + tlsId + '_show'] = btn.id; - // TODO: Find way to set the current icon using the iconloader if this is not default - - // Include data for extension button as well as ref button - curH = holders['#' + flyoutHolder[0].id] = [{ - sel: '#' + id, - fn: btn.events.click, - icon: btn.id, - // key: btn.key, - isDefault: true - }]; // , refData - // - // // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'} - // - // const pos = ('position' in opts)?opts.position:'last'; - // const len = flyoutHolder.children().length; - // - // // Add at given position or end - // if (!isNaN(pos) && pos >= 0 && pos < len) { - // flyoutHolder.children().eq(pos).before(button); - // } else { - // flyoutHolder.append(button); - // curH.reverse(); - // } - } else if (btn.type === 'app_menu') { - button.append('<div>').append(btn.title); - } - } else if (btn.list) { - // Add button to list - button.addClass('push_button'); - $$b('#' + btn.list + '_opts').append(button); - if (btn.isDefault) { - $$b('#cur_' + btn.list).append(button.children().clone()); - var _svgicon = btn.svgicon || btn.id; - placementObj['#cur_' + btn.list] = _svgicon; - } - } else if (btn.includeWith) { - // Add to flyout menu / make flyout menu - var opts = btn.includeWith; - // opts.button, default, position - refBtn = $$b(opts.button); - - flyoutHolder = refBtn.parent(); - // Create a flyout menu if there isn't one already - var _tlsId = void 0; - if (!refBtn.parent().hasClass('tools_flyout')) { - // Create flyout placeholder - _tlsId = refBtn[0].id.replace('tool_', 'tools_'); - showBtn = refBtn.clone().attr('id', _tlsId + '_show').append($$b('<div>', { class: 'flyout_arrow_horiz' })); - - refBtn.before(showBtn); - // Create a flyout div - flyoutHolder = makeFlyoutHolder(_tlsId, refBtn); - } - - refData = Actions.getButtonData(opts.button); - - if (opts.isDefault) { - placementObj['#' + _tlsId + '_show'] = btn.id; - } - // TODO: Find way to set the current icon using the iconloader if this is not default - - // Include data for extension button as well as ref button - curH = holders['#' + flyoutHolder[0].id] = [{ - sel: '#' + id, - fn: btn.events.click, - icon: btn.id, - key: btn.key, - isDefault: Boolean(btn.includeWith && btn.includeWith.isDefault) - }, refData]; - - // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'} - - var pos = 'position' in opts ? opts.position : 'last'; - var len = flyoutHolder.children().length; - - // Add at given position or end - if (!isNaN(pos) && pos >= 0 && pos < len) { - flyoutHolder.children().eq(pos).before(button); - } else { - flyoutHolder.append(button); - curH.reverse(); - } - } - - if (!svgicons) { - button.append(icon); - } - - if (!btn.list) { - // Add given events to button - $$b.each(btn.events, function (name, func) { - if (name === 'click' && btn.type === 'mode') { - if (btn.includeWith) { - button.bind(name, func); - } else { - button.bind(name, function () { - if (toolButtonClick(button)) { - func(); + default: + break; } }); } - if (btn.key) { - $$b(document).bind('keydown', btn.key, func); - if (btn.title) { - button.attr('title', btn.title + ' [' + btn.key + ']'); + + svgicons = ext.svgicons; + + if (!ext.buttons) { + _context5.next = 24; + break; + } + + fallbackObj = {}, placementObj = {}, holders = {}; + /** + * @typedef {GenericArray} module:SVGEditor.KeyArray + * @property {string} 0 The key to bind (on `keydown`) + * @property {boolean} 1 Whether to `preventDefault` on the `keydown` event + * @property {boolean} 2 Not apparently in use (NoDisableInInput) + */ + + /** + * @typedef {string|module:SVGEditor.KeyArray} module:SVGEditor.Key + */ + + /** + * @typedef {PlainObject} module:SVGEditor.Button + * @property {string} id A unique identifier for this button. If SVG icons are used, this must match the ID used in the icon file. Required. + * @property {"mode_flyout"|"mode"|"context"|"app_menu"} type Type of button. Required. + * @property {string} title The tooltip text that will appear when the user hovers over the icon. Required. + * @property {PlainObject.<string, external:jQuery.Function>|PlainObject.<"click", external:jQuery.Function>} events DOM event names with associated functions. Example: `{click () { alert('Button was clicked') } }`. Click is used with `includeWith` and `type` of "mode_flyout" (and "mode"); any events may be added if `list` is not present. Expected. + * @property {string} panel The ID of the context panel to be included, if type is "context". Required only if type is "context". + * @property {string} icon The file path to the raster version of the icon image source. Required only if no `svgicons` is supplied from [ExtensionInitResponse]{@link module:svgcanvas.ExtensionInitResponse}. + * @property {string} [svgicon] If absent, will utilize the button "id"; used to set "placement" on the `svgIcons` call + * @property {string} [list] Points to the "id" of a `context_tools` item of type "button-select" into which the button will be added as a panel list item + * @property {Integer} [position] The numeric index for placement; defaults to last position (as of the time of extension addition) if not present. For use with {@link http://api.jquery.com/eq/}. + * @property {boolean} [isDefault] Whether or not the button is the default. Used with `list`. + * @property {PlainObject} [includeWith] Object with flyout menu data + * @property {boolean} [includeWith.isDefault] Indicates whether button is default in flyout list or not. + * @property {string} includeWith.button jQuery selector of the existing button to be joined. Example: '#tool_line'. Required if `includeWith` is used. + * @property {"last"|Integer} [includeWith.position] Position of icon in flyout list; will be added to end if not indicated. Integer is for use with {@link http://api.jquery.com/eq/}. + * @property {module:SVGEditor.Key} [key] The key to bind to the button + */ + // Add buttons given by extension + + $$b.each(ext.buttons, function (i, + /** @type {module:SVGEditor.Button} */ + btn) { + var id = btn.id; + var num = i; // Give button a unique ID + + while ($$b('#' + id).length) { + id = btn.id + '_' + ++num; } + + var icon; + + if (!svgicons) { + icon = $$b('<img src="' + btn.icon + '">'); + } else { + fallbackObj[id] = btn.icon; + var svgicon = btn.svgicon || btn.id; + + if (btn.type === 'app_menu') { + placementObj['#' + id + ' > div'] = svgicon; + } else { + placementObj['#' + id] = svgicon; + } + } + + var cls, parent; // Set button up according to its type + + switch (btn.type) { + case 'mode_flyout': + case 'mode': + cls = 'tool_button'; + parent = '#tools_left'; + break; + + case 'context': + cls = 'tool_button'; + parent = '#' + btn.panel; // create the panel if it doesn't exist + + if (!$$b(parent).length) { + $$b('<div>', { + id: btn.panel + }).appendTo('#tools_top'); + } + + break; + + case 'app_menu': + cls = ''; + parent = '#main_menu ul'; + break; + } + + var flyoutHolder, showBtn, refData, refBtn; + var button = $$b(btn.list || btn.type === 'app_menu' ? '<li/>' : '<div/>').attr('id', id).attr('title', btn.title).addClass(cls); + + if (!btn.includeWith && !btn.list) { + if ('position' in btn) { + if ($$b(parent).children().eq(btn.position).length) { + $$b(parent).children().eq(btn.position).before(button); + } else { + $$b(parent).children().last().after(button); + } + } else { + button.appendTo(parent); + } + + if (btn.type === 'mode_flyout') { + // Add to flyout menu / make flyout menu + // const opts = btn.includeWith; + // // opts.button, default, position + refBtn = $$b(button); + flyoutHolder = refBtn.parent(); // Create a flyout menu if there isn't one already + + var tlsId; + + if (!refBtn.parent().hasClass('tools_flyout')) { + // Create flyout placeholder + tlsId = refBtn[0].id.replace('tool_', 'tools_'); + showBtn = refBtn.clone().attr('id', tlsId + '_show').append($$b('<div>', { + class: 'flyout_arrow_horiz' + })); + refBtn.before(showBtn); // Create a flyout div + + flyoutHolder = makeFlyoutHolder(tlsId, refBtn); + flyoutHolder.data('isLibrary', true); + showBtn.data('isLibrary', true); + } // refData = Actions.getButtonData(opts.button); + + + placementObj['#' + tlsId + '_show'] = btn.id; // TODO: Find way to set the current icon using the iconloader if this is not default + // Include data for extension button as well as ref button + + /* curH = */ + + holders['#' + flyoutHolder[0].id] = [{ + sel: '#' + id, + fn: btn.events.click, + icon: btn.id, + // key: btn.key, + isDefault: true + }]; // , refData + // + // // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'} + // + // const pos = ('position' in opts)?opts.position:'last'; + // const len = flyoutHolder.children().length; + // + // // Add at given position or end + // if (!isNaN(pos) && pos >= 0 && pos < len) { + // flyoutHolder.children().eq(pos).before(button); + // } else { + // flyoutHolder.append(button); + // curH.reverse(); + // } + } else if (btn.type === 'app_menu') { + button.append('<div>').append(btn.title); + } + } else if (btn.list) { + // Add button to list + button.addClass('push_button'); + $$b('#' + btn.list + '_opts').append(button); + + if (btn.isDefault) { + $$b('#cur_' + btn.list).append(button.children().clone()); + + var _svgicon = btn.svgicon || btn.id; + + placementObj['#cur_' + btn.list] = _svgicon; + } + } else if (btn.includeWith) { + // Add to flyout menu / make flyout menu + var opts = btn.includeWith; // opts.button, default, position + + refBtn = $$b(opts.button); + flyoutHolder = refBtn.parent(); // Create a flyout menu if there isn't one already + + var _tlsId; + + if (!refBtn.parent().hasClass('tools_flyout')) { + // Create flyout placeholder + _tlsId = refBtn[0].id.replace('tool_', 'tools_'); + showBtn = refBtn.clone().attr('id', _tlsId + '_show').append($$b('<div>', { + class: 'flyout_arrow_horiz' + })); + refBtn.before(showBtn); // Create a flyout div + + flyoutHolder = makeFlyoutHolder(_tlsId, refBtn); + } + + refData = Actions.getButtonData(opts.button); + + if (opts.isDefault) { + placementObj['#' + _tlsId + '_show'] = btn.id; + } // TODO: Find way to set the current icon using the iconloader if this is not default + // Include data for extension button as well as ref button + + + var curH = holders['#' + flyoutHolder[0].id] = [{ + sel: '#' + id, + fn: btn.events.click, + icon: btn.id, + key: btn.key, + isDefault: Boolean(btn.includeWith && btn.includeWith.isDefault) + }, refData]; // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'} + + var pos = 'position' in opts ? opts.position : 'last'; + var len = flyoutHolder.children().length; // Add at given position or end + + if (!isNaN(pos) && pos >= 0 && pos < len) { + flyoutHolder.children().eq(pos).before(button); + } else { + flyoutHolder.append(button); + curH.reverse(); + } + } + + if (!svgicons) { + button.append(icon); + } + + if (!btn.list) { + // Add given events to button + $$b.each(btn.events, function (name, func) { + if (name === 'click' && btn.type === 'mode') { + // `touch.js` changes `touchstart` to `mousedown`, + // so we must map extension click events as well + if (isTouch() && name === 'click') { + name = 'mousedown'; + } + + if (btn.includeWith) { + button.bind(name, func); + } else { + button.bind(name, function () { + if (toolButtonClick(button)) { + func(); + } + }); + } + + if (btn.key) { + $$b(document).bind('keydown', btn.key, func); + + if (btn.title) { + button.attr('title', btn.title + ' [' + btn.key + ']'); + } + } + } else { + button.bind(name, func); + } + }); + } + + setupFlyouts(holders); + }); + $$b.each(btnSelects, function () { + addAltDropDown(this.elem, this.list, this.callback, { + seticon: true + }); + }); + + if (!svgicons) { + _context5.next = 24; + break; } - } else { - button.bind(name, func); - } - }); + + return _context5.abrupt("return", new Promise(function (resolve, reject) { + // eslint-disable-line promise/avoid-new + $$b.svgIcons(svgicons, { + w: 24, + h: 24, + id_match: false, + no_img: !isWebkit(), + fallback: fallbackObj, + placement: placementObj, + callback: function callback(icons) { + // Non-ideal hack to make the icon match the current size + // if (curPrefs.iconsize && curPrefs.iconsize !== 'm') { + if ($$b.pref('iconsize') !== 'm') { + prepResize(); + } + + runCallback(); + resolve(); + } + }); + })); + + case 24: + return _context5.abrupt("return", runCallback()); + + case 25: + case "end": + return _context5.stop(); + } } + }, _callee5, this); + })); - setupFlyouts(holders); - }); + return function extAdded(_x4, _x5) { + return _ref13.apply(this, arguments); + }; + }(); + /** + * @param {string} color + * @param {Float} opac + * @param {string} type + * @returns {module:jGraduate~Paint} + */ - $$b.each(btnSelects, function () { - addAltDropDown(this.elem, this.list, this.callback, { seticon: true }); - }); - - if (svgicons) { - return new Promise(function (resolve, reject) { - $$b.svgIcons(svgicons, { - w: 24, h: 24, - id_match: false, - no_img: !isWebkit(), - fallback: fallbackObj, - placement: placementObj, - callback: function callback(icons) { - // Non-ideal hack to make the icon match the current size - // if (curPrefs.iconsize && curPrefs.iconsize !== 'm') { - if ($$b.pref('iconsize') !== 'm') { - prepResize(); - } - runCallback(); - resolve(); - } - }); - }); - } - } - return runCallback(); - }; var getPaint = function getPaint(color, opac, type) { // update the editor's fill paint - var opts = { alpha: opac }; + var opts = { + alpha: opac + }; + if (color.startsWith('url(#')) { var refElem = svgCanvas.getRefElem(color); + if (refElem) { refElem = refElem.cloneNode(true); } else { refElem = $$b('#' + type + '_color defs *')[0]; } + opts[refElem.tagName] = refElem; } else if (color.startsWith('#')) { opts.solidColor = color.substr(1); } else { opts.solidColor = 'none'; } + return new $$b.jGraduate.Paint(opts); - }; - - // $('#text').focus(function () { textBeingEntered = true; }); + }; // $('#text').focus(function () { textBeingEntered = true; }); // $('#text').blur(function () { textBeingEntered = false; }); - // bind the selected event to our function that handles updates to the UI + + svgCanvas.bind('selected', selectedChanged); svgCanvas.bind('transition', elementTransition); svgCanvas.bind('changed', elementChanged); @@ -28410,15 +32412,19 @@ // Ignore Chrome return; } + var exportWindowName = data.exportWindowName; if (exportWindowName) { exportWindow = window.open('', exportWindowName); // A hack to get the window via JSON-able name without opening a new one } + if (!exportWindow || exportWindow.closed) { + /* await */ $$b.alert(uiStrings$1.notification.popupWindowBlocked); return; } + exportWindow.location.href = data.output; }); svgCanvas.bind('zoomed', zoomChanged); @@ -28426,30 +32432,29 @@ svgCanvas.bind('updateCanvas', /** * @param {external:Window} win - * @param {false} center - * @param {module:math.XYObject} newCtr + * @param {PlainObject} centerInfo + * @param {false} centerInfo.center + * @param {module:math.XYObject} centerInfo.newCtr * @listens module:svgcanvas.SvgCanvas#event:updateCanvas * @returns {undefined} */ - function (win, _ref14) { - var center = _ref14.center, - newCtr = _ref14.newCtr; - + function (win, _ref15) { + var center = _ref15.center, + newCtr = _ref15.newCtr; updateCanvas(center, newCtr); }); svgCanvas.bind('contextset', contextChanged); svgCanvas.bind('extension_added', extAdded); svgCanvas.textActions.setInputElem($$b('#text')[0]); - var str = '<div class="palette_item" data-rgb="none"></div>'; $$b.each(palette, function (i, item) { str += '<div class="palette_item" style="background-color: ' + item + ';" data-rgb="' + item + '"></div>'; }); - $$b('#palette').append(str); - - // Set up editor background functionality + $$b('#palette').append(str); // Set up editor background functionality // TODO add checkerboard as "pattern" + var colorBlocks = ['#FFF', '#888', '#000']; // ,'url(data:image/gif;base64,R0lGODlhEAAQAIAAAP%2F%2F%2F9bW1iH5BAAAAAAALAAAAAAQABAAAAIfjG%2Bgq4jM3IFLJgpswNly%2FXkcBpIiVaInlLJr9FZWAQA7)']; + str = ''; $$b.each(colorBlocks, function () { str += '<div class="color_block" style="background-color:' + this + ';"></div>'; @@ -28464,53 +32469,87 @@ $$b(this).addClass(curBg); }); }); - setBackground($$b.pref('bkgd_color'), $$b.pref('bkgd_url')); - $$b('#image_save_opts input').val([$$b.pref('img_save')]); + /** + * @implements {module:jQuerySpinButton.ValueCallback} + */ var changeRectRadius = function changeRectRadius(ctl) { svgCanvas.setRectRadius(ctl.value); }; + /** + * @implements {module:jQuerySpinButton.ValueCallback} + */ + var changeFontSize = function changeFontSize(ctl) { svgCanvas.setFontSize(ctl.value); }; + /** + * @implements {module:jQuerySpinButton.ValueCallback} + */ + var changeStrokeWidth = function changeStrokeWidth(ctl) { var val = ctl.value; + if (val === 0 && selectedElement && ['line', 'polyline'].includes(selectedElement.nodeName)) { val = ctl.value = 1; } + svgCanvas.setStrokeWidth(val); }; + /** + * @implements {module:jQuerySpinButton.ValueCallback} + */ + var changeRotationAngle = function changeRotationAngle(ctl) { svgCanvas.setRotationAngle(ctl.value); - $$b('#tool_reorient').toggleClass('disabled', parseInt(ctl.value, 10) === 0); + $$b('#tool_reorient').toggleClass('disabled', parseInt(ctl.value) === 0); }; + /** + * @param {external:jQuery.fn.SpinButton} ctl Spin Button + * @param {string} [val=ctl.value] + * @returns {undefined} + */ + var changeOpacity = function changeOpacity(ctl, val) { - if (val == null) { + if (isNullish(val)) { val = ctl.value; } + $$b('#group_opacity').val(val); + if (!ctl || !ctl.handle) { $$b('#opac_slider').slider('option', 'value', val); } + svgCanvas.setOpacity(val / 100); }; + /** + * @param {external:jQuery.fn.SpinButton} ctl Spin Button + * @param {string} [val=ctl.value] + * @param {boolean} noUndo + * @returns {undefined} + */ + var changeBlur = function changeBlur(ctl, val, noUndo) { - if (val == null) { + if (isNullish(val)) { val = ctl.value; } + $$b('#blur').val(val); var complete = false; + if (!ctl || !ctl.handle) { $$b('#blur_slider').slider('option', 'value', val); complete = true; } + if (noUndo) { svgCanvas.setBlurNoUndo(val); } else { @@ -28522,56 +32561,94 @@ svgCanvas.setStrokeAttr('stroke-dasharray', $$b(this).val()); operaRepaint(); }); - $$b('#stroke_linejoin').change(function () { svgCanvas.setStrokeAttr('stroke-linejoin', $$b(this).val()); operaRepaint(); - }); + }); // Lose focus for select elements when changed (Allows keyboard shortcuts to work better) - // Lose focus for select elements when changed (Allows keyboard shortcuts to work better) $$b('select').change(function () { $$b(this).blur(); - }); + }); // fired when user wants to move elements to another layer - // fired when user wants to move elements to another layer var promptMoveLayerOnce = false; - $$b('#selLayerNames').change(function () { - var destLayer = this.options[this.selectedIndex].value; - var confirmStr = uiStrings$1.notification.QmoveElemsToLayer.replace('%s', destLayer); - var moveToLayer = function moveToLayer(ok) { - if (!ok) { - return; - } - promptMoveLayerOnce = true; - svgCanvas.moveSelectedToLayer(destLayer); - svgCanvas.clearSelection(); - populateLayers(); - }; - if (destLayer) { - if (promptMoveLayerOnce) { - moveToLayer(true); - } else { - $$b.confirm(confirmStr, moveToLayer); - } - } - }); + $$b('#selLayerNames').change( + /*#__PURE__*/ + _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee6() { + var destLayer, confirmStr, moveToLayer, ok; + return regeneratorRuntime.wrap(function _callee6$(_context6) { + while (1) { + switch (_context6.prev = _context6.next) { + case 0: + destLayer = this.options[this.selectedIndex].value; + confirmStr = uiStrings$1.notification.QmoveElemsToLayer.replace('%s', destLayer); + /** + * @param {boolean} ok + * @returns {undefined} + */ + moveToLayer = function moveToLayer(ok) { + if (!ok) { + return; + } + + promptMoveLayerOnce = true; + svgCanvas.moveSelectedToLayer(destLayer); + svgCanvas.clearSelection(); + populateLayers(); + }; + + if (!destLayer) { + _context6.next = 14; + break; + } + + if (!promptMoveLayerOnce) { + _context6.next = 8; + break; + } + + moveToLayer(true); + _context6.next = 14; + break; + + case 8: + _context6.next = 10; + return $$b.confirm(confirmStr); + + case 10: + ok = _context6.sent; + + if (ok) { + _context6.next = 13; + break; + } + + return _context6.abrupt("return"); + + case 13: + moveToLayer(true); + + case 14: + case "end": + return _context6.stop(); + } + } + }, _callee6, this); + }))); $$b('#font_family').change(function () { svgCanvas.setFontFamily(this.value); }); - $$b('#seg_type').change(function () { svgCanvas.setSegType($$b(this).val()); }); - $$b('#text').bind('keyup input', function () { svgCanvas.setTextContent(this.value); }); - $$b('#image_url').change(function () { setImageURL(this.value); }); - $$b('#link_url').change(function () { if (this.value.length) { svgCanvas.setLinkURL(this.value); @@ -28579,19 +32656,19 @@ svgCanvas.removeHyperlink(); } }); - $$b('#g_title').change(function () { svgCanvas.setGroupTitle(this.value); }); - $$b('.attr_changer').change(function () { var attr = this.getAttribute('data-attr'); var val = this.value; var valid = isValidUnit(attr, val, selectedElement); if (!valid) { - $$b.alert(uiStrings$1.notification.invalidAttrValGiven); this.value = selectedElement.getAttribute(attr); + /* await */ + + $$b.alert(uiStrings$1.notification.invalidAttrValGiven); return false; } @@ -28600,17 +32677,16 @@ val = svgCanvas.convertToNum(attr, val); } else if (curConfig.baseUnit !== 'px') { // Convert unitless value to one with given unit - var unitData = getTypeMap(); if (selectedElement[attr] || svgCanvas.getMode() === 'pathedit' || attr === 'x' || attr === 'y') { val *= unitData[curConfig.baseUnit]; } } - } - - // if the user is changing the id, then de-select the element first + } // if the user is changing the id, then de-select the element first // change the ID, then re-select it with the new ID + + if (attr === 'id') { var elem = selectedElement; svgCanvas.clearSelection(); @@ -28619,28 +32695,30 @@ } else { svgCanvas.changeSelectedAttribute(attr, val); } - this.blur(); - }); - // Prevent selection of elements when shift-clicking + this.blur(); + return true; + }); // Prevent selection of elements when shift-clicking + $$b('#palette').mouseover(function () { var inp = $$b('<input type="hidden">'); $$b(this).append(inp); inp.focus().remove(); }); - $$b('.palette_item').mousedown(function (evt) { // shift key or right click for stroke var picker = evt.shiftKey || evt.button === 2 ? 'stroke' : 'fill'; var color = $$b(this).data('rgb'); - var paint = void 0; + var paint; // Webkit-based browsers returned 'initial' here for no stroke - // Webkit-based browsers returned 'initial' here for no stroke if (color === 'none' || color === 'transparent' || color === 'initial') { color = 'none'; paint = new $$b.jGraduate.Paint(); } else { - paint = new $$b.jGraduate.Paint({ alpha: 100, solidColor: color.substr(1) }); + paint = new $$b.jGraduate.Paint({ + alpha: 100, + solidColor: color.substr(1) + }); } paintBox[picker].setPaint(paint); @@ -28649,37 +32727,35 @@ if (color !== 'none' && svgCanvas.getPaintOpacity(picker) !== 1) { svgCanvas.setPaintOpacity(picker, 1.0); } + updateToolButtonState(); }).bind('contextmenu', function (e) { e.preventDefault(); }); - $$b('#toggle_stroke_tools').on('click', function () { $$b('#tools_bottom').toggleClass('expanded'); }); (function () { var wArea = workarea[0]; - var lastX = null, lastY = null, panning = false, keypan = false; - $$b('#svgcanvas').bind('mousemove mouseup', function (evt) { if (panning === false) { - return; + return true; } wArea.scrollLeft -= evt.clientX - lastX; wArea.scrollTop -= evt.clientY - lastY; - lastX = evt.clientX; lastY = evt.clientY; if (evt.type === 'mouseup') { panning = false; } + return false; }).mousedown(function (evt) { if (evt.button === 1 || keypan === true) { @@ -28688,12 +32764,12 @@ lastY = evt.clientY; return false; } - }); + return true; + }); $$b(window).mouseup(function () { panning = false; }); - $$b(document).bind('keydown', 'space', function (evt) { svgCanvas.spaceKey = keypan = true; evt.preventDefault(); @@ -28709,11 +32785,11 @@ workarea.css('cursor', zoomInIcon); } }); - /** * @param {boolean} active * @returns {undefined} */ + editor.setPanning = function (active) { svgCanvas.spaceKey = keypan = active; }; @@ -28723,12 +32799,10 @@ var button = $$b('#main_icon'); var overlay = $$b('#main_icon span'); var list = $$b('#main_menu'); - var onButton = false; var height = 0; var jsHover = true; var setClick = false; - /* // Currently unused const hideMenu = function () { @@ -28738,9 +32812,9 @@ $$b(window).mouseup(function (evt) { if (!onButton) { - button.removeClass('buttondown'); - // do not hide if it was the file input as that input needs to be visible + button.removeClass('buttondown'); // do not hide if it was the file input as that input needs to be visible // for its change event to fire + if (evt.target.tagName !== 'INPUT') { list.fadeOut(200); } else if (!setClick) { @@ -28750,23 +32824,26 @@ }); } } + onButton = false; }).mousedown(function (evt) { // $('.contextMenu').hide(); var islib = $$b(evt.target).closest('div.tools_flyout, .contextMenu').length; + if (!islib) { $$b('.tools_flyout:visible,.contextMenu').fadeOut(250); } }); - overlay.bind('mousedown', function () { if (!button.hasClass('buttondown')) { // Margin must be reset in case it was changed before; list.css('margin-left', 0).show(); + if (!height) { height = list.height(); - } - // Using custom animation as slideDown has annoying 'bounce effect' + } // Using custom animation as slideDown has annoying 'bounce effect' + + list.css('height', 0).animate({ height: height }, 200); @@ -28774,20 +32851,19 @@ } else { list.fadeOut(200); } + button.toggleClass('buttondown buttonup'); }).hover(function () { onButton = true; }).mouseout(function () { onButton = false; }); + var listItems = $$b('#main_menu li'); // Check if JS method of hovering needs to be used (Webkit bug) - var listItems = $$b('#main_menu li'); - - // Check if JS method of hovering needs to be used (Webkit bug) listItems.mouseover(function () { jsHover = $$b(this).css('background-color') === 'rgba(0, 0, 0, 0)'; - listItems.unbind('mouseover'); + if (jsHover) { listItems.mouseover(function () { this.style.backgroundColor = '#FFC'; @@ -28797,9 +32873,9 @@ }); } }); - })(); - // Made public for UI customization. + })(); // Made public for UI customization. // TODO: Group UI functions into a public editor.ui interface. + /** * See {@link http://api.jquery.com/bind/#bind-eventType-eventData-handler} * @callback module:SVGEditor.DropDownCallback @@ -28807,35 +32883,41 @@ * @listens external:jQuery.Event * @returns {undefined|boolean} Calls `preventDefault()` and `stopPropagation()` */ + /** * @param {Element|string} elem DOM Element or selector * @param {module:SVGEditor.DropDownCallback} callback Mouseup callback * @param {boolean} dropUp * @returns {undefined} */ + + editor.addDropDown = function (elem, callback, dropUp) { if (!$$b(elem).length) { return; } // Quit if called on non-existent element + + var button = $$b(elem).find('button'); var list = $$b(elem).find('ul').attr('id', $$b(elem)[0].id + '-list'); + if (dropUp) { $$b(elem).addClass('dropup'); } else { // Move list to place where it can overflow container $$b('#option_lists').append(list); } - list.find('li').bind('mouseup', callback); + list.find('li').bind('mouseup', callback); var onButton = false; $$b(window).mouseup(function (evt) { if (!onButton) { button.removeClass('down'); list.hide(); } + onButton = false; }); - button.bind('mousedown', function () { if (!button.hasClass('down')) { if (!dropUp) { @@ -28845,11 +32927,13 @@ left: pos.left - 10 }); } + list.show(); onButton = true; } else { list.hide(); } + button.toggleClass('down'); }).hover(function () { onButton = true; @@ -28861,16 +32945,15 @@ editor.addDropDown('#font_family_dropdown', function () { $$b('#font_family').val($$b(this).text()).change(); }); - editor.addDropDown('#opacity_dropdown', function () { if ($$b(this).find('div').length) { return; } - var perc = parseInt($$b(this).text().split('%')[0], 10); - changeOpacity(false, perc); - }, true); - // For slider usage, see: http://jqueryui.com/demos/slider/ + var perc = parseInt($$b(this).text().split('%')[0]); + changeOpacity(false, perc); + }, true); // For slider usage, see: http://jqueryui.com/demos/slider/ + $$b('#opac_slider').slider({ start: function start() { $$b('#opacity_dropdown li:not(.special)').hide(); @@ -28883,9 +32966,7 @@ changeOpacity(ui); } }); - editor.addDropDown('#blur_dropdown', $$b.noop); - var slideStart = false; $$b('#blur_slider').slider({ max: 10, @@ -28903,30 +32984,34 @@ changeBlur(ui, null, slideStart); } }); - editor.addDropDown('#zoom_dropdown', function () { var item = $$b(this); var val = item.data('val'); + if (val) { zoomChanged(window, val); } else { - changeZoom({ value: parseFloat(item.text()) }); + changeZoom({ + value: parseFloat(item.text()) + }); } }, true); - addAltDropDown('#stroke_linecap', '#linecap_opts', function () { setStrokeOpt(this, true); - }, { dropUp: true }); - + }, { + dropUp: true + }); addAltDropDown('#stroke_linejoin', '#linejoin_opts', function () { setStrokeOpt(this, true); - }, { dropUp: true }); - + }, { + dropUp: true + }); addAltDropDown('#tool_position', '#position_opts', function () { var letter = this.id.replace('tool_pos', '').charAt(0); svgCanvas.alignSelectedElements(letter, 'page'); - }, { multiclick: true }); - + }, { + multiclick: true + }); /* When a flyout icon is selected (if flyout) { @@ -28939,81 +33024,137 @@ , else: - Just run its stuff */ - // Unfocus text input when workarea is mousedowned. + (function () { - var inp = void 0; + var inp; + /** + * + * @returns {undefined} + */ + var unfocus = function unfocus() { $$b(inp).blur(); }; $$b('#svg_editor').find('button, select, input:not(#text)').focus(function () { - inp = this; + inp = this; // eslint-disable-line consistent-this + uiContext = 'toolbars'; workarea.mousedown(unfocus); }).blur(function () { uiContext = 'canvas'; - workarea.unbind('mousedown', unfocus); - // Go back to selecting text if in textedit mode + workarea.unbind('mousedown', unfocus); // Go back to selecting text if in textedit mode + if (svgCanvas.getMode() === 'textedit') { $$b('#text').focus(); } }); })(); + /** + * + * @returns {undefined} + */ + var clickFHPath = function clickFHPath() { if (toolButtonClick('#tool_fhpath')) { svgCanvas.setMode('fhpath'); } }; + /** + * + * @returns {undefined} + */ + var clickLine = function clickLine() { if (toolButtonClick('#tool_line')) { svgCanvas.setMode('line'); } }; + /** + * + * @returns {undefined} + */ + var clickSquare = function clickSquare() { if (toolButtonClick('#tool_square')) { svgCanvas.setMode('square'); } }; + /** + * + * @returns {undefined} + */ + var clickRect = function clickRect() { if (toolButtonClick('#tool_rect')) { svgCanvas.setMode('rect'); } }; + /** + * + * @returns {undefined} + */ + var clickFHRect = function clickFHRect() { if (toolButtonClick('#tool_fhrect')) { svgCanvas.setMode('fhrect'); } }; + /** + * + * @returns {undefined} + */ + var clickCircle = function clickCircle() { if (toolButtonClick('#tool_circle')) { svgCanvas.setMode('circle'); } }; + /** + * + * @returns {undefined} + */ + var clickEllipse = function clickEllipse() { if (toolButtonClick('#tool_ellipse')) { svgCanvas.setMode('ellipse'); } }; + /** + * + * @returns {undefined} + */ + var clickFHEllipse = function clickFHEllipse() { if (toolButtonClick('#tool_fhellipse')) { svgCanvas.setMode('fhellipse'); } }; + /** + * + * @returns {undefined} + */ + var clickImage = function clickImage() { if (toolButtonClick('#tool_image')) { svgCanvas.setMode('image'); } }; + /** + * + * @returns {undefined} + */ + var clickZoom = function clickZoom() { if (toolButtonClick('#tool_zoom')) { @@ -29021,16 +33162,26 @@ workarea.css('cursor', zoomInIcon); } }; + /** + * @param {Float} multiplier + * @returns {undefined} + */ + var zoomImage = function zoomImage(multiplier) { var res = svgCanvas.getResolution(); - multiplier = multiplier ? res.zoom * multiplier : 1; - // setResolution(res.w * multiplier, res.h * multiplier, true); + multiplier = multiplier ? res.zoom * multiplier : 1; // setResolution(res.w * multiplier, res.h * multiplier, true); + $$b('#zoom').val(multiplier * 100); svgCanvas.setZoom(multiplier); zoomDone(); updateCanvas(true); }; + /** + * + * @returns {undefined} + */ + var dblclickZoom = function dblclickZoom() { if (toolButtonClick('#tool_zoom')) { @@ -29038,38 +33189,67 @@ setSelectMode(); } }; + /** + * + * @returns {undefined} + */ + var clickText = function clickText() { if (toolButtonClick('#tool_text')) { svgCanvas.setMode('text'); } }; + /** + * + * @returns {undefined} + */ + var clickPath = function clickPath() { if (toolButtonClick('#tool_path')) { svgCanvas.setMode('path'); } }; + /** + * Delete is a contextual tool that only appears in the ribbon if + * an element has been selected. + * @returns {undefined} + */ + - // Delete is a contextual tool that only appears in the ribbon if - // an element has been selected var deleteSelected = function deleteSelected() { - if (selectedElement != null || multiselected) { + if (!isNullish(selectedElement) || multiselected) { svgCanvas.deleteSelectedElements(); } }; + /** + * + * @returns {undefined} + */ + var cutSelected = function cutSelected() { - if (selectedElement != null || multiselected) { + if (!isNullish(selectedElement) || multiselected) { svgCanvas.cutSelectedElements(); } }; + /** + * + * @returns {undefined} + */ + var copySelected = function copySelected() { - if (selectedElement != null || multiselected) { + if (!isNullish(selectedElement) || multiselected) { svgCanvas.copySelectedElements(); } }; + /** + * + * @returns {undefined} + */ + var pasteInCenter = function pasteInCenter() { var zoom = svgCanvas.getZoom(); @@ -29077,76 +33257,162 @@ var y = (workarea[0].scrollTop + workarea.height() / 2) / zoom - svgCanvas.contentH; svgCanvas.pasteElements('point', x, y); }; + /** + * + * @returns {undefined} + */ + var moveToTopSelected = function moveToTopSelected() { - if (selectedElement != null) { + if (!isNullish(selectedElement)) { svgCanvas.moveToTopSelectedElement(); } }; + /** + * + * @returns {undefined} + */ + var moveToBottomSelected = function moveToBottomSelected() { - if (selectedElement != null) { + if (!isNullish(selectedElement)) { svgCanvas.moveToBottomSelectedElement(); } }; + /** + * @param {"Up"|"Down"} dir + * @returns {undefined} + */ + var moveUpDownSelected = function moveUpDownSelected(dir) { - if (selectedElement != null) { + if (!isNullish(selectedElement)) { svgCanvas.moveUpDownSelected(dir); } }; + /** + * + * @returns {undefined} + */ - var convertToPath$$1 = function convertToPath$$1() { - if (selectedElement != null) { + + var convertToPath = function convertToPath() { + if (!isNullish(selectedElement)) { svgCanvas.convertToPath(); } }; + /** + * + * @returns {undefined} + */ + var reorientPath = function reorientPath() { - if (selectedElement != null) { + if (!isNullish(selectedElement)) { path.reorient(); } }; + /** + * + * @returns {Promise} Resolves to `undefined` + */ - var makeHyperlink = function makeHyperlink() { - if (selectedElement != null || multiselected) { - $$b.prompt(uiStrings$1.notification.enterNewLinkURL, 'http://', function (url) { - if (url) { - svgCanvas.makeHyperlink(url); + + var makeHyperlink = + /*#__PURE__*/ + function () { + var _ref17 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee7() { + var url; + return regeneratorRuntime.wrap(function _callee7$(_context7) { + while (1) { + switch (_context7.prev = _context7.next) { + case 0: + if (!(!isNullish(selectedElement) || multiselected)) { + _context7.next = 5; + break; + } + + _context7.next = 3; + return $$b.prompt(uiStrings$1.notification.enterNewLinkURL, 'http://'); + + case 3: + url = _context7.sent; + + if (url) { + svgCanvas.makeHyperlink(url); + } + + case 5: + case "end": + return _context7.stop(); + } } - }); - } - }; + }, _callee7, this); + })); + + return function makeHyperlink() { + return _ref17.apply(this, arguments); + }; + }(); + /** + * @param {Float} dx + * @param {Float} dy + * @returns {undefined} + */ + var moveSelected = function moveSelected(dx, dy) { - if (selectedElement != null || multiselected) { + if (!isNullish(selectedElement) || multiselected) { if (curConfig.gridSnapping) { // Use grid snap value regardless of zoom level var multi = svgCanvas.getZoom() * curConfig.snappingStep; dx *= multi; dy *= multi; } + svgCanvas.moveSelectedElements(dx, dy); } }; + /** + * + * @returns {undefined} + */ + var linkControlPoints = function linkControlPoints() { $$b('#tool_node_link').toggleClass('push_button_pressed tool_button'); var linked = $$b('#tool_node_link').hasClass('push_button_pressed'); path.linkControlPoints(linked); }; + /** + * + * @returns {undefined} + */ + var clonePathNode = function clonePathNode() { if (path.getNodePoint()) { path.clonePathNode(); } }; + /** + * + * @returns {undefined} + */ + var deletePathNode = function deletePathNode() { if (path.getNodePoint()) { path.deletePathNode(); } }; + /** + * + * @returns {undefined} + */ + var addSubPath = function addSubPath() { var button = $$b('#tool_add_subpath'); @@ -29154,67 +33420,135 @@ button.toggleClass('push_button_pressed tool_button'); path.addSubPath(sp); }; + /** + * + * @returns {undefined} + */ + var opencloseSubPath = function opencloseSubPath() { path.opencloseSubPath(); }; + /** + * + * @returns {undefined} + */ + var selectNext = function selectNext() { svgCanvas.cycleElement(1); }; + /** + * + * @returns {undefined} + */ + var selectPrev = function selectPrev() { svgCanvas.cycleElement(0); }; + /** + * @param {0|1} cw + * @param {Integer} step + * @returns {undefined} + */ + var rotateSelected = function rotateSelected(cw, step) { - if (selectedElement == null || multiselected) { + if (isNullish(selectedElement) || multiselected) { return; } + if (!cw) { step *= -1; } + var angle = parseFloat($$b('#angle').val()) + step; svgCanvas.setRotationAngle(angle); updateContextPanel(); }; - /** * @fires module:svgcanvas.SvgCanvas#event:ext-onNewDocument - * @returns {undefined} + * @returns {Promise} Resolves to `undefined` */ - var clickClear = function clickClear() { - var _curConfig$dimensions = slicedToArray(curConfig.dimensions, 2), - x = _curConfig$dimensions[0], - y = _curConfig$dimensions[1]; - $$b.confirm(uiStrings$1.notification.QwantToClear, function (ok) { - if (!ok) { - return; - } - setSelectMode(); - svgCanvas.clear(); - svgCanvas.setResolution(x, y); - updateCanvas(true); - zoomImage(); - populateLayers(); - updateContextPanel(); - prepPaints(); - svgCanvas.runExtensions('onNewDocument'); - }); - }; + + var clickClear = + /*#__PURE__*/ + function () { + var _ref18 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee8() { + var _curConfig$dimensions, x, y, ok; + + return regeneratorRuntime.wrap(function _callee8$(_context8) { + while (1) { + switch (_context8.prev = _context8.next) { + case 0: + _curConfig$dimensions = _slicedToArray(curConfig.dimensions, 2), x = _curConfig$dimensions[0], y = _curConfig$dimensions[1]; + _context8.next = 3; + return $$b.confirm(uiStrings$1.notification.QwantToClear); + + case 3: + ok = _context8.sent; + + if (ok) { + _context8.next = 6; + break; + } + + return _context8.abrupt("return"); + + case 6: + setSelectMode(); + svgCanvas.clear(); + svgCanvas.setResolution(x, y); + updateCanvas(true); + zoomImage(); + populateLayers(); + updateContextPanel(); + prepPaints(); + svgCanvas.runExtensions('onNewDocument'); + + case 15: + case "end": + return _context8.stop(); + } + } + }, _callee8, this); + })); + + return function clickClear() { + return _ref18.apply(this, arguments); + }; + }(); + /** + * + * @returns {false} + */ + var clickBold = function clickBold() { svgCanvas.setBold(!svgCanvas.getBold()); updateContextPanel(); return false; }; + /** + * + * @returns {false} + */ + var clickItalic = function clickItalic() { svgCanvas.setItalic(!svgCanvas.getItalic()); updateContextPanel(); return false; }; + /** + * + * @returns {undefined} + */ + var clickSave = function clickSave() { // In the future, more options can be provided here @@ -29225,105 +33559,142 @@ svgCanvas.save(saveOpts); }; - var loadingURL = void 0; - var clickExport = function clickExport() { - $$b.select('Select an image type for export: ', [ - // See http://kangax.github.io/jstests/toDataUrl_mime_type_test/ for a useful list of MIME types and browser support - // 'ICO', // Todo: Find a way to preserve transparency in SVG-Edit if not working presently and do full packaging for x-icon; then switch back to position after 'PNG' - 'PNG', 'JPEG', 'BMP', 'WEBP', 'PDF'], function () { - var _ref15 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5(imgType) { - var exportWindowName, openExportWindow, chrome, quality; - return regeneratorRuntime.wrap(function _callee5$(_context5) { - while (1) { - switch (_context5.prev = _context5.next) { - case 0: - openExportWindow = function openExportWindow() { - var str = uiStrings$1.notification.loadingImage; - if (curConfig.exportWindowType === 'new') { - editor.exportWindowCt++; - } - exportWindowName = curConfig.canvasName + editor.exportWindowCt; - var popHTML = void 0, - popURL = void 0; - if (loadingURL) { - popURL = loadingURL; + var loadingURL; + /** + * + * @returns {Promise} Resolves to `undefined` + */ + + var clickExport = + /*#__PURE__*/ + function () { + var _ref19 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee9() { + var imgType, exportWindowName, openExportWindow, chrome, quality; + return regeneratorRuntime.wrap(function _callee9$(_context9) { + while (1) { + switch (_context9.prev = _context9.next) { + case 0: + openExportWindow = function _ref20() { + var loadingImage = uiStrings$1.notification.loadingImage; + + if (curConfig.exportWindowType === 'new') { + editor.exportWindowCt++; + } + + exportWindowName = curConfig.canvasName + editor.exportWindowCt; + var popHTML, popURL; + + if (loadingURL) { + popURL = loadingURL; + } else { + popHTML = "<!DOCTYPE html><html>\n <head>\n <meta charset=\"utf-8\">\n <title>".concat(loadingImage, "\n \n

    ").concat(loadingImage, "

    \n "); + + if (typeof URL !== 'undefined' && URL.createObjectURL) { + var blob = new Blob([popHTML], { + type: 'text/html' + }); + popURL = URL.createObjectURL(blob); } else { - popHTML = '\n \n \n ' + str + '\n \n

    ' + str + '

    \n '; - if ((typeof URL === 'undefined' ? 'undefined' : _typeof(URL)) && URL.createObjectURL) { - var blob = new Blob([popHTML], { type: 'text/html' }); - popURL = URL.createObjectURL(blob); - } else { - popURL = 'data:text/html;base64;charset=utf-8,' + encode64(popHTML); - } - loadingURL = popURL; + popURL = 'data:text/html;base64;charset=utf-8,' + encode64(popHTML); } - exportWindow = window.open(popURL, exportWindowName); - }; - if (imgType) { - _context5.next = 3; - break; + loadingURL = popURL; } - return _context5.abrupt('return'); + exportWindow = window.open(popURL, exportWindowName); + }; - case 3: - // Open placeholder window (prevents popup) - exportWindowName = void 0; - chrome = isChrome(); + _context9.next = 3; + return $$b.select('Select an image type for export: ', [// See http://kangax.github.io/jstests/toDataUrl_mime_type_test/ for a useful list of MIME types and browser support + // 'ICO', // Todo: Find a way to preserve transparency in SVG-Edit if not working presently and do full packaging for x-icon; then switch back to position after 'PNG' + 'PNG', 'JPEG', 'BMP', 'WEBP', 'PDF'], function () { + var sel = $$b(this); - if (!(imgType === 'PDF')) { - _context5.next = 10; - break; + if (sel.val() === 'JPEG' || sel.val() === 'WEBP') { + if (!$$b('#image-slider').length) { + $$b("
    ")).appendTo(sel.parent()); + } + } else { + $$b('#image-slider').parent().remove(); } + }); - if (!customExportPDF && !chrome) { - openExportWindow(); - } - svgCanvas.exportPDF(exportWindowName, chrome ? 'save' : undefined); - _context5.next = 14; + case 3: + imgType = _context9.sent; + + if (imgType) { + _context9.next = 6; break; + } - case 10: - if (!customExportImage) { - openExportWindow(); - } - quality = parseInt($$b('#image-slider').val(), 10) / 100; - /* const results = */ - _context5.next = 14; - return svgCanvas.rasterExport(imgType, quality, exportWindowName); + return _context9.abrupt("return"); - case 14: - case 'end': - return _context5.stop(); - } + case 6: + chrome = isChrome(); + + if (!(imgType === 'PDF')) { + _context9.next = 12; + break; + } + + if (!customExportPDF && !chrome) { + openExportWindow(); + } + + svgCanvas.exportPDF(exportWindowName); + _context9.next = 16; + break; + + case 12: + if (!customExportImage) { + openExportWindow(); + } + + quality = parseInt($$b('#image-slider').val()) / 100; + /* const results = */ + + _context9.next = 16; + return svgCanvas.rasterExport(imgType, quality, exportWindowName); + + case 16: + case "end": + return _context9.stop(); } - }, _callee5, this); - })); - - return function (_x5) { - return _ref15.apply(this, arguments); - }; - }(), function () { - var sel = $$b(this); - if (sel.val() === 'JPEG' || sel.val() === 'WEBP') { - if (!$$b('#image-slider').length) { - $$b('
    ').appendTo(sel.parent()); } - } else { - $$b('#image-slider').parent().remove(); - } - }); - }; + }, _callee9, this); + })); + + return function clickExport() { + return _ref19.apply(this, arguments); + }; + }(); + /** + * By default, svgCanvas.open() is a no-op. It is up to an extension + * mechanism (opera widget, etc.) to call `setCustomHandlers()` which + * will make it do something. + * @returns {undefined} + */ + - // by default, svgCanvas.open() is a no-op. - // it is up to an extension mechanism (opera widget, etc) - // to call setCustomHandlers() which will make it do something var clickOpen = function clickOpen() { svgCanvas.open(); }; + /** + * + * @returns {undefined} + */ + + + var clickImport = function clickImport() { + /* */ + }; + /** + * + * @returns {undefined} + */ - var clickImport = function clickImport() {}; var clickUndo = function clickUndo() { if (undoMgr.getUndoStackSize() > 0) { @@ -29331,6 +33702,11 @@ populateLayers(); } }; + /** + * + * @returns {undefined} + */ + var clickRedo = function clickRedo() { if (undoMgr.getRedoStackSize() > 0) { @@ -29338,25 +33714,44 @@ populateLayers(); } }; + /** + * + * @returns {undefined} + */ + var clickGroup = function clickGroup() { // group if (multiselected) { - svgCanvas.groupSelectedElements(); - // ungroup + svgCanvas.groupSelectedElements(); // ungroup } else if (selectedElement) { svgCanvas.ungroupSelectedElement(); } }; + /** + * + * @returns {undefined} + */ + var clickClone = function clickClone() { svgCanvas.cloneSelectedElements(20, 20); }; + /** + * + * @returns {undefined} + */ + var clickAlign = function clickAlign() { var letter = this.id.replace('tool_align', '').charAt(0); svgCanvas.alignSelectedElements(letter, $$b('#align_relative_to').val()); }; + /** + * + * @returns {undefined} + */ + var clickWireframe = function clickWireframe() { $$b('#tool_wireframe').toggleClass('push_button_pressed tool_button'); @@ -29365,9 +33760,12 @@ if (supportsNonSS) { return; } + var wfRules = $$b('#wireframe_rules'); + if (!wfRules.length) { - wfRules = $$b('').appendTo('head'); + /* wfRules = */ + $$b('').appendTo('head'); } else { wfRules.empty(); } @@ -29379,21 +33777,24 @@ cancel: 'button,fieldset', containment: 'window' }).css('position', 'absolute'); - var docprops = false; var preferences = false; + /** + * + * @returns {undefined} + */ var showDocProperties = function showDocProperties() { if (docprops) { return; } - docprops = true; - // This selects the correct radio button by using the array notation - $$b('#image_save_opts input').val([$$b.pref('img_save')]); + docprops = true; // This selects the correct radio button by using the array notation + + $$b('#image_save_opts input').val([$$b.pref('img_save')]); // update resolution option with actual resolution - // update resolution option with actual resolution var res = svgCanvas.getResolution(); + if (curConfig.baseUnit !== 'px') { res.w = convertUnit(res.w) + curConfig.baseUnit; res.h = convertUnit(res.h) + curConfig.baseUnit; @@ -29402,75 +33803,135 @@ $$b('#canvas_width').val(res.w); $$b('#canvas_height').val(res.h); $$b('#canvas_title').val(svgCanvas.getDocumentTitle()); - $$b('#svg_docprops').show(); }; + /** + * + * @returns {undefined} + */ + var showPreferences = function showPreferences() { if (preferences) { return; } - preferences = true; - $$b('#main_menu').hide(); - // Update background color with current one - var blocks = $$b('#bg_blocks div'); - var curBg = 'cur_background'; + preferences = true; + $$b('#main_menu').hide(); // Update background color with current one + var canvasBg = curPrefs.bkgd_color; var url = $$b.pref('bkgd_url'); blocks.each(function () { var blk = $$b(this); var isBg = blk.css('background-color') === canvasBg; blk.toggleClass(curBg, isBg); + if (isBg) { $$b('#canvas_bg_url').removeClass(curBg); } }); + if (!canvasBg) { blocks.eq(0).addClass(curBg); } + if (url) { $$b('#canvas_bg_url').val(url); } + $$b('#grid_snapping_on').prop('checked', curConfig.gridSnapping); $$b('#grid_snapping_step').attr('value', curConfig.snappingStep); $$b('#grid_color').attr('value', curConfig.gridColor); - $$b('#svg_prefs').show(); }; + /** + * + * @returns {undefined} + */ + var hideSourceEditor = function hideSourceEditor() { $$b('#svg_source_editor').hide(); editingsource = false; $$b('#svg_source_textarea').blur(); }; + /** + * + * @returns {Promise} Resolves to `undefined` + */ - var saveSourceEditor = function saveSourceEditor() { - if (!editingsource) { - return; - } - var saveChanges = function saveChanges() { - svgCanvas.clearSelection(); - hideSourceEditor(); - zoomImage(); - populateLayers(); - updateTitle(); - prepPaints(); - }; + var saveSourceEditor = + /*#__PURE__*/ + function () { + var _ref21 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee10() { + var saveChanges, ok; + return regeneratorRuntime.wrap(function _callee10$(_context10) { + while (1) { + switch (_context10.prev = _context10.next) { + case 0: + if (editingsource) { + _context10.next = 2; + break; + } - if (!svgCanvas.setSvgString($$b('#svg_source_textarea').val())) { - $$b.confirm(uiStrings$1.notification.QerrorsRevertToSource, function (ok) { - if (!ok) { - return false; + return _context10.abrupt("return"); + + case 2: + saveChanges = function saveChanges() { + svgCanvas.clearSelection(); + hideSourceEditor(); + zoomImage(); + populateLayers(); + updateTitle(); + prepPaints(); + }; + + if (svgCanvas.setSvgString($$b('#svg_source_textarea').val())) { + _context10.next = 11; + break; + } + + _context10.next = 6; + return $$b.confirm(uiStrings$1.notification.QerrorsRevertToSource); + + case 6: + ok = _context10.sent; + + if (ok) { + _context10.next = 9; + break; + } + + return _context10.abrupt("return"); + + case 9: + saveChanges(); + return _context10.abrupt("return"); + + case 11: + saveChanges(); + setSelectMode(); + + case 13: + case "end": + return _context10.stop(); + } } - saveChanges(); - }); - } else { - saveChanges(); - } - setSelectMode(); - }; + }, _callee10, this); + })); + + return function saveSourceEditor() { + return _ref21.apply(this, arguments); + }; + }(); + /** + * + * @returns {undefined} + */ + var hideDocProperties = function hideDocProperties() { $$b('#svg_docprops').hide(); @@ -29479,150 +33940,250 @@ $$b('#image_save_opts input').val([$$b.pref('img_save')]); docprops = false; }; + /** + * + * @returns {undefined} + */ + var hidePreferences = function hidePreferences() { $$b('#svg_prefs').hide(); preferences = false; }; + /** + * + * @returns {boolean} Whether there were problems saving the document properties + */ + var saveDocProperties = function saveDocProperties() { // set title var newTitle = $$b('#canvas_title').val(); updateTitle(newTitle); - svgCanvas.setDocumentTitle(newTitle); + svgCanvas.setDocumentTitle(newTitle); // update resolution - // update resolution var width = $$b('#canvas_width'), w = width.val(); var height = $$b('#canvas_height'), h = height.val(); if (w !== 'fit' && !isValidUnit('width', w)) { - $$b.alert(uiStrings$1.notification.invalidAttrValGiven); width.parent().addClass('error'); + /* await */ + + $$b.alert(uiStrings$1.notification.invalidAttrValGiven); return false; } width.parent().removeClass('error'); if (h !== 'fit' && !isValidUnit('height', h)) { - $$b.alert(uiStrings$1.notification.invalidAttrValGiven); height.parent().addClass('error'); + /* await */ + + $$b.alert(uiStrings$1.notification.invalidAttrValGiven); return false; } height.parent().removeClass('error'); if (!svgCanvas.setResolution(w, h)) { + /* await */ $$b.alert(uiStrings$1.notification.noContentToFitTo); return false; - } + } // Set image save option + - // Set image save option $$b.pref('img_save', $$b('#image_save_opts :checked').val()); updateCanvas(); hideDocProperties(); + return true; }; - /** - * Save user preferences based on current values in the UI + * Save user preferences based on current values in the UI. * @function module:SVGEditor.savePreferences * @returns {undefined} */ - var savePreferences = editor.savePreferences = function () { - // Set background - var color = $$b('#bg_blocks div.cur_background').css('background-color') || '#FFF'; - setBackground(color, $$b('#canvas_bg_url').val()); - // set language - var lang = $$b('#lang_select').val(); - if (lang !== $$b.pref('lang')) { - editor.putLocale(lang, goodLangs, curConfig); - } - // set icon size - setIconSize($$b('#iconsize').val()); + var savePreferences = editor.savePreferences = + /*#__PURE__*/ + _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee11() { + var color, lang, _ref23, langParam, langData; - // set grid setting - curConfig.gridSnapping = $$b('#grid_snapping_on')[0].checked; - curConfig.snappingStep = $$b('#grid_snapping_step').val(); - curConfig.gridColor = $$b('#grid_color').val(); - curConfig.showRulers = $$b('#show_rulers')[0].checked; + return regeneratorRuntime.wrap(function _callee11$(_context11) { + while (1) { + switch (_context11.prev = _context11.next) { + case 0: + // Set background + color = $$b('#bg_blocks div.cur_background').css('background-color') || '#FFF'; + setBackground(color, $$b('#canvas_bg_url').val()); // set language - $$b('#rulers').toggle(curConfig.showRulers); - if (curConfig.showRulers) { - updateRulers(); - } - curConfig.baseUnit = $$b('#base_unit').val(); + lang = $$b('#lang_select').val(); - svgCanvas.setConfig(curConfig); + if (!(lang !== $$b.pref('lang'))) { + _context11.next = 11; + break; + } - updateCanvas(); - hidePreferences(); - }; + _context11.next = 6; + return editor.putLocale(lang, goodLangs, curConfig); + + case 6: + _ref23 = _context11.sent; + langParam = _ref23.langParam; + langData = _ref23.langData; + _context11.next = 11; + return setLang(langParam, langData); + + case 11: + // set icon size + setIconSize($$b('#iconsize').val()); // set grid setting + + curConfig.gridSnapping = $$b('#grid_snapping_on')[0].checked; + curConfig.snappingStep = $$b('#grid_snapping_step').val(); + curConfig.gridColor = $$b('#grid_color').val(); + curConfig.showRulers = $$b('#show_rulers')[0].checked; + $$b('#rulers').toggle(curConfig.showRulers); + + if (curConfig.showRulers) { + updateRulers(); + } + + curConfig.baseUnit = $$b('#base_unit').val(); + svgCanvas.setConfig(curConfig); + updateCanvas(); + hidePreferences(); + + case 22: + case "end": + return _context11.stop(); + } + } + }, _callee11, this); + })); var resetScrollPos = $$b.noop; + /** + * + * @returns {Promise} Resolves to `undefined` + */ - var cancelOverlays = function cancelOverlays() { - $$b('#dialog_box').hide(); - if (!editingsource && !docprops && !preferences) { - if (curContext) { - svgCanvas.leaveContext(); - } - return; - } + var cancelOverlays = + /*#__PURE__*/ + function () { + var _ref24 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee12() { + var ok; + return regeneratorRuntime.wrap(function _callee12$(_context12) { + while (1) { + switch (_context12.prev = _context12.next) { + case 0: + $$b('#dialog_box').hide(); - if (editingsource) { - if (origSource !== $$b('#svg_source_textarea').val()) { - $$b.confirm(uiStrings$1.notification.QignoreSourceChanges, function (ok) { - if (ok) { - hideSourceEditor(); + if (!(!editingsource && !docprops && !preferences)) { + _context12.next = 4; + break; + } + + if (curContext) { + svgCanvas.leaveContext(); + } + + return _context12.abrupt("return"); + + case 4: + if (!editingsource) { + _context12.next = 15; + break; + } + + if (!(origSource !== $$b('#svg_source_textarea').val())) { + _context12.next = 12; + break; + } + + _context12.next = 8; + return $$b.confirm(uiStrings$1.notification.QignoreSourceChanges); + + case 8: + ok = _context12.sent; + + if (ok) { + hideSourceEditor(); + } + + _context12.next = 13; + break; + + case 12: + hideSourceEditor(); + + case 13: + _context12.next = 16; + break; + + case 15: + if (docprops) { + hideDocProperties(); + } else if (preferences) { + hidePreferences(); + } + + case 16: + resetScrollPos(); + + case 17: + case "end": + return _context12.stop(); } - }); - } else { - hideSourceEditor(); - } - } else if (docprops) { - hideDocProperties(); - } else if (preferences) { - hidePreferences(); - } - resetScrollPos(); - }; - - var winWh = { width: $$b(window).width(), height: $$b(window).height() }; - - // Fix for Issue 781: Drawing area jumps to top-left corner on window resize (IE9) - if (isIE()) { - (function () { - resetScrollPos = function resetScrollPos() { - if (workarea[0].scrollLeft === 0 && workarea[0].scrollTop === 0) { - workarea[0].scrollLeft = curScrollPos.left; - workarea[0].scrollTop = curScrollPos.top; } - }; + }, _callee12, this); + })); + return function cancelOverlays() { + return _ref24.apply(this, arguments); + }; + }(); + + var winWh = { + width: $$b(window).width(), + height: $$b(window).height() + }; // Fix for Issue 781: Drawing area jumps to top-left corner on window resize (IE9) + + if (isIE()) { + resetScrollPos = function resetScrollPos() { + if (workarea[0].scrollLeft === 0 && workarea[0].scrollTop === 0) { + workarea[0].scrollLeft = curScrollPos.left; + workarea[0].scrollTop = curScrollPos.top; + } + }; + + curScrollPos = { + left: workarea[0].scrollLeft, + top: workarea[0].scrollTop + }; + $$b(window).resize(resetScrollPos); + editor.ready(function () { + // TODO: Find better way to detect when to do this to minimize + // flickering effect + return new Promise(function (resolve, reject) { + // eslint-disable-line promise/avoid-new + setTimeout(function () { + resetScrollPos(); + resolve(); + }, 500); + }); + }); + workarea.scroll(function () { curScrollPos = { left: workarea[0].scrollLeft, top: workarea[0].scrollTop }; - - $$b(window).resize(resetScrollPos); - editor.ready(function () { - // TODO: Find better way to detect when to do this to minimize - // flickering effect - setTimeout(function () { - resetScrollPos(); - }, 500); - }); - - workarea.scroll(function () { - curScrollPos = { - left: workarea[0].scrollLeft, - top: workarea[0].scrollTop - }; - }); - })(); + }); } $$b(window).resize(function (evt) { @@ -29633,43 +34194,35 @@ }); setFlyoutPositions(); }); + workarea.scroll(function () { + // TODO: jQuery's scrollLeft/Top() wouldn't require a null check + if ($$b('#ruler_x').length) { + $$b('#ruler_x')[0].scrollLeft = workarea[0].scrollLeft; + } - (function () { - workarea.scroll(function () { - // TODO: jQuery's scrollLeft/Top() wouldn't require a null check - if ($$b('#ruler_x').length) { - $$b('#ruler_x')[0].scrollLeft = workarea[0].scrollLeft; - } - if ($$b('#ruler_y').length) { - $$b('#ruler_y')[0].scrollTop = workarea[0].scrollTop; - } - }); - })(); - + if ($$b('#ruler_y').length) { + $$b('#ruler_y')[0].scrollTop = workarea[0].scrollTop; + } + }); $$b('#url_notice').click(function () { + /* await */ $$b.alert(this.title); }); - - $$b('#change_image_url').click(promptImgURL); - - // added these event handlers for all the push buttons so they + $$b('#change_image_url').click(promptImgURL); // added these event handlers for all the push buttons so they // behave more like buttons being pressed-in and not images + (function () { var toolnames = ['clear', 'open', 'save', 'source', 'delete', 'delete_multi', 'paste', 'clone', 'clone_multi', 'move_top', 'move_bottom']; var curClass = 'tool_button_current'; - var allTools = ''; - $$b.each(toolnames, function (i, item) { allTools += (i ? ',' : '') + '#tool_' + item; }); - $$b(allTools).mousedown(function () { $$b(this).addClass(curClass); }).bind('mousedown mouseout', function () { $$b(this).removeClass(curClass); }); - $$b('#tool_undo, #tool_redo').mousedown(function () { if (!$$b(this).hasClass('disabled')) { $$b(this).addClass(curClass); @@ -29677,42 +34230,54 @@ }).bind('mousedown mouseout', function () { $$b(this).removeClass(curClass); }); - })(); - - // switch modifier key in tooltips if mac + })(); // switch modifier key in tooltips if mac // NOTE: This code is not used yet until I can figure out how to successfully bind ctrl/meta // in Opera and Chrome + + if (isMac() && !window.opera) { var shortcutButtons = ['tool_clear', 'tool_save', 'tool_source', 'tool_undo', 'tool_redo', 'tool_clone']; var _i2 = shortcutButtons.length; + while (_i2--) { var button = document.getElementById(shortcutButtons[_i2]); + if (button) { var title = button.title; - var index = title.indexOf('Ctrl+'); button.title = [title.substr(0, index), 'Cmd+', title.substr(index + 5)].join(''); } } } + /** + * @param {external:jQuery} elem + * @todo Go back to the color boxes having white background-color and then setting + * background-image to none.png (otherwise partially transparent gradients look weird) + * @returns {undefined} + */ + - // TODO: go back to the color boxes having white background-color and then setting - // background-image to none.png (otherwise partially transparent gradients look weird) var colorPicker = function colorPicker(elem) { - var picker = elem.attr('id') === 'stroke_color' ? 'stroke' : 'fill'; - // const opacity = (picker == 'stroke' ? $('#stroke_opacity') : $('#fill_opacity')); - var title = picker === 'stroke' ? uiStrings$1.ui.pick_stroke_paint_opacity : uiStrings$1.ui.pick_fill_paint_opacity; - // let wasNone = false; // Currently unused + var picker = elem.attr('id') === 'stroke_color' ? 'stroke' : 'fill'; // const opacity = (picker == 'stroke' ? $('#stroke_opacity') : $('#fill_opacity')); + + var title = picker === 'stroke' ? uiStrings$1.ui.pick_stroke_paint_opacity : uiStrings$1.ui.pick_fill_paint_opacity; // let wasNone = false; // Currently unused + var pos = elem.offset(); var paint = paintBox[picker].paint; - $$b('#color_picker').draggable({ cancel: '.jGraduate_tabs, .jGraduate_colPick, .jGraduate_gradPick, .jPicker', containment: 'window' - }).css(curConfig.colorPickerCSS || { left: pos.left - 140, bottom: 40 }).jGraduate({ + }).css(curConfig.colorPickerCSS || { + left: pos.left - 140, + bottom: 40 + }).jGraduate({ paint: paint, - window: { pickerTitle: title }, - images: { clientPath: curConfig.jGraduatePath }, + window: { + pickerTitle: title + }, + images: { + clientPath: curConfig.jGraduatePath + }, newstop: 'inverse' }, function (p) { paint = new $$b.jGraduate.Paint(p); @@ -29724,158 +34289,183 @@ }); }; - var PaintBox = function PaintBox(container, type) { - var paintColor = void 0, - paintOpacity = void 0; - var cur = curConfig[type === 'fill' ? 'initFill' : 'initStroke']; - // set up gradients to be used for the buttons - var svgdocbox = new DOMParser().parseFromString('\n \n \n ', 'text/xml'); + var PaintBox = + /*#__PURE__*/ + function () { + function PaintBox(container, type) { + _classCallCheck(this, PaintBox); - var docElem = svgdocbox.documentElement; - docElem = $$b(container)[0].appendChild(document.importNode(docElem, true)); - docElem.setAttribute('width', 16.5); + var cur = curConfig[type === 'fill' ? 'initFill' : 'initStroke']; // set up gradients to be used for the buttons - this.rect = docElem.firstElementChild; - this.defs = docElem.getElementsByTagName('defs')[0]; - this.grad = this.defs.firstElementChild; - this.paint = new $$b.jGraduate.Paint({ solidColor: cur.color }); - this.type = type; + var svgdocbox = new DOMParser().parseFromString("\n \n \n "), 'text/xml'); + var docElem = svgdocbox.documentElement; + docElem = $$b(container)[0].appendChild(document.importNode(docElem, true)); + docElem.setAttribute('width', 16.5); + this.rect = docElem.firstElementChild; + this.defs = docElem.getElementsByTagName('defs')[0]; + this.grad = this.defs.firstElementChild; + this.paint = new $$b.jGraduate.Paint({ + solidColor: cur.color + }); + this.type = type; + } - this.setPaint = function (paint, apply) { - this.paint = paint; + _createClass(PaintBox, [{ + key: "setPaint", + value: function setPaint(paint, apply) { + this.paint = paint; + var ptype = paint.type; + var opac = paint.alpha / 100; + var fillAttr = 'none'; - var ptype = paint.type; - var opac = paint.alpha / 100; - - var fillAttr = 'none'; - switch (ptype) { - case 'solidColor': - fillAttr = paint[ptype] !== 'none' ? '#' + paint[ptype] : paint[ptype]; - break; - case 'linearGradient': - case 'radialGradient': - this.grad.remove(); - this.grad = this.defs.appendChild(paint[ptype]); - var id = this.grad.id = 'gradbox_' + this.type; - fillAttr = 'url(#' + id + ')'; - break; - } - - this.rect.setAttribute('fill', fillAttr); - this.rect.setAttribute('opacity', opac); - - if (apply) { - svgCanvas.setColor(this.type, paintColor, true); - svgCanvas.setPaintOpacity(this.type, paintOpacity, true); - } - }; - - this.update = function (apply) { - if (!selectedElement) { - return; - } - - var type = this.type; - - switch (selectedElement.tagName) { - case 'use': - case 'image': - case 'foreignObject': - // These elements don't have fill or stroke, so don't change - // the current value - return; - case 'g': - case 'a': - { - var childs = selectedElement.getElementsByTagName('*'); - - var gPaint = null; - for (var _i3 = 0, len = childs.length; _i3 < len; _i3++) { - var elem = childs[_i3]; - var p = elem.getAttribute(type); - if (_i3 === 0) { - gPaint = p; - } else if (gPaint !== p) { - gPaint = null; - break; - } - } - - if (gPaint === null) { - // No common color, don't update anything - paintColor = null; - return; - } - paintColor = gPaint; - paintOpacity = 1; + switch (ptype) { + case 'solidColor': + fillAttr = paint[ptype] !== 'none' ? '#' + paint[ptype] : paint[ptype]; break; - }default: - paintOpacity = parseFloat(selectedElement.getAttribute(type + '-opacity')); - if (isNaN(paintOpacity)) { - paintOpacity = 1.0; - } - var defColor = type === 'fill' ? 'black' : 'none'; - paintColor = selectedElement.getAttribute(type) || defColor; + case 'linearGradient': + case 'radialGradient': + { + this.grad.remove(); + this.grad = this.defs.appendChild(paint[ptype]); + var id = this.grad.id = 'gradbox_' + this.type; + fillAttr = 'url(#' + id + ')'; + break; + } + } + + this.rect.setAttribute('fill', fillAttr); + this.rect.setAttribute('opacity', opac); + + if (apply) { + svgCanvas.setColor(this.type, this._paintColor, true); + svgCanvas.setPaintOpacity(this.type, this._paintOpacity, true); + } } + }, { + key: "update", + value: function update(apply) { + if (!selectedElement) { + return; + } - if (apply) { - svgCanvas.setColor(type, paintColor, true); - svgCanvas.setPaintOpacity(type, paintOpacity, true); + var type = this.type; + + switch (selectedElement.tagName) { + case 'use': + case 'image': + case 'foreignObject': + // These elements don't have fill or stroke, so don't change + // the current value + return; + + case 'g': + case 'a': + { + var childs = selectedElement.getElementsByTagName('*'); + var gPaint = null; + + for (var _i3 = 0, len = childs.length; _i3 < len; _i3++) { + var elem = childs[_i3]; + var p = elem.getAttribute(type); + + if (_i3 === 0) { + gPaint = p; + } else if (gPaint !== p) { + gPaint = null; + break; + } + } + + if (gPaint === null) { + // No common color, don't update anything + this._paintColor = null; + return; + } + + this._paintColor = gPaint; + this._paintOpacity = 1; + break; + } + + default: + { + this._paintOpacity = parseFloat(selectedElement.getAttribute(type + '-opacity')); + + if (isNaN(this._paintOpacity)) { + this._paintOpacity = 1.0; + } + + var defColor = type === 'fill' ? 'black' : 'none'; + this._paintColor = selectedElement.getAttribute(type) || defColor; + } + } + + if (apply) { + svgCanvas.setColor(type, this._paintColor, true); + svgCanvas.setPaintOpacity(type, this._paintOpacity, true); + } + + this._paintOpacity *= 100; + var paint = getPaint(this._paintColor, this._paintOpacity, type); // update the rect inside #fill_color/#stroke_color + + this.setPaint(paint); } + }, { + key: "prep", + value: function prep() { + var ptype = this.paint.type; - paintOpacity *= 100; - - var paint = getPaint(paintColor, paintOpacity, type); - // update the rect inside #fill_color/#stroke_color - this.setPaint(paint); - }; - - this.prep = function () { - var ptype = this.paint.type; - - switch (ptype) { - case 'linearGradient': - case 'radialGradient': - var paint = new $$b.jGraduate.Paint({ copy: this.paint }); - svgCanvas.setPaint(type, paint); - break; + switch (ptype) { + case 'linearGradient': + case 'radialGradient': + { + var paint = new $$b.jGraduate.Paint({ + copy: this.paint + }); + svgCanvas.setPaint(this.type, paint); + break; + } + } } - }; - }; + }]); + + return PaintBox; + }(); paintBox.fill = new PaintBox('#fill_color', 'fill'); paintBox.stroke = new PaintBox('#stroke_color', 'stroke'); - $$b('#stroke_width').val(curConfig.initStroke.width); - $$b('#group_opacity').val(curConfig.initOpacity * 100); + $$b('#group_opacity').val(curConfig.initOpacity * 100); // Use this SVG elem to test vectorEffect support - // Use this SVG elem to test vectorEffect support var testEl = paintBox.fill.rect.cloneNode(false); testEl.setAttribute('style', 'vector-effect:non-scaling-stroke'); var supportsNonSS = testEl.style.vectorEffect === 'non-scaling-stroke'; testEl.removeAttribute('style'); - var svgdocbox = paintBox.fill.rect.ownerDocument; - // Use this to test support for blur element. Seems to work to test support in Webkit + var svgdocbox = paintBox.fill.rect.ownerDocument; // Use this to test support for blur element. Seems to work to test support in Webkit + var blurTest = svgdocbox.createElementNS(NS.SVG, 'feGaussianBlur'); + if (blurTest.stdDeviationX === undefined) { $$b('#tool_blur').hide(); } - $$b(blurTest).remove(); - // Test for zoom icon support + $$b(blurTest).remove(); // Test for zoom icon support + (function () { var pre = '-' + uaPrefix.toLowerCase() + '-zoom-'; var zoom = pre + 'in'; workarea.css('cursor', zoom); + if (workarea.css('cursor') === zoom) { zoomInIcon = zoom; zoomOutIcon = pre + 'out'; } - workarea.css('cursor', 'auto'); - })(); - // Test for embedImage support (use timeout to not interfere with page load) + workarea.css('cursor', 'auto'); + })(); // Test for embedImage support (use timeout to not interfere with page load) + + setTimeout(function () { svgCanvas.embedImage('images/logo.png', function (datauri) { if (!datauri) { @@ -29887,32 +34477,26 @@ } }); }, 1000); - $$b('#fill_color, #tool_fill .icon_label').click(function () { colorPicker($$b('#fill_color')); updateToolButtonState(); }); - $$b('#stroke_color, #tool_stroke .icon_label').click(function () { colorPicker($$b('#stroke_color')); updateToolButtonState(); }); - $$b('#group_opacityLabel').click(function () { $$b('#opacity_dropdown button').mousedown(); $$b(window).mouseup(); }); - $$b('#zoomLabel').click(function () { $$b('#zoom_dropdown button').mousedown(); $$b(window).mouseup(); }); - $$b('#tool_move_top').mousedown(function (evt) { $$b('#tools_stacking').show(); evt.preventDefault(); }); - $$b('.layer_button').mousedown(function () { $$b(this).addClass('layer_buttonpressed'); }).mouseout(function () { @@ -29920,7 +34504,6 @@ }).mouseup(function () { $$b(this).removeClass('layer_buttonpressed'); }); - $$b('.push_button').mousedown(function () { if (!$$b(this).hasClass('disabled')) { $$b(this).addClass('push_button_pressed').removeClass('push_button'); @@ -29929,72 +34512,157 @@ $$b(this).removeClass('push_button_pressed').addClass('push_button'); }).mouseup(function () { $$b(this).removeClass('push_button_pressed').addClass('push_button'); - }); + }); // ask for a layer name - // ask for a layer name - $$b('#layer_new').click(function () { - var uniqName = void 0, - i = svgCanvas.getCurrentDrawing().getNumLayers(); - do { - uniqName = uiStrings$1.layers.layer + ' ' + ++i; - } while (svgCanvas.getCurrentDrawing().hasLayer(uniqName)); + $$b('#layer_new').click( + /*#__PURE__*/ + _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee13() { + var uniqName, i, newName; + return regeneratorRuntime.wrap(function _callee13$(_context13) { + while (1) { + switch (_context13.prev = _context13.next) { + case 0: + i = svgCanvas.getCurrentDrawing().getNumLayers(); - $$b.prompt(uiStrings$1.notification.enterUniqueLayerName, uniqName, function (newName) { - if (!newName) { - return; + do { + uniqName = uiStrings$1.layers.layer + ' ' + ++i; + } while (svgCanvas.getCurrentDrawing().hasLayer(uniqName)); + + _context13.next = 4; + return $$b.prompt(uiStrings$1.notification.enterUniqueLayerName, uniqName); + + case 4: + newName = _context13.sent; + + if (newName) { + _context13.next = 7; + break; + } + + return _context13.abrupt("return"); + + case 7: + if (!svgCanvas.getCurrentDrawing().hasLayer(newName)) { + _context13.next = 10; + break; + } + + /* await */ + $$b.alert(uiStrings$1.notification.dupeLayerName); + return _context13.abrupt("return"); + + case 10: + svgCanvas.createLayer(newName); + updateContextPanel(); + populateLayers(); + + case 13: + case "end": + return _context13.stop(); + } } - if (svgCanvas.getCurrentDrawing().hasLayer(newName)) { - $$b.alert(uiStrings$1.notification.dupeLayerName); - return; - } - svgCanvas.createLayer(newName); - updateContextPanel(); - populateLayers(); - }); - }); + }, _callee13, this); + }))); + /** + * + * @returns {undefined} + */ function deleteLayer() { if (svgCanvas.deleteCurrentLayer()) { updateContextPanel(); - populateLayers(); - // This matches what SvgCanvas does + populateLayers(); // This matches what SvgCanvas does // TODO: make this behavior less brittle (svg-editor should get which // layer is selected from the canvas and then select that one in the UI) + $$b('#layerlist tr.layer').removeClass('layersel'); $$b('#layerlist tr.layer:first').addClass('layersel'); } } + /** + * + * @returns {undefined} + */ + function cloneLayer() { - var name = svgCanvas.getCurrentDrawing().getCurrentLayerName() + ' copy'; + return _cloneLayer.apply(this, arguments); + } + /** + * + * @returns {undefined} + */ - $$b.prompt(uiStrings$1.notification.enterUniqueLayerName, name, function (newName) { - if (!newName) { - return; - } - if (svgCanvas.getCurrentDrawing().hasLayer(newName)) { - $$b.alert(uiStrings$1.notification.dupeLayerName); - return; - } - svgCanvas.cloneLayer(newName); - updateContextPanel(); - populateLayers(); - }); + + function _cloneLayer() { + _cloneLayer = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee19() { + var name, newName; + return regeneratorRuntime.wrap(function _callee19$(_context19) { + while (1) { + switch (_context19.prev = _context19.next) { + case 0: + name = svgCanvas.getCurrentDrawing().getCurrentLayerName() + ' copy'; + _context19.next = 3; + return $$b.prompt(uiStrings$1.notification.enterUniqueLayerName, name); + + case 3: + newName = _context19.sent; + + if (newName) { + _context19.next = 6; + break; + } + + return _context19.abrupt("return"); + + case 6: + if (!svgCanvas.getCurrentDrawing().hasLayer(newName)) { + _context19.next = 9; + break; + } + + /* await */ + $$b.alert(uiStrings$1.notification.dupeLayerName); + return _context19.abrupt("return"); + + case 9: + svgCanvas.cloneLayer(newName); + updateContextPanel(); + populateLayers(); + + case 12: + case "end": + return _context19.stop(); + } + } + }, _callee19, this); + })); + return _cloneLayer.apply(this, arguments); } function mergeLayer() { if ($$b('#layerlist tr.layersel').index() === svgCanvas.getCurrentDrawing().getNumLayers() - 1) { return; } + svgCanvas.mergeLayer(); updateContextPanel(); populateLayers(); } + /** + * @param {Integer} pos + * @returns {undefined} + */ + function moveLayer(pos) { var total = svgCanvas.getCurrentDrawing().getNumLayers(); - var curIndex = $$b('#layerlist tr.layersel').index(); + if (curIndex > 0 || curIndex < total - 1) { curIndex += pos; svgCanvas.setCurrentLayerPosition(total - curIndex - 1); @@ -30003,92 +34671,130 @@ } $$b('#layer_delete').click(deleteLayer); - $$b('#layer_up').click(function () { moveLayer(-1); }); - $$b('#layer_down').click(function () { moveLayer(1); }); + $$b('#layer_rename').click( + /*#__PURE__*/ + _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee14() { + var oldName, newName; + return regeneratorRuntime.wrap(function _callee14$(_context14) { + while (1) { + switch (_context14.prev = _context14.next) { + case 0: + // const curIndex = $('#layerlist tr.layersel').prevAll().length; // Currently unused + oldName = $$b('#layerlist tr.layersel td.layername').text(); + _context14.next = 3; + return $$b.prompt(uiStrings$1.notification.enterNewLayerName, ''); - $$b('#layer_rename').click(function () { - // const curIndex = $('#layerlist tr.layersel').prevAll().length; // Currently unused - var oldName = $$b('#layerlist tr.layersel td.layername').text(); - $$b.prompt(uiStrings$1.notification.enterNewLayerName, '', function (newName) { - if (!newName) { - return; + case 3: + newName = _context14.sent; + + if (newName) { + _context14.next = 6; + break; + } + + return _context14.abrupt("return"); + + case 6: + if (!(oldName === newName || svgCanvas.getCurrentDrawing().hasLayer(newName))) { + _context14.next = 9; + break; + } + + /* await */ + $$b.alert(uiStrings$1.notification.layerHasThatName); + return _context14.abrupt("return"); + + case 9: + svgCanvas.renameCurrentLayer(newName); + populateLayers(); + + case 11: + case "end": + return _context14.stop(); + } } - if (oldName === newName || svgCanvas.getCurrentDrawing().hasLayer(newName)) { - $$b.alert(uiStrings$1.notification.layerHasThatName); - return; - } - - svgCanvas.renameCurrentLayer(newName); - populateLayers(); - }); - }); - + }, _callee14, this); + }))); var SIDEPANEL_MAXWIDTH = 300; var SIDEPANEL_OPENWIDTH = 150; var sidedrag = -1, sidedragging = false, allowmove = false; - /** * @param {Float} delta * @fires module:svgcanvas.SvgCanvas#event:ext-workareaResized * @returns {undefined} */ + var changeSidePanelWidth = function changeSidePanelWidth(delta) { var rulerX = $$b('#ruler_x'); $$b('#sidepanels').width('+=' + delta); $$b('#layerpanel').width('+=' + delta); - rulerX.css('right', parseInt(rulerX.css('right'), 10) + delta); - workarea.css('right', parseInt(workarea.css('right'), 10) + delta); + rulerX.css('right', parseInt(rulerX.css('right')) + delta); + workarea.css('right', parseInt(workarea.css('right')) + delta); svgCanvas.runExtensions('workareaResized'); }; + /** + * @param {Event} evt + * @returns {undefined} + */ + var resizeSidePanel = function resizeSidePanel(evt) { if (!allowmove) { return; } + if (sidedrag === -1) { return; } + sidedragging = true; var deltaX = sidedrag - evt.pageX; var sideWidth = $$b('#sidepanels').width(); + if (sideWidth + deltaX > SIDEPANEL_MAXWIDTH) { - deltaX = SIDEPANEL_MAXWIDTH - sideWidth; - sideWidth = SIDEPANEL_MAXWIDTH; + deltaX = SIDEPANEL_MAXWIDTH - sideWidth; // sideWidth = SIDEPANEL_MAXWIDTH; } else if (sideWidth + deltaX < 2) { - deltaX = 2 - sideWidth; - sideWidth = 2; + deltaX = 2 - sideWidth; // sideWidth = 2; } + if (deltaX === 0) { return; } + sidedrag -= deltaX; changeSidePanelWidth(deltaX); }; - /** - * If width is non-zero, then fully close it, otherwise fully open it + * If width is non-zero, then fully close it; otherwise fully open it. * @param {boolean} close Forces the side panel closed * @returns {undefined} */ + + var toggleSidePanel = function toggleSidePanel(close) { + var dpr = window.devicePixelRatio || 1; var w = $$b('#sidepanels').width(); - var deltaX = (w > 2 || close ? 2 : SIDEPANEL_OPENWIDTH) - w; + var isOpened = (dpr < 1 ? w : w / dpr) > 2; + var zoomAdjustedSidepanelWidth = (dpr < 1 ? 1 : dpr) * SIDEPANEL_OPENWIDTH; + var deltaX = (isOpened || close ? 0 : zoomAdjustedSidepanelWidth) - w; changeSidePanelWidth(deltaX); }; $$b('#sidepanel_handle').mousedown(function (evt) { sidedrag = evt.pageX; $$b(window).mousemove(resizeSidePanel); - allowmove = false; - // Silly hack for Chrome, which always runs mousemove right after mousedown + allowmove = false; // Silly hack for Chrome, which always runs mousemove right after mousedown + setTimeout(function () { allowmove = true; }, 20); @@ -30096,19 +34802,16 @@ if (!sidedragging) { toggleSidePanel(); } + sidedrag = -1; sidedragging = false; }); - $$b(window).mouseup(function () { sidedrag = -1; sidedragging = false; $$b('#svg_editor').unbind('mousemove', resizeSidePanel); }); - - populateLayers(); - - // function changeResolution (x,y) { + populateLayers(); // function changeResolution (x,y) { // const {zoom} = svgCanvas.getResolution(); // setResolution(x * zoom, y * zoom); // } @@ -30119,11 +34822,15 @@ }; $$b(window).bind('load resize', centerCanvas); + /** + * @implements {module:jQuerySpinButton.StepCallback} + */ function stepFontSize(elem, step) { var origVal = Number(elem.value); var sugVal = origVal + step; var increasing = sugVal >= origVal; + if (step === 0) { return origVal; } @@ -30132,23 +34839,34 @@ if (increasing) { return Math.round(origVal * 1.1); } + return Math.round(origVal / 1.1); } + if (origVal <= 1) { if (increasing) { return origVal * 2; } + return origVal / 2; } + return sugVal; } + /** + * @implements {module:jQuerySpinButton.StepCallback} + */ + function stepZoom(elem, step) { var origVal = Number(elem.value); + if (origVal === 0) { return 100; } + var sugVal = origVal + step; + if (step === 0) { return origVal; } @@ -30156,13 +34874,13 @@ if (origVal >= 100) { return sugVal; } + if (sugVal >= origVal) { return origVal * 2; } - return origVal / 2; - } - // function setResolution (w, h, center) { + return origVal / 2; + } // function setResolution (w, h, center) { // updateCanvas(); // // w -= 0; h -= 0; // // $('#svgcanvas').css({width: w, height: h}); @@ -30178,8 +34896,10 @@ // // } // } + $$b('#resolution').change(function () { var wh = $$b('#canvas_width,#canvas_height'); + if (!this.selectedIndex) { if ($$b('#canvas_width').val() === 'fit') { wh.removeAttr('disabled').val(100); @@ -30192,15 +34912,15 @@ $$b('#canvas_height').val(dims[1]); wh.removeAttr('disabled'); } - }); + }); // Prevent browser from erroneously repopulating fields - // Prevent browser from erroneously repopulating fields $$b('input,select').attr('autocomplete', 'off'); - + var dialogSelectors = ['#tool_source_cancel', '#tool_docprops_cancel', '#tool_prefs_cancel', '.overlay']; /** * Associate all button actions as well as non-button keyboard shortcuts * @namespace {PlainObject} module:SVGEditor~Actions */ + var Actions = function () { /** * @typedef {PlainObject} module:SVGEditor.ToolButton @@ -30213,218 +34933,527 @@ * @property {string} [icon] The button ID * @property {boolean} isDefault For flyout holders */ + /** * * @name module:SVGEditor~ToolButtons * @type {module:SVGEditor.ToolButton[]} */ - var toolButtons = [{ sel: '#tool_select', fn: clickSelect, evt: 'click', key: ['V', true] }, { sel: '#tool_fhpath', fn: clickFHPath, evt: 'click', key: ['Q', true] }, { sel: '#tool_line', fn: clickLine, evt: 'click', key: ['L', true], parent: '#tools_line', prepend: true }, { sel: '#tool_rect', fn: clickRect, evt: 'mouseup', - key: ['R', true], parent: '#tools_rect', icon: 'rect' }, { sel: '#tool_square', fn: clickSquare, evt: 'mouseup', - parent: '#tools_rect', icon: 'square' }, { sel: '#tool_fhrect', fn: clickFHRect, evt: 'mouseup', - parent: '#tools_rect', icon: 'fh_rect' }, { sel: '#tool_ellipse', fn: clickEllipse, evt: 'mouseup', - key: ['E', true], parent: '#tools_ellipse', icon: 'ellipse' }, { sel: '#tool_circle', fn: clickCircle, evt: 'mouseup', - parent: '#tools_ellipse', icon: 'circle' }, { sel: '#tool_fhellipse', fn: clickFHEllipse, evt: 'mouseup', - parent: '#tools_ellipse', icon: 'fh_ellipse' }, { sel: '#tool_path', fn: clickPath, evt: 'click', key: ['P', true] }, { sel: '#tool_text', fn: clickText, evt: 'click', key: ['T', true] }, { sel: '#tool_image', fn: clickImage, evt: 'mouseup' }, { sel: '#tool_zoom', fn: clickZoom, evt: 'mouseup', key: ['Z', true] }, { sel: '#tool_clear', fn: clickClear, evt: 'mouseup', key: ['N', true] }, { sel: '#tool_save', fn: function fn() { + var toolButtons = [{ + sel: '#tool_select', + fn: clickSelect, + evt: 'click', + key: ['V', true] + }, { + sel: '#tool_fhpath', + fn: clickFHPath, + evt: 'click', + key: ['Q', true] + }, { + sel: '#tool_line', + fn: clickLine, + evt: 'click', + key: ['L', true], + parent: '#tools_line', + prepend: true + }, { + sel: '#tool_rect', + fn: clickRect, + evt: 'mouseup', + key: ['R', true], + parent: '#tools_rect', + icon: 'rect' + }, { + sel: '#tool_square', + fn: clickSquare, + evt: 'mouseup', + parent: '#tools_rect', + icon: 'square' + }, { + sel: '#tool_fhrect', + fn: clickFHRect, + evt: 'mouseup', + parent: '#tools_rect', + icon: 'fh_rect' + }, { + sel: '#tool_ellipse', + fn: clickEllipse, + evt: 'mouseup', + key: ['E', true], + parent: '#tools_ellipse', + icon: 'ellipse' + }, { + sel: '#tool_circle', + fn: clickCircle, + evt: 'mouseup', + parent: '#tools_ellipse', + icon: 'circle' + }, { + sel: '#tool_fhellipse', + fn: clickFHEllipse, + evt: 'mouseup', + parent: '#tools_ellipse', + icon: 'fh_ellipse' + }, { + sel: '#tool_path', + fn: clickPath, + evt: 'click', + key: ['P', true] + }, { + sel: '#tool_text', + fn: clickText, + evt: 'click', + key: ['T', true] + }, { + sel: '#tool_image', + fn: clickImage, + evt: 'mouseup' + }, { + sel: '#tool_zoom', + fn: clickZoom, + evt: 'mouseup', + key: ['Z', true] + }, { + sel: '#tool_clear', + fn: clickClear, + evt: 'mouseup', + key: ['N', true] + }, { + sel: '#tool_save', + fn: function fn() { if (editingsource) { saveSourceEditor(); } else { clickSave(); } }, - evt: 'mouseup', key: ['S', true] }, { sel: '#tool_export', fn: clickExport, evt: 'mouseup' }, { sel: '#tool_open', fn: clickOpen, evt: 'mouseup', key: ['O', true] }, { sel: '#tool_import', fn: clickImport, evt: 'mouseup' }, { sel: '#tool_source', fn: showSourceEditor, evt: 'click', key: ['U', true] }, { sel: '#tool_wireframe', fn: clickWireframe, evt: 'click', key: ['F', true] }, { sel: '#tool_source_cancel,.overlay,#tool_docprops_cancel,#tool_prefs_cancel', - fn: cancelOverlays, evt: 'click', key: ['esc', false, false], hidekey: true }, { sel: '#tool_source_save', fn: saveSourceEditor, evt: 'click' }, { sel: '#tool_docprops_save', fn: saveDocProperties, evt: 'click' }, { sel: '#tool_docprops', fn: showDocProperties, evt: 'mouseup' }, { sel: '#tool_prefs_save', fn: savePreferences, evt: 'click' }, { sel: '#tool_prefs_option', fn: function fn() { - showPreferences();return false; + evt: 'mouseup', + key: ['S', true] + }, { + sel: '#tool_export', + fn: clickExport, + evt: 'mouseup' + }, { + sel: '#tool_open', + fn: clickOpen, + evt: 'mouseup', + key: ['O', true] + }, { + sel: '#tool_import', + fn: clickImport, + evt: 'mouseup' + }, { + sel: '#tool_source', + fn: showSourceEditor, + evt: 'click', + key: ['U', true] + }, { + sel: '#tool_wireframe', + fn: clickWireframe, + evt: 'click', + key: ['F', true] + }, { + key: ['esc', false, false], + fn: function fn() { + if (dialogSelectors.every(function (sel) { + return $$b(sel + ':hidden').length; + })) { + svgCanvas.clearSelection(); + } }, - evt: 'mouseup' }, { sel: '#tool_delete,#tool_delete_multi', fn: deleteSelected, - evt: 'click', key: ['del/backspace', true] }, { sel: '#tool_reorient', fn: reorientPath, evt: 'click' }, { sel: '#tool_node_link', fn: linkControlPoints, evt: 'click' }, { sel: '#tool_node_clone', fn: clonePathNode, evt: 'click' }, { sel: '#tool_node_delete', fn: deletePathNode, evt: 'click' }, { sel: '#tool_openclose_path', fn: opencloseSubPath, evt: 'click' }, { sel: '#tool_add_subpath', fn: addSubPath, evt: 'click' }, { sel: '#tool_move_top', fn: moveToTopSelected, evt: 'click', key: 'ctrl+shift+]' }, { sel: '#tool_move_bottom', fn: moveToBottomSelected, evt: 'click', key: 'ctrl+shift+[' }, { sel: '#tool_topath', fn: convertToPath$$1, evt: 'click' }, { sel: '#tool_make_link,#tool_make_link_multi', fn: makeHyperlink, evt: 'click' }, { sel: '#tool_undo', fn: clickUndo, evt: 'click' }, { sel: '#tool_redo', fn: clickRedo, evt: 'click' }, { sel: '#tool_clone,#tool_clone_multi', fn: clickClone, evt: 'click', key: ['D', true] }, { sel: '#tool_group_elements', fn: clickGroup, evt: 'click', key: ['G', true] }, { sel: '#tool_ungroup', fn: clickGroup, evt: 'click' }, { sel: '#tool_unlink_use', fn: clickGroup, evt: 'click' }, { sel: '[id^=tool_align]', fn: clickAlign, evt: 'click' }, - // these two lines are required to make Opera work properly with the flyout mechanism + hidekey: true + }, { + sel: dialogSelectors.join(','), + fn: cancelOverlays, + evt: 'click', + key: ['esc', false, false], + hidekey: true + }, { + sel: '#tool_source_save', + fn: saveSourceEditor, + evt: 'click' + }, { + sel: '#tool_docprops_save', + fn: saveDocProperties, + evt: 'click' + }, { + sel: '#tool_docprops', + fn: showDocProperties, + evt: 'mouseup' + }, { + sel: '#tool_prefs_save', + fn: savePreferences, + evt: 'click' + }, { + sel: '#tool_prefs_option', + fn: function fn() { + showPreferences(); + return false; + }, + evt: 'mouseup' + }, { + sel: '#tool_delete,#tool_delete_multi', + fn: deleteSelected, + evt: 'click', + key: ['del/backspace', true] + }, { + sel: '#tool_reorient', + fn: reorientPath, + evt: 'click' + }, { + sel: '#tool_node_link', + fn: linkControlPoints, + evt: 'click' + }, { + sel: '#tool_node_clone', + fn: clonePathNode, + evt: 'click' + }, { + sel: '#tool_node_delete', + fn: deletePathNode, + evt: 'click' + }, { + sel: '#tool_openclose_path', + fn: opencloseSubPath, + evt: 'click' + }, { + sel: '#tool_add_subpath', + fn: addSubPath, + evt: 'click' + }, { + sel: '#tool_move_top', + fn: moveToTopSelected, + evt: 'click', + key: 'ctrl+shift+]' + }, { + sel: '#tool_move_bottom', + fn: moveToBottomSelected, + evt: 'click', + key: 'ctrl+shift+[' + }, { + sel: '#tool_topath', + fn: convertToPath, + evt: 'click' + }, { + sel: '#tool_make_link,#tool_make_link_multi', + fn: makeHyperlink, + evt: 'click' + }, { + sel: '#tool_undo', + fn: clickUndo, + evt: 'click' + }, { + sel: '#tool_redo', + fn: clickRedo, + evt: 'click' + }, { + sel: '#tool_clone,#tool_clone_multi', + fn: clickClone, + evt: 'click', + key: ['D', true] + }, { + sel: '#tool_group_elements', + fn: clickGroup, + evt: 'click', + key: ['G', true] + }, { + sel: '#tool_ungroup', + fn: clickGroup, + evt: 'click' + }, { + sel: '#tool_unlink_use', + fn: clickGroup, + evt: 'click' + }, { + sel: '[id^=tool_align]', + fn: clickAlign, + evt: 'click' + }, // these two lines are required to make Opera work properly with the flyout mechanism // {sel: '#tools_rect_show', fn: clickRect, evt: 'click'}, // {sel: '#tools_ellipse_show', fn: clickEllipse, evt: 'click'}, - { sel: '#tool_bold', fn: clickBold, evt: 'mousedown' }, { sel: '#tool_italic', fn: clickItalic, evt: 'mousedown' }, { sel: '#sidepanel_handle', fn: toggleSidePanel, key: ['X'] }, { sel: '#copy_save_done', fn: cancelOverlays, evt: 'click' }, - - // Shortcuts not associated with buttons - - { key: 'ctrl+left', fn: function fn() { + { + sel: '#tool_bold', + fn: clickBold, + evt: 'mousedown' + }, { + sel: '#tool_italic', + fn: clickItalic, + evt: 'mousedown' + }, { + sel: '#sidepanel_handle', + fn: toggleSidePanel, + key: ['X'] + }, { + sel: '#copy_save_done', + fn: cancelOverlays, + evt: 'click' + }, // Shortcuts not associated with buttons + { + key: 'ctrl+left', + fn: function fn() { rotateSelected(0, 1); } - }, { key: 'ctrl+right', fn: function fn() { + }, { + key: 'ctrl+right', + fn: function fn() { rotateSelected(1, 1); } - }, { key: 'ctrl+shift+left', fn: function fn() { + }, { + key: 'ctrl+shift+left', + fn: function fn() { rotateSelected(0, 5); } - }, { key: 'ctrl+shift+right', fn: function fn() { + }, { + key: 'ctrl+shift+right', + fn: function fn() { rotateSelected(1, 5); } - }, { key: 'shift+O', fn: selectPrev }, { key: 'shift+P', fn: selectNext }, { key: [modKey + 'up', true], fn: function fn() { + }, { + key: 'shift+O', + fn: selectPrev + }, { + key: 'shift+P', + fn: selectNext + }, { + key: [modKey + 'up', true], + fn: function fn() { zoomImage(2); } - }, { key: [modKey + 'down', true], fn: function fn() { + }, { + key: [modKey + 'down', true], + fn: function fn() { zoomImage(0.5); } - }, { key: [modKey + ']', true], fn: function fn() { + }, { + key: [modKey + ']', true], + fn: function fn() { moveUpDownSelected('Up'); } - }, { key: [modKey + '[', true], fn: function fn() { + }, { + key: [modKey + '[', true], + fn: function fn() { moveUpDownSelected('Down'); } - }, { key: ['up', true], fn: function fn() { + }, { + key: ['up', true], + fn: function fn() { moveSelected(0, -1); } - }, { key: ['down', true], fn: function fn() { + }, { + key: ['down', true], + fn: function fn() { moveSelected(0, 1); } - }, { key: ['left', true], fn: function fn() { + }, { + key: ['left', true], + fn: function fn() { moveSelected(-1, 0); } - }, { key: ['right', true], fn: function fn() { + }, { + key: ['right', true], + fn: function fn() { moveSelected(1, 0); } - }, { key: 'shift+up', fn: function fn() { + }, { + key: 'shift+up', + fn: function fn() { moveSelected(0, -10); } - }, { key: 'shift+down', fn: function fn() { + }, { + key: 'shift+down', + fn: function fn() { moveSelected(0, 10); } - }, { key: 'shift+left', fn: function fn() { + }, { + key: 'shift+left', + fn: function fn() { moveSelected(-10, 0); } - }, { key: 'shift+right', fn: function fn() { + }, { + key: 'shift+right', + fn: function fn() { moveSelected(10, 0); } - }, { key: ['alt+up', true], fn: function fn() { + }, { + key: ['alt+up', true], + fn: function fn() { svgCanvas.cloneSelectedElements(0, -1); } - }, { key: ['alt+down', true], fn: function fn() { + }, { + key: ['alt+down', true], + fn: function fn() { svgCanvas.cloneSelectedElements(0, 1); } - }, { key: ['alt+left', true], fn: function fn() { + }, { + key: ['alt+left', true], + fn: function fn() { svgCanvas.cloneSelectedElements(-1, 0); } - }, { key: ['alt+right', true], fn: function fn() { + }, { + key: ['alt+right', true], + fn: function fn() { svgCanvas.cloneSelectedElements(1, 0); } - }, { key: ['alt+shift+up', true], fn: function fn() { + }, { + key: ['alt+shift+up', true], + fn: function fn() { svgCanvas.cloneSelectedElements(0, -10); } - }, { key: ['alt+shift+down', true], fn: function fn() { + }, { + key: ['alt+shift+down', true], + fn: function fn() { svgCanvas.cloneSelectedElements(0, 10); } - }, { key: ['alt+shift+left', true], fn: function fn() { + }, { + key: ['alt+shift+left', true], + fn: function fn() { svgCanvas.cloneSelectedElements(-10, 0); } - }, { key: ['alt+shift+right', true], fn: function fn() { + }, { + key: ['alt+shift+right', true], + fn: function fn() { svgCanvas.cloneSelectedElements(10, 0); } - }, { key: 'A', fn: function fn() { + }, { + key: 'a', + fn: function fn() { svgCanvas.selectAllInCurrentLayer(); } - }, + }, { + key: modKey + 'a', + fn: function fn() { + svgCanvas.selectAllInCurrentLayer(); + } + }, // Standard shortcuts + { + key: modKey + 'z', + fn: clickUndo + }, { + key: modKey + 'shift+z', + fn: clickRedo + }, { + key: modKey + 'y', + fn: clickRedo + }, { + key: modKey + 'x', + fn: cutSelected + }, { + key: modKey + 'c', + fn: copySelected + }, { + key: modKey + 'v', + fn: pasteInCenter + }]; // Tooltips not directly associated with a single function - // Standard shortcuts - { key: modKey + 'z', fn: clickUndo }, { key: modKey + 'shift+z', fn: clickRedo }, { key: modKey + 'y', fn: clickRedo }, { key: modKey + 'x', fn: cutSelected }, { key: modKey + 'c', fn: copySelected }, { key: modKey + 'v', fn: pasteInCenter }]; - - // Tooltips not directly associated with a single function var keyAssocs = { '4/Shift+4': '#tools_rect_show', '5/Shift+5': '#tools_ellipse_show' }; - return { /** @lends module:SVGEditor~Actions */ + /** * @returns {undefined} */ setAll: function setAll() { var flyouts = {}; - $$b.each(toolButtons, function (i, opts) { // Bind function to button - var btn = void 0; + var btn; + if (opts.sel) { btn = $$b(opts.sel); + if (!btn.length) { return true; } // Skip if markup does not exist + + if (opts.evt) { + // `touch.js` changes `touchstart` to `mousedown`, + // so we must map tool button click events as well if (isTouch() && opts.evt === 'click') { opts.evt = 'mousedown'; } - btn[opts.evt](opts.fn); - } - // Add to parent flyout menu, if able to be displayed + btn[opts.evt](opts.fn); + } // Add to parent flyout menu, if able to be displayed + + if (opts.parent && $$b(opts.parent + '_show').length) { var fH = $$b(opts.parent); + if (!fH.length) { fH = makeFlyoutHolder(opts.parent.substr(1)); } + if (opts.prepend) { btn[0].style.margin = 'initial'; } + fH[opts.prepend ? 'prepend' : 'append'](btn); if (!Array.isArray(flyouts[opts.parent])) { flyouts[opts.parent] = []; } + flyouts[opts.parent].push(opts); } - } + } // Bind function to shortcut key + - // Bind function to shortcut key if (opts.key) { // Set shortcut based on options - var keyval = void 0, - - // disInInp = true, + var keyval, + // disInInp = true, pd = false; + if (Array.isArray(opts.key)) { keyval = opts.key[0]; + if (opts.key.length > 1) { pd = opts.key[1]; - } - // if (opts.key.length > 2) { disInInp = opts.key[2]; } + } // if (opts.key.length > 2) { disInInp = opts.key[2]; } + } else { keyval = opts.key; } - keyval += ''; + keyval = String(keyval); var fn = opts.fn; - - $$b.each(keyval.split('/'), function (i, key) { + $$b.each(keyval.split('/'), function (j, key) { $$b(document).bind('keydown', key, function (e) { fn(); + if (pd) { e.preventDefault(); - } - // Prevent default on ALL keys? + } // Prevent default on ALL keys? + + return false; }); - }); + }); // Put shortcut in title - // Put shortcut in title if (opts.sel && !opts.hidekey && btn.attr('title')) { var newTitle = btn.attr('title').split('[')[0] + ' (' + keyval + ')'; - keyAssocs[keyval] = opts.sel; - // Disregard for menu items + keyAssocs[keyval] = opts.sel; // Disregard for menu items + if (!btn.parents('#main_menu').length) { btn.attr('title', newTitle); } } } - }); - // Setup flyouts - setupFlyouts(flyouts); - - // Misc additional actions + return true; + }); // Setup flyouts + setupFlyouts(flyouts); // Misc additional actions // Make 'return' keypress trigger the change event + $$b('.attr_changer, #image_url').bind('keydown', 'return', function (evt) { $$b(this).change(); evt.preventDefault(); }); - $$b(window).bind('keydown', 'tab', function (e) { if (uiContext === 'canvas') { e.preventDefault(); @@ -30436,7 +35465,6 @@ selectPrev(); } }); - $$b('#tool_zoom').dblclick(dblclickZoom); }, @@ -30446,25 +35474,29 @@ setTitles: function setTitles() { $$b.each(keyAssocs, function (keyval, sel) { var menu = $$b(sel).parents('#main_menu').length; - $$b(sel).each(function () { - var t = void 0; + var t; + if (menu) { t = $$b(this).text().split(' [')[0]; } else { t = this.title.split(' [')[0]; } - var keyStr = ''; - // Shift+Up + + var keyStr = ''; // Shift+Up + $$b.each(keyval.split('/'), function (i, key) { var modBits = key.split('+'); var mod = ''; + if (modBits.length > 1) { mod = modBits[0] + '+'; key = modBits[1]; } + keyStr += (i ? '/' : '') + mod + (uiStrings$1['key_' + key] || key); }); + if (menu) { this.lastChild.textContent = t + ' [' + keyStr + ']'; } else { @@ -30484,15 +35516,16 @@ }); } }; - }(); + }(); // Select given tool + - // Select given tool editor.ready(function () { - var tool = void 0; + var tool; var itool = curConfig.initTool, container = $$b('#tools_left, #svg_editor .tools_flyout'), preTool = container.find('#tool_' + itool), regTool = container.find('#' + itool); + if (preTool.length) { tool = preTool; } else if (regTool.length) { @@ -30500,6 +35533,7 @@ } else { tool = $$b('#tool_select'); } + tool.click().mouseup(); if (curConfig.wireframe) { @@ -30510,7 +35544,7 @@ toggleSidePanel(); } - $$b('#rulers').toggle(!!curConfig.showRulers); + $$b('#rulers').toggle(Boolean(curConfig.showRulers)); if (curConfig.showRulers) { $$b('#show_rulers')[0].checked = true; @@ -30531,19 +35565,57 @@ if (curConfig.gridColor) { $$b('#grid_color').val(curConfig.gridColor); } + }); // init SpinButtons + + $$b('#rect_rx').SpinButton({ + min: 0, + max: 1000, + stateObj: stateObj, + callback: changeRectRadius }); + $$b('#stroke_width').SpinButton({ + min: 0, + max: 99, + smallStep: 0.1, + stateObj: stateObj, + callback: changeStrokeWidth + }); + $$b('#angle').SpinButton({ + min: -180, + max: 180, + step: 5, + stateObj: stateObj, + callback: changeRotationAngle + }); + $$b('#font_size').SpinButton({ + min: 0.001, + stepfunc: stepFontSize, + stateObj: stateObj, + callback: changeFontSize + }); + $$b('#group_opacity').SpinButton({ + min: 0, + max: 100, + step: 5, + stateObj: stateObj, + callback: changeOpacity + }); + $$b('#blur').SpinButton({ + min: 0, + max: 10, + step: 0.1, + stateObj: stateObj, + callback: changeBlur + }); + $$b('#zoom').SpinButton({ + min: 0.001, + max: 10000, + step: 50, + stepfunc: stepZoom, + stateObj: stateObj, + callback: changeZoom // Set default zoom - // init SpinButtons - $$b('#rect_rx').SpinButton({ min: 0, max: 1000, stateObj: stateObj, callback: changeRectRadius }); - $$b('#stroke_width').SpinButton({ min: 0, max: 99, smallStep: 0.1, stateObj: stateObj, callback: changeStrokeWidth }); - $$b('#angle').SpinButton({ min: -180, max: 180, step: 5, stateObj: stateObj, callback: changeRotationAngle }); - $$b('#font_size').SpinButton({ min: 0.001, stepfunc: stepFontSize, stateObj: stateObj, callback: changeFontSize }); - $$b('#group_opacity').SpinButton({ min: 0, max: 100, step: 5, stateObj: stateObj, callback: changeOpacity }); - $$b('#blur').SpinButton({ min: 0, max: 10, step: 0.1, stateObj: stateObj, callback: changeBlur }); - $$b('#zoom').SpinButton({ min: 0.001, max: 10000, step: 50, stepfunc: stepZoom, stateObj: stateObj, callback: changeZoom }) - // Set default zoom - .val(svgCanvas.getZoom() * 100); - + }).val(svgCanvas.getZoom() * 100); $$b('#workarea').contextMenu({ menu: 'cmenu_canvas', inSpeed: 0 @@ -30552,56 +35624,79 @@ case 'delete': deleteSelected(); break; + case 'cut': cutSelected(); break; + case 'copy': copySelected(); break; + case 'paste': svgCanvas.pasteElements(); break; + case 'paste_in_place': svgCanvas.pasteElements('in_place'); break; + case 'group': case 'group_elements': svgCanvas.groupSelectedElements(); break; + case 'ungroup': svgCanvas.ungroupSelectedElement(); break; + case 'move_front': moveToTopSelected(); break; + case 'move_up': moveUpDownSelected('Up'); break; + case 'move_down': moveUpDownSelected('Down'); break; + case 'move_back': moveToBottomSelected(); break; + default: if (hasCustomHandler(action)) { getCustomHandler(action).call(); } + break; } }); + /** + * Implements {@see module:jQueryContextMenu.jQueryContextMenuListener} + * @param {"dupe"|"delete"|"merge_down"|"merge_all"} action + * @param {external:jQuery} el + * @param {{x: Float, y: Float, docX: Float, docY: Float}} pos + * @returns {undefined} + */ var lmenuFunc = function lmenuFunc(action, el, pos) { switch (action) { case 'dupe': + /* await */ cloneLayer(); break; + case 'delete': deleteLayer(); break; + case 'merge_down': mergeLayer(); break; + case 'merge_all': svgCanvas.mergeAllLayers(); updateContextPanel(); @@ -30614,29 +35709,31 @@ menu: 'cmenu_layers', inSpeed: 0 }, lmenuFunc); - $$b('#layer_moreopts').contextMenu({ menu: 'cmenu_layers', inSpeed: 0, allowLeft: true }, lmenuFunc); - $$b('.contextMenu li').mousedown(function (ev) { ev.preventDefault(); }); - $$b('#cmenu_canvas li').disableContextMenu(); canvMenu.enableContextMenuItems('#delete,#cut,#copy'); + /** + * @returns {undefined} + */ function enableOrDisableClipboard() { - var svgeditClipboard = void 0; + var svgeditClipboard; + try { svgeditClipboard = localStorage.getItem('svgedit_clipboard'); } catch (err) {} + canvMenu[(svgeditClipboard ? 'en' : 'dis') + 'ableContextMenuItems']('#paste,#paste_in_place'); } - enableOrDisableClipboard(); + enableOrDisableClipboard(); window.addEventListener('storage', function (e) { if (e.key !== 'svgedit_clipboard') { return; @@ -30644,69 +35741,89 @@ enableOrDisableClipboard(); }); - window.addEventListener('beforeunload', function (e) { // Suppress warning if page is empty if (undoMgr.getUndoStackSize() === 0) { editor.showSaveWarning = false; - } + } // showSaveWarning is set to 'false' when the page is saved. + - // showSaveWarning is set to 'false' when the page is saved. if (!curConfig.no_save_warning && editor.showSaveWarning) { // Browser already asks question about closing the page e.returnValue = uiStrings$1.notification.unsavedChanges; // Firefox needs this when beforeunload set by addEventListener (even though message is not used) + return uiStrings$1.notification.unsavedChanges; } - }, false); + return true; + }); /** - * Expose the uiStrings + * Expose the `uiStrings`. * @function module:SVGEditor.canvas.getUIStrings * @returns {module:SVGEditor.uiStrings} */ + editor.canvas.getUIStrings = function () { return uiStrings$1; }; + /** + * @returns {Promise} Resolves to boolean indicating `true` if there were no changes + * and `false` after the user confirms. + */ - /** - * @callback module:SVGEditor.OpenPrepCallback - * @param {boolean} noChanges - * @returns {undefined} - */ - /** - * @param {module:SVGEditor.OpenPrepCallback} func Confirmation dialog callback - * @returns {undefined} - */ - editor.openPrep = function (func) { + + editor.openPrep = function () { $$b('#main_menu').hide(); + if (undoMgr.getUndoStackSize() === 0) { - func(true); - } else { - $$b.confirm(uiStrings$1.notification.QwantToOpen, func); + return true; } + + return $$b.confirm(uiStrings$1.notification.QwantToOpen); }; + /** + * + * @param {Event} e + * @returns {undefined} + */ + function onDragEnter(e) { e.stopPropagation(); - e.preventDefault(); - // and indicator should be displayed here, such as "drop files here" + e.preventDefault(); // and indicator should be displayed here, such as "drop files here" } + /** + * + * @param {Event} e + * @returns {undefined} + */ + function onDragOver(e) { e.stopPropagation(); e.preventDefault(); } + /** + * + * @param {Event} e + * @returns {undefined} + */ + function onDragLeave(e) { e.stopPropagation(); - e.preventDefault(); - // hypothetical indicator should be removed here - } - // Use HTML5 File API: http://www.w3.org/TR/FileAPI/ + e.preventDefault(); // hypothetical indicator should be removed here + } // Use HTML5 File API: http://www.w3.org/TR/FileAPI/ // if browser has HTML5 File API support, then we will show the open menu item // and provide a file input to click. When that change event fires, it will // get the text contents of the file and send it to the canvas + + if (window.FileReader) { + /** + * @param {Event} e + * @returns {undefined} + */ var importImage = function importImage(e) { $$b.process_cancel(uiStrings$1.notification.loadingImage); e.stopPropagation(); @@ -30714,6 +35831,7 @@ $$b('#workarea').removeAttr('style'); $$b('#main_menu').hide(); var file = e.type === 'drop' ? e.dataTransfer.files[0] : this.files[0]; + if (!file) { $$b('#dialog_box').hide(); return; @@ -30721,178 +35839,293 @@ /* if (file.type === 'application/pdf') { // Todo: Handle PDF imports } else */ - if (file.type.includes('image')) { - // Detected an image - // svg handling - var reader = void 0; - if (file.type.includes('svg')) { - reader = new FileReader(); - reader.onloadend = function (e) { - var newElement = svgCanvas.importSvgString(e.target.result, true); - svgCanvas.ungroupSelectedElement(); - svgCanvas.ungroupSelectedElement(); - svgCanvas.groupSelectedElements(); + + + if (!file.type.includes('image')) { + return; + } // Detected an image + // svg handling + + + var reader; + + if (file.type.includes('svg')) { + reader = new FileReader(); + + reader.onloadend = function (ev) { + var newElement = svgCanvas.importSvgString(ev.target.result, true); + svgCanvas.ungroupSelectedElement(); + svgCanvas.ungroupSelectedElement(); + svgCanvas.groupSelectedElements(); + svgCanvas.alignSelectedElements('m', 'page'); + svgCanvas.alignSelectedElements('c', 'page'); // highlight imported element, otherwise we get strange empty selectbox + + svgCanvas.selectOnly([newElement]); + $$b('#dialog_box').hide(); + }; + + reader.readAsText(file); + } else { + // bitmap handling + reader = new FileReader(); + + reader.onloadend = function (_ref27) { + var result = _ref27.target.result; + + /** + * Insert the new image until we know its dimensions + * @param {Float} width + * @param {Float} height + * @returns {undefined} + */ + var insertNewImage = function insertNewImage(width, height) { + var newImage = svgCanvas.addSVGElementFromJson({ + element: 'image', + attr: { + x: 0, + y: 0, + width: width, + height: height, + id: svgCanvas.getNextId(), + style: 'pointer-events:inherit' + } + }); + svgCanvas.setHref(newImage, result); + svgCanvas.selectOnly([newImage]); svgCanvas.alignSelectedElements('m', 'page'); svgCanvas.alignSelectedElements('c', 'page'); - // highlight imported element, otherwise we get strange empty selectbox - svgCanvas.selectOnly([newElement]); + updateContextPanel(); $$b('#dialog_box').hide(); - }; - reader.readAsText(file); - } else { - // bitmap handling - reader = new FileReader(); - reader.onloadend = function (_ref16) { - var result = _ref16.target.result; + }; // create dummy img so we know the default dimensions - // let's insert the new image until we know its dimensions - var insertNewImage = function insertNewImage(width, height) { - var newImage = svgCanvas.addSVGElementFromJson({ - element: 'image', - attr: { - x: 0, - y: 0, - width: width, - height: height, - id: svgCanvas.getNextId(), - style: 'pointer-events:inherit' - } - }); - svgCanvas.setHref(newImage, result); - svgCanvas.selectOnly([newImage]); - svgCanvas.alignSelectedElements('m', 'page'); - svgCanvas.alignSelectedElements('c', 'page'); - updateContextPanel(); - $$b('#dialog_box').hide(); - }; - // create dummy img so we know the default dimensions - var imgWidth = 100; - var imgHeight = 100; - var img = new Image(); - img.style.opacity = 0; - img.onload = function () { - imgWidth = img.offsetWidth || img.naturalWidth || img.width; - imgHeight = img.offsetHeight || img.naturalHeight || img.height; - insertNewImage(imgWidth, imgHeight); - }; - img.src = result; - }; - reader.readAsDataURL(file); - } + + var imgWidth = 100; + var imgHeight = 100; + var img = new Image(); + img.style.opacity = 0; + img.addEventListener('load', function () { + imgWidth = img.offsetWidth || img.naturalWidth || img.width; + imgHeight = img.offsetHeight || img.naturalHeight || img.height; + insertNewImage(imgWidth, imgHeight); + }); + img.src = result; + }; + + reader.readAsDataURL(file); } }; - workarea[0].addEventListener('dragenter', onDragEnter, false); - workarea[0].addEventListener('dragover', onDragOver, false); - workarea[0].addEventListener('dragleave', onDragLeave, false); - workarea[0].addEventListener('drop', importImage, false); + workarea[0].addEventListener('dragenter', onDragEnter); + workarea[0].addEventListener('dragover', onDragOver); + workarea[0].addEventListener('dragleave', onDragLeave); + workarea[0].addEventListener('drop', importImage); + var open = $$b('').click( + /*#__PURE__*/ + _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee16() { + var ok, reader; + return regeneratorRuntime.wrap(function _callee16$(_context16) { + while (1) { + switch (_context16.prev = _context16.next) { + case 0: + _context16.next = 2; + return editor.openPrep(); - var open = $$b('').change(function () { - var f = this; - editor.openPrep(function (ok) { - if (!ok) { - return; + case 2: + ok = _context16.sent; + + if (ok) { + _context16.next = 5; + break; + } + + return _context16.abrupt("return"); + + case 5: + svgCanvas.clear(); + + if (this.files.length === 1) { + $$b.process_cancel(uiStrings$1.notification.loadingImage); + reader = new FileReader(); + + reader.onloadend = + /*#__PURE__*/ + function () { + var _ref29 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee15(e) { + return regeneratorRuntime.wrap(function _callee15$(_context15) { + while (1) { + switch (_context15.prev = _context15.next) { + case 0: + _context15.next = 2; + return loadSvgString(e.target.result); + + case 2: + updateCanvas(); + + case 3: + case "end": + return _context15.stop(); + } + } + }, _callee15, this); + })); + + return function (_x6) { + return _ref29.apply(this, arguments); + }; + }(); + + reader.readAsText(this.files[0]); + } + + case 7: + case "end": + return _context16.stop(); + } } - svgCanvas.clear(); - if (f.files.length === 1) { - $$b.process_cancel(uiStrings$1.notification.loadingImage); - var reader = new FileReader(); - reader.onloadend = function (e) { - loadSvgString(e.target.result); - updateCanvas(); - }; - reader.readAsText(f.files[0]); - } - }); - }); + }, _callee16, this); + }))); $$b('#tool_open').show().prepend(open); - var imgImport = $$b('').change(importImage); $$b('#tool_import').show().prepend(imgImport); } - // $(function () { - updateCanvas(true); - // }); - - // const revnums = 'svg-editor.js ($Rev$) '; + updateCanvas(true); // const revnums = 'svg-editor.js ($Rev$) '; // revnums += svgCanvas.getVersion(); // $('#copyright')[0].setAttribute('title', revnums); + var loadedExtensionNames = []; /** * @function module:SVGEditor.setLang * @param {string} lang The language code * @param {module:locale.LocaleStrings} allStrings See {@tutorial LocaleDocs} * @fires module:svgcanvas.SvgCanvas#event:ext-langReady * @fires module:svgcanvas.SvgCanvas#event:ext-langChanged - * @returns {undefined} + * @returns {Promise} A Promise which resolves to `undefined` */ - var setLang = editor.setLang = function (lang, allStrings) { - editor.langChanged = true; - $$b.pref('lang', lang); - $$b('#lang_select').val(lang); - if (!allStrings) { - return; - } - $$b.extend(uiStrings$1, allStrings); - // const notif = allStrings.notification; // Currently unused - // $.extend will only replace the given strings - var oldLayerName = $$b('#layerlist tr.layersel td.layername').text(); - var renameLayer = oldLayerName === uiStrings$1.common.layer + ' 1'; + var setLang = editor.setLang = + /*#__PURE__*/ + function () { + var _ref30 = _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee17(lang, allStrings) { + var _this = this; - svgCanvas.setUiStrings(allStrings); - Actions.setTitles(); + var oldLayerName, renameLayer, elems; + return regeneratorRuntime.wrap(function _callee17$(_context17) { + while (1) { + switch (_context17.prev = _context17.next) { + case 0: + editor.langChanged = true; + $$b.pref('lang', lang); + $$b('#lang_select').val(lang); - if (renameLayer) { - svgCanvas.renameCurrentLayer(uiStrings$1.common.layer + ' 1'); - populateLayers(); - } + if (allStrings) { + _context17.next = 5; + break; + } - // In case extensions loaded before the locale, now we execute a callback on them - if (extsPreLang.length) { - while (extsPreLang.length) { - var ext = extsPreLang.shift(); - ext.langReady({ - lang: lang, - uiStrings: uiStrings$1, - importLocale: getImportLocale({ defaultLang: lang, defaultName: ext.name }) - }); - } - } else { - svgCanvas.runExtensions('langReady', /** @type {module:svgcanvas.SvgCanvas#event:ext-langReady} */{ lang: lang, uiStrings: uiStrings$1 }); - } - svgCanvas.runExtensions('langChanged', /** @type {module:svgcanvas.SvgCanvas#event:ext-langChanged} */lang); + return _context17.abrupt("return"); - // Update flyout tooltips - setFlyoutTitles(); + case 5: + $$b.extend(uiStrings$1, allStrings); // const notif = allStrings.notification; // Currently unused + // $.extend will only replace the given strings - // Copy title for certain tool elements - var elems = { - '#stroke_color': '#tool_stroke .icon_label, #tool_stroke .color_block', - '#fill_color': '#tool_fill label, #tool_fill .color_block', - '#linejoin_miter': '#cur_linejoin', - '#linecap_butt': '#cur_linecap' + oldLayerName = $$b('#layerlist tr.layersel td.layername').text(); + renameLayer = oldLayerName === uiStrings$1.common.layer + ' 1'; + svgCanvas.setUiStrings(allStrings); + Actions.setTitles(); + + if (renameLayer) { + svgCanvas.renameCurrentLayer(uiStrings$1.common.layer + ' 1'); + populateLayers(); + } // In case extensions loaded before the locale, now we execute a callback on them + + + if (!extsPreLang.length) { + _context17.next = 17; + break; + } + + _context17.next = 14; + return Promise.all(extsPreLang.map(function (ext) { + loadedExtensionNames.push(ext.name); + return ext.langReady({ + lang: lang, + uiStrings: uiStrings$1, + importLocale: getImportLocale({ + defaultLang: lang, + defaultName: ext.name + }) + }); + })); + + case 14: + extsPreLang.length = 0; + _context17.next = 18; + break; + + case 17: + loadedExtensionNames.forEach(function (loadedExtensionName) { + _this.runExtension(loadedExtensionName, 'langReady', + /** @type {module:svgcanvas.SvgCanvas#event:ext-langReady} */ + { + lang: lang, + uiStrings: uiStrings$1, + importLocale: getImportLocale({ + defaultLang: lang, + defaultName: loadedExtensionName + }) + }); + }); + + case 18: + svgCanvas.runExtensions('langChanged', + /** @type {module:svgcanvas.SvgCanvas#event:ext-langChanged} */ + lang); // Update flyout tooltips + + setFlyoutTitles(); // Copy title for certain tool elements + + elems = { + '#stroke_color': '#tool_stroke .icon_label, #tool_stroke .color_block', + '#fill_color': '#tool_fill label, #tool_fill .color_block', + '#linejoin_miter': '#cur_linejoin', + '#linecap_butt': '#cur_linecap' + }; + $$b.each(elems, function (source, dest) { + $$b(dest).attr('title', $$b(source)[0].title); + }); // Copy alignment titles + + $$b('#multiselected_panel div[id^=tool_align]').each(function () { + $$b('#tool_pos' + this.id.substr(10))[0].title = this.title; + }); + + case 23: + case "end": + return _context17.stop(); + } + } + }, _callee17, this); + })); + + return function (_x7, _x8) { + return _ref30.apply(this, arguments); }; + }(); - $$b.each(elems, function (source, dest) { - $$b(dest).attr('title', $$b(source)[0].title); - }); - - // Copy alignment titles - $$b('#multiselected_panel div[id^=tool_align]').each(function () { - $$b('#tool_pos' + this.id.substr(10))[0].title = this.title; - }); - }; init$7( /** * @implements {module:locale.LocaleEditorInit} */ { /** - * Gets an array of results from extensions with a `addLangData` method + * Gets an array of results from extensions with a `addLangData` method, * returning an object with a `data` property set to its locales (to be - * merged with regular locales) + * merged with regular locales). * @param {string} langParam * @fires module:svgcanvas.SvgCanvas#event:ext-addLangData * @todo Can we forego this in favor of `langReady` (or forego `langReady`)? @@ -30903,189 +36136,313 @@ /** * @function * @type {module:svgcanvas.ExtensionVarBuilder} - * @param {string} defaultLang - * @param {string} defaultName + * @param {string} name * @returns {module:svgcanvas.SvgCanvas#event:ext-addLangData} */ function (name) { // We pass in a function as we don't know the extension name here when defining this `addLangData` method return { lang: langParam, - importLocale: getImportLocale({ defaultLang: langParam, defaultName: name }) + importLocale: getImportLocale({ + defaultLang: langParam, + defaultName: name + }) }; }, true); }, - curConfig: curConfig - }); - // Load extensions + }); // Load extensions // Bit of a hack to run extensions in local Opera/IE9 + if (document.location.protocol === 'file:') { setTimeout(extAndLocaleFunc, 100); } else { - // Returns a promise (if we wanted to fire 'extensions-loaded' event, potentially useful to hide interface as some extension locales are only available after this) + // Returns a promise (if we wanted to fire 'extensions-loaded' event, + // potentially useful to hide interface as some extension locales + // are only available after this) extAndLocaleFunc(); } }; - /** * @callback module:SVGEditor.ReadyCallback - * @returns {undefined} + * @returns {Promise|undefined} */ + /** * Queues a callback to be invoked when the editor is ready (or * to be invoked immediately if it is already ready--i.e., - * if `svgEditor.runCallbacks` has been run) + * if `runCallbacks` has been run). * @param {module:SVGEditor.ReadyCallback} cb Callback to be queued to invoke - * @returns {undefined} + * @returns {Promise} Resolves when all callbacks, including the supplied have resolved */ - editor.ready = function (cb) { - if (!isReady) { - callbacks.push(cb); - } else { - cb(); - } - }; + + editor.ready = function (cb) { + // eslint-disable-line promise/prefer-await-to-callbacks + return new Promise(function (resolve, reject) { + // eslint-disable-line promise/avoid-new + if (isReady) { + resolve(cb()); // eslint-disable-line callback-return, promise/prefer-await-to-callbacks + + return; + } + + callbacks.push([cb, resolve, reject]); + }); + }; /** * Invokes the callbacks previous set by `svgEditor.ready` - * @returns {undefined} + * @returns {Promise} Resolves to `undefined` if all callbacks succeeded and rejects otherwise */ - editor.runCallbacks = function () { - callbacks.forEach(function (cb) { - cb(); - }); - isReady = true; - }; + + editor.runCallbacks = + /*#__PURE__*/ + _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee20() { + return regeneratorRuntime.wrap(function _callee20$(_context20) { + while (1) { + switch (_context20.prev = _context20.next) { + case 0: + _context20.prev = 0; + _context20.next = 3; + return Promise.all(callbacks.map(function (_ref33) { + var _ref34 = _slicedToArray(_ref33, 1), + cb = _ref34[0]; + + return cb(); // eslint-disable-line promise/prefer-await-to-callbacks + })); + + case 3: + _context20.next = 9; + break; + + case 5: + _context20.prev = 5; + _context20.t0 = _context20["catch"](0); + callbacks.forEach(function (_ref35) { + var _ref36 = _slicedToArray(_ref35, 3), + reject = _ref36[2]; + + reject(); + }); + throw _context20.t0; + + case 9: + callbacks.forEach(function (_ref37) { + var _ref38 = _slicedToArray(_ref37, 2), + resolve = _ref38[1]; + + resolve(); + }); + isReady = true; + + case 11: + case "end": + return _context20.stop(); + } + } + }, _callee20, this, [[0, 5]]); + })); /** * @param {string} str The SVG string to load - * @returns {undefined} + * @param {PlainObject} [opts={}] + * @param {boolean} [opts.noAlert=false] Option to avoid alert to user and instead get rejected promise + * @returns {Promise} */ - editor.loadFromString = function (str) { - editor.ready(function () { - loadSvgString(str); - }); - }; + editor.loadFromString = function (str) { + var _ref39 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + noAlert = _ref39.noAlert; + + editor.ready( + /*#__PURE__*/ + _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee21() { + return regeneratorRuntime.wrap(function _callee21$(_context21) { + while (1) { + switch (_context21.prev = _context21.next) { + case 0: + _context21.prev = 0; + _context21.next = 3; + return loadSvgString(str, { + noAlert: noAlert + }); + + case 3: + _context21.next = 9; + break; + + case 5: + _context21.prev = 5; + _context21.t0 = _context21["catch"](0); + + if (!noAlert) { + _context21.next = 9; + break; + } + + throw _context21.t0; + + case 9: + case "end": + return _context21.stop(); + } + } + }, _callee21, this, [[0, 5]]); + }))); + }; /** - * Not presently in use + * Not presently in use. * @param {PlainObject} featList * @returns {undefined} */ - editor.disableUI = function (featList) { - // $(function () { + + + editor.disableUI = function (featList) {// $(function () { // $('#tool_wireframe, #tool_image, #main_button, #tool_source, #sidepanels').remove(); // $('#tools_top').css('left', 5); // }); }; - /** * @callback module:SVGEditor.URLLoadCallback * @param {boolean} success * @returns {undefined} */ + /** * @param {string} url URL from which to load an SVG string via Ajax - * @param {PlainObject} [opts] May contain properties: `cache`, `callback` - * @param {boolean} opts.cache - * @param {module:SVGEditor.URLLoadCallback} opts.callback Invoked with `true` or `false` depending on success - * @returns {undefined} + * @param {PlainObject} [opts={}] May contain properties: `cache`, `callback` + * @param {boolean} [opts.cache] + * @param {boolean} [opts.noAlert] + * @returns {Promise} Resolves to `undefined` or rejects upon bad loading of + * the SVG (or upon failure to parse the loaded string) when `noAlert` is + * enabled */ - editor.loadFromURL = function (url, opts) { - if (!opts) { - opts = {}; - } - - var _opts = opts, - cache = _opts.cache, - cb = _opts.callback; - editor.ready(function () { - $$b.ajax({ - url: url, - dataType: 'text', - cache: !!cache, - beforeSend: function beforeSend() { - $$b.process_cancel(uiStrings$1.notification.loadingImage); - }, - success: function success(str) { - loadSvgString(str, cb); - }, - error: function error(xhr, stat, err) { - if (xhr.status !== 404 && xhr.responseText) { - loadSvgString(xhr.responseText, cb); - } else { - $$b.alert(uiStrings$1.notification.URLloadFail + ': \n' + err, cb); + editor.loadFromURL = function (url) { + var _ref41 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + cache = _ref41.cache, + noAlert = _ref41.noAlert; + + return editor.ready(function () { + return new Promise(function (resolve, reject) { + // eslint-disable-line promise/avoid-new + $$b.ajax({ + url: url, + dataType: 'text', + cache: Boolean(cache), + beforeSend: function beforeSend() { + $$b.process_cancel(uiStrings$1.notification.loadingImage); + }, + success: function success(str) { + resolve(loadSvgString(str, { + noAlert: noAlert + })); + }, + error: function error(xhr, stat, err) { + if (xhr.status !== 404 && xhr.responseText) { + resolve(loadSvgString(xhr.responseText, { + noAlert: noAlert + })); + return; + } + + if (noAlert) { + reject(new Error('URLLoadFail')); + return; + } + + $$b.alert(uiStrings$1.notification.URLLoadFail + ': \n' + err); + resolve(); + }, + complete: function complete() { + $$b('#dialog_box').hide(); } - }, - complete: function complete() { - $$b('#dialog_box').hide(); - } + }); }); }); }; - /** * @param {string} str The Data URI to base64-decode (if relevant) and load - * @returns {undefined} + * @param {PlainObject} [opts={}] + * @param {boolean} [opts.noAlert] + * @returns {Promise} Resolves to `undefined` and rejects if loading SVG string fails and `noAlert` is enabled */ + + editor.loadFromDataURI = function (str) { + var _ref42 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + noAlert = _ref42.noAlert; + editor.ready(function () { var base64 = false; var pre = str.match(/^data:image\/svg\+xml;base64,/); + if (pre) { base64 = true; } else { - pre = str.match(/^data:image\/svg\+xml(?:;(?:utf8)?)?,/); + pre = str.match(/^data:image\/svg\+xml(?:;|;utf8)?,/); } + if (pre) { pre = pre[0]; } + var src = str.slice(pre.length); - loadSvgString(base64 ? decode64(src) : decodeURIComponent(src)); + return loadSvgString(base64 ? decode64(src) : decodeURIComponent(src), { + noAlert: noAlert + }); }); }; - /** * @param {string} name Used internally; no need for i18n. * @param {module:svgcanvas.ExtensionInitCallback} init Config to be invoked on this module - * @param {module:SVGEditor~ImportLocale} importLocale Importer defaulting to pth with current extension name and locale + * @param {module:svgcanvas.ExtensionInitArgs} initArgs * @throws {Error} If called too early * @returns {Promise} Resolves to `undefined` */ - editor.addExtension = function (name, init$$1, importLocale) { + + + editor.addExtension = function (name, init, initArgs) { // Note that we don't want this on editor.ready since some extensions // may want to run before then (like server_opensave). // $(function () { if (!svgCanvas) { throw new Error('Extension added too early'); } - return svgCanvas.addExtension.call(this, name, init$$1, importLocale); - // }); - }; - // Defer injection to wait out initial menu processing. This probably goes + return svgCanvas.addExtension.call(this, name, init, initArgs); // }); + }; // Defer injection to wait out initial menu processing. This probably goes // away once all context menu behavior is brought to context menu. + + editor.ready(function () { injectExtendedContextMenuItemsIntoDom(); }); - var extensionsAdded = false; var messageQueue = []; /** - * @param {Any} data - * @param {string} origin + * @param {PlainObject} info + * @param {Any} info.data + * @param {string} info.origin * @fires module:svgcanvas.SvgCanvas#event:message * @returns {undefined} */ - var messageListener = function messageListener(_ref17) { - var data = _ref17.data, - origin = _ref17.origin; + var messageListener = function messageListener(_ref43) { + var data = _ref43.data, + origin = _ref43.origin; + // eslint-disable-line no-shadow // console.log('data, origin, extensionsAdded', data, origin, extensionsAdded); - var messageObj = { data: data, origin: origin }; + var messageObj = { + data: data, + origin: origin + }; + if (!extensionsAdded) { messageQueue.push(messageObj); } else { @@ -31094,31 +36451,56 @@ svgCanvas.call('message', messageObj); } }; - window.addEventListener('message', messageListener); - // Run init once DOM is loaded + window.addEventListener('message', messageListener); // Run init once DOM is loaded // jQuery(editor.init); - Promise.resolve().then(function () { - // We wait a micro-task to let the svgEditor variable be defined for module checks - editor.init(); - }); + + _asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee22() { + return regeneratorRuntime.wrap(function _callee22$(_context22) { + while (1) { + switch (_context22.prev = _context22.next) { + case 0: + _context22.prev = 0; + _context22.next = 3; + return Promise.resolve(); + + case 3: + editor.init(); + _context22.next = 9; + break; + + case 6: + _context22.prev = 6; + _context22.t0 = _context22["catch"](0); + console.error(_context22.t0); // eslint-disable-line no-console + + case 9: + case "end": + return _context22.stop(); + } + } + }, _callee22, this, [[0, 6]]); + }))(); // TO BUILD AN IIFE VERSION OF THIS FILE (AS CAN WORK ON OLDER BROWSERS), window.svgEditor = editor; - window.svgEditor.modules = false; + window.svgEditor.modules = false; // URL OVERRIDE CONFIG - // URL OVERRIDE CONFIG editor.setConfig({ /** To override the ability for URLs to set URL-based SVG content, uncomment the following: */ // preventURLContentLoading: true, + /** To override the ability for URLs to set other configuration (including extension config), uncomment the following: */ // preventAllURLConfig: true, + /** To override the ability for URLs to set their own extensions, uncomment the following (note that if `setConfig()` is used in @@ -31127,29 +36509,27 @@ */ // lockExtensions: true, }); - editor.setConfig({ /* Provide default values here which differ from that of the editor but which the URL can override */ - }, { allowInitialUserOverride: true }); + }, { + allowInitialUserOverride: true + }); // EXTENSION CONFIG - // EXTENSION CONFIG editor.setConfig({ - extensions: [ - // 'ext-overview_window.js', 'ext-markers.js', 'ext-connector.js', 'ext-eyedropper.js', 'ext-shapes.js', 'ext-imagelib.js', 'ext-grid.js', 'ext-polygon.js', 'ext-star.js', 'ext-panning.js', 'ext-storage.js' - ], noDefaultExtensions: false // noDefaultExtensions can only be meaningfully used in svgedit-config-iife.js or in the URL - }); + extensions: [// 'ext-overview_window.js', 'ext-markers.js', 'ext-connector.js', 'ext-eyedropper.js', 'ext-shapes.js', 'ext-imagelib.js', 'ext-grid.js', 'ext-polygon.js', 'ext-star.js', 'ext-panning.js', 'ext-storage.js' + ], + noDefaultExtensions: false // noDefaultExtensions can only be meaningfully used in svgedit-config-iife.js or in the URL + + }); // STYLESHEET CONFIG - // STYLESHEET CONFIG editor.setConfig({ stylesheets: ['@default', '../svgedit-custom.css'] - }); + }); // OTHER CONFIG - // OTHER CONFIG - editor.setConfig({ - // canvasName: 'default', + editor.setConfig({// canvasName: 'default', // canvas_expansion: 3, // initFill: { // color: 'FF0000', // solid red @@ -31172,13 +36552,14 @@ // langPath: 'locale/', // extPath: 'extensions/', // jGraduatePath: 'jgraduate/images/', + /* Uncomment the following to allow at least same domain (embedded) access, - including file:// access. + including `file:///` access. Setting as `['*']` would allow any domain to access but would be unsafe to data privacy and integrity. */ - // allowedOrigins: [window.location.origin || 'null'], // May be 'null' (as a string) when used as a file:// URL + // allowedOrigins: [location.origin || 'null'], // May be 'null' (as a string) when used as a `file:///` URL // DOCUMENT PROPERTIES // dimensions: [640, 480], // EDITOR OPTIONS @@ -31193,9 +36574,8 @@ // noStorageOnLoad: false, // Some interaction with ext-storage.js; prevent even the loading of previously saved local storage // forceStorage: false, // Some interaction with ext-storage.js; strongly discouraged from modification as it bypasses user privacy by preventing them from choosing whether to keep local storage or not // emptyStorageOnDecline: true, // Used by ext-storage.js; empty any prior storage if the user declines to store - }); + }); // PREF CHANGES - // PREF CHANGES /** setConfig() can also be used to set preferences in addition to configuration (see defaultPrefs in svg-editor.js for a list of @@ -31209,9 +36589,10 @@ Failing to use allowInitialUserOverride will ensure preferences are hard-coded here regardless of URL or prior user storage setting. */ - editor.setConfig({ - // lang: '', // Set dynamically within locale.js if not previously set + + editor.setConfig({// lang: '', // Set dynamically within locale.js if not previously set // iconsize: '', // Will default to 's' if the window height is smaller than the minimum height and 'm' otherwise + /** * When showing the preferences dialog, svg-editor.js currently relies * on curPrefs instead of $.pref, so allowing an override for bkgd_color @@ -31226,10 +36607,11 @@ // save_notice_done: false, // export_notice_done: false }); - editor.setConfig({ - // Indicate pref settings here if you wish to allow user storage or URL settings + editor.setConfig({// Indicate pref settings here if you wish to allow user storage or URL settings // to be able to override your default preferences (unless other config options // have already explicitly prevented one or the other) - }, { allowInitialUserOverride: true }); + }, { + allowInitialUserOverride: true + }); }()); diff --git a/test/contextmenu_test.js b/test/contextmenu_test.js index c5391536..2aa6931a 100644 --- a/test/contextmenu_test.js +++ b/test/contextmenu_test.js @@ -8,6 +8,10 @@ QUnit.log((details) => { } }); +/** + * Tear down tests, resetting custom menus. + * @returns {undefined} + */ function tearDown () { contextmenu.resetCustomMenus(); } @@ -26,20 +30,26 @@ QUnit.test('Test svgedit.contextmenu package', function (assert) { QUnit.test('Test svgedit.contextmenu does not add invalid menu item', function (assert) { assert.expect(3); - contextmenu.add({id: 'justanid'}); - assert.ok(!contextmenu.hasCustomHandler('justanid'), 'menu item with just an id is invalid'); + assert.throws( + () => contextmenu.add({id: 'justanid'}), + 'menu item with just an id is invalid' + ); - contextmenu.add({id: 'idandlabel', label: 'anicelabel'}); - assert.ok(!contextmenu.hasCustomHandler('idandlabel'), 'menu item with just an id and label is invalid'); + assert.throws( + () => contextmenu.add({id: 'idandlabel', label: 'anicelabel'}), + 'menu item with just an id and label is invalid' + ); - contextmenu.add({id: 'idandlabel', label: 'anicelabel', action: 'notafunction'}); - assert.ok(!contextmenu.hasCustomHandler('idandlabel'), 'menu item with action that is not a function is invalid'); + assert.throws( + () => contextmenu.add({id: 'idandlabel', label: 'anicelabel', action: 'notafunction'}), + 'menu item with action that is not a function is invalid' + ); }); QUnit.test('Test svgedit.contextmenu adds valid menu item', function (assert) { assert.expect(2); - const validItem = {id: 'valid', label: 'anicelabel', action () { alert('testing'); }}; + const validItem = {id: 'valid', label: 'anicelabel', action () { console.log('testing'); }}; contextmenu.add(validItem); assert.ok(contextmenu.hasCustomHandler('valid'), 'Valid menu item is added.'); @@ -50,11 +60,14 @@ QUnit.test('Test svgedit.contextmenu adds valid menu item', function (assert) { QUnit.test('Test svgedit.contextmenu rejects valid duplicate menu item id', function (assert) { assert.expect(1); - const validItem1 = {id: 'valid', label: 'anicelabel', action () { alert('testing'); }}; - const validItem2 = {id: 'valid', label: 'anicelabel', action () { alert('testingtwice'); }}; + const validItem1 = {id: 'valid', label: 'anicelabel', action () { console.log('testing'); }}; + const validItem2 = {id: 'valid', label: 'anicelabel', action () { console.log('testingtwice'); }}; contextmenu.add(validItem1); - contextmenu.add(validItem2); - assert.equal(contextmenu.getCustomHandler('valid'), validItem1.action, 'duplicate menu item is rejected.'); + assert.throws( + () => contextmenu.add(validItem2), + 'duplicate menu item is rejected.' + ); + tearDown(); }); diff --git a/test/coords_test.js b/test/coords_test.js index 48837d3d..594a2dd3 100644 --- a/test/coords_test.js +++ b/test/coords_test.js @@ -18,6 +18,11 @@ const svg = document.createElementNS(NS.SVG, 'svg'); svgroot.append(svg); let elemId = 1; + +/** + * Set up tests with mock data. + * @returns {undefined} + */ function setUp () { // Mock out editor context. utilities.init( @@ -38,13 +43,17 @@ function setUp () { getGridSnapping () { return false; }, getDrawing () { return { - getNextId () { return '' + elemId++; } + getNextId () { return String(elemId++); } }; } } ); } +/** + * Tear down tests, removing elements. + * @returns {undefined} + */ function tearDown () { while (svg.hasChildNodes()) { svg.firstChild.remove(); diff --git a/test/draw_test.js b/test/draw_test.js index 479041df..6393d198 100644 --- a/test/draw_test.js +++ b/test/draw_test.js @@ -65,8 +65,7 @@ const currentDrawing_ = new draw.Drawing(svgcontent, idprefix); const getCurrentDrawing = function () { return currentDrawing_; }; -const setCurrentGroup = (cg) => { -}; +const setCurrentGroup = (cg) => { /* */ }; draw.init( /** * @implements {module:draw.DrawCanvasInit} @@ -77,11 +76,15 @@ draw.init( } ); +/** + * @param {module:utilities.SVGElementJSON} jsonMap + * @returns {SVGElement} + */ function createSVGElement (jsonMap) { - const elem = document.createElementNS(NS.SVG, jsonMap['element']); - for (const attr in jsonMap['attr']) { - elem.setAttribute(attr, jsonMap['attr'][attr]); - } + const elem = document.createElementNS(NS.SVG, jsonMap.element); + Object.entries(jsonMap.attr).forEach(([attr, value]) => { + elem.setAttribute(attr, value); + }); return elem; } @@ -143,12 +146,7 @@ const cleanupSVG = function (svgElem) { while (svgElem.firstChild) { svgElem.firstChild.remove(); } }; -QUnit.module('svgedit.draw.Drawing', { - beforeEach () { - }, - afterEach () { - } -}); +QUnit.module('svgedit.draw.Drawing'); QUnit.test('Test draw module', function (assert) { assert.expect(4); @@ -157,7 +155,7 @@ QUnit.test('Test draw module', function (assert) { assert.equal(typeof draw, typeof {}); assert.ok(draw.Drawing); - assert.equal(typeof draw.Drawing, typeof function () {}); + assert.equal(typeof draw.Drawing, typeof function () { /* */ }); }); QUnit.test('Test document creation', function (assert) { @@ -311,7 +309,7 @@ QUnit.test('Test releaseId()', function (assert) { QUnit.test('Test getNumLayers', function (assert) { assert.expect(3); const drawing = new draw.Drawing(svg); - assert.equal(typeof drawing.getNumLayers, typeof function () {}); + assert.equal(typeof drawing.getNumLayers, typeof function () { /* */ }); assert.equal(drawing.getNumLayers(), 0); setupSVGWith3Layers(svg); @@ -329,7 +327,7 @@ QUnit.test('Test hasLayer', function (assert) { const drawing = new draw.Drawing(svg); drawing.identifyLayers(); - assert.equal(typeof drawing.hasLayer, typeof function () {}); + assert.equal(typeof drawing.hasLayer, typeof function () { /* */ }); assert.ok(!drawing.hasLayer('invalid-layer')); assert.ok(drawing.hasLayer(LAYER3)); @@ -447,7 +445,7 @@ QUnit.test('Test getCurrentLayer()', function (assert) { drawing.identifyLayers(); assert.ok(drawing.getCurrentLayer); - assert.equal(typeof drawing.getCurrentLayer, typeof function () {}); + assert.equal(typeof drawing.getCurrentLayer, typeof function () { /* */ }); assert.ok(drawing.getCurrentLayer()); assert.equal(drawing.getCurrentLayer(), drawing.all_layers[2].getGroup()); @@ -462,7 +460,7 @@ QUnit.test('Test setCurrentLayer() and getCurrentLayerName()', function (assert) drawing.identifyLayers(); assert.ok(drawing.setCurrentLayer); - assert.equal(typeof drawing.setCurrentLayer, typeof function () {}); + assert.equal(typeof drawing.setCurrentLayer, typeof function () { /* */ }); drawing.setCurrentLayer(LAYER2); assert.equal(drawing.getCurrentLayerName(), LAYER2); @@ -485,7 +483,7 @@ QUnit.test('Test setCurrentLayerName()', function (assert) { drawing.identifyLayers(); assert.ok(drawing.setCurrentLayerName); - assert.equal(typeof drawing.setCurrentLayerName, typeof function () {}); + assert.equal(typeof drawing.setCurrentLayerName, typeof function () { /* */ }); const oldName = drawing.getCurrentLayerName(); const newName = 'New Name'; @@ -519,7 +517,7 @@ QUnit.test('Test createLayer()', function (assert) { drawing.identifyLayers(); assert.ok(drawing.createLayer); - assert.equal(typeof drawing.createLayer, typeof function () {}); + assert.equal(typeof drawing.createLayer, typeof function () { /* */ }); const NEW_LAYER_NAME = 'Layer A'; const layerG = drawing.createLayer(NEW_LAYER_NAME, mockHrService); @@ -553,7 +551,7 @@ QUnit.test('Test mergeLayer()', function (assert) { assert.equal(drawing.getCurrentLayer(), layers[2]); assert.ok(drawing.mergeLayer); - assert.equal(typeof drawing.mergeLayer, typeof function () {}); + assert.equal(typeof drawing.mergeLayer, typeof function () { /* */ }); drawing.mergeLayer(mockHrService); @@ -623,7 +621,7 @@ QUnit.test('Test mergeAllLayers()', function (assert) { drawing.identifyLayers(); assert.ok(drawing.mergeAllLayers); - assert.equal(typeof drawing.mergeAllLayers, typeof function () {}); + assert.equal(typeof drawing.mergeAllLayers, typeof function () { /* */ }); drawing.mergeAllLayers(mockHrService); @@ -661,7 +659,7 @@ QUnit.test('Test cloneLayer()', function (assert) { drawing.identifyLayers(); assert.ok(drawing.cloneLayer); - assert.equal(typeof drawing.cloneLayer, typeof function () {}); + assert.equal(typeof drawing.cloneLayer, typeof function () { /* */ }); const clone = drawing.cloneLayer('clone', mockHrService); @@ -703,7 +701,7 @@ QUnit.test('Test getLayerVisibility()', function (assert) { drawing.identifyLayers(); assert.ok(drawing.getLayerVisibility); - assert.equal(typeof drawing.getLayerVisibility, typeof function () {}); + assert.equal(typeof drawing.getLayerVisibility, typeof function () { /* */ }); assert.ok(drawing.getLayerVisibility(LAYER1)); assert.ok(drawing.getLayerVisibility(LAYER2)); assert.ok(drawing.getLayerVisibility(LAYER3)); @@ -719,7 +717,7 @@ QUnit.test('Test setLayerVisibility()', function (assert) { drawing.identifyLayers(); assert.ok(drawing.setLayerVisibility); - assert.equal(typeof drawing.setLayerVisibility, typeof function () {}); + assert.equal(typeof drawing.setLayerVisibility, typeof function () { /* */ }); drawing.setLayerVisibility(LAYER3, false); drawing.setLayerVisibility(LAYER2, true); @@ -743,7 +741,7 @@ QUnit.test('Test getLayerOpacity()', function (assert) { drawing.identifyLayers(); assert.ok(drawing.getLayerOpacity); - assert.equal(typeof drawing.getLayerOpacity, typeof function () {}); + assert.equal(typeof drawing.getLayerOpacity, typeof function () { /* */ }); assert.strictEqual(drawing.getLayerOpacity(LAYER1), 1.0); assert.strictEqual(drawing.getLayerOpacity(LAYER2), 1.0); assert.strictEqual(drawing.getLayerOpacity(LAYER3), 1.0); @@ -759,7 +757,7 @@ QUnit.test('Test setLayerOpacity()', function (assert) { drawing.identifyLayers(); assert.ok(drawing.setLayerOpacity); - assert.equal(typeof drawing.setLayerOpacity, typeof function () {}); + assert.equal(typeof drawing.setLayerOpacity, typeof function () { /* */ }); drawing.setLayerOpacity(LAYER1, 0.4); drawing.setLayerOpacity(LAYER2, 'invalid-string'); @@ -802,18 +800,18 @@ QUnit.test('Test svgedit.draw.randomizeIds()', function (assert) { // Confirm in LET_DOCUMENT_DECIDE mode that the document decides // if there is a nonce. let drawing = new draw.Drawing(svgN.cloneNode(true)); - assert.ok(!!drawing.getNonce()); + assert.ok(drawing.getNonce()); drawing = new draw.Drawing(svg.cloneNode(true)); assert.ok(!drawing.getNonce()); // Confirm that a nonce is set once we're in ALWAYS_RANDOMIZE mode. draw.randomizeIds(true, drawing); - assert.ok(!!drawing.getNonce()); + assert.ok(drawing.getNonce()); // Confirm new drawings in ALWAYS_RANDOMIZE mode have a nonce. drawing = new draw.Drawing(svg.cloneNode(true)); - assert.ok(!!drawing.getNonce()); + assert.ok(drawing.getNonce()); drawing.clearNonce(); assert.ok(!drawing.getNonce()); @@ -822,7 +820,7 @@ QUnit.test('Test svgedit.draw.randomizeIds()', function (assert) { // but that their se:nonce attribute is left alone. draw.randomizeIds(false, drawing); assert.ok(!drawing.getNonce()); - assert.ok(!!drawing.getSvgElem().getAttributeNS(NS.SE, 'nonce')); + assert.ok(drawing.getSvgElem().getAttributeNS(NS.SE, 'nonce')); drawing = new draw.Drawing(svg.cloneNode(true)); assert.ok(!drawing.getNonce()); diff --git a/test/history_test.js b/test/history_test.js index 13cc8e42..6f4edebe 100644 --- a/test/history_test.js +++ b/test/history_test.js @@ -3,16 +3,16 @@ import {NS} from '../editor/namespaces.js'; import * as transformlist from '../editor/svgtransformlist.js'; import * as utilities from '../editor/utilities.js'; -import * as history from '../editor/history.js'; +import * as hstory from '../editor/history.js'; // TODO(codedread): Write tests for handling history events. // Mocked out methods. -transformlist.changeRemoveElementFromListMap((elem) => {}); +transformlist.changeRemoveElementFromListMap((elem) => { /* */ }); utilities.mock({ getHref (elem) { return '#foo'; }, - setHref (elem, val) {}, + setHref (elem, val) { /* */ }, getRotationAngle (elem) { return 0; } }); @@ -36,10 +36,10 @@ QUnit.module('svgedit.history'); class MockCommand { constructor (optText) { this.text_ = optText; } - apply () {} - unapply () {} + apply () { /* */ } // eslint-disable-line class-methods-use-this + unapply () { /* */ } // eslint-disable-line class-methods-use-this getText () { return this.text_; } - elements () { return []; } + elements () { return []; } // eslint-disable-line class-methods-use-this } /* @@ -48,9 +48,17 @@ class MockHistoryEventHandler { } */ +/** + * Set up tests (with undo manager). + * @returns {undefined} + */ function setUp () { - undoMgr = new history.UndoManager(); + undoMgr = new hstory.UndoManager(); } +/** + * Tear down tests, destroying undo manager. + * @returns {undefined} + */ function tearDown () { undoMgr = null; } @@ -58,19 +66,19 @@ function tearDown () { QUnit.test('Test svgedit.history package', function (assert) { assert.expect(13); - assert.ok(history); - assert.ok(history.MoveElementCommand); - assert.ok(history.InsertElementCommand); - assert.ok(history.ChangeElementCommand); - assert.ok(history.RemoveElementCommand); - assert.ok(history.BatchCommand); - assert.ok(history.UndoManager); - assert.equal(typeof history.MoveElementCommand, typeof function () {}); - assert.equal(typeof history.InsertElementCommand, typeof function () {}); - assert.equal(typeof history.ChangeElementCommand, typeof function () {}); - assert.equal(typeof history.RemoveElementCommand, typeof function () {}); - assert.equal(typeof history.BatchCommand, typeof function () {}); - assert.equal(typeof history.UndoManager, typeof function () {}); + assert.ok(hstory); + assert.ok(hstory.MoveElementCommand); + assert.ok(hstory.InsertElementCommand); + assert.ok(hstory.ChangeElementCommand); + assert.ok(hstory.RemoveElementCommand); + assert.ok(hstory.BatchCommand); + assert.ok(hstory.UndoManager); + assert.equal(typeof hstory.MoveElementCommand, typeof function () { /* */ }); + assert.equal(typeof hstory.InsertElementCommand, typeof function () { /* */ }); + assert.equal(typeof hstory.ChangeElementCommand, typeof function () { /* */ }); + assert.equal(typeof hstory.RemoveElementCommand, typeof function () { /* */ }); + assert.equal(typeof hstory.BatchCommand, typeof function () { /* */ }); + assert.equal(typeof hstory.UndoManager, typeof function () { /* */ }); }); QUnit.test('Test UndoManager methods', function (assert) { @@ -86,12 +94,12 @@ QUnit.test('Test UndoManager methods', function (assert) { assert.ok(undoMgr.getNextRedoCommandText); assert.equal(typeof undoMgr, typeof {}); - assert.equal(typeof undoMgr.addCommandToHistory, typeof function () {}); - assert.equal(typeof undoMgr.getUndoStackSize, typeof function () {}); - assert.equal(typeof undoMgr.getRedoStackSize, typeof function () {}); - assert.equal(typeof undoMgr.resetUndoStack, typeof function () {}); - assert.equal(typeof undoMgr.getNextUndoCommandText, typeof function () {}); - assert.equal(typeof undoMgr.getNextRedoCommandText, typeof function () {}); + assert.equal(typeof undoMgr.addCommandToHistory, typeof function () { /* */ }); + assert.equal(typeof undoMgr.getUndoStackSize, typeof function () { /* */ }); + assert.equal(typeof undoMgr.getRedoStackSize, typeof function () { /* */ }); + assert.equal(typeof undoMgr.resetUndoStack, typeof function () { /* */ }); + assert.equal(typeof undoMgr.getNextUndoCommandText, typeof function () { /* */ }); + assert.equal(typeof undoMgr.getNextRedoCommandText, typeof function () { /* */ }); tearDown(); }); @@ -309,11 +317,11 @@ QUnit.test('Test MoveElementCommand', function (assert) { setUp(); - let move = new history.MoveElementCommand(div3, div1, divparent); + let move = new hstory.MoveElementCommand(div3, div1, divparent); assert.ok(move.unapply); assert.ok(move.apply); - assert.equal(typeof move.unapply, typeof function () {}); - assert.equal(typeof move.apply, typeof function () {}); + assert.equal(typeof move.unapply, typeof function () { /* */ }); + assert.equal(typeof move.apply, typeof function () { /* */ }); move.unapply(); assert.equal(divparent.firstElementChild, div3); @@ -325,7 +333,7 @@ QUnit.test('Test MoveElementCommand', function (assert) { assert.equal(divparent.firstElementChild.nextElementSibling, div2); assert.equal(divparent.lastElementChild, div3); - move = new history.MoveElementCommand(div1, null, divparent); + move = new hstory.MoveElementCommand(div1, null, divparent); move.unapply(); assert.equal(divparent.firstElementChild, div2); @@ -337,7 +345,7 @@ QUnit.test('Test MoveElementCommand', function (assert) { assert.equal(divparent.firstElementChild.nextElementSibling, div2); assert.equal(divparent.lastElementChild, div3); - move = new history.MoveElementCommand(div2, div5, div4); + move = new hstory.MoveElementCommand(div2, div5, div4); move.unapply(); assert.equal(divparent.firstElementChild, div1); @@ -361,11 +369,11 @@ QUnit.test('Test InsertElementCommand', function (assert) { setUp(); - let insert = new history.InsertElementCommand(div3); + let insert = new hstory.InsertElementCommand(div3); assert.ok(insert.unapply); assert.ok(insert.apply); - assert.equal(typeof insert.unapply, typeof function () {}); - assert.equal(typeof insert.apply, typeof function () {}); + assert.equal(typeof insert.unapply, typeof function () { /* */ }); + assert.equal(typeof insert.apply, typeof function () { /* */ }); insert.unapply(); assert.equal(divparent.childElementCount, 2); @@ -379,7 +387,7 @@ QUnit.test('Test InsertElementCommand', function (assert) { assert.equal(div1.nextElementSibling, div2); assert.equal(div2.nextElementSibling, div3); - insert = new history.InsertElementCommand(div2); + insert = new hstory.InsertElementCommand(div2); insert.unapply(); assert.equal(divparent.childElementCount, 2); @@ -404,11 +412,11 @@ QUnit.test('Test RemoveElementCommand', function (assert) { const div6 = document.createElement('div'); div6.id = 'div6'; - let remove = new history.RemoveElementCommand(div6, null, divparent); + let remove = new hstory.RemoveElementCommand(div6, null, divparent); assert.ok(remove.unapply); assert.ok(remove.apply); - assert.equal(typeof remove.unapply, typeof function () {}); - assert.equal(typeof remove.apply, typeof function () {}); + assert.equal(typeof remove.unapply, typeof function () { /* */ }); + assert.equal(typeof remove.apply, typeof function () { /* */ }); remove.unapply(); assert.equal(divparent.childElementCount, 4); @@ -423,7 +431,7 @@ QUnit.test('Test RemoveElementCommand', function (assert) { assert.equal(div1.nextElementSibling, div2); assert.equal(div2.nextElementSibling, div3); - remove = new history.RemoveElementCommand(div6, div2, divparent); + remove = new hstory.RemoveElementCommand(div6, div2, divparent); remove.unapply(); assert.equal(divparent.childElementCount, 4); @@ -447,12 +455,12 @@ QUnit.test('Test ChangeElementCommand', function (assert) { setUp(); div1.setAttribute('title', 'new title'); - let change = new history.ChangeElementCommand(div1, + let change = new hstory.ChangeElementCommand(div1, {title: 'old title', class: 'foo'}); assert.ok(change.unapply); assert.ok(change.apply); - assert.equal(typeof change.unapply, typeof function () {}); - assert.equal(typeof change.apply, typeof function () {}); + assert.equal(typeof change.unapply, typeof function () { /* */ }); + assert.equal(typeof change.apply, typeof function () { /* */ }); change.unapply(); assert.equal(div1.getAttribute('title'), 'old title'); @@ -463,7 +471,7 @@ QUnit.test('Test ChangeElementCommand', function (assert) { assert.ok(!div1.getAttribute('class')); div1.textContent = 'inner text'; - change = new history.ChangeElementCommand(div1, + change = new hstory.ChangeElementCommand(div1, {'#text': null}); change.unapply(); @@ -473,7 +481,7 @@ QUnit.test('Test ChangeElementCommand', function (assert) { assert.equal(div1.textContent, 'inner text'); div1.textContent = ''; - change = new history.ChangeElementCommand(div1, + change = new hstory.ChangeElementCommand(div1, {'#text': 'old text'}); change.unapply(); @@ -502,7 +510,7 @@ QUnit.test('Test ChangeElementCommand', function (assert) { }); gethrefvalue = '#newhref'; - change = new history.ChangeElementCommand(rect, + change = new hstory.ChangeElementCommand(rect, {'#href': '#oldhref'}); assert.equal(justCalled, 'getHref'); @@ -517,19 +525,19 @@ QUnit.test('Test ChangeElementCommand', function (assert) { assert.equal(justCalled, 'setHref'); const line = document.createElementNS(NS.SVG, 'line'); - line.setAttributeNS(null, 'class', 'newClass'); - change = new history.ChangeElementCommand(line, {class: 'oldClass'}); + line.setAttribute('class', 'newClass'); + change = new hstory.ChangeElementCommand(line, {class: 'oldClass'}); assert.ok(change.unapply); assert.ok(change.apply); - assert.equal(typeof change.unapply, typeof function () {}); - assert.equal(typeof change.apply, typeof function () {}); + assert.equal(typeof change.unapply, typeof function () { /* */ }); + assert.equal(typeof change.apply, typeof function () { /* */ }); change.unapply(); - assert.equal(line.getAttributeNS(null, 'class'), 'oldClass'); + assert.equal(line.getAttribute('class'), 'oldClass'); change.apply(); - assert.equal(line.getAttributeNS(null, 'class'), 'newClass'); + assert.equal(line.getAttribute('class'), 'newClass'); tearDown(); }); @@ -542,15 +550,15 @@ QUnit.test('Test BatchCommand', function (assert) { let concatResult = ''; MockCommand.prototype.apply = function () { concatResult += this.text_; }; - const batch = new history.BatchCommand(); + const batch = new hstory.BatchCommand(); assert.ok(batch.unapply); assert.ok(batch.apply); assert.ok(batch.addSubCommand); assert.ok(batch.isEmpty); - assert.equal(typeof batch.unapply, typeof function () {}); - assert.equal(typeof batch.apply, typeof function () {}); - assert.equal(typeof batch.addSubCommand, typeof function () {}); - assert.equal(typeof batch.isEmpty, typeof function () {}); + assert.equal(typeof batch.unapply, typeof function () { /* */ }); + assert.equal(typeof batch.apply, typeof function () { /* */ }); + assert.equal(typeof batch.addSubCommand, typeof function () { /* */ }); + assert.equal(typeof batch.isEmpty, typeof function () { /* */ }); assert.ok(batch.isEmpty()); @@ -563,13 +571,13 @@ QUnit.test('Test BatchCommand', function (assert) { batch.apply(); assert.equal(concatResult, 'abc'); - MockCommand.prototype.apply = function () {}; + MockCommand.prototype.apply = function () { /* */ }; MockCommand.prototype.unapply = function () { concatResult += this.text_; }; concatResult = ''; batch.unapply(); assert.equal(concatResult, 'cba'); - MockCommand.prototype.unapply = function () {}; + MockCommand.prototype.unapply = function () { /* */ }; tearDown(); }); diff --git a/test/jQuery.attr_test.js b/test/jQuery.attr_test.js index 69ddc8f9..351fdaa1 100644 --- a/test/jQuery.attr_test.js +++ b/test/jQuery.attr_test.js @@ -1,5 +1,9 @@ /* eslint-env qunit */ +/* eslint-disable import/unambiguous */ + +// Todo: Incomplete! + // log function QUnit.log((details) => { if (window.console && window.console.log) { diff --git a/test/math_test.js b/test/math_test.js index b849b672..5b4ec399 100644 --- a/test/math_test.js +++ b/test/math_test.js @@ -20,9 +20,9 @@ QUnit.test('Test svgedit.math package', function (assert) { assert.ok(math.transformPoint); assert.ok(math.isIdentity); assert.ok(math.matrixMultiply); - assert.equal(typeof math.transformPoint, typeof function () {}); - assert.equal(typeof math.isIdentity, typeof function () {}); - assert.equal(typeof math.matrixMultiply, typeof function () {}); + assert.equal(typeof math.transformPoint, typeof function () { /* */ }); + assert.equal(typeof math.isIdentity, typeof function () { /* */ }); + assert.equal(typeof math.matrixMultiply, typeof function () { /* */ }); }); QUnit.test('Test svgedit.math.transformPoint() function', function (assert) { diff --git a/test/qunit/qunit-assert-almostEquals.js b/test/qunit/qunit-assert-almostEquals.js index d7f679a8..e33265ce 100644 --- a/test/qunit/qunit-assert-almostEquals.js +++ b/test/qunit/qunit-assert-almostEquals.js @@ -1,5 +1,12 @@ const NEAR_ZERO = 5e-6; // 0.000005, Firefox fails at higher levels of precision. +/** + * Checks that the supplied values are equal with a high though not absolute degree of precision. + * @param {Float} actual + * @param {Float} expected + * @param {string} message + * @returns {undefined} + */ function almostEquals (actual, expected, message) { message = message || (actual + ' did not equal ' + expected); this.pushResult({ @@ -10,6 +17,10 @@ function almostEquals (actual, expected, message) { }); } +/** + * @param {external:qunit} QUnit + * @returns {external:qunit} The same instance passed in after extending + */ export default function extend (QUnit) { QUnit.extend(QUnit.assert, { almostEquals diff --git a/test/qunit/qunit-assert-close.js b/test/qunit/qunit-assert-close.js index 30f0b071..3f9ccfab 100644 --- a/test/qunit/qunit-assert-close.js +++ b/test/qunit/qunit-assert-close.js @@ -8,6 +8,7 @@ * @param {Float} expected * @param {Float} maxDifference (the maximum inclusive difference allowed between the actual and expected numbers) * @param {string} [message] Defaults to structured message + * @returns {undefined} */ function close (actual, expected, maxDifference, message) { const actualDiff = (actual === expected) ? 0 : Math.abs(actual - expected), @@ -20,12 +21,13 @@ function close (actual, expected, maxDifference, message) { * Checks that the first two arguments are equal, or are numbers close enough to be considered equal * based on a specified maximum allowable difference percentage. * - * @example assert.close.percent(155, 150, 3.4); // Difference is ~3.33% + * @example assert.close.percent(155, 150, 3.4); // Difference is ~3.33% * * @param {Float} actual * @param {Float} expected * @param {Float} maxPercentDifference (the maximum inclusive difference percentage allowed between the actual and expected numbers) * @param {string} [message] Defaults to a structured message + * @returns {undefined} */ function closePercent (actual, expected, maxPercentDifference, message) { let actualDiff, result; @@ -55,6 +57,7 @@ function closePercent (actual, expected, maxPercentDifference, message) { * @param {Float} expected * @param {Float} minDifference (the minimum exclusive difference allowed between the actual and expected numbers) * @param {string} [message] Defaults to structured message + * @returns {undefined} */ function notClose (actual, expected, minDifference, message) { const actualDiff = Math.abs(actual - expected), @@ -67,12 +70,13 @@ function notClose (actual, expected, minDifference, message) { * Checks that the first two arguments are numbers with differences greater than the specified * minimum difference percentage. * - * @example assert.notClose.percent(156, 150, 3.5); // Difference is 4.0% + * @example assert.notClose.percent(156, 150, 3.5); // Difference is 4.0% * * @param {Float} actual * @param {Float} expected * @param {Float} minPercentDifference (the minimum exclusive difference percentage allowed between the actual and expected numbers) * @param {string} [message] Defaults to a structured message + * @returns {undefined} */ function notClosePercent (actual, expected, minPercentDifference, message) { let actualDiff, result; @@ -92,6 +96,10 @@ function notClosePercent (actual, expected, minPercentDifference, message) { this.pushResult({result, actual, expected, message}); } +/** + * @param {external:qunit} QUnit + * @returns {external:qunit} The same instance passed in after extending + */ export default function extend (QUnit) { QUnit.extend(QUnit.assert, { close, diff --git a/test/qunit/qunit-assert-expectOutOfBoundsException.js b/test/qunit/qunit-assert-expectOutOfBoundsException.js index 20d911c3..895eec2a 100644 --- a/test/qunit/qunit-assert-expectOutOfBoundsException.js +++ b/test/qunit/qunit-assert-expectOutOfBoundsException.js @@ -1,3 +1,10 @@ +/** + * Expects an out of bounds `INDEX_SIZE_ERR` exception. + * @param {GenericObject} obj + * @param {GenericCallback} fn + * @param {Any} arg1 + * @returns {undefined} + */ function expectOutOfBoundsException (obj, fn, arg1) { const expected = true; const message = 'Caught an INDEX_SIZE_ERR exception'; @@ -10,9 +17,13 @@ function expectOutOfBoundsException (obj, fn, arg1) { } } const actual = result; - console.log('aaa', result, actual, expected); this.pushResult({result, actual, expected, message}); } + +/** + * @param {external:qunit} QUnit + * @returns {external:qunit} The same instance passed in after extending + */ export default function extend (QUnit) { QUnit.extend(QUnit.assert, { expectOutOfBoundsException diff --git a/test/recalculate_test.js b/test/recalculate_test.js index e7b86d5e..8b069d9d 100644 --- a/test/recalculate_test.js +++ b/test/recalculate_test.js @@ -20,6 +20,11 @@ const svg = document.createElementNS(NS.SVG, 'svg'); svgroot.append(svg); let elemId = 1; + +/** + * Initilize modules to set up the tests. + * @returns {undefined} + */ function setUp () { utilities.init( /** @@ -39,7 +44,7 @@ function setUp () { getGridSnapping () { return false; }, getDrawing () { return { - getNextId () { return '' + elemId++; } + getNextId () { return String(elemId++); } }; } } @@ -51,13 +56,17 @@ function setUp () { { getSVGRoot () { return svg; }, getStartTransform () { return ''; }, - setStartTransform () {} + setStartTransform () { /* */ } } ); } let elem; +/** + * Initialize for tests and set up `rect` element. + * @returns {undefined} + */ function setUpRect () { setUp(); elem = document.createElementNS(NS.SVG, 'rect'); @@ -68,6 +77,10 @@ function setUpRect () { svg.append(elem); } +/** + * Initialize for tests and set up `text` element with `tspan` child. + * @returns {undefined} + */ function setUpTextWithTspan () { setUp(); elem = document.createElementNS(NS.SVG, 'text'); @@ -84,6 +97,10 @@ function setUpTextWithTspan () { svg.append(elem); } +/** + * Tear down the tests (empty the svg element). + * @returns {undefined} + */ function tearDown () { while (svg.hasChildNodes()) { svg.firstChild.remove(); diff --git a/test/sanitize_test.js b/test/sanitize_test.js index 46589871..d7261964 100644 --- a/test/sanitize_test.js +++ b/test/sanitize_test.js @@ -15,7 +15,7 @@ QUnit.test('Test sanitizeSvg() strips ws from style attr', function (assert) { assert.expect(2); const rect = document.createElementNS(NS.SVG, 'rect'); - rect.setAttribute('style', 'stroke: blue ; stroke-width : 40;'); + rect.setAttribute('style', 'stroke: blue ;\t\tstroke-width :\t\t40;'); // sanitizeSvg() requires the node to have a parent and a document. svg.append(rect); sanitize.sanitizeSvg(rect); diff --git a/test/select_test.js b/test/select_test.js index 8f4e9523..9b7570dd 100644 --- a/test/select_test.js +++ b/test/select_test.js @@ -1,6 +1,6 @@ /* eslint-env qunit */ -import {NS} from '../editor/namespaces.js'; import * as select from '../editor/select.js'; +import {NS} from '../editor/namespaces.js'; // log function QUnit.log((details) => { @@ -23,16 +23,20 @@ const mockConfig = { */ const mockFactory = { createSVGElement (jsonMap) { - const elem = document.createElementNS(NS.SVG, jsonMap['element']); - for (const attr in jsonMap.attr) { - elem.setAttribute(attr, jsonMap.attr[attr]); - } + const elem = document.createElementNS(NS.SVG, jsonMap.element); + Object.entries(jsonMap.attr).forEach(([attr, value]) => { + elem.setAttribute(attr, value); + }); return elem; }, svgRoot () { return svgroot; }, svgContent () { return svgcontent; } }; +/** + * Potentially reusable test set-up. + * @returns {undefined} + */ function setUp () { svgroot = mockFactory.createSVGElement({ element: 'svg', @@ -66,6 +70,10 @@ function setUpWithInit () { } */ +/** + * Tear down the test by emptying our sandbox area. + * @returns {undefined} + */ function tearDown () { while (sandbox.hasChildNodes()) { sandbox.firstChild.remove(); @@ -81,10 +89,10 @@ QUnit.test('Test svgedit.select package', function (assert) { assert.ok(select.init); assert.ok(select.getSelectorManager); assert.equal(typeof select, typeof {}); - assert.equal(typeof select.Selector, typeof function () {}); - assert.equal(typeof select.SelectorManager, typeof function () {}); - assert.equal(typeof select.init, typeof function () {}); - assert.equal(typeof select.getSelectorManager, typeof function () {}); + assert.equal(typeof select.Selector, typeof function () { /* */ }); + assert.equal(typeof select.SelectorManager, typeof function () { /* */ }); + assert.equal(typeof select.init, typeof function () { /* */ }); + assert.equal(typeof select.getSelectorManager, typeof function () { /* */ }); }); QUnit.test('Test Selector DOM structure', function (assert) { diff --git a/test/sinon/sinon-qunit.js b/test/sinon/sinon-qunit.js index d719de78..bf7637de 100644 --- a/test/sinon/sinon-qunit.js +++ b/test/sinon/sinon-qunit.js @@ -1,6 +1,20 @@ // Adapted from https://www.npmjs.com/package/sinon-test -export default function ({sinon, QUnit}) { +/** + * @external QUnit + */ +/** + * @external sinon + */ + +/** + * Adds methods to Sinon using a QUnit implementation. + * @param {PlainObject} implementations + * @param {external:sinon} implementations.sinon + * @param {external:QUnit} implementations.QUnit + * @returns {undefined} + */ +export default function sinonQunit ({sinon, QUnit}) { sinon.assert.fail = function (msg) { QUnit.ok(false, msg); }; @@ -10,7 +24,7 @@ export default function ({sinon, QUnit}) { }; const qTest = QUnit.test; - QUnit.test = function (testName, callback) { + QUnit.test = function (testName, callback) { // eslint-disable-line promise/prefer-await-to-callbacks return qTest(testName, sinon.test(callback)); }; } diff --git a/test/svgtransformlist_test.js b/test/svgtransformlist_test.js index a8732223..f2ce5691 100644 --- a/test/svgtransformlist_test.js +++ b/test/svgtransformlist_test.js @@ -21,6 +21,10 @@ QUnit.log((details) => { const svgroot = document.querySelector('#svgroot'); let svgcontent, rect, circle; +/** + * Set up tests, adding elements. + * @returns {undefined} + */ function setUp () { svgcontent = svgroot.appendChild(document.createElementNS(NS.SVG, 'svg')); rect = svgcontent.appendChild(document.createElementNS(NS.SVG, 'rect')); @@ -29,6 +33,10 @@ function setUp () { circle.id = 'c'; } +/** + * Tear down tests, emptying SVG root, and resetting list map. + * @returns {undefined} + */ function tearDown () { transformlist.resetListMap(); while (svgroot.hasChildNodes()) { @@ -82,7 +90,7 @@ QUnit.test('Test SVGTransformList.initialize()', function (assert) { const t = svgcontent.createSVGTransform(); assert.ok(t); assert.ok(rxform.initialize); - assert.equal(typeof rxform.initialize, typeof function () {}); + assert.equal(typeof rxform.initialize, typeof function () { /* */ }); rxform.initialize(t); assert.equal(rxform.numberOfItems, 1); assert.equal(cxform.numberOfItems, 0); @@ -110,8 +118,8 @@ QUnit.test('Test SVGTransformList.appendItem() and getItem()', function (assert) assert.ok(rxform.appendItem); assert.ok(rxform.getItem); - assert.equal(typeof rxform.appendItem, typeof function () {}); - assert.equal(typeof rxform.getItem, typeof function () {}); + assert.equal(typeof rxform.appendItem, typeof function () { /* */ }); + assert.equal(typeof rxform.getItem, typeof function () { /* */ }); rxform.appendItem(t1); rxform.appendItem(t2); @@ -145,7 +153,7 @@ QUnit.test('Test SVGTransformList.removeItem()', function (assert) { const t1 = svgcontent.createSVGTransform(), t2 = svgcontent.createSVGTransform(); assert.ok(rxform.removeItem); - assert.equal(typeof rxform.removeItem, typeof function () {}); + assert.equal(typeof rxform.removeItem, typeof function () { /* */ }); rxform.appendItem(t1); rxform.appendItem(t2); @@ -168,7 +176,7 @@ QUnit.test('Test SVGTransformList.replaceItem()', function (assert) { const cxform = transformlist.getTransformList(circle); assert.ok(rxform.replaceItem); - assert.equal(typeof rxform.replaceItem, typeof function () {}); + assert.equal(typeof rxform.replaceItem, typeof function () { /* */ }); const t1 = svgcontent.createSVGTransform(), t2 = svgcontent.createSVGTransform(), @@ -205,7 +213,7 @@ QUnit.test('Test SVGTransformList.insertItemBefore()', function (assert) { const cxform = transformlist.getTransformList(circle); assert.ok(rxform.insertItemBefore); - assert.equal(typeof rxform.insertItemBefore, typeof function () {}); + assert.equal(typeof rxform.insertItemBefore, typeof function () { /* */ }); const t1 = svgcontent.createSVGTransform(), t2 = svgcontent.createSVGTransform(), diff --git a/test/test1.js b/test/test1.js index 2efffa02..30117dce 100644 --- a/test/test1.js +++ b/test/test1.js @@ -40,7 +40,8 @@ const svgCanvas = new SvgCanvas( extensions: ['ext-arrows.js', 'ext-connector.js', 'ext-eyedropper.js'], initTool: 'select', wireframe: false - }); + } +); const // svgroot = document.getElementById('svgroot'), @@ -188,7 +189,7 @@ QUnit.test('Test import math elements inside a foreignObject', function (assert) // see Bug https://bugs.webkit.org/show_bug.cgi?id=35042 const math = fo.firstChild; - assert.equal(!!math, true, 'Math element exists'); + assert.equal(Boolean(math), true, 'Math element exists'); assert.equal(math.nodeName, 'math', 'Math element has the proper nodeName'); assert.equal(math.getAttribute('id'), 'm', 'Math element has an id'); assert.equal(math.namespaceURI, 'http://www.w3.org/1998/Math/MathML', 'Preserved MathML namespace'); @@ -227,12 +228,13 @@ QUnit.test('Test importing SVG remaps IDs', function (assert) { /* const doc = */ svgCanvas.setSvgString( '' + - 'Layer 1' + - '' + - '' + - '' + - '' + - ''); + 'Layer 1' + + '' + + '' + + '' + + '' + + '' + ); svgCanvas.importSvgString( '' + diff --git a/test/ui-tests/accessibility.js b/test/ui-tests/accessibility.js new file mode 100644 index 00000000..c92fd545 --- /dev/null +++ b/test/ui-tests/accessibility.js @@ -0,0 +1,44 @@ +// https://github.com/DevExpress/testcafe +// https://devexpress.github.io/testcafe/documentation/test-api/ +// https://github.com/helen-dikareva/axe-testcafe +import axeCheck from 'axe-testcafe'; + +fixture`TestCafe Axe accessibility tests (Editor - no parameters)` + .page`http://localhost:8000/editor/svg-editor.html`; + +test('Editor - no parameters', async (t) => { + await axeCheck(t); // , axeContent, axeOptions: https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#api-name-axerun +}); + +fixture`TestCafe Axe accessibility tests (Editor - with all extensions)` + .page`http://localhost:8000/editor/svg-editor.html?extensions=ext-arrows.js,ext-closepath.js,ext-foreignobject.js,ext-helloworld.js,ext-mathjax.js,ext-php_savefile.js,ext-server_moinsave.js,ext-server_opensave.js,ext-webappfind.js,ext-xdomain-messaging.js`; + +test('Editor ES - with all extensions', async (t) => { + await axeCheck(t); // , axeContent, axeOptions: https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#api-name-axerun +}); + +/* eslint-disable qunit/no-commented-tests */ +// Waiting for https://github.com/DevExpress/testcafe-hammerhead/issues/1725 (also https://github.com/DevExpress/testcafe/issues/2734 ) +/** +fixture`TestCafe Axe accessibility tests (Editor ES - no parameters)` + .page`http://localhost:8000/editor/svg-editor-es.html`; + +test('Editor ES - no parameters', async t => { + await axeCheck(t); // , axeContent, axeOptions: https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#api-name-axerun +}); + +fixture`TestCafe Axe accessibility tests (Editor ES - with all extensions)` + .page`http://localhost:8000/editor/svg-editor-es.html?extensions=ext-arrows.js,ext-closepath.js,ext-foreignobject.js,ext-helloworld.js,ext-mathjax.js,ext-php_savefile.js,ext-server_moinsave.js,ext-server_opensave.js,ext-webappfind.js,ext-xdomain-messaging.js`; + +test('Editor ES - with all extensions', async t => { + await axeCheck(t); // , axeContent, axeOptions: https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#api-name-axerun +}); + +fixture`TestCafe Axe accessibility tests (Embedded - no parameters)` + .page`http://localhost:8000/editor/embedapi.html`; + +test('Embedded - no parameters', async t => { + await axeCheck(t); // , axeContent, axeOptions: https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#api-name-axerun +}); +*/ +/* eslint-enable qunit/no-commented-tests */ diff --git a/test/ui-tests/ui.js b/test/ui-tests/ui.js new file mode 100644 index 00000000..6c15c01a --- /dev/null +++ b/test/ui-tests/ui.js @@ -0,0 +1,22 @@ +// https://github.com/DevExpress/testcafe +// https://devexpress.github.io/testcafe/documentation/test-api/ +// https://github.com/helen-dikareva/axe-testcafe +import {Selector} from 'testcafe'; + +fixture`TestCafe UI tests` + .page`http://localhost:8000/editor/svg-editor.html`; + +test('Editor - No parameters: Export button', async (t) => { + await t + .click('#dialog_buttons > input[type=button][value=OK]') + .click('#main_icon') + .expect(Selector('#tool_export')).ok('Has open button'); +}); + +test('Editor - No parameters: Export button clicking', async (t) => { + await t + .click('#dialog_buttons > input[type=button][value=OK]') + .click('#main_icon') + .click('#tool_export') + .expect(Selector('#dialog_content select')).ok('Export dialog opens'); +}); diff --git a/test/units_test.js b/test/units_test.js index cf386dc7..09248998 100644 --- a/test/units_test.js +++ b/test/units_test.js @@ -8,6 +8,10 @@ QUnit.log((details) => { } }); +/** + * Set up tests, supplying mock data. + * @returns {undefined} + */ function setUp () { units.init( /** @@ -35,7 +39,7 @@ QUnit.test('Test svgedit.units.shortFloat()', function (assert) { setUp(); assert.ok(units.shortFloat); - assert.equal(typeof units.shortFloat, typeof function () {}); + assert.equal(typeof units.shortFloat, typeof function () { /* */ }); const {shortFloat} = units; assert.equal(shortFloat(0.00000001), 0); @@ -51,7 +55,7 @@ QUnit.test('Test svgedit.units.isValidUnit()', function (assert) { setUp(); assert.ok(units.isValidUnit); - assert.equal(typeof units.isValidUnit, typeof function () {}); + assert.equal(typeof units.isValidUnit, typeof function () { /* */ }); const {isValidUnit} = units; assert.ok(isValidUnit('0')); @@ -79,7 +83,7 @@ QUnit.test('Test svgedit.units.convertUnit()', function (assert) { setUp(); assert.ok(units.convertUnit); - assert.equal(typeof units.convertUnit, typeof function () {}); + assert.equal(typeof units.convertUnit, typeof function () { /* */ }); // cm in default setup assert.equal(units.convertUnit(42), 1.1113); assert.equal(units.convertUnit(42, 'px'), 42); diff --git a/test/utilities_bbox_test.js b/test/utilities_bbox_test.js index c5ff45de..a436567c 100644 --- a/test/utilities_bbox_test.js +++ b/test/utilities_bbox_test.js @@ -16,14 +16,25 @@ QUnit.log((details) => { } }); +/** + * Create an SVG element for a mock. + * @param {module:utilities.SVGElementJSON} jsonMap + * @returns {SVGElement} + */ function mockCreateSVGElement (jsonMap) { - const elem = document.createElementNS(NS.SVG, jsonMap['element']); - for (const attr in jsonMap['attr']) { - elem.setAttribute(attr, jsonMap['attr'][attr]); - } + const elem = document.createElementNS(NS.SVG, jsonMap.element); + Object.entries(jsonMap.attr).forEach(([attr, value]) => { + elem.setAttribute(attr, value); + }); return elem; } let mockaddSVGElementFromJsonCallCount = 0; + +/** + * Mock of {@link module:utilities.EditorContext#addSVGElementFromJson}. + * @param {module:utilities.SVGElementJSON} json + * @returns {SVGElement} + */ function mockaddSVGElementFromJson (json) { const elem = mockCreateSVGElement(json); svgroot.append(elem); @@ -32,7 +43,7 @@ function mockaddSVGElementFromJson (json) { } const mockPathActions = { resetOrientation (pth) { - if (pth == null || pth.nodeName !== 'path') { return false; } + if (utilities.isNullish(pth) || pth.nodeName !== 'path') { return false; } const tlist = transformlist.getTransformList(pth); const m = math.transformListToTransform(tlist).matrix; tlist.clear(); @@ -57,6 +68,7 @@ const mockPathActions = { path.replacePathSeg(type, i, pts, pth); } // path.reorientGrads(pth, m); + return undefined; } }; @@ -75,8 +87,6 @@ QUnit.module('svgedit.utilities_bbox', { transformlist.resetListMap(); path.init(null); mockaddSVGElementFromJsonCallCount = 0; - }, - afterEach () { } }); @@ -167,7 +177,7 @@ QUnit.test('Test getBBoxWithTransform and a rotation transform', function (asser const rect = {x: 10, y: 10, width: 10, height: 20}; const angle = 45; - const origin = {x: 15, y: 20}; + const origin = {x: 15, y: 20}; // eslint-disable-line no-shadow elem = mockCreateSVGElement({ element: 'rect', attr: {id: 'rect2', x: rect.x, y: rect.y, width: rect.width, height: rect.height, transform: 'rotate(' + angle + ' ' + origin.x + ',' + origin.y + ')'} @@ -256,7 +266,7 @@ QUnit.test('Test getBBoxWithTransform with rotation and matrix transforms', func const rect = {x: 10, y: 10, width: 10, height: 20}; const angle = 45; - const origin = {x: 15, y: 20}; + const origin = {x: 15, y: 20}; // eslint-disable-line no-shadow tx = 10; // tx right ty = 10; // tx down txInRotatedSpace = Math.sqrt(tx * tx + ty * ty); // translate in rotated 45 space. @@ -443,10 +453,23 @@ QUnit.test('Test getStrokedBBox with no stroke-width attribute', function (asser g.remove(); }); +/** + * Returns radians for degrees. + * @param {Float} degrees + * @returns {Float} + */ function radians (degrees) { return degrees * Math.PI / 180; } -function rotatePoint (point, angle, origin) { + +/** + * + * @param {module:utilities.BBoxObject} point + * @param {Float} angle + * @param {module:math.XYObject} origin + * @returns {module:math.XYObject} + */ +function rotatePoint (point, angle, origin) { // eslint-disable-line no-shadow if (!origin) { origin = {x: 0, y: 0}; } @@ -458,7 +481,14 @@ function rotatePoint (point, angle, origin) { y: x * Math.sin(theta) + y * Math.cos(theta) + origin.y }; } -function rotateRect (rect, angle, origin) { +/** + * + * @param {module:utilities.BBoxObject} rect + * @param {Float} angle + * @param {module:math.XYObject} origin + * @returns {module:utilities.BBoxObject} + */ +function rotateRect (rect, angle, origin) { // eslint-disable-line no-shadow const tl = rotatePoint({x: rect.x, y: rect.y}, angle, origin); const tr = rotatePoint({x: rect.x + rect.width, y: rect.y}, angle, origin); const br = rotatePoint({x: rect.x + rect.width, y: rect.y + rect.height}, angle, origin); diff --git a/test/utilities_performance_test.js b/test/utilities_performance_test.js index 3796c13f..aa65a7a8 100644 --- a/test/utilities_performance_test.js +++ b/test/utilities_performance_test.js @@ -14,13 +14,24 @@ QUnit.log((details) => { const currentLayer = document.getElementById('layer1'); +/** + * Create an SVG element for a mock. + * @param {module:utilities.SVGElementJSON} jsonMap + * @returns {SVGElement} + */ function mockCreateSVGElement (jsonMap) { - const elem = document.createElementNS(NS.SVG, jsonMap['element']); - for (const attr in jsonMap['attr']) { - elem.setAttribute(attr, jsonMap['attr'][attr]); - } + const elem = document.createElementNS(NS.SVG, jsonMap.element); + Object.entries(jsonMap.attr).forEach(([attr, value]) => { + elem.setAttribute(attr, value); + }); return elem; } + +/** + * Mock of {@link module:utilities.EditorContext#addSVGElementFromJson}. + * @param {module:utilities.SVGElementJSON} json + * @returns {SVGElement} + */ function mockaddSVGElementFromJson (json) { const elem = mockCreateSVGElement(json); currentLayer.append(elem); @@ -31,27 +42,28 @@ function mockaddSVGElementFromJson (json) { const groupWithMatrixTransform = document.getElementById('svg_group_with_matrix_transform'); const textWithMatrixTransform = document.getElementById('svg_text_with_matrix_transform'); +/** + * Toward performance testing, fill document with clones of element. + * @param {SVGElement} elem + * @param {Integer} count + * @returns {undefined} + */ function fillDocumentByCloningElement (elem, count) { const elemId = elem.getAttribute('id') + '-'; for (let index = 0; index < count; index++) { const clone = elem.cloneNode(true); // t: deep clone // Make sure you set a unique ID like a real document. clone.setAttribute('id', elemId + index); - const parent = elem.parentNode; - parent.append(clone); + const {parentNode} = elem; + parentNode.append(clone); } } -QUnit.module('svgedit.utilities_performance', { - beforeEach () { - }, - afterEach () { - } -}); +QUnit.module('svgedit.utilities_performance'); const mockPathActions = { resetOrientation (path) { - if (path == null || path.nodeName !== 'path') { return false; } + if (utilities.isNullish(path) || path.nodeName !== 'path') { return false; } const tlist = transformlist.getTransformList(path); const m = math.transformListToTransform(tlist).matrix; tlist.clear(); @@ -64,10 +76,13 @@ const mockPathActions = { for (let i = 0; i < len; ++i) { const seg = segList.getItem(i); const type = seg.pathSegType; - if (type === 1) { continue; } + if (type === 1) { + continue; + } const pts = []; ['', 1, 2].forEach(function (n, j) { - const x = seg['x' + n], y = seg['y' + n]; + const x = seg['x' + n], + y = seg['y' + n]; if (x !== undefined && y !== undefined) { const pt = math.transformPoint(x, y, m); pts.splice(pts.length, 0, pt.x, pt.y); @@ -77,6 +92,7 @@ const mockPathActions = { } // utilities.reorientGrads(path, m); + return undefined; } }; @@ -89,27 +105,27 @@ const mockPathActions = { // Chrome // Before Optimization -// Pass1 svgCanvas.getStrokedBBox total ms 4,218, ave ms 41.0, min/max 37 51 -// Pass2 svgCanvas.getStrokedBBox total ms 4,458, ave ms 43.3, min/max 32 63 +// Pass1 svgCanvas.getStrokedBBox total ms 4,218, ave ms 41.0, min/max 37 51 +// Pass2 svgCanvas.getStrokedBBox total ms 4,458, ave ms 43.3, min/max 32 63 // Optimized Code -// Pass1 svgCanvas.getStrokedBBox total ms 1,112, ave ms 10.8, min/max 9 20 -// Pass2 svgCanvas.getStrokedBBox total ms 34, ave ms 0.3, min/max 0 20 +// Pass1 svgCanvas.getStrokedBBox total ms 1,112, ave ms 10.8, min/max 9 20 +// Pass2 svgCanvas.getStrokedBBox total ms 34, ave ms 0.3, min/max 0 20 // Firefox // Before Optimization -// Pass1 svgCanvas.getStrokedBBox total ms 3,794, ave ms 36.8, min/max 33 48 -// Pass2 svgCanvas.getStrokedBBox total ms 4,049, ave ms 39.3, min/max 28 53 +// Pass1 svgCanvas.getStrokedBBox total ms 3,794, ave ms 36.8, min/max 33 48 +// Pass2 svgCanvas.getStrokedBBox total ms 4,049, ave ms 39.3, min/max 28 53 // Optimized Code -// Pass1 svgCanvas.getStrokedBBox total ms 104, ave ms 1.0, min/max 0 23 -// Pass2 svgCanvas.getStrokedBBox total ms 71, ave ms 0.7, min/max 0 23 +// Pass1 svgCanvas.getStrokedBBox total ms 104, ave ms 1.0, min/max 0 23 +// Pass2 svgCanvas.getStrokedBBox total ms 71, ave ms 0.7, min/max 0 23 // Safari // Before Optimization -// Pass1 svgCanvas.getStrokedBBox total ms 4,840, ave ms 47.0, min/max 45 62 -// Pass2 svgCanvas.getStrokedBBox total ms 4,849, ave ms 47.1, min/max 34 62 +// Pass1 svgCanvas.getStrokedBBox total ms 4,840, ave ms 47.0, min/max 45 62 +// Pass2 svgCanvas.getStrokedBBox total ms 4,849, ave ms 47.1, min/max 34 62 // Optimized Code -// Pass1 svgCanvas.getStrokedBBox total ms 42, ave ms 0.4, min/max 0 23 -// Pass2 svgCanvas.getStrokedBBox total ms 17, ave ms 0.2, min/max 0 23 +// Pass1 svgCanvas.getStrokedBBox total ms 42, ave ms 0.4, min/max 0 23 +// Pass2 svgCanvas.getStrokedBBox total ms 17, ave ms 0.2, min/max 0 23 QUnit.test('Test svgCanvas.getStrokedBBox() performance with matrix transforms', function (assert) { const done = assert.async(); @@ -144,11 +160,11 @@ QUnit.test('Test svgCanvas.getStrokedBBox() performance with matrix transforms', // The second pass is two to ten times faster. setTimeout(function () { - const count = children.length; + const ct = children.length; - const start = lastTime = now = Date.now(); + const strt = lastTime = now = Date.now(); // Skip the first child which is the title. - for (let index = 1; index < count; index++) { + for (let index = 1; index < ct; index++) { const child = children[index]; /* const obj = */ getStrokedBBox([child], mockaddSVGElementFromJson, mockPathActions); now = Date.now(); const delta = now - lastTime; lastTime = now; @@ -157,10 +173,10 @@ QUnit.test('Test svgCanvas.getStrokedBBox() performance with matrix transforms', max = Math.max(max, delta); } - total = lastTime - start; - const ave = total / count; - assert.ok(ave < 2, 'svgedit.utilities.getStrokedBBox average execution time is less than 1 ms'); - console.log('Pass2 svgCanvas.getStrokedBBox total ms ' + total + ', ave ms ' + ave.toFixed(1) + ',\t min/max ' + min + ' ' + max); + total = lastTime - strt; + const avg = total / ct; + assert.ok(avg < 2, 'svgedit.utilities.getStrokedBBox average execution time is less than 1 ms'); + console.log('Pass2 svgCanvas.getStrokedBBox total ms ' + total + ', ave ms ' + avg.toFixed(1) + ',\t min/max ' + min + ' ' + max); done(); }); diff --git a/test/utilities_test.js b/test/utilities_test.js index 384cc79c..c70b0935 100644 --- a/test/utilities_test.js +++ b/test/utilities_test.js @@ -1,8 +1,8 @@ /* eslint-env qunit */ -import {NS} from '../editor/namespaces.js'; -import * as utilities from '../editor/utilities.js'; import * as browser from '../editor/browser.js'; +import * as utilities from '../editor/utilities.js'; +import {NS} from '../editor/namespaces.js'; // log function QUnit.log((details) => { @@ -11,19 +11,29 @@ QUnit.log((details) => { } }); +/** + * Create an element for test. + * @param {module:utilities.SVGElementJSON} jsonMap + * @returns {SVGElement} + */ function mockCreateSVGElement (jsonMap) { - const elem = document.createElementNS(NS.SVG, jsonMap['element']); - for (const attr in jsonMap['attr']) { - elem.setAttribute(attr, jsonMap['attr'][attr]); - } + const elem = document.createElementNS(NS.SVG, jsonMap.element); + Object.entries(jsonMap.attr).forEach(([attr, value]) => { + elem.setAttribute(attr, value); + }); return elem; } +/** + * Adds SVG Element per parameters and appends to root. + * @param {module:utilities.SVGElementJSON} json + * @returns {SVGElement} + */ function mockaddSVGElementFromJson (json) { const elem = mockCreateSVGElement(json); svgroot.append(elem); return elem; } -const mockPathActions = {resetOrientation () {}}; +const mockPathActions = {resetOrientation () { /* */ }}; let mockHistorySubCommands = []; const mockHistory = { BatchCommand: class { @@ -34,7 +44,8 @@ const mockHistory = { } }, RemoveElementCommand: class { - constructor (elem, nextSibling, parent) { // Longhand needed since used as a constructor + // Longhand needed since used as a constructor + constructor (elem, nextSibling, parent) { this.elem = elem; this.nextSibling = nextSibling; this.parent = parent; @@ -51,9 +62,28 @@ const mockCount = { addToSelection: 0, addCommandToHistory: 0 }; -function mockClearSelection () { mockCount.clearSelection++; } -function mockAddToSelection () { mockCount.addToSelection++; } -function mockAddCommandToHistory () { mockCount.addCommandToHistory++; } + +/** + * Increments clear seleciton count for mock test. + * @returns {undefined} + */ +function mockClearSelection () { + mockCount.clearSelection++; +} +/** +* Increments add selection count for mock test. + * @returns {undefined} + */ +function mockAddToSelection () { + mockCount.addToSelection++; +} +/** +* Increments add command to history count for mock test. + * @returns {undefined} + */ +function mockAddCommandToHistory () { + mockCount.addCommandToHistory++; +} const svg = document.createElementNS(NS.SVG, 'svg'); const sandbox = document.getElementById('sandbox'); @@ -70,8 +100,7 @@ QUnit.module('svgedit.utilities', { mockCount.addToSelection = 0; mockCount.addCommandToHistory = 0; }, - afterEach () { - } + afterEach () { /* */ } }); QUnit.test('Test svgedit.utilities package', function (assert) { @@ -79,7 +108,7 @@ QUnit.test('Test svgedit.utilities package', function (assert) { assert.ok(utilities); assert.ok(utilities.toXml); - assert.equal(typeof utilities.toXml, typeof function () {}); + assert.equal(typeof utilities.toXml, typeof function () { /* */ }); }); QUnit.test('Test svgedit.utilities.toXml() function', function (assert) { @@ -169,7 +198,7 @@ QUnit.test('Test getPathBBox', function (assert) { assert.expect(3); const doc = utilities.text2xml(''); const path = doc.createElementNS(NS.SVG, 'path'); - path.setAttributeNS(null, 'd', 'm0,0l5,0l0,5l-5,0l0,-5z'); + path.setAttribute('d', 'm0,0l5,0l0,5l-5,0l0,-5z'); const bb = utilities.getPathBBox(path); assert.equal(typeof bb, 'object', 'BBox returned object'); assert.ok(bb.x && !isNaN(bb.x)); @@ -181,7 +210,7 @@ QUnit.test('Test getPathDFromSegments', function (assert) { const doc = utilities.text2xml(''); const path = doc.createElementNS(NS.SVG, 'path'); - path.setAttributeNS(null, 'd', 'm0,0l5,0l0,5l-5,0l0,-5z'); + path.setAttribute('d', 'm0,0l5,0l0,5l-5,0l0,-5z'); let d = getPathDFromSegments([ ['M', [1, 2]], ['Z', []] @@ -227,7 +256,7 @@ QUnit.test('Test getPathDFromElement', function (assert) { attr: {id: 'roundrect', x: '0', y: '1', rx: '2', ry: '3', width: '10', height: '11'} }); svgroot.append(elem); - const closeEnough = new RegExp('M0,4 C0,2.3[0-9]* 0.9[0-9]*,1 2,1 L8,1 C9.0[0-9]*,1 10,2.3[0-9]* 10,4 L10,9 C10,10.6[0-9]* 9.08675799086758,12 8,12 L2,12 C0.9[0-9]*,12 0,10.6[0-9]* 0,9 L0,4 Z'); + const closeEnough = new RegExp('M0,4 C0,2.3\\d* 0.9\\d*,1 2,1 L8,1 C9.0\\d*,1 10,2.3\\d* 10,4 L10,9 C10,10.6\\d* 9.08675799086758,12 8,12 L2,12 C0.9\\d*,12 0,10.6\\d* 0,9 L0,4 Z'); assert.equal(closeEnough.test(getPathDFromElement(elem)), true); elem.remove(); @@ -259,6 +288,10 @@ QUnit.test('Test getPathDFromElement', function (assert) { }); QUnit.test('Test getBBoxOfElementAsPath', function (assert) { + /** + * Wrap `utilities.getBBoxOfElementAsPath` to convert bbox to object for testing. + * @implements {module:utilities.getBBoxOfElementAsPath} + */ function getBBoxOfElementAsPath (elem, addSVGElementFromJson, pathActions) { const bbox = utilities.getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions); return utilities.bboxToObj(bbox); // need this for assert.equal() to work.