From 8c9e40d349e28341fe69f940f644d580b070bbc4 Mon Sep 17 00:00:00 2001 From: Brett Zamir Date: Tue, 22 May 2018 18:03:16 +0800 Subject: [PATCH] - 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) - 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) - Fix: Zoom when scrolled; incorporates #169 (@AndrolGenhald), adapting for conventions; also allow avoidance when shift key pressed - Fix: Update Atom feed reference in HTML - Fixes related to recent commits: Some path and method name fixes needed, function order, missing methods, variable scope declaration, no need for DOMContentLoaded listeners in modules, switch back to non-default export, avoid trimming nullish, deal with mock tests, fix `math.matrixMultiply`, use jquery-svg where needed for array/SVG attributes; add babel-polyfill and defer script to imagelib; other misc. fixes - Enhancement: Move config-sample.js out of `editor` directory - Enhancement: For `callback`-style extensions, also provide config object; add following to that object: buildCanvgCallback, canvg, decode64, encode64, executeAfterLoads, getTypeMap, isChrome, ieIE, NS, text2xml - Enhancement: Complete ES6 modules work (extensions, locales, tests), along with Babel; make Node build routine for converting modular source to non-modular, use `loadStylesheets` for modular stylehsheet 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). - 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) - Docs: Remove "dependencies" comments in code except where summarizing role of jQuery or a non-obvious dependency - Refactoring/Linting: Enfore `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 - 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 - npm: Update devDeps - npm: Add html modules and config build to test script --- .babelrc | 13 + .eslintignore | 16 +- .eslintrc | 13 +- .gitignore | 12 +- .npmignore | 4 + build-html.js | 49 + dist/extensions/ext-arrows.js | 299 + dist/extensions/ext-closepath.js | 97 + dist/extensions/ext-connector.js | 615 + dist/extensions/ext-eyedropper.js | 127 + dist/extensions/ext-foreignobject.js | 272 + dist/extensions/ext-grid.js | 168 + dist/extensions/ext-helloworld.js | 83 + dist/extensions/ext-imagelib.js | 395 + dist/extensions/ext-markers.js | 600 + dist/extensions/ext-mathjax.js | 208 + dist/extensions/ext-overview_window.js | 152 + dist/extensions/ext-panning.js | 50 + dist/extensions/ext-php_savefile.js | 28 + dist/extensions/ext-polygon.js | 275 + dist/extensions/ext-server_moinsave.js | 63 + dist/extensions/ext-server_opensave.js | 232 + dist/extensions/ext-shapes.js | 349 + dist/extensions/ext-star.js | 246 + dist/extensions/ext-storage.js | 274 + dist/extensions/ext-webappfind.js | 70 + dist/extensions/ext-xdomain-messaging.js | 54 + dist/extensions/imagelib/index.js | 67 + dist/index-es.js | 30727 +++++++++++++++ dist/index-es.min.js | 2 + dist/index-es.min.js.map | 1 + dist/index-umd.js | 30735 ++++++++++++++++ dist/index-umd.min.js | 2 + dist/index-umd.min.js.map | 1 + dist/locale/lang.af.js | 247 + dist/locale/lang.ar.js | 247 + dist/locale/lang.az.js | 247 + dist/locale/lang.be.js | 247 + dist/locale/lang.bg.js | 247 + dist/locale/lang.ca.js | 247 + dist/locale/lang.cs.js | 247 + dist/locale/lang.cy.js | 247 + dist/locale/lang.da.js | 247 + dist/locale/lang.de.js | 247 + dist/locale/lang.el.js | 247 + dist/locale/lang.en.js | 248 + dist/locale/lang.es.js | 247 + dist/locale/lang.et.js | 247 + dist/locale/lang.fa.js | 240 + dist/locale/lang.fi.js | 247 + dist/locale/lang.fr.js | 247 + dist/locale/lang.fy.js | 247 + dist/locale/lang.ga.js | 247 + dist/locale/lang.gl.js | 247 + dist/locale/lang.he.js | 247 + dist/locale/lang.hi.js | 247 + dist/locale/lang.hr.js | 247 + dist/locale/lang.hu.js | 247 + dist/locale/lang.hy.js | 247 + dist/locale/lang.id.js | 247 + dist/locale/lang.is.js | 247 + dist/locale/lang.it.js | 247 + dist/locale/lang.ja.js | 247 + dist/locale/lang.ko.js | 247 + dist/locale/lang.lt.js | 247 + dist/locale/lang.lv.js | 247 + dist/locale/lang.mk.js | 247 + dist/locale/lang.ms.js | 247 + dist/locale/lang.mt.js | 247 + dist/locale/lang.nl.js | 247 + dist/locale/lang.no.js | 247 + dist/locale/lang.pl.js | 248 + dist/locale/lang.pt-BR.js | 246 + dist/locale/lang.pt-PT.js | 247 + dist/locale/lang.ro.js | 246 + dist/locale/lang.ru.js | 247 + dist/locale/lang.sk.js | 247 + dist/locale/lang.sl.js | 246 + dist/locale/lang.sq.js | 247 + dist/locale/lang.sr.js | 247 + dist/locale/lang.sv.js | 247 + dist/locale/lang.sw.js | 247 + dist/locale/lang.test.js | 247 + dist/locale/lang.th.js | 247 + dist/locale/lang.tl.js | 247 + dist/locale/lang.tr.js | 247 + dist/locale/lang.uk.js | 247 + dist/locale/lang.vi.js | 247 + dist/locale/lang.yi.js | 247 + dist/locale/lang.zh-CN.js | 247 + dist/locale/lang.zh-HK.js | 247 + dist/locale/lang.zh-TW.js | 247 + dist/redirect-on-lacking-support.js | 2100 ++ docs/ConfigOptions.md | 15 +- docs/ExtensionDocs.md | 8 +- editor/browser.js | 8 +- editor/canvg/canvg.js | 18 +- editor/contextmenu.js | 6 +- editor/contextmenu/jquery.contextMenu.js | 4 +- editor/coords.js | 3 - editor/draw.js | 267 +- editor/embedapi-dom.js | 129 +- editor/extensions/ext-arrows.js | 13 +- editor/extensions/ext-closepath.js | 7 +- editor/extensions/ext-connector.js | 40 +- editor/extensions/ext-eyedropper.js | 13 +- editor/extensions/ext-foreignobject.js | 28 +- editor/extensions/ext-grid.js | 16 +- editor/extensions/ext-helloworld.js | 7 +- editor/extensions/ext-imagelib.js | 44 +- editor/extensions/ext-markers.js | 49 +- editor/extensions/ext-mathjax.js | 23 +- editor/extensions/ext-overview_window.js | 9 +- editor/extensions/ext-panning.js | 5 +- editor/extensions/ext-php_savefile.js | 5 +- editor/extensions/ext-polygon.js | 32 +- editor/extensions/ext-server_moinsave.js | 13 +- editor/extensions/ext-server_opensave.js | 21 +- editor/extensions/ext-shapes.js | 84 +- editor/extensions/ext-star.js | 36 +- editor/extensions/ext-storage.js | 10 +- editor/extensions/ext-webappfind.js | 4 +- editor/extensions/ext-xdomain-messaging.js | 3 +- editor/extensions/imagelib/index-es.html | 19 + editor/extensions/imagelib/index.html | 6 +- editor/external/babel-polyfill/polyfill.js | 7574 ++++ .../external/babel-polyfill/polyfill.min.js | 4 + .../dynamic-import-polyfill/importModule.js | 66 + editor/external/load-stylesheets/index-es.js | 80 + editor/history.js | 6 +- editor/jgraduate/jpicker.js | 443 +- editor/jgraduate/jpicker.min.js | 1 - editor/jgraduate/jquery.jgraduate.js | 19 +- editor/jgraduate/jquery.jgraduate.min.js | 1 - editor/jquery-svg.js | 11 +- editor/jspdf/jspdf.plugin.svgToPdf.js | 1 + editor/locale/lang.af.js | 2 +- editor/locale/lang.ar.js | 2 +- editor/locale/lang.az.js | 2 +- editor/locale/lang.be.js | 2 +- editor/locale/lang.bg.js | 2 +- editor/locale/lang.ca.js | 2 +- editor/locale/lang.cs.js | 2 +- editor/locale/lang.cy.js | 2 +- editor/locale/lang.da.js | 2 +- editor/locale/lang.de.js | 2 +- editor/locale/lang.el.js | 2 +- editor/locale/lang.en.js | 2 +- editor/locale/lang.es.js | 2 +- editor/locale/lang.et.js | 2 +- editor/locale/lang.fa.js | 2 +- editor/locale/lang.fi.js | 2 +- editor/locale/lang.fr.js | 2 +- editor/locale/lang.fy.js | 2 +- editor/locale/lang.ga.js | 2 +- editor/locale/lang.gl.js | 2 +- editor/locale/lang.he.js | 2 +- editor/locale/lang.hi.js | 2 +- editor/locale/lang.hr.js | 2 +- editor/locale/lang.hu.js | 2 +- editor/locale/lang.hy.js | 2 +- editor/locale/lang.id.js | 2 +- editor/locale/lang.is.js | 2 +- editor/locale/lang.it.js | 2 +- editor/locale/lang.ja.js | 2 +- editor/locale/lang.ko.js | 2 +- editor/locale/lang.lt.js | 2 +- editor/locale/lang.lv.js | 2 +- editor/locale/lang.mk.js | 2 +- editor/locale/lang.ms.js | 2 +- editor/locale/lang.mt.js | 2 +- editor/locale/lang.nl.js | 2 +- editor/locale/lang.no.js | 2 +- editor/locale/lang.pl.js | 2 +- editor/locale/lang.pt-BR.js | 2 +- editor/locale/lang.pt-PT.js | 2 +- editor/locale/lang.ro.js | 2 +- editor/locale/lang.ru.js | 2 +- editor/locale/lang.sk.js | 2 +- editor/locale/lang.sl.js | 2 +- editor/locale/lang.sq.js | 2 +- editor/locale/lang.sr.js | 2 +- editor/locale/lang.sv.js | 2 +- editor/locale/lang.sw.js | 2 +- editor/locale/lang.test.js | 2 +- editor/locale/lang.th.js | 2 +- editor/locale/lang.tl.js | 2 +- editor/locale/lang.tr.js | 2 +- editor/locale/lang.uk.js | 2 +- editor/locale/lang.vi.js | 2 +- editor/locale/lang.yi.js | 2 +- editor/locale/lang.zh-CN.js | 2 +- editor/locale/lang.zh-HK.js | 2 +- editor/locale/lang.zh-TW.js | 2 +- editor/locale/locale.js | 32 +- editor/math.js | 8 +- editor/path.js | 1175 +- editor/pathseg.js | 122 +- editor/recalculate.js | 7 +- editor/sanitize.js | 137 +- editor/select.js | 57 +- editor/spinbtn/JQuerySpinBtn.js | 7 + editor/spinbtn/JQuerySpinBtn.min.js | 1 - editor/svg-editor-es.html | 766 + editor/svg-editor.html | 1183 +- editor/svg-editor.js | 259 +- editor/svg-editor.manifest | 8 +- editor/svgcanvas.js | 2007 +- editor/svgedit.js | 2 +- editor/svgicons/jquery.svgicons.js | 10 +- editor/svgtransformlist.js | 299 +- editor/svgutils.js | 331 +- editor/units.js | 48 +- package-lock.json | 3458 +- package.json | 34 +- rollup-config.config.js | 32 + rollup.config.js | 136 + ...g-sample.js => svgedit-config-sample-es.js | 30 +- test/all_tests.html | 45 +- test/all_tests.js | 4 +- test/contextmenu_test.html | 9 +- test/contextmenu_test.js | 58 +- test/coords_test.html | 16 +- test/coords_test.js | 152 +- test/draw_test.html | 19 +- test/draw_test.js | 707 +- test/history_test.html | 12 +- test/history_test.js | 501 +- test/jquery-svg_test.html | 6 +- test/jquery-svg_test.js | 4 +- test/math_test.html | 8 +- test/math_test.js | 111 +- test/path_test.html | 13 +- test/path_test.js | 233 +- test/qunit/qunit-assert-almostEquals.js | 18 + test/qunit/qunit-assert-close.js | 69 +- ...qunit-assert-expectOutOfBoundsException.js | 21 + test/qunit/qunit.css | 197 - test/qunit/qunit.js | 1415 - test/recalculate_test.html | 19 +- test/recalculate_test.js | 66 +- test/sanitize_test.html | 13 +- test/sanitize_test.js | 21 +- test/select_test.html | 12 +- test/select_test.js | 91 +- test/sinon/sinon-1.17.3.js | 6437 ---- test/sinon/sinon-qunit-1.0.0.js | 62 - test/sinon/sinon-qunit.js | 16 + test/svgtransformlist_test.html | 15 +- test/svgtransformlist_test.js | 350 +- test/svgutils_bbox_test.html | 16 +- test/svgutils_bbox_test.js | 342 +- test/svgutils_performance_test.html | 15 +- test/svgutils_performance_test.js | 49 +- test/svgutils_test.html | 13 +- test/svgutils_test.js | 315 +- test/test1.html | 27 +- test/test1.js | 116 +- test/units_test.html | 14 +- test/units_test.js | 90 +- 260 files changed, 100462 insertions(+), 13388 deletions(-) create mode 100644 .babelrc create mode 100644 build-html.js create mode 100644 dist/extensions/ext-arrows.js create mode 100644 dist/extensions/ext-closepath.js create mode 100644 dist/extensions/ext-connector.js create mode 100644 dist/extensions/ext-eyedropper.js create mode 100644 dist/extensions/ext-foreignobject.js create mode 100644 dist/extensions/ext-grid.js create mode 100644 dist/extensions/ext-helloworld.js create mode 100644 dist/extensions/ext-imagelib.js create mode 100644 dist/extensions/ext-markers.js create mode 100644 dist/extensions/ext-mathjax.js create mode 100644 dist/extensions/ext-overview_window.js create mode 100644 dist/extensions/ext-panning.js create mode 100644 dist/extensions/ext-php_savefile.js create mode 100644 dist/extensions/ext-polygon.js create mode 100644 dist/extensions/ext-server_moinsave.js create mode 100644 dist/extensions/ext-server_opensave.js create mode 100644 dist/extensions/ext-shapes.js create mode 100644 dist/extensions/ext-star.js create mode 100644 dist/extensions/ext-storage.js create mode 100644 dist/extensions/ext-webappfind.js create mode 100644 dist/extensions/ext-xdomain-messaging.js create mode 100644 dist/extensions/imagelib/index.js create mode 100644 dist/index-es.js create mode 100644 dist/index-es.min.js create mode 100644 dist/index-es.min.js.map create mode 100644 dist/index-umd.js create mode 100644 dist/index-umd.min.js create mode 100644 dist/index-umd.min.js.map create mode 100644 dist/locale/lang.af.js create mode 100644 dist/locale/lang.ar.js create mode 100644 dist/locale/lang.az.js create mode 100644 dist/locale/lang.be.js create mode 100644 dist/locale/lang.bg.js create mode 100644 dist/locale/lang.ca.js create mode 100644 dist/locale/lang.cs.js create mode 100644 dist/locale/lang.cy.js create mode 100644 dist/locale/lang.da.js create mode 100644 dist/locale/lang.de.js create mode 100644 dist/locale/lang.el.js create mode 100644 dist/locale/lang.en.js create mode 100644 dist/locale/lang.es.js create mode 100644 dist/locale/lang.et.js create mode 100644 dist/locale/lang.fa.js create mode 100644 dist/locale/lang.fi.js create mode 100644 dist/locale/lang.fr.js create mode 100644 dist/locale/lang.fy.js create mode 100644 dist/locale/lang.ga.js create mode 100644 dist/locale/lang.gl.js create mode 100644 dist/locale/lang.he.js create mode 100644 dist/locale/lang.hi.js create mode 100644 dist/locale/lang.hr.js create mode 100644 dist/locale/lang.hu.js create mode 100644 dist/locale/lang.hy.js create mode 100644 dist/locale/lang.id.js create mode 100644 dist/locale/lang.is.js create mode 100644 dist/locale/lang.it.js create mode 100644 dist/locale/lang.ja.js create mode 100644 dist/locale/lang.ko.js create mode 100644 dist/locale/lang.lt.js create mode 100644 dist/locale/lang.lv.js create mode 100644 dist/locale/lang.mk.js create mode 100644 dist/locale/lang.ms.js create mode 100644 dist/locale/lang.mt.js create mode 100644 dist/locale/lang.nl.js create mode 100644 dist/locale/lang.no.js create mode 100644 dist/locale/lang.pl.js create mode 100644 dist/locale/lang.pt-BR.js create mode 100644 dist/locale/lang.pt-PT.js create mode 100644 dist/locale/lang.ro.js create mode 100644 dist/locale/lang.ru.js create mode 100644 dist/locale/lang.sk.js create mode 100644 dist/locale/lang.sl.js create mode 100644 dist/locale/lang.sq.js create mode 100644 dist/locale/lang.sr.js create mode 100644 dist/locale/lang.sv.js create mode 100644 dist/locale/lang.sw.js create mode 100644 dist/locale/lang.test.js create mode 100644 dist/locale/lang.th.js create mode 100644 dist/locale/lang.tl.js create mode 100644 dist/locale/lang.tr.js create mode 100644 dist/locale/lang.uk.js create mode 100644 dist/locale/lang.vi.js create mode 100644 dist/locale/lang.yi.js create mode 100644 dist/locale/lang.zh-CN.js create mode 100644 dist/locale/lang.zh-HK.js create mode 100644 dist/locale/lang.zh-TW.js create mode 100644 dist/redirect-on-lacking-support.js create mode 100644 editor/extensions/imagelib/index-es.html create mode 100644 editor/external/babel-polyfill/polyfill.js create mode 100644 editor/external/babel-polyfill/polyfill.min.js create mode 100644 editor/external/dynamic-import-polyfill/importModule.js create mode 100644 editor/external/load-stylesheets/index-es.js delete mode 100644 editor/jgraduate/jpicker.min.js delete mode 100644 editor/jgraduate/jquery.jgraduate.min.js delete mode 100644 editor/spinbtn/JQuerySpinBtn.min.js create mode 100644 editor/svg-editor-es.html create mode 100644 rollup-config.config.js create mode 100644 rollup.config.js rename editor/config-sample.js => svgedit-config-sample-es.js (81%) create mode 100644 test/qunit/qunit-assert-almostEquals.js create mode 100644 test/qunit/qunit-assert-expectOutOfBoundsException.js delete mode 100644 test/qunit/qunit.css delete mode 100644 test/qunit/qunit.js delete mode 100644 test/sinon/sinon-1.17.3.js delete mode 100644 test/sinon/sinon-qunit-1.0.0.js create mode 100644 test/sinon/sinon-qunit.js diff --git a/.babelrc b/.babelrc new file mode 100644 index 00000000..9772b939 --- /dev/null +++ b/.babelrc @@ -0,0 +1,13 @@ +{ + "presets": [ + [ + "env", + { + "modules": false + } + ] + ], + "plugins": [ + "external-helpers" + ] +} diff --git a/.eslintignore b/.eslintignore index b86d5417..e7f9668d 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,15 +1,20 @@ node_modules +dist +svgedit-config-es.js +svgedit-config-iife.js +svgedit-config-sample-iife.js +svgedit-custom.css + # Vendor/minified files editor/jquery.min.js editor/jquery-ui -editor/jgraduate/jpicker.min.js -editor/jgraduate/jquery.jgraduate.min.js - +# Previously minified though exporting editor/jquerybbq + +# Previously minified though exporting editor/js-hotkeys -editor/spinbtn/JQuerySpinBtn.min.js editor/jspdf/jspdf.min.js editor/jspdf/underscore-min.js @@ -17,5 +22,4 @@ editor/jspdf/underscore-min.js editor/extensions/imagelib/jquery.min.js editor/extensions/mathjax -test/qunit -test/sinon +editor/external diff --git a/.eslintrc b/.eslintrc index e3c5a90d..cb7ad48d 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,11 +1,12 @@ { - "extends": "standard", + "extends": ["standard", "plugin:qunit/recommended"], "parserOptions": { - "sourceType": "module" + "sourceType": "module" }, + "plugins": ["qunit"], "env": { - "node": false, - "browser": true + "node": false, + "browser": true }, "rules": { "semi": [2, "always"], @@ -14,6 +15,8 @@ "object-property-newline": 0, "one-var": 0, "no-var": 2, - "prefer-const": 2 + "prefer-const": 2, + "no-extra-semi": 2, + "quote-props": [2, "as-needed"] } } diff --git a/.gitignore b/.gitignore index 957286bd..be8c1c67 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,11 @@ node_modules -# See editor/config-sample.js for an example -editor/config.js -editor/custom.css build/ -editor/svgedit.compiled.js + +# For examples, see +# svgedit-config-sample-es.js +# svgedit-config-sample-iife.js +svgedit-config-es.js +svgedit-config-iife.js + +svgedit-custom.css diff --git a/.npmignore b/.npmignore index 9daeafb9..970ab1d2 100644 --- a/.npmignore +++ b/.npmignore @@ -1 +1,5 @@ +docs +svgedit-config-es.js +svgedit-config-iife.js +screencasts test diff --git a/build-html.js b/build-html.js new file mode 100644 index 00000000..4eec2fa5 --- /dev/null +++ b/build-html.js @@ -0,0 +1,49 @@ +/* eslint-env node */ +const fs = require('fs'); +fs.readFile('editor/svg-editor-es.html', 'utf8', (err, data) => { + if (err) { + console.log('Error reading `svg-editor-es.html` file', err); + return; + } + data = data + .replace( + '', + ` +` + ).replace( + '', + '' + ).replace( + '', + '' + ); + fs.writeFile('editor/svg-editor.html', data, (err) => { + if (err) { + console.log('Error writing file', err); + return; + } + console.log('Completed file rewriting!'); + }); +}); +fs.readFile('editor/extensions/imagelib/index-es.html', 'utf8', (err, data) => { + if (err) { + console.log('Error reading `imagelib/index-es.html` file', err); + return; + } + data = data + .replace( + '', + ` +` + ).replace( + '', + '' + ); + fs.writeFile('editor/extensions/imagelib/index.html', data, (err) => { + if (err) { + console.log('Error writing file', err); + return; + } + console.log('Completed file rewriting!'); + }); +}); diff --git a/dist/extensions/ext-arrows.js b/dist/extensions/ext-arrows.js new file mode 100644 index 00000000..240a58fd --- /dev/null +++ b/dist/extensions/ext-arrows.js @@ -0,0 +1,299 @@ +(function () { + 'use strict'; + + /* globals jQuery */ + /* + * ext-arrows.js + * + * Licensed under the MIT License + * + * Copyright(c) 2010 Alexis Deveria + * + */ + + svgEditor.addExtension('Arrows', function (S) { + var svgCanvas = svgEditor.canvas; + var $ = jQuery; + // {svgcontent} = S, + var addElem = S.addSvgElementFromJson, + nonce = S.nonce, + langList = { + en: [{ id: 'arrow_none', textContent: 'No arrow' }], + fr: [{ id: 'arrow_none', textContent: 'Sans flèche' }] + }, + prefix = 'se_arrow_'; + + + var selElems = void 0, + arrowprefix = void 0, + randomizeIds = S.randomize_ids; + + function setArrowNonce(window, n) { + randomizeIds = true; + arrowprefix = prefix + n + '_'; + pathdata.fw.id = arrowprefix + 'fw'; + pathdata.bk.id = arrowprefix + 'bk'; + } + + function unsetArrowNonce(window) { + randomizeIds = false; + arrowprefix = prefix; + pathdata.fw.id = arrowprefix + 'fw'; + pathdata.bk.id = arrowprefix + 'bk'; + } + + svgCanvas.bind('setnonce', setArrowNonce); + svgCanvas.bind('unsetnonce', unsetArrowNonce); + + if (randomizeIds) { + arrowprefix = prefix + nonce + '_'; + } else { + arrowprefix = prefix; + } + + var pathdata = { + fw: { d: 'm0,0l10,5l-10,5l5,-5l-5,-5z', refx: 8, id: arrowprefix + 'fw' }, + bk: { d: 'm10,0l-10,5l10,5l-5,-5l5,-5z', refx: 2, id: arrowprefix + 'bk' } + }; + + function getLinked(elem, attr) { + var str = elem.getAttribute(attr); + if (!str) { + return null; + } + var m = str.match(/\(#(.*)\)/); + if (!m || m.length !== 2) { + return null; + } + return S.getElem(m[1]); + } + + function showPanel(on) { + $('#arrow_panel').toggle(on); + if (on) { + var el = selElems[0]; + var end = el.getAttribute('marker-end'); + var start = el.getAttribute('marker-start'); + var mid = el.getAttribute('marker-mid'); + var val = void 0; + if (end && start) { + val = 'both'; + } else if (end) { + val = 'end'; + } else if (start) { + val = 'start'; + } else if (mid) { + val = 'mid'; + if (mid.includes('bk')) { + val = 'mid_bk'; + } + } + + if (!start && !mid && !end) { + val = 'none'; + } + + $('#arrow_list').val(val); + } + } + + function resetMarker() { + var el = selElems[0]; + el.removeAttribute('marker-start'); + el.removeAttribute('marker-mid'); + el.removeAttribute('marker-end'); + } + + function addMarker(dir, type, id) { + // TODO: Make marker (or use?) per arrow type, since refX can be different + id = id || arrowprefix + dir; + + var data = pathdata[dir]; + + if (type === 'mid') { + data.refx = 5; + } + + var marker = S.getElem(id); + if (!marker) { + marker = addElem({ + element: 'marker', + attr: { + viewBox: '0 0 10 10', + id: id, + refY: 5, + markerUnits: 'strokeWidth', + markerWidth: 5, + markerHeight: 5, + orient: 'auto', + style: 'pointer-events:none' // Currently needed for Opera + } + }); + var arrow = addElem({ + element: 'path', + attr: { + d: data.d, + fill: '#000000' + } + }); + marker.appendChild(arrow); + S.findDefs().appendChild(marker); + } + + marker.setAttribute('refX', data.refx); + + return marker; + } + + function setArrow() { + resetMarker(); + + var type = this.value; + if (type === 'none') { + return; + } + + // Set marker on element + var dir = 'fw'; + if (type === 'mid_bk') { + type = 'mid'; + dir = 'bk'; + } else if (type === 'both') { + addMarker('bk', type); + svgCanvas.changeSelectedAttribute('marker-start', 'url(#' + pathdata.bk.id + ')'); + type = 'end'; + dir = 'fw'; + } else if (type === 'start') { + dir = 'bk'; + } + + addMarker(dir, type); + svgCanvas.changeSelectedAttribute('marker-' + type, 'url(#' + pathdata[dir].id + ')'); + S.call('changed', selElems); + } + + function colorChanged(elem) { + var color = elem.getAttribute('stroke'); + var mtypes = ['start', 'mid', 'end']; + var defs = S.findDefs(); + + $.each(mtypes, function (i, type) { + var marker = getLinked(elem, 'marker-' + type); + if (!marker) { + return; + } + + var curColor = $(marker).children().attr('fill'); + var curD = $(marker).children().attr('d'); + if (curColor === color) { + return; + } + + var allMarkers = $(defs).find('marker'); + var newMarker = null; + // Different color, check if already made + allMarkers.each(function () { + var attrs = $(this).children().attr(['fill', 'd']); + if (attrs.fill === color && attrs.d === curD) { + // Found another marker with this color and this path + newMarker = this; + } + }); + + if (!newMarker) { + // Create a new marker with this color + var lastId = marker.id; + var dir = lastId.includes('_fw') ? 'fw' : 'bk'; + + newMarker = addMarker(dir, type, arrowprefix + dir + allMarkers.length); + + $(newMarker).children().attr('fill', color); + } + + $(elem).attr('marker-' + type, 'url(#' + newMarker.id + ')'); + + // Check if last marker can be removed + var remove = true; + $(S.svgcontent).find('line, polyline, path, polygon').each(function () { + var elem = this; + $.each(mtypes, function (j, mtype) { + if ($(elem).attr('marker-' + mtype) === 'url(#' + marker.id + ')') { + remove = false; + return remove; + } + }); + if (!remove) { + return false; + } + }); + + // Not found, so can safely remove + if (remove) { + $(marker).remove(); + } + }); + } + + return { + name: 'Arrows', + context_tools: [{ + type: 'select', + panel: 'arrow_panel', + title: 'Select arrow type', + id: 'arrow_list', + options: { + none: 'No arrow', + end: '---->', + start: '<----', + both: '<--->', + mid: '-->--', + mid_bk: '--<--' + }, + defval: 'none', + events: { + change: setArrow + } + }], + callback: function callback() { + $('#arrow_panel').hide(); + // Set ID so it can be translated in locale file + $('#arrow_list option')[0].id = 'connector_no_arrow'; + }, + addLangData: function addLangData(lang) { + return { + data: langList[lang] + }; + }, + selectedChanged: function selectedChanged(opts) { + // Use this to update the current selected elements + selElems = opts.elems; + + var markerElems = ['line', 'path', 'polyline', 'polygon']; + var i = selElems.length; + while (i--) { + var elem = selElems[i]; + if (elem && markerElems.includes(elem.tagName)) { + if (opts.selectedElement && !opts.multiselected) { + showPanel(true); + } else { + showPanel(false); + } + } else { + showPanel(false); + } + } + }, + elementChanged: function elementChanged(opts) { + var elem = opts.elems[0]; + if (elem && (elem.getAttribute('marker-start') || elem.getAttribute('marker-mid') || elem.getAttribute('marker-end'))) { + // const start = elem.getAttribute('marker-start'); + // const mid = elem.getAttribute('marker-mid'); + // const end = elem.getAttribute('marker-end'); + // Has marker, so see if it should match color + colorChanged(elem); + } + } + }; + }); + +}()); diff --git a/dist/extensions/ext-closepath.js b/dist/extensions/ext-closepath.js new file mode 100644 index 00000000..c2644211 --- /dev/null +++ b/dist/extensions/ext-closepath.js @@ -0,0 +1,97 @@ +(function () { + 'use strict'; + + /* globals jQuery */ + /* + * ext-closepath.js + * + * Licensed under the MIT License + * + * Copyright(c) 2010 Jeff Schiller + * + */ + + // This extension adds a simple button to the contextual panel for paths + // The button toggles whether the path is open or closed + svgEditor.addExtension('ClosePath', function () { + var $ = jQuery; + var selElems = void 0; + var updateButton = function updateButton(path) { + var seglist = path.pathSegList, + closed = seglist.getItem(seglist.numberOfItems - 1).pathSegType === 1, + showbutton = closed ? '#tool_openpath' : '#tool_closepath', + hidebutton = closed ? '#tool_closepath' : '#tool_openpath'; + $(hidebutton).hide(); + $(showbutton).show(); + }; + var showPanel = function showPanel(on) { + $('#closepath_panel').toggle(on); + if (on) { + var path = selElems[0]; + if (path) { + updateButton(path); + } + } + }; + var toggleClosed = function toggleClosed() { + var path = selElems[0]; + if (path) { + var seglist = path.pathSegList, + last = seglist.numberOfItems - 1; + // is closed + if (seglist.getItem(last).pathSegType === 1) { + seglist.removeItem(last); + } else { + seglist.appendItem(path.createSVGPathSegClosePath()); + } + updateButton(path); + } + }; + + return { + name: 'ClosePath', + svgicons: svgEditor.curConfig.extIconsPath + 'closepath_icons.svg', + buttons: [{ + id: 'tool_openpath', + type: 'context', + panel: 'closepath_panel', + title: 'Open path', + events: { + click: function click() { + toggleClosed(); + } + } + }, { + id: 'tool_closepath', + type: 'context', + panel: 'closepath_panel', + title: 'Close path', + events: { + click: function click() { + toggleClosed(); + } + } + }], + callback: function callback() { + $('#closepath_panel').hide(); + }, + selectedChanged: function selectedChanged(opts) { + selElems = opts.elems; + var i = selElems.length; + while (i--) { + var elem = selElems[i]; + if (elem && elem.tagName === 'path') { + if (opts.selectedElement && !opts.multiselected) { + showPanel(true); + } else { + showPanel(false); + } + } else { + showPanel(false); + } + } + } + }; + }); + +}()); diff --git a/dist/extensions/ext-connector.js b/dist/extensions/ext-connector.js new file mode 100644 index 00000000..bfec9742 --- /dev/null +++ b/dist/extensions/ext-connector.js @@ -0,0 +1,615 @@ +(function () { + 'use strict'; + + /* globals jQuery */ + /* + * ext-connector.js + * + * Licensed under the MIT License + * + * Copyright(c) 2010 Alexis Deveria + * + */ + + svgEditor.addExtension('Connector', function (S) { + var $ = jQuery; + var svgCanvas = svgEditor.canvas; + var svgroot = S.svgroot, + getNextId = S.getNextId, + getElem = S.getElem, + curConfig = S.curConfig, + addElem = S.addSvgElementFromJson, + selManager = S.selectorManager, + connSel = '.se_connector', + elData = $.data; + var startX = void 0, + startY = void 0, + curLine = void 0, + startElem = void 0, + endElem = void 0, + seNs = void 0, + svgcontent = S.svgcontent, + started = false, + connections = [], + selElems = []; + + + var langList = { + en: [{ id: 'mode_connect', title: 'Connect two objects' }], + fr: [{ id: 'mode_connect', title: 'Connecter deux objets' }] + }; + + function getBBintersect(x, y, bb, offset) { + if (offset) { + offset -= 0; + bb = $.extend({}, bb); + bb.width += offset; + bb.height += offset; + bb.x -= offset / 2; + bb.y -= offset / 2; + } + + var midX = bb.x + bb.width / 2; + var midY = bb.y + bb.height / 2; + var lenX = x - midX; + var lenY = y - midY; + + var slope = Math.abs(lenY / lenX); + + var ratio = void 0; + if (slope < bb.height / bb.width) { + ratio = bb.width / 2 / Math.abs(lenX); + } else { + ratio = bb.height / 2 / Math.abs(lenY); + } + + return { + x: midX + lenX * ratio, + y: midY + lenY * ratio + }; + } + + function getOffset(side, line) { + var giveOffset = !!line.getAttribute('marker-' + side); + // const giveOffset = $(line).data(side+'_off'); + + // TODO: Make this number (5) be based on marker width/height + var size = line.getAttribute('stroke-width') * 5; + return giveOffset ? size : 0; + } + + function showPanel(on) { + var connRules = $('#connector_rules'); + if (!connRules.length) { + connRules = $('').appendTo('head'); + } + connRules.text(!on ? '' : '#tool_clone, #tool_topath, #tool_angle, #xy_panel { display: none !important; }'); + $('#connector_panel').toggle(on); + } + + function setPoint(elem, pos, x, y, setMid) { + var pts = elem.points; + var pt = svgroot.createSVGPoint(); + pt.x = x; + pt.y = y; + if (pos === 'end') { + pos = pts.numberOfItems - 1; + } + // TODO: Test for this on init, then use alt only if needed + try { + pts.replaceItem(pt, pos); + } catch (err) { + // Should only occur in FF which formats points attr as "n,n n,n", so just split + var ptArr = elem.getAttribute('points').split(' '); + for (var i = 0; i < ptArr.length; i++) { + if (i === pos) { + ptArr[i] = x + ',' + y; + } + } + elem.setAttribute('points', ptArr.join(' ')); + } + + if (setMid) { + // Add center point + var ptStart = pts.getItem(0); + var ptEnd = pts.getItem(pts.numberOfItems - 1); + setPoint(elem, 1, (ptEnd.x + ptStart.x) / 2, (ptEnd.y + ptStart.y) / 2); + } + } + + function updateLine(diffX, diffY) { + // Update line with element + var i = connections.length; + while (i--) { + var conn = connections[i]; + var line = conn.connector; + // const {elem} = conn; + + var pre = conn.is_start ? 'start' : 'end'; + // const sw = line.getAttribute('stroke-width') * 5; + + // Update bbox for this element + var bb = elData(line, pre + '_bb'); + bb.x = conn.start_x + diffX; + bb.y = conn.start_y + diffY; + elData(line, pre + '_bb', bb); + + var altPre = conn.is_start ? 'end' : 'start'; + + // Get center pt of connected element + var bb2 = elData(line, altPre + '_bb'); + var srcX = bb2.x + bb2.width / 2; + var srcY = bb2.y + bb2.height / 2; + + // Set point of element being moved + var pt = getBBintersect(srcX, srcY, bb, getOffset(pre, line)); // $(line).data(pre+'_off')?sw:0 + setPoint(line, conn.is_start ? 0 : 'end', pt.x, pt.y, true); + + // Set point of connected element + var pt2 = getBBintersect(pt.x, pt.y, elData(line, altPre + '_bb'), getOffset(altPre, line)); + setPoint(line, conn.is_start ? 'end' : 0, pt2.x, pt2.y, true); + } + } + + /** + * + * @param {array} [elem=selElems] Array of elements + */ + function findConnectors() { + var elems = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : selElems; + + var connectors = $(svgcontent).find(connSel); + connections = []; + + // Loop through connectors to see if one is connected to the element + connectors.each(function () { + var addThis = void 0; + function add() { + if (elems.includes(this)) { + // Pretend this element is selected + addThis = true; + } + } + + // Grab the ends + var parts = []; + ['start', 'end'].forEach(function (pos, i) { + var key = 'c_' + pos; + var part = elData(this, key); + if (part == null) { + part = document.getElementById(this.attributes['se:connector'].value.split(' ')[i]); + elData(this, 'c_' + pos, part.id); + elData(this, pos + '_bb', svgCanvas.getStrokedBBox([part])); + } else part = document.getElementById(part); + parts.push(part); + }.bind(this)); + + for (var i = 0; i < 2; i++) { + var cElem = parts[i]; + + addThis = false; + // The connected element might be part of a selected group + $(cElem).parents().each(add); + + if (!cElem || !cElem.parentNode) { + $(this).remove(); + continue; + } + if (elems.includes(cElem) || addThis) { + var bb = svgCanvas.getStrokedBBox([cElem]); + connections.push({ + elem: cElem, + connector: this, + is_start: i === 0, + start_x: bb.x, + start_y: bb.y + }); + } + } + }); + } + + function updateConnectors(elems) { + // Updates connector lines based on selected elements + // Is not used on mousemove, as it runs getStrokedBBox every time, + // which isn't necessary there. + findConnectors(elems); + if (connections.length) { + // Update line with element + var i = connections.length; + while (i--) { + var conn = connections[i]; + var line = conn.connector; + var elem = conn.elem; + + // const sw = line.getAttribute('stroke-width') * 5; + + var pre = conn.is_start ? 'start' : 'end'; + + // Update bbox for this element + var bb = svgCanvas.getStrokedBBox([elem]); + bb.x = conn.start_x; + bb.y = conn.start_y; + elData(line, pre + '_bb', bb); + /* const addOffset = */elData(line, pre + '_off'); + + var altPre = conn.is_start ? 'end' : 'start'; + + // Get center pt of connected element + var bb2 = elData(line, altPre + '_bb'); + var srcX = bb2.x + bb2.width / 2; + var srcY = bb2.y + bb2.height / 2; + + // Set point of element being moved + var pt = getBBintersect(srcX, srcY, bb, getOffset(pre, line)); + setPoint(line, conn.is_start ? 0 : 'end', pt.x, pt.y, true); + + // Set point of connected element + var pt2 = getBBintersect(pt.x, pt.y, elData(line, altPre + '_bb'), getOffset(altPre, line)); + setPoint(line, conn.is_start ? 'end' : 0, pt2.x, pt2.y, true); + + // Update points attribute manually for webkit + if (navigator.userAgent.includes('AppleWebKit')) { + var pts = line.points; + var len = pts.numberOfItems; + var ptArr = []; + for (var j = 0; j < len; j++) { + pt = pts.getItem(j); + ptArr[j] = pt.x + ',' + pt.y; + } + line.setAttribute('points', ptArr.join(' ')); + } + } + } + } + + // Do once + (function () { + var gse = svgCanvas.groupSelectedElements; + + svgCanvas.groupSelectedElements = function () { + svgCanvas.removeFromSelection($(connSel).toArray()); + return gse.apply(this, arguments); + }; + + var mse = svgCanvas.moveSelectedElements; + + svgCanvas.moveSelectedElements = function () { + var cmd = mse.apply(this, arguments); + updateConnectors(); + return cmd; + }; + + seNs = svgCanvas.getEditorNS(); + })(); + + // Do on reset + function init() { + // Make sure all connectors have data set + $(svgcontent).find('*').each(function () { + var conn = this.getAttributeNS(seNs, 'connector'); + if (conn) { + this.setAttribute('class', connSel.substr(1)); + var connData = conn.split(' '); + var sbb = svgCanvas.getStrokedBBox([getElem(connData[0])]); + var ebb = svgCanvas.getStrokedBBox([getElem(connData[1])]); + $(this).data('c_start', connData[0]).data('c_end', connData[1]).data('start_bb', sbb).data('end_bb', ebb); + svgCanvas.getEditorNS(true); + } + }); + // updateConnectors(); + } + + // $(svgroot).parent().mousemove(function (e) { + // // if (started + // // || svgCanvas.getMode() !== 'connector' + // // || e.target.parentNode.parentNode !== svgcontent) return; + // + // console.log('y') + // // if (e.target.parentNode.parentNode === svgcontent) { + // // + // // } + // }); + + return { + name: 'Connector', + svgicons: svgEditor.curConfig.imgPath + 'conn.svg', + buttons: [{ + id: 'mode_connect', + type: 'mode', + icon: svgEditor.curConfig.imgPath + 'cut.png', + title: 'Connect two objects', + includeWith: { + button: '#tool_line', + isDefault: false, + position: 1 + }, + events: { + click: function click() { + svgCanvas.setMode('connector'); + } + } + }], + addLangData: function addLangData(lang) { + return { + data: langList[lang] + }; + }, + mouseDown: function mouseDown(opts) { + var e = opts.event; + startX = opts.start_x; + startY = opts.start_y; + var mode = svgCanvas.getMode(); + + if (mode === 'connector') { + if (started) { + return; + } + + var mouseTarget = e.target; + + var parents = $(mouseTarget).parents(); + + if ($.inArray(svgcontent, parents) !== -1) { + // Connectable element + + // If child of foreignObject, use parent + var fo = $(mouseTarget).closest('foreignObject'); + startElem = fo.length ? fo[0] : mouseTarget; + + // Get center of source element + var bb = svgCanvas.getStrokedBBox([startElem]); + var x = bb.x + bb.width / 2; + var y = bb.y + bb.height / 2; + + started = true; + curLine = addElem({ + element: 'polyline', + attr: { + id: getNextId(), + points: x + ',' + y + ' ' + x + ',' + y + ' ' + startX + ',' + startY, + stroke: '#' + curConfig.initStroke.color, + 'stroke-width': !startElem.stroke_width || startElem.stroke_width === 0 ? curConfig.initStroke.width : startElem.stroke_width, + fill: 'none', + opacity: curConfig.initStroke.opacity, + style: 'pointer-events:none' + } + }); + elData(curLine, 'start_bb', bb); + } + return { + started: true + }; + } + if (mode === 'select') { + findConnectors(); + } + }, + mouseMove: function mouseMove(opts) { + var zoom = svgCanvas.getZoom(); + // const e = opts.event; + var x = opts.mouse_x / zoom; + var y = opts.mouse_y / zoom; + + var diffX = x - startX, + diffY = y - startY; + + var mode = svgCanvas.getMode(); + + if (mode === 'connector' && started) { + // const sw = curLine.getAttribute('stroke-width') * 3; + // Set start point (adjusts based on bb) + var pt = getBBintersect(x, y, elData(curLine, 'start_bb'), getOffset('start', curLine)); + startX = pt.x; + startY = pt.y; + + setPoint(curLine, 0, pt.x, pt.y, true); + + // Set end point + setPoint(curLine, 'end', x, y, true); + } else if (mode === 'select') { + var slen = selElems.length; + while (slen--) { + var elem = selElems[slen]; + // Look for selected connector elements + if (elem && elData(elem, 'c_start')) { + // Remove the "translate" transform given to move + svgCanvas.removeFromSelection([elem]); + svgCanvas.getTransformList(elem).clear(); + } + } + if (connections.length) { + updateLine(diffX, diffY); + } + } + }, + mouseUp: function mouseUp(opts) { + // const zoom = svgCanvas.getZoom(); + var e = opts.event; + // , x = opts.mouse_x / zoom, + // , y = opts.mouse_y / zoom, + var mouseTarget = e.target; + + if (svgCanvas.getMode() === 'connector') { + var fo = $(mouseTarget).closest('foreignObject'); + if (fo.length) { + mouseTarget = fo[0]; + } + + var parents = $(mouseTarget).parents(); + + if (mouseTarget === startElem) { + // Start line through click + started = true; + return { + keep: true, + element: null, + started: started + }; + } + if ($.inArray(svgcontent, parents) === -1) { + // Not a valid target element, so remove line + $(curLine).remove(); + started = false; + return { + keep: false, + element: null, + started: started + }; + } + // Valid end element + endElem = mouseTarget; + + var startId = startElem.id, + endId = endElem.id; + var connStr = startId + ' ' + endId; + var altStr = endId + ' ' + startId; + // Don't create connector if one already exists + var dupe = $(svgcontent).find(connSel).filter(function () { + var conn = this.getAttributeNS(seNs, 'connector'); + if (conn === connStr || conn === altStr) { + return true; + } + }); + if (dupe.length) { + $(curLine).remove(); + return { + keep: false, + element: null, + started: false + }; + } + + var bb = svgCanvas.getStrokedBBox([endElem]); + + var pt = getBBintersect(startX, startY, bb, getOffset('start', curLine)); + setPoint(curLine, 'end', pt.x, pt.y, true); + $(curLine).data('c_start', startId).data('c_end', endId).data('end_bb', bb); + seNs = svgCanvas.getEditorNS(true); + curLine.setAttributeNS(seNs, 'se:connector', connStr); + curLine.setAttribute('class', connSel.substr(1)); + curLine.setAttribute('opacity', 1); + svgCanvas.addToSelection([curLine]); + svgCanvas.moveToBottomSelectedElement(); + selManager.requestSelector(curLine).showGrips(false); + started = false; + return { + keep: true, + element: curLine, + started: started + }; + } + }, + selectedChanged: function selectedChanged(opts) { + // TODO: Find better way to skip operations if no connectors are in use + if (!$(svgcontent).find(connSel).length) { + return; + } + + if (svgCanvas.getMode() === 'connector') { + svgCanvas.setMode('select'); + } + + // Use this to update the current selected elements + selElems = opts.elems; + + var i = selElems.length; + while (i--) { + var elem = selElems[i]; + if (elem && elData(elem, 'c_start')) { + selManager.requestSelector(elem).showGrips(false); + if (opts.selectedElement && !opts.multiselected) { + // TODO: Set up context tools and hide most regular line tools + showPanel(true); + } else { + showPanel(false); + } + } else { + showPanel(false); + } + } + updateConnectors(); + }, + elementChanged: function elementChanged(opts) { + var elem = opts.elems[0]; + if (elem && elem.tagName === 'svg' && elem.id === 'svgcontent') { + // Update svgcontent (can change on import) + svgcontent = elem; + init(); + } + + // Has marker, so change offset + if (elem && (elem.getAttribute('marker-start') || elem.getAttribute('marker-mid') || elem.getAttribute('marker-end'))) { + var start = elem.getAttribute('marker-start'); + var mid = elem.getAttribute('marker-mid'); + var end = elem.getAttribute('marker-end'); + curLine = elem; + $(elem).data('start_off', !!start).data('end_off', !!end); + + if (elem.tagName === 'line' && mid) { + // Convert to polyline to accept mid-arrow + + var x1 = Number(elem.getAttribute('x1')); + var x2 = Number(elem.getAttribute('x2')); + var y1 = Number(elem.getAttribute('y1')); + var y2 = Number(elem.getAttribute('y2')); + var _elem = elem, + id = _elem.id; + + + var midPt = ' ' + (x1 + x2) / 2 + ',' + (y1 + y2) / 2 + ' '; + var pline = addElem({ + element: 'polyline', + attr: { + points: x1 + ',' + y1 + midPt + x2 + ',' + y2, + stroke: elem.getAttribute('stroke'), + 'stroke-width': elem.getAttribute('stroke-width'), + 'marker-mid': mid, + fill: 'none', + opacity: elem.getAttribute('opacity') || 1 + } + }); + $(elem).after(pline).remove(); + svgCanvas.clearSelection(); + pline.id = id; + svgCanvas.addToSelection([pline]); + elem = pline; + } + } + // Update line if it's a connector + if (elem.getAttribute('class') === connSel.substr(1)) { + var _start = getElem(elData(elem, 'c_start')); + updateConnectors([_start]); + } else { + updateConnectors(); + } + }, + IDsUpdated: function IDsUpdated(input) { + var remove = []; + input.elems.forEach(function (elem) { + if ('se:connector' in elem.attr) { + elem.attr['se:connector'] = elem.attr['se:connector'].split(' ').map(function (oldID) { + return input.changes[oldID]; + }).join(' '); + + // Check validity - the field would be something like 'svg_21 svg_22', but + // if one end is missing, it would be 'svg_21' and therefore fail this test + if (!/. ./.test(elem.attr['se:connector'])) { + remove.push(elem.attr.id); + } + } + }); + return { remove: remove }; + }, + toolButtonStateUpdate: function toolButtonStateUpdate(opts) { + if (opts.nostroke) { + if ($('#mode_connect').hasClass('tool_button_current')) { + svgEditor.clickSelect(); + } + } + $('#mode_connect').toggleClass('disabled', opts.nostroke); + } + }; + }); + +}()); diff --git a/dist/extensions/ext-eyedropper.js b/dist/extensions/ext-eyedropper.js new file mode 100644 index 00000000..3d1d2f95 --- /dev/null +++ b/dist/extensions/ext-eyedropper.js @@ -0,0 +1,127 @@ +(function () { + 'use strict'; + + /* globals jQuery */ + /* + * ext-eyedropper.js + * + * Licensed under the MIT License + * + * Copyright(c) 2010 Jeff Schiller + * + */ + + svgEditor.addExtension('eyedropper', function (S) { + var $ = jQuery; + var ChangeElementCommand = S.ChangeElementCommand, + svgCanvas = svgEditor.canvas, + addToHistory = function addToHistory(cmd) { + svgCanvas.undoMgr.addCommandToHistory(cmd); + }, + currentStyle = { + fillPaint: 'red', fillOpacity: 1.0, + strokePaint: 'black', strokeOpacity: 1.0, + strokeWidth: 5, strokeDashArray: null, + opacity: 1.0, + strokeLinecap: 'butt', + strokeLinejoin: 'miter' + }; + + function getStyle(opts) { + // if we are in eyedropper mode, we don't want to disable the eye-dropper tool + var mode = svgCanvas.getMode(); + if (mode === 'eyedropper') { + return; + } + + var tool = $('#tool_eyedropper'); + // enable-eye-dropper if one element is selected + var elem = null; + if (!opts.multiselected && opts.elems[0] && !['svg', 'g', 'use'].includes(opts.elems[0].nodeName)) { + elem = opts.elems[0]; + tool.removeClass('disabled'); + // grab the current style + currentStyle.fillPaint = elem.getAttribute('fill') || 'black'; + currentStyle.fillOpacity = elem.getAttribute('fill-opacity') || 1.0; + currentStyle.strokePaint = elem.getAttribute('stroke'); + currentStyle.strokeOpacity = elem.getAttribute('stroke-opacity') || 1.0; + currentStyle.strokeWidth = elem.getAttribute('stroke-width'); + currentStyle.strokeDashArray = elem.getAttribute('stroke-dasharray'); + currentStyle.strokeLinecap = elem.getAttribute('stroke-linecap'); + currentStyle.strokeLinejoin = elem.getAttribute('stroke-linejoin'); + currentStyle.opacity = elem.getAttribute('opacity') || 1.0; + // disable eye-dropper tool + } else { + tool.addClass('disabled'); + } + } + + return { + name: 'eyedropper', + svgicons: svgEditor.curConfig.extIconsPath + 'eyedropper-icon.xml', + buttons: [{ + id: 'tool_eyedropper', + type: 'mode', + title: 'Eye Dropper Tool', + key: 'I', + events: { + click: function click() { + svgCanvas.setMode('eyedropper'); + } + } + }], + + // if we have selected an element, grab its paint and enable the eye dropper button + selectedChanged: getStyle, + elementChanged: getStyle, + + mouseDown: function mouseDown(opts) { + var mode = svgCanvas.getMode(); + if (mode === 'eyedropper') { + var e = opts.event; + var target = e.target; + + if (!['svg', 'g', 'use'].includes(target.nodeName)) { + var changes = {}; + + var change = function change(elem, attrname, newvalue) { + changes[attrname] = elem.getAttribute(attrname); + elem.setAttribute(attrname, newvalue); + }; + + if (currentStyle.fillPaint) { + change(target, 'fill', currentStyle.fillPaint); + } + if (currentStyle.fillOpacity) { + change(target, 'fill-opacity', currentStyle.fillOpacity); + } + if (currentStyle.strokePaint) { + change(target, 'stroke', currentStyle.strokePaint); + } + if (currentStyle.strokeOpacity) { + change(target, 'stroke-opacity', currentStyle.strokeOpacity); + } + if (currentStyle.strokeWidth) { + change(target, 'stroke-width', currentStyle.strokeWidth); + } + if (currentStyle.strokeDashArray) { + change(target, 'stroke-dasharray', currentStyle.strokeDashArray); + } + if (currentStyle.opacity) { + change(target, 'opacity', currentStyle.opacity); + } + if (currentStyle.strokeLinecap) { + change(target, 'stroke-linecap', currentStyle.strokeLinecap); + } + if (currentStyle.strokeLinejoin) { + change(target, 'stroke-linejoin', currentStyle.strokeLinejoin); + } + + addToHistory(new ChangeElementCommand(target, changes)); + } + } + } + }; + }); + +}()); diff --git a/dist/extensions/ext-foreignobject.js b/dist/extensions/ext-foreignobject.js new file mode 100644 index 00000000..77f12a8a --- /dev/null +++ b/dist/extensions/ext-foreignobject.js @@ -0,0 +1,272 @@ +(function () { + 'use strict'; + + /* globals jQuery */ + /* + * ext-foreignobject.js + * + * Licensed under the Apache License, Version 2 + * + * Copyright(c) 2010 Jacques Distler + * Copyright(c) 2010 Alexis Deveria + * + */ + + svgEditor.addExtension('foreignObject', function (S) { + var text2xml = S.text2xml, + NS = S.NS; + + var $ = jQuery; + var svgCanvas = svgEditor.canvas; + var + // {svgcontent} = S, + // addElem = S.addSvgElementFromJson, + svgdoc = S.svgroot.parentNode.ownerDocument; + + var properlySourceSizeTextArea = function properlySourceSizeTextArea() { + // TODO: remove magic numbers here and get values from CSS + var height = $('#svg_source_container').height() - 80; + $('#svg_source_textarea').css('height', height); + }; + + function showPanel(on) { + var fcRules = $('#fc_rules'); + if (!fcRules.length) { + fcRules = $('').appendTo('head'); + } + fcRules.text(!on ? '' : ' #tool_topath { display: none !important; }'); + $('#foreignObject_panel').toggle(on); + } + + function toggleSourceButtons(on) { + $('#tool_source_save, #tool_source_cancel').toggle(!on); + $('#foreign_save, #foreign_cancel').toggle(on); + } + + var selElems = void 0, + started = void 0, + newFO = void 0, + editingforeign = false; + + // Function: setForeignString(xmlString, elt) + // This function sets the content of element elt to the input XML. + // + // Parameters: + // xmlString - The XML text. + // elt - the parent element to append to + // + // Returns: + // This function returns false if the set was unsuccessful, true otherwise. + function setForeignString(xmlString) { + var elt = selElems[0]; + try { + // convert string into XML document + var newDoc = text2xml('' + xmlString + ''); + // run it through our sanitizer to remove anything we do not support + S.sanitizeSvg(newDoc.documentElement); + elt.parentNode.replaceChild(svgdoc.importNode(newDoc.documentElement.firstChild, true), elt); + S.call('changed', [elt]); + svgCanvas.clearSelection(); + } catch (e) { + console.log(e); + return false; + } + + return true; + } + + function showForeignEditor() { + var elt = selElems[0]; + if (!elt || editingforeign) { + return; + } + editingforeign = true; + toggleSourceButtons(true); + elt.removeAttribute('fill'); + + var str = S.svgToString(elt, 0); + $('#svg_source_textarea').val(str); + $('#svg_source_editor').fadeIn(); + properlySourceSizeTextArea(); + $('#svg_source_textarea').focus(); + } + + function setAttr(attr, val) { + svgCanvas.changeSelectedAttribute(attr, val); + S.call('changed', selElems); + } + + return { + name: 'foreignObject', + svgicons: svgEditor.curConfig.extIconsPath + 'foreignobject-icons.xml', + buttons: [{ + id: 'tool_foreign', + type: 'mode', + title: 'Foreign Object Tool', + events: { + click: function click() { + svgCanvas.setMode('foreign'); + } + } + }, { + id: 'edit_foreign', + type: 'context', + panel: 'foreignObject_panel', + title: 'Edit ForeignObject Content', + events: { + click: function click() { + showForeignEditor(); + } + } + }], + + context_tools: [{ + type: 'input', + panel: 'foreignObject_panel', + title: "Change foreignObject's width", + id: 'foreign_width', + label: 'w', + size: 3, + events: { + change: function change() { + setAttr('width', this.value); + } + } + }, { + type: 'input', + panel: 'foreignObject_panel', + title: "Change foreignObject's height", + id: 'foreign_height', + label: 'h', + events: { + change: function change() { + setAttr('height', this.value); + } + } + }, { + type: 'input', + panel: 'foreignObject_panel', + title: "Change foreignObject's font size", + id: 'foreign_font_size', + label: 'font-size', + size: 2, + defval: 16, + events: { + change: function change() { + setAttr('font-size', this.value); + } + } + }], + callback: function callback() { + $('#foreignObject_panel').hide(); + + var endChanges = function endChanges() { + $('#svg_source_editor').hide(); + editingforeign = false; + $('#svg_source_textarea').blur(); + toggleSourceButtons(false); + }; + + // TODO: Needs to be done after orig icon loads + setTimeout(function () { + // Create source save/cancel buttons + /* const save = */$('#tool_source_save').clone().hide().attr('id', 'foreign_save').unbind().appendTo('#tool_source_back').click(function () { + if (!editingforeign) { + return; + } + + if (!setForeignString($('#svg_source_textarea').val())) { + $.confirm('Errors found. Revert to original?', function (ok) { + if (!ok) { + return false; + } + endChanges(); + }); + } else { + endChanges(); + } + // setSelectMode(); + }); + + /* const cancel = */$('#tool_source_cancel').clone().hide().attr('id', 'foreign_cancel').unbind().appendTo('#tool_source_back').click(function () { + endChanges(); + }); + }, 3000); + }, + mouseDown: function mouseDown(opts) { + // const e = opts.event; + + if (svgCanvas.getMode() === 'foreign') { + started = true; + newFO = S.addSvgElementFromJson({ + element: 'foreignObject', + attr: { + x: opts.start_x, + y: opts.start_y, + id: S.getNextId(), + 'font-size': 16, // cur_text.font_size, + width: '48', + height: '20', + style: 'pointer-events:inherit' + } + }); + var m = svgdoc.createElementNS(NS.MATH, 'math'); + m.setAttributeNS(NS.XMLNS, 'xmlns', NS.MATH); + m.setAttribute('display', 'inline'); + var mi = svgdoc.createElementNS(NS.MATH, 'mi'); + mi.setAttribute('mathvariant', 'normal'); + mi.textContent = '\u03A6'; + var mo = svgdoc.createElementNS(NS.MATH, 'mo'); + mo.textContent = '\u222A'; + var mi2 = svgdoc.createElementNS(NS.MATH, 'mi'); + mi2.textContent = '\u2133'; + m.appendChild(mi); + m.appendChild(mo); + m.appendChild(mi2); + newFO.appendChild(m); + return { + started: true + }; + } + }, + mouseUp: function mouseUp(opts) { + // const e = opts.event; + if (svgCanvas.getMode() === 'foreign' && started) { + var attrs = $(newFO).attr(['width', 'height']); + var keep = attrs.width !== '0' || attrs.height !== '0'; + svgCanvas.addToSelection([newFO], true); + + return { + keep: keep, + element: newFO + }; + } + }, + selectedChanged: function selectedChanged(opts) { + // Use this to update the current selected elements + selElems = opts.elems; + + var i = selElems.length; + while (i--) { + var elem = selElems[i]; + if (elem && elem.tagName === 'foreignObject') { + if (opts.selectedElement && !opts.multiselected) { + $('#foreign_font_size').val(elem.getAttribute('font-size')); + $('#foreign_width').val(elem.getAttribute('width')); + $('#foreign_height').val(elem.getAttribute('height')); + showPanel(true); + } else { + showPanel(false); + } + } else { + showPanel(false); + } + } + }, + elementChanged: function elementChanged(opts) { + // const elem = opts.elems[0]; + } + }; + }); + +}()); diff --git a/dist/extensions/ext-grid.js b/dist/extensions/ext-grid.js new file mode 100644 index 00000000..c69b0d1b --- /dev/null +++ b/dist/extensions/ext-grid.js @@ -0,0 +1,168 @@ +(function () { + 'use strict'; + + /* globals jQuery */ + /* + * ext-grid.js + * + * Licensed under the Apache License, Version 2 + * + * Copyright(c) 2010 Redou Mine + * Copyright(c) 2010 Alexis Deveria + * + */ + + svgEditor.addExtension('view_grid', function (_ref) { + var NS = _ref.NS, + getTypeMap = _ref.getTypeMap; + + var $ = jQuery; + var svgCanvas = svgEditor.canvas; + var svgdoc = document.getElementById('svgcanvas').ownerDocument, + assignAttributes = svgCanvas.assignAttributes, + hcanvas = document.createElement('canvas'), + canvBG = $('#canvasBackground'), + units = getTypeMap(), + intervals = [0.01, 0.1, 1, 10, 100, 1000]; + + var showGrid = svgEditor.curConfig.showGrid || false; + + $(hcanvas).hide().appendTo('body'); + + var canvasGrid = svgdoc.createElementNS(NS.SVG, 'svg'); + assignAttributes(canvasGrid, { + id: 'canvasGrid', + width: '100%', + height: '100%', + x: 0, + y: 0, + overflow: 'visible', + display: 'none' + }); + canvBG.append(canvasGrid); + + // grid-pattern + var gridPattern = svgdoc.createElementNS(NS.SVG, 'pattern'); + assignAttributes(gridPattern, { + id: 'gridpattern', + patternUnits: 'userSpaceOnUse', + x: 0, // -(value.strokeWidth / 2), // position for strokewidth + y: 0, // -(value.strokeWidth / 2), // position for strokewidth + width: 100, + height: 100 + }); + + var gridimg = svgdoc.createElementNS(NS.SVG, 'image'); + assignAttributes(gridimg, { + x: 0, + y: 0, + width: 100, + height: 100 + }); + gridPattern.appendChild(gridimg); + $('#svgroot defs').append(gridPattern); + + // grid-box + var gridBox = svgdoc.createElementNS(NS.SVG, 'rect'); + assignAttributes(gridBox, { + width: '100%', + height: '100%', + x: 0, + y: 0, + 'stroke-width': 0, + stroke: 'none', + fill: 'url(#gridpattern)', + style: 'pointer-events: none; display:visible;' + }); + $('#canvasGrid').append(gridBox); + + function updateGrid(zoom) { + // TODO: Try this with elements, then compare performance difference + var unit = units[svgEditor.curConfig.baseUnit]; // 1 = 1px + var uMulti = unit * zoom; + // Calculate the main number interval + var rawM = 100 / uMulti; + var multi = 1; + for (var i = 0; i < intervals.length; i++) { + var num = intervals[i]; + multi = num; + if (rawM <= num) { + break; + } + } + var bigInt = multi * uMulti; + + // Set the canvas size to the width of the container + hcanvas.width = bigInt; + hcanvas.height = bigInt; + var ctx = hcanvas.getContext('2d'); + var curD = 0.5; + var part = bigInt / 10; + + ctx.globalAlpha = 0.2; + ctx.strokeStyle = svgEditor.curConfig.gridColor; + for (var _i = 1; _i < 10; _i++) { + var subD = Math.round(part * _i) + 0.5; + // const lineNum = (i % 2)?12:10; + var lineNum = 0; + ctx.moveTo(subD, bigInt); + ctx.lineTo(subD, lineNum); + ctx.moveTo(bigInt, subD); + ctx.lineTo(lineNum, subD); + } + ctx.stroke(); + ctx.beginPath(); + ctx.globalAlpha = 0.5; + ctx.moveTo(curD, bigInt); + ctx.lineTo(curD, 0); + + ctx.moveTo(bigInt, curD); + ctx.lineTo(0, curD); + ctx.stroke(); + + var datauri = hcanvas.toDataURL('image/png'); + gridimg.setAttribute('width', bigInt); + gridimg.setAttribute('height', bigInt); + gridimg.parentNode.setAttribute('width', bigInt); + gridimg.parentNode.setAttribute('height', bigInt); + svgCanvas.setHref(gridimg, datauri); + } + + function gridUpdate() { + if (showGrid) { + updateGrid(svgCanvas.getZoom()); + } + $('#canvasGrid').toggle(showGrid); + $('#view_grid').toggleClass('push_button_pressed tool_button'); + } + return { + name: 'view_grid', + svgicons: svgEditor.curConfig.extIconsPath + 'grid-icon.xml', + + zoomChanged: function zoomChanged(zoom) { + if (showGrid) { + updateGrid(zoom); + } + }, + callback: function callback() { + if (showGrid) { + gridUpdate(); + } + }, + + buttons: [{ + id: 'view_grid', + type: 'context', + panel: 'editor_panel', + title: 'Show/Hide Grid', + events: { + click: function click() { + svgEditor.curConfig.showGrid = showGrid = !showGrid; + gridUpdate(); + } + } + }] + }; + }); + +}()); diff --git a/dist/extensions/ext-helloworld.js b/dist/extensions/ext-helloworld.js new file mode 100644 index 00000000..9f82c98a --- /dev/null +++ b/dist/extensions/ext-helloworld.js @@ -0,0 +1,83 @@ +(function () { + 'use strict'; + + /* globals jQuery */ + /* + * ext-helloworld.js + * + * Licensed under the MIT License + * + * Copyright(c) 2010 Alexis Deveria + * + */ + + /* + This is a very basic SVG-Edit extension. It adds a "Hello World" button in + the left panel. Clicking on the button, and then the canvas will show the + user the point on the canvas that was clicked on. + */ + + svgEditor.addExtension('Hello World', function () { + var $ = jQuery; + var svgCanvas = svgEditor.canvas; + return { + name: 'Hello World', + // For more notes on how to make an icon file, see the source of + // the helloworld-icon.xml + svgicons: svgEditor.curConfig.extIconsPath + 'helloworld-icon.xml', + + // Multiple buttons can be added in this array + buttons: [{ + // Must match the icon ID in helloworld-icon.xml + id: 'hello_world', + + // This indicates that the button will be added to the "mode" + // button panel on the left side + type: 'mode', + + // Tooltip text + title: "Say 'Hello World'", + + // Events + events: { + click: function click() { + // The action taken when the button is clicked on. + // For "mode" buttons, any other button will + // automatically be de-pressed. + svgCanvas.setMode('hello_world'); + } + } + }], + // This is triggered when the main mouse button is pressed down + // on the editor canvas (not the tool panels) + mouseDown: function mouseDown() { + // Check the mode on mousedown + if (svgCanvas.getMode() === 'hello_world') { + // The returned object must include "started" with + // a value of true in order for mouseUp to be triggered + return { started: true }; + } + }, + + + // This is triggered from anywhere, but "started" must have been set + // to true (see above). Note that "opts" is an object with event info + mouseUp: function mouseUp(opts) { + // Check the mode on mouseup + if (svgCanvas.getMode() === 'hello_world') { + var zoom = svgCanvas.getZoom(); + + // Get the actual coordinate by dividing by the zoom value + var x = opts.mouse_x / zoom; + var y = opts.mouse_y / zoom; + + var text = 'Hello World!\n\nYou clicked here: ' + x + ', ' + y; + + // Show the text using the custom alert function + $.alert(text); + } + } + }; + }); + +}()); diff --git a/dist/extensions/ext-imagelib.js b/dist/extensions/ext-imagelib.js new file mode 100644 index 00000000..009c1309 --- /dev/null +++ b/dist/extensions/ext-imagelib.js @@ -0,0 +1,395 @@ +(function () { + 'use strict'; + + /* globals jQuery */ + /* + * ext-imagelib.js + * + * Licensed under the MIT License + * + * Copyright(c) 2010 Alexis Deveria + * + */ + + svgEditor.addExtension('imagelib', function (_ref) { + var decode64 = _ref.decode64; + + var $ = jQuery; + var _svgEditor = svgEditor, + uiStrings = _svgEditor.uiStrings, + svgCanvas = _svgEditor.canvas; + + + $.extend(uiStrings, { + imagelib: { + select_lib: 'Select an image library', + show_list: 'Show library list', + import_single: 'Import single', + import_multi: 'Import multiple', + open: 'Open as new document' + } + }); + + var modularVersion = !('svgEditor' in window) || !window.svgEditor || window.svgEditor.modules !== false; + + var imgLibs = [{ + name: 'Demo library (local)', + url: svgEditor.curConfig.extPath + 'imagelib/index' + (modularVersion ? '-es' : '') + '.html', + description: 'Demonstration library for SVG-edit on this server' + }, { + name: 'IAN Symbol Libraries', + url: 'https://ian.umces.edu/symbols/catalog/svgedit/album_chooser.php', + description: 'Free library of illustrations' + }, { + name: 'Openclipart', + url: 'https://openclipart.org/svgedit', + description: 'Share and Use Images. Over 50,000 Public Domain SVG Images and Growing.' + }]; + + function closeBrowser() { + $('#imgbrowse_holder').hide(); + } + + function importImage(url) { + var newImage = svgCanvas.addSvgElementFromJson({ + element: 'image', + attr: { + x: 0, + y: 0, + width: 0, + height: 0, + id: svgCanvas.getNextId(), + style: 'pointer-events:inherit' + } + }); + svgCanvas.clearSelection(); + svgCanvas.addToSelection([newImage]); + svgCanvas.setImageURL(url); + } + + var pending = {}; + + var mode = 's'; + var multiArr = []; + var transferStopped = false; + var preview = void 0, + submit = void 0; + + window.addEventListener('message', function (evt) { + // Receive `postMessage` data + var response = evt.data; + + if (!response || typeof response !== 'string') { + // Do nothing + return; + } + try { + // Todo: This block can be removed (and the above check changed to + // insist on an object) if embedAPI moves away from a string to + // an object (if IE9 support not needed) + response = JSON.parse(response); + if (response.namespace !== 'imagelib') { + return; + } + } catch (e) { + return; + } + + var hasName = 'name' in response; + var hasHref = 'href' in response; + + if (!hasName && transferStopped) { + transferStopped = false; + return; + } + + var id = void 0; + if (hasHref) { + id = response.href; + response = response.data; + } + + // Hide possible transfer dialog box + $('#dialog_box').hide(); + var entry = void 0, + curMeta = void 0, + svgStr = void 0, + imgStr = void 0; + var type = hasName ? 'meta' : response.charAt(0); + switch (type) { + case 'meta': + { + // Metadata + transferStopped = false; + curMeta = response; + + pending[curMeta.id] = curMeta; + + var name = curMeta.name || 'file'; + + var message = uiStrings.notification.retrieving.replace('%s', name); + + if (mode !== 'm') { + $.process_cancel(message, function () { + transferStopped = true; + // Should a message be sent back to the frame? + + $('#dialog_box').hide(); + }); + } else { + entry = $('
' + message + '
').data('id', curMeta.id); + preview.append(entry); + curMeta.entry = entry; + } + + return; + } + case '<': + svgStr = true; + break; + case 'd': + { + if (response.startsWith('data:image/svg+xml')) { + var pre = 'data:image/svg+xml;base64,'; + var src = response.substring(pre.length); + response = decode64(src); + svgStr = true; + break; + } else if (response.startsWith('data:image/')) { + imgStr = true; + break; + } + } + // Else fall through + default: + // TODO: See if there's a way to base64 encode the binary data stream + // const str = 'data:;base64,' + svgedit.utilities.encode64(response, true); + + // Assume it's raw image data + // importImage(str); + + // Don't give warning as postMessage may have been used by something else + if (mode !== 'm') { + closeBrowser(); + } else { + pending[id].entry.remove(); + } + // $.alert('Unexpected data was returned: ' + response, function() { + // if (mode !== 'm') { + // closeBrowser(); + // } else { + // pending[id].entry.remove(); + // } + // }); + return; + } + + switch (mode) { + case 's': + // Import one + if (svgStr) { + svgCanvas.importSvgString(response); + } else if (imgStr) { + importImage(response); + } + closeBrowser(); + break; + case 'm': + // Import multiple + multiArr.push([svgStr ? 'svg' : 'img', response]); + curMeta = pending[id]; + var title = void 0; + if (svgStr) { + if (curMeta && curMeta.name) { + title = curMeta.name; + } else { + // Try to find a title + var xml = new DOMParser().parseFromString(response, 'text/xml').documentElement; + title = $(xml).children('title').first().text() || '(SVG #' + response.length + ')'; + } + if (curMeta) { + preview.children().each(function () { + if ($(this).data('id') === id) { + if (curMeta.preview_url) { + $(this).html('' + title); + } else { + $(this).text(title); + } + submit.removeAttr('disabled'); + } + }); + } else { + preview.append('
' + title + '
'); + submit.removeAttr('disabled'); + } + } else { + if (curMeta && curMeta.preview_url) { + title = curMeta.name || ''; + } + if (curMeta && curMeta.preview_url) { + entry = '' + title; + } else { + entry = ''; + } + + if (curMeta) { + preview.children().each(function () { + if ($(this).data('id') === id) { + $(this).html(entry); + submit.removeAttr('disabled'); + } + }); + } else { + preview.append($('
').append(entry)); + submit.removeAttr('disabled'); + } + } + break; + case 'o': + // Open + if (!svgStr) { + break; + } + svgEditor.openPrep(function (ok) { + if (!ok) { + return; + } + svgCanvas.clear(); + svgCanvas.setSvgString(response); + // updateCanvas(); + }); + closeBrowser(); + break; + } + }, true); + + function toggleMulti(show) { + $('#lib_framewrap, #imglib_opts').css({ right: show ? 200 : 10 }); + if (!preview) { + preview = $('
').css({ + position: 'absolute', + top: 45, + right: 10, + width: 180, + bottom: 45, + background: '#fff', + overflow: 'auto' + }).insertAfter('#lib_framewrap'); + + submit = $('').appendTo('#imgbrowse').on('click touchend', function () { + $.each(multiArr, function (i) { + var type = this[0]; + var data = this[1]; + if (type === 'svg') { + svgCanvas.importSvgString(data); + } else { + importImage(data); + } + svgCanvas.moveSelectedElements(i * 20, i * 20, false); + }); + preview.empty(); + multiArr = []; + $('#imgbrowse_holder').hide(); + }).css({ + position: 'absolute', + bottom: 10, + right: -10 + }); + } + + preview.toggle(show); + submit.toggle(show); + } + + function showBrowser() { + var browser = $('#imgbrowse'); + if (!browser.length) { + $('
' + '
').insertAfter('#svg_docprops'); + browser = $('#imgbrowse'); + + var allLibs = uiStrings.imagelib.select_lib; + + var libOpts = $('
    ').appendTo(browser); + var frame = $('' - ) + const exportWindow = window.open( + 'data:text/html;charset=utf-8,' + encodeURIComponent('' + str + '

    ' + str + '

    '), + 'svg-edit-exportWindow' ); - const frame = document.getElementById('svgedit'); + svgCanvas.rasterExport('PNG', null, exportWindow.name); +} + +function exportPDF () { + const str = svgEditor.uiStrings.notification.loadingImage; + + /** + // If you want to handle the PDF blob yourself, do as follows + svgCanvas.bind('exportedPDF', function (win, data) { + alert(data.dataurlstring); + }); + svgCanvas.exportPDF(); // Accepts two args: optionalWindowName supplied back to bound exportPDF handler and optionalOutputType (defaults to dataurlstring) + return; + */ + + const exportWindow = window.open( + 'data:text/html;charset=utf-8,' + encodeURIComponent('' + str + '

    ' + str + '

    '), + 'svg-edit-exportWindow' + ); + svgCanvas.exportPDF(exportWindow.name); +} + +// Add event handlers +$('#load').click(loadSvg); +$('#save').click(saveSvg); +$('#exportPNG').click(exportPNG); +$('#exportPDF').click(exportPDF); + +const iframe = $('' +); +iframe[0].addEventListener('load', function () { + svgCanvas = new EmbeddedSVGEdit(frame); + // Hide main button, as we will be controlling new, load, save, etc. from the host document + const doc = frame.contentDocument || frame.contentWindow.document; + const mainButton = doc.getElementById('main_button'); + mainButton.style.display = 'none'; }); +$('body').append(iframe); +const frame = document.getElementById('svgedit'); diff --git a/editor/extensions/ext-arrows.js b/editor/extensions/ext-arrows.js index 8ab9e929..c4e08cc7 100644 --- a/editor/extensions/ext-arrows.js +++ b/editor/extensions/ext-arrows.js @@ -1,4 +1,4 @@ -/* globals jQuery, svgEditor, svgCanvas */ +/* globals jQuery */ /* * ext-arrows.js * @@ -7,18 +7,19 @@ * Copyright(c) 2010 Alexis Deveria * */ - +import svgEditor from '../svg-editor.js'; svgEditor.addExtension('Arrows', function (S) { + const svgCanvas = svgEditor.canvas; const $ = jQuery; const // {svgcontent} = S, addElem = S.addSvgElementFromJson, {nonce} = S, langList = { - 'en': [ - {'id': 'arrow_none', 'textContent': 'No arrow'} + en: [ + {id: 'arrow_none', textContent: 'No arrow'} ], - 'fr': [ - {'id': 'arrow_none', 'textContent': 'Sans flèche'} + fr: [ + {id: 'arrow_none', textContent: 'Sans flèche'} ] }, prefix = 'se_arrow_'; diff --git a/editor/extensions/ext-closepath.js b/editor/extensions/ext-closepath.js index bdaf9775..244d8e0e 100644 --- a/editor/extensions/ext-closepath.js +++ b/editor/extensions/ext-closepath.js @@ -1,4 +1,4 @@ -/* globals jQuery, svgEditor */ +/* globals jQuery */ /* * ext-closepath.js * @@ -7,7 +7,8 @@ * Copyright(c) 2010 Jeff Schiller * */ -// import './pathseg.js'; +import '../pathseg.js'; +import svgEditor from '../svg-editor.js'; // This extension adds a simple button to the contextual panel for paths // The button toggles whether the path is open or closed @@ -46,7 +47,7 @@ svgEditor.addExtension('ClosePath', function () { return { name: 'ClosePath', - svgicons: svgEditor.curConfig.extPath + 'closepath_icons.svg', + svgicons: svgEditor.curConfig.extIconsPath + 'closepath_icons.svg', buttons: [{ id: 'tool_openpath', type: 'context', diff --git a/editor/extensions/ext-connector.js b/editor/extensions/ext-connector.js index 7e35248e..0455a61e 100644 --- a/editor/extensions/ext-connector.js +++ b/editor/extensions/ext-connector.js @@ -1,4 +1,4 @@ -/* globals jQuery, svgEditor, svgCanvas */ +/* globals jQuery */ /* * ext-connector.js * @@ -8,8 +8,10 @@ * */ +import svgEditor from '../svg-editor.js'; svgEditor.addExtension('Connector', function (S) { const $ = jQuery; + const svgCanvas = svgEditor.canvas; const {svgroot, getNextId, getElem, curConfig} = S, addElem = S.addSvgElementFromJson, selManager = S.selectorManager, @@ -29,11 +31,11 @@ svgEditor.addExtension('Connector', function (S) { selElems = []; const langList = { - 'en': [ - {'id': 'mode_connect', 'title': 'Connect two objects'} + en: [ + {id: 'mode_connect', title: 'Connect two objects'} ], - 'fr': [ - {'id': 'mode_connect', 'title': 'Connecter deux objets'} + fr: [ + {id: 'mode_connect', title: 'Connecter deux objets'} ] }; @@ -360,15 +362,15 @@ svgEditor.addExtension('Connector', function (S) { started = true; curLine = addElem({ - 'element': 'polyline', - 'attr': { - 'id': getNextId(), - 'points': (x + ',' + y + ' ' + x + ',' + y + ' ' + startX + ',' + startY), - 'stroke': '#' + curConfig.initStroke.color, + element: 'polyline', + attr: { + id: getNextId(), + points: (x + ',' + y + ' ' + x + ',' + y + ' ' + startX + ',' + startY), + stroke: '#' + curConfig.initStroke.color, 'stroke-width': (!startElem.stroke_width || startElem.stroke_width === 0) ? curConfig.initStroke.width : startElem.stroke_width, - 'fill': 'none', - 'opacity': curConfig.initStroke.opacity, - 'style': 'pointer-events:none' + fill: 'none', + opacity: curConfig.initStroke.opacity, + style: 'pointer-events:none' } }); elData(curLine, 'start_bb', bb); @@ -555,14 +557,14 @@ svgEditor.addExtension('Connector', function (S) { const midPt = (' ' + ((x1 + x2) / 2) + ',' + ((y1 + y2) / 2) + ' '); const pline = addElem({ - 'element': 'polyline', - 'attr': { - 'points': (x1 + ',' + y1 + midPt + x2 + ',' + y2), - 'stroke': elem.getAttribute('stroke'), + element: 'polyline', + attr: { + points: (x1 + ',' + y1 + midPt + x2 + ',' + y2), + stroke: elem.getAttribute('stroke'), 'stroke-width': elem.getAttribute('stroke-width'), 'marker-mid': mid, - 'fill': 'none', - 'opacity': elem.getAttribute('opacity') || 1 + fill: 'none', + opacity: elem.getAttribute('opacity') || 1 } }); $(elem).after(pline).remove(); diff --git a/editor/extensions/ext-eyedropper.js b/editor/extensions/ext-eyedropper.js index eac235dd..384a1081 100644 --- a/editor/extensions/ext-eyedropper.js +++ b/editor/extensions/ext-eyedropper.js @@ -1,4 +1,4 @@ -/* globals jQuery, svgEditor, svgedit */ +/* globals jQuery */ /* * ext-eyedropper.js * @@ -8,18 +8,13 @@ * */ -// Dependencies: -// 1) jQuery -// 2) history.js -// 3) svg_editor.js -// 4) svgcanvas.js +import svgEditor from '../svg-editor.js'; svgEditor.addExtension('eyedropper', function (S) { const $ = jQuery; - const // {svgcontent} = S, + const {ChangeElementCommand} = S, // , svgcontent, // svgdoc = S.svgroot.parentNode.ownerDocument, svgCanvas = svgEditor.canvas, - {ChangeElementCommand} = svgedit.history, addToHistory = function (cmd) { svgCanvas.undoMgr.addCommandToHistory(cmd); }, currentStyle = { fillPaint: 'red', fillOpacity: 1.0, @@ -61,7 +56,7 @@ svgEditor.addExtension('eyedropper', function (S) { return { name: 'eyedropper', - svgicons: svgEditor.curConfig.extPath + 'eyedropper-icon.xml', + svgicons: svgEditor.curConfig.extIconsPath + 'eyedropper-icon.xml', buttons: [{ id: 'tool_eyedropper', type: 'mode', diff --git a/editor/extensions/ext-foreignobject.js b/editor/extensions/ext-foreignobject.js index 730dbe41..3447aaa9 100644 --- a/editor/extensions/ext-foreignobject.js +++ b/editor/extensions/ext-foreignobject.js @@ -1,4 +1,4 @@ -/* globals jQuery, svgEditor, svgedit, svgCanvas */ +/* globals jQuery */ /* * ext-foreignobject.js * @@ -9,11 +9,13 @@ * */ -import {NS} from './svgedit.js'; +import svgEditor from '../svg-editor.js'; svgEditor.addExtension('foreignObject', function (S) { + const {text2xml, NS} = S; const $ = jQuery; - const Utils = svgedit.utilities, + const svgCanvas = svgEditor.canvas; + const // {svgcontent} = S, // addElem = S.addSvgElementFromJson, svgdoc = S.svgroot.parentNode.ownerDocument; @@ -56,7 +58,7 @@ svgEditor.addExtension('foreignObject', function (S) { const elt = selElems[0]; try { // convert string into XML document - const newDoc = Utils.text2xml('' + xmlString + ''); + const newDoc = text2xml('' + xmlString + ''); // run it through our sanitizer to remove anything we do not support S.sanitizeSvg(newDoc.documentElement); elt.parentNode.replaceChild(svgdoc.importNode(newDoc.documentElement.firstChild, true), elt); @@ -91,7 +93,7 @@ svgEditor.addExtension('foreignObject', function (S) { return { name: 'foreignObject', - svgicons: svgEditor.curConfig.extPath + 'foreignobject-icons.xml', + svgicons: svgEditor.curConfig.extIconsPath + 'foreignobject-icons.xml', buttons: [{ id: 'tool_foreign', type: 'mode', @@ -194,15 +196,15 @@ svgEditor.addExtension('foreignObject', function (S) { if (svgCanvas.getMode() === 'foreign') { started = true; newFO = S.addSvgElementFromJson({ - 'element': 'foreignObject', - 'attr': { - 'x': opts.start_x, - 'y': opts.start_y, - 'id': S.getNextId(), + element: 'foreignObject', + attr: { + x: opts.start_x, + y: opts.start_y, + id: S.getNextId(), 'font-size': 16, // cur_text.font_size, - 'width': '48', - 'height': '20', - 'style': 'pointer-events:inherit' + width: '48', + height: '20', + style: 'pointer-events:inherit' } }); const m = svgdoc.createElementNS(NS.MATH, 'math'); diff --git a/editor/extensions/ext-grid.js b/editor/extensions/ext-grid.js index 20210471..663e1d30 100644 --- a/editor/extensions/ext-grid.js +++ b/editor/extensions/ext-grid.js @@ -1,4 +1,4 @@ -/* globals jQuery, svgEditor, svgCanvas */ +/* globals jQuery */ /* * ext-grid.js * @@ -9,20 +9,16 @@ * */ -// Dependencies: -// 1) units.js -// 2) everything else +import svgEditor from '../svg-editor.js'; -import {NS} from './svgedit.js'; -import {getTypeMap} from './units.js'; - -svgEditor.addExtension('view_grid', function () { +svgEditor.addExtension('view_grid', function ({NS, getTypeMap}) { const $ = jQuery; + const svgCanvas = svgEditor.canvas; const svgdoc = document.getElementById('svgcanvas').ownerDocument, {assignAttributes} = svgCanvas, hcanvas = document.createElement('canvas'), canvBG = $('#canvasBackground'), - units = getTypeMap(), + units = getTypeMap(), // Assumes prior `init()` call on `units.js` module intervals = [0.01, 0.1, 1, 10, 100, 1000]; let showGrid = svgEditor.curConfig.showGrid || false; @@ -136,7 +132,7 @@ svgEditor.addExtension('view_grid', function () { } return { name: 'view_grid', - svgicons: svgEditor.curConfig.extPath + 'grid-icon.xml', + svgicons: svgEditor.curConfig.extIconsPath + 'grid-icon.xml', zoomChanged (zoom) { if (showGrid) { updateGrid(zoom); } diff --git a/editor/extensions/ext-helloworld.js b/editor/extensions/ext-helloworld.js index f49807d2..44a5c1fe 100644 --- a/editor/extensions/ext-helloworld.js +++ b/editor/extensions/ext-helloworld.js @@ -1,4 +1,4 @@ -/* globals jQuery, svgEditor, svgCanvas */ +/* globals jQuery */ /* * ext-helloworld.js * @@ -13,14 +13,15 @@ the left panel. Clicking on the button, and then the canvas will show the user the point on the canvas that was clicked on. */ - +import svgEditor from '../svg-editor.js'; svgEditor.addExtension('Hello World', function () { const $ = jQuery; + const svgCanvas = svgEditor.canvas; return { name: 'Hello World', // For more notes on how to make an icon file, see the source of // the helloworld-icon.xml - svgicons: svgEditor.curConfig.extPath + 'helloworld-icon.xml', + svgicons: svgEditor.curConfig.extIconsPath + 'helloworld-icon.xml', // Multiple buttons can be added in this array buttons: [{ diff --git a/editor/extensions/ext-imagelib.js b/editor/extensions/ext-imagelib.js index 3d3d7896..604dda6d 100644 --- a/editor/extensions/ext-imagelib.js +++ b/editor/extensions/ext-imagelib.js @@ -1,4 +1,4 @@ -/* globals jQuery, svgEditor, svgedit, svgCanvas */ +/* globals jQuery */ /* * ext-imagelib.js * @@ -7,10 +7,11 @@ * Copyright(c) 2010 Alexis Deveria * */ +import svgEditor from '../svg-editor.js'; -svgEditor.addExtension('imagelib', function () { +svgEditor.addExtension('imagelib', function ({decode64}) { const $ = jQuery; - const {uiStrings} = svgEditor; + const {uiStrings, canvas: svgCanvas} = svgEditor; $.extend(uiStrings, { imagelib: { @@ -22,10 +23,15 @@ svgEditor.addExtension('imagelib', function () { } }); + const modularVersion = !('svgEditor' in window) || + !window.svgEditor || + window.svgEditor.modules !== false; + const imgLibs = [ { name: 'Demo library (local)', - url: svgEditor.curConfig.extPath + 'imagelib/index.html', + url: svgEditor.curConfig.extPath + + 'imagelib/index' + (modularVersion ? '-es' : '') + '.html', description: 'Demonstration library for SVG-edit on this server' }, { @@ -46,14 +52,14 @@ svgEditor.addExtension('imagelib', function () { function importImage (url) { const newImage = svgCanvas.addSvgElementFromJson({ - 'element': 'image', - 'attr': { - 'x': 0, - 'y': 0, - 'width': 0, - 'height': 0, - 'id': svgCanvas.getNextId(), - 'style': 'pointer-events:inherit' + element: 'image', + attr: { + x: 0, + y: 0, + width: 0, + height: 0, + id: svgCanvas.getNextId(), + style: 'pointer-events:inherit' } }); svgCanvas.clearSelection(); @@ -142,7 +148,7 @@ svgEditor.addExtension('imagelib', function () { if (response.startsWith('data:image/svg+xml')) { const pre = 'data:image/svg+xml;base64,'; const src = response.substring(pre.length); - response = svgedit.utilities.decode64(src); + response = decode64(src); svgStr = true; break; } else if (response.startsWith('data:image/')) { @@ -354,16 +360,16 @@ svgEditor.addExtension('imagelib', function () { cancel.prepend($.getSvgIcon('cancel', true)); back.prepend($.getSvgIcon('tool_imagelib', true)); - $.each(imgLibs, function (i, opts) { + $.each(imgLibs, function (i, {name, url, description}) { $('
  • ') .appendTo(libOpts) - .text(opts.name) + .text(name) .on('click touchend', function () { - frame.attr('src', opts.url).show(); - header.text(opts.name); + frame.attr('src', url).show(); + header.text(name); libOpts.hide(); back.show(); - }).append('' + opts.description + ''); + }).append(`${description}`); }); } else { $('#imgbrowse_holder').show(); @@ -371,7 +377,7 @@ svgEditor.addExtension('imagelib', function () { } return { - svgicons: svgEditor.curConfig.extPath + 'ext-imagelib.xml', + svgicons: svgEditor.curConfig.extIconsPath + 'ext-imagelib.xml', buttons: [{ id: 'tool_imagelib', type: 'app_menu', // _flyout diff --git a/editor/extensions/ext-markers.js b/editor/extensions/ext-markers.js index b7ff3702..fd9a172b 100644 --- a/editor/extensions/ext-markers.js +++ b/editor/extensions/ext-markers.js @@ -1,4 +1,4 @@ -/* globals jQuery, svgEditor, svgCanvas */ +/* globals jQuery */ /* * ext-markers.js * @@ -30,9 +30,10 @@ * add support for dimension extension lines * */ - +import svgEditor from '../svg-editor.js'; svgEditor.addExtension('Markers', function (S) { const $ = jQuery; + const svgCanvas = svgEditor.canvas; const // {svgcontent} = S, addElem = S.addSvgElementFromJson; const mtypes = ['start', 'mid', 'end']; @@ -51,7 +52,7 @@ svgEditor.addExtension('Markers', function (S) { rightarrow: {element: 'path', attr: {d: 'M100,50 L0,90 L30,50 L0,10 Z'}}, textmarker: - {element: 'text', attr: {x: 0, y: 0, 'stroke-width': 0, 'stroke': 'none', 'font-size': 75, 'font-family': 'serif', 'text-anchor': 'left', + {element: 'text', attr: {x: 0, y: 0, 'stroke-width': 0, stroke: 'none', 'font-size': 75, 'font-family': 'serif', 'text-anchor': 'left', 'xml:space': 'preserve'}}, forwardslash: {element: 'path', attr: {d: 'M30,100 L70,0'}}, @@ -72,7 +73,7 @@ svgEditor.addExtension('Markers', function (S) { }; const langList = { - 'en': [ + en: [ {id: 'start_marker_list', title: 'Select start marker type'}, {id: 'mid_marker_list', title: 'Select mid marker type'}, {id: 'end_marker_list', title: 'Select end marker type'}, @@ -229,14 +230,14 @@ svgEditor.addExtension('Markers', function (S) { markerHeight = bb.height / 10; const box = addElem({ - 'element': 'rect', - 'attr': { - 'x': bb.x, - 'y': bb.y, - 'width': bb.width, - 'height': bb.height, - 'fill': txtBoxBg, - 'stroke': txtBoxBorder, + element: 'rect', + attr: { + x: bb.x, + y: bb.y, + width: bb.width, + height: bb.height, + fill: txtBoxBg, + stroke: txtBoxBorder, 'stroke-width': txtBoxStrokeWidth } }); @@ -270,13 +271,13 @@ svgEditor.addExtension('Markers', function (S) { const midPt = (' ' + ((x1 + x2) / 2) + ',' + ((y1 + y2) / 2) + ' '); const pline = addElem({ - 'element': 'polyline', - 'attr': { - 'points': (x1 + ',' + y1 + midPt + x2 + ',' + y2), - 'stroke': elem.getAttribute('stroke'), + element: 'polyline', + attr: { + points: (x1 + ',' + y1 + midPt + x2 + ',' + y2), + stroke: elem.getAttribute('stroke'), 'stroke-width': elem.getAttribute('stroke-width'), - 'fill': 'none', - 'opacity': elem.getAttribute('opacity') || 1 + fill: 'none', + opacity: elem.getAttribute('opacity') || 1 } }); $.each(mtypes, function (i, pos) { // get any existing marker definitions @@ -298,7 +299,7 @@ svgEditor.addExtension('Markers', function (S) { } function setMarker () { - const poslist = {'start_marker': 'start', 'mid_marker': 'mid', 'end_marker': 'end'}; + const poslist = {start_marker: 'start', mid_marker: 'mid', end_marker: 'end'}; const pos = poslist[this.id]; const markerName = 'marker-' + pos; let el = selElems[0]; @@ -435,21 +436,21 @@ svgEditor.addExtension('Markers', function (S) { id: idPrefix + 'markers_off', title: 'Turn off all markers', type: 'context', - events: { 'click': setMarkerSet }, + events: { click: setMarkerSet }, panel: 'marker_panel' }); buttons.push({ id: idPrefix + 'markers_dimension', title: 'Dimension', type: 'context', - events: { 'click': setMarkerSet }, + events: { click: setMarkerSet }, panel: 'marker_panel' }); buttons.push({ id: idPrefix + 'markers_label', title: 'Label', type: 'context', - events: { 'click': setMarkerSet }, + events: { click: setMarkerSet }, panel: 'marker_panel' }); */ @@ -463,7 +464,7 @@ svgEditor.addExtension('Markers', function (S) { svgicon: id, title, type: 'context', - events: {'click': setArrowFromButton}, + events: {click: setArrowFromButton}, panel: 'marker_panel', list: listname, isDefault: def @@ -477,7 +478,7 @@ svgEditor.addExtension('Markers', function (S) { let currentLang; const ret = { name: 'Markers', - svgicons: svgEditor.curConfig.extPath + 'markers-icons.xml', + svgicons: svgEditor.curConfig.extIconsPath + 'markers-icons.xml', callback () { $('#marker_panel').addClass('toolset').hide(); }, diff --git a/editor/extensions/ext-mathjax.js b/editor/extensions/ext-mathjax.js index 37db221b..c40e5260 100644 --- a/editor/extensions/ext-mathjax.js +++ b/editor/extensions/ext-mathjax.js @@ -1,4 +1,4 @@ -/* globals jQuery, MathJax, svgEditor, svgCanvas */ +/* globals jQuery, MathJax */ /* * ext-mathjax.js * @@ -7,9 +7,10 @@ * Copyright(c) 2013 Jo Segaert * */ - +import svgEditor from '../svg-editor.js'; svgEditor.addExtension('mathjax', function () { const $ = jQuery; + const svgCanvas = svgEditor.canvas; // Configuration of the MathJax extention. @@ -112,7 +113,7 @@ svgEditor.addExtension('mathjax', function () { return { name: 'MathJax', - svgicons: svgEditor.curConfig.extPath + 'mathjax-icons.xml', + svgicons: svgEditor.curConfig.extIconsPath + 'mathjax-icons.xml', buttons: [{ id: 'tool_mathjax', type: 'mode', @@ -164,8 +165,20 @@ svgEditor.addExtension('mathjax', function () { $('body').addClass('tex2jax_ignore'); // Now get (and run) the MathJax Library. - // Todo: insert script with `s.type = 'module';` once modules widely supported - // and if this ends up providing an ES6 module export + // Todo: insert script with modules once widely supported + // and if MathJax (and its `TeX-AMS-MML_SVG.js` dependency) ends up + // providing an ES6 module export: https://github.com/mathjax/MathJax/issues/1998 + /* + const s = document.createElement('script'); + const modularVersion = !('svgEditor' in window) || + !window.svgEditor || + window.svgEditor.modules !== false; + if (modularVersion) { + s.type = 'module'; // Make this the default when widely supported + } + s.src = curConfig.extPath + mathjaxSrcSecure; + // See `executeAfterLoads` in `svgutils.js` + */ $.getScript(mathjaxSrcSecure) .done(function (script, textStatus) { // When MathJax is loaded get the div where the math will be rendered. diff --git a/editor/extensions/ext-overview_window.js b/editor/extensions/ext-overview_window.js index 416ca61a..4090e74d 100644 --- a/editor/extensions/ext-overview_window.js +++ b/editor/extensions/ext-overview_window.js @@ -1,4 +1,4 @@ -/* globals jQuery, svgEditor, svgedit */ +/* globals jQuery */ /* * ext-overview_window.js * @@ -7,13 +7,14 @@ * Copyright(c) 2013 James Sacksteder * */ +import svgEditor from '../svg-editor.js'; -svgEditor.addExtension('overview_window', function () { +svgEditor.addExtension('overview_window', function ({isChrome, isIE}) { const $ = jQuery; const overviewWindowGlobals = {}; // Disabled in Chrome 48-, see https://github.com/SVG-Edit/svgedit/issues/26 and // https://code.google.com/p/chromium/issues/detail?id=565120. - if (svgedit.browser.isChrome()) { + if (isChrome()) { const verIndex = navigator.userAgent.indexOf('Chrome/') + 7; const chromeVersion = parseInt(navigator.userAgent.substring(verIndex), 10); if (chromeVersion < 49) { @@ -72,7 +73,7 @@ svgEditor.addExtension('overview_window', function () { let viewX = 640; let viewY = 480; - if (svgedit.browser.isIE()) { + if (isIE()) { // This has only been tested with Firefox 10 and IE 9 (without chrome frame). // I am not sure if if is Firefox or IE that is being non compliant here. // Either way the one that is noncompliant may become more compliant later. diff --git a/editor/extensions/ext-panning.js b/editor/extensions/ext-panning.js index 09c12722..aa2b69ea 100644 --- a/editor/extensions/ext-panning.js +++ b/editor/extensions/ext-panning.js @@ -1,4 +1,4 @@ -/* globals svgEditor, svgCanvas */ +import svgEditor from '../svg-editor.js'; /* * ext-panning.js * @@ -13,9 +13,10 @@ */ svgEditor.addExtension('ext-panning', function () { + const svgCanvas = svgEditor.canvas; return { name: 'Extension Panning', - svgicons: svgEditor.curConfig.extPath + 'ext-panning.xml', + svgicons: svgEditor.curConfig.extIconsPath + 'ext-panning.xml', buttons: [{ id: 'ext-panning', type: 'mode', diff --git a/editor/extensions/ext-php_savefile.js b/editor/extensions/ext-php_savefile.js index 2805d494..a80e4821 100644 --- a/editor/extensions/ext-php_savefile.js +++ b/editor/extensions/ext-php_savefile.js @@ -1,10 +1,11 @@ -/* globals jQuery, svgCanvas, svgEditor */ +/* globals jQuery */ // TODO: Might add support for "exportImage" custom // handler as in "ext-server_opensave.js" (and in savefile.php) - +import svgEditor from '../svg-editor.js'; svgEditor.addExtension('php_savefile', { callback () { const $ = jQuery; + const svgCanvas = svgEditor.canvas; function getFileNameFromTitle () { const title = svgCanvas.getDocumentTitle(); return title.trim(); diff --git a/editor/extensions/ext-polygon.js b/editor/extensions/ext-polygon.js index 24a278ce..8b1d3d8d 100644 --- a/editor/extensions/ext-polygon.js +++ b/editor/extensions/ext-polygon.js @@ -1,4 +1,4 @@ -/* globals jQuery, svgEditor, svgCanvas */ +/* globals jQuery */ /* * ext-polygon.js * @@ -7,8 +7,10 @@ * All rights reserved * */ +import svgEditor from '../svg-editor.js'; svgEditor.addExtension('polygon', function (S) { const $ = jQuery; + const svgCanvas = svgEditor.canvas; const // {svgcontent} = S, // addElem = S.addSvgElementFromJson, editingitex = false; @@ -88,7 +90,7 @@ svgEditor.addExtension('polygon', function (S) { semantics.appendChild(annotation); math.appendChild(semantics); // make an AJAX request to the server, to get the MathML - $.post(ajaxEndpoint, {tex, 'display': 'inline'}, function(data){ + $.post(ajaxEndpoint, {tex, display: 'inline'}, function(data){ const children = data.documentElement.childNodes; while (children.length > 0) { mrow.appendChild(svgdoc.adoptNode(children[0], true)); @@ -109,7 +111,7 @@ svgEditor.addExtension('polygon', function (S) { */ return { name: 'polygon', - svgicons: svgEditor.curConfig.extPath + 'polygon-icons.svg', + svgicons: svgEditor.curConfig.extIconsPath + 'polygon-icons.svg', buttons: [{ id: 'tool_polygon', type: 'mode', @@ -183,18 +185,18 @@ svgEditor.addExtension('polygon', function (S) { started = true; newFO = S.addSvgElementFromJson({ - 'element': 'polygon', - 'attr': { - 'cx': opts.start_x, - 'cy': opts.start_y, - 'id': S.getNextId(), - 'shape': 'regularPoly', - 'sides': document.getElementById('polySides').value, - 'orient': 'x', - 'edge': 0, - 'fill': rgb, - 'strokecolor': sRgb, - 'strokeWidth': sWidth + element: 'polygon', + attr: { + cx: opts.start_x, + cy: opts.start_y, + id: S.getNextId(), + shape: 'regularPoly', + sides: document.getElementById('polySides').value, + orient: 'x', + edge: 0, + fill: rgb, + strokecolor: sRgb, + strokeWidth: sWidth } }); diff --git a/editor/extensions/ext-server_moinsave.js b/editor/extensions/ext-server_moinsave.js index 2efb8027..f8c4f158 100644 --- a/editor/extensions/ext-server_moinsave.js +++ b/editor/extensions/ext-server_moinsave.js @@ -1,4 +1,4 @@ -/* globals jQuery, svgEditor, svgedit, svgCanvas, canvg */ +/* globals jQuery */ /* * ext-server_moinsave.js * @@ -10,11 +10,12 @@ * (I agree to dual license my work to additional GPLv2 or later) * */ +import svgEditor from '../svg-editor.js'; svgEditor.addExtension('server_opensave', { - callback () { + callback ({canvg, encode64, buildCanvgCallback}) { const $ = jQuery; - const Utils = svgedit.utilities; + const svgCanvas = svgEditor.canvas; const saveSvgAction = '/+modify'; // Create upload target (hidden iframe) @@ -25,18 +26,18 @@ svgEditor.addExtension('server_opensave', { const svg = '\n' + data; const qstr = $.param.querystring(); const name = qstr.substr(9).split('/+get/')[1]; - const svgData = Utils.encode64(svg); + const svgData = encode64(svg); if (!$('#export_canvas').length) { $('', {id: 'export_canvas'}).hide().appendTo('body'); } const c = $('#export_canvas')[0]; c.width = svgCanvas.contentW; c.height = svgCanvas.contentH; - Utils.buildCanvgCallback(function () { + buildCanvgCallback(function () { canvg(c, svg, {renderCallback () { const datauri = c.toDataURL('image/png'); // const {uiStrings} = svgEditor; - const pngData = Utils.encode64(datauri); // Brett: This encoding seems unnecessary + const pngData = encode64(datauri); // Brett: This encoding seems unnecessary /* const form = */ $('
    ').attr({ method: 'post', action: saveSvgAction + '/' + name, diff --git a/editor/extensions/ext-server_opensave.js b/editor/extensions/ext-server_opensave.js index 80b8d852..393d466c 100644 --- a/editor/extensions/ext-server_opensave.js +++ b/editor/extensions/ext-server_opensave.js @@ -1,4 +1,4 @@ -/* globals jQuery, svgEditor, svgedit, svgCanvas, canvg */ +/* globals jQuery */ /* * ext-server_opensave.js * @@ -7,10 +7,12 @@ * Copyright(c) 2010 Alexis Deveria * */ +import svgEditor from '../svg-editor.js'; svgEditor.addExtension('server_opensave', { - callback () { + callback ({canvg, decode64, encode64, buildCanvgCallback}) { const $ = jQuery; + const svgCanvas = svgEditor.canvas; function getFileNameFromTitle () { const title = svgCanvas.getDocumentTitle(); // We convert (to underscore) only those disallowed Win7 file name characters @@ -23,16 +25,19 @@ svgEditor.addExtension('server_opensave', { const support = $('')[0].download === ''; let a; if (support) { - a = $('hidden').attr({download: (filename || 'image') + suffix, href: uri}).css('display', 'none').appendTo('body'); + a = $('hidden').attr({ + download: (filename || 'image') + suffix, + href: uri + }).css('display', 'none').appendTo('body'); a[0].click(); return true; } } const saveSvgAction = svgEditor.curConfig.extPath + 'filesave.php', - saveImgAction = svgEditor.curConfig.extPath + 'filesave.php', + saveImgAction = svgEditor.curConfig.extPath + 'filesave.php'; // Create upload target (hidden iframe) - Utils = svgedit.utilities; + let cancelled = false; $(' - - - - - - - - - - - - - +

    This file frames all SVG-edit test pages. This should only include + tests known to work. These tests are known to pass 100% in the + following: + Firefox 3.6, Chrome 7, IE9 Preview 6 (1.9.8006.6000), Opera 10.63. + If a test is broken in this page, it is possible that YOU + broke it. Please do not submit code that breaks any of these tests.

    + + + + + + + + + + + + + + + + + - diff --git a/test/all_tests.js b/test/all_tests.js index 4cadd3c3..2d45f3a4 100644 --- a/test/all_tests.js +++ b/test/all_tests.js @@ -1,8 +1,8 @@ const iframes = document.querySelectorAll('iframe'); [...iframes].forEach((f) => { f.addEventListener('load', () => { - f.contentWindow.QUnit.done = () => { + f.contentWindow.QUnit.done(() => { f.style.height = (f.contentDocument.body.scrollHeight + 20) + 'px'; - }; + }); }); }); diff --git a/test/contextmenu_test.html b/test/contextmenu_test.html index 315d771c..93724ec4 100644 --- a/test/contextmenu_test.html +++ b/test/contextmenu_test.html @@ -4,7 +4,7 @@ Unit Tests for contextmenu.js - + - - - + +

    Unit Tests for contextmenu.js

      - + diff --git a/test/contextmenu_test.js b/test/contextmenu_test.js index dbe239d6..7097e8f3 100644 --- a/test/contextmenu_test.js +++ b/test/contextmenu_test.js @@ -1,60 +1,60 @@ /* eslint-env qunit */ -/* globals svgedit, equals */ +import * as contextmenu from '../editor/contextmenu.js'; // log function -QUnit.log = function (details) { +QUnit.log(function (details) { if (window.console && window.console.log) { window.console.log(details.result + ' :: ' + details.message); } -}; +}); function tearDown () { - svgedit.contextmenu.resetCustomMenus(); + contextmenu.resetCustomMenus(); } -module('svgedit.contextmenu'); +QUnit.module('svgedit.contextmenu'); -test('Test svgedit.contextmenu package', function () { - expect(4); +QUnit.test('Test svgedit.contextmenu package', function (assert) { + assert.expect(4); - ok(svgedit.contextmenu, 'contextmenu registered correctly'); - ok(svgedit.addContextMenuItem, 'addContextMenuItem registered correctly'); - ok(svgedit.contextmenu.hasCustomMenuItemHandler, 'contextmenu hasCustomHandler registered correctly'); - ok(svgedit.contextmenu.getCustomMenuItemHandler, 'contextmenu getCustomHandler registered correctly'); + assert.ok(contextmenu, 'contextmenu registered correctly'); + assert.ok(contextmenu.add, 'add registered correctly'); + assert.ok(contextmenu.hasCustomHandler, 'contextmenu hasCustomHandler registered correctly'); + assert.ok(contextmenu.getCustomHandler, 'contextmenu getCustomHandler registered correctly'); }); -test('Test svgedit.contextmenu does not add invalid menu item', function () { - expect(3); +QUnit.test('Test svgedit.contextmenu does not add invalid menu item', function (assert) { + assert.expect(3); - svgedit.addContextMenuItem({id: 'justanid'}); - ok(!svgedit.contextmenu.hasCustomMenuItemHandler('justanid'), 'menu item with just an id is invalid'); + contextmenu.add({id: 'justanid'}); + assert.ok(!contextmenu.hasCustomHandler('justanid'), 'menu item with just an id is invalid'); - svgedit.addContextMenuItem({id: 'idandlabel', label: 'anicelabel'}); - ok(!svgedit.contextmenu.hasCustomMenuItemHandler('idandlabel'), 'menu item with just an id and label is invalid'); + contextmenu.add({id: 'idandlabel', label: 'anicelabel'}); + assert.ok(!contextmenu.hasCustomHandler('idandlabel'), 'menu item with just an id and label is invalid'); - svgedit.addContextMenuItem({id: 'idandlabel', label: 'anicelabel', action: 'notafunction'}); - ok(!svgedit.contextmenu.hasCustomMenuItemHandler('idandlabel'), 'menu item with action that is not a function 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'); }); -test('Test svgedit.contextmenu adds valid menu item', function () { - expect(2); +QUnit.test('Test svgedit.contextmenu adds valid menu item', function (assert) { + assert.expect(2); const validItem = {id: 'valid', label: 'anicelabel', action () { alert('testing'); }}; - svgedit.addContextMenuItem(validItem); + contextmenu.add(validItem); - ok(svgedit.contextmenu.hasCustomMenuItemHandler('valid'), 'Valid menu item is added.'); - equals(svgedit.contextmenu.getCustomMenuItemHandler('valid'), validItem.action, 'Valid menu action is added.'); + assert.ok(contextmenu.hasCustomHandler('valid'), 'Valid menu item is added.'); + assert.equal(contextmenu.getCustomHandler('valid'), validItem.action, 'Valid menu action is added.'); tearDown(); }); -test('Test svgedit.contextmenu rejects valid duplicate menu item id', function () { - expect(1); +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'); }}; - svgedit.addContextMenuItem(validItem1); - svgedit.addContextMenuItem(validItem2); + contextmenu.add(validItem1); + contextmenu.add(validItem2); - equals(svgedit.contextmenu.getCustomMenuItemHandler('valid'), validItem1.action, 'duplicate menu item is rejected.'); + assert.equal(contextmenu.getCustomHandler('valid'), validItem1.action, 'duplicate menu item is rejected.'); tearDown(); }); diff --git a/test/coords_test.html b/test/coords_test.html index 34f13db4..18e529ac 100644 --- a/test/coords_test.html +++ b/test/coords_test.html @@ -4,25 +4,17 @@ Unit Tests for coords.js - + - - - - - - - - - - + +

      Unit Tests for svgedit.coords

        - + diff --git a/test/coords_test.js b/test/coords_test.js index 4571b024..314825b3 100644 --- a/test/coords_test.js +++ b/test/coords_test.js @@ -1,29 +1,31 @@ /* eslint-env qunit */ -/* globals svgedit, equals */ +import {NS} from '../editor/svgedit.js'; +import * as utilities from '../editor/svgutils.js'; +import * as coords from '../editor/coords.js'; // log function -QUnit.log = function (details) { +QUnit.log(function (details) { if (window.console && window.console.log) { window.console.log(details.result + ' :: ' + details.message); } -}; +}); const root = document.getElementById('root'); -const svgroot = document.createElementNS(svgedit.NS.SVG, 'svg'); +const svgroot = document.createElementNS(NS.SVG, 'svg'); svgroot.id = 'svgroot'; root.appendChild(svgroot); -const svg = document.createElementNS(svgedit.NS.SVG, 'svg'); +const svg = document.createElementNS(NS.SVG, 'svg'); svgroot.appendChild(svg); let elemId = 1; function setUp () { // Mock out editor context. - svgedit.utilities.init({ + utilities.init({ getSVGRoot () { return svg; }, getDOMDocument () { return null; }, getDOMContainer () { return null; } }); - svgedit.coords.init({ + coords.init({ getGridSnapping () { return false; }, getDrawing () { return { @@ -39,12 +41,12 @@ function tearDown () { } } -test('Test remapElement(translate) for rect', function () { - expect(4); +QUnit.test('Test remapElement(translate) for rect', function (assert) { + assert.expect(4); setUp(); - const rect = document.createElementNS(svgedit.NS.SVG, 'rect'); + const rect = document.createElementNS(NS.SVG, 'rect'); rect.setAttribute('x', '200'); rect.setAttribute('y', '150'); rect.setAttribute('width', '250'); @@ -64,21 +66,21 @@ test('Test remapElement(translate) for rect', function () { m.c = 0; m.d = 1; m.e = 100; m.f = -50; - svgedit.coords.remapElement(rect, attrs, m); + coords.remapElement(rect, attrs, m); - equals(rect.getAttribute('x'), '300'); - equals(rect.getAttribute('y'), '100'); - equals(rect.getAttribute('width'), '125'); - equals(rect.getAttribute('height'), '75'); + assert.equal(rect.getAttribute('x'), '300'); + assert.equal(rect.getAttribute('y'), '100'); + assert.equal(rect.getAttribute('width'), '125'); + assert.equal(rect.getAttribute('height'), '75'); tearDown(); }); -test('Test remapElement(scale) for rect', function () { - expect(4); +QUnit.test('Test remapElement(scale) for rect', function (assert) { + assert.expect(4); setUp(); - const rect = document.createElementNS(svgedit.NS.SVG, 'rect'); + const rect = document.createElementNS(NS.SVG, 'rect'); rect.setAttribute('width', '250'); rect.setAttribute('height', '120'); svg.appendChild(rect); @@ -96,21 +98,21 @@ test('Test remapElement(scale) for rect', function () { m.c = 0; m.d = 0.5; m.e = 0; m.f = 0; - svgedit.coords.remapElement(rect, attrs, m); + coords.remapElement(rect, attrs, m); - equals(rect.getAttribute('x'), '0'); - equals(rect.getAttribute('y'), '0'); - equals(rect.getAttribute('width'), '500'); - equals(rect.getAttribute('height'), '60'); + assert.equal(rect.getAttribute('x'), '0'); + assert.equal(rect.getAttribute('y'), '0'); + assert.equal(rect.getAttribute('width'), '500'); + assert.equal(rect.getAttribute('height'), '60'); tearDown(); }); -test('Test remapElement(translate) for circle', function () { - expect(3); +QUnit.test('Test remapElement(translate) for circle', function (assert) { + assert.expect(3); setUp(); - const circle = document.createElementNS(svgedit.NS.SVG, 'circle'); + const circle = document.createElementNS(NS.SVG, 'circle'); circle.setAttribute('cx', '200'); circle.setAttribute('cy', '150'); circle.setAttribute('r', '125'); @@ -128,20 +130,20 @@ test('Test remapElement(translate) for circle', function () { m.c = 0; m.d = 1; m.e = 100; m.f = -50; - svgedit.coords.remapElement(circle, attrs, m); + coords.remapElement(circle, attrs, m); - equals(circle.getAttribute('cx'), '300'); - equals(circle.getAttribute('cy'), '100'); - equals(circle.getAttribute('r'), '125'); + assert.equal(circle.getAttribute('cx'), '300'); + assert.equal(circle.getAttribute('cy'), '100'); + assert.equal(circle.getAttribute('r'), '125'); tearDown(); }); -test('Test remapElement(scale) for circle', function () { - expect(3); +QUnit.test('Test remapElement(scale) for circle', function (assert) { + assert.expect(3); setUp(); - const circle = document.createElementNS(svgedit.NS.SVG, 'circle'); + const circle = document.createElementNS(NS.SVG, 'circle'); circle.setAttribute('cx', '200'); circle.setAttribute('cy', '150'); circle.setAttribute('r', '250'); @@ -159,21 +161,21 @@ test('Test remapElement(scale) for circle', function () { m.c = 0; m.d = 0.5; m.e = 0; m.f = 0; - svgedit.coords.remapElement(circle, attrs, m); + coords.remapElement(circle, attrs, m); - equals(circle.getAttribute('cx'), '400'); - equals(circle.getAttribute('cy'), '75'); + assert.equal(circle.getAttribute('cx'), '400'); + assert.equal(circle.getAttribute('cy'), '75'); // Radius is the minimum that fits in the new bounding box. - equals(circle.getAttribute('r'), '125'); + assert.equal(circle.getAttribute('r'), '125'); tearDown(); }); -test('Test remapElement(translate) for ellipse', function () { - expect(4); +QUnit.test('Test remapElement(translate) for ellipse', function (assert) { + assert.expect(4); setUp(); - const ellipse = document.createElementNS(svgedit.NS.SVG, 'ellipse'); + const ellipse = document.createElementNS(NS.SVG, 'ellipse'); ellipse.setAttribute('cx', '200'); ellipse.setAttribute('cy', '150'); ellipse.setAttribute('rx', '125'); @@ -193,21 +195,21 @@ test('Test remapElement(translate) for ellipse', function () { m.c = 0; m.d = 1; m.e = 100; m.f = -50; - svgedit.coords.remapElement(ellipse, attrs, m); + coords.remapElement(ellipse, attrs, m); - equals(ellipse.getAttribute('cx'), '300'); - equals(ellipse.getAttribute('cy'), '100'); - equals(ellipse.getAttribute('rx'), '125'); - equals(ellipse.getAttribute('ry'), '75'); + assert.equal(ellipse.getAttribute('cx'), '300'); + assert.equal(ellipse.getAttribute('cy'), '100'); + assert.equal(ellipse.getAttribute('rx'), '125'); + assert.equal(ellipse.getAttribute('ry'), '75'); tearDown(); }); -test('Test remapElement(scale) for ellipse', function () { - expect(4); +QUnit.test('Test remapElement(scale) for ellipse', function (assert) { + assert.expect(4); setUp(); - const ellipse = document.createElementNS(svgedit.NS.SVG, 'ellipse'); + const ellipse = document.createElementNS(NS.SVG, 'ellipse'); ellipse.setAttribute('cx', '200'); ellipse.setAttribute('cy', '150'); ellipse.setAttribute('rx', '250'); @@ -227,21 +229,21 @@ test('Test remapElement(scale) for ellipse', function () { m.c = 0; m.d = 0.5; m.e = 0; m.f = 0; - svgedit.coords.remapElement(ellipse, attrs, m); + coords.remapElement(ellipse, attrs, m); - equals(ellipse.getAttribute('cx'), '400'); - equals(ellipse.getAttribute('cy'), '75'); - equals(ellipse.getAttribute('rx'), '500'); - equals(ellipse.getAttribute('ry'), '60'); + assert.equal(ellipse.getAttribute('cx'), '400'); + assert.equal(ellipse.getAttribute('cy'), '75'); + assert.equal(ellipse.getAttribute('rx'), '500'); + assert.equal(ellipse.getAttribute('ry'), '60'); tearDown(); }); -test('Test remapElement(translate) for line', function () { - expect(4); +QUnit.test('Test remapElement(translate) for line', function (assert) { + assert.expect(4); setUp(); - const line = document.createElementNS(svgedit.NS.SVG, 'line'); + const line = document.createElementNS(NS.SVG, 'line'); line.setAttribute('x1', '50'); line.setAttribute('y1', '100'); line.setAttribute('x2', '120'); @@ -261,21 +263,21 @@ test('Test remapElement(translate) for line', function () { m.c = 0; m.d = 1; m.e = 100; m.f = -50; - svgedit.coords.remapElement(line, attrs, m); + coords.remapElement(line, attrs, m); - equals(line.getAttribute('x1'), '150'); - equals(line.getAttribute('y1'), '50'); - equals(line.getAttribute('x2'), '220'); - equals(line.getAttribute('y2'), '150'); + assert.equal(line.getAttribute('x1'), '150'); + assert.equal(line.getAttribute('y1'), '50'); + assert.equal(line.getAttribute('x2'), '220'); + assert.equal(line.getAttribute('y2'), '150'); tearDown(); }); -test('Test remapElement(scale) for line', function () { - expect(4); +QUnit.test('Test remapElement(scale) for line', function (assert) { + assert.expect(4); setUp(); - const line = document.createElementNS(svgedit.NS.SVG, 'line'); + const line = document.createElementNS(NS.SVG, 'line'); line.setAttribute('x1', '50'); line.setAttribute('y1', '100'); line.setAttribute('x2', '120'); @@ -295,21 +297,21 @@ test('Test remapElement(scale) for line', function () { m.c = 0; m.d = 0.5; m.e = 0; m.f = 0; - svgedit.coords.remapElement(line, attrs, m); + coords.remapElement(line, attrs, m); - equals(line.getAttribute('x1'), '100'); - equals(line.getAttribute('y1'), '50'); - equals(line.getAttribute('x2'), '240'); - equals(line.getAttribute('y2'), '100'); + assert.equal(line.getAttribute('x1'), '100'); + assert.equal(line.getAttribute('y1'), '50'); + assert.equal(line.getAttribute('x2'), '240'); + assert.equal(line.getAttribute('y2'), '100'); tearDown(); }); -test('Test remapElement(translate) for text', function () { - expect(2); +QUnit.test('Test remapElement(translate) for text', function (assert) { + assert.expect(2); setUp(); - const text = document.createElementNS(svgedit.NS.SVG, 'text'); + const text = document.createElementNS(NS.SVG, 'text'); text.setAttribute('x', '50'); text.setAttribute('y', '100'); svg.appendChild(text); @@ -325,10 +327,10 @@ test('Test remapElement(translate) for text', function () { m.c = 0; m.d = 1; m.e = 100; m.f = -50; - svgedit.coords.remapElement(text, attrs, m); + coords.remapElement(text, attrs, m); - equals(text.getAttribute('x'), '150'); - equals(text.getAttribute('y'), '50'); + assert.equal(text.getAttribute('x'), '150'); + assert.equal(text.getAttribute('y'), '50'); tearDown(); }); diff --git a/test/draw_test.html b/test/draw_test.html index fbc7a72e..03768c93 100644 --- a/test/draw_test.html +++ b/test/draw_test.html @@ -4,25 +4,18 @@ Unit Tests for draw.js - + - - - - - - - - - - - + + + +

        Unit Tests for draw.js

          - + diff --git a/test/draw_test.js b/test/draw_test.js index 56e8dc5d..a5593bcc 100644 --- a/test/draw_test.js +++ b/test/draw_test.js @@ -1,26 +1,39 @@ +/* globals sinon, sinonTest */ /* eslint-env qunit */ -/* globals svgedit, equals */ +import {NS} from '../editor/svgedit.js'; +import * as draw from '../editor/draw.js'; +import * as units from '../editor/units.js'; +import sinonQunit from './sinon/sinon-qunit.js'; + +sinon.test = sinonTest(sinon, { + injectIntoThis: true, + injectInto: null, + properties: ['spy', 'stub', 'mock', 'clock', 'sandbox'], + useFakeTimers: false, + useFakeServer: false +}); +sinonQunit({sinon, QUnit}); // log function -QUnit.log = function (details) { +QUnit.log(function (details) { if (window.console && window.console.log) { window.console.log(details.result + ' :: ' + details.message); } -}; -const {NS} = svgedit; -const LAYER_CLASS = svgedit.draw.Layer.CLASS_NAME; +}); + +const LAYER_CLASS = draw.Layer.CLASS_NAME; const NONCE = 'foo'; const LAYER1 = 'Layer 1'; const LAYER2 = 'Layer 2'; const LAYER3 = 'Layer 3'; const PATH_ATTR = { // clone will convert relative to absolute, so the test for equality fails. - // 'd': 'm7.38867,57.38867c0,-27.62431 22.37569,-50 50,-50c27.62431,0 50,22.37569 50,50c0,27.62431 -22.37569,50 -50,50c-27.62431,0 -50,-22.37569 -50,-50z', - 'd': 'M7.389,57.389C7.389,29.764 29.764,7.389 57.389,7.389C85.013,7.389 107.389,29.764 107.389,57.389C107.389,85.013 85.013,107.389 57.389,107.389C29.764,107.389 7.389,85.013 7.389,57.389z', - 'transform': 'rotate(45 57.388671875000036,57.388671874999986) ', + // d: 'm7.38867,57.38867c0,-27.62431 22.37569,-50 50,-50c27.62431,0 50,22.37569 50,50c0,27.62431 -22.37569,50 -50,50c-27.62431,0 -50,-22.37569 -50,-50z', + d: 'M7.389,57.389C7.389,29.764 29.764,7.389 57.389,7.389C85.013,7.389 107.389,29.764 107.389,57.389C107.389,85.013 85.013,107.389 57.389,107.389C29.764,107.389 7.389,85.013 7.389,57.389z', + transform: 'rotate(45 57.388671875000036,57.388671874999986) ', 'stroke-width': '5', - 'stroke': '#660000', - 'fill': '#ff0000' + stroke: '#660000', + fill: '#ff0000' }; const svg = document.createElementNS(NS.SVG, 'svg'); @@ -33,13 +46,27 @@ const svgN = document.createElementNS(NS.SVG, 'svg'); svgN.setAttributeNS(NS.XMLNS, 'xmlns:se', NS.SE); svgN.setAttributeNS(NS.SE, 'se:nonce', NONCE); -svgedit.units.init({ - // used by svgedit.units.shortFloat - call path: cloneLayer -> copyElem -> convertPath -> pathDSegment -> shortFloat +units.init({ + // used by units.shortFloat - call path: cloneLayer -> copyElem -> convertPath -> pathDSegment -> shortFloat getRoundDigits () { return 3; } }); +// Simplifying from svgcanvas.js usage +const idprefix = 'svg_'; +const svgcontent = document.createElementNS(NS.SVG, 'svg'); +const currentDrawing_ = new draw.Drawing(svgcontent, idprefix); +const getCurrentDrawing = function () { + return currentDrawing_; +}; +const setCurrentGroup = (cg) => { +}; +draw.init({ + getCurrentDrawing, + setCurrentGroup +}); + function createSVGElement (jsonMap) { - const elem = document.createElementNS(svgedit.NS.SVG, jsonMap['element']); + const elem = document.createElementNS(NS.SVG, jsonMap['element']); for (const attr in jsonMap['attr']) { elem.setAttribute(attr, jsonMap['attr'][attr]); } @@ -70,29 +97,29 @@ const setupSvgWith3Layers = function (svgElem) { const createSomeElementsInGroup = function (group) { group.appendChild(createSVGElement({ - 'element': 'path', - 'attr': PATH_ATTR + element: 'path', + attr: PATH_ATTR })); // group.appendChild(createSVGElement({ - // 'element': 'path', - // 'attr': {'d': 'M0,1L2,3'} + // element: 'path', + // attr: {d: 'M0,1L2,3'} // })); group.appendChild(createSVGElement({ - 'element': 'rect', - 'attr': {'x': '0', 'y': '1', 'width': '5', 'height': '10'} + element: 'rect', + attr: {x: '0', y: '1', width: '5', height: '10'} })); group.appendChild(createSVGElement({ - 'element': 'line', - 'attr': {'x1': '0', 'y1': '1', 'x2': '5', 'y2': '6'} + element: 'line', + attr: {x1: '0', y1: '1', x2: '5', y2: '6'} })); const g = createSVGElement({ - 'element': 'g', - 'attr': {} + element: 'g', + attr: {} }); g.appendChild(createSVGElement({ - 'element': 'rect', - 'attr': {'x': '0', 'y': '1', 'width': '5', 'height': '10'} + element: 'rect', + attr: {x: '0', y: '1', width: '5', height: '10'} })); group.appendChild(g); return 4; @@ -102,107 +129,107 @@ const cleanupSvg = function (svgElem) { while (svgElem.firstChild) { svgElem.removeChild(svgElem.firstChild); } }; -module('svgedit.draw.Drawing', { - setup () { +QUnit.module('svgedit.draw.Drawing', { + beforeEach () { }, - teardown () { + afterEach () { } }); -test('Test draw module', function () { - expect(4); +QUnit.test('Test draw module', function (assert) { + assert.expect(4); - ok(svgedit.draw); - equals(typeof svgedit.draw, typeof {}); + assert.ok(draw); + assert.equal(typeof draw, typeof {}); - ok(svgedit.draw.Drawing); - equals(typeof svgedit.draw.Drawing, typeof function () {}); + assert.ok(draw.Drawing); + assert.equal(typeof draw.Drawing, typeof function () {}); }); -test('Test document creation', function () { - expect(3); +QUnit.test('Test document creation', function (assert) { + assert.expect(3); let doc; try { - doc = new svgedit.draw.Drawing(); - ok(false, 'Created drawing without a valid element'); + doc = new draw.Drawing(); + assert.ok(false, 'Created drawing without a valid element'); } catch (e) { - ok(true); + assert.ok(true); } try { - doc = new svgedit.draw.Drawing(svg); - ok(doc); - equals(typeof doc, typeof {}); + doc = new draw.Drawing(svg); + assert.ok(doc); + assert.equal(typeof doc, typeof {}); } catch (e) { - ok(false, 'Could not create document from valid element: ' + e); + assert.ok(false, 'Could not create document from valid element: ' + e); } }); -test('Test nonce', function () { - expect(7); +QUnit.test('Test nonce', function (assert) { + assert.expect(7); - let doc = new svgedit.draw.Drawing(svg); - equals(doc.getNonce(), ''); + let doc = new draw.Drawing(svg); + assert.equal(doc.getNonce(), ''); - doc = new svgedit.draw.Drawing(svgN); - equals(doc.getNonce(), NONCE); - equals(doc.getSvgElem().getAttributeNS(NS.SE, 'nonce'), NONCE); + doc = new draw.Drawing(svgN); + assert.equal(doc.getNonce(), NONCE); + assert.equal(doc.getSvgElem().getAttributeNS(NS.SE, 'nonce'), NONCE); doc.clearNonce(); - ok(!doc.getNonce()); - ok(!doc.getSvgElem().getAttributeNS(NS.SE, 'se:nonce')); + assert.ok(!doc.getNonce()); + assert.ok(!doc.getSvgElem().getAttributeNS(NS.SE, 'se:nonce')); doc.setNonce(NONCE); - equals(doc.getNonce(), NONCE); - equals(doc.getSvgElem().getAttributeNS(NS.SE, 'nonce'), NONCE); + assert.equal(doc.getNonce(), NONCE); + assert.equal(doc.getSvgElem().getAttributeNS(NS.SE, 'nonce'), NONCE); }); -test('Test getId() and getNextId() without nonce', function () { - expect(7); +QUnit.test('Test getId() and getNextId() without nonce', function (assert) { + assert.expect(7); const elem2 = document.createElementNS(NS.SVG, 'circle'); elem2.id = 'svg_2'; svg.appendChild(elem2); - const doc = new svgedit.draw.Drawing(svg); + const doc = new draw.Drawing(svg); - equals(doc.getId(), 'svg_0'); + assert.equal(doc.getId(), 'svg_0'); - equals(doc.getNextId(), 'svg_1'); - equals(doc.getId(), 'svg_1'); + assert.equal(doc.getNextId(), 'svg_1'); + assert.equal(doc.getId(), 'svg_1'); - equals(doc.getNextId(), 'svg_3'); - equals(doc.getId(), 'svg_3'); + assert.equal(doc.getNextId(), 'svg_3'); + assert.equal(doc.getId(), 'svg_3'); - equals(doc.getNextId(), 'svg_4'); - equals(doc.getId(), 'svg_4'); + assert.equal(doc.getNextId(), 'svg_4'); + assert.equal(doc.getId(), 'svg_4'); // clean out svg document cleanupSvg(svg); }); -test('Test getId() and getNextId() with prefix without nonce', function () { - expect(7); +QUnit.test('Test getId() and getNextId() with prefix without nonce', function (assert) { + assert.expect(7); const prefix = 'Bar-'; - const doc = new svgedit.draw.Drawing(svg, prefix); + const doc = new draw.Drawing(svg, prefix); - equals(doc.getId(), prefix + '0'); + assert.equal(doc.getId(), prefix + '0'); - equals(doc.getNextId(), prefix + '1'); - equals(doc.getId(), prefix + '1'); + assert.equal(doc.getNextId(), prefix + '1'); + assert.equal(doc.getId(), prefix + '1'); - equals(doc.getNextId(), prefix + '2'); - equals(doc.getId(), prefix + '2'); + assert.equal(doc.getNextId(), prefix + '2'); + assert.equal(doc.getId(), prefix + '2'); - equals(doc.getNextId(), prefix + '3'); - equals(doc.getId(), prefix + '3'); + assert.equal(doc.getNextId(), prefix + '3'); + assert.equal(doc.getId(), prefix + '3'); cleanupSvg(svg); }); -test('Test getId() and getNextId() with nonce', function () { - expect(7); +QUnit.test('Test getId() and getNextId() with nonce', function (assert) { + assert.expect(7); const prefix = 'svg_' + NONCE; @@ -210,146 +237,146 @@ test('Test getId() and getNextId() with nonce', function () { elem2.id = prefix + '_2'; svgN.appendChild(elem2); - const doc = new svgedit.draw.Drawing(svgN); + const doc = new draw.Drawing(svgN); - equals(doc.getId(), prefix + '_0'); + assert.equal(doc.getId(), prefix + '_0'); - equals(doc.getNextId(), prefix + '_1'); - equals(doc.getId(), prefix + '_1'); + assert.equal(doc.getNextId(), prefix + '_1'); + assert.equal(doc.getId(), prefix + '_1'); - equals(doc.getNextId(), prefix + '_3'); - equals(doc.getId(), prefix + '_3'); + assert.equal(doc.getNextId(), prefix + '_3'); + assert.equal(doc.getId(), prefix + '_3'); - equals(doc.getNextId(), prefix + '_4'); - equals(doc.getId(), prefix + '_4'); + assert.equal(doc.getNextId(), prefix + '_4'); + assert.equal(doc.getId(), prefix + '_4'); cleanupSvg(svgN); }); -test('Test getId() and getNextId() with prefix with nonce', function () { - expect(7); +QUnit.test('Test getId() and getNextId() with prefix with nonce', function (assert) { + assert.expect(7); const PREFIX = 'Bar-'; - const doc = new svgedit.draw.Drawing(svgN, PREFIX); + const doc = new draw.Drawing(svgN, PREFIX); const prefix = PREFIX + NONCE + '_'; - equals(doc.getId(), prefix + '0'); + assert.equal(doc.getId(), prefix + '0'); - equals(doc.getNextId(), prefix + '1'); - equals(doc.getId(), prefix + '1'); + assert.equal(doc.getNextId(), prefix + '1'); + assert.equal(doc.getId(), prefix + '1'); - equals(doc.getNextId(), prefix + '2'); - equals(doc.getId(), prefix + '2'); + assert.equal(doc.getNextId(), prefix + '2'); + assert.equal(doc.getId(), prefix + '2'); - equals(doc.getNextId(), prefix + '3'); - equals(doc.getId(), prefix + '3'); + assert.equal(doc.getNextId(), prefix + '3'); + assert.equal(doc.getId(), prefix + '3'); cleanupSvg(svgN); }); -test('Test releaseId()', function () { - expect(6); +QUnit.test('Test releaseId()', function (assert) { + assert.expect(6); - const doc = new svgedit.draw.Drawing(svg); + const doc = new draw.Drawing(svg); const firstId = doc.getNextId(); /* const secondId = */ doc.getNextId(); const result = doc.releaseId(firstId); - ok(result); - equals(doc.getNextId(), firstId); - equals(doc.getNextId(), 'svg_3'); + assert.ok(result); + assert.equal(doc.getNextId(), firstId); + assert.equal(doc.getNextId(), 'svg_3'); - ok(!doc.releaseId('bad-id')); - ok(doc.releaseId(firstId)); - ok(!doc.releaseId(firstId)); + assert.ok(!doc.releaseId('bad-id')); + assert.ok(doc.releaseId(firstId)); + assert.ok(!doc.releaseId(firstId)); cleanupSvg(svg); }); -test('Test getNumLayers', function () { - expect(3); - const drawing = new svgedit.draw.Drawing(svg); - equals(typeof drawing.getNumLayers, typeof function () {}); - equals(drawing.getNumLayers(), 0); +QUnit.test('Test getNumLayers', function (assert) { + assert.expect(3); + const drawing = new draw.Drawing(svg); + assert.equal(typeof drawing.getNumLayers, typeof function () {}); + assert.equal(drawing.getNumLayers(), 0); setupSvgWith3Layers(svg); drawing.identifyLayers(); - equals(drawing.getNumLayers(), 3); + assert.equal(drawing.getNumLayers(), 3); cleanupSvg(svg); }); -test('Test hasLayer', function () { - expect(5); +QUnit.test('Test hasLayer', function (assert) { + assert.expect(5); setupSvgWith3Layers(svg); - const drawing = new svgedit.draw.Drawing(svg); + const drawing = new draw.Drawing(svg); drawing.identifyLayers(); - equals(typeof drawing.hasLayer, typeof function () {}); - ok(!drawing.hasLayer('invalid-layer')); + assert.equal(typeof drawing.hasLayer, typeof function () {}); + assert.ok(!drawing.hasLayer('invalid-layer')); - ok(drawing.hasLayer(LAYER3)); - ok(drawing.hasLayer(LAYER2)); - ok(drawing.hasLayer(LAYER1)); + assert.ok(drawing.hasLayer(LAYER3)); + assert.ok(drawing.hasLayer(LAYER2)); + assert.ok(drawing.hasLayer(LAYER1)); cleanupSvg(svg); }); -test('Test identifyLayers() with empty document', function () { - expect(11); +QUnit.test('Test identifyLayers() with empty document', function (assert) { + assert.expect(11); - const drawing = new svgedit.draw.Drawing(svg); - equals(drawing.getCurrentLayer(), null); + const drawing = new draw.Drawing(svg); + assert.equal(drawing.getCurrentLayer(), null); // By default, an empty document gets an empty group created. drawing.identifyLayers(); // Check that element now has one child node - ok(drawing.getSvgElem().hasChildNodes()); - equals(drawing.getSvgElem().childNodes.length, 1); + assert.ok(drawing.getSvgElem().hasChildNodes()); + assert.equal(drawing.getSvgElem().childNodes.length, 1); // Check that all_layers are correctly set up. - equals(drawing.getNumLayers(), 1); + assert.equal(drawing.getNumLayers(), 1); const emptyLayer = drawing.all_layers[0]; - ok(emptyLayer); + assert.ok(emptyLayer); const layerGroup = emptyLayer.getGroup(); - equals(layerGroup, drawing.getSvgElem().firstChild); - equals(layerGroup.tagName, 'g'); - equals(layerGroup.getAttribute('class'), LAYER_CLASS); - ok(layerGroup.hasChildNodes()); - equals(layerGroup.childNodes.length, 1); + assert.equal(layerGroup, drawing.getSvgElem().firstChild); + assert.equal(layerGroup.tagName, 'g'); + assert.equal(layerGroup.getAttribute('class'), LAYER_CLASS); + assert.ok(layerGroup.hasChildNodes()); + assert.equal(layerGroup.childNodes.length, 1); const firstChild = layerGroup.childNodes.item(0); - equals(firstChild.tagName, 'title'); + assert.equal(firstChild.tagName, 'title'); cleanupSvg(svg); }); -test('Test identifyLayers() with some layers', function () { - expect(8); +QUnit.test('Test identifyLayers() with some layers', function (assert) { + assert.expect(8); - const drawing = new svgedit.draw.Drawing(svg); + const drawing = new draw.Drawing(svg); setupSvgWith3Layers(svg); - equals(svg.childNodes.length, 3); + assert.equal(svg.childNodes.length, 3); drawing.identifyLayers(); - equals(drawing.getNumLayers(), 3); - equals(drawing.all_layers[0].getGroup(), svg.childNodes.item(0)); - equals(drawing.all_layers[1].getGroup(), svg.childNodes.item(1)); - equals(drawing.all_layers[2].getGroup(), svg.childNodes.item(2)); + assert.equal(drawing.getNumLayers(), 3); + assert.equal(drawing.all_layers[0].getGroup(), svg.childNodes.item(0)); + assert.equal(drawing.all_layers[1].getGroup(), svg.childNodes.item(1)); + assert.equal(drawing.all_layers[2].getGroup(), svg.childNodes.item(2)); - equals(drawing.all_layers[0].getGroup().getAttribute('class'), LAYER_CLASS); - equals(drawing.all_layers[1].getGroup().getAttribute('class'), LAYER_CLASS); - equals(drawing.all_layers[2].getGroup().getAttribute('class'), LAYER_CLASS); + assert.equal(drawing.all_layers[0].getGroup().getAttribute('class'), LAYER_CLASS); + assert.equal(drawing.all_layers[1].getGroup().getAttribute('class'), LAYER_CLASS); + assert.equal(drawing.all_layers[2].getGroup().getAttribute('class'), LAYER_CLASS); cleanupSvg(svg); }); -test('Test identifyLayers() with some layers and orphans', function () { - expect(14); +QUnit.test('Test identifyLayers() with some layers and orphans', function (assert) { + assert.expect(14); setupSvgWith3Layers(svg); @@ -358,115 +385,115 @@ test('Test identifyLayers() with some layers and orphans', function () { svg.appendChild(orphan1); svg.appendChild(orphan2); - equals(svg.childNodes.length, 5); + assert.equal(svg.childNodes.length, 5); - const drawing = new svgedit.draw.Drawing(svg); + const drawing = new draw.Drawing(svg); drawing.identifyLayers(); - equals(drawing.getNumLayers(), 4); - equals(drawing.all_layers[0].getGroup(), svg.childNodes.item(0)); - equals(drawing.all_layers[1].getGroup(), svg.childNodes.item(1)); - equals(drawing.all_layers[2].getGroup(), svg.childNodes.item(2)); - equals(drawing.all_layers[3].getGroup(), svg.childNodes.item(3)); + assert.equal(drawing.getNumLayers(), 4); + assert.equal(drawing.all_layers[0].getGroup(), svg.childNodes.item(0)); + assert.equal(drawing.all_layers[1].getGroup(), svg.childNodes.item(1)); + assert.equal(drawing.all_layers[2].getGroup(), svg.childNodes.item(2)); + assert.equal(drawing.all_layers[3].getGroup(), svg.childNodes.item(3)); - equals(drawing.all_layers[0].getGroup().getAttribute('class'), LAYER_CLASS); - equals(drawing.all_layers[1].getGroup().getAttribute('class'), LAYER_CLASS); - equals(drawing.all_layers[2].getGroup().getAttribute('class'), LAYER_CLASS); - equals(drawing.all_layers[3].getGroup().getAttribute('class'), LAYER_CLASS); + assert.equal(drawing.all_layers[0].getGroup().getAttribute('class'), LAYER_CLASS); + assert.equal(drawing.all_layers[1].getGroup().getAttribute('class'), LAYER_CLASS); + assert.equal(drawing.all_layers[2].getGroup().getAttribute('class'), LAYER_CLASS); + assert.equal(drawing.all_layers[3].getGroup().getAttribute('class'), LAYER_CLASS); const layer4 = drawing.all_layers[3].getGroup(); - equals(layer4.tagName, 'g'); - equals(layer4.childNodes.length, 3); - equals(layer4.childNodes.item(1), orphan1); - equals(layer4.childNodes.item(2), orphan2); + assert.equal(layer4.tagName, 'g'); + assert.equal(layer4.childNodes.length, 3); + assert.equal(layer4.childNodes.item(1), orphan1); + assert.equal(layer4.childNodes.item(2), orphan2); cleanupSvg(svg); }); -test('Test getLayerName()', function () { - expect(4); +QUnit.test('Test getLayerName()', function (assert) { + assert.expect(4); - const drawing = new svgedit.draw.Drawing(svg); + const drawing = new draw.Drawing(svg); setupSvgWith3Layers(svg); drawing.identifyLayers(); - equals(drawing.getNumLayers(), 3); - equals(drawing.getLayerName(0), LAYER1); - equals(drawing.getLayerName(1), LAYER2); - equals(drawing.getLayerName(2), LAYER3); + assert.equal(drawing.getNumLayers(), 3); + assert.equal(drawing.getLayerName(0), LAYER1); + assert.equal(drawing.getLayerName(1), LAYER2); + assert.equal(drawing.getLayerName(2), LAYER3); cleanupSvg(svg); }); -test('Test getCurrentLayer()', function () { - expect(4); +QUnit.test('Test getCurrentLayer()', function (assert) { + assert.expect(4); - const drawing = new svgedit.draw.Drawing(svg); + const drawing = new draw.Drawing(svg); setupSvgWith3Layers(svg); drawing.identifyLayers(); - ok(drawing.getCurrentLayer); - equals(typeof drawing.getCurrentLayer, typeof function () {}); - ok(drawing.getCurrentLayer()); - equals(drawing.getCurrentLayer(), drawing.all_layers[2].getGroup()); + assert.ok(drawing.getCurrentLayer); + assert.equal(typeof drawing.getCurrentLayer, typeof function () {}); + assert.ok(drawing.getCurrentLayer()); + assert.equal(drawing.getCurrentLayer(), drawing.all_layers[2].getGroup()); cleanupSvg(svg); }); -test('Test setCurrentLayer() and getCurrentLayerName()', function () { - expect(6); +QUnit.test('Test setCurrentLayer() and getCurrentLayerName()', function (assert) { + assert.expect(6); - const drawing = new svgedit.draw.Drawing(svg); + const drawing = new draw.Drawing(svg); setupSvgWith3Layers(svg); drawing.identifyLayers(); - ok(drawing.setCurrentLayer); - equals(typeof drawing.setCurrentLayer, typeof function () {}); + assert.ok(drawing.setCurrentLayer); + assert.equal(typeof drawing.setCurrentLayer, typeof function () {}); drawing.setCurrentLayer(LAYER2); - equals(drawing.getCurrentLayerName(), LAYER2); - equals(drawing.getCurrentLayer(), drawing.all_layers[1].getGroup()); + assert.equal(drawing.getCurrentLayerName(), LAYER2); + assert.equal(drawing.getCurrentLayer(), drawing.all_layers[1].getGroup()); drawing.setCurrentLayer(LAYER3); - equals(drawing.getCurrentLayerName(), LAYER3); - equals(drawing.getCurrentLayer(), drawing.all_layers[2].getGroup()); + assert.equal(drawing.getCurrentLayerName(), LAYER3); + assert.equal(drawing.getCurrentLayer(), drawing.all_layers[2].getGroup()); cleanupSvg(svg); }); -test('Test setCurrentLayerName()', function () { +QUnit.test('Test setCurrentLayerName()', function (assert) { const mockHrService = { changeElement: this.spy() }; - const drawing = new svgedit.draw.Drawing(svg); + const drawing = new draw.Drawing(svg); setupSvgWith3Layers(svg); drawing.identifyLayers(); - ok(drawing.setCurrentLayerName); - equals(typeof drawing.setCurrentLayerName, typeof function () {}); + assert.ok(drawing.setCurrentLayerName); + assert.equal(typeof drawing.setCurrentLayerName, typeof function () {}); const oldName = drawing.getCurrentLayerName(); const newName = 'New Name'; - ok(drawing.layer_map[oldName]); - equals(drawing.layer_map[newName], undefined); // newName shouldn't exist. + assert.ok(drawing.layer_map[oldName]); + assert.equal(drawing.layer_map[newName], undefined); // newName shouldn't exist. const result = drawing.setCurrentLayerName(newName, mockHrService); - equals(result, newName); - equals(drawing.getCurrentLayerName(), newName); + assert.equal(result, newName); + assert.equal(drawing.getCurrentLayerName(), newName); // Was the map updated? - equals(drawing.layer_map[oldName], undefined); - equals(drawing.layer_map[newName], drawing.current_layer); + assert.equal(drawing.layer_map[oldName], undefined); + assert.equal(drawing.layer_map[newName], drawing.current_layer); // Was mockHrService called? - ok(mockHrService.changeElement.calledOnce); - equals(oldName, mockHrService.changeElement.getCall(0).args[1]['#text']); - equals(newName, mockHrService.changeElement.getCall(0).args[0].textContent); + assert.ok(mockHrService.changeElement.calledOnce); + assert.equal(oldName, mockHrService.changeElement.getCall(0).args[1]['#text']); + assert.equal(newName, mockHrService.changeElement.getCall(0).args[0].textContent); cleanupSvg(svg); }); -test('Test createLayer()', function () { - expect(10); +QUnit.test('Test createLayer()', function (assert) { + assert.expect(10); const mockHrService = { startBatchCommand: this.spy(), @@ -474,29 +501,29 @@ test('Test createLayer()', function () { insertElement: this.spy() }; - const drawing = new svgedit.draw.Drawing(svg); + const drawing = new draw.Drawing(svg); setupSvgWith3Layers(svg); drawing.identifyLayers(); - ok(drawing.createLayer); - equals(typeof drawing.createLayer, typeof function () {}); + assert.ok(drawing.createLayer); + assert.equal(typeof drawing.createLayer, typeof function () {}); const NEW_LAYER_NAME = 'Layer A'; const layerG = drawing.createLayer(NEW_LAYER_NAME, mockHrService); - equals(drawing.getNumLayers(), 4); - equals(layerG, drawing.getCurrentLayer()); - equals(layerG.getAttribute('class'), LAYER_CLASS); - equals(NEW_LAYER_NAME, drawing.getCurrentLayerName()); - equals(NEW_LAYER_NAME, drawing.getLayerName(3)); + assert.equal(drawing.getNumLayers(), 4); + assert.equal(layerG, drawing.getCurrentLayer()); + assert.equal(layerG.getAttribute('class'), LAYER_CLASS); + assert.equal(NEW_LAYER_NAME, drawing.getCurrentLayerName()); + assert.equal(NEW_LAYER_NAME, drawing.getLayerName(3)); - equals(layerG, mockHrService.insertElement.getCall(0).args[0]); - ok(mockHrService.startBatchCommand.calledOnce); - ok(mockHrService.endBatchCommand.calledOnce); + assert.equal(layerG, mockHrService.insertElement.getCall(0).args[0]); + assert.ok(mockHrService.startBatchCommand.calledOnce); + assert.ok(mockHrService.endBatchCommand.calledOnce); cleanupSvg(svg); }); -test('Test mergeLayer()', function () { +QUnit.test('Test mergeLayer()', function (assert) { const mockHrService = { startBatchCommand: this.spy(), endBatchCommand: this.spy(), @@ -504,35 +531,35 @@ test('Test mergeLayer()', function () { removeElement: this.spy() }; - const drawing = new svgedit.draw.Drawing(svg); + const drawing = new draw.Drawing(svg); const layers = setupSvgWith3Layers(svg); const elementCount = createSomeElementsInGroup(layers[2]) + 1; // +1 for title element - equals(layers[1].childElementCount, 1); - equals(layers[2].childElementCount, elementCount); + assert.equal(layers[1].childElementCount, 1); + assert.equal(layers[2].childElementCount, elementCount); drawing.identifyLayers(); - equals(drawing.getCurrentLayer(), layers[2]); + assert.equal(drawing.getCurrentLayer(), layers[2]); - ok(drawing.mergeLayer); - equals(typeof drawing.mergeLayer, typeof function () {}); + assert.ok(drawing.mergeLayer); + assert.equal(typeof drawing.mergeLayer, typeof function () {}); drawing.mergeLayer(mockHrService); - equals(drawing.getNumLayers(), 2); - equals(svg.childElementCount, 2); - equals(drawing.getCurrentLayer(), layers[1]); - equals(layers[1].childElementCount, elementCount); + assert.equal(drawing.getNumLayers(), 2); + assert.equal(svg.childElementCount, 2); + assert.equal(drawing.getCurrentLayer(), layers[1]); + assert.equal(layers[1].childElementCount, elementCount); // check history record - ok(mockHrService.startBatchCommand.calledOnce); - ok(mockHrService.endBatchCommand.calledOnce); - equals(mockHrService.startBatchCommand.getCall(0).args[0], 'Merge Layer'); - equals(mockHrService.moveElement.callCount, elementCount - 1); // -1 because the title was not moved. - equals(mockHrService.removeElement.callCount, 2); // remove group and title. + assert.ok(mockHrService.startBatchCommand.calledOnce); + assert.ok(mockHrService.endBatchCommand.calledOnce); + assert.equal(mockHrService.startBatchCommand.getCall(0).args[0], 'Merge Layer'); + assert.equal(mockHrService.moveElement.callCount, elementCount - 1); // -1 because the title was not moved. + assert.equal(mockHrService.removeElement.callCount, 2); // remove group and title. cleanupSvg(svg); }); -test('Test mergeLayer() when no previous layer to merge', function () { +QUnit.test('Test mergeLayer() when no previous layer to merge', function (assert) { const mockHrService = { startBatchCommand: this.spy(), endBatchCommand: this.spy(), @@ -540,31 +567,31 @@ test('Test mergeLayer() when no previous layer to merge', function () { removeElement: this.spy() }; - const drawing = new svgedit.draw.Drawing(svg); + const drawing = new draw.Drawing(svg); const layers = setupSvgWith3Layers(svg); drawing.identifyLayers(); drawing.setCurrentLayer(LAYER1); - equals(drawing.getCurrentLayer(), layers[0]); + assert.equal(drawing.getCurrentLayer(), layers[0]); drawing.mergeLayer(mockHrService); - equals(drawing.getNumLayers(), 3); - equals(svg.childElementCount, 3); - equals(drawing.getCurrentLayer(), layers[0]); - equals(layers[0].childElementCount, 1); - equals(layers[1].childElementCount, 1); - equals(layers[2].childElementCount, 1); + assert.equal(drawing.getNumLayers(), 3); + assert.equal(svg.childElementCount, 3); + assert.equal(drawing.getCurrentLayer(), layers[0]); + assert.equal(layers[0].childElementCount, 1); + assert.equal(layers[1].childElementCount, 1); + assert.equal(layers[2].childElementCount, 1); // check history record - equals(mockHrService.startBatchCommand.callCount, 0); - equals(mockHrService.endBatchCommand.callCount, 0); - equals(mockHrService.moveElement.callCount, 0); - equals(mockHrService.removeElement.callCount, 0); + assert.equal(mockHrService.startBatchCommand.callCount, 0); + assert.equal(mockHrService.endBatchCommand.callCount, 0); + assert.equal(mockHrService.moveElement.callCount, 0); + assert.equal(mockHrService.removeElement.callCount, 0); cleanupSvg(svg); }); -test('Test mergeAllLayers()', function () { +QUnit.test('Test mergeAllLayers()', function (assert) { const mockHrService = { startBatchCommand: this.spy(), endBatchCommand: this.spy(), @@ -572,221 +599,221 @@ test('Test mergeAllLayers()', function () { removeElement: this.spy() }; - const drawing = new svgedit.draw.Drawing(svg); + const drawing = new draw.Drawing(svg); const layers = setupSvgWith3Layers(svg); const elementCount = createSomeElementsInGroup(layers[0]) + 1; // +1 for title element createSomeElementsInGroup(layers[1]); createSomeElementsInGroup(layers[2]); - equals(layers[0].childElementCount, elementCount); - equals(layers[1].childElementCount, elementCount); - equals(layers[2].childElementCount, elementCount); + assert.equal(layers[0].childElementCount, elementCount); + assert.equal(layers[1].childElementCount, elementCount); + assert.equal(layers[2].childElementCount, elementCount); drawing.identifyLayers(); - ok(drawing.mergeAllLayers); - equals(typeof drawing.mergeAllLayers, typeof function () {}); + assert.ok(drawing.mergeAllLayers); + assert.equal(typeof drawing.mergeAllLayers, typeof function () {}); drawing.mergeAllLayers(mockHrService); - equals(drawing.getNumLayers(), 1); - equals(svg.childElementCount, 1); - equals(drawing.getCurrentLayer(), layers[0]); - equals(layers[0].childElementCount, elementCount * 3 - 2); // -2 because two titles were deleted. + assert.equal(drawing.getNumLayers(), 1); + assert.equal(svg.childElementCount, 1); + assert.equal(drawing.getCurrentLayer(), layers[0]); + assert.equal(layers[0].childElementCount, elementCount * 3 - 2); // -2 because two titles were deleted. // check history record - equals(mockHrService.startBatchCommand.callCount, 3); // mergeAllLayers + 2 * mergeLayer - equals(mockHrService.endBatchCommand.callCount, 3); - equals(mockHrService.startBatchCommand.getCall(0).args[0], 'Merge all Layers'); - equals(mockHrService.startBatchCommand.getCall(1).args[0], 'Merge Layer'); - equals(mockHrService.startBatchCommand.getCall(2).args[0], 'Merge Layer'); + assert.equal(mockHrService.startBatchCommand.callCount, 3); // mergeAllLayers + 2 * mergeLayer + assert.equal(mockHrService.endBatchCommand.callCount, 3); + assert.equal(mockHrService.startBatchCommand.getCall(0).args[0], 'Merge all Layers'); + assert.equal(mockHrService.startBatchCommand.getCall(1).args[0], 'Merge Layer'); + assert.equal(mockHrService.startBatchCommand.getCall(2).args[0], 'Merge Layer'); // moveElement count is times 3 instead of 2, because one layer's elements were moved twice. // moveElement count is minus 3 because the three titles were not moved. - equals(mockHrService.moveElement.callCount, elementCount * 3 - 3); - equals(mockHrService.removeElement.callCount, 2 * 2); // remove group and title twice. + assert.equal(mockHrService.moveElement.callCount, elementCount * 3 - 3); + assert.equal(mockHrService.removeElement.callCount, 2 * 2); // remove group and title twice. cleanupSvg(svg); }); -test('Test cloneLayer()', function () { +QUnit.test('Test cloneLayer()', function (assert) { const mockHrService = { startBatchCommand: this.spy(), endBatchCommand: this.spy(), insertElement: this.spy() }; - const drawing = new svgedit.draw.Drawing(svg); + const drawing = new draw.Drawing(svg); const layers = setupSvgWith3Layers(svg); const layer3 = layers[2]; const elementCount = createSomeElementsInGroup(layer3) + 1; // +1 for title element - equals(layer3.childElementCount, elementCount); + assert.equal(layer3.childElementCount, elementCount); drawing.identifyLayers(); - ok(drawing.cloneLayer); - equals(typeof drawing.cloneLayer, typeof function () {}); + assert.ok(drawing.cloneLayer); + assert.equal(typeof drawing.cloneLayer, typeof function () {}); const clone = drawing.cloneLayer('clone', mockHrService); - equals(drawing.getNumLayers(), 4); - equals(svg.childElementCount, 4); - equals(drawing.getCurrentLayer(), clone); - equals(clone.childElementCount, elementCount); + assert.equal(drawing.getNumLayers(), 4); + assert.equal(svg.childElementCount, 4); + assert.equal(drawing.getCurrentLayer(), clone); + assert.equal(clone.childElementCount, elementCount); // check history record - ok(mockHrService.startBatchCommand.calledOnce); // mergeAllLayers + 2 * mergeLayer - ok(mockHrService.endBatchCommand.calledOnce); - equals(mockHrService.startBatchCommand.getCall(0).args[0], 'Duplicate Layer'); - equals(mockHrService.insertElement.callCount, 1); - equals(mockHrService.insertElement.getCall(0).args[0], clone); + assert.ok(mockHrService.startBatchCommand.calledOnce); // mergeAllLayers + 2 * mergeLayer + assert.ok(mockHrService.endBatchCommand.calledOnce); + assert.equal(mockHrService.startBatchCommand.getCall(0).args[0], 'Duplicate Layer'); + assert.equal(mockHrService.insertElement.callCount, 1); + assert.equal(mockHrService.insertElement.getCall(0).args[0], clone); // check that path is cloned properly - equals(clone.childNodes.length, elementCount); + assert.equal(clone.childNodes.length, elementCount); const path = clone.childNodes[1]; - equals(path.id, 'svg_1'); - equals(path.getAttribute('d'), PATH_ATTR.d); - equals(path.getAttribute('transform'), PATH_ATTR.transform); - equals(path.getAttribute('fill'), PATH_ATTR.fill); - equals(path.getAttribute('stroke'), PATH_ATTR.stroke); - equals(path.getAttribute('stroke-width'), PATH_ATTR['stroke-width']); + assert.equal(path.id, 'svg_1'); + assert.equal(path.getAttribute('d'), PATH_ATTR.d); + assert.equal(path.getAttribute('transform'), PATH_ATTR.transform); + assert.equal(path.getAttribute('fill'), PATH_ATTR.fill); + assert.equal(path.getAttribute('stroke'), PATH_ATTR.stroke); + assert.equal(path.getAttribute('stroke-width'), PATH_ATTR['stroke-width']); // check that g is cloned properly const g = clone.childNodes[4]; - equals(g.childNodes.length, 1); - equals(g.id, 'svg_4'); + assert.equal(g.childNodes.length, 1); + assert.equal(g.id, 'svg_4'); cleanupSvg(svg); }); -test('Test getLayerVisibility()', function () { - expect(5); +QUnit.test('Test getLayerVisibility()', function (assert) { + assert.expect(5); - const drawing = new svgedit.draw.Drawing(svg); + const drawing = new draw.Drawing(svg); setupSvgWith3Layers(svg); drawing.identifyLayers(); - ok(drawing.getLayerVisibility); - equals(typeof drawing.getLayerVisibility, typeof function () {}); - ok(drawing.getLayerVisibility(LAYER1)); - ok(drawing.getLayerVisibility(LAYER2)); - ok(drawing.getLayerVisibility(LAYER3)); + assert.ok(drawing.getLayerVisibility); + assert.equal(typeof drawing.getLayerVisibility, typeof function () {}); + assert.ok(drawing.getLayerVisibility(LAYER1)); + assert.ok(drawing.getLayerVisibility(LAYER2)); + assert.ok(drawing.getLayerVisibility(LAYER3)); cleanupSvg(svg); }); -test('Test setLayerVisibility()', function () { - expect(6); +QUnit.test('Test setLayerVisibility()', function (assert) { + assert.expect(6); - const drawing = new svgedit.draw.Drawing(svg); + const drawing = new draw.Drawing(svg); setupSvgWith3Layers(svg); drawing.identifyLayers(); - ok(drawing.setLayerVisibility); - equals(typeof drawing.setLayerVisibility, typeof function () {}); + assert.ok(drawing.setLayerVisibility); + assert.equal(typeof drawing.setLayerVisibility, typeof function () {}); drawing.setLayerVisibility(LAYER3, false); drawing.setLayerVisibility(LAYER2, true); drawing.setLayerVisibility(LAYER1, false); - ok(!drawing.getLayerVisibility(LAYER1)); - ok(drawing.getLayerVisibility(LAYER2)); - ok(!drawing.getLayerVisibility(LAYER3)); + assert.ok(!drawing.getLayerVisibility(LAYER1)); + assert.ok(drawing.getLayerVisibility(LAYER2)); + assert.ok(!drawing.getLayerVisibility(LAYER3)); drawing.setLayerVisibility(LAYER3, 'test-string'); - ok(!drawing.getLayerVisibility(LAYER3)); + assert.ok(!drawing.getLayerVisibility(LAYER3)); cleanupSvg(svg); }); -test('Test getLayerOpacity()', function () { - expect(5); +QUnit.test('Test getLayerOpacity()', function (assert) { + assert.expect(5); - const drawing = new svgedit.draw.Drawing(svg); + const drawing = new draw.Drawing(svg); setupSvgWith3Layers(svg); drawing.identifyLayers(); - ok(drawing.getLayerOpacity); - equals(typeof drawing.getLayerOpacity, typeof function () {}); - ok(drawing.getLayerOpacity(LAYER1) === 1.0); - ok(drawing.getLayerOpacity(LAYER2) === 1.0); - ok(drawing.getLayerOpacity(LAYER3) === 1.0); + assert.ok(drawing.getLayerOpacity); + 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); cleanupSvg(svg); }); -test('Test setLayerOpacity()', function () { - expect(6); +QUnit.test('Test setLayerOpacity()', function (assert) { + assert.expect(6); - const drawing = new svgedit.draw.Drawing(svg); + const drawing = new draw.Drawing(svg); setupSvgWith3Layers(svg); drawing.identifyLayers(); - ok(drawing.setLayerOpacity); - equals(typeof drawing.setLayerOpacity, typeof function () {}); + assert.ok(drawing.setLayerOpacity); + assert.equal(typeof drawing.setLayerOpacity, typeof function () {}); drawing.setLayerOpacity(LAYER1, 0.4); drawing.setLayerOpacity(LAYER2, 'invalid-string'); drawing.setLayerOpacity(LAYER3, -1.4); - ok(drawing.getLayerOpacity(LAYER1) === 0.4); - QUnit.log({result: 'layer2 opacity', message: drawing.getLayerOpacity(LAYER2)}); - ok(drawing.getLayerOpacity(LAYER2) === 1.0); - ok(drawing.getLayerOpacity(LAYER3) === 1.0); + assert.strictEqual(drawing.getLayerOpacity(LAYER1), 0.4); + console.log('layer2 opacity ' + drawing.getLayerOpacity(LAYER2)); + assert.strictEqual(drawing.getLayerOpacity(LAYER2), 1.0); + assert.strictEqual(drawing.getLayerOpacity(LAYER3), 1.0); drawing.setLayerOpacity(LAYER3, 100); - ok(drawing.getLayerOpacity(LAYER3) === 1.0); + assert.strictEqual(drawing.getLayerOpacity(LAYER3), 1.0); cleanupSvg(svg); }); -test('Test deleteCurrentLayer()', function () { - expect(6); +QUnit.test('Test deleteCurrentLayer()', function (assert) { + assert.expect(6); - const drawing = new svgedit.draw.Drawing(svg); + const drawing = new draw.Drawing(svg); setupSvgWith3Layers(svg); drawing.identifyLayers(); drawing.setCurrentLayer(LAYER2); const curLayer = drawing.getCurrentLayer(); - equals(curLayer, drawing.all_layers[1].getGroup()); + assert.equal(curLayer, drawing.all_layers[1].getGroup()); const deletedLayer = drawing.deleteCurrentLayer(); - equals(curLayer, deletedLayer); - equals(2, drawing.getNumLayers()); - equals(LAYER1, drawing.all_layers[0].getName()); - equals(LAYER3, drawing.all_layers[1].getName()); - equals(drawing.getCurrentLayer(), drawing.all_layers[1].getGroup()); + assert.equal(curLayer, deletedLayer); + assert.equal(drawing.getNumLayers(), 2); + assert.equal(LAYER1, drawing.all_layers[0].getName()); + assert.equal(LAYER3, drawing.all_layers[1].getName()); + assert.equal(drawing.getCurrentLayer(), drawing.all_layers[1].getGroup()); }); -test('Test svgedit.draw.randomizeIds()', function () { - expect(9); +QUnit.test('Test svgedit.draw.randomizeIds()', function (assert) { + assert.expect(9); // Confirm in LET_DOCUMENT_DECIDE mode that the document decides // if there is a nonce. - let drawing = new svgedit.draw.Drawing(svgN.cloneNode(true)); - ok(!!drawing.getNonce()); + let drawing = new draw.Drawing(svgN.cloneNode(true)); + assert.ok(!!drawing.getNonce()); - drawing = new svgedit.draw.Drawing(svg.cloneNode(true)); - 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. - svgedit.draw.randomizeIds(true, drawing); - ok(!!drawing.getNonce()); + draw.randomizeIds(true, drawing); + assert.ok(!!drawing.getNonce()); // Confirm new drawings in ALWAYS_RANDOMIZE mode have a nonce. - drawing = new svgedit.draw.Drawing(svg.cloneNode(true)); - ok(!!drawing.getNonce()); + drawing = new draw.Drawing(svg.cloneNode(true)); + assert.ok(!!drawing.getNonce()); drawing.clearNonce(); - ok(!drawing.getNonce()); + assert.ok(!drawing.getNonce()); // Confirm new drawings in NEVER_RANDOMIZE mode do not have a nonce // but that their se:nonce attribute is left alone. - svgedit.draw.randomizeIds(false, drawing); - ok(!drawing.getNonce()); - ok(!!drawing.getSvgElem().getAttributeNS(NS.SE, 'nonce')); + draw.randomizeIds(false, drawing); + assert.ok(!drawing.getNonce()); + assert.ok(!!drawing.getSvgElem().getAttributeNS(NS.SE, 'nonce')); - drawing = new svgedit.draw.Drawing(svg.cloneNode(true)); - ok(!drawing.getNonce()); + drawing = new draw.Drawing(svg.cloneNode(true)); + assert.ok(!drawing.getNonce()); - drawing = new svgedit.draw.Drawing(svgN.cloneNode(true)); - ok(!drawing.getNonce()); + drawing = new draw.Drawing(svgN.cloneNode(true)); + assert.ok(!drawing.getNonce()); }); diff --git a/test/history_test.html b/test/history_test.html index 8f11f420..faefe45a 100644 --- a/test/history_test.html +++ b/test/history_test.html @@ -4,24 +4,22 @@ Unit Tests for history.js - + - - - - + +

          Unit Tests for history.js

            -