move to standard linter for simpler configuration

master
JFH 2021-12-28 11:02:29 -03:00
parent 258e2bd6a1
commit fdcfc8a253
251 changed files with 19760 additions and 19935 deletions

View File

@ -1,30 +0,0 @@
node_modules
ignore
coverage
instrumented
dist
docs/jsdoc
archive
jsconfig.json
releases
!.eslintrc.js
!.ncurc.js
es-dev-server.config.js
nyc.config.js
svgedit-custom.css
# Vendor/minified files
src/editor/jquery.min.js
# Previously minified though exporting
src/editor/js-hotkeys
src/editor/extensions/ext-mathjax/mathjax
# jquery files
src/editor/jgraduate/jQuery.jPicker.js

View File

@ -1,96 +0,0 @@
"use strict";
module.exports = {
extends: [
"plugin:compat/recommended",
"plugin:node/recommended",
"plugin:no-unsanitized/DOM",
"plugin:promise/recommended",
"plugin:import/errors",
"plugin:markdown/recommended",
"eslint:recommended"
],
plugins: [ "jsdoc", "promise", "html", "import" ],
parserOptions: {
ecmaVersion: 2020,
sourceType: "module"
},
env: {
browser: true,
es6: true
},
rules: {
/** @todo len should probably more 120-150 */
"max-len": [ "warn", { "code": 250 } ],
"indent": [ "error", 2 ],
"no-var": "error",
/** @todo this rule should be actived. needs some courage as this rule is broken in many places... */
"one-var": [ "error", "never" ],
/** @todo jsdoc should be made warn or error */
"valid-jsdoc": "off",
/** @todo no param reassign creates too many warnings but should be a warning */
"no-param-reassign": "off",
/** @todo no use before define creates too many warnings but should be a warning */
"no-use-before-define": "off",
/** @todo camel case creates too many warnings but should be a warning */
"camelcase": "off",
"comma-dangle": [ "error" ],
"node/no-unsupported-features/es-syntax": 0,
"no-unused-vars": [ "error", { "argsIgnorePattern": "^_" } ],
"semi" : "error",
"prefer-const": "error",
"no-trailing-spaces": "error",
"array-bracket-spacing": [ "error", "always" ],
"comma-spacing": "error",
"object-curly-spacing": [ "error", "always" ],
"no-console": [
"warn",
{ "allow": [ "warn", "error", "info", "table" ] }
],
"arrow-parens": [ "error", "always" ]
},
overrides: [
{
files: [ 'cypress/**/*' ],
extends: [
"plugin:cypress/recommended"
],
env: {
mocha: true,
node: true
},
globals: { "assert": true },
rules: {
// with ci, instrumented is not created before linter
"import/no-unresolved": [ 2, { ignore: [ 'instrumented' ] } ],
"node/no-missing-import": 0,
"node/no-unpublished-import": 0,
"node/no-unpublished-require": 0
}
},
{
files: [ 'docs/**/*' ],
rules: { // md files have example that don't need a strict checking
"no-undef": 0,
"import/no-unresolved": 0,
"node/no-missing-import": 0,
"jsdoc/check-examples": [
"warn",
{
rejectExampleCodeRegex: "^`",
checkDefaults: true,
checkParams: true,
checkProperties: true
}
]
}
},
{
files: [ 'src/editor/locale/*.js' ],
rules: { // lang files may have long length
"max-len": "off",
"camelcase": "off"
}
}
]
};

1
.gitignore vendored
View File

@ -9,7 +9,6 @@ coverage
instrumented
.nyc_output
.vscode
.eslintcache
.DS_Store
.idea
dist

View File

@ -2,5 +2,4 @@ lgtm.yml
coverage/**
.nyc_output
instrumented/**
.eslintcache
node_modules/**

View File

@ -1,14 +1,14 @@
import {
visitAndApproveStorage
} from '../../support/ui-test-helper.js';
} from '../../support/ui-test-helper.js'
describe('UI - Clipboard', function () {
beforeEach(() => {
visitAndApproveStorage();
});
visitAndApproveStorage()
})
it('Editor - Copy and paste', () => {
cy.get('#tool_source').click();
cy.get('#tool_source').click()
cy.get('#svg_source_textarea')
.type('{selectall}', { force: true })
@ -17,47 +17,47 @@ describe('UI - Clipboard', function () {
<title>Layer 1</title>
<circle cx="100" cy="100" r="50" fill="#FF0000" id="testCircle" stroke="#000000" stroke-width="5"/>
</g>
</svg>`, { force: true, parseSpecialCharSequences: false });
cy.get('#tool_source_save').click();
cy.get('#testCircle').should('exist');
cy.get('#svg_1').should('not.exist');
cy.get('#svg_2').should('not.exist');
</svg>`, { force: true, parseSpecialCharSequences: false })
cy.get('#tool_source_save').click()
cy.get('#testCircle').should('exist')
cy.get('#svg_1').should('not.exist')
cy.get('#svg_2').should('not.exist')
// Copy.
cy.get('#testCircle').click().rightclick();
cy.get('#cmenu_canvas a[href="#copy"]').click({ force: true });
cy.get('#testCircle').click().rightclick()
cy.get('#cmenu_canvas a[href="#copy"]').click({ force: true })
// Paste.
// Scrollbars fail to recenter in Cypress test. Works fine in reality.
// Thus forcing click is needed since workspace is mostly offscreen.
cy.get('#svgroot').rightclick({ force: true });
cy.get('#cmenu_canvas a[href="#paste"]').click({ force: true });
cy.get('#testCircle').should('exist');
cy.get('#svg_1').should('exist');
cy.get('#svg_2').should('not.exist');
cy.get('#svgroot').rightclick({ force: true })
cy.get('#cmenu_canvas a[href="#paste"]').click({ force: true })
cy.get('#testCircle').should('exist')
cy.get('#svg_1').should('exist')
cy.get('#svg_2').should('not.exist')
// Cut.
cy.get('#testCircle').click().rightclick();
cy.get('#cmenu_canvas a[href="#cut"]').click({ force: true });
cy.get('#testCircle').should('not.exist');
cy.get('#svg_1').should('exist');
cy.get('#svg_2').should('not.exist');
cy.get('#testCircle').click().rightclick()
cy.get('#cmenu_canvas a[href="#cut"]').click({ force: true })
cy.get('#testCircle').should('not.exist')
cy.get('#svg_1').should('exist')
cy.get('#svg_2').should('not.exist')
// Paste.
// Scrollbars fail to recenter in Cypress test. Works fine in reality.
// Thus forcing click is needed since workspace is mostly offscreen.
cy.get('#svgroot').rightclick({ force: true });
cy.get('#cmenu_canvas a[href="#paste"]').click({ force: true });
cy.get('#testCircle').should('not.exist');
cy.get('#svg_1').should('exist');
cy.get('#svg_2').should('exist');
cy.get('#svgroot').rightclick({ force: true })
cy.get('#cmenu_canvas a[href="#paste"]').click({ force: true })
cy.get('#testCircle').should('not.exist')
cy.get('#svg_1').should('exist')
cy.get('#svg_2').should('exist')
// Delete.
cy.get('#svg_2').click().rightclick();
cy.get('#cmenu_canvas a[href="#delete"]').click({ force: true });
cy.get('#svg_1').click().rightclick();
cy.get('#cmenu_canvas a[href="#delete"]').click({ force: true });
cy.get('#svg_1').should('not.exist');
cy.get('#svg_2').should('not.exist');
});
});
cy.get('#svg_2').click().rightclick()
cy.get('#cmenu_canvas a[href="#delete"]').click({ force: true })
cy.get('#svg_1').click().rightclick()
cy.get('#cmenu_canvas a[href="#delete"]').click({ force: true })
cy.get('#svg_1').should('not.exist')
cy.get('#svg_2').should('not.exist')
})
})

View File

@ -1,15 +1,15 @@
import {
visitAndApproveStorage
} from '../../support/ui-test-helper.js';
} from '../../support/ui-test-helper.js'
describe('UI - Control Points', function () {
beforeEach(() => {
visitAndApproveStorage();
});
visitAndApproveStorage()
})
it('Editor - No parameters: Drag control point of arc path', () => {
const randomOffset = () => 2 + Math.round(10 + Math.random() * 40);
cy.get('#tool_source').click();
const randomOffset = () => 2 + Math.round(10 + Math.random() * 40)
cy.get('#tool_source').click()
cy.get('#svg_source_textarea')
.type('{selectall}', { force: true })
.type(`<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg">
@ -17,18 +17,18 @@ describe('UI - Control Points', function () {
<title>Layer 1</title>
<path d="m187,194a114,62 0 1 0 219,2" id="svg_1" fill="#FF0000" stroke="#000000" stroke-width="5"/>
</g>
</svg>`, { force: true, parseSpecialCharSequences: false });
cy.get('#tool_source_save').click({ force: true });
</svg>`, { force: true, parseSpecialCharSequences: false })
cy.get('#tool_source_save').click({ force: true })
cy.get('#svg_1').click({ force: true }).click({ force: true });
cy.get('#svg_1').click({ force: true }).click({ force: true })
cy.get('#pathpointgrip_0').trigger('mousedown', { which: 1, force: true })
.trigger('mousemove', randomOffset(), randomOffset(), { force: true })
.trigger('mouseup', { force: true });
.trigger('mouseup', { force: true })
cy.get('#pathpointgrip_1').trigger('mousedown', { which: 1, force: true })
.trigger('mousemove', randomOffset(), randomOffset(), { force: true })
.trigger('mouseup', { force: true });
.trigger('mouseup', { force: true })
cy.get('#svg_1[d]').should('not.contain', 'NaN');
});
});
cy.get('#svg_1[d]').should('not.contain', 'NaN')
})
})

View File

@ -1,20 +1,20 @@
import {
visitAndApproveStorage, openMainMenu
} from '../../support/ui-test-helper.js';
} from '../../support/ui-test-helper.js'
describe('UI - Export tests', function () {
beforeEach(() => {
visitAndApproveStorage();
});
visitAndApproveStorage()
})
it('Editor - No parameters: Has export button', () => {
openMainMenu();
cy.get('#tool_export');
});
openMainMenu()
cy.get('#tool_export')
})
it('Editor - No parameters: Export button clicking; dialog opens', () => {
openMainMenu();
cy.get('#tool_export').click({ force: true });
cy.get('#dialog_content select');
});
});
openMainMenu()
cy.get('#tool_export').click({ force: true })
cy.get('#dialog_content select')
})
})

View File

@ -1,15 +1,15 @@
import {
visitAndApproveStorage
} from '../../../support/ui-test-helper.js';
} from '../../../support/ui-test-helper.js'
// See https://github.com/SVG-Edit/svgedit/issues/359
describe('Fix issue 359', function () {
beforeEach(() => {
visitAndApproveStorage();
});
visitAndApproveStorage()
})
it('can undo without throwing', function () {
cy.get('#tool_source').click();
cy.get('#tool_source').click()
cy.get('#svg_source_textarea')
.type('{selectall}', { force: true })
.type(`<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg">
@ -17,10 +17,10 @@ describe('Fix issue 359', function () {
<title>Layer 1</title>
<rect fill="#ffff00" height="70" width="165" x="179.5" y="146.5"/>
</g>
</svg>`, { parseSpecialCharSequences: false, force: true });
cy.get('#tool_source_save').click();
cy.get('#tool_undo').click();
cy.get('#tool_redo').click(); // test also redo to make the test more comprehensive
</svg>`, { parseSpecialCharSequences: false, force: true })
cy.get('#tool_source_save').click()
cy.get('#tool_undo').click()
cy.get('#tool_redo').click() // test also redo to make the test more comprehensive
// if the undo throws an error to the console, the test will fail
});
});
})
})

View File

@ -1,15 +1,15 @@
import {
visitAndApproveStorage
} from '../../../support/ui-test-helper.js';
} from '../../../support/ui-test-helper.js'
// See https://github.com/SVG-Edit/svgedit/issues/407
describe('Fix issue 407', function () {
beforeEach(() => {
visitAndApproveStorage();
});
visitAndApproveStorage()
})
it('can enter edit on text child', function () {
cy.get('#tool_source').click();
cy.get('#tool_source').click()
cy.get('#svg_source_textarea')
.type('{selectall}', { force: true })
.type(`<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg">
@ -20,16 +20,16 @@ describe('Fix issue 407', function () {
<text fill="#000000" id="a_text" text-anchor="middle" x="260.5" xml:space="preserve" y="192.5">hello</text>
</g>
</g>
</svg>`, { force: true, parseSpecialCharSequences: false });
cy.get('#tool_source_save').click();
cy.get('#svg_1').click().dblclick();
cy.get('#a_text').should('exist');
</svg>`, { force: true, parseSpecialCharSequences: false })
cy.get('#tool_source_save').click()
cy.get('#svg_1').click().dblclick()
cy.get('#a_text').should('exist')
cy.get('#a_text')
.trigger('mousedown', { which: 1, force: true })
.trigger('mouseup', { force: true })
.dblclick({ force: true });
.dblclick({ force: true })
// svgedit use the #text text field to capture the text
cy.get('#text').type('1234', { force: true });
cy.get('#a_text').should('have.text', 'he1234llo');
});
});
cy.get('#text').type('1234', { force: true })
cy.get('#a_text').should('have.text', 'he1234llo')
})
})

View File

@ -1,15 +1,15 @@
import {
visitAndApproveStorage
} from '../../../support/ui-test-helper.js';
} from '../../../support/ui-test-helper.js'
// See https://github.com/SVG-Edit/svgedit/issues/408
describe('Fix issue 408', function () {
beforeEach(() => {
visitAndApproveStorage();
});
visitAndApproveStorage()
})
it('should not throw when showing/saving svg content', function () {
cy.get('#tool_source').click();
cy.get('#tool_source').click()
cy.get('#svg_source_textarea')
.type('{selectall}', { force: true })
.type(`<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
@ -20,10 +20,10 @@ describe('Fix issue 408', function () {
<circle cx="117.5" cy="87.5" fill="#ffff00" r="19.84943" stroke="#000000" />
</g>
</g>
</svg>`, { force: true, parseSpecialCharSequences: false });
cy.get('#tool_source_save').click();
cy.get('#svg_6').click().dblclick(); // change context
cy.get('#tool_source').click(); // reopen tool_source
cy.get('#tool_source_save').should('exist'); // The save button should be here if it does not throw
});
});
</svg>`, { force: true, parseSpecialCharSequences: false })
cy.get('#tool_source_save').click()
cy.get('#svg_6').click().dblclick() // change context
cy.get('#tool_source').click() // reopen tool_source
cy.get('#tool_source_save').should('exist') // The save button should be here if it does not throw
})
})

View File

@ -1,15 +1,15 @@
import {
visitAndApproveStorage
} from '../../../support/ui-test-helper.js';
} from '../../../support/ui-test-helper.js'
// See https://github.com/SVG-Edit/svgedit/issues/423
describe('Fix issue 423', function () {
beforeEach(() => {
visitAndApproveStorage();
});
visitAndApproveStorage()
})
it('should not throw when undoing the move', function () {
cy.get('#tool_source').click();
cy.get('#tool_source').click()
cy.get('#svg_source_textarea')
.type('{selectall}', { force: true })
.type(`<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
@ -22,12 +22,12 @@ describe('Fix issue 423', function () {
<rect clip-path="url(#svg_2)" fill="#0033b5" height="174.9" id="TANK1" width="78" x="77.5" y="29"/>
</g>
</g>
</svg>`, { parseSpecialCharSequences: false, force: true });
cy.get('#tool_source_save').click({ force: true });
</svg>`, { parseSpecialCharSequences: false, force: true })
cy.get('#tool_source_save').click({ force: true })
cy.get('#TANK1')
.trigger('mousedown', { force: true })
.trigger('mousemove', 50, 0, { force: true })
.trigger('mouseup', { force: true });
cy.get('#tool_undo').click({ force: true });
});
});
.trigger('mouseup', { force: true })
cy.get('#tool_undo').click({ force: true })
})
})

View File

@ -1,16 +1,16 @@
import {
visitAndApproveStorage
} from '../../../support/ui-test-helper.js';
} from '../../../support/ui-test-helper.js'
// See https://github.com/SVG-Edit/svgedit/issues/660
describe('Fix issue 660', function () {
beforeEach(() => {
visitAndApproveStorage();
cy.viewport(512, 512);
});
visitAndApproveStorage()
cy.viewport(512, 512)
})
/** @todo: reenable this test when we understand why it is passing locally but not on ci */
it.skip('can resize text', function () {
cy.get('#tool_source').click();
cy.get('#tool_source').click()
cy.get('#svg_source_textarea')
.type('{selectall}', { force: true })
.type(`<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg">
@ -18,18 +18,18 @@ describe('Fix issue 660', function () {
<title>Layer 1</title>
<text fill="#000000" id="a_text" text-anchor="middle" x="260.5" xml:space="preserve" y="192.5" font-size="40">hello</text>
</g>
</svg>`, { force: true, parseSpecialCharSequences: false });
cy.get('#tool_source_save').click({ force: true });
cy.get('#a_text').should('exist');
</svg>`, { force: true, parseSpecialCharSequences: false })
cy.get('#tool_source_save').click({ force: true })
cy.get('#a_text').should('exist')
cy.get('#a_text')
.trigger('mousedown', { which: 1, force: true })
.trigger('mouseup', { force: true });
.trigger('mouseup', { force: true })
cy.get('#selectorGrip_resize_s')
.trigger('mousedown', { which: 1, force: true })
.trigger('mousemove', { clientX: 0, clientY: 600 })
.trigger('mouseup', { force: true });
.trigger('mouseup', { force: true })
// svgedit use the #text text field to capture the text
cy.get('#a_text').should('have.attr', 'transform')
.and('equal', 'matrix(1 0 0 4.54639 0 -540.825)'); // Chrome 96 is matrix(1 0 0 4.17431 0 -325.367)
});
});
.and('equal', 'matrix(1 0 0 4.54639 0 -540.825)') // Chrome 96 is matrix(1 0 0 4.17431 0 -325.367)
})
})

View File

@ -1,14 +1,14 @@
import {
visitAndApproveStorage
} from '../../support/ui-test-helper.js';
} from '../../support/ui-test-helper.js'
// See https://github.com/SVG-Edit/svgedit/issues/364
describe('Key commands', function () {
beforeEach(() => {
visitAndApproveStorage();
});
visitAndApproveStorage()
})
it.skip('cmd-A on empty canvas should not cause an error', function () {
cy.get('body').type('{cmd}a');
});
});
cy.get('body').type('{cmd}a')
})
})

View File

@ -1,190 +1,188 @@
import {
visitAndApproveStorage
} from '../../support/ui-test-helper.js';
} from '../../support/ui-test-helper.js'
const testSnapshot = () => {
cy.get('#svgcontent').cleanSnapshot();
};
cy.get('#svgcontent').cleanSnapshot()
}
describe('use various parts of svg-edit', function () {
before(() => {
visitAndApproveStorage();
});
visitAndApproveStorage()
})
it('check tool_source', function () {
cy.get('#tool_source').click({ force: true });
cy.get('#tool_source').click({ force: true })
cy.get('#svg_source_textarea')
.type('{selectall}', { force: true })
.type(`<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<g class="layer">
<title>Layer 1</title>
</g>
</svg>`, { force: true, parseSpecialCharSequences: false });
cy.get('#tool_source_save').click({ force: true });
testSnapshot();
});
</svg>`, { force: true, parseSpecialCharSequences: false })
cy.get('#tool_source_save').click({ force: true })
testSnapshot()
})
it('check tool_fhpath', function () {
cy.get('#tool_fhpath')
.click({ force: true });
.click({ force: true })
cy.get('#svgcontent')
.trigger('mousemove', 200, 200, { force: true })
.trigger('mousedown', 200, 200, { force: true })
.trigger('mousemove', 20, 20, { force: true })
.trigger('mouseup', { force: true });
testSnapshot();
});
.trigger('mouseup', { force: true })
testSnapshot()
})
it('check tool_text', function () {
cy.get('#tool_text')
.click({ force: true });
.click({ force: true })
cy.get('#svgcontent')
.trigger('mousedown', 46, 35, { force: true })
.trigger('mouseup', { force: true });
.trigger('mousedown', 46, 35, { force: true })
.trigger('mouseup', { force: true })
// svgedit use the #text text field to capture the text
cy.get('#text').type('AB', { force: true });
testSnapshot();
});
cy.get('#text').type('AB', { force: true })
testSnapshot()
})
it('check tool_clone', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#svg_1').click({ force: true })
cy.get('#tool_clone')
.click({ force: true });
testSnapshot();
});
.click({ force: true })
testSnapshot()
})
it('check tool_italic', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#svg_1').click({ force: true })
cy.get('#tool_italic')
.click({ force: true });
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(500);
testSnapshot();
});
.click({ force: true })
testSnapshot()
})
it('check tool_bold', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#svg_1').click({ force: true })
cy.get('#tool_bold')
.click({ force: true });
testSnapshot();
});
.click({ force: true })
testSnapshot()
})
it('check tool_text_change_x_y_coordinate', function () {
cy.get('#svg_2').click({ force: true });
for(let n = 0; n < 25; n ++){
cy.get('#svg_2').click({ force: true })
for (let n = 0; n < 25; n++) {
cy.get('#selected_x').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
for(let n = 0; n < 25; n ++){
for (let n = 0; n < 25; n++) {
cy.get('#selected_y').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_text_change_font_size', function () {
cy.get('#svg_1').click({ force: true });
for(let n = 0; n < 10; n ++){
cy.get('#svg_1').click({ force: true })
for (let n = 0; n < 10; n++) {
cy.get('#font_size').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_text_change_stroke_width', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#svg_1').click({ force: true })
cy.get('#stroke_width').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
testSnapshot();
});
.click({ force: true })
testSnapshot()
})
it('check tool_text_change_stoke_fill_color', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#stroke_color').shadow().find('#picker').eq(0).click({ force: true });
cy.get('#svg_1').click({ force: true })
cy.get('#stroke_color').shadow().find('#picker').eq(0).click({ force: true })
cy.get('#stroke_color').shadow().find('#color_picker').eq(0)
.find('#jGraduate_colPick').eq(0).find('#jPicker-table').eq(0)
.find('.QuickColor').eq(51).click({ force: true });
.find('.QuickColor').eq(51).click({ force: true })
cy.get('#stroke_color').shadow().find('#color_picker').eq(0)
.find('#jGraduate_colPick').eq(0).find('#jPicker-table').eq(0)
.find('#Ok').eq(0).click({ force: true });
cy.get('#fill_color').shadow().find('#picker').eq(0).click({ force: true });
.find('#Ok').eq(0).click({ force: true })
cy.get('#fill_color').shadow().find('#picker').eq(0).click({ force: true })
cy.get('#fill_color').shadow().find('#color_picker').eq(0)
.find('#jGraduate_colPick').eq(0).find('#jPicker-table').eq(0)
.find('.QuickColor').eq(3).click({ force: true });
.find('.QuickColor').eq(3).click({ force: true })
cy.get('#fill_color').shadow().find('#color_picker').eq(0)
.find('#jGraduate_colPick').eq(0).find('#jPicker-table').eq(0)
.find('#Ok').eq(0).click({ force: true });
testSnapshot();
});
.find('#Ok').eq(0).click({ force: true })
testSnapshot()
})
it('check tool_text_anchor_start', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#svg_1').click({ force: true })
cy.get('#tool_text_anchor_start')
.click({ force: true });
testSnapshot();
});
.click({ force: true })
testSnapshot()
})
it('check tool_text_anchor_middle', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#svg_1').click({ force: true })
cy.get('#tool_text_anchor_middle')
.click({ force: true });
testSnapshot();
});
.click({ force: true })
testSnapshot()
})
it('check tool_text_anchor_end', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#svg_1').click({ force: true })
cy.get('#tool_text_anchor_end')
.click({ force: true });
testSnapshot();
});
.click({ force: true })
testSnapshot()
})
it('check tool_text_change_rotation', function () {
cy.get('#svg_2').click({ force: true });
for(let n = 0; n < 5; n ++){
cy.get('#svg_2').click({ force: true })
for (let n = 0; n < 5; n++) {
cy.get('#angle').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_text_change_blur', function () {
cy.get('#svg_2').click({ force: true });
for(let n = 0; n < 10; n ++){
cy.get('#svg_2').click({ force: true })
for (let n = 0; n < 10; n++) {
cy.get('#blur').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_text_change_opacity', function () {
cy.get('#svg_2').click({ force: true });
for(let n = 0; n < 10; n ++){
cy.get('#svg_2').click({ force: true })
for (let n = 0; n < 10; n++) {
cy.get('#opacity').shadow().find('elix-number-spin-box').eq(0).shadow().find('#downButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_text_align_to_page', function () {
cy.get('#svg_2').click({ force: true });
cy.get('#tool_position').shadow().find('elix-dropdown-list').eq(0).invoke('attr', 'opened', 'opened');
cy.get('#svg_2').click({ force: true })
cy.get('#tool_position').shadow().find('elix-dropdown-list').eq(0).invoke('attr', 'opened', 'opened')
cy.get('#tool_position').find('se-list-item').eq(2).shadow().find('elix-option').eq(0)
.click({ force: true });
testSnapshot();
});
.click({ force: true })
testSnapshot()
})
it('check tool_text_change_class', function () {
cy.get('#svg_2').click({ force: true });
cy.get('#svg_2').click({ force: true })
cy.get('#elem_class').shadow().find('elix-input').eq(0).shadow().find('#inner').eq(0)
.type('svg_2_class{enter}', { force: true });
.type('svg_2_class{enter}', { force: true })
cy.get('#svg_2')
.should('satisfy', ($el) => {
const classList = Array.from($el[0].classList);
return classList.includes('svg_2_class');
});
});
const classList = Array.from($el[0].classList)
return classList.includes('svg_2_class')
})
})
it('check tool_text_change_id', function () {
cy.get('#svg_2').click({ force: true }).click({ force: true });
cy.get('#svg_2').click({ force: true }).click({ force: true })
cy.get('#elem_id').shadow().find('elix-input').eq(0).shadow().find('#inner').eq(0)
.type('_id{enter}', { force: true });
.type('_id{enter}', { force: true })
cy.get('#svg_2_id')
.should('satisfy', ($el) => {
const classList = Array.from($el[0].classList);
return classList.includes('svg_2_class');
});
});
const classList = Array.from($el[0].classList)
return classList.includes('svg_2_class')
})
})
it('check tool_text_delete', function () {
cy.get('#svg_2_id').click({ force: true });
cy.get('#tool_delete').click({ force: true });
testSnapshot();
});
cy.get('#svg_2_id').click({ force: true })
cy.get('#tool_delete').click({ force: true })
testSnapshot()
})
it('check tool_text_change_font_family', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#tool_font_family').shadow().find('select').select("Serif");
testSnapshot();
});
});
cy.get('#svg_1').click({ force: true })
cy.get('#tool_font_family').shadow().find('select').select('Serif')
testSnapshot()
})
})

View File

@ -1,55 +1,55 @@
import {
visitAndApproveStorage
} from '../../support/ui-test-helper.js';
} from '../../support/ui-test-helper.js'
const testSnapshot = () => {
cy.get('#svgcontent').cleanSnapshot();
};
cy.get('#svgcontent').cleanSnapshot()
}
describe('use all parts of svg-edit', function () {
before(() => {
visitAndApproveStorage();
});
visitAndApproveStorage()
})
it('check tool_source_set', function () {
cy.get('#tool_source').click({ force: true });
cy.get('#tool_source').click({ force: true })
cy.get('#svg_source_textarea')
.type('{selectall}', { force: true })
.type(`<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<g class="layer">
<title>Layer 1</title>
</g>
</svg>`, { force: true, parseSpecialCharSequences: false });
cy.get('#tool_source_save').click({ force: true });
testSnapshot();
});
</svg>`, { force: true, parseSpecialCharSequences: false })
cy.get('#tool_source_save').click({ force: true })
testSnapshot()
})
it('check tool_shape', function () {
cy.get('#tool_shapelib').shadow().find('.overall').eq(0).click({ force: true });
cy.get('[data-shape="heart"]').click({ force: true });
cy.get('#tool_shapelib').shadow().find('.overall').eq(0).click({ force: true })
cy.get('[data-shape="heart"]').click({ force: true })
cy.get('#svgcontent')
.trigger('mousemove', 200, 200, { force: true })
.trigger('mousedown', 200, 200, { force: true })
.trigger('mousemove', 20, 20, { force: true })
.trigger('mouseup', { force: true });
.trigger('mouseup', { force: true })
cy.get('#selectorGrip_rotate')
.trigger('mousedown')
.trigger('mousemove', 20, 20, { force: true })
.trigger('mouseup', { force: true });
testSnapshot();
});
.trigger('mouseup', { force: true })
testSnapshot()
})
it('check tool_image', function () {
cy.get('#tool_image').click({ force: true });
cy.get('#tool_image').click({ force: true })
cy.get('#svgcontent')
.trigger('mousedown', 100, 100, { force: true })
.trigger('mousemove', 120, 120, { force: true })
.trigger('mouseup', { force: true });
.trigger('mouseup', { force: true })
// eslint-disable-next-line promise/catch-or-return
cy.window()
// eslint-disable-next-line promise/always-return
.then(($win) => {
cy.stub($win, 'prompt').returns('./images/logo.svg');
cy.contains('OK');
});
testSnapshot();
});
});
cy.stub($win, 'prompt').returns('./images/logo.svg')
cy.contains('OK')
})
testSnapshot()
})
})

View File

@ -1,124 +1,124 @@
import {
visitAndApproveStorage
} from '../../support/ui-test-helper.js';
} from '../../support/ui-test-helper.js'
const testSnapshot = () => {
cy.get('#svgcontent').cleanSnapshot();
};
cy.get('#svgcontent').cleanSnapshot()
}
describe('use all parts of svg-edit', function () {
before(() => {
visitAndApproveStorage();
});
visitAndApproveStorage()
})
it('check tool_source_set', function () {
cy.get('#tool_source').click({ force: true });
cy.get('#tool_source').click({ force: true })
cy.get('#svg_source_textarea')
.type('{selectall}', { force: true })
.type(`<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<g class="layer">
<title>Layer 1</title>
</g>
</svg>`, { force: true, parseSpecialCharSequences: false });
cy.get('#tool_source_save').click({ force: true });
testSnapshot();
});
</svg>`, { force: true, parseSpecialCharSequences: false })
cy.get('#tool_source_save').click({ force: true })
testSnapshot()
})
it('check tool_circle', function () {
cy.get('#tool_circle')
.click({ force: true });
.click({ force: true })
cy.get('#svgcontent')
.trigger('mousedown', 150, 150, { force: true })
.trigger('mousemove', 250, 200, { force: true })
.trigger('mouseup', { force: true });
testSnapshot();
});
.trigger('mouseup', { force: true })
testSnapshot()
})
it('check tool_fhellipse', function () {
cy.get('#tool_fhellipse')
.click({ force: true });
.click({ force: true })
cy.get('#svgcontent')
.trigger('mousedown', 200, 80, { force: true })
.trigger('mousemove', 320, 80, { force: true })
.trigger('mousemove', 320, 180, { force: true })
.trigger('mousemove', 200, 180, { force: true })
.trigger('mousemove', 200, 80, { force: true })
.trigger('mouseup', 200, 80, { force: true });
testSnapshot();
});
.trigger('mouseup', 200, 80, { force: true })
testSnapshot()
})
it('check tool_ellipse', function () {
cy.get('#tool_ellipse').click({ force: true });
cy.get('#tool_ellipse').click({ force: true })
cy.get('#svgcontent')
.trigger('mousedown', 75, 150, { force: true })
.trigger('mousemove', 130, 175, { force: true })
.trigger('mouseup', { force: true });
testSnapshot();
});
.trigger('mouseup', { force: true })
testSnapshot()
})
it('check tool_circle_change_fill_color', function () {
cy.get('#svg_2').click({ force: true });
cy.get('#svg_2').click({ force: true })
cy.get('#js-se-palette').find('.square').eq(8)
.click({ force: true });
testSnapshot();
});
.click({ force: true })
testSnapshot()
})
it('check tool_circle_change_opacity', function () {
cy.get('#svg_2').click({ force: true });
for(let n = 0; n < 10; n ++){
cy.get('#svg_2').click({ force: true })
for (let n = 0; n < 10; n++) {
cy.get('#opacity').shadow().find('elix-number-spin-box').eq(0).shadow().find('#downButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_ellipse_change_rotation', function () {
cy.get('#svg_3').click({ force: true });
for(let n = 0; n < 5; n ++){
cy.get('#svg_3').click({ force: true })
for (let n = 0; n < 5; n++) {
cy.get('#angle').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_ellipse_change_blur', function () {
cy.get('#svg_3').click({ force: true });
for(let n = 0; n < 10; n ++){
cy.get('#svg_3').click({ force: true })
for (let n = 0; n < 10; n++) {
cy.get('#blur').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_ellipse_change_cx_cy_coordinate', function () {
cy.get('#svg_3').click({ force: true });
for(let n = 0; n < 25; n ++){
cy.get('#svg_3').click({ force: true })
for (let n = 0; n < 25; n++) {
cy.get('#ellipse_cx').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
for(let n = 0; n < 25; n ++){
for (let n = 0; n < 25; n++) {
cy.get('#ellipse_cy').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_ellipse_change_rx_ry_radius', function () {
cy.get('#svg_3').click({ force: true });
for(let n = 0; n < 25; n ++){
cy.get('#svg_3').click({ force: true })
for (let n = 0; n < 25; n++) {
cy.get('#ellipse_rx').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
for(let n = 0; n < 25; n ++){
for (let n = 0; n < 25; n++) {
cy.get('#ellipse_ry').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_ellipse_bring_to_back', function () {
cy.get('#svg_2').click({ force: true });
cy.get('#tool_move_bottom').click({ force: true });
testSnapshot();
});
cy.get('#svg_2').click({ force: true })
cy.get('#tool_move_bottom').click({ force: true })
testSnapshot()
})
it('check tool_ellipse_bring_to_front', function () {
cy.get('#svg_2').click({ force: true });
cy.get('#tool_move_top').click({ force: true });
testSnapshot();
});
cy.get('#svg_2').click({ force: true })
cy.get('#tool_move_top').click({ force: true })
testSnapshot()
})
it('check tool_ellipse_clone', function () {
cy.get('#svg_2').click({ force: true });
cy.get('#tool_clone').click({ force: true });
testSnapshot();
});
});
cy.get('#svg_2').click({ force: true })
cy.get('#tool_clone').click({ force: true })
testSnapshot()
})
})

View File

@ -1,31 +1,31 @@
import {
visitAndApproveStorage
} from '../../support/ui-test-helper.js';
} from '../../support/ui-test-helper.js'
const testSnapshot = () => {
cy.get('#svgcontent').cleanSnapshot();
};
cy.get('#svgcontent').cleanSnapshot()
}
describe('use all parts of svg-edit', function () {
before(() => {
visitAndApproveStorage();
});
visitAndApproveStorage()
})
it('check tool_source_set', function () {
cy.get('#tool_source').click({ force: true });
cy.get('#tool_source').click({ force: true })
cy.get('#svg_source_textarea')
.type('{selectall}', { force: true })
.type(`<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<g class="layer">
<title>Layer 1</title>
</g>
</svg>`, { force: true, parseSpecialCharSequences: false });
cy.get('#tool_source_save').click({ force: true });
testSnapshot();
});
</svg>`, { force: true, parseSpecialCharSequences: false })
cy.get('#tool_source_save').click({ force: true })
testSnapshot()
})
it('check tool_path', function () {
cy.get('#tool_path')
.click({ force: true });
.click({ force: true })
cy.get('#svgcontent')
.trigger('mousedown', 50, 50, { force: true })
.trigger('mouseup', { force: true })
@ -37,49 +37,49 @@ describe('use all parts of svg-edit', function () {
.trigger('mouseup', { force: true })
.trigger('mousemove', 0, 0, { force: true })
.trigger('mousedown', 0, 0, { force: true })
.trigger('mouseup', { force: true });
testSnapshot();
});
.trigger('mouseup', { force: true })
testSnapshot()
})
it('check tool_path_change_node_xy', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#svg_1').dblclick({ force: true });
for(let n = 0; n < 25; n ++){
cy.get('#svg_1').click({ force: true })
cy.get('#svg_1').dblclick({ force: true })
for (let n = 0; n < 25; n++) {
cy.get('#path_node_x').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
for(let n = 0; n < 25; n ++){
for (let n = 0; n < 25; n++) {
cy.get('#path_node_y').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_path_change_seg_type', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#svg_1').dblclick({ force: true });
cy.get('#seg_type').shadow().find('select').select('6').should('have.value', '6');
cy.get('#svg_1').click({ force: true })
cy.get('#svg_1').dblclick({ force: true })
cy.get('#seg_type').shadow().find('select').select('6').should('have.value', '6')
cy.get('#ctrlpointgrip_3c1')
.trigger('mousedown', { force: true })
.trigger('mousemove', 130, 175, { force: true })
.trigger('mouseup', { force: true });
testSnapshot();
});
.trigger('mouseup', { force: true })
testSnapshot()
})
it('check tool_path_change_clone_node', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#svg_1').dblclick({ force: true });
cy.get('#tool_node_clone').click({ force: true });
cy.get('#svg_1').click({ force: true })
cy.get('#svg_1').dblclick({ force: true })
cy.get('#tool_node_clone').click({ force: true })
cy.get('#pathpointgrip_4')
.trigger('mousedown', { force: true })
.trigger('mousemove', 130, 175, { force: true })
.trigger('mouseup', { force: true });
testSnapshot();
});
.trigger('mouseup', { force: true })
testSnapshot()
})
it('check tool_path_openclose', function () {
cy.get('#tool_select').click({ force: true });
cy.get('#svg_1').click({ force: true });
cy.get('#svg_1').dblclick({ force: true });
cy.get('#tool_openclose_path').click({ force: true });
testSnapshot();
});
cy.get('#tool_select').click({ force: true })
cy.get('#svg_1').click({ force: true })
cy.get('#svg_1').dblclick({ force: true })
cy.get('#tool_openclose_path').click({ force: true })
testSnapshot()
})
/* it('check tool_path_add_subpath', function () {
cy.get('#tool_add_subpath').click({ force: true });
cy.get('#svgcontent')
@ -97,4 +97,4 @@ describe('use all parts of svg-edit', function () {
cy.get('#tool_select').click({ force: true });
testSnapshot();
}); */
});
})

View File

@ -1,164 +1,164 @@
import {
visitAndApproveStorage
} from '../../support/ui-test-helper.js';
} from '../../support/ui-test-helper.js'
const testSnapshot = () => {
cy.get('#svgcontent').cleanSnapshot();
};
cy.get('#svgcontent').cleanSnapshot()
}
describe('use all parts of svg-edit', function () {
before(() => {
visitAndApproveStorage();
});
visitAndApproveStorage()
})
it('check tool_source_set', function () {
cy.get('#tool_source').click({ force: true });
cy.get('#tool_source').click({ force: true })
cy.get('#svg_source_textarea')
.type('{selectall}', { force: true })
.type(`<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<g class="layer">
<title>Layer 1</title>
</g>
</svg>`, { force: true, parseSpecialCharSequences: false });
cy.get('#tool_source_save').click({ force: true });
testSnapshot();
});
</svg>`, { force: true, parseSpecialCharSequences: false })
cy.get('#tool_source_save').click({ force: true })
testSnapshot()
})
it('check tool_rect', function () {
cy.get('#tool_rect')
.click({ force: true });
.click({ force: true })
cy.get('#svgcontent')
.trigger('mousedown', 150, 150, { force: true })
.trigger('mousemove', 250, 200, { force: true })
.trigger('mouseup', { force: true });
testSnapshot();
});
.trigger('mouseup', { force: true })
testSnapshot()
})
it('check tool_fhrect', function () {
cy.get('#tool_fhrect')
.click({ force: true });
.click({ force: true })
cy.get('#svgcontent')
.trigger('mousedown', 200, 80, { force: true })
.trigger('mousemove', 320, 80, { force: true })
.trigger('mousemove', 320, 180, { force: true })
.trigger('mousemove', 200, 180, { force: true })
.trigger('mousemove', 200, 80, { force: true })
.trigger('mouseup', 200, 80, { force: true });
testSnapshot();
});
.trigger('mouseup', 200, 80, { force: true })
testSnapshot()
})
it('check tool_square', function () {
cy.get('#tool_square').click({ force: true });
cy.get('#tool_square').click({ force: true })
cy.get('#svgcontent')
.trigger('mousedown', 75, 150, { force: true })
.trigger('mousemove', 125, 200, { force: true })
.trigger('mouseup', { force: true });
testSnapshot();
});
.trigger('mouseup', { force: true })
testSnapshot()
})
it('check tool_rect_change_fill_color', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#svg_1').click({ force: true })
cy.get('#js-se-palette').find('.square').eq(8)
.click({ force: true });
testSnapshot();
});
.click({ force: true })
testSnapshot()
})
it('check tool_rect_change_rotation', function () {
cy.get('#svg_1').click({ force: true });
for(let n = 0; n < 5; n ++){
cy.get('#svg_1').click({ force: true })
for (let n = 0; n < 5; n++) {
cy.get('#angle').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_rect_change_blur', function () {
cy.get('#svg_1').click({ force: true });
for(let n = 0; n < 10; n ++){
cy.get('#svg_1').click({ force: true })
for (let n = 0; n < 10; n++) {
cy.get('#blur').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_rect_change_opacity', function () {
cy.get('#svg_1').click({ force: true });
for(let n = 0; n < 10; n ++){
cy.get('#svg_1').click({ force: true })
for (let n = 0; n < 10; n++) {
cy.get('#opacity').shadow().find('elix-number-spin-box').eq(0).shadow().find('#downButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_fhrect_change_x_y_coordinate', function () {
cy.get('#svg_2').click({ force: true });
for(let n = 0; n < 25; n ++){
cy.get('#svg_2').click({ force: true })
for (let n = 0; n < 25; n++) {
cy.get('#selected_x').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
for(let n = 0; n < 25; n ++){
for (let n = 0; n < 25; n++) {
cy.get('#selected_y').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_fhrect_change_width_height', function () {
cy.get('#svg_2').click({ force: true });
for(let n = 0; n < 25; n ++){
cy.get('#svg_2').click({ force: true })
for (let n = 0; n < 25; n++) {
cy.get('#rect_width').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
for(let n = 0; n < 25; n ++){
for (let n = 0; n < 25; n++) {
cy.get('#rect_height').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_square_clone', function () {
cy.get('#svg_3').click({ force: true });
cy.get('#tool_clone').click({ force: true });
testSnapshot();
});
cy.get('#svg_3').click({ force: true })
cy.get('#tool_clone').click({ force: true })
testSnapshot()
})
it('check tool_square_bring_to_back', function () {
cy.get('#svg_3').click({ force: true });
cy.get('#tool_move_bottom').click({ force: true });
testSnapshot();
});
cy.get('#svg_3').click({ force: true })
cy.get('#tool_move_bottom').click({ force: true })
testSnapshot()
})
it('check tool_square_bring_to_front', function () {
cy.get('#svg_3').click({ force: true });
cy.get('#tool_move_top').click({ force: true });
testSnapshot();
});
cy.get('#svg_3').click({ force: true })
cy.get('#tool_move_top').click({ force: true })
testSnapshot()
})
it('check tool_square_change_corner_radius', function () {
cy.get('#svg_4').click({ force: true });
for(let n = 0; n < 25; n ++){
cy.get('#svg_4').click({ force: true })
for (let n = 0; n < 25; n++) {
cy.get('#rect_rx').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_rect_change_to_path', function () {
cy.get('#svg_2').click({ force: true });
cy.get('#tool_topath').click({ force: true });
testSnapshot();
});
cy.get('#svg_2').click({ force: true })
cy.get('#tool_topath').click({ force: true })
testSnapshot()
})
it('check tool_rect_delete', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#tool_delete').click({ force: true });
cy.get('#svg_3').click({ force: true });
cy.get('#tool_delete').click({ force: true });
testSnapshot();
});
cy.get('#svg_1').click({ force: true })
cy.get('#tool_delete').click({ force: true })
cy.get('#svg_3').click({ force: true })
cy.get('#tool_delete').click({ force: true })
testSnapshot()
})
it('check tool_rect_change_class', function () {
cy.get('#svg_2').click({ force: true });
cy.get('#svg_2').click({ force: true })
cy.get('#elem_class').shadow().find('elix-input').eq(0).shadow().find('#inner').eq(0)
.type('svg_2_class{enter}', { force: true });
.type('svg_2_class{enter}', { force: true })
cy.get('#svg_2')
.should('satisfy', ($el) => {
const classList = Array.from($el[0].classList);
return classList.includes('svg_2_class');
});
});
const classList = Array.from($el[0].classList)
return classList.includes('svg_2_class')
})
})
it('check tool_rect_change_id', function () {
cy.get('#svg_2').click({ force: true }).click({ force: true });
cy.get('#svg_2').click({ force: true }).click({ force: true })
cy.get('#elem_id').shadow().find('elix-input').eq(0).shadow().find('#inner').eq(0)
.type('_id{enter}', { force: true });
.type('_id{enter}', { force: true })
cy.get('#svg_2_id')
.should('satisfy', ($el) => {
const classList = Array.from($el[0].classList);
return classList.includes('svg_2_class');
});
});
});
const classList = Array.from($el[0].classList)
return classList.includes('svg_2_class')
})
})
})

View File

@ -1,153 +1,153 @@
import {
visitAndApproveStorage
} from '../../support/ui-test-helper.js';
} from '../../support/ui-test-helper.js'
const testSnapshot = () => {
cy.get('#svgcontent').cleanSnapshot();
};
cy.get('#svgcontent').cleanSnapshot()
}
describe('use all parts of svg-edit', function () {
before(() => {
visitAndApproveStorage();
});
visitAndApproveStorage()
})
it('check tool_source_set', function () {
cy.get('#tool_source').click({ force: true });
cy.get('#tool_source').click({ force: true })
cy.get('#svg_source_textarea')
.type('{selectall}', { force: true })
.type(`<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<g class="layer">
<title>Layer 1</title>
</g>
</svg>`, { force: true, parseSpecialCharSequences: false });
cy.get('#tool_source_save').click({ force: true });
testSnapshot();
});
</svg>`, { force: true, parseSpecialCharSequences: false })
cy.get('#tool_source_save').click({ force: true })
testSnapshot()
})
it('check tool_line', function () {
cy.get('#tool_line')
.click({ force: true });
.click({ force: true })
cy.get('#svgcontent')
.trigger('mousemove', 200, 200, { force: true })
.trigger('mousedown', 200, 200, { force: true })
.trigger('mousemove', 250, 250, { force: true })
.trigger('mouseup', { force: true });
testSnapshot();
});
.trigger('mouseup', { force: true })
testSnapshot()
})
it('check tool_line_change_class', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#svg_1').click({ force: true })
cy.get('#elem_class').shadow().find('elix-input').eq(0).shadow().find('#inner').eq(0)
.type('svg_1_class{enter}', { force: true });
.type('svg_1_class{enter}', { force: true })
cy.get('#svg_1')
.should('satisfy', ($el) => {
const classList = Array.from($el[0].classList);
return classList.includes('svg_1_class');
});
});
const classList = Array.from($el[0].classList)
return classList.includes('svg_1_class')
})
})
it('check tool_line_change_id', function () {
cy.get('#svg_1').click({ force: true }).click({ force: true });
cy.get('#svg_1').click({ force: true }).click({ force: true })
cy.get('#elem_id').shadow().find('elix-input').eq(0).shadow().find('#inner').eq(0)
.type('_id{enter}', { force: true });
.type('_id{enter}', { force: true })
cy.get('#svg_1_id')
.should('satisfy', ($el) => {
const classList = Array.from($el[0].classList);
return classList.includes('svg_1_class');
});
});
const classList = Array.from($el[0].classList)
return classList.includes('svg_1_class')
})
})
it('check tool_line_change_rotation', function () {
cy.get('#svg_1_id').click({ force: true });
for(let n = 0; n < 5; n ++){
cy.get('#svg_1_id').click({ force: true })
for (let n = 0; n < 5; n++) {
cy.get('#angle').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_line_change_blur', function () {
cy.get('#svg_1_id').click({ force: true });
for(let n = 0; n < 10; n ++){
cy.get('#svg_1_id').click({ force: true })
for (let n = 0; n < 10; n++) {
cy.get('#blur').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_line_change_opacity', function () {
cy.get('#svg_1_id').click({ force: true });
for(let n = 0; n < 10; n ++){
cy.get('#svg_1_id').click({ force: true })
for (let n = 0; n < 10; n++) {
cy.get('#opacity').shadow().find('elix-number-spin-box').eq(0).shadow().find('#downButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_line_delete', function () {
cy.get('#svg_1_id').click({ force: true });
cy.get('#tool_delete').click({ force: true });
testSnapshot();
});
cy.get('#svg_1_id').click({ force: true })
cy.get('#tool_delete').click({ force: true })
testSnapshot()
})
it('check tool_line_clone', function () {
cy.get('#tool_line')
.click({ force: true });
.click({ force: true })
cy.get('#svgcontent')
.trigger('mousemove', 200, 200, { force: true })
.trigger('mousedown', 200, 200, { force: true })
.trigger('mousemove', 250, 250, { force: true })
.trigger('mouseup', { force: true });
cy.get('#svg_2').click({ force: true });
cy.get('#tool_clone').click({ force: true });
testSnapshot();
});
.trigger('mouseup', { force: true })
cy.get('#svg_2').click({ force: true })
cy.get('#tool_clone').click({ force: true })
testSnapshot()
})
it('check tool_line_bring_to_back', function () {
cy.get('#svg_2').click({ force: true });
cy.get('#tool_move_bottom').click({ force: true });
testSnapshot();
});
cy.get('#svg_2').click({ force: true })
cy.get('#tool_move_bottom').click({ force: true })
testSnapshot()
})
it('check tool_line_bring_to_front', function () {
cy.get('#svg_2').click({ force: true });
cy.get('#tool_move_top').click({ force: true });
testSnapshot();
});
cy.get('#svg_2').click({ force: true })
cy.get('#tool_move_top').click({ force: true })
testSnapshot()
})
it('check tool_line_change_x_y_coordinate', function () {
cy.get('#svg_2').click({ force: true });
for(let n = 0; n < 25; n ++){
cy.get('#svg_2').click({ force: true })
for (let n = 0; n < 25; n++) {
cy.get('#line_x1').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
for(let n = 0; n < 25; n ++){
for (let n = 0; n < 25; n++) {
cy.get('#line_y1').shadow().find('elix-number-spin-box').eq(0).shadow().find('#downButton').eq(0)
.click({ force: true });
.click({ force: true })
}
for(let n = 0; n < 25; n ++){
for (let n = 0; n < 25; n++) {
cy.get('#line_x2').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
for(let n = 0; n < 25; n ++){
for (let n = 0; n < 25; n++) {
cy.get('#line_y2').shadow().find('elix-number-spin-box').eq(0).shadow().find('#downButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_line_change_stroke_width', function () {
cy.get('#svg_2').click({ force: true });
for(let n = 0; n < 10; n ++){
cy.get('#svg_2').click({ force: true })
for (let n = 0; n < 10; n++) {
cy.get('#stroke_width').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_line_change_stoke_color', function () {
cy.get('#svg_3').click({ force: true });
cy.get('#stroke_color').shadow().find('#picker').eq(0).click({ force: true });
cy.get('#svg_3').click({ force: true })
cy.get('#stroke_color').shadow().find('#picker').eq(0).click({ force: true })
cy.get('#stroke_color').shadow().find('#color_picker').eq(0)
.find('#jGraduate_colPick').eq(0).find('#jPicker-table').eq(0)
.find('.QuickColor').eq(9).click({ force: true });
.find('.QuickColor').eq(9).click({ force: true })
cy.get('#stroke_color').shadow().find('#color_picker').eq(0)
.find('#jGraduate_colPick').eq(0).find('#jPicker-table').eq(0)
.find('#Ok').eq(0).click({ force: true });
testSnapshot();
});
.find('#Ok').eq(0).click({ force: true })
testSnapshot()
})
it('check tool_line_align_to_page', function () {
cy.get('#svg_3').click({ force: true });
cy.get('#tool_position').shadow().find('elix-dropdown-list').eq(0).invoke('attr', 'opened', 'opened');
cy.get('#svg_3').click({ force: true })
cy.get('#tool_position').shadow().find('elix-dropdown-list').eq(0).invoke('attr', 'opened', 'opened')
cy.get('#tool_position').find('se-list-item').eq(2).shadow().find('elix-option').eq(0)
.click({ force: true });
testSnapshot();
});
});
.click({ force: true })
testSnapshot()
})
})

View File

@ -1,108 +1,108 @@
import {
visitAndApproveStorage
} from '../../support/ui-test-helper.js';
} from '../../support/ui-test-helper.js'
const testSnapshot = () => {
cy.get('#svgcontent').cleanSnapshot();
};
cy.get('#svgcontent').cleanSnapshot()
}
describe('use all parts of svg-edit', function () {
before(() => {
visitAndApproveStorage();
});
visitAndApproveStorage()
})
it('check tool_source_set', function () {
cy.get('#tool_source').click({ force: true });
cy.get('#tool_source').click({ force: true })
cy.get('#svg_source_textarea')
.type('{selectall}', { force: true })
.type(`<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<g class="layer">
<title>Layer 1</title>
</g>
</svg>`, { force: true, parseSpecialCharSequences: false });
cy.get('#tool_source_save').click({ force: true });
testSnapshot();
});
</svg>`, { force: true, parseSpecialCharSequences: false })
cy.get('#tool_source_save').click({ force: true })
testSnapshot()
})
it('check tool_polygon', function () {
cy.get('#tool_polygon')
.click({ force: true });
.click({ force: true })
cy.get('#svgcontent')
.trigger('mousedown', 325, 250, { force: true })
.trigger('mousemove', 325, 345, { force: true })
.trigger('mouseup', { force: true });
testSnapshot();
});
.trigger('mouseup', { force: true })
testSnapshot()
})
it('check tool_polygon_clone', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#tool_clone').click({ force: true });
testSnapshot();
});
cy.get('#svg_1').click({ force: true })
cy.get('#tool_clone').click({ force: true })
testSnapshot()
})
it('check tool_polygon_change_class', function () {
cy.get('#svg_2').click({ force: true });
cy.get('#svg_2').click({ force: true })
cy.get('#elem_class').shadow().find('elix-input').eq(0).shadow().find('#inner').eq(0)
.type('svg_2_class{enter}', { force: true });
.type('svg_2_class{enter}', { force: true })
cy.get('#svg_2')
.should('satisfy', ($el) => {
const classList = Array.from($el[0].classList);
return classList.includes('svg_2_class');
});
});
const classList = Array.from($el[0].classList)
return classList.includes('svg_2_class')
})
})
it('check tool_polygon_change_id', function () {
cy.get('#svg_2').click({ force: true }).click({ force: true });
cy.get('#svg_2').click({ force: true }).click({ force: true })
cy.get('#elem_id').shadow().find('elix-input').eq(0).shadow().find('#inner').eq(0)
.type('_id{enter}', { force: true });
.type('_id{enter}', { force: true })
cy.get('#svg_2_id')
.should('satisfy', ($el) => {
const classList = Array.from($el[0].classList);
return classList.includes('svg_2_class');
});
});
const classList = Array.from($el[0].classList)
return classList.includes('svg_2_class')
})
})
it('check tool_polygon_change_rotation', function () {
cy.get('#svg_2_id').click({ force: true });
for(let n = 0; n < 5; n ++){
cy.get('#svg_2_id').click({ force: true })
for (let n = 0; n < 5; n++) {
cy.get('#angle').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_polygon_change_blur', function () {
cy.get('#svg_2_id').click({ force: true });
for(let n = 0; n < 10; n ++){
cy.get('#svg_2_id').click({ force: true })
for (let n = 0; n < 10; n++) {
cy.get('#blur').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_polygon_change_opacity', function () {
cy.get('#svg_2_id').click({ force: true });
for(let n = 0; n < 10; n ++){
cy.get('#svg_2_id').click({ force: true })
for (let n = 0; n < 10; n++) {
cy.get('#opacity').shadow().find('elix-number-spin-box').eq(0).shadow().find('#downButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_polygon_bring_to_back', function () {
cy.get('#svg_2_id').click({ force: true });
cy.get('#tool_move_bottom').click({ force: true });
testSnapshot();
});
cy.get('#svg_2_id').click({ force: true })
cy.get('#tool_move_bottom').click({ force: true })
testSnapshot()
})
it('check tool_polygon_bring_to_front', function () {
cy.get('#svg_2_id').click({ force: true });
cy.get('#tool_move_top').click({ force: true });
testSnapshot();
});
cy.get('#svg_2_id').click({ force: true })
cy.get('#tool_move_top').click({ force: true })
testSnapshot()
})
it('check tool_polygon_delete', function () {
cy.get('#svg_2_id').click({ force: true });
cy.get('#tool_delete').click({ force: true });
testSnapshot();
});
cy.get('#svg_2_id').click({ force: true })
cy.get('#tool_delete').click({ force: true })
testSnapshot()
})
it('check tool_polygon_align_to_page', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#tool_position').shadow().find('elix-dropdown-list').eq(0).invoke('attr', 'opened', 'opened');
cy.get('#svg_1').click({ force: true })
cy.get('#tool_position').shadow().find('elix-dropdown-list').eq(0).invoke('attr', 'opened', 'opened')
cy.get('#tool_position').find('se-list-item').eq(0).shadow().find('elix-option').eq(0)
.click({ force: true });
testSnapshot();
});
.click({ force: true })
testSnapshot()
})
/* it('check tool_polygon_change_x_y_coordinate', function () {
cy.get('#svg_1').click({ force: true });
for(let n = 0; n < 25; n ++){
@ -116,35 +116,35 @@ describe('use all parts of svg-edit', function () {
testSnapshot();
}); */
it('check tool_polygon_change_stroke_width', function () {
cy.get('#svg_1').click({ force: true });
for(let n = 0; n < 10; n ++){
cy.get('#svg_1').click({ force: true })
for (let n = 0; n < 10; n++) {
cy.get('#stroke_width').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_polygon_change_stoke_fill_color', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#stroke_color').shadow().find('#picker').eq(0).click({ force: true });
cy.get('#svg_1').click({ force: true })
cy.get('#stroke_color').shadow().find('#picker').eq(0).click({ force: true })
cy.get('#stroke_color').shadow().find('#color_picker').eq(0)
.find('#jGraduate_colPick').eq(0).find('#jPicker-table').eq(0)
.find('.QuickColor').eq(51).click({ force: true });
.find('.QuickColor').eq(51).click({ force: true })
cy.get('#stroke_color').shadow().find('#color_picker').eq(0)
.find('#jGraduate_colPick').eq(0).find('#jPicker-table').eq(0)
.find('#Ok').eq(0).click({ force: true });
cy.get('#fill_color').shadow().find('#picker').eq(0).click({ force: true });
.find('#Ok').eq(0).click({ force: true })
cy.get('#fill_color').shadow().find('#picker').eq(0).click({ force: true })
cy.get('#fill_color').shadow().find('#color_picker').eq(0)
.find('#jGraduate_colPick').eq(0).find('#jPicker-table').eq(0)
.find('.QuickColor').eq(3).click({ force: true });
.find('.QuickColor').eq(3).click({ force: true })
cy.get('#fill_color').shadow().find('#color_picker').eq(0)
.find('#jGraduate_colPick').eq(0).find('#jPicker-table').eq(0)
.find('#Ok').eq(0).click({ force: true });
testSnapshot();
});
.find('#Ok').eq(0).click({ force: true })
testSnapshot()
})
it('check tool_polygon_change_sides', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#svg_1').click({ force: true })
cy.get('#polySides').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
testSnapshot();
});
});
.click({ force: true })
testSnapshot()
})
})

View File

@ -1,138 +1,138 @@
import {
visitAndApproveStorage
} from '../../support/ui-test-helper.js';
} from '../../support/ui-test-helper.js'
const testSnapshot = () => {
cy.get('#svgcontent').cleanSnapshot();
};
cy.get('#svgcontent').cleanSnapshot()
}
describe('use all parts of svg-edit', function () {
before(() => {
visitAndApproveStorage();
});
visitAndApproveStorage()
})
it('check tool_source_set', function () {
cy.get('#tool_source').click({ force: true });
cy.get('#tool_source').click({ force: true })
cy.get('#svg_source_textarea')
.type('{selectall}', { force: true })
.type(`<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<g class="layer">
<title>Layer 1</title>
</g>
</svg>`, { force: true, parseSpecialCharSequences: false });
cy.get('#tool_source_save').click({ force: true });
testSnapshot();
});
</svg>`, { force: true, parseSpecialCharSequences: false })
cy.get('#tool_source_save').click({ force: true })
testSnapshot()
})
it('check tool_star', function () {
cy.get('#tool_star')
.click({ force: true });
.click({ force: true })
cy.get('#svgcontent')
.trigger('mousedown', 300, 150, { force: true })
.trigger('mousemove', 300, 250, { force: true })
.trigger('mouseup', { force: true });
testSnapshot();
});
.trigger('mouseup', { force: true })
testSnapshot()
})
it('check tool_star_clone', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#tool_clone').click({ force: true });
testSnapshot();
});
cy.get('#svg_1').click({ force: true })
cy.get('#tool_clone').click({ force: true })
testSnapshot()
})
it('check tool_star_change_class', function () {
cy.get('#svg_2').click({ force: true });
cy.get('#svg_2').click({ force: true })
cy.get('#elem_class').shadow().find('elix-input').eq(0).shadow().find('#inner').eq(0)
.type('svg_2_class{enter}', { force: true });
.type('svg_2_class{enter}', { force: true })
cy.get('#svg_2')
.should('satisfy', ($el) => {
const classList = Array.from($el[0].classList);
return classList.includes('svg_2_class');
});
});
const classList = Array.from($el[0].classList)
return classList.includes('svg_2_class')
})
})
it('check tool_star_change_id', function () {
cy.get('#svg_2').click({ force: true }).click({ force: true });
cy.get('#svg_2').click({ force: true }).click({ force: true })
cy.get('#elem_id').shadow().find('elix-input').eq(0).shadow().find('#inner').eq(0)
.type('_id{enter}', { force: true });
.type('_id{enter}', { force: true })
cy.get('#svg_2_id')
.should('satisfy', ($el) => {
const classList = Array.from($el[0].classList);
return classList.includes('svg_2_class');
});
});
const classList = Array.from($el[0].classList)
return classList.includes('svg_2_class')
})
})
it('check tool_star_change_rotation', function () {
cy.get('#svg_2_id').click({ force: true });
for(let n = 0; n < 5; n ++){
cy.get('#svg_2_id').click({ force: true })
for (let n = 0; n < 5; n++) {
cy.get('#angle').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_star_change_blur', function () {
cy.get('#svg_2_id').click({ force: true });
for(let n = 0; n < 10; n ++){
cy.get('#svg_2_id').click({ force: true })
for (let n = 0; n < 10; n++) {
cy.get('#blur').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_star_change_opacity', function () {
cy.get('#svg_2_id').click({ force: true });
for(let n = 0; n < 10; n ++){
cy.get('#svg_2_id').click({ force: true })
for (let n = 0; n < 10; n++) {
cy.get('#opacity').shadow().find('elix-number-spin-box').eq(0).shadow().find('#downButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_star_bring_to_back', function () {
cy.get('#svg_2_id').click({ force: true });
cy.get('#tool_move_bottom').click({ force: true });
testSnapshot();
});
cy.get('#svg_2_id').click({ force: true })
cy.get('#tool_move_bottom').click({ force: true })
testSnapshot()
})
it('check tool_star_bring_to_front', function () {
cy.get('#svg_2_id').click({ force: true });
cy.get('#tool_move_top').click({ force: true });
testSnapshot();
});
cy.get('#svg_2_id').click({ force: true })
cy.get('#tool_move_top').click({ force: true })
testSnapshot()
})
it('check tool_star_delete', function () {
cy.get('#svg_2_id').click({ force: true });
cy.get('#tool_delete').click({ force: true });
testSnapshot();
});
cy.get('#svg_2_id').click({ force: true })
cy.get('#tool_delete').click({ force: true })
testSnapshot()
})
it('check tool_star_align_to_page', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#tool_position').shadow().find('elix-dropdown-list').eq(0).invoke('attr', 'opened', 'opened');
cy.get('#svg_1').click({ force: true })
cy.get('#tool_position').shadow().find('elix-dropdown-list').eq(0).invoke('attr', 'opened', 'opened')
cy.get('#tool_position').find('se-list-item').eq(0).shadow().find('elix-option').eq(0)
.click({ force: true });
testSnapshot();
});
.click({ force: true })
testSnapshot()
})
it('check tool_star_change_stroke_width', function () {
cy.get('#svg_1').click({ force: true });
for(let n = 0; n < 10; n ++){
cy.get('#svg_1').click({ force: true })
for (let n = 0; n < 10; n++) {
cy.get('#stroke_width').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
.click({ force: true })
}
testSnapshot();
});
testSnapshot()
})
it('check tool_star_change_stoke_fill_color', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#stroke_color').shadow().find('#picker').eq(0).click({ force: true });
cy.get('#svg_1').click({ force: true })
cy.get('#stroke_color').shadow().find('#picker').eq(0).click({ force: true })
cy.get('#stroke_color').shadow().find('#color_picker').eq(0)
.find('#jGraduate_colPick').eq(0).find('#jPicker-table').eq(0)
.find('.QuickColor').eq(51).click({ force: true });
.find('.QuickColor').eq(51).click({ force: true })
cy.get('#stroke_color').shadow().find('#color_picker').eq(0)
.find('#jGraduate_colPick').eq(0).find('#jPicker-table').eq(0)
.find('#Ok').eq(0).click({ force: true });
cy.get('#fill_color').shadow().find('#picker').eq(0).click({ force: true });
.find('#Ok').eq(0).click({ force: true })
cy.get('#fill_color').shadow().find('#picker').eq(0).click({ force: true })
cy.get('#fill_color').shadow().find('#color_picker').eq(0)
.find('#jGraduate_colPick').eq(0).find('#jPicker-table').eq(0)
.find('.QuickColor').eq(3).click({ force: true });
.find('.QuickColor').eq(3).click({ force: true })
cy.get('#fill_color').shadow().find('#color_picker').eq(0)
.find('#jGraduate_colPick').eq(0).find('#jPicker-table').eq(0)
.find('#Ok').eq(0).click({ force: true });
testSnapshot();
});
.find('#Ok').eq(0).click({ force: true })
testSnapshot()
})
it('check tool_star_change_sides', function () {
cy.get('#svg_1').click({ force: true });
cy.get('#svg_1').click({ force: true })
cy.get('#starNumPoints').shadow().find('elix-number-spin-box').eq(0).shadow().find('#upButton').eq(0)
.click({ force: true });
testSnapshot();
});
});
.click({ force: true })
testSnapshot()
})
})

View File

@ -1,17 +1,17 @@
import {
visitAndApproveStorage
} from '../../support/ui-test-helper.js';
} from '../../support/ui-test-helper.js'
describe('UI - Tool selection', function () {
beforeEach(() => {
visitAndApproveStorage();
});
visitAndApproveStorage()
})
it('should set rectangle selection by click', function () {
cy.get('#tools_rect')
.should('not.have.attr', 'pressed');
.should('not.have.attr', 'pressed')
cy.get('#tools_rect')
.trigger('click', { force: true })
.should('have.attr', 'pressed');
});
});
.should('have.attr', 'pressed')
})
})

View File

@ -2,10 +2,10 @@
describe('Browser bugs', function () {
it('removeItem and setAttribute test (Chromium 843901; now fixed)', function () {
// See https://bugs.chromium.org/p/chromium/issues/detail?id=843901
const elem = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
elem.setAttribute('transform', 'matrix(1,0,0,1,0,0)');
elem.transform.baseVal.removeItem(0);
elem.removeAttribute('transform');
assert.equal(elem.hasAttribute('transform'), false);
});
});
const elem = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
elem.setAttribute('transform', 'matrix(1,0,0,1,0,0)')
elem.transform.baseVal.removeItem(0)
elem.removeAttribute('transform')
assert.equal(elem.hasAttribute('transform'), false)
})
})

View File

@ -1,4 +1,4 @@
import * as contextmenu from '../../../instrumented/editor/contextmenu.js';
import * as contextmenu from '../../../instrumented/editor/contextmenu.js'
describe('contextmenu', function () {
/**
@ -6,53 +6,53 @@ describe('contextmenu', function () {
* @returns {void}
*/
afterEach(() => {
contextmenu.resetCustomMenus();
});
contextmenu.resetCustomMenus()
})
it('Test svgedit.contextmenu package', function () {
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');
});
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')
})
it('Test svgedit.contextmenu does not add invalid menu item', function () {
assert.throws(
() => contextmenu.add({ id: 'justanid' }),
null, null,
'menu item with just an id is invalid'
);
)
assert.throws(
() => contextmenu.add({ id: 'idandlabel', label: 'anicelabel' }),
null, null,
'menu item with just an id and label is invalid'
);
)
assert.throws(
() => contextmenu.add({ id: 'idandlabel', label: 'anicelabel', action: 'notafunction' }),
null, null,
'menu item with action that is not a function is invalid'
);
});
)
})
it('Test svgedit.contextmenu adds valid menu item', function () {
const validItem = { id: 'valid', label: 'anicelabel', action () { /* empty fn */ } };
contextmenu.add(validItem);
const validItem = { id: 'valid', label: 'anicelabel', action () { /* empty fn */ } }
contextmenu.add(validItem)
assert.ok(contextmenu.hasCustomHandler('valid'), 'Valid menu item is added.');
assert.equal(contextmenu.getCustomHandler('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.')
})
it('Test svgedit.contextmenu rejects valid duplicate menu item id', function () {
const validItem1 = { id: 'valid', label: 'anicelabel', action () { /* empty fn */ } };
const validItem2 = { id: 'valid', label: 'anicelabel', action () { /* empty fn */ } };
contextmenu.add(validItem1);
const validItem1 = { id: 'valid', label: 'anicelabel', action () { /* empty fn */ } }
const validItem2 = { id: 'valid', label: 'anicelabel', action () { /* empty fn */ } }
contextmenu.add(validItem1)
assert.throws(
() => contextmenu.add(validItem2),
null, null,
'duplicate menu item is rejected.'
);
});
});
)
})
})

View File

@ -1,25 +1,25 @@
import { NS } from '../../../instrumented/svgcanvas/namespaces.js';
import * as utilities from '../../../instrumented/svgcanvas/utilities.js';
import * as coords from '../../../instrumented/svgcanvas/coords.js';
import { NS } from '../../../instrumented/svgcanvas/namespaces.js'
import * as utilities from '../../../instrumented/svgcanvas/utilities.js'
import * as coords from '../../../instrumented/svgcanvas/coords.js'
describe('coords', function () {
let elemId = 1;
let elemId = 1
const root = document.createElement('div');
root.id = 'root';
root.style.visibility = 'hidden';
document.body.append(root);
const root = document.createElement('div')
root.id = 'root'
root.style.visibility = 'hidden'
document.body.append(root)
/**
* Set up tests with mock data.
* @returns {void}
*/
beforeEach(function () {
const svgroot = document.createElementNS(NS.SVG, 'svg');
svgroot.id = 'svgroot';
root.append(svgroot);
this.svg = document.createElementNS(NS.SVG, 'svg');
svgroot.append(this.svg);
const svgroot = document.createElementNS(NS.SVG, 'svg')
svgroot.id = 'svgroot'
root.append(svgroot)
this.svg = document.createElementNS(NS.SVG, 'svg')
svgroot.append(this.svg)
// Mock out editor context.
utilities.init(
@ -27,25 +27,25 @@ describe('coords', function () {
* @implements {module:utilities.EditorContext}
*/
{
getSvgRoot: () => { return this.svg; },
getDOMDocument () { return null; },
getDOMContainer () { return null; }
getSvgRoot: () => { return this.svg },
getDOMDocument () { return null },
getDOMContainer () { return null }
}
);
)
coords.init(
/**
* @implements {module:coords.EditorContext}
*/
{
getGridSnapping () { return false; },
getGridSnapping () { return false },
getDrawing () {
return {
getNextId () { return String(elemId++); }
};
getNextId () { return String(elemId++) }
}
}
}
);
});
)
})
/**
* Tear down tests, removing elements.
@ -53,255 +53,255 @@ describe('coords', function () {
*/
afterEach(function () {
while (this.svg.hasChildNodes()) {
this.svg.firstChild.remove();
this.svg.firstChild.remove()
}
});
})
it('Test remapElement(translate) for rect', function () {
const rect = document.createElementNS(NS.SVG, 'rect');
rect.setAttribute('x', '200');
rect.setAttribute('y', '150');
rect.setAttribute('width', '250');
rect.setAttribute('height', '120');
this.svg.append(rect);
const rect = document.createElementNS(NS.SVG, 'rect')
rect.setAttribute('x', '200')
rect.setAttribute('y', '150')
rect.setAttribute('width', '250')
rect.setAttribute('height', '120')
this.svg.append(rect)
const attrs = {
x: '200',
y: '150',
width: '125',
height: '75'
};
}
// Create a translate.
const m = this.svg.createSVGMatrix();
m.a = 1; m.b = 0;
m.c = 0; m.d = 1;
m.e = 100; m.f = -50;
const m = this.svg.createSVGMatrix()
m.a = 1; m.b = 0
m.c = 0; m.d = 1
m.e = 100; m.f = -50
coords.remapElement(rect, attrs, m);
coords.remapElement(rect, attrs, m)
assert.equal(rect.getAttribute('x'), '300');
assert.equal(rect.getAttribute('y'), '100');
assert.equal(rect.getAttribute('width'), '125');
assert.equal(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')
})
it('Test remapElement(scale) for rect', function () {
const rect = document.createElementNS(NS.SVG, 'rect');
rect.setAttribute('width', '250');
rect.setAttribute('height', '120');
this.svg.append(rect);
const rect = document.createElementNS(NS.SVG, 'rect')
rect.setAttribute('width', '250')
rect.setAttribute('height', '120')
this.svg.append(rect)
const attrs = {
x: '0',
y: '0',
width: '250',
height: '120'
};
}
// Create a translate.
const m = this.svg.createSVGMatrix();
m.a = 2; m.b = 0;
m.c = 0; m.d = 0.5;
m.e = 0; m.f = 0;
const m = this.svg.createSVGMatrix()
m.a = 2; m.b = 0
m.c = 0; m.d = 0.5
m.e = 0; m.f = 0
coords.remapElement(rect, attrs, m);
coords.remapElement(rect, attrs, m)
assert.equal(rect.getAttribute('x'), '0');
assert.equal(rect.getAttribute('y'), '0');
assert.equal(rect.getAttribute('width'), '500');
assert.equal(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')
})
it('Test remapElement(translate) for circle', function () {
const circle = document.createElementNS(NS.SVG, 'circle');
circle.setAttribute('cx', '200');
circle.setAttribute('cy', '150');
circle.setAttribute('r', '125');
this.svg.append(circle);
const circle = document.createElementNS(NS.SVG, 'circle')
circle.setAttribute('cx', '200')
circle.setAttribute('cy', '150')
circle.setAttribute('r', '125')
this.svg.append(circle)
const attrs = {
cx: '200',
cy: '150',
r: '125'
};
}
// Create a translate.
const m = this.svg.createSVGMatrix();
m.a = 1; m.b = 0;
m.c = 0; m.d = 1;
m.e = 100; m.f = -50;
const m = this.svg.createSVGMatrix()
m.a = 1; m.b = 0
m.c = 0; m.d = 1
m.e = 100; m.f = -50
coords.remapElement(circle, attrs, m);
coords.remapElement(circle, attrs, m)
assert.equal(circle.getAttribute('cx'), '300');
assert.equal(circle.getAttribute('cy'), '100');
assert.equal(circle.getAttribute('r'), '125');
});
assert.equal(circle.getAttribute('cx'), '300')
assert.equal(circle.getAttribute('cy'), '100')
assert.equal(circle.getAttribute('r'), '125')
})
it('Test remapElement(scale) for circle', function () {
const circle = document.createElementNS(NS.SVG, 'circle');
circle.setAttribute('cx', '200');
circle.setAttribute('cy', '150');
circle.setAttribute('r', '250');
this.svg.append(circle);
const circle = document.createElementNS(NS.SVG, 'circle')
circle.setAttribute('cx', '200')
circle.setAttribute('cy', '150')
circle.setAttribute('r', '250')
this.svg.append(circle)
const attrs = {
cx: '200',
cy: '150',
r: '250'
};
}
// Create a translate.
const m = this.svg.createSVGMatrix();
m.a = 2; m.b = 0;
m.c = 0; m.d = 0.5;
m.e = 0; m.f = 0;
const m = this.svg.createSVGMatrix()
m.a = 2; m.b = 0
m.c = 0; m.d = 0.5
m.e = 0; m.f = 0
coords.remapElement(circle, attrs, m);
coords.remapElement(circle, attrs, m)
assert.equal(circle.getAttribute('cx'), '400');
assert.equal(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.
assert.equal(circle.getAttribute('r'), '125');
});
assert.equal(circle.getAttribute('r'), '125')
})
it('Test remapElement(translate) for ellipse', function () {
const ellipse = document.createElementNS(NS.SVG, 'ellipse');
ellipse.setAttribute('cx', '200');
ellipse.setAttribute('cy', '150');
ellipse.setAttribute('rx', '125');
ellipse.setAttribute('ry', '75');
this.svg.append(ellipse);
const ellipse = document.createElementNS(NS.SVG, 'ellipse')
ellipse.setAttribute('cx', '200')
ellipse.setAttribute('cy', '150')
ellipse.setAttribute('rx', '125')
ellipse.setAttribute('ry', '75')
this.svg.append(ellipse)
const attrs = {
cx: '200',
cy: '150',
rx: '125',
ry: '75'
};
}
// Create a translate.
const m = this.svg.createSVGMatrix();
m.a = 1; m.b = 0;
m.c = 0; m.d = 1;
m.e = 100; m.f = -50;
const m = this.svg.createSVGMatrix()
m.a = 1; m.b = 0
m.c = 0; m.d = 1
m.e = 100; m.f = -50
coords.remapElement(ellipse, attrs, m);
coords.remapElement(ellipse, attrs, m)
assert.equal(ellipse.getAttribute('cx'), '300');
assert.equal(ellipse.getAttribute('cy'), '100');
assert.equal(ellipse.getAttribute('rx'), '125');
assert.equal(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')
})
it('Test remapElement(scale) for ellipse', function () {
const ellipse = document.createElementNS(NS.SVG, 'ellipse');
ellipse.setAttribute('cx', '200');
ellipse.setAttribute('cy', '150');
ellipse.setAttribute('rx', '250');
ellipse.setAttribute('ry', '120');
this.svg.append(ellipse);
const ellipse = document.createElementNS(NS.SVG, 'ellipse')
ellipse.setAttribute('cx', '200')
ellipse.setAttribute('cy', '150')
ellipse.setAttribute('rx', '250')
ellipse.setAttribute('ry', '120')
this.svg.append(ellipse)
const attrs = {
cx: '200',
cy: '150',
rx: '250',
ry: '120'
};
}
// Create a translate.
const m = this.svg.createSVGMatrix();
m.a = 2; m.b = 0;
m.c = 0; m.d = 0.5;
m.e = 0; m.f = 0;
const m = this.svg.createSVGMatrix()
m.a = 2; m.b = 0
m.c = 0; m.d = 0.5
m.e = 0; m.f = 0
coords.remapElement(ellipse, attrs, m);
coords.remapElement(ellipse, attrs, m)
assert.equal(ellipse.getAttribute('cx'), '400');
assert.equal(ellipse.getAttribute('cy'), '75');
assert.equal(ellipse.getAttribute('rx'), '500');
assert.equal(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')
})
it('Test remapElement(translate) for line', function () {
const line = document.createElementNS(NS.SVG, 'line');
line.setAttribute('x1', '50');
line.setAttribute('y1', '100');
line.setAttribute('x2', '120');
line.setAttribute('y2', '200');
this.svg.append(line);
const line = document.createElementNS(NS.SVG, 'line')
line.setAttribute('x1', '50')
line.setAttribute('y1', '100')
line.setAttribute('x2', '120')
line.setAttribute('y2', '200')
this.svg.append(line)
const attrs = {
x1: '50',
y1: '100',
x2: '120',
y2: '200'
};
}
// Create a translate.
const m = this.svg.createSVGMatrix();
m.a = 1; m.b = 0;
m.c = 0; m.d = 1;
m.e = 100; m.f = -50;
const m = this.svg.createSVGMatrix()
m.a = 1; m.b = 0
m.c = 0; m.d = 1
m.e = 100; m.f = -50
coords.remapElement(line, attrs, m);
coords.remapElement(line, attrs, m)
assert.equal(line.getAttribute('x1'), '150');
assert.equal(line.getAttribute('y1'), '50');
assert.equal(line.getAttribute('x2'), '220');
assert.equal(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')
})
it('Test remapElement(scale) for line', function () {
const line = document.createElementNS(NS.SVG, 'line');
line.setAttribute('x1', '50');
line.setAttribute('y1', '100');
line.setAttribute('x2', '120');
line.setAttribute('y2', '200');
this.svg.append(line);
const line = document.createElementNS(NS.SVG, 'line')
line.setAttribute('x1', '50')
line.setAttribute('y1', '100')
line.setAttribute('x2', '120')
line.setAttribute('y2', '200')
this.svg.append(line)
const attrs = {
x1: '50',
y1: '100',
x2: '120',
y2: '200'
};
}
// Create a translate.
const m = this.svg.createSVGMatrix();
m.a = 2; m.b = 0;
m.c = 0; m.d = 0.5;
m.e = 0; m.f = 0;
const m = this.svg.createSVGMatrix()
m.a = 2; m.b = 0
m.c = 0; m.d = 0.5
m.e = 0; m.f = 0
coords.remapElement(line, attrs, m);
coords.remapElement(line, attrs, m)
assert.equal(line.getAttribute('x1'), '100');
assert.equal(line.getAttribute('y1'), '50');
assert.equal(line.getAttribute('x2'), '240');
assert.equal(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')
})
it('Test remapElement(translate) for text', function () {
const text = document.createElementNS(NS.SVG, 'text');
text.setAttribute('x', '50');
text.setAttribute('y', '100');
this.svg.append(text);
const text = document.createElementNS(NS.SVG, 'text')
text.setAttribute('x', '50')
text.setAttribute('y', '100')
this.svg.append(text)
const attrs = {
x: '50',
y: '100'
};
}
// Create a translate.
const m = this.svg.createSVGMatrix();
m.a = 1; m.b = 0;
m.c = 0; m.d = 1;
m.e = 100; m.f = -50;
const m = this.svg.createSVGMatrix()
m.a = 1; m.b = 0
m.c = 0; m.d = 1
m.e = 100; m.f = -50
coords.remapElement(text, attrs, m);
coords.remapElement(text, attrs, m)
assert.equal(text.getAttribute('x'), '150');
assert.equal(text.getAttribute('y'), '50');
});
});
assert.equal(text.getAttribute('x'), '150')
assert.equal(text.getAttribute('y'), '50')
})
})

File diff suppressed because it is too large Load Diff

View File

@ -1,31 +1,34 @@
import { NS } from '../../../instrumented/svgcanvas/namespaces.js';
import * as utilities from '../../../instrumented/svgcanvas/utilities.js';
import * as history from '../../../instrumented/svgcanvas/history.js';
import { NS } from '../../../instrumented/svgcanvas/namespaces.js'
import * as utilities from '../../../instrumented/svgcanvas/utilities.js'
import * as history from '../../../instrumented/svgcanvas/history.js'
describe('history', function () {
// TODO(codedread): Write tests for handling history events.
utilities.mock({
getHref () { return '#foo'; },
getHref () { return '#foo' },
setHref () { /* empty fn */ },
getRotationAngle () { return 0; }
});
getRotationAngle () { return 0 }
})
// const svg = document.createElementNS(NS.SVG, 'svg');
let undoMgr = null;
let undoMgr = null
class MockCommand extends history.Command {
constructor (optText) {
super();
this.text = optText;
super()
this.text = optText
}
apply (handler) {
super.apply(handler, () => { /* empty fn */ });
super.apply(handler, () => { /* empty fn */ })
}
unapply (handler) {
super.unapply(handler, () => { /* empty fn */ });
super.unapply(handler, () => { /* empty fn */ })
}
elements () { return []; }
elements () { return [] }
}
/*
@ -39,479 +42,479 @@ describe('history', function () {
* @returns {void}
*/
beforeEach(function () {
undoMgr = new history.UndoManager();
undoMgr = new history.UndoManager()
document.body.textContent = '';
this.divparent = document.createElement('div');
this.divparent.id = 'divparent';
this.divparent.style.visibility = 'hidden';
document.body.textContent = ''
this.divparent = document.createElement('div')
this.divparent.id = 'divparent'
this.divparent.style.visibility = 'hidden'
for (let i = 1; i <= 5; i++) {
const div = document.createElement('div');
const id = `div${i}`;
div.id = id;
this[id] = div;
const div = document.createElement('div')
const id = `div${i}`
div.id = id
this[id] = div
}
this.divparent.append(this.div1, this.div2, this.div3);
this.divparent.append(this.div1, this.div2, this.div3)
this.div4.style.visibility = 'hidden';
this.div4.append(this.div5);
this.div4.style.visibility = 'hidden'
this.div4.append(this.div5)
document.body.append(this.divparent, this.div);
});
document.body.append(this.divparent, this.div)
})
/**
* Tear down tests, destroying undo manager.
* @returns {void}
*/
afterEach(() => {
undoMgr = null;
});
undoMgr = null
})
it('Test svgedit.history package', function () {
assert.ok(history);
assert.ok(history.MoveElementCommand);
assert.ok(history.InsertElementCommand);
assert.ok(history.ChangeElementCommand);
assert.ok(history.RemoveElementCommand);
assert.ok(history.BatchCommand);
assert.ok(history.UndoManager);
assert.equal(typeof history.MoveElementCommand, typeof function () { /* empty fn */ });
assert.equal(typeof history.InsertElementCommand, typeof function () { /* empty fn */ });
assert.equal(typeof history.ChangeElementCommand, typeof function () { /* empty fn */ });
assert.equal(typeof history.RemoveElementCommand, typeof function () { /* empty fn */ });
assert.equal(typeof history.BatchCommand, typeof function () { /* empty fn */ });
assert.equal(typeof history.UndoManager, typeof function () { /* empty fn */ });
});
assert.ok(history)
assert.ok(history.MoveElementCommand)
assert.ok(history.InsertElementCommand)
assert.ok(history.ChangeElementCommand)
assert.ok(history.RemoveElementCommand)
assert.ok(history.BatchCommand)
assert.ok(history.UndoManager)
assert.equal(typeof history.MoveElementCommand, typeof function () { /* empty fn */ })
assert.equal(typeof history.InsertElementCommand, typeof function () { /* empty fn */ })
assert.equal(typeof history.ChangeElementCommand, typeof function () { /* empty fn */ })
assert.equal(typeof history.RemoveElementCommand, typeof function () { /* empty fn */ })
assert.equal(typeof history.BatchCommand, typeof function () { /* empty fn */ })
assert.equal(typeof history.UndoManager, typeof function () { /* empty fn */ })
})
it('Test UndoManager methods', function () {
assert.ok(undoMgr);
assert.ok(undoMgr.addCommandToHistory);
assert.ok(undoMgr.getUndoStackSize);
assert.ok(undoMgr.getRedoStackSize);
assert.ok(undoMgr.resetUndoStack);
assert.ok(undoMgr.getNextUndoCommandText);
assert.ok(undoMgr.getNextRedoCommandText);
assert.ok(undoMgr)
assert.ok(undoMgr.addCommandToHistory)
assert.ok(undoMgr.getUndoStackSize)
assert.ok(undoMgr.getRedoStackSize)
assert.ok(undoMgr.resetUndoStack)
assert.ok(undoMgr.getNextUndoCommandText)
assert.ok(undoMgr.getNextRedoCommandText)
assert.equal(typeof undoMgr, typeof {});
assert.equal(typeof undoMgr.addCommandToHistory, typeof function () { /* empty fn */ });
assert.equal(typeof undoMgr.getUndoStackSize, typeof function () { /* empty fn */ });
assert.equal(typeof undoMgr.getRedoStackSize, typeof function () { /* empty fn */ });
assert.equal(typeof undoMgr.resetUndoStack, typeof function () { /* empty fn */ });
assert.equal(typeof undoMgr.getNextUndoCommandText, typeof function () { /* empty fn */ });
assert.equal(typeof undoMgr.getNextRedoCommandText, typeof function () { /* empty fn */ });
});
assert.equal(typeof undoMgr, typeof {})
assert.equal(typeof undoMgr.addCommandToHistory, typeof function () { /* empty fn */ })
assert.equal(typeof undoMgr.getUndoStackSize, typeof function () { /* empty fn */ })
assert.equal(typeof undoMgr.getRedoStackSize, typeof function () { /* empty fn */ })
assert.equal(typeof undoMgr.resetUndoStack, typeof function () { /* empty fn */ })
assert.equal(typeof undoMgr.getNextUndoCommandText, typeof function () { /* empty fn */ })
assert.equal(typeof undoMgr.getNextRedoCommandText, typeof function () { /* empty fn */ })
})
it('Test UndoManager.addCommandToHistory() function', function () {
assert.equal(undoMgr.getUndoStackSize(), 0);
undoMgr.addCommandToHistory(new MockCommand());
assert.equal(undoMgr.getUndoStackSize(), 1);
undoMgr.addCommandToHistory(new MockCommand());
assert.equal(undoMgr.getUndoStackSize(), 2);
});
assert.equal(undoMgr.getUndoStackSize(), 0)
undoMgr.addCommandToHistory(new MockCommand())
assert.equal(undoMgr.getUndoStackSize(), 1)
undoMgr.addCommandToHistory(new MockCommand())
assert.equal(undoMgr.getUndoStackSize(), 2)
})
it('Test UndoManager.getUndoStackSize() and getRedoStackSize() functions', function () {
undoMgr.addCommandToHistory(new MockCommand());
undoMgr.addCommandToHistory(new MockCommand());
undoMgr.addCommandToHistory(new MockCommand());
undoMgr.addCommandToHistory(new MockCommand())
undoMgr.addCommandToHistory(new MockCommand())
undoMgr.addCommandToHistory(new MockCommand())
assert.equal(undoMgr.getUndoStackSize(), 3);
assert.equal(undoMgr.getRedoStackSize(), 0);
assert.equal(undoMgr.getUndoStackSize(), 3)
assert.equal(undoMgr.getRedoStackSize(), 0)
undoMgr.undo();
assert.equal(undoMgr.getUndoStackSize(), 2);
assert.equal(undoMgr.getRedoStackSize(), 1);
undoMgr.undo()
assert.equal(undoMgr.getUndoStackSize(), 2)
assert.equal(undoMgr.getRedoStackSize(), 1)
undoMgr.undo();
assert.equal(undoMgr.getUndoStackSize(), 1);
assert.equal(undoMgr.getRedoStackSize(), 2);
undoMgr.undo()
assert.equal(undoMgr.getUndoStackSize(), 1)
assert.equal(undoMgr.getRedoStackSize(), 2)
undoMgr.undo();
assert.equal(undoMgr.getUndoStackSize(), 0);
assert.equal(undoMgr.getRedoStackSize(), 3);
undoMgr.undo()
assert.equal(undoMgr.getUndoStackSize(), 0)
assert.equal(undoMgr.getRedoStackSize(), 3)
undoMgr.undo();
assert.equal(undoMgr.getUndoStackSize(), 0);
assert.equal(undoMgr.getRedoStackSize(), 3);
undoMgr.undo()
assert.equal(undoMgr.getUndoStackSize(), 0)
assert.equal(undoMgr.getRedoStackSize(), 3)
undoMgr.redo();
assert.equal(undoMgr.getUndoStackSize(), 1);
assert.equal(undoMgr.getRedoStackSize(), 2);
undoMgr.redo()
assert.equal(undoMgr.getUndoStackSize(), 1)
assert.equal(undoMgr.getRedoStackSize(), 2)
undoMgr.redo();
assert.equal(undoMgr.getUndoStackSize(), 2);
assert.equal(undoMgr.getRedoStackSize(), 1);
undoMgr.redo()
assert.equal(undoMgr.getUndoStackSize(), 2)
assert.equal(undoMgr.getRedoStackSize(), 1)
undoMgr.redo();
assert.equal(undoMgr.getUndoStackSize(), 3);
assert.equal(undoMgr.getRedoStackSize(), 0);
undoMgr.redo()
assert.equal(undoMgr.getUndoStackSize(), 3)
assert.equal(undoMgr.getRedoStackSize(), 0)
undoMgr.redo();
assert.equal(undoMgr.getUndoStackSize(), 3);
assert.equal(undoMgr.getRedoStackSize(), 0);
});
undoMgr.redo()
assert.equal(undoMgr.getUndoStackSize(), 3)
assert.equal(undoMgr.getRedoStackSize(), 0)
})
it('Test UndoManager.resetUndoStackSize() function', function () {
undoMgr.addCommandToHistory(new MockCommand());
undoMgr.addCommandToHistory(new MockCommand());
undoMgr.addCommandToHistory(new MockCommand());
undoMgr.undo();
undoMgr.addCommandToHistory(new MockCommand())
undoMgr.addCommandToHistory(new MockCommand())
undoMgr.addCommandToHistory(new MockCommand())
undoMgr.undo()
assert.equal(undoMgr.getUndoStackSize(), 2);
assert.equal(undoMgr.getRedoStackSize(), 1);
assert.equal(undoMgr.getUndoStackSize(), 2)
assert.equal(undoMgr.getRedoStackSize(), 1)
undoMgr.resetUndoStack();
undoMgr.resetUndoStack()
assert.equal(undoMgr.getUndoStackSize(), 0);
assert.equal(undoMgr.getRedoStackSize(), 0);
});
assert.equal(undoMgr.getUndoStackSize(), 0)
assert.equal(undoMgr.getRedoStackSize(), 0)
})
it('Test UndoManager.getNextUndoCommandText() function', function () {
assert.equal(undoMgr.getNextUndoCommandText(), '');
assert.equal(undoMgr.getNextUndoCommandText(), '')
undoMgr.addCommandToHistory(new MockCommand('First'));
undoMgr.addCommandToHistory(new MockCommand('Second'));
undoMgr.addCommandToHistory(new MockCommand('Third'));
undoMgr.addCommandToHistory(new MockCommand('First'))
undoMgr.addCommandToHistory(new MockCommand('Second'))
undoMgr.addCommandToHistory(new MockCommand('Third'))
assert.equal(undoMgr.getNextUndoCommandText(), 'Third');
assert.equal(undoMgr.getNextUndoCommandText(), 'Third')
undoMgr.undo();
assert.equal(undoMgr.getNextUndoCommandText(), 'Second');
undoMgr.undo()
assert.equal(undoMgr.getNextUndoCommandText(), 'Second')
undoMgr.undo();
assert.equal(undoMgr.getNextUndoCommandText(), 'First');
undoMgr.undo()
assert.equal(undoMgr.getNextUndoCommandText(), 'First')
undoMgr.undo();
assert.equal(undoMgr.getNextUndoCommandText(), '');
undoMgr.undo()
assert.equal(undoMgr.getNextUndoCommandText(), '')
undoMgr.redo();
assert.equal(undoMgr.getNextUndoCommandText(), 'First');
undoMgr.redo()
assert.equal(undoMgr.getNextUndoCommandText(), 'First')
undoMgr.redo();
assert.equal(undoMgr.getNextUndoCommandText(), 'Second');
undoMgr.redo()
assert.equal(undoMgr.getNextUndoCommandText(), 'Second')
undoMgr.redo();
assert.equal(undoMgr.getNextUndoCommandText(), 'Third');
undoMgr.redo()
assert.equal(undoMgr.getNextUndoCommandText(), 'Third')
undoMgr.redo();
assert.equal(undoMgr.getNextUndoCommandText(), 'Third');
});
undoMgr.redo()
assert.equal(undoMgr.getNextUndoCommandText(), 'Third')
})
it('Test UndoManager.getNextRedoCommandText() function', function () {
assert.equal(undoMgr.getNextRedoCommandText(), '');
assert.equal(undoMgr.getNextRedoCommandText(), '')
undoMgr.addCommandToHistory(new MockCommand('First'));
undoMgr.addCommandToHistory(new MockCommand('Second'));
undoMgr.addCommandToHistory(new MockCommand('Third'));
undoMgr.addCommandToHistory(new MockCommand('First'))
undoMgr.addCommandToHistory(new MockCommand('Second'))
undoMgr.addCommandToHistory(new MockCommand('Third'))
assert.equal(undoMgr.getNextRedoCommandText(), '');
assert.equal(undoMgr.getNextRedoCommandText(), '')
undoMgr.undo();
assert.equal(undoMgr.getNextRedoCommandText(), 'Third');
undoMgr.undo()
assert.equal(undoMgr.getNextRedoCommandText(), 'Third')
undoMgr.undo();
assert.equal(undoMgr.getNextRedoCommandText(), 'Second');
undoMgr.undo()
assert.equal(undoMgr.getNextRedoCommandText(), 'Second')
undoMgr.undo();
assert.equal(undoMgr.getNextRedoCommandText(), 'First');
undoMgr.undo()
assert.equal(undoMgr.getNextRedoCommandText(), 'First')
undoMgr.redo();
assert.equal(undoMgr.getNextRedoCommandText(), 'Second');
undoMgr.redo()
assert.equal(undoMgr.getNextRedoCommandText(), 'Second')
undoMgr.redo();
assert.equal(undoMgr.getNextRedoCommandText(), 'Third');
undoMgr.redo()
assert.equal(undoMgr.getNextRedoCommandText(), 'Third')
undoMgr.redo();
assert.equal(undoMgr.getNextRedoCommandText(), '');
});
undoMgr.redo()
assert.equal(undoMgr.getNextRedoCommandText(), '')
})
it('Test UndoManager.undo() and redo() functions', function () {
let lastCalled = null;
const cmd1 = new MockCommand();
const cmd2 = new MockCommand();
const cmd3 = new MockCommand();
cmd1.apply = function () { lastCalled = 'cmd1.apply'; };
cmd2.apply = function () { lastCalled = 'cmd2.apply'; };
cmd3.apply = function () { lastCalled = 'cmd3.apply'; };
cmd1.unapply = function () { lastCalled = 'cmd1.unapply'; };
cmd2.unapply = function () { lastCalled = 'cmd2.unapply'; };
cmd3.unapply = function () { lastCalled = 'cmd3.unapply'; };
let lastCalled = null
const cmd1 = new MockCommand()
const cmd2 = new MockCommand()
const cmd3 = new MockCommand()
cmd1.apply = function () { lastCalled = 'cmd1.apply' }
cmd2.apply = function () { lastCalled = 'cmd2.apply' }
cmd3.apply = function () { lastCalled = 'cmd3.apply' }
cmd1.unapply = function () { lastCalled = 'cmd1.unapply' }
cmd2.unapply = function () { lastCalled = 'cmd2.unapply' }
cmd3.unapply = function () { lastCalled = 'cmd3.unapply' }
undoMgr.addCommandToHistory(cmd1);
undoMgr.addCommandToHistory(cmd2);
undoMgr.addCommandToHistory(cmd3);
undoMgr.addCommandToHistory(cmd1)
undoMgr.addCommandToHistory(cmd2)
undoMgr.addCommandToHistory(cmd3)
assert.ok(!lastCalled);
assert.ok(!lastCalled)
undoMgr.undo();
assert.equal(lastCalled, 'cmd3.unapply');
undoMgr.undo()
assert.equal(lastCalled, 'cmd3.unapply')
undoMgr.redo();
assert.equal(lastCalled, 'cmd3.apply');
undoMgr.redo()
assert.equal(lastCalled, 'cmd3.apply')
undoMgr.undo();
undoMgr.undo();
assert.equal(lastCalled, 'cmd2.unapply');
undoMgr.undo()
undoMgr.undo()
assert.equal(lastCalled, 'cmd2.unapply')
undoMgr.undo();
assert.equal(lastCalled, 'cmd1.unapply');
lastCalled = null;
undoMgr.undo()
assert.equal(lastCalled, 'cmd1.unapply')
lastCalled = null
undoMgr.undo();
assert.ok(!lastCalled);
undoMgr.undo()
assert.ok(!lastCalled)
undoMgr.redo();
assert.equal(lastCalled, 'cmd1.apply');
undoMgr.redo()
assert.equal(lastCalled, 'cmd1.apply')
undoMgr.redo();
assert.equal(lastCalled, 'cmd2.apply');
undoMgr.redo()
assert.equal(lastCalled, 'cmd2.apply')
undoMgr.redo();
assert.equal(lastCalled, 'cmd3.apply');
lastCalled = null;
undoMgr.redo()
assert.equal(lastCalled, 'cmd3.apply')
lastCalled = null
undoMgr.redo();
assert.ok(!lastCalled);
});
undoMgr.redo()
assert.ok(!lastCalled)
})
it('Test MoveElementCommand', function () {
let move = new history.MoveElementCommand(this.div3, this.div1, this.divparent);
assert.ok(move.unapply);
assert.ok(move.apply);
assert.equal(typeof move.unapply, typeof function () { /* empty fn */ });
assert.equal(typeof move.apply, typeof function () { /* empty fn */ });
let move = new history.MoveElementCommand(this.div3, this.div1, this.divparent)
assert.ok(move.unapply)
assert.ok(move.apply)
assert.equal(typeof move.unapply, typeof function () { /* empty fn */ })
assert.equal(typeof move.apply, typeof function () { /* empty fn */ })
move.unapply();
assert.equal(this.divparent.firstElementChild, this.div3);
assert.equal(this.divparent.firstElementChild.nextElementSibling, this.div1);
assert.equal(this.divparent.lastElementChild, this.div2);
move.unapply()
assert.equal(this.divparent.firstElementChild, this.div3)
assert.equal(this.divparent.firstElementChild.nextElementSibling, this.div1)
assert.equal(this.divparent.lastElementChild, this.div2)
move.apply();
assert.equal(this.divparent.firstElementChild, this.div1);
assert.equal(this.divparent.firstElementChild.nextElementSibling, this.div2);
assert.equal(this.divparent.lastElementChild, this.div3);
move.apply()
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.divparent.firstElementChild.nextElementSibling, this.div2)
assert.equal(this.divparent.lastElementChild, this.div3)
move = new history.MoveElementCommand(this.div1, null, this.divparent);
move = new history.MoveElementCommand(this.div1, null, this.divparent)
move.unapply();
assert.equal(this.divparent.firstElementChild, this.div2);
assert.equal(this.divparent.firstElementChild.nextElementSibling, this.div3);
assert.equal(this.divparent.lastElementChild, this.div1);
move.unapply()
assert.equal(this.divparent.firstElementChild, this.div2)
assert.equal(this.divparent.firstElementChild.nextElementSibling, this.div3)
assert.equal(this.divparent.lastElementChild, this.div1)
move.apply();
assert.equal(this.divparent.firstElementChild, this.div1);
assert.equal(this.divparent.firstElementChild.nextElementSibling, this.div2);
assert.equal(this.divparent.lastElementChild, this.div3);
move.apply()
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.divparent.firstElementChild.nextElementSibling, this.div2)
assert.equal(this.divparent.lastElementChild, this.div3)
move = new history.MoveElementCommand(this.div2, this.div5, this.div4);
move = new history.MoveElementCommand(this.div2, this.div5, this.div4)
move.unapply();
assert.equal(this.divparent.firstElementChild, this.div1);
assert.equal(this.divparent.firstElementChild.nextElementSibling, this.div3);
assert.equal(this.divparent.lastElementChild, this.div3);
assert.equal(this.div4.firstElementChild, this.div2);
assert.equal(this.div4.firstElementChild.nextElementSibling, this.div5);
move.unapply()
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.divparent.firstElementChild.nextElementSibling, this.div3)
assert.equal(this.divparent.lastElementChild, this.div3)
assert.equal(this.div4.firstElementChild, this.div2)
assert.equal(this.div4.firstElementChild.nextElementSibling, this.div5)
move.apply();
assert.equal(this.divparent.firstElementChild, this.div1);
assert.equal(this.divparent.firstElementChild.nextElementSibling, this.div2);
assert.equal(this.divparent.lastElementChild, this.div3);
assert.equal(this.div4.firstElementChild, this.div5);
assert.equal(this.div4.lastElementChild, this.div5);
});
move.apply()
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.divparent.firstElementChild.nextElementSibling, this.div2)
assert.equal(this.divparent.lastElementChild, this.div3)
assert.equal(this.div4.firstElementChild, this.div5)
assert.equal(this.div4.lastElementChild, this.div5)
})
it('Test InsertElementCommand', function () {
let insert = new history.InsertElementCommand(this.div3);
assert.ok(insert.unapply);
assert.ok(insert.apply);
assert.equal(typeof insert.unapply, typeof function () { /* empty fn */ });
assert.equal(typeof insert.apply, typeof function () { /* empty fn */ });
let insert = new history.InsertElementCommand(this.div3)
assert.ok(insert.unapply)
assert.ok(insert.apply)
assert.equal(typeof insert.unapply, typeof function () { /* empty fn */ })
assert.equal(typeof insert.apply, typeof function () { /* empty fn */ })
insert.unapply();
assert.equal(this.divparent.childElementCount, 2);
assert.equal(this.divparent.firstElementChild, this.div1);
assert.equal(this.div1.nextElementSibling, this.div2);
assert.equal(this.divparent.lastElementChild, this.div2);
insert.unapply()
assert.equal(this.divparent.childElementCount, 2)
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.div1.nextElementSibling, this.div2)
assert.equal(this.divparent.lastElementChild, this.div2)
insert.apply();
assert.equal(this.divparent.childElementCount, 3);
assert.equal(this.divparent.firstElementChild, this.div1);
assert.equal(this.div1.nextElementSibling, this.div2);
assert.equal(this.div2.nextElementSibling, this.div3);
insert.apply()
assert.equal(this.divparent.childElementCount, 3)
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.div1.nextElementSibling, this.div2)
assert.equal(this.div2.nextElementSibling, this.div3)
insert = new history.InsertElementCommand(this.div2);
insert = new history.InsertElementCommand(this.div2)
insert.unapply();
assert.equal(this.divparent.childElementCount, 2);
assert.equal(this.divparent.firstElementChild, this.div1);
assert.equal(this.div1.nextElementSibling, this.div3);
assert.equal(this.divparent.lastElementChild, this.div3);
insert.unapply()
assert.equal(this.divparent.childElementCount, 2)
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.div1.nextElementSibling, this.div3)
assert.equal(this.divparent.lastElementChild, this.div3)
insert.apply();
assert.equal(this.divparent.childElementCount, 3);
assert.equal(this.divparent.firstElementChild, this.div1);
assert.equal(this.div1.nextElementSibling, this.div2);
assert.equal(this.div2.nextElementSibling, this.div3);
});
insert.apply()
assert.equal(this.divparent.childElementCount, 3)
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.div1.nextElementSibling, this.div2)
assert.equal(this.div2.nextElementSibling, this.div3)
})
it('Test RemoveElementCommand', function () {
const div6 = document.createElement('div');
div6.id = 'div6';
const div6 = document.createElement('div')
div6.id = 'div6'
let remove = new history.RemoveElementCommand(div6, null, this.divparent);
assert.ok(remove.unapply);
assert.ok(remove.apply);
assert.equal(typeof remove.unapply, typeof function () { /* empty fn */ });
assert.equal(typeof remove.apply, typeof function () { /* empty fn */ });
let remove = new history.RemoveElementCommand(div6, null, this.divparent)
assert.ok(remove.unapply)
assert.ok(remove.apply)
assert.equal(typeof remove.unapply, typeof function () { /* empty fn */ })
assert.equal(typeof remove.apply, typeof function () { /* empty fn */ })
remove.unapply();
assert.equal(this.divparent.childElementCount, 4);
assert.equal(this.divparent.firstElementChild, this.div1);
assert.equal(this.div1.nextElementSibling, this.div2);
assert.equal(this.div2.nextElementSibling, this.div3);
assert.equal(this.div3.nextElementSibling, div6);
remove.unapply()
assert.equal(this.divparent.childElementCount, 4)
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.div1.nextElementSibling, this.div2)
assert.equal(this.div2.nextElementSibling, this.div3)
assert.equal(this.div3.nextElementSibling, div6)
remove.apply();
assert.equal(this.divparent.childElementCount, 3);
assert.equal(this.divparent.firstElementChild, this.div1);
assert.equal(this.div1.nextElementSibling, this.div2);
assert.equal(this.div2.nextElementSibling, this.div3);
remove.apply()
assert.equal(this.divparent.childElementCount, 3)
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.div1.nextElementSibling, this.div2)
assert.equal(this.div2.nextElementSibling, this.div3)
remove = new history.RemoveElementCommand(div6, this.div2, this.divparent);
remove = new history.RemoveElementCommand(div6, this.div2, this.divparent)
remove.unapply();
assert.equal(this.divparent.childElementCount, 4);
assert.equal(this.divparent.firstElementChild, this.div1);
assert.equal(this.div1.nextElementSibling, div6);
assert.equal(div6.nextElementSibling, this.div2);
assert.equal(this.div2.nextElementSibling, this.div3);
remove.unapply()
assert.equal(this.divparent.childElementCount, 4)
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.div1.nextElementSibling, div6)
assert.equal(div6.nextElementSibling, this.div2)
assert.equal(this.div2.nextElementSibling, this.div3)
remove.apply();
assert.equal(this.divparent.childElementCount, 3);
assert.equal(this.divparent.firstElementChild, this.div1);
assert.equal(this.div1.nextElementSibling, this.div2);
assert.equal(this.div2.nextElementSibling, this.div3);
});
remove.apply()
assert.equal(this.divparent.childElementCount, 3)
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.div1.nextElementSibling, this.div2)
assert.equal(this.div2.nextElementSibling, this.div3)
})
it('Test ChangeElementCommand', function () {
this.div1.setAttribute('title', 'new title');
this.div1.setAttribute('title', 'new title')
let change = new history.ChangeElementCommand(this.div1,
{ title: 'old title', class: 'foo' });
assert.ok(change.unapply);
assert.ok(change.apply);
assert.equal(typeof change.unapply, typeof function () { /* empty fn */ });
assert.equal(typeof change.apply, typeof function () { /* empty fn */ });
{ title: 'old title', class: 'foo' })
assert.ok(change.unapply)
assert.ok(change.apply)
assert.equal(typeof change.unapply, typeof function () { /* empty fn */ })
assert.equal(typeof change.apply, typeof function () { /* empty fn */ })
change.unapply();
assert.equal(this.div1.getAttribute('title'), 'old title');
assert.equal(this.div1.getAttribute('class'), 'foo');
change.unapply()
assert.equal(this.div1.getAttribute('title'), 'old title')
assert.equal(this.div1.getAttribute('class'), 'foo')
change.apply();
assert.equal(this.div1.getAttribute('title'), 'new title');
assert.ok(!this.div1.getAttribute('class'));
change.apply()
assert.equal(this.div1.getAttribute('title'), 'new title')
assert.ok(!this.div1.getAttribute('class'))
this.div1.textContent = 'inner text';
this.div1.textContent = 'inner text'
change = new history.ChangeElementCommand(this.div1,
{ '#text': null });
{ '#text': null })
change.unapply();
assert.ok(!this.div1.textContent);
change.unapply()
assert.ok(!this.div1.textContent)
change.apply();
assert.equal(this.div1.textContent, 'inner text');
change.apply()
assert.equal(this.div1.textContent, 'inner text')
this.div1.textContent = '';
this.div1.textContent = ''
change = new history.ChangeElementCommand(this.div1,
{ '#text': 'old text' });
{ '#text': 'old text' })
change.unapply();
assert.equal(this.div1.textContent, 'old text');
change.unapply()
assert.equal(this.div1.textContent, 'old text')
change.apply();
assert.ok(!this.div1.textContent);
change.apply()
assert.ok(!this.div1.textContent)
// TODO(codedread): Refactor this #href stuff in history.js and svgcanvas.js
const rect = document.createElementNS(NS.SVG, 'rect');
let justCalled = null;
let gethrefvalue = null;
let sethrefvalue = null;
const rect = document.createElementNS(NS.SVG, 'rect')
let justCalled = null
let gethrefvalue = null
let sethrefvalue = null
utilities.mock({
getHref (elem) {
assert.equal(elem, rect);
justCalled = 'getHref';
return gethrefvalue;
assert.equal(elem, rect)
justCalled = 'getHref'
return gethrefvalue
},
setHref (elem, val) {
assert.equal(elem, rect);
assert.equal(val, sethrefvalue);
justCalled = 'setHref';
assert.equal(elem, rect)
assert.equal(val, sethrefvalue)
justCalled = 'setHref'
},
getRotationAngle () { return 0; }
});
getRotationAngle () { return 0 }
})
gethrefvalue = '#newhref';
gethrefvalue = '#newhref'
change = new history.ChangeElementCommand(rect,
{ '#href': '#oldhref' });
assert.equal(justCalled, 'getHref');
{ '#href': '#oldhref' })
assert.equal(justCalled, 'getHref')
justCalled = null;
sethrefvalue = '#oldhref';
change.unapply();
assert.equal(justCalled, 'setHref');
justCalled = null
sethrefvalue = '#oldhref'
change.unapply()
assert.equal(justCalled, 'setHref')
justCalled = null;
sethrefvalue = '#newhref';
change.apply();
assert.equal(justCalled, 'setHref');
justCalled = null
sethrefvalue = '#newhref'
change.apply()
assert.equal(justCalled, 'setHref')
const line = document.createElementNS(NS.SVG, 'line');
line.setAttribute('class', 'newClass');
change = new history.ChangeElementCommand(line, { class: 'oldClass' });
const line = document.createElementNS(NS.SVG, 'line')
line.setAttribute('class', 'newClass')
change = new history.ChangeElementCommand(line, { class: 'oldClass' })
assert.ok(change.unapply);
assert.ok(change.apply);
assert.equal(typeof change.unapply, typeof function () { /* empty fn */ });
assert.equal(typeof change.apply, typeof function () { /* empty fn */ });
assert.ok(change.unapply)
assert.ok(change.apply)
assert.equal(typeof change.unapply, typeof function () { /* empty fn */ })
assert.equal(typeof change.apply, typeof function () { /* empty fn */ })
change.unapply();
assert.equal(line.getAttribute('class'), 'oldClass');
change.unapply()
assert.equal(line.getAttribute('class'), 'oldClass')
change.apply();
assert.equal(line.getAttribute('class'), 'newClass');
});
change.apply()
assert.equal(line.getAttribute('class'), 'newClass')
})
it('Test BatchCommand', function () {
let concatResult = '';
MockCommand.prototype.apply = function () { concatResult += this.text; };
let concatResult = ''
MockCommand.prototype.apply = function () { concatResult += this.text }
const batch = new history.BatchCommand();
assert.ok(batch.unapply);
assert.ok(batch.apply);
assert.ok(batch.addSubCommand);
assert.ok(batch.isEmpty);
assert.equal(typeof batch.unapply, 'function');
assert.equal(typeof batch.apply, 'function');
assert.equal(typeof batch.addSubCommand, 'function');
assert.equal(typeof batch.isEmpty, 'function');
const batch = new history.BatchCommand()
assert.ok(batch.unapply)
assert.ok(batch.apply)
assert.ok(batch.addSubCommand)
assert.ok(batch.isEmpty)
assert.equal(typeof batch.unapply, 'function')
assert.equal(typeof batch.apply, 'function')
assert.equal(typeof batch.addSubCommand, 'function')
assert.equal(typeof batch.isEmpty, 'function')
assert.ok(batch.isEmpty());
assert.ok(batch.isEmpty())
batch.addSubCommand(new MockCommand('a'));
assert.ok(!batch.isEmpty());
batch.addSubCommand(new MockCommand('b'));
batch.addSubCommand(new MockCommand('c'));
batch.addSubCommand(new MockCommand('a'))
assert.ok(!batch.isEmpty())
batch.addSubCommand(new MockCommand('b'))
batch.addSubCommand(new MockCommand('c'))
assert.ok(!concatResult);
batch.apply();
assert.equal(concatResult, 'abc');
assert.ok(!concatResult)
batch.apply()
assert.equal(concatResult, 'abc')
MockCommand.prototype.apply = function () { /* empty fn */ };
MockCommand.prototype.unapply = function () { concatResult += this.text; };
concatResult = '';
assert.ok(!concatResult);
batch.unapply();
assert.equal(concatResult, 'cba');
MockCommand.prototype.apply = function () { /* empty fn */ }
MockCommand.prototype.unapply = function () { concatResult += this.text }
concatResult = ''
assert.ok(!concatResult)
batch.unapply()
assert.equal(concatResult, 'cba')
MockCommand.prototype.unapply = function () { /* empty fn */ };
});
});
MockCommand.prototype.unapply = function () { /* empty fn */ }
})
})

View File

@ -1,106 +1,106 @@
import { NS } from '../../../instrumented/svgcanvas/namespaces.js';
import * as math from '../../../instrumented/svgcanvas/math.js';
import { NS } from '../../../instrumented/svgcanvas/namespaces.js'
import * as math from '../../../instrumented/svgcanvas/math.js'
describe('math', function () {
const svg = document.createElementNS(NS.SVG, 'svg');
const svg = document.createElementNS(NS.SVG, 'svg')
it('Test svgedit.math package', function () {
assert.ok(math);
assert.ok(math.transformPoint);
assert.ok(math.isIdentity);
assert.ok(math.matrixMultiply);
assert.equal(typeof math.transformPoint, typeof function () { /* empty fn */ });
assert.equal(typeof math.isIdentity, typeof function () { /* empty fn */ });
assert.equal(typeof math.matrixMultiply, typeof function () { /* empty fn */ });
});
assert.ok(math)
assert.ok(math.transformPoint)
assert.ok(math.isIdentity)
assert.ok(math.matrixMultiply)
assert.equal(typeof math.transformPoint, typeof function () { /* empty fn */ })
assert.equal(typeof math.isIdentity, typeof function () { /* empty fn */ })
assert.equal(typeof math.matrixMultiply, typeof function () { /* empty fn */ })
})
it('Test svgedit.math.transformPoint() function', function () {
const { transformPoint } = math;
const { transformPoint } = math
const m = svg.createSVGMatrix();
m.a = 1; m.b = 0;
m.c = 0; m.d = 1;
m.e = 0; m.f = 0;
let pt = transformPoint(100, 200, m);
assert.equal(pt.x, 100);
assert.equal(pt.y, 200);
const m = svg.createSVGMatrix()
m.a = 1; m.b = 0
m.c = 0; m.d = 1
m.e = 0; m.f = 0
let pt = transformPoint(100, 200, m)
assert.equal(pt.x, 100)
assert.equal(pt.y, 200)
m.e = 300; m.f = 400;
pt = transformPoint(100, 200, m);
assert.equal(pt.x, 400);
assert.equal(pt.y, 600);
m.e = 300; m.f = 400
pt = transformPoint(100, 200, m)
assert.equal(pt.x, 400)
assert.equal(pt.y, 600)
m.a = 0.5; m.b = 0.75;
m.c = 1.25; m.d = 2;
pt = transformPoint(100, 200, m);
assert.equal(pt.x, 100 * m.a + 200 * m.c + m.e);
assert.equal(pt.y, 100 * m.b + 200 * m.d + m.f);
});
m.a = 0.5; m.b = 0.75
m.c = 1.25; m.d = 2
pt = transformPoint(100, 200, m)
assert.equal(pt.x, 100 * m.a + 200 * m.c + m.e)
assert.equal(pt.y, 100 * m.b + 200 * m.d + m.f)
})
it('Test svgedit.math.isIdentity() function', function () {
assert.ok(math.isIdentity(svg.createSVGMatrix()));
assert.ok(math.isIdentity(svg.createSVGMatrix()))
const m = svg.createSVGMatrix();
m.a = 1; m.b = 0;
m.c = 0; m.d = 1;
m.e = 0; m.f = 0;
assert.ok(math.isIdentity(m));
});
const m = svg.createSVGMatrix()
m.a = 1; m.b = 0
m.c = 0; m.d = 1
m.e = 0; m.f = 0
assert.ok(math.isIdentity(m))
})
it('Test svgedit.math.matrixMultiply() function', function () {
const mult = math.matrixMultiply;
const { isIdentity } = math;
const mult = math.matrixMultiply
const { isIdentity } = math
// translate there and back
const tr1 = svg.createSVGMatrix().translate(100, 50);
const tr2 = svg.createSVGMatrix().translate(-90, 0);
const tr3 = svg.createSVGMatrix().translate(-10, -50);
let I = mult(tr1, tr2, tr3);
assert.ok(isIdentity(I), 'Expected identity matrix when translating there and back');
const tr1 = svg.createSVGMatrix().translate(100, 50)
const tr2 = svg.createSVGMatrix().translate(-90, 0)
const tr3 = svg.createSVGMatrix().translate(-10, -50)
let I = mult(tr1, tr2, tr3)
assert.ok(isIdentity(I), 'Expected identity matrix when translating there and back')
// rotate there and back
// TODO: currently Mozilla fails this when rotating back at -50 and then -40 degrees
// (b and c are *almost* zero, but not zero)
const rotThere = svg.createSVGMatrix().rotate(90);
const rotBack = svg.createSVGMatrix().rotate(-90); // TODO: set this to -50
const rotBackMore = svg.createSVGMatrix().rotate(0); // TODO: set this to -40
I = mult(rotThere, rotBack, rotBackMore);
assert.ok(isIdentity(I), 'Expected identity matrix when rotating there and back');
const rotThere = svg.createSVGMatrix().rotate(90)
const rotBack = svg.createSVGMatrix().rotate(-90) // TODO: set this to -50
const rotBackMore = svg.createSVGMatrix().rotate(0) // TODO: set this to -40
I = mult(rotThere, rotBack, rotBackMore)
assert.ok(isIdentity(I), 'Expected identity matrix when rotating there and back')
// scale up and down
const scaleUp = svg.createSVGMatrix().scale(4);
const scaleDown = svg.createSVGMatrix().scaleNonUniform(0.25, 1);
const scaleDownMore = svg.createSVGMatrix().scaleNonUniform(1, 0.25);
I = mult(scaleUp, scaleDown, scaleDownMore);
assert.ok(isIdentity(I), 'Expected identity matrix when scaling up and down');
const scaleUp = svg.createSVGMatrix().scale(4)
const scaleDown = svg.createSVGMatrix().scaleNonUniform(0.25, 1)
const scaleDownMore = svg.createSVGMatrix().scaleNonUniform(1, 0.25)
I = mult(scaleUp, scaleDown, scaleDownMore)
assert.ok(isIdentity(I), 'Expected identity matrix when scaling up and down')
// test multiplication with its inverse
I = mult(rotThere, rotThere.inverse());
assert.ok(isIdentity(I), 'Expected identity matrix when multiplying a matrix by its inverse');
I = mult(rotThere.inverse(), rotThere);
assert.ok(isIdentity(I), 'Expected identity matrix when multiplying a matrix by its inverse');
});
I = mult(rotThere, rotThere.inverse())
assert.ok(isIdentity(I), 'Expected identity matrix when multiplying a matrix by its inverse')
I = mult(rotThere.inverse(), rotThere)
assert.ok(isIdentity(I), 'Expected identity matrix when multiplying a matrix by its inverse')
})
it('Test svgedit.math.transformBox() function', function () {
const { transformBox } = math;
const { transformBox } = math
const m = svg.createSVGMatrix();
m.a = 1; m.b = 0;
m.c = 0; m.d = 1;
m.e = 0; m.f = 0;
const m = svg.createSVGMatrix()
m.a = 1; m.b = 0
m.c = 0; m.d = 1
m.e = 0; m.f = 0
const r = transformBox(10, 10, 200, 300, m);
assert.equal(r.tl.x, 10);
assert.equal(r.tl.y, 10);
assert.equal(r.tr.x, 210);
assert.equal(r.tr.y, 10);
assert.equal(r.bl.x, 10);
assert.equal(r.bl.y, 310);
assert.equal(r.br.x, 210);
assert.equal(r.br.y, 310);
assert.equal(r.aabox.x, 10);
assert.equal(r.aabox.y, 10);
assert.equal(r.aabox.width, 200);
assert.equal(r.aabox.height, 300);
});
});
const r = transformBox(10, 10, 200, 300, m)
assert.equal(r.tl.x, 10)
assert.equal(r.tl.y, 10)
assert.equal(r.tr.x, 210)
assert.equal(r.tr.y, 10)
assert.equal(r.bl.x, 10)
assert.equal(r.bl.y, 310)
assert.equal(r.br.x, 210)
assert.equal(r.br.y, 310)
assert.equal(r.aabox.x, 10)
assert.equal(r.aabox.y, 10)
assert.equal(r.aabox.width, 200)
assert.equal(r.aabox.height, 300)
})
})

View File

@ -1,10 +1,10 @@
/* globals SVGPathSeg */
import 'pathseg';
import { NS } from '../../../instrumented/svgcanvas/namespaces.js';
import * as utilities from '../../../instrumented/svgcanvas/utilities.js';
import * as pathModule from '../../../instrumented/svgcanvas/path.js';
import { Path, Segment } from '../../../instrumented/svgcanvas/path-method.js';
import { init as unitsInit } from '../../../instrumented/common/units.js';
import 'pathseg'
import { NS } from '../../../instrumented/svgcanvas/namespaces.js'
import * as utilities from '../../../instrumented/svgcanvas/utilities.js'
import * as pathModule from '../../../instrumented/svgcanvas/path.js'
import { Path, Segment } from '../../../instrumented/svgcanvas/path-method.js'
import { init as unitsInit } from '../../../instrumented/common/units.js'
describe('path', function () {
/**
@ -18,165 +18,165 @@ describe('path', function () {
* @returns {EditorContexts}
*/
function getMockContexts (svg) {
svg = svg || document.createElementNS(NS.SVG, 'svg');
const selectorParentGroup = document.createElementNS(NS.SVG, 'g');
selectorParentGroup.setAttribute('id', 'selectorParentGroup');
svg.append(selectorParentGroup);
svg = svg || document.createElementNS(NS.SVG, 'svg')
const selectorParentGroup = document.createElementNS(NS.SVG, 'g')
selectorParentGroup.setAttribute('id', 'selectorParentGroup')
svg.append(selectorParentGroup)
return [
/**
* @implements {module:path.EditorContext}
*/
{
getSvgRoot () { return svg; },
getZoom () { return 1; }
getSvgRoot () { return svg },
getZoom () { return 1 }
},
/**
* @implements {module:utilities.EditorContext}
*/
{
getDOMDocument () { return svg; },
getDOMContainer () { return svg; },
getSvgRoot () { return svg; }
getDOMDocument () { return svg },
getDOMContainer () { return svg },
getSvgRoot () { return svg }
}
];
]
}
it('Test svgedit.path.replacePathSeg', function () {
const path = document.createElementNS(NS.SVG, 'path');
path.setAttribute('d', 'M0,0 L10,11 L20,21Z');
const path = document.createElementNS(NS.SVG, 'path')
path.setAttribute('d', 'M0,0 L10,11 L20,21Z')
const [ mockPathContext, mockUtilitiesContext ] = getMockContexts();
pathModule.init(mockPathContext);
utilities.init(mockUtilitiesContext);
new Path(path);
const [mockPathContext, mockUtilitiesContext] = getMockContexts()
pathModule.init(mockPathContext)
utilities.init(mockUtilitiesContext)
Path(path)
assert.equal(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'L');
assert.equal(path.pathSegList.getItem(1).x, 10);
assert.equal(path.pathSegList.getItem(1).y, 11);
assert.equal(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'L')
assert.equal(path.pathSegList.getItem(1).x, 10)
assert.equal(path.pathSegList.getItem(1).y, 11)
pathModule.replacePathSeg(SVGPathSeg.PATHSEG_LINETO_REL, 1, [ 30, 31 ], path);
pathModule.replacePathSeg(SVGPathSeg.PATHSEG_LINETO_REL, 1, [30, 31], path)
assert.equal(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'l');
assert.equal(path.pathSegList.getItem(1).x, 30);
assert.equal(path.pathSegList.getItem(1).y, 31);
});
assert.equal(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'l')
assert.equal(path.pathSegList.getItem(1).x, 30)
assert.equal(path.pathSegList.getItem(1).y, 31)
})
it('Test svgedit.path.Segment.setType simple', function () {
const path = document.createElementNS(NS.SVG, 'path');
path.setAttribute('d', 'M0,0 L10,11 L20,21Z');
const path = document.createElementNS(NS.SVG, 'path')
path.setAttribute('d', 'M0,0 L10,11 L20,21Z')
const [ mockPathContext, mockUtilitiesContext ] = getMockContexts();
pathModule.init(mockPathContext);
utilities.init(mockUtilitiesContext);
new Path(path);
const [mockPathContext, mockUtilitiesContext] = getMockContexts()
pathModule.init(mockPathContext)
utilities.init(mockUtilitiesContext)
Path(path)
assert.equal(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'L');
assert.equal(path.pathSegList.getItem(1).x, 10);
assert.equal(path.pathSegList.getItem(1).y, 11);
assert.equal(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'L')
assert.equal(path.pathSegList.getItem(1).x, 10)
assert.equal(path.pathSegList.getItem(1).y, 11)
const segment = new Segment(1, path.pathSegList.getItem(1));
segment.setType(SVGPathSeg.PATHSEG_LINETO_REL, [ 30, 31 ]);
assert.equal(segment.item.pathSegTypeAsLetter, 'l');
assert.equal(segment.item.x, 30);
assert.equal(segment.item.y, 31);
const segment = new Segment(1, path.pathSegList.getItem(1))
segment.setType(SVGPathSeg.PATHSEG_LINETO_REL, [30, 31])
assert.equal(segment.item.pathSegTypeAsLetter, 'l')
assert.equal(segment.item.x, 30)
assert.equal(segment.item.y, 31)
// Also verify that the actual path changed.
assert.equal(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'l');
assert.equal(path.pathSegList.getItem(1).x, 30);
assert.equal(path.pathSegList.getItem(1).y, 31);
});
assert.equal(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'l')
assert.equal(path.pathSegList.getItem(1).x, 30)
assert.equal(path.pathSegList.getItem(1).y, 31)
})
it('Test svgedit.path.Segment.setType with control points', function () {
// Setup the dom for a mock control group.
const svg = document.createElementNS(NS.SVG, 'svg');
const path = document.createElementNS(NS.SVG, 'path');
path.setAttribute('d', 'M0,0 C11,12 13,14 15,16 Z');
svg.append(path);
const svg = document.createElementNS(NS.SVG, 'svg')
const path = document.createElementNS(NS.SVG, 'path')
path.setAttribute('d', 'M0,0 C11,12 13,14 15,16 Z')
svg.append(path)
const [ mockPathContext, mockUtilitiesContext ] = getMockContexts(svg);
pathModule.init(mockPathContext);
utilities.init(mockUtilitiesContext);
const segment = new Segment(1, path.pathSegList.getItem(1));
segment.path = new Path(path);
const [mockPathContext, mockUtilitiesContext] = getMockContexts(svg)
pathModule.init(mockPathContext)
utilities.init(mockUtilitiesContext)
const segment = new Segment(1, path.pathSegList.getItem(1))
segment.path = new Path(path)
assert.equal(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'C');
assert.equal(path.pathSegList.getItem(1).x1, 11);
assert.equal(path.pathSegList.getItem(1).y1, 12);
assert.equal(path.pathSegList.getItem(1).x2, 13);
assert.equal(path.pathSegList.getItem(1).y2, 14);
assert.equal(path.pathSegList.getItem(1).x, 15);
assert.equal(path.pathSegList.getItem(1).y, 16);
assert.equal(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'C')
assert.equal(path.pathSegList.getItem(1).x1, 11)
assert.equal(path.pathSegList.getItem(1).y1, 12)
assert.equal(path.pathSegList.getItem(1).x2, 13)
assert.equal(path.pathSegList.getItem(1).y2, 14)
assert.equal(path.pathSegList.getItem(1).x, 15)
assert.equal(path.pathSegList.getItem(1).y, 16)
segment.setType(SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, [ 30, 31, 32, 33, 34, 35 ]);
assert.equal(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'c');
assert.equal(path.pathSegList.getItem(1).x1, 32);
assert.equal(path.pathSegList.getItem(1).y1, 33);
assert.equal(path.pathSegList.getItem(1).x2, 34);
assert.equal(path.pathSegList.getItem(1).y2, 35);
assert.equal(path.pathSegList.getItem(1).x, 30);
assert.equal(path.pathSegList.getItem(1).y, 31);
});
segment.setType(SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, [30, 31, 32, 33, 34, 35])
assert.equal(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'c')
assert.equal(path.pathSegList.getItem(1).x1, 32)
assert.equal(path.pathSegList.getItem(1).y1, 33)
assert.equal(path.pathSegList.getItem(1).x2, 34)
assert.equal(path.pathSegList.getItem(1).y2, 35)
assert.equal(path.pathSegList.getItem(1).x, 30)
assert.equal(path.pathSegList.getItem(1).y, 31)
})
it('Test svgedit.path.Segment.move', function () {
const path = document.createElementNS(NS.SVG, 'path');
path.setAttribute('d', 'M0,0 L10,11 L20,21Z');
const path = document.createElementNS(NS.SVG, 'path')
path.setAttribute('d', 'M0,0 L10,11 L20,21Z')
const [ mockPathContext, mockUtilitiesContext ] = getMockContexts();
pathModule.init(mockPathContext);
utilities.init(mockUtilitiesContext);
new Path(path);
const [mockPathContext, mockUtilitiesContext] = getMockContexts()
pathModule.init(mockPathContext)
utilities.init(mockUtilitiesContext)
Path(path)
assert.equal(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'L');
assert.equal(path.pathSegList.getItem(1).x, 10);
assert.equal(path.pathSegList.getItem(1).y, 11);
assert.equal(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'L')
assert.equal(path.pathSegList.getItem(1).x, 10)
assert.equal(path.pathSegList.getItem(1).y, 11)
const segment = new Segment(1, path.pathSegList.getItem(1));
segment.move(-3, 4);
assert.equal(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'L');
assert.equal(path.pathSegList.getItem(1).x, 7);
assert.equal(path.pathSegList.getItem(1).y, 15);
});
const segment = new Segment(1, path.pathSegList.getItem(1))
segment.move(-3, 4)
assert.equal(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'L')
assert.equal(path.pathSegList.getItem(1).x, 7)
assert.equal(path.pathSegList.getItem(1).y, 15)
})
it('Test svgedit.path.Segment.moveCtrl', function () {
const path = document.createElementNS(NS.SVG, 'path');
path.setAttribute('d', 'M0,0 C11,12 13,14 15,16 Z');
const path = document.createElementNS(NS.SVG, 'path')
path.setAttribute('d', 'M0,0 C11,12 13,14 15,16 Z')
const [ mockPathContext, mockUtilitiesContext ] = getMockContexts();
pathModule.init(mockPathContext);
utilities.init(mockUtilitiesContext);
new Path(path);
const [mockPathContext, mockUtilitiesContext] = getMockContexts()
pathModule.init(mockPathContext)
utilities.init(mockUtilitiesContext)
Path(path)
assert.equal(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'C');
assert.equal(path.pathSegList.getItem(1).x1, 11);
assert.equal(path.pathSegList.getItem(1).y1, 12);
assert.equal(path.pathSegList.getItem(1).x2, 13);
assert.equal(path.pathSegList.getItem(1).y2, 14);
assert.equal(path.pathSegList.getItem(1).x, 15);
assert.equal(path.pathSegList.getItem(1).y, 16);
assert.equal(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'C')
assert.equal(path.pathSegList.getItem(1).x1, 11)
assert.equal(path.pathSegList.getItem(1).y1, 12)
assert.equal(path.pathSegList.getItem(1).x2, 13)
assert.equal(path.pathSegList.getItem(1).y2, 14)
assert.equal(path.pathSegList.getItem(1).x, 15)
assert.equal(path.pathSegList.getItem(1).y, 16)
const segment = new Segment(1, path.pathSegList.getItem(1));
segment.moveCtrl(1, 100, -200);
assert.equal(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'C');
assert.equal(path.pathSegList.getItem(1).x1, 111);
assert.equal(path.pathSegList.getItem(1).y1, -188);
assert.equal(path.pathSegList.getItem(1).x2, 13);
assert.equal(path.pathSegList.getItem(1).y2, 14);
assert.equal(path.pathSegList.getItem(1).x, 15);
assert.equal(path.pathSegList.getItem(1).y, 16);
});
const segment = new Segment(1, path.pathSegList.getItem(1))
segment.moveCtrl(1, 100, -200)
assert.equal(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'C')
assert.equal(path.pathSegList.getItem(1).x1, 111)
assert.equal(path.pathSegList.getItem(1).y1, -188)
assert.equal(path.pathSegList.getItem(1).x2, 13)
assert.equal(path.pathSegList.getItem(1).y2, 14)
assert.equal(path.pathSegList.getItem(1).x, 15)
assert.equal(path.pathSegList.getItem(1).y, 16)
})
it('Test svgedit.path.convertPath', function () {
unitsInit({
getRoundDigits () { return 5; }
});
getRoundDigits () { return 5 }
})
const path = document.createElementNS(NS.SVG, 'path');
path.setAttribute('d', 'M40,55h20v20');
const path = document.createElementNS(NS.SVG, 'path')
path.setAttribute('d', 'M40,55h20v20')
const abs = pathModule.convertPath(path);
assert.equal(abs, 'M40,55L60,55L60,75');
const abs = pathModule.convertPath(path)
assert.equal(abs, 'M40,55L60,55L60,75')
const rel = pathModule.convertPath(path, true);
assert.equal(rel, 'm40,55l20,0l0,20');
});
});
const rel = pathModule.convertPath(path, true)
assert.equal(rel, 'm40,55l20,0l0,20')
})
})

View File

@ -1,122 +1,121 @@
import { NS } from '../../../instrumented/svgcanvas/namespaces.js';
import * as utilities from '../../../instrumented/svgcanvas/utilities.js';
import * as coords from '../../../instrumented/svgcanvas/coords.js';
import * as recalculate from '../../../instrumented/svgcanvas/recalculate.js';
import { NS } from '../../../instrumented/svgcanvas/namespaces.js'
import * as utilities from '../../../instrumented/svgcanvas/utilities.js'
import * as coords from '../../../instrumented/svgcanvas/coords.js'
import * as recalculate from '../../../instrumented/svgcanvas/recalculate.js'
describe('recalculate', function () {
const root = document.createElement('div');
root.id = 'root';
root.style.visibility = 'hidden';
const root = document.createElement('div')
root.id = 'root'
root.style.visibility = 'hidden'
const svgroot = document.createElementNS(NS.SVG, 'svg');
svgroot.id = 'svgroot';
root.append(svgroot);
const svg = document.createElementNS(NS.SVG, 'svg');
svgroot.append(svg);
const svgroot = document.createElementNS(NS.SVG, 'svg')
svgroot.id = 'svgroot'
root.append(svgroot)
const svg = document.createElementNS(NS.SVG, 'svg')
svgroot.append(svg)
const dataStorage = {
_storage: new WeakMap(),
put: function (element, key, obj) {
if (!this._storage.has(element)) {
this._storage.set(element, new Map());
this._storage.set(element, new Map())
}
this._storage.get(element).set(key, obj);
this._storage.get(element).set(key, obj)
},
get: function (element, key) {
return this._storage.get(element).get(key);
return this._storage.get(element).get(key)
},
has: function (element, key) {
return this._storage.has(element) && this._storage.get(element).has(key);
return this._storage.has(element) && this._storage.get(element).has(key)
},
remove: function (element, key) {
const ret = this._storage.get(element).delete(key);
const ret = this._storage.get(element).delete(key)
if (!this._storage.get(element).size === 0) {
this._storage.delete(element);
this._storage.delete(element)
}
return ret;
return ret
}
};
}
let elemId = 1;
let elemId = 1
/**
* Initilize modules to set up the tests.
* @returns {void}
*/
function setUp() {
function setUp () {
utilities.init(
/**
* @implements {module:utilities.EditorContext}
*/
{
getSvgRoot() { return svg; },
getDOMDocument() { return null; },
getDOMContainer() { return null; },
getDataStorage() { return dataStorage; }
getSvgRoot () { return svg },
getDOMDocument () { return null },
getDOMContainer () { return null },
getDataStorage () { return dataStorage }
}
);
)
coords.init(
/**
* @implements {module:coords.EditorContext}
*/
{
getGridSnapping() { return false; },
getDrawing() {
getGridSnapping () { return false },
getDrawing () {
return {
getNextId() { return String(elemId++); }
};
getNextId () { return String(elemId++) }
}
},
getDataStorage() { return dataStorage; }
getDataStorage () { return dataStorage }
}
);
)
recalculate.init(
/**
* @implements {module:recalculate.EditorContext}
*/
{
getSvgRoot() { return svg; },
getStartTransform() { return ''; },
setStartTransform() { /* empty fn */ },
getDataStorage() { return dataStorage; }
getSvgRoot () { return svg },
getStartTransform () { return '' },
setStartTransform () { /* empty fn */ },
getDataStorage () { return dataStorage }
}
);
)
}
let elem;
let elem
/**
* Initialize for tests and set up `rect` element.
* @returns {void}
*/
function setUpRect() {
setUp();
elem = document.createElementNS(NS.SVG, 'rect');
elem.setAttribute('x', '200');
elem.setAttribute('y', '150');
elem.setAttribute('width', '250');
elem.setAttribute('height', '120');
svg.append(elem);
function setUpRect () {
setUp()
elem = document.createElementNS(NS.SVG, 'rect')
elem.setAttribute('x', '200')
elem.setAttribute('y', '150')
elem.setAttribute('width', '250')
elem.setAttribute('height', '120')
svg.append(elem)
}
/**
* Initialize for tests and set up `text` element with `tspan` child.
* @returns {void}
*/
function setUpTextWithTspan() {
setUp();
elem = document.createElementNS(NS.SVG, 'text');
elem.setAttribute('x', '200');
elem.setAttribute('y', '150');
function setUpTextWithTspan () {
setUp()
elem = document.createElementNS(NS.SVG, 'text')
elem.setAttribute('x', '200')
elem.setAttribute('y', '150')
const tspan = document.createElementNS(NS.SVG, 'tspan');
tspan.setAttribute('x', '200');
tspan.setAttribute('y', '150');
const tspan = document.createElementNS(NS.SVG, 'tspan')
tspan.setAttribute('x', '200')
tspan.setAttribute('y', '150')
const theText = 'Foo bar';
tspan.append(theText);
elem.append(tspan);
svg.append(elem);
const theText = 'Foo bar'
tspan.append(theText)
elem.append(tspan)
svg.append(elem)
}
/**
@ -125,53 +124,53 @@ describe('recalculate', function () {
*/
afterEach(() => {
while (svg.hasChildNodes()) {
svg.firstChild.remove();
svg.firstChild.remove()
}
});
})
it('Test recalculateDimensions() on rect with identity matrix', function () {
setUpRect();
elem.setAttribute('transform', 'matrix(1,0,0,1,0,0)');
setUpRect()
elem.setAttribute('transform', 'matrix(1,0,0,1,0,0)')
recalculate.recalculateDimensions(elem);
recalculate.recalculateDimensions(elem)
// Ensure that the identity matrix is swallowed and the element has no
// transform on it.
assert.equal(elem.hasAttribute('transform'), false);
});
assert.equal(elem.hasAttribute('transform'), false)
})
it('Test recalculateDimensions() on rect with simple translate', function () {
setUpRect();
elem.setAttribute('transform', 'translate(100,50)');
setUpRect()
elem.setAttribute('transform', 'translate(100,50)')
recalculate.recalculateDimensions(elem);
recalculate.recalculateDimensions(elem)
assert.equal(elem.hasAttribute('transform'), false);
assert.equal(elem.getAttribute('x'), '300');
assert.equal(elem.getAttribute('y'), '200');
assert.equal(elem.getAttribute('width'), '250');
assert.equal(elem.getAttribute('height'), '120');
});
assert.equal(elem.hasAttribute('transform'), false)
assert.equal(elem.getAttribute('x'), '300')
assert.equal(elem.getAttribute('y'), '200')
assert.equal(elem.getAttribute('width'), '250')
assert.equal(elem.getAttribute('height'), '120')
})
it('Test recalculateDimensions() on text w/tspan with simple translate', function () {
setUpTextWithTspan();
elem.setAttribute('transform', 'translate(100,50)');
setUpTextWithTspan()
elem.setAttribute('transform', 'translate(100,50)')
recalculate.recalculateDimensions(elem);
recalculate.recalculateDimensions(elem)
// Ensure that the identity matrix is swallowed and the element has no
// transform on it.
assert.equal(elem.hasAttribute('transform'), false);
assert.equal(elem.getAttribute('x'), '300');
assert.equal(elem.getAttribute('y'), '200');
assert.equal(elem.hasAttribute('transform'), false)
assert.equal(elem.getAttribute('x'), '300')
assert.equal(elem.getAttribute('y'), '200')
const tspan = elem.firstElementChild;
assert.equal(tspan.getAttribute('x'), '300');
assert.equal(tspan.getAttribute('y'), '200');
});
const tspan = elem.firstElementChild
assert.equal(tspan.getAttribute('x'), '300')
assert.equal(tspan.getAttribute('y'), '200')
})
// TODO: Since recalculateDimensions() and surrounding code is
// probably the largest, most complicated and strange piece of
// code in SVG-edit, we need to write a whole lot of unit tests
// for it here.
});
})

View File

@ -1,17 +1,17 @@
import { NS } from '../../../instrumented/svgcanvas/namespaces.js';
import * as sanitize from '../../../instrumented/svgcanvas/sanitize.js';
import { NS } from '../../../instrumented/svgcanvas/namespaces.js'
import * as sanitize from '../../../instrumented/svgcanvas/sanitize.js'
describe('sanitize', function () {
const svg = document.createElementNS(NS.SVG, 'svg');
const svg = document.createElementNS(NS.SVG, 'svg')
it('Test sanitizeSvg() strips ws from style attr', function () {
const rect = document.createElementNS(NS.SVG, 'rect');
rect.setAttribute('style', 'stroke: blue ;\t\tstroke-width :\t\t40;');
const rect = document.createElementNS(NS.SVG, 'rect')
rect.setAttribute('style', 'stroke: blue ;\t\tstroke-width :\t\t40;')
// sanitizeSvg() requires the node to have a parent and a document.
svg.append(rect);
sanitize.sanitizeSvg(rect);
svg.append(rect)
sanitize.sanitizeSvg(rect)
assert.equal(rect.getAttribute('stroke'), 'blue');
assert.equal(rect.getAttribute('stroke-width'), '40');
});
});
assert.equal(rect.getAttribute('stroke'), 'blue')
assert.equal(rect.getAttribute('stroke-width'), '40')
})
})

View File

@ -1,37 +1,37 @@
import * as select from '../../../instrumented/svgcanvas/select.js';
import { NS } from '../../../instrumented/svgcanvas/namespaces.js';
import * as select from '../../../instrumented/svgcanvas/select.js'
import { NS } from '../../../instrumented/svgcanvas/namespaces.js'
describe('select', function () {
const sandbox = document.createElement('div');
sandbox.id = 'sandbox';
const sandbox = document.createElement('div')
sandbox.id = 'sandbox'
let svgroot;
let svgContent;
let svgroot
let svgContent
const mockConfig = {
dimensions: [ 640, 480 ]
};
dimensions: [640, 480]
}
const dataStorage = {
_storage: new WeakMap(),
put: function (element, key, obj) {
if (!this._storage.has(element)) {
this._storage.set(element, new Map());
this._storage.set(element, new Map())
}
this._storage.get(element).set(key, obj);
this._storage.get(element).set(key, obj)
},
get: function (element, key) {
return this._storage.get(element).get(key);
return this._storage.get(element).get(key)
},
has: function (element, key) {
return this._storage.has(element) && this._storage.get(element).has(key);
return this._storage.has(element) && this._storage.get(element).has(key)
},
remove: function (element, key) {
const ret = this._storage.get(element).delete(key);
const ret = this._storage.get(element).delete(key)
if (!this._storage.get(element).size === 0) {
this._storage.delete(element);
this._storage.delete(element)
}
return ret;
return ret
}
};
}
/**
* @implements {module:select.SVGFactory}
@ -39,16 +39,16 @@ describe('select', function () {
const mockSvgCanvas = {
curConfig: mockConfig,
createSVGElement (jsonMap) {
const elem = document.createElementNS(NS.SVG, jsonMap.element);
Object.entries(jsonMap.attr).forEach(([ attr, value ]) => {
elem.setAttribute(attr, value);
});
return elem;
const elem = document.createElementNS(NS.SVG, jsonMap.element)
Object.entries(jsonMap.attr).forEach(([attr, value]) => {
elem.setAttribute(attr, value)
})
return elem
},
getSvgRoot () { return svgroot; },
getSvgContent () { return svgContent; },
getDataStorage () { return dataStorage; }
};
getSvgRoot () { return svgroot },
getSvgContent () { return svgContent },
getDataStorage () { return dataStorage }
}
/**
* Potentially reusable test set-up.
@ -58,13 +58,13 @@ describe('select', function () {
svgroot = mockSvgCanvas.createSVGElement({
element: 'svg',
attr: { id: 'svgroot' }
});
})
svgContent = mockSvgCanvas.createSVGElement({
element: 'svg',
attr: { id: 'svgcontent' }
});
})
svgroot.append(svgContent);
svgroot.append(svgContent)
/* const rect = */ svgContent.append(
mockSvgCanvas.createSVGElement({
element: 'rect',
@ -76,9 +76,9 @@ describe('select', function () {
height: '100'
}
})
);
sandbox.append(svgroot);
});
)
sandbox.append(svgroot)
})
/*
function setUpWithInit () {
@ -92,61 +92,61 @@ describe('select', function () {
*/
afterEach(() => {
while (sandbox.hasChildNodes()) {
sandbox.firstChild.remove();
sandbox.firstChild.remove()
}
});
})
it('Test svgedit.select package', function () {
assert.ok(select);
assert.ok(select.Selector);
assert.ok(select.SelectorManager);
assert.ok(select.init);
assert.ok(select.getSelectorManager);
assert.equal(typeof select, typeof {});
assert.equal(typeof select.Selector, typeof function () { /* empty fn */ });
assert.equal(typeof select.SelectorManager, typeof function () { /* empty fn */ });
assert.equal(typeof select.init, typeof function () { /* empty fn */ });
assert.equal(typeof select.getSelectorManager, typeof function () { /* empty fn */ });
});
assert.ok(select)
assert.ok(select.Selector)
assert.ok(select.SelectorManager)
assert.ok(select.init)
assert.ok(select.getSelectorManager)
assert.equal(typeof select, typeof {})
assert.equal(typeof select.Selector, typeof function () { /* empty fn */ })
assert.equal(typeof select.SelectorManager, typeof function () { /* empty fn */ })
assert.equal(typeof select.init, typeof function () { /* empty fn */ })
assert.equal(typeof select.getSelectorManager, typeof function () { /* empty fn */ })
})
it('Test Selector DOM structure', function () {
assert.ok(svgroot);
assert.ok(svgroot.hasChildNodes());
assert.ok(svgroot)
assert.ok(svgroot.hasChildNodes())
// Verify non-existence of Selector DOM nodes
assert.equal(svgroot.childNodes.length, 1);
assert.equal(svgroot.childNodes.item(0), svgContent);
assert.ok(!svgroot.querySelector('#selectorParentGroup'));
assert.equal(svgroot.childNodes.length, 1)
assert.equal(svgroot.childNodes.item(0), svgContent)
assert.ok(!svgroot.querySelector('#selectorParentGroup'))
select.init(mockSvgCanvas);
select.init(mockSvgCanvas)
assert.equal(svgroot.childNodes.length, 3);
assert.equal(svgroot.childNodes.length, 3)
// Verify existence of canvas background.
const cb = svgroot.childNodes.item(0);
assert.ok(cb);
assert.equal(cb.id, 'canvasBackground');
const cb = svgroot.childNodes.item(0)
assert.ok(cb)
assert.equal(cb.id, 'canvasBackground')
assert.ok(svgroot.childNodes.item(1));
assert.equal(svgroot.childNodes.item(1), svgContent);
assert.ok(svgroot.childNodes.item(1))
assert.equal(svgroot.childNodes.item(1), svgContent)
// Verify existence of selectorParentGroup.
const spg = svgroot.childNodes.item(2);
assert.ok(spg);
assert.equal(svgroot.querySelector('#selectorParentGroup'), spg);
assert.equal(spg.id, 'selectorParentGroup');
assert.equal(spg.tagName, 'g');
const spg = svgroot.childNodes.item(2)
assert.ok(spg)
assert.equal(svgroot.querySelector('#selectorParentGroup'), spg)
assert.equal(spg.id, 'selectorParentGroup')
assert.equal(spg.tagName, 'g')
// Verify existence of all grip elements.
assert.ok(spg.querySelector('#selectorGrip_resize_nw'));
assert.ok(spg.querySelector('#selectorGrip_resize_n'));
assert.ok(spg.querySelector('#selectorGrip_resize_ne'));
assert.ok(spg.querySelector('#selectorGrip_resize_e'));
assert.ok(spg.querySelector('#selectorGrip_resize_se'));
assert.ok(spg.querySelector('#selectorGrip_resize_s'));
assert.ok(spg.querySelector('#selectorGrip_resize_sw'));
assert.ok(spg.querySelector('#selectorGrip_resize_w'));
assert.ok(spg.querySelector('#selectorGrip_rotateconnector'));
assert.ok(spg.querySelector('#selectorGrip_rotate'));
});
});
assert.ok(spg.querySelector('#selectorGrip_resize_nw'))
assert.ok(spg.querySelector('#selectorGrip_resize_n'))
assert.ok(spg.querySelector('#selectorGrip_resize_ne'))
assert.ok(spg.querySelector('#selectorGrip_resize_e'))
assert.ok(spg.querySelector('#selectorGrip_resize_se'))
assert.ok(spg.querySelector('#selectorGrip_resize_s'))
assert.ok(spg.querySelector('#selectorGrip_resize_sw'))
assert.ok(spg.querySelector('#selectorGrip_resize_w'))
assert.ok(spg.querySelector('#selectorGrip_rotateconnector'))
assert.ok(spg.querySelector('#selectorGrip_rotate'))
})
})

View File

@ -1,5 +1,5 @@
/* eslint-disable max-len, no-console */
import SvgCanvas from '../../../instrumented/svgcanvas/svgcanvas.js';
import SvgCanvas from '../../../instrumented/svgcanvas/svgcanvas.js'
describe('Basic Module', function () {
// helper functions
@ -12,34 +12,34 @@ describe('Basic Module', function () {
};
*/
let svgCanvas;
let svgCanvas
const
// svgroot = document.getElementById('svgroot'),
// svgdoc = svgroot.documentElement,
svgns = 'http://www.w3.org/2000/svg';
const xlinkns = 'http://www.w3.org/1999/xlink';
svgns = 'http://www.w3.org/2000/svg'
const xlinkns = 'http://www.w3.org/1999/xlink'
beforeEach(() => {
document.body.textContent = '';
const svgEditor = document.createElement('div');
svgEditor.id = 'svg_editor';
const svgcanvas = document.createElement('div');
svgcanvas.style.visibility = 'hidden';
svgcanvas.id = 'svgcanvas';
const workarea = document.createElement('div');
workarea.id = 'workarea';
workarea.append(svgcanvas);
const toolsLeft = document.createElement('div');
toolsLeft.id = 'tools_left';
document.body.textContent = ''
const svgEditor = document.createElement('div')
svgEditor.id = 'svg_editor'
const svgcanvas = document.createElement('div')
svgcanvas.style.visibility = 'hidden'
svgcanvas.id = 'svgcanvas'
const workarea = document.createElement('div')
workarea.id = 'workarea'
workarea.append(svgcanvas)
const toolsLeft = document.createElement('div')
toolsLeft.id = 'tools_left'
svgEditor.append(workarea, toolsLeft);
document.body.append(svgEditor);
svgEditor.append(workarea, toolsLeft)
document.body.append(svgEditor)
svgCanvas = new SvgCanvas(
document.getElementById('svgcanvas'), {
canvas_expansion: 3,
dimensions: [ 640, 480 ],
dimensions: [640, 480],
initFill: {
color: 'FF0000', // solid red
opacity: 1
@ -53,20 +53,20 @@ describe('Basic Module', function () {
imgPath: '../editor/images',
langPath: 'locale/',
extPath: 'extensions/',
extensions: [ 'ext-arrows.js', 'ext-eyedropper.js' ],
extensions: ['ext-arrows.js', 'ext-eyedropper.js'],
initTool: 'select',
wireframe: false
}
);
});
)
})
it('Test existence of SvgCanvas object', function () {
assert.equal(typeof {}, typeof svgCanvas);
});
assert.equal(typeof {}, typeof svgCanvas)
})
describe('Path Module', function () {
it('Test path conversion from absolute to relative', function () {
const convert = svgCanvas.pathActions.convertPath;
const convert = svgCanvas.pathActions.convertPath
// TODO: Test these paths:
// "m400.00491,625.01379a1.78688,1.78688 0 1 1-3.57373,0a1.78688,1.78688 0 1 13.57373,0z"
@ -78,36 +78,36 @@ describe('Basic Module', function () {
"<path id='p1' d='M100,100 L200,100 L100,100Z'/>" +
"<path id='p2' d='m 0,0 l 200,0 l 0,100 L 0,100'/>" +
'</svg>'
);
)
const p1 = document.getElementById('p1');
const p2 = document.getElementById('p2');
const dAbs = p1.getAttribute('d');
const seglist = p1.pathSegList;
const p1 = document.getElementById('p1')
const p2 = document.getElementById('p2')
const dAbs = p1.getAttribute('d')
const seglist = p1.pathSegList
assert.equal(p1.nodeName, 'path', "Expected 'path', got");
assert.equal(p1.nodeName, 'path', "Expected 'path', got")
assert.equal(seglist.numberOfItems, 4, 'Number of segments before conversion');
assert.equal(seglist.numberOfItems, 4, 'Number of segments before conversion')
// verify segments before conversion
let curseg = seglist.getItem(0);
assert.equal(curseg.pathSegTypeAsLetter.toUpperCase(), 'M', 'Before conversion, segment #1 type');
curseg = seglist.getItem(1);
assert.equal(curseg.pathSegTypeAsLetter.toUpperCase(), 'L', 'Before conversion, segment #2 type');
curseg = seglist.getItem(3);
assert.equal(curseg.pathSegTypeAsLetter.toUpperCase(), 'Z', 'Before conversion, segment #3 type' + dAbs);
let curseg = seglist.getItem(0)
assert.equal(curseg.pathSegTypeAsLetter.toUpperCase(), 'M', 'Before conversion, segment #1 type')
curseg = seglist.getItem(1)
assert.equal(curseg.pathSegTypeAsLetter.toUpperCase(), 'L', 'Before conversion, segment #2 type')
curseg = seglist.getItem(3)
assert.equal(curseg.pathSegTypeAsLetter.toUpperCase(), 'Z', 'Before conversion, segment #3 type' + dAbs)
// convert and verify segments
let d = convert(p1, true);
assert.equal(d, 'm100,100l100,0l-100,0z', 'Converted path to relative string');
let d = convert(p1, true)
assert.equal(d, 'm100,100l100,0l-100,0z', 'Converted path to relative string')
// TODO: see why this isn't working in SVG-edit
d = convert(p2, true);
console.log('Convert true', d);
d = convert(p2, false);
console.log('Convert false', d);
});
});
d = convert(p2, true)
console.log('Convert true', d)
d = convert(p2, false)
console.log('Convert false', d)
})
})
describe('Import Module', function () {
it('Test import use', function () {
@ -118,16 +118,16 @@ describe('Basic Module', function () {
"<use id='foreign-use' xlink:href='somefile.svg#the-rect'/>" +
"<use id='no-use'/>" +
'</svg>'
);
)
const u = document.getElementById('the-use');
const fu = document.getElementById('foreign-use');
const nfu = document.getElementById('no-use');
const u = document.getElementById('the-use')
const fu = document.getElementById('foreign-use')
const nfu = document.getElementById('no-use')
assert.equal((u && u.nodeName), 'use', 'Did not import <use> element');
assert.equal(fu, null, 'Removed <use> element that had a foreign href');
assert.equal(nfu, null, 'Removed <use> element that had no href');
});
assert.equal((u && u.nodeName), 'use', 'Did not import <use> element')
assert.equal(fu, null, 'Removed <use> element that had a foreign href')
assert.equal(nfu, null, 'Removed <use> element that had no href')
})
// This test shows that an element with an invalid attribute is still parsed in properly
// and only the attribute is not imported
@ -136,13 +136,13 @@ describe('Basic Module', function () {
'<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg">' +
'<text x="182.75" y="173.5" id="the-text" fill="#008000" font-size="150" font-family="serif" text-anchor="middle" d="M116,222 L110,108">words</text>' +
'</svg>'
);
)
const t = document.getElementById('the-text');
const t = document.getElementById('the-text')
assert.equal((t && t.nodeName), 'text', 'Did not import <text> element');
assert.equal(t.getAttribute('d'), null, 'Imported a <text> with a d attribute');
});
assert.equal((t && t.nodeName), 'text', 'Did not import <text> element')
assert.equal(t.getAttribute('d'), null, 'Imported a <text> with a d attribute')
})
// This test makes sure import/export properly handles namespaced attributes
it('Test importing/exporting namespaced attributes', function () {
@ -151,22 +151,22 @@ describe('Basic Module', function () {
'<image xlink:href="../editor/images/logo.png"/>' +
'<polyline id="se_test_elem" se:foo="bar" foo:bar="baz"/>' +
'</svg>'
);
const attrVal = document.getElementById('se_test_elem').getAttributeNS('http://svg-edit.googlecode.com', 'foo');
)
const attrVal = document.getElementById('se_test_elem').getAttributeNS('http://svg-edit.googlecode.com', 'foo')
assert.strictEqual(attrVal, 'bar', true, 'Preserved namespaced attribute on import');
assert.strictEqual(attrVal, 'bar', true, 'Preserved namespaced attribute on import')
const output = svgCanvas.getSvgString();
const hasXlink = output.includes('xmlns:xlink="http://www.w3.org/1999/xlink"');
const hasSe = output.includes('xmlns:se=');
const hasFoo = output.includes('xmlns:foo=');
const hasAttr = output.includes('se:foo="bar"');
const output = svgCanvas.getSvgString()
const hasXlink = output.includes('xmlns:xlink="http://www.w3.org/1999/xlink"')
const hasSe = output.includes('xmlns:se=')
const hasFoo = output.includes('xmlns:foo=')
const hasAttr = output.includes('se:foo="bar"')
assert.equal(hasAttr, true, 'Preserved namespaced attribute on export');
assert.equal(hasXlink, true, 'Included xlink: xmlns');
assert.equal(hasSe, true, 'Included se: xmlns');
assert.equal(hasFoo, false, 'Did not include foo: xmlns');
});
assert.equal(hasAttr, true, 'Preserved namespaced attribute on export')
assert.equal(hasXlink, true, 'Included xlink: xmlns')
assert.equal(hasSe, true, 'Included se: xmlns')
assert.equal(hasFoo, false, 'Did not include foo: xmlns')
})
it('Test import math elements inside a foreignObject', function () {
/* const set = */ svgCanvas.setSvgString(
@ -179,17 +179,17 @@ describe('Basic Module', function () {
'</math>' +
'</foreignObject>' +
'</svg>'
);
const fo = document.getElementById('fo');
)
const fo = document.getElementById('fo')
// we cannot use getElementById('math') because not all browsers understand MathML and do not know to use the @id attribute
// see Bug https://bugs.webkit.org/show_bug.cgi?id=35042
const math = fo.firstChild;
const math = fo.firstChild
assert.equal(Boolean(math), true, 'Math element exists');
assert.equal(math.nodeName, 'math', 'Math element has the proper nodeName');
assert.equal(math.getAttribute('id'), 'm', 'Math element has an id');
assert.equal(math.namespaceURI, 'http://www.w3.org/1998/Math/MathML', 'Preserved MathML namespace');
});
assert.equal(Boolean(math), true, 'Math element exists')
assert.equal(math.nodeName, 'math', 'Math element has the proper nodeName')
assert.equal(math.getAttribute('id'), 'm', 'Math element has an id')
assert.equal(math.namespaceURI, 'http://www.w3.org/1998/Math/MathML', 'Preserved MathML namespace')
})
it('Test importing SVG into existing drawing', function () {
/* const doc = */ svgCanvas.setSvgString(
@ -199,23 +199,23 @@ describe('Basic Module', function () {
'<ellipse cx="300" cy="100" rx="40" ry="30" fill="green"/>' +
'</g>' +
'</svg>'
);
)
svgCanvas.importSvgString(
'<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">' +
'<circle cx="50" cy="50" r="40" fill="yellow"/>' +
'<rect width="20" height="20" fill="blue"/>' +
'</svg>'
);
)
const svgContent = document.getElementById('svgcontent');
const circles = svgContent.getElementsByTagNameNS(svgns, 'circle');
const rects = svgContent.getElementsByTagNameNS(svgns, 'rect');
const ellipses = svgContent.getElementsByTagNameNS(svgns, 'ellipse');
assert.equal(circles.length, 2, 'Found two circles upon importing');
assert.equal(rects.length, 1, 'Found one rectangle upon importing');
assert.equal(ellipses.length, 1, 'Found one ellipse upon importing');
});
const svgContent = document.getElementById('svgcontent')
const circles = svgContent.getElementsByTagNameNS(svgns, 'circle')
const rects = svgContent.getElementsByTagNameNS(svgns, 'rect')
const ellipses = svgContent.getElementsByTagNameNS(svgns, 'ellipse')
assert.equal(circles.length, 2, 'Found two circles upon importing')
assert.equal(rects.length, 1, 'Found one rectangle upon importing')
assert.equal(ellipses.length, 1, 'Found one ellipse upon importing')
})
it('Test importing SVG remaps IDs', function () {
/* const doc = */ svgCanvas.setSvgString(
@ -226,7 +226,7 @@ describe('Basic Module', function () {
'<ellipse id="svg_3" cx="300" cy="100" rx="40" ry="30" fill="green"/>' +
'</g>' +
'</svg>'
);
)
svgCanvas.importSvgString(
'<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink">' +
@ -240,24 +240,24 @@ describe('Basic Module', function () {
'<circle id="svg_1" cx="50" cy="50" r="40" fill="url(#svg_2)"/>' +
'<use id="svg_4" width="30" height="30" xl:href="#svg_3"/>' +
'</svg>'
);
)
const svgContent = document.getElementById('svgcontent');
const circles = svgContent.getElementsByTagNameNS(svgns, 'circle');
const rects = svgContent.getElementsByTagNameNS(svgns, 'rect');
const svgContent = document.getElementById('svgcontent')
const circles = svgContent.getElementsByTagNameNS(svgns, 'circle')
const rects = svgContent.getElementsByTagNameNS(svgns, 'rect')
// ellipses = svgContent.getElementsByTagNameNS(svgns, 'ellipse'),
const defs = svgContent.getElementsByTagNameNS(svgns, 'defs');
const defs = svgContent.getElementsByTagNameNS(svgns, 'defs')
// grads = svgContent.getElementsByTagNameNS(svgns, 'linearGradient'),
const uses = svgContent.getElementsByTagNameNS(svgns, 'use');
assert.notEqual(circles.item(0).id, 'svg_1', 'Circle not re-identified');
assert.notEqual(rects.item(0).id, 'svg_3', 'Rectangle not re-identified');
const uses = svgContent.getElementsByTagNameNS(svgns, 'use')
assert.notEqual(circles.item(0).id, 'svg_1', 'Circle not re-identified')
assert.notEqual(rects.item(0).id, 'svg_3', 'Rectangle not re-identified')
// TODO: determine why this test fails in WebKit browsers
// assert.equal(grads.length, 1, 'Linear gradient imported');
const grad = defs.item(0).firstChild;
assert.notEqual(grad.id, 'svg_2', 'Linear gradient not re-identified');
assert.notEqual(circles.item(0).getAttribute('fill'), 'url(#svg_2)', 'Circle fill value not remapped');
assert.notEqual(rects.item(0).getAttribute('stroke'), 'url(#svg_2)', 'Rectangle stroke value not remapped');
assert.notEqual(uses.item(0).getAttributeNS(xlinkns, 'href'), '#svg_3');
});
});
});
const grad = defs.item(0).firstChild
assert.notEqual(grad.id, 'svg_2', 'Linear gradient not re-identified')
assert.notEqual(circles.item(0).getAttribute('fill'), 'url(#svg_2)', 'Circle fill value not remapped')
assert.notEqual(rects.item(0).getAttribute('stroke'), 'url(#svg_2)', 'Rectangle stroke value not remapped')
assert.notEqual(uses.item(0).getAttributeNS(xlinkns, 'href'), '#svg_3')
})
})
})

View File

@ -1,4 +1,4 @@
import * as units from '../../../instrumented/common/units.js';
import * as units from '../../../instrumented/common/units.js'
describe('units', function () {
/**
@ -6,86 +6,86 @@ describe('units', function () {
* @returns {void}
*/
beforeEach(() => {
document.body.textContent = '';
const anchor = document.createElement('div');
anchor.id = 'anchor';
anchor.style.visibility = 'hidden';
document.body.textContent = ''
const anchor = document.createElement('div')
anchor.id = 'anchor'
anchor.style.visibility = 'hidden'
const elementsContainer = document.createElement('div');
elementsContainer.id = 'elementsContainer';
const elementsContainer = document.createElement('div')
elementsContainer.id = 'elementsContainer'
const uniqueId = document.createElement('div');
uniqueId.id = 'uniqueId';
uniqueId.style.visibility = 'hidden';
const uniqueId = document.createElement('div')
uniqueId.id = 'uniqueId'
uniqueId.style.visibility = 'hidden'
const nonUniqueId = document.createElement('div');
nonUniqueId.id = 'nonUniqueId';
nonUniqueId.style.visibility = 'hidden';
const nonUniqueId = document.createElement('div')
nonUniqueId.id = 'nonUniqueId'
nonUniqueId.style.visibility = 'hidden'
elementsContainer.append(uniqueId, nonUniqueId);
elementsContainer.append(uniqueId, nonUniqueId)
document.body.append(anchor, elementsContainer);
document.body.append(anchor, elementsContainer)
units.init(
/**
* @implements {module:units.ElementContainer}
*/
{
getBaseUnit () { return 'cm'; },
getHeight () { return 600; },
getWidth () { return 800; },
getRoundDigits () { return 4; },
getElement (elementId) { return document.getElementById(elementId); }
getBaseUnit () { return 'cm' },
getHeight () { return 600 },
getWidth () { return 800 },
getRoundDigits () { return 4 },
getElement (elementId) { return document.getElementById(elementId) }
}
);
});
)
})
it('Test svgedit.units package', function () {
assert.ok(units);
assert.equal(typeof units, typeof {});
});
assert.ok(units)
assert.equal(typeof units, typeof {})
})
it('Test svgedit.units.shortFloat()', function () {
assert.ok(units.shortFloat);
assert.equal(typeof units.shortFloat, typeof function () { /* empty fn */ });
assert.ok(units.shortFloat)
assert.equal(typeof units.shortFloat, typeof function () { /* empty fn */ })
const { shortFloat } = units;
assert.equal(shortFloat(0.00000001), 0);
assert.equal(shortFloat(1), 1);
assert.equal(shortFloat(3.45678), 3.4568);
assert.equal(shortFloat(1.23443), 1.2344);
assert.equal(shortFloat(1.23455), 1.2346);
});
const { shortFloat } = units
assert.equal(shortFloat(0.00000001), 0)
assert.equal(shortFloat(1), 1)
assert.equal(shortFloat(3.45678), 3.4568)
assert.equal(shortFloat(1.23443), 1.2344)
assert.equal(shortFloat(1.23455), 1.2346)
})
it('Test svgedit.units.isValidUnit()', function () {
assert.ok(units.isValidUnit);
assert.equal(typeof units.isValidUnit, typeof function () { /* empty fn */ });
assert.ok(units.isValidUnit)
assert.equal(typeof units.isValidUnit, typeof function () { /* empty fn */ })
const { isValidUnit } = units;
assert.ok(isValidUnit('0'));
assert.ok(isValidUnit('1'));
assert.ok(isValidUnit('1.1'));
assert.ok(isValidUnit('-1.1'));
assert.ok(isValidUnit('.6mm'));
assert.ok(isValidUnit('-.6cm'));
assert.ok(isValidUnit('6000in'));
assert.ok(isValidUnit('6px'));
assert.ok(isValidUnit('6.3pc'));
assert.ok(isValidUnit('-0.4em'));
assert.ok(isValidUnit('-0.ex'));
assert.ok(isValidUnit('40.123%'));
const { isValidUnit } = units
assert.ok(isValidUnit('0'))
assert.ok(isValidUnit('1'))
assert.ok(isValidUnit('1.1'))
assert.ok(isValidUnit('-1.1'))
assert.ok(isValidUnit('.6mm'))
assert.ok(isValidUnit('-.6cm'))
assert.ok(isValidUnit('6000in'))
assert.ok(isValidUnit('6px'))
assert.ok(isValidUnit('6.3pc'))
assert.ok(isValidUnit('-0.4em'))
assert.ok(isValidUnit('-0.ex'))
assert.ok(isValidUnit('40.123%'))
assert.equal(isValidUnit('id', 'uniqueId', document.getElementById('uniqueId')), true);
assert.equal(isValidUnit('id', 'newId', document.getElementById('uniqueId')), true);
assert.equal(isValidUnit('id', 'uniqueId'), false);
assert.equal(isValidUnit('id', 'uniqueId', document.getElementById('nonUniqueId')), false);
});
assert.equal(isValidUnit('id', 'uniqueId', document.getElementById('uniqueId')), true)
assert.equal(isValidUnit('id', 'newId', document.getElementById('uniqueId')), true)
assert.equal(isValidUnit('id', 'uniqueId'), false)
assert.equal(isValidUnit('id', 'uniqueId', document.getElementById('nonUniqueId')), false)
})
it('Test svgedit.units.convertUnit()', function () {
assert.ok(units.convertUnit);
assert.equal(typeof units.convertUnit, typeof function () { /* empty fn */ });
assert.ok(units.convertUnit)
assert.equal(typeof units.convertUnit, typeof function () { /* empty fn */ })
// cm in default setup
assert.equal(units.convertUnit(42), 1.1113);
assert.equal(units.convertUnit(42, 'px'), 42);
});
});
assert.equal(units.convertUnit(42), 1.1113)
assert.equal(units.convertUnit(42, 'px'), 42)
})
})

View File

@ -1,12 +1,13 @@
import 'pathseg';
import 'pathseg'
import { NS } from '../../../instrumented/svgcanvas/namespaces.js';
import * as utilities from '../../../instrumented/svgcanvas/utilities.js';
import * as math from '../../../instrumented/svgcanvas/math.js';
import * as path from '../../../instrumented/svgcanvas/path.js';
import setAssertionMethods from '../../support/assert-close.js';
import { NS } from '../../../instrumented/svgcanvas/namespaces.js'
import * as utilities from '../../../instrumented/svgcanvas/utilities.js'
import * as math from '../../../instrumented/svgcanvas/math.js'
import * as path from '../../../instrumented/svgcanvas/path.js'
import setAssertionMethods from '../../support/assert-close.js'
chai.use(setAssertionMethods);
// eslint-disable-next-line
chai.use(setAssertionMethods)
describe('utilities bbox', function () {
/**
@ -15,13 +16,13 @@ describe('utilities bbox', function () {
* @returns {SVGElement}
*/
function mockCreateSVGElement (jsonMap) {
const elem = document.createElementNS(NS.SVG, jsonMap.element);
Object.entries(jsonMap.attr).forEach(([ attr, value ]) => {
elem.setAttribute(attr, value);
});
return elem;
const elem = document.createElementNS(NS.SVG, jsonMap.element)
Object.entries(jsonMap.attr).forEach(([attr, value]) => {
elem.setAttribute(attr, value)
})
return elem
}
let mockaddSVGElemensFromJsonCallCount = 0;
let mockaddSVGElemensFromJsonCallCount = 0
/**
* Mock of {@link module:utilities.EditorContext#addSVGElemensFromJson}.
@ -29,435 +30,435 @@ describe('utilities bbox', function () {
* @returns {SVGElement}
*/
function mockaddSVGElemensFromJson (json) {
const elem = mockCreateSVGElement(json);
svgroot.append(elem);
mockaddSVGElemensFromJsonCallCount++;
return elem;
const elem = mockCreateSVGElement(json)
svgroot.append(elem)
mockaddSVGElemensFromJsonCallCount++
return elem
}
const mockPathActions = {
resetOrientation (pth) {
if (utilities.isNullish(pth) || pth.nodeName !== 'path') { return false; }
const tlist = pth.transform.baseVal;
const m = math.transformListToTransform(tlist).matrix;
tlist.clear();
pth.removeAttribute('transform');
const segList = pth.pathSegList;
if (utilities.isNullish(pth) || pth.nodeName !== 'path') { return false }
const tlist = pth.transform.baseVal
const m = math.transformListToTransform(tlist).matrix
tlist.clear()
pth.removeAttribute('transform')
const segList = pth.pathSegList
const len = segList.numberOfItems;
const len = segList.numberOfItems
// let lastX, lastY;
for (let i = 0; i < len; ++i) {
const seg = segList.getItem(i);
const type = seg.pathSegType;
if (type === 1) { continue; }
const seg = segList.getItem(i)
const type = seg.pathSegType
if (type === 1) { continue }
const pts = [];
[ '', 1, 2 ].forEach(function (n) {
const x = seg['x' + n]; const y = seg['y' + n];
['', 1, 2].forEach(function (n) {
const x = seg['x' + n]; const y = seg['y' + n]
if (x !== undefined && y !== undefined) {
const pt = math.transformPoint(x, y, m);
pts.splice(pts.length, 0, pt.x, pt.y);
const pt = math.transformPoint(x, y, m)
pts.splice(pts.length, 0, pt.x, pt.y)
}
});
path.replacePathSeg(type, i, pts, pth);
})
path.replacePathSeg(type, i, pts, pth)
}
return undefined;
return undefined
}
};
}
const EPSILON = 0.001;
const EPSILON = 0.001
let svgroot;
let svgroot
beforeEach(() => {
document.body.textContent = '';
document.body.textContent = ''
// const svg = document.createElementNS(NS.SVG, 'svg');
const sandbox = document.createElement('div');
sandbox.id = 'sandbox';
document.body.append(sandbox);
const sandbox = document.createElement('div')
sandbox.id = 'sandbox'
document.body.append(sandbox)
svgroot = mockCreateSVGElement({
element: 'svg',
attr: { id: 'svgroot' }
});
sandbox.append(svgroot);
})
sandbox.append(svgroot)
const mockSvgCanvas = {
createSVGElement (jsonMap) {
const elem = document.createElementNS(NS.SVG, jsonMap.element);
Object.entries(jsonMap.attr).forEach(([ attr, value ]) => {
elem.setAttribute(attr, value);
});
return elem;
const elem = document.createElementNS(NS.SVG, jsonMap.element)
Object.entries(jsonMap.attr).forEach(([attr, value]) => {
elem.setAttribute(attr, value)
})
return elem
},
getSvgRoot () { return svgroot; }
};
getSvgRoot () { return svgroot }
}
path.init(mockSvgCanvas);
mockaddSVGElemensFromJsonCallCount = 0;
});
path.init(mockSvgCanvas)
mockaddSVGElemensFromJsonCallCount = 0
})
it('Test svgedit.utilities package', function () {
assert.ok(utilities);
assert.ok(utilities.getBBoxWithTransform);
assert.ok(utilities.getStrokedBBox);
assert.ok(utilities.getRotationAngleFromTransformList);
assert.ok(utilities.getRotationAngle);
});
assert.ok(utilities)
assert.ok(utilities.getBBoxWithTransform)
assert.ok(utilities.getStrokedBBox)
assert.ok(utilities.getRotationAngleFromTransformList)
assert.ok(utilities.getRotationAngle)
})
it('Test getBBoxWithTransform and no transform', function () {
const { getBBoxWithTransform } = utilities;
const { getBBoxWithTransform } = utilities
let elem = mockCreateSVGElement({
element: 'path',
attr: { id: 'path', d: 'M0,1 L2,3' }
});
svgroot.append(elem);
let bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions);
assert.deepEqual(bbox, { x: 0, y: 1, width: 2, height: 2 });
assert.equal(mockaddSVGElemensFromJsonCallCount, 0);
elem.remove();
})
svgroot.append(elem)
let bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions)
assert.deepEqual(bbox, { x: 0, y: 1, width: 2, height: 2 })
assert.equal(mockaddSVGElemensFromJsonCallCount, 0)
elem.remove()
elem = mockCreateSVGElement({
element: 'rect',
attr: { id: 'rect', x: '0', y: '1', width: '5', height: '10' }
});
svgroot.append(elem);
bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions);
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 });
assert.equal(mockaddSVGElemensFromJsonCallCount, 0);
elem.remove();
})
svgroot.append(elem)
bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions)
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 })
assert.equal(mockaddSVGElemensFromJsonCallCount, 0)
elem.remove()
elem = mockCreateSVGElement({
element: 'line',
attr: { id: 'line', x1: '0', y1: '1', x2: '5', y2: '6' }
});
svgroot.append(elem);
bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions);
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 5 });
assert.equal(mockaddSVGElemensFromJsonCallCount, 0);
elem.remove();
})
svgroot.append(elem)
bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions)
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 5 })
assert.equal(mockaddSVGElemensFromJsonCallCount, 0)
elem.remove()
elem = mockCreateSVGElement({
element: 'rect',
attr: { id: 'rect', x: '0', y: '1', width: '5', height: '10' }
});
})
const g = mockCreateSVGElement({
element: 'g',
attr: {}
});
g.append(elem);
svgroot.append(g);
bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions);
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 });
assert.equal(mockaddSVGElemensFromJsonCallCount, 0);
g.remove();
});
})
g.append(elem)
svgroot.append(g)
bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions)
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 })
assert.equal(mockaddSVGElemensFromJsonCallCount, 0)
g.remove()
})
it('Test getBBoxWithTransform and a rotation transform', function () {
const { getBBoxWithTransform } = utilities;
const { getBBoxWithTransform } = utilities
let elem = mockCreateSVGElement({
element: 'path',
attr: { id: 'path', d: 'M10,10 L20,20', transform: 'rotate(45 10,10)' }
});
svgroot.append(elem);
let bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions);
assert.close(bbox.x, 10, EPSILON);
assert.close(bbox.y, 10, EPSILON);
assert.close(bbox.width, 0, EPSILON);
assert.close(bbox.height, Math.sqrt(100 + 100), EPSILON);
elem.remove();
})
svgroot.append(elem)
let bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions)
assert.close(bbox.x, 10, EPSILON)
assert.close(bbox.y, 10, EPSILON)
assert.close(bbox.width, 0, EPSILON)
assert.close(bbox.height, Math.sqrt(100 + 100), EPSILON)
elem.remove()
elem = mockCreateSVGElement({
element: 'rect',
attr: { id: 'rect', x: '10', y: '10', width: '10', height: '20', transform: 'rotate(90 15,20)' }
});
svgroot.append(elem);
bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions);
assert.close(bbox.x, 5, EPSILON);
assert.close(bbox.y, 15, EPSILON);
assert.close(bbox.width, 20, EPSILON);
assert.close(bbox.height, 10, EPSILON);
assert.equal(mockaddSVGElemensFromJsonCallCount, 1);
elem.remove();
})
svgroot.append(elem)
bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions)
assert.close(bbox.x, 5, EPSILON)
assert.close(bbox.y, 15, EPSILON)
assert.close(bbox.width, 20, EPSILON)
assert.close(bbox.height, 10, EPSILON)
assert.equal(mockaddSVGElemensFromJsonCallCount, 1)
elem.remove()
const rect = { x: 10, y: 10, width: 10, height: 20 };
const angle = 45;
const origin = { x: 15, y: 20 };
const rect = { x: 10, y: 10, width: 10, height: 20 }
const angle = 45
const origin = { x: 15, y: 20 }
elem = mockCreateSVGElement({
element: 'rect',
attr: { id: 'rect2', x: rect.x, y: rect.y, width: rect.width, height: rect.height, transform: 'rotate(' + angle + ' ' + origin.x + ',' + origin.y + ')' }
});
svgroot.append(elem);
mockaddSVGElemensFromJsonCallCount = 0;
bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions);
const r2 = rotateRect(rect, angle, origin);
assert.close(bbox.x, r2.x, EPSILON, 'rect2 x is ' + r2.x);
assert.close(bbox.y, r2.y, EPSILON, 'rect2 y is ' + r2.y);
assert.close(bbox.width, r2.width, EPSILON, 'rect2 width is' + r2.width);
assert.close(bbox.height, r2.height, EPSILON, 'rect2 height is ' + r2.height);
assert.equal(mockaddSVGElemensFromJsonCallCount, 0);
elem.remove();
})
svgroot.append(elem)
mockaddSVGElemensFromJsonCallCount = 0
bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions)
const r2 = rotateRect(rect, angle, origin)
assert.close(bbox.x, r2.x, EPSILON, 'rect2 x is ' + r2.x)
assert.close(bbox.y, r2.y, EPSILON, 'rect2 y is ' + r2.y)
assert.close(bbox.width, r2.width, EPSILON, 'rect2 width is' + r2.width)
assert.close(bbox.height, r2.height, EPSILON, 'rect2 height is ' + r2.height)
assert.equal(mockaddSVGElemensFromJsonCallCount, 0)
elem.remove()
// Same as previous but wrapped with g and the transform is with the g.
elem = mockCreateSVGElement({
element: 'rect',
attr: { id: 'rect3', x: rect.x, y: rect.y, width: rect.width, height: rect.height }
});
})
const g = mockCreateSVGElement({
element: 'g',
attr: { transform: 'rotate(' + angle + ' ' + origin.x + ',' + origin.y + ')' }
});
g.append(elem);
svgroot.append(g);
mockaddSVGElemensFromJsonCallCount = 0;
bbox = getBBoxWithTransform(g, mockaddSVGElemensFromJson, mockPathActions);
assert.close(bbox.x, r2.x, EPSILON, 'rect2 x is ' + r2.x);
assert.close(bbox.y, r2.y, EPSILON, 'rect2 y is ' + r2.y);
assert.close(bbox.width, r2.width, EPSILON, 'rect2 width is' + r2.width);
assert.close(bbox.height, r2.height, EPSILON, 'rect2 height is ' + r2.height);
assert.equal(mockaddSVGElemensFromJsonCallCount, 0);
g.remove();
})
g.append(elem)
svgroot.append(g)
mockaddSVGElemensFromJsonCallCount = 0
bbox = getBBoxWithTransform(g, mockaddSVGElemensFromJson, mockPathActions)
assert.close(bbox.x, r2.x, EPSILON, 'rect2 x is ' + r2.x)
assert.close(bbox.y, r2.y, EPSILON, 'rect2 y is ' + r2.y)
assert.close(bbox.width, r2.width, EPSILON, 'rect2 width is' + r2.width)
assert.close(bbox.height, r2.height, EPSILON, 'rect2 height is ' + r2.height)
assert.equal(mockaddSVGElemensFromJsonCallCount, 0)
g.remove()
elem = mockCreateSVGElement({
element: 'ellipse',
attr: { id: 'ellipse1', cx: '100', cy: '100', rx: '50', ry: '50', transform: 'rotate(45 100,100)' }
});
svgroot.append(elem);
mockaddSVGElemensFromJsonCallCount = 0;
bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions);
})
svgroot.append(elem)
mockaddSVGElemensFromJsonCallCount = 0
bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions)
/** @todo: Review these test the BBox algorithm is using the bezier control points to calculate the bounding box. Should be 50, 50, 100, 100. */
// assert.ok(bbox.x > 45 && bbox.x <= 50);
assert.ok(bbox.y > 45 && bbox.y <= 50);
assert.ok(bbox.y > 45 && bbox.y <= 50)
// assert.ok(bbox.width >= 100 && bbox.width < 110);
// assert.ok(bbox.height >= 100 && bbox.height < 110);
assert.equal(mockaddSVGElemensFromJsonCallCount, 1);
elem.remove();
});
assert.equal(mockaddSVGElemensFromJsonCallCount, 1)
elem.remove()
})
it('Test getBBoxWithTransform with rotation and matrix transforms', function () {
const { getBBoxWithTransform } = utilities;
const { getBBoxWithTransform } = utilities
let tx = 10; // tx right
let ty = 10; // tx down
let txInRotatedSpace = Math.sqrt(tx * tx + ty * ty); // translate in rotated 45 space.
let tyInRotatedSpace = 0;
let matrix = 'matrix(1,0,0,1,' + txInRotatedSpace + ',' + tyInRotatedSpace + ')';
let tx = 10 // tx right
let ty = 10 // tx down
let txInRotatedSpace = Math.sqrt(tx * tx + ty * ty) // translate in rotated 45 space.
let tyInRotatedSpace = 0
let matrix = 'matrix(1,0,0,1,' + txInRotatedSpace + ',' + tyInRotatedSpace + ')'
let elem = mockCreateSVGElement({
element: 'path',
attr: { id: 'path', d: 'M10,10 L20,20', transform: 'rotate(45 10,10) ' + matrix }
});
svgroot.append(elem);
let bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions);
assert.close(bbox.x, 10 + tx, EPSILON);
assert.close(bbox.y, 10 + ty, EPSILON);
assert.close(bbox.width, 0, EPSILON);
assert.close(bbox.height, Math.sqrt(100 + 100), EPSILON);
elem.remove();
})
svgroot.append(elem)
let bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions)
assert.close(bbox.x, 10 + tx, EPSILON)
assert.close(bbox.y, 10 + ty, EPSILON)
assert.close(bbox.width, 0, EPSILON)
assert.close(bbox.height, Math.sqrt(100 + 100), EPSILON)
elem.remove()
txInRotatedSpace = tx; // translate in rotated 90 space.
tyInRotatedSpace = -ty;
matrix = 'matrix(1,0,0,1,' + txInRotatedSpace + ',' + tyInRotatedSpace + ')';
txInRotatedSpace = tx // translate in rotated 90 space.
tyInRotatedSpace = -ty
matrix = 'matrix(1,0,0,1,' + txInRotatedSpace + ',' + tyInRotatedSpace + ')'
elem = mockCreateSVGElement({
element: 'rect',
attr: { id: 'rect', x: '10', y: '10', width: '10', height: '20', transform: 'rotate(90 15,20) ' + matrix }
});
svgroot.append(elem);
bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions);
assert.close(bbox.x, 5 + tx, EPSILON);
assert.close(bbox.y, 15 + ty, EPSILON);
assert.close(bbox.width, 20, EPSILON);
assert.close(bbox.height, 10, EPSILON);
elem.remove();
})
svgroot.append(elem)
bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions)
assert.close(bbox.x, 5 + tx, EPSILON)
assert.close(bbox.y, 15 + ty, EPSILON)
assert.close(bbox.width, 20, EPSILON)
assert.close(bbox.height, 10, EPSILON)
elem.remove()
const rect = { x: 10, y: 10, width: 10, height: 20 };
const angle = 45;
const origin = { x: 15, y: 20 };
tx = 10; // tx right
ty = 10; // tx down
txInRotatedSpace = Math.sqrt(tx * tx + ty * ty); // translate in rotated 45 space.
tyInRotatedSpace = 0;
matrix = 'matrix(1,0,0,1,' + txInRotatedSpace + ',' + tyInRotatedSpace + ')';
const rect = { x: 10, y: 10, width: 10, height: 20 }
const angle = 45
const origin = { x: 15, y: 20 }
tx = 10 // tx right
ty = 10 // tx down
txInRotatedSpace = Math.sqrt(tx * tx + ty * ty) // translate in rotated 45 space.
tyInRotatedSpace = 0
matrix = 'matrix(1,0,0,1,' + txInRotatedSpace + ',' + tyInRotatedSpace + ')'
elem = mockCreateSVGElement({
element: 'rect',
attr: { id: 'rect2', x: rect.x, y: rect.y, width: rect.width, height: rect.height, transform: 'rotate(' + angle + ' ' + origin.x + ',' + origin.y + ') ' + matrix }
});
svgroot.append(elem);
bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions);
const r2 = rotateRect(rect, angle, origin);
assert.close(bbox.x, r2.x + tx, EPSILON, 'rect2 x is ' + r2.x);
assert.close(bbox.y, r2.y + ty, EPSILON, 'rect2 y is ' + r2.y);
assert.close(bbox.width, r2.width, EPSILON, 'rect2 width is' + r2.width);
assert.close(bbox.height, r2.height, EPSILON, 'rect2 height is ' + r2.height);
elem.remove();
})
svgroot.append(elem)
bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions)
const r2 = rotateRect(rect, angle, origin)
assert.close(bbox.x, r2.x + tx, EPSILON, 'rect2 x is ' + r2.x)
assert.close(bbox.y, r2.y + ty, EPSILON, 'rect2 y is ' + r2.y)
assert.close(bbox.width, r2.width, EPSILON, 'rect2 width is' + r2.width)
assert.close(bbox.height, r2.height, EPSILON, 'rect2 height is ' + r2.height)
elem.remove()
// Same as previous but wrapped with g and the transform is with the g.
elem = mockCreateSVGElement({
element: 'rect',
attr: { id: 'rect3', x: rect.x, y: rect.y, width: rect.width, height: rect.height }
});
})
const g = mockCreateSVGElement({
element: 'g',
attr: { transform: 'rotate(' + angle + ' ' + origin.x + ',' + origin.y + ') ' + matrix }
});
g.append(elem);
svgroot.append(g);
bbox = getBBoxWithTransform(g, mockaddSVGElemensFromJson, mockPathActions);
assert.close(bbox.x, r2.x + tx, EPSILON, 'rect2 x is ' + r2.x);
assert.close(bbox.y, r2.y + ty, EPSILON, 'rect2 y is ' + r2.y);
assert.close(bbox.width, r2.width, EPSILON, 'rect2 width is' + r2.width);
assert.close(bbox.height, r2.height, EPSILON, 'rect2 height is ' + r2.height);
g.remove();
})
g.append(elem)
svgroot.append(g)
bbox = getBBoxWithTransform(g, mockaddSVGElemensFromJson, mockPathActions)
assert.close(bbox.x, r2.x + tx, EPSILON, 'rect2 x is ' + r2.x)
assert.close(bbox.y, r2.y + ty, EPSILON, 'rect2 y is ' + r2.y)
assert.close(bbox.width, r2.width, EPSILON, 'rect2 width is' + r2.width)
assert.close(bbox.height, r2.height, EPSILON, 'rect2 height is ' + r2.height)
g.remove()
elem = mockCreateSVGElement({
element: 'ellipse',
attr: { id: 'ellipse1', cx: '100', cy: '100', rx: '50', ry: '50', transform: 'rotate(45 100,100) ' + matrix }
});
svgroot.append(elem);
bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions);
})
svgroot.append(elem)
bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions)
/** @todo: the BBox algorithm is using the bezier control points to calculate the bounding box. Should be 50, 50, 100, 100. */
// assert.ok(bbox.x > 45 + tx && bbox.x <= 50 + tx);
assert.ok(bbox.y > 45 + ty && bbox.y <= 50 + ty);
assert.ok(bbox.y > 45 + ty && bbox.y <= 50 + ty)
// assert.ok(bbox.width >= 100 && bbox.width < 110);
// assert.ok(bbox.height >= 100 && bbox.height < 110);
elem.remove();
});
elem.remove()
})
it('Test getStrokedBBox with stroke-width 10', function () {
const { getStrokedBBox } = utilities;
const { getStrokedBBox } = utilities
const strokeWidth = 10;
const strokeWidth = 10
let elem = mockCreateSVGElement({
element: 'path',
attr: { id: 'path', d: 'M0,1 L2,3', 'stroke-width': strokeWidth }
});
svgroot.append(elem);
let bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions);
assert.deepEqual(bbox, { x: 0 - strokeWidth / 2, y: 1 - strokeWidth / 2, width: 2 + strokeWidth, height: 2 + strokeWidth });
elem.remove();
})
svgroot.append(elem)
let bbox = getStrokedBBox([elem], mockaddSVGElemensFromJson, mockPathActions)
assert.deepEqual(bbox, { x: 0 - strokeWidth / 2, y: 1 - strokeWidth / 2, width: 2 + strokeWidth, height: 2 + strokeWidth })
elem.remove()
elem = mockCreateSVGElement({
element: 'rect',
attr: { id: 'rect', x: '0', y: '1', width: '5', height: '10', 'stroke-width': strokeWidth }
});
svgroot.append(elem);
bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions);
assert.deepEqual(bbox, { x: 0 - strokeWidth / 2, y: 1 - strokeWidth / 2, width: 5 + strokeWidth, height: 10 + strokeWidth });
elem.remove();
})
svgroot.append(elem)
bbox = getStrokedBBox([elem], mockaddSVGElemensFromJson, mockPathActions)
assert.deepEqual(bbox, { x: 0 - strokeWidth / 2, y: 1 - strokeWidth / 2, width: 5 + strokeWidth, height: 10 + strokeWidth })
elem.remove()
elem = mockCreateSVGElement({
element: 'line',
attr: { id: 'line', x1: '0', y1: '1', x2: '5', y2: '6', 'stroke-width': strokeWidth }
});
svgroot.append(elem);
bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions);
assert.deepEqual(bbox, { x: 0 - strokeWidth / 2, y: 1 - strokeWidth / 2, width: 5 + strokeWidth, height: 5 + strokeWidth });
elem.remove();
})
svgroot.append(elem)
bbox = getStrokedBBox([elem], mockaddSVGElemensFromJson, mockPathActions)
assert.deepEqual(bbox, { x: 0 - strokeWidth / 2, y: 1 - strokeWidth / 2, width: 5 + strokeWidth, height: 5 + strokeWidth })
elem.remove()
elem = mockCreateSVGElement({
element: 'rect',
attr: { id: 'rect', x: '0', y: '1', width: '5', height: '10', 'stroke-width': strokeWidth }
});
})
const g = mockCreateSVGElement({
element: 'g',
attr: {}
});
g.append(elem);
svgroot.append(g);
bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions);
assert.deepEqual(bbox, { x: 0 - strokeWidth / 2, y: 1 - strokeWidth / 2, width: 5 + strokeWidth, height: 10 + strokeWidth });
g.remove();
});
})
g.append(elem)
svgroot.append(g)
bbox = getStrokedBBox([elem], mockaddSVGElemensFromJson, mockPathActions)
assert.deepEqual(bbox, { x: 0 - strokeWidth / 2, y: 1 - strokeWidth / 2, width: 5 + strokeWidth, height: 10 + strokeWidth })
g.remove()
})
it("Test getStrokedBBox with stroke-width 'none'", function () {
const { getStrokedBBox } = utilities;
const { getStrokedBBox } = utilities
let elem = mockCreateSVGElement({
element: 'path',
attr: { id: 'path', d: 'M0,1 L2,3', 'stroke-width': 'none' }
});
svgroot.append(elem);
let bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions);
assert.deepEqual(bbox, { x: 0, y: 1, width: 2, height: 2 });
elem.remove();
})
svgroot.append(elem)
let bbox = getStrokedBBox([elem], mockaddSVGElemensFromJson, mockPathActions)
assert.deepEqual(bbox, { x: 0, y: 1, width: 2, height: 2 })
elem.remove()
elem = mockCreateSVGElement({
element: 'rect',
attr: { id: 'rect', x: '0', y: '1', width: '5', height: '10', 'stroke-width': 'none' }
});
svgroot.append(elem);
bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions);
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 });
elem.remove();
})
svgroot.append(elem)
bbox = getStrokedBBox([elem], mockaddSVGElemensFromJson, mockPathActions)
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 })
elem.remove()
elem = mockCreateSVGElement({
element: 'line',
attr: { id: 'line', x1: '0', y1: '1', x2: '5', y2: '6', 'stroke-width': 'none' }
});
svgroot.append(elem);
bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions);
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 5 });
elem.remove();
})
svgroot.append(elem)
bbox = getStrokedBBox([elem], mockaddSVGElemensFromJson, mockPathActions)
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 5 })
elem.remove()
elem = mockCreateSVGElement({
element: 'rect',
attr: { id: 'rect', x: '0', y: '1', width: '5', height: '10', 'stroke-width': 'none' }
});
})
const g = mockCreateSVGElement({
element: 'g',
attr: {}
});
g.append(elem);
svgroot.append(g);
bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions);
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 });
g.remove();
});
})
g.append(elem)
svgroot.append(g)
bbox = getStrokedBBox([elem], mockaddSVGElemensFromJson, mockPathActions)
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 })
g.remove()
})
it('Test getStrokedBBox with no stroke-width attribute', function () {
const { getStrokedBBox } = utilities;
const { getStrokedBBox } = utilities
let elem = mockCreateSVGElement({
element: 'path',
attr: { id: 'path', d: 'M0,1 L2,3' }
});
svgroot.append(elem);
let bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions);
assert.deepEqual(bbox, { x: 0, y: 1, width: 2, height: 2 });
elem.remove();
})
svgroot.append(elem)
let bbox = getStrokedBBox([elem], mockaddSVGElemensFromJson, mockPathActions)
assert.deepEqual(bbox, { x: 0, y: 1, width: 2, height: 2 })
elem.remove()
elem = mockCreateSVGElement({
element: 'rect',
attr: { id: 'rect', x: '0', y: '1', width: '5', height: '10' }
});
svgroot.append(elem);
bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions);
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 });
elem.remove();
})
svgroot.append(elem)
bbox = getStrokedBBox([elem], mockaddSVGElemensFromJson, mockPathActions)
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 })
elem.remove()
elem = mockCreateSVGElement({
element: 'line',
attr: { id: 'line', x1: '0', y1: '1', x2: '5', y2: '6' }
});
svgroot.append(elem);
bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions);
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 5 });
elem.remove();
})
svgroot.append(elem)
bbox = getStrokedBBox([elem], mockaddSVGElemensFromJson, mockPathActions)
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 5 })
elem.remove()
elem = mockCreateSVGElement({
element: 'rect',
attr: { id: 'rect', x: '0', y: '1', width: '5', height: '10' }
});
})
const g = mockCreateSVGElement({
element: 'g',
attr: {}
});
g.append(elem);
svgroot.append(g);
bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions);
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 });
g.remove();
});
})
g.append(elem)
svgroot.append(g)
bbox = getStrokedBBox([elem], mockaddSVGElemensFromJson, mockPathActions)
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 })
g.remove()
})
/**
* Returns radians for degrees.
@ -465,7 +466,7 @@ describe('utilities bbox', function () {
* @returns {Float}
*/
function radians (degrees) {
return degrees * Math.PI / 180;
return degrees * Math.PI / 180
}
/**
@ -477,15 +478,15 @@ describe('utilities bbox', function () {
*/
function rotatePoint (point, angle, origin) {
if (!origin) {
origin = { x: 0, y: 0 };
origin = { x: 0, y: 0 }
}
const x = point.x - origin.x;
const y = point.y - origin.y;
const theta = radians(angle);
const x = point.x - origin.x
const y = point.y - origin.y
const theta = radians(angle)
return {
x: x * Math.cos(theta) + y * Math.sin(theta) + origin.x,
y: x * Math.sin(theta) + y * Math.cos(theta) + origin.y
};
}
}
/**
*
@ -495,21 +496,21 @@ describe('utilities bbox', function () {
* @returns {module:utilities.BBoxObject}
*/
function rotateRect (rect, angle, origin) {
const tl = rotatePoint({ x: rect.x, y: rect.y }, angle, origin);
const tr = rotatePoint({ x: rect.x + rect.width, y: rect.y }, angle, origin);
const br = rotatePoint({ x: rect.x + rect.width, y: rect.y + rect.height }, angle, origin);
const bl = rotatePoint({ x: rect.x, y: rect.y + rect.height }, angle, origin);
const tl = rotatePoint({ x: rect.x, y: rect.y }, angle, origin)
const tr = rotatePoint({ x: rect.x + rect.width, y: rect.y }, angle, origin)
const br = rotatePoint({ x: rect.x + rect.width, y: rect.y + rect.height }, angle, origin)
const bl = rotatePoint({ x: rect.x, y: rect.y + rect.height }, angle, origin)
const minx = Math.min(tl.x, tr.x, bl.x, br.x);
const maxx = Math.max(tl.x, tr.x, bl.x, br.x);
const miny = Math.min(tl.y, tr.y, bl.y, br.y);
const maxy = Math.max(tl.y, tr.y, bl.y, br.y);
const minx = Math.min(tl.x, tr.x, bl.x, br.x)
const maxx = Math.max(tl.x, tr.x, bl.x, br.x)
const miny = Math.min(tl.y, tr.y, bl.y, br.y)
const maxy = Math.max(tl.y, tr.y, bl.y, br.y)
return {
x: minx,
y: miny,
width: (maxx - minx),
height: (maxy - miny)
};
}
}
});
})

View File

@ -1,17 +1,17 @@
/* eslint-disable max-len, no-console */
import 'pathseg';
import 'pathseg'
import { NS } from '../../../instrumented/svgcanvas/namespaces.js';
import * as utilities from '../../../instrumented/svgcanvas/utilities.js';
import * as math from '../../../instrumented/svgcanvas/math.js';
import { NS } from '../../../instrumented/svgcanvas/namespaces.js'
import * as utilities from '../../../instrumented/svgcanvas/utilities.js'
import * as math from '../../../instrumented/svgcanvas/math.js'
describe('utilities performance', function () {
let currentLayer; let groupWithMatrixTransform; let textWithMatrixTransform;
let currentLayer; let groupWithMatrixTransform; let textWithMatrixTransform
beforeEach(() => {
document.body.textContent = '';
const style = document.createElement('style');
style.id = 'styleoverrides';
style.media = 'screen';
document.body.textContent = ''
const style = document.createElement('style')
style.id = 'styleoverrides'
style.media = 'screen'
style.textContent = `
#svgcanvas svg * {
cursor: move;
@ -19,9 +19,9 @@ describe('utilities performance', function () {
}
#svgcanvas svg {
cursor: default
}`;
}`
document.head.append(style);
document.head.append(style)
const editor = new DOMParser().parseFromString(`<div id="svg_editor">
<div id="workarea" style="cursor: auto; overflow: scroll; line-height: 12px; right: 100px;">
@ -64,14 +64,14 @@ describe('utilities performance', function () {
</svg>
</svg>
</div>
</div></div>`, 'application/xml');
const newNode = document.body.ownerDocument.importNode(editor.documentElement, true);
document.body.append(newNode);
</div></div>`, 'application/xml')
const newNode = document.body.ownerDocument.importNode(editor.documentElement, true)
document.body.append(newNode)
currentLayer = document.getElementById('layer1');
groupWithMatrixTransform = document.getElementById('svg_group_with_matrix_transform');
textWithMatrixTransform = document.getElementById('svg_text_with_matrix_transform');
});
currentLayer = document.getElementById('layer1')
groupWithMatrixTransform = document.getElementById('svg_group_with_matrix_transform')
textWithMatrixTransform = document.getElementById('svg_text_with_matrix_transform')
})
/**
* Create an SVG element for a mock.
@ -79,11 +79,11 @@ describe('utilities performance', function () {
* @returns {SVGElement}
*/
function mockCreateSVGElement (jsonMap) {
const elem = document.createElementNS(NS.SVG, jsonMap.element);
Object.entries(jsonMap.attr).forEach(([ attr, value ]) => {
elem.setAttribute(attr, value);
});
return elem;
const elem = document.createElementNS(NS.SVG, jsonMap.element)
Object.entries(jsonMap.attr).forEach(([attr, value]) => {
elem.setAttribute(attr, value)
})
return elem
}
/**
@ -92,9 +92,9 @@ describe('utilities performance', function () {
* @returns {SVGElement}
*/
function mockaddSVGElemensFromJson (json) {
const elem = mockCreateSVGElement(json);
currentLayer.append(elem);
return elem;
const elem = mockCreateSVGElement(json)
currentLayer.append(elem)
return elem
}
/**
@ -104,49 +104,49 @@ describe('utilities performance', function () {
* @returns {void}
*/
function fillDocumentByCloningElement (elem, count) {
const elemId = elem.getAttribute('id') + '-';
const elemId = elem.getAttribute('id') + '-'
for (let index = 0; index < count; index++) {
const clone = elem.cloneNode(true); // t: deep clone
const clone = elem.cloneNode(true) // t: deep clone
// Make sure you set a unique ID like a real document.
clone.setAttribute('id', elemId + index);
const { parentNode } = elem;
parentNode.append(clone);
clone.setAttribute('id', elemId + index)
const { parentNode } = elem
parentNode.append(clone)
}
}
const mockPathActions = {
resetOrientation (path) {
if (utilities.isNullish(path) || path.nodeName !== 'path') { return false; }
const tlist = path.transform.baseVal;
const m = math.transformListToTransform(tlist).matrix;
tlist.clear();
path.removeAttribute('transform');
const segList = path.pathSegList;
if (utilities.isNullish(path) || path.nodeName !== 'path') { return false }
const tlist = path.transform.baseVal
const m = math.transformListToTransform(tlist).matrix
tlist.clear()
path.removeAttribute('transform')
const segList = path.pathSegList
const len = segList.numberOfItems;
const len = segList.numberOfItems
// let lastX, lastY;
for (let i = 0; i < len; ++i) {
const seg = segList.getItem(i);
const type = seg.pathSegType;
const seg = segList.getItem(i)
const type = seg.pathSegType
if (type === 1) {
continue;
continue
}
const pts = [];
[ '', 1, 2 ].forEach(function (n) {
const x = seg['x' + n];
const y = seg['y' + n];
['', 1, 2].forEach(function (n) {
const x = seg['x' + n]
const y = seg['y' + n]
if (x !== undefined && y !== undefined) {
const pt = math.transformPoint(x, y, m);
pts.splice(pts.length, 0, pt.x, pt.y);
const pt = math.transformPoint(x, y, m)
pts.splice(pts.length, 0, pt.x, pt.y)
}
});
})
// path.replacePathSeg(type, i, pts, path);
}
return undefined;
return undefined
}
};
}
// //////////////////////////////////////////////////////////
// Performance times with various browsers on Macbook 2011 8MB RAM OS X El Capitan 10.11.4
@ -180,57 +180,57 @@ describe('utilities performance', function () {
// Pass2 svgCanvas.getStrokedBBox total ms 17, ave ms 0.2, min/max 0 23
it('Test svgCanvas.getStrokedBBox() performance with matrix transforms', function () {
const { getStrokedBBox } = utilities;
const { children } = currentLayer;
const { getStrokedBBox } = utilities
const { children } = currentLayer
let lastTime; let now;
let min = Number.MAX_VALUE;
let max = 0;
let total = 0;
let lastTime; let now
let min = Number.MAX_VALUE
let max = 0
let total = 0
fillDocumentByCloningElement(groupWithMatrixTransform, 50);
fillDocumentByCloningElement(textWithMatrixTransform, 50);
fillDocumentByCloningElement(groupWithMatrixTransform, 50)
fillDocumentByCloningElement(textWithMatrixTransform, 50)
// The first pass through all elements is slower.
const count = children.length;
const start = lastTime = now = Date.now();
const count = children.length
const start = lastTime = now = Date.now()
// Skip the first child which is the title.
for (let index = 1; index < count; index++) {
const child = children[index];
/* const obj = */ getStrokedBBox([ child ], mockaddSVGElemensFromJson, mockPathActions);
now = Date.now(); const delta = now - lastTime; lastTime = now;
total += delta;
min = Math.min(min, delta);
max = Math.max(max, delta);
const child = children[index]
/* const obj = */ getStrokedBBox([child], mockaddSVGElemensFromJson, mockPathActions)
now = Date.now(); const delta = now - lastTime; lastTime = now
total += delta
min = Math.min(min, delta)
max = Math.max(max, delta)
}
total = lastTime - start;
const ave = total / count;
assert.isBelow(ave, 20, 'svgedit.utilities.getStrokedBBox average execution time is less than 20 ms');
console.log('Pass1 svgCanvas.getStrokedBBox total ms ' + total + ', ave ms ' + ave.toFixed(1) + ',\t min/max ' + min + ' ' + max);
total = lastTime - start
const ave = total / count
assert.isBelow(ave, 20, 'svgedit.utilities.getStrokedBBox average execution time is less than 20 ms')
console.log('Pass1 svgCanvas.getStrokedBBox total ms ' + total + ', ave ms ' + ave.toFixed(1) + ',\t min/max ' + min + ' ' + max)
return new Promise((resolve) => {
// The second pass is two to ten times faster.
setTimeout(function () {
const ct = children.length;
const ct = children.length
const strt = lastTime = now = Date.now();
const strt = lastTime = now = Date.now()
// Skip the first child which is the title.
for (let index = 1; index < ct; index++) {
const child = children[index];
/* const obj = */ getStrokedBBox([ child ], mockaddSVGElemensFromJson, mockPathActions);
now = Date.now(); const delta = now - lastTime; lastTime = now;
total += delta;
min = Math.min(min, delta);
max = Math.max(max, delta);
const child = children[index]
/* const obj = */ getStrokedBBox([child], mockaddSVGElemensFromJson, mockPathActions)
now = Date.now(); const delta = now - lastTime; lastTime = now
total += delta
min = Math.min(min, delta)
max = Math.max(max, delta)
}
total = lastTime - strt;
const avg = total / ct;
assert.isBelow(avg, 2, 'svgedit.utilities.getStrokedBBox average execution time is less than 1 ms');
console.log('Pass2 svgCanvas.getStrokedBBox total ms ' + total + ', ave ms ' + avg.toFixed(1) + ',\t min/max ' + min + ' ' + max);
total = lastTime - strt
const avg = total / ct
assert.isBelow(avg, 2, 'svgedit.utilities.getStrokedBBox average execution time is less than 1 ms')
console.log('Pass2 svgCanvas.getStrokedBBox total ms ' + total + ', ave ms ' + avg.toFixed(1) + ',\t min/max ' + min + ' ' + max)
resolve();
});
});
});
});
resolve()
})
})
})
})

View File

@ -1,5 +1,5 @@
import * as utilities from '../../../instrumented/svgcanvas/utilities.js';
import { NS } from '../../../instrumented/svgcanvas/namespaces.js';
import * as utilities from '../../../instrumented/svgcanvas/utilities.js'
import { NS } from '../../../instrumented/svgcanvas/namespaces.js'
describe('utilities', function () {
/**
@ -8,11 +8,11 @@ describe('utilities', function () {
* @returns {SVGElement}
*/
function mockCreateSVGElement (jsonMap) {
const elem = document.createElementNS(NS.SVG, jsonMap.element);
Object.entries(jsonMap.attr).forEach(([ attr, value ]) => {
elem.setAttribute(attr, value);
});
return elem;
const elem = document.createElementNS(NS.SVG, jsonMap.element)
Object.entries(jsonMap.attr).forEach(([attr, value]) => {
elem.setAttribute(attr, value)
})
return elem
}
/**
* Adds SVG Element per parameters and appends to root.
@ -20,225 +20,225 @@ describe('utilities', function () {
* @returns {SVGElement}
*/
function mockaddSVGElemensFromJson (json) {
const elem = mockCreateSVGElement(json);
svgroot.append(elem);
return elem;
const elem = mockCreateSVGElement(json)
svgroot.append(elem)
return elem
}
const mockPathActions = { resetOrientation () { /* empty fn */ } };
let mockHistorySubCommands = [];
const mockPathActions = { resetOrientation () { /* empty fn */ } }
let mockHistorySubCommands = []
const mockHistory = {
BatchCommand: class {
addSubCommand (cmd) {
mockHistorySubCommands.push(cmd);
mockHistorySubCommands.push(cmd)
}
},
RemoveElementCommand: class {
// Longhand needed since used as a constructor
constructor (elem, nextSibling, parent) {
this.elem = elem;
this.nextSibling = nextSibling;
this.parent = parent;
this.elem = elem
this.nextSibling = nextSibling
this.parent = parent
}
},
InsertElementCommand: class {
constructor (path) { // Longhand needed since used as a constructor
this.path = path;
this.path = path
}
}
};
}
const mockCount = {
clearSelection: 0,
addToSelection: 0,
addCommandToHistory: 0
};
}
/**
* Increments clear seleciton count for mock test.
* @returns {void}
*/
function mockClearSelection () {
mockCount.clearSelection++;
mockCount.clearSelection++
}
/**
* Increments add selection count for mock test.
* @returns {void}
*/
function mockAddToSelection () {
mockCount.addToSelection++;
mockCount.addToSelection++
}
/**
* Increments add command to history count for mock test.
* @returns {void}
*/
function mockAddCommandToHistory () {
mockCount.addCommandToHistory++;
mockCount.addCommandToHistory++
}
let svg; let svgroot;
let svg; let svgroot
beforeEach(() => {
document.body.textContent = '';
document.body.textContent = ''
mockHistorySubCommands = [];
mockCount.clearSelection = 0;
mockCount.addToSelection = 0;
mockCount.addCommandToHistory = 0;
mockHistorySubCommands = []
mockCount.clearSelection = 0
mockCount.addToSelection = 0
mockCount.addCommandToHistory = 0
const sandbox = document.createElement('div');
svg = document.createElementNS(NS.SVG, 'svg');
const sandbox = document.createElement('div')
svg = document.createElementNS(NS.SVG, 'svg')
svgroot = mockCreateSVGElement({
element: 'svg',
attr: { id: 'svgroot' }
});
sandbox.append(svgroot);
document.body.append(sandbox);
});
})
sandbox.append(svgroot)
document.body.append(sandbox)
})
it('Test svgedit.utilities package', function () {
assert.ok(utilities);
assert.ok(utilities.toXml);
assert.equal(typeof utilities.toXml, typeof function () { /* empty fn */ });
});
assert.ok(utilities)
assert.ok(utilities.toXml)
assert.equal(typeof utilities.toXml, typeof function () { /* empty fn */ })
})
it('Test svgedit.utilities.toXml() function', function () {
const { toXml } = utilities;
const { toXml } = utilities
assert.equal(toXml('a'), 'a');
assert.equal(toXml('ABC_'), 'ABC_');
assert.equal(toXml('PB&J'), 'PB&amp;J');
assert.equal(toXml('2 < 5'), '2 &lt; 5');
assert.equal(toXml('5 > 2'), '5 &gt; 2');
assert.equal(toXml('\'<&>"'), '&#x27;&lt;&amp;&gt;&quot;');
});
assert.equal(toXml('a'), 'a')
assert.equal(toXml('ABC_'), 'ABC_')
assert.equal(toXml('PB&J'), 'PB&amp;J')
assert.equal(toXml('2 < 5'), '2 &lt; 5')
assert.equal(toXml('5 > 2'), '5 &gt; 2')
assert.equal(toXml('\'<&>"'), '&#x27;&lt;&amp;&gt;&quot;')
})
it('Test svgedit.utilities.encode64() function', function () {
const { encode64 } = utilities;
const { encode64 } = utilities
assert.equal(encode64('abcdef'), 'YWJjZGVm');
assert.equal(encode64('12345'), 'MTIzNDU=');
assert.equal(encode64(' '), 'IA==');
assert.equal(encode64('`~!@#$%^&*()-_=+[{]}\\|;:\'",<.>/?'), 'YH4hQCMkJV4mKigpLV89K1t7XX1cfDs6JyIsPC4+Lz8=');
});
assert.equal(encode64('abcdef'), 'YWJjZGVm')
assert.equal(encode64('12345'), 'MTIzNDU=')
assert.equal(encode64(' '), 'IA==')
assert.equal(encode64('`~!@#$%^&*()-_=+[{]}\\|;:\'",<.>/?'), 'YH4hQCMkJV4mKigpLV89K1t7XX1cfDs6JyIsPC4+Lz8=')
})
it('Test svgedit.utilities.decode64() function', function () {
const { decode64 } = utilities;
const { decode64 } = utilities
assert.equal(decode64('YWJjZGVm'), 'abcdef');
assert.equal(decode64('MTIzNDU='), '12345');
assert.equal(decode64('IA=='), ' ');
assert.equal(decode64('YH4hQCMkJV4mKigpLV89K1t7XX1cfDs6JyIsPC4+Lz8='), '`~!@#$%^&*()-_=+[{]}\\|;:\'",<.>/?');
});
assert.equal(decode64('YWJjZGVm'), 'abcdef')
assert.equal(decode64('MTIzNDU='), '12345')
assert.equal(decode64('IA=='), ' ')
assert.equal(decode64('YH4hQCMkJV4mKigpLV89K1t7XX1cfDs6JyIsPC4+Lz8='), '`~!@#$%^&*()-_=+[{]}\\|;:\'",<.>/?')
})
it('Test svgedit.utilities.convertToXMLReferences() function', function () {
const convert = utilities.convertToXMLReferences;
assert.equal(convert('ABC'), 'ABC');
const convert = utilities.convertToXMLReferences
assert.equal(convert('ABC'), 'ABC')
// assert.equal(convert('<27>BC'), '&#192;BC');
});
})
it('Test svgedit.utilities.bboxToObj() function', function () {
const { bboxToObj } = utilities;
const { bboxToObj } = utilities
const rect = svg.createSVGRect();
rect.x = 1;
rect.y = 2;
rect.width = 3;
rect.height = 4;
const rect = svg.createSVGRect()
rect.x = 1
rect.y = 2
rect.width = 3
rect.height = 4
const obj = bboxToObj(rect);
assert.equal(typeof obj, typeof {});
assert.equal(obj.x, 1);
assert.equal(obj.y, 2);
assert.equal(obj.width, 3);
assert.equal(obj.height, 4);
});
const obj = bboxToObj(rect)
assert.equal(typeof obj, typeof {})
assert.equal(obj.x, 1)
assert.equal(obj.y, 2)
assert.equal(obj.width, 3)
assert.equal(obj.height, 4)
})
it('Test getUrlFromAttr', function () {
assert.equal(utilities.getUrlFromAttr('url(#foo)'), '#foo');
assert.equal(utilities.getUrlFromAttr('url(somefile.svg#foo)'), 'somefile.svg#foo');
assert.equal(utilities.getUrlFromAttr('url("#foo")'), '#foo');
assert.equal(utilities.getUrlFromAttr('url("#foo")'), '#foo');
});
assert.equal(utilities.getUrlFromAttr('url(#foo)'), '#foo')
assert.equal(utilities.getUrlFromAttr('url(somefile.svg#foo)'), 'somefile.svg#foo')
assert.equal(utilities.getUrlFromAttr('url("#foo")'), '#foo')
assert.equal(utilities.getUrlFromAttr('url("#foo")'), '#foo')
})
it('Test getPathDFromSegments', function () {
const { getPathDFromSegments } = utilities;
const { getPathDFromSegments } = utilities
const doc = utilities.text2xml('<svg></svg>');
const path = doc.createElementNS(NS.SVG, 'path');
path.setAttribute('d', 'm0,0l5,0l0,5l-5,0l0,-5z');
const doc = utilities.text2xml('<svg></svg>')
const path = doc.createElementNS(NS.SVG, 'path')
path.setAttribute('d', 'm0,0l5,0l0,5l-5,0l0,-5z')
let d = getPathDFromSegments([
[ 'M', [ 1, 2 ] ],
[ 'Z', [] ]
]);
assert.equal(d, 'M1,2 Z');
['M', [1, 2]],
['Z', []]
])
assert.equal(d, 'M1,2 Z')
d = getPathDFromSegments([
[ 'M', [ 1, 2 ] ],
[ 'M', [ 3, 4 ] ],
[ 'Z', [] ]
]);
assert.equal(d, 'M1,2 M3,4 Z');
['M', [1, 2]],
['M', [3, 4]],
['Z', []]
])
assert.equal(d, 'M1,2 M3,4 Z')
d = getPathDFromSegments([
[ 'M', [ 1, 2 ] ],
[ 'C', [ 3, 4, 5, 6 ] ],
[ 'Z', [] ]
]);
assert.equal(d, 'M1,2 C3,4 5,6 Z');
});
['M', [1, 2]],
['C', [3, 4, 5, 6]],
['Z', []]
])
assert.equal(d, 'M1,2 C3,4 5,6 Z')
})
it('Test getPathDFromElement', function () {
const { getPathDFromElement } = utilities;
const { getPathDFromElement } = utilities
let elem = mockCreateSVGElement({
element: 'path',
attr: { id: 'path', d: 'M0,1 Z' }
});
svgroot.append(elem);
assert.equal(getPathDFromElement(elem), 'M0,1 Z');
elem.remove();
})
svgroot.append(elem)
assert.equal(getPathDFromElement(elem), 'M0,1 Z')
elem.remove()
elem = mockCreateSVGElement({
element: 'rect',
attr: { id: 'rect', x: '0', y: '1', width: '5', height: '10' }
});
svgroot.append(elem);
assert.equal(getPathDFromElement(elem), 'M0,1 L5,1 L5,11 L0,11 L0,1 Z');
elem.remove();
})
svgroot.append(elem)
assert.equal(getPathDFromElement(elem), 'M0,1 L5,1 L5,11 L0,11 L0,1 Z')
elem.remove()
elem = mockCreateSVGElement({
element: 'rect',
attr: { id: 'roundrect', x: '0', y: '1', rx: '2', ry: '3', width: '10', height: '11' }
});
svgroot.append(elem);
const closeEnough = /M0,4 C0,2.3\d* 0.9\d*,1 2,1 L8,1 C9.0\d*,1 10,2.3\d* 10,4 L10,9 C10,10.6\d* 9.0\d*,12 8,12 L2,12 C0.9\d*,12 0,10.6\d* 0,9 L0,4 Z/;
assert.equal(closeEnough.test(getPathDFromElement(elem)), true);
elem.remove();
})
svgroot.append(elem)
const closeEnough = /M0,4 C0,2.3\d* 0.9\d*,1 2,1 L8,1 C9.0\d*,1 10,2.3\d* 10,4 L10,9 C10,10.6\d* 9.0\d*,12 8,12 L2,12 C0.9\d*,12 0,10.6\d* 0,9 L0,4 Z/
assert.equal(closeEnough.test(getPathDFromElement(elem)), true)
elem.remove()
elem = mockCreateSVGElement({
element: 'line',
attr: { id: 'line', x1: '0', y1: '1', x2: '5', y2: '6' }
});
svgroot.append(elem);
assert.equal(getPathDFromElement(elem), 'M0,1L5,6');
elem.remove();
})
svgroot.append(elem)
assert.equal(getPathDFromElement(elem), 'M0,1L5,6')
elem.remove()
elem = mockCreateSVGElement({
element: 'circle',
attr: { id: 'circle', cx: '10', cy: '11', rx: '5', ry: '10' }
});
svgroot.append(elem);
assert.equal(getPathDFromElement(elem), 'M5,11 C5,5.475138121546961 7.237569060773481,1 10,1 C12.762430939226519,1 15,5.475138121546961 15,11 C15,16.524861878453038 12.762430939226519,21 10,21 C7.237569060773481,21 5,16.524861878453038 5,11 Z');
elem.remove();
})
svgroot.append(elem)
assert.equal(getPathDFromElement(elem), 'M5,11 C5,5.475138121546961 7.237569060773481,1 10,1 C12.762430939226519,1 15,5.475138121546961 15,11 C15,16.524861878453038 12.762430939226519,21 10,21 C7.237569060773481,21 5,16.524861878453038 5,11 Z')
elem.remove()
elem = mockCreateSVGElement({
element: 'polyline',
attr: { id: 'polyline', points: '0,1 5,1 5,11 0,11' }
});
svgroot.append(elem);
assert.equal(getPathDFromElement(elem), 'M0,1 5,1 5,11 0,11');
elem.remove();
})
svgroot.append(elem)
assert.equal(getPathDFromElement(elem), 'M0,1 5,1 5,11 0,11')
elem.remove()
assert.equal(getPathDFromElement({ tagName: 'something unknown' }), undefined);
});
assert.equal(getPathDFromElement({ tagName: 'something unknown' }), undefined)
})
it('Test getBBoxOfElementAsPath', function () {
/**
@ -246,88 +246,88 @@ describe('utilities', function () {
* @type {module:utilities.getBBoxOfElementAsPath}
*/
function getBBoxOfElementAsPath (elem, addSVGElemensFromJson, pathActions) {
const bbox = utilities.getBBoxOfElementAsPath(elem, addSVGElemensFromJson, pathActions);
return utilities.bboxToObj(bbox); // need this for assert.equal() to work.
const bbox = utilities.getBBoxOfElementAsPath(elem, addSVGElemensFromJson, pathActions)
return utilities.bboxToObj(bbox) // need this for assert.equal() to work.
}
let elem = mockCreateSVGElement({
element: 'path',
attr: { id: 'path', d: 'M0,1 Z' }
});
svgroot.append(elem);
let bbox = getBBoxOfElementAsPath(elem, mockaddSVGElemensFromJson, mockPathActions);
assert.deepEqual(bbox, { x: 0, y: 1, width: 0, height: 0 });
elem.remove();
})
svgroot.append(elem)
let bbox = getBBoxOfElementAsPath(elem, mockaddSVGElemensFromJson, mockPathActions)
assert.deepEqual(bbox, { x: 0, y: 1, width: 0, height: 0 })
elem.remove()
elem = mockCreateSVGElement({
element: 'rect',
attr: { id: 'rect', x: '0', y: '1', width: '5', height: '10' }
});
svgroot.append(elem);
bbox = getBBoxOfElementAsPath(elem, mockaddSVGElemensFromJson, mockPathActions);
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 });
elem.remove();
})
svgroot.append(elem)
bbox = getBBoxOfElementAsPath(elem, mockaddSVGElemensFromJson, mockPathActions)
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 })
elem.remove()
elem = mockCreateSVGElement({
element: 'line',
attr: { id: 'line', x1: '0', y1: '1', x2: '5', y2: '6' }
});
svgroot.append(elem);
bbox = getBBoxOfElementAsPath(elem, mockaddSVGElemensFromJson, mockPathActions);
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 5 });
elem.remove();
})
svgroot.append(elem)
bbox = getBBoxOfElementAsPath(elem, mockaddSVGElemensFromJson, mockPathActions)
assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 5 })
elem.remove()
// TODO: test element with transform. Need resetOrientation above to be working or mock it.
});
})
it('Test convertToPath rect', function () {
const { convertToPath } = utilities;
const { convertToPath } = utilities
const attrs = {
fill: 'red',
stroke: 'white',
'stroke-width': '1',
visibility: 'hidden'
};
}
const elem = mockCreateSVGElement({
element: 'rect',
attr: { id: 'rect', x: '0', y: '1', width: '5', height: '10' }
});
svgroot.append(elem);
const path = convertToPath(elem, attrs, mockaddSVGElemensFromJson, mockPathActions, mockClearSelection, mockAddToSelection, mockHistory, mockAddCommandToHistory);
assert.equal(path.getAttribute('d'), 'M0,1 L5,1 L5,11 L0,11 L0,1 Z');
assert.equal(path.getAttribute('visibilituy'), null);
assert.equal(path.id, 'rect');
assert.equal(path.parentNode, svgroot);
assert.equal(elem.parentNode, null);
assert.equal(mockHistorySubCommands.length, 2);
assert.equal(mockCount.clearSelection, 1);
assert.equal(mockCount.addToSelection, 1);
assert.equal(mockCount.addCommandToHistory, 1);
path.remove();
});
})
svgroot.append(elem)
const path = convertToPath(elem, attrs, mockaddSVGElemensFromJson, mockPathActions, mockClearSelection, mockAddToSelection, mockHistory, mockAddCommandToHistory)
assert.equal(path.getAttribute('d'), 'M0,1 L5,1 L5,11 L0,11 L0,1 Z')
assert.equal(path.getAttribute('visibilituy'), null)
assert.equal(path.id, 'rect')
assert.equal(path.parentNode, svgroot)
assert.equal(elem.parentNode, null)
assert.equal(mockHistorySubCommands.length, 2)
assert.equal(mockCount.clearSelection, 1)
assert.equal(mockCount.addToSelection, 1)
assert.equal(mockCount.addCommandToHistory, 1)
path.remove()
})
it('Test convertToPath unknown element', function () {
const { convertToPath } = utilities;
const { convertToPath } = utilities
const attrs = {
fill: 'red',
stroke: 'white',
'stroke-width': '1',
visibility: 'hidden'
};
}
const elem = {
tagName: 'something unknown',
id: 'something-unknown',
getAttribute () { return ''; },
getAttribute () { return '' },
parentNode: svgroot
};
const path = convertToPath(elem, attrs, mockaddSVGElemensFromJson, mockPathActions, mockClearSelection, mockAddToSelection, mockHistory, mockAddCommandToHistory);
assert.equal(path, null);
assert.equal(elem.parentNode, svgroot);
assert.equal(mockHistorySubCommands.length, 0);
assert.equal(mockCount.clearSelection, 0);
assert.equal(mockCount.addToSelection, 0);
assert.equal(mockCount.addCommandToHistory, 0);
});
});
}
const path = convertToPath(elem, attrs, mockaddSVGElemensFromJson, mockPathActions, mockClearSelection, mockAddToSelection, mockHistory, mockAddCommandToHistory)
assert.equal(path, null)
assert.equal(elem.parentNode, svgroot)
assert.equal(mockHistorySubCommands.length, 0)
assert.equal(mockCount.clearSelection, 0)
assert.equal(mockCount.addToSelection, 0)
assert.equal(mockCount.addCommandToHistory, 0)
})
})

View File

@ -1,4 +1,4 @@
'use strict';
'use strict'
// ***********************************************************
// This example plugins/index.js can be used to load plugins
@ -11,6 +11,6 @@
// ***********************************************************
require('@babel/register')({
plugins: [ '@babel/plugin-transform-modules-commonjs' ]
});
module.exports = require('./main.js').default;
plugins: ['@babel/plugin-transform-modules-commonjs']
})
module.exports = require('./main.js').default

View File

@ -1,8 +1,8 @@
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
import codeCoverageTask from "@cypress/code-coverage/task.js";
import { initPlugin } from "cypress-plugin-snapshots/plugin.js";
import codeCoverageTask from '@cypress/code-coverage/task.js'
import { initPlugin } from 'cypress-plugin-snapshots/plugin.js'
export default (on, config) => {
// `on` is used to hook into various events Cypress emits
@ -12,35 +12,35 @@ export default (on, config) => {
// `config` is the resolved Cypress config
// https://docs.cypress.io/guides/tooling/code-coverage.html#Install-the-plugin
codeCoverageTask(on, config);
initPlugin(on, config);
on("before:browser:launch", (browser, launchOptions) => {
if (browser.name === "chrome" && browser.isHeadless) {
codeCoverageTask(on, config)
initPlugin(on, config)
on('before:browser:launch', (browser, launchOptions) => {
if (browser.name === 'chrome' && browser.isHeadless) {
// fullPage screenshot size is 1400x1200 on non-retina screens
// and 2800x2400 on retina screens
launchOptions.args.push("--window-size=1400,1200");
launchOptions.args.push('--window-size=1400,1200')
// force screen to be non-retina (1400x1200 size)
launchOptions.args.push("--force-device-scale-factor=1");
launchOptions.args.push('--force-device-scale-factor=1')
// force screen to be retina (2800x2400 size)
// launchOptions.args.push('--force-device-scale-factor=2')
}
if (browser.name === "electron" && browser.isHeadless) {
if (browser.name === 'electron' && browser.isHeadless) {
// fullPage screenshot size is 1400x1200
launchOptions.preferences.width = 1400;
launchOptions.preferences.height = 1200;
launchOptions.preferences.width = 1400
launchOptions.preferences.height = 1200
}
if (browser.name === "firefox" && browser.isHeadless) {
if (browser.name === 'firefox' && browser.isHeadless) {
// menubars take up height on the screen
// so fullPage screenshot size is 1400x1126
launchOptions.args.push("--width=1400");
launchOptions.args.push("--height=1200");
launchOptions.args.push('--width=1400')
launchOptions.args.push('--height=1200')
}
return launchOptions;
});
return config;
};
return launchOptions
})
return config
}

View File

@ -1,6 +1,6 @@
import assertionWrapper from './assertion-wrapper.js';
import assertionWrapper from './assertion-wrapper.js'
const NEAR_ZERO = 5e-6; // 0.000005, Firefox fails at higher levels of precision.
const NEAR_ZERO = 5e-6 // 0.000005, Firefox fails at higher levels of precision.
/**
* Checks that the supplied values are equal with a high though not absolute degree of precision.
@ -10,9 +10,9 @@ const NEAR_ZERO = 5e-6; // 0.000005, Firefox fails at higher levels of precision
* @returns {void}
*/
function almostEquals (actual, expected, message) {
message = message || (actual + ' did not equal ' + expected);
const result = Math.abs(actual - expected) < NEAR_ZERO;
return { result, message, actual, expected };
message = message || (actual + ' did not equal ' + expected)
const result = Math.abs(actual - expected) < NEAR_ZERO
return { result, message, actual, expected }
}
/**
@ -21,9 +21,9 @@ function almostEquals (actual, expected, message) {
* @returns {void}
*/
function setAssertionMethods (_chai, utils) {
const wrap = assertionWrapper(_chai, utils);
const wrap = assertionWrapper(_chai, utils)
assert.almostEquals = wrap(almostEquals);
assert.almostEquals = wrap(almostEquals)
}
export default setAssertionMethods;
export default setAssertionMethods

View File

@ -1,4 +1,4 @@
import assertionWrapper from './assertion-wrapper.js';
import assertionWrapper from './assertion-wrapper.js'
/**
* @typedef {PlainObject} InfoObject
@ -21,10 +21,10 @@ import assertionWrapper from './assertion-wrapper.js';
* @returns {InfoObject}
*/
function close (actual, expected, maxDifference, message) {
const actualDiff = (actual === expected) ? 0 : Math.abs(actual - expected);
const result = actualDiff <= maxDifference;
message = message || (actual + ' should be within ' + maxDifference + ' (inclusive) of ' + expected + (result ? '' : '. Actual: ' + actualDiff));
return { result, message, actual, expected };
const actualDiff = (actual === expected) ? 0 : Math.abs(actual - expected)
const result = actualDiff <= maxDifference
message = message || (actual + ' should be within ' + maxDifference + ' (inclusive) of ' + expected + (result ? '' : '. Actual: ' + actualDiff))
return { result, message, actual, expected }
}
/**
@ -40,21 +40,21 @@ function close (actual, expected, maxDifference, message) {
* @returns {InfoObject}
*/
function closePercent (actual, expected, maxPercentDifference, message) {
let actualDiff; let result;
let actualDiff; let result
if (actual === expected) {
actualDiff = 0;
result = actualDiff <= maxPercentDifference;
actualDiff = 0
result = actualDiff <= maxPercentDifference
} else if (actual !== 0 && expected !== 0 && expected !== Infinity && expected !== -Infinity) {
actualDiff = Math.abs(100 * (actual - expected) / expected);
result = actualDiff <= maxPercentDifference;
actualDiff = Math.abs(100 * (actual - expected) / expected)
result = actualDiff <= maxPercentDifference
} else {
// Dividing by zero (0)! Should return `false` unless the max percentage was `Infinity`
actualDiff = Infinity;
result = maxPercentDifference === Infinity;
actualDiff = Infinity
result = maxPercentDifference === Infinity
}
message = message || (actual + ' should be within ' + maxPercentDifference + '% (inclusive) of ' + expected + (result ? '' : '. Actual: ' + actualDiff + '%'));
message = message || (actual + ' should be within ' + maxPercentDifference + '% (inclusive) of ' + expected + (result ? '' : '. Actual: ' + actualDiff + '%'))
return { result, message, actual, expected };
return { result, message, actual, expected }
}
/**
@ -70,10 +70,10 @@ function closePercent (actual, expected, maxPercentDifference, message) {
* @returns {InfoObject}
*/
function notClose (actual, expected, minDifference, message) {
const actualDiff = Math.abs(actual - expected);
const result = actualDiff > minDifference;
message = message || (actual + ' should not be within ' + minDifference + ' (exclusive) of ' + expected + (result ? '' : '. Actual: ' + actualDiff));
return { result, message, actual, expected };
const actualDiff = Math.abs(actual - expected)
const result = actualDiff > minDifference
message = message || (actual + ' should not be within ' + minDifference + ' (exclusive) of ' + expected + (result ? '' : '. Actual: ' + actualDiff))
return { result, message, actual, expected }
}
/**
@ -89,21 +89,21 @@ function notClose (actual, expected, minDifference, message) {
* @returns {InfoObject}
*/
function notClosePercent (actual, expected, minPercentDifference, message) {
let actualDiff; let result;
let actualDiff; let result
if (actual === expected) {
actualDiff = 0;
result = actualDiff > minPercentDifference;
actualDiff = 0
result = actualDiff > minPercentDifference
} else if (actual !== 0 && expected !== 0 && expected !== Infinity && expected !== -Infinity) {
actualDiff = Math.abs(100 * (actual - expected) / expected);
result = actualDiff > minPercentDifference;
actualDiff = Math.abs(100 * (actual - expected) / expected)
result = actualDiff > minPercentDifference
} else {
// Dividing by zero (0)! Should only return `true` if the min percentage was `Infinity`
actualDiff = Infinity;
result = minPercentDifference !== Infinity;
actualDiff = Infinity
result = minPercentDifference !== Infinity
}
message = message || (actual + ' should not be within ' + minPercentDifference + '% (exclusive) of ' + expected + (result ? '' : '. Actual: ' + actualDiff + '%'));
message = message || (actual + ' should not be within ' + minPercentDifference + '% (exclusive) of ' + expected + (result ? '' : '. Actual: ' + actualDiff + '%'))
return { result, message, actual, expected };
return { result, message, actual, expected }
}
/**
@ -112,12 +112,12 @@ function notClosePercent (actual, expected, minPercentDifference, message) {
* @returns {void}
*/
function setAssertionMethods (_chai, utils) {
const wrap = assertionWrapper(_chai, utils);
const wrap = assertionWrapper(_chai, utils)
assert.close = wrap(close);
assert.closePercent = wrap(closePercent);
assert.notClose = wrap(notClose);
assert.notClosePercent = wrap(notClosePercent);
assert.close = wrap(close)
assert.closePercent = wrap(closePercent)
assert.notClose = wrap(notClose)
assert.notClosePercent = wrap(notClosePercent)
}
export default setAssertionMethods;
export default setAssertionMethods

View File

@ -1,4 +1,4 @@
import assertionWrapper from './assertion-wrapper.js';
import assertionWrapper from './assertion-wrapper.js'
/**
* Expects an out of bounds `INDEX_SIZE_ERR` exception.
@ -8,18 +8,18 @@ import assertionWrapper from './assertion-wrapper.js';
* @returns {void}
*/
function expectOutOfBoundsException (obj, fn, arg1) {
const expected = true;
const message = 'Caught an INDEX_SIZE_ERR exception';
let result = false;
const expected = true
const message = 'Caught an INDEX_SIZE_ERR exception'
let result = false
try {
obj[fn](arg1);
obj[fn](arg1)
} catch (e) {
if (e.code === 1) {
result = true;
result = true
}
}
const actual = result;
return { result, message, actual, expected };
const actual = result
return { result, message, actual, expected }
}
/**
@ -28,9 +28,9 @@ function expectOutOfBoundsException (obj, fn, arg1) {
* @returns {void}
*/
function setAssertionMethods (_chai, utils) {
const wrap = assertionWrapper(_chai, utils);
const wrap = assertionWrapper(_chai, utils)
assert.expectOutOfBoundsException = wrap(expectOutOfBoundsException);
assert.expectOutOfBoundsException = wrap(expectOutOfBoundsException)
}
export default setAssertionMethods;
export default setAssertionMethods

View File

@ -6,10 +6,10 @@
function setAssertionMethods (_chai, _utils) {
return (method) => {
return (...args) => {
const { result, message, actual, expected } = method(...args);
const assertion = new _chai.Assertion();
assertion.assert(result, `Expected ${actual} to be ${expected}`, message);
};
};
const { result, message, actual, expected } = method(...args)
const assertion = new _chai.Assertion()
assertion.assert(result, `Expected ${actual} to be ${expected}`, message)
}
}
}
export default setAssertionMethods;
export default setAssertionMethods

View File

@ -23,9 +23,9 @@
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
/* globals Cypress */
// remove the style attributes that is causing differences in snapshots
const ngAttributes = [ 'style' ];
const ngAttributes = ['style']
Cypress.Commands.add(
'cleanSnapshot',
@ -33,16 +33,16 @@ Cypress.Commands.add(
prevSubject: true
},
(subject, _snapshotOptions) => {
let html = subject[0].outerHTML;
let html = subject[0].outerHTML
for (const attribute of ngAttributes) {
const expression = new RegExp(`${attribute}[^= ]*="[^"]*"`, 'g');
html = html.replace(expression, '');
const expression = new RegExp(`${attribute}[^= ]*="[^"]*"`, 'g')
html = html.replace(expression, '')
}
html = html.replace(/<!--[\s\S]*?-->/g, '');
html = html.replace(/<!--[\s\S]*?-->/g, '')
const sanitisedBody = new DOMParser().parseFromString(html, 'text/html').querySelector('body');
const sanitisedBody = new DOMParser().parseFromString(html, 'text/html').querySelector('body')
return cy.wrap(sanitisedBody.firstChild).toMatchSnapshot();
return cy.wrap(sanitisedBody.firstChild).toMatchSnapshot()
}
);
)

View File

@ -14,7 +14,7 @@
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands.js';
import './commands.js'
// Alternatively you can use CommonJS syntax:
// require('./commands')
@ -29,17 +29,17 @@ import './commands.js';
* @see https://github.com/cypress-io/cypress-fiddle
* @example import {testExamples} from '@cypress/fiddle';
*/
import '@cypress/fiddle';
import '@cypress/fiddle'
/**
* COVERAGE.
* @see https://docs.cypress.io/guides/tooling/code-coverage.html#Install-the-plugin
*/
import '@cypress/code-coverage/support.js';
import '@cypress/code-coverage/support.js'
/*****
* SNAPSHOTS
* @see https://www.npmjs.com/package/cypress-plugin-snapshots
*/
import 'cypress-plugin-snapshots/commands.js';
import 'cypress-plugin-snapshots/commands.js'

View File

@ -1,24 +1,24 @@
export const approveStorage = () => {
// JFH will need to be chnaged when dialog is changed...
cy.get('#storage_ok').click();
};
cy.get('#storage_ok').click()
}
export const visitAndApproveStorage = () => {
cy.visit('/instrumented/editor/index.html');
approveStorage();
};
cy.visit('/instrumented/editor/index.html')
approveStorage()
}
export const openMainMenu = () => {
return cy.get('#main_button').click({ force: true });
};
return cy.get('#main_button').click({ force: true })
}
export const openEditorPreferences = () => {
openMainMenu();
return cy.get('#tool_editor_prefs').click();
};
openMainMenu()
return cy.get('#tool_editor_prefs').click()
}
export const selectEnglish = () => {
openEditorPreferences();
cy.get('#lang_select').select('en');
cy.get('#tool_prefs_save').click();
};
openEditorPreferences()
cy.get('#lang_select').select('en')
cy.get('#tool_prefs_save').click()
}

View File

@ -27,14 +27,14 @@
<input id="text" style="width:0;height:0;opacity: 0"/>
<script type="module">
/* globals canvas */
import SvgCanvas from '../src/svgcanvas/svgcanvas.js';
import SvgCanvas from '../src/svgcanvas/svgcanvas.js'
const container = document.querySelector('#editorContainer');
const { width, height } = { width: 500, height: 300 };
window.width = width;
window.height = height;
const container = document.querySelector('#editorContainer')
const { width, height } = { width: 500, height: 300 }
window.width = width
window.height = height
const hiddenTextTagId = "text";
const hiddenTextTagId = 'text'
const config = {
initFill: { color: 'FFFFFF', opacity: 1 },
@ -44,28 +44,27 @@ const config = {
imgPath: '../src/editor/images',
dimensions: [ width, height ],
baseUnit: 'px'
};
}
window.canvas = new SvgCanvas(container, config);
canvas.updateCanvas(width, height);
window.canvas = new SvgCanvas(container, config)
canvas.updateCanvas(width, height)
window.fill = function (colour) {
canvas.getSelectedElements().forEach((el) => {
el.setAttribute('fill', colour);
});
};
el.setAttribute('fill', colour)
})
}
const hiddenTextTag = window.canvas.$id(hiddenTextTagId);
window.canvas.textActions.setInputElem(hiddenTextTag);
const hiddenTextTag = window.canvas.$id(hiddenTextTagId)
window.canvas.textActions.setInputElem(hiddenTextTag)
const addListenerMulti = (element, eventNames, listener)=> {
eventNames.split(' ').forEach((eventName)=> element.addEventListener(eventName, listener, false));
};
const addListenerMulti = (element, eventNames, listener) => {
eventNames.split(' ').forEach((eventName) => element.addEventListener(eventName, listener, false))
}
addListenerMulti(hiddenTextTag, 'keyup input', (evt) => {
window.canvas.setTextContent(evt.currentTarget.value);
});
window.canvas.setTextContent(evt.currentTarget.value)
})
</script>
</body>
</html>

View File

@ -1,8 +1,8 @@
/* eslint-env node */
'use strict';
'use strict'
module.exports = {
plugins: [ 'plugins/markdown' ],
plugins: ['plugins/markdown'],
markdown: {},
recurseDepth: 10,
source: {
@ -33,4 +33,4 @@ module.exports = {
destination: 'docs/jsdoc',
tutorials: 'docs/tutorials'
}
};
}

View File

@ -48,7 +48,7 @@ svgEditor.setConfig({
initFill: {
color: '0000FF'
}
});
})
```
This will set the default width/height of the image, the size of the outside
@ -121,13 +121,13 @@ set if storage is found.
```js
// Serialized string:
svgEditor.loadFromString('<svg xmlns="...">...</svg>');
svgEditor.loadFromString('<svg xmlns="...">...</svg>')
// Data URI:
svgEditor.loadFromDataURI('data:image/svg+xml;base64,...');
svgEditor.loadFromDataURI('data:image/svg+xml;base64,...')
// Local URL:
svgEditor.loadFromURL('images/logo.svg');
svgEditor.loadFromURL('images/logo.svg')
```
### Preload a file (by URL)
@ -136,13 +136,13 @@ As a URL parameter, one can pre-load an SVG file in the following manner:
```js
// Data URI
location.href += '?source=' + encodeURIComponent('data:image/svg+xml;utf8,' + svgText);
location.href += '?source=' + encodeURIComponent('data:image/svg+xml;utf8,' + svgText)
// Data URI (base 64):
location.href += '?source=' + encodeURIComponent('data:image/svg+xml;base64,' + svgTextAsBase64); // data%3Aimage%2Fsvg%2Bxml%3Bbase64%2C ...
location.href += '?source=' + encodeURIComponent('data:image/svg+xml;base64,' + svgTextAsBase64) // data%3Aimage%2Fsvg%2Bxml%3Bbase64%2C ...
// Local URL:
location.href += '?url=' + encodeURIComponent('images/logo.svg'); // images%2Flogo.svg
location.href += '?url=' + encodeURIComponent('images/logo.svg') // images%2Flogo.svg
```
**Note:** There is currently a bug that prevents data URIs ending with
@ -160,7 +160,7 @@ To add your own stylesheets along with the default stylesheets, ensure
`"@default"` is present in the array along with your own. For example:
```js
svgEditor.setConfig({ stylesheets: [ '@default', 'myStylesheet.css' ] });
svgEditor.setConfig({ stylesheets: [ '@default', 'myStylesheet.css' ] })
```
(In version 2.8, the CSS file `editor/custom.css` was included by default,

View File

@ -11,7 +11,7 @@ svgEditor.setCustomHandlers({
save (_win, _data) {
// Save svg
}
});
})
```
Other methods corresponding to UI events that may be supplied are `open`
@ -40,9 +40,9 @@ $(document).bind('svgEditorReady', function () {
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="50">
<ellipse cx="50" cy="25" rx="50" ry="25" style="fill:blue;"/>
</svg>`;
$('iframe.svgedit')[0].contentWindow.svgCanvas.setSvgString(svg);
});
</svg>`
$('iframe.svgedit')[0].contentWindow.svgCanvas.setSvgString(svg)
})
```
If you are acting within the frame, you may use `svgEditor.ready`
@ -86,7 +86,7 @@ Canvas events are listened to with the bind method
([JSDocs API]{@link module:svgcanvas.SvgCanvas#bind}):
```js
canvas.bind(eventName, callback);
canvas.bind(eventName, callback)
```
Canvas events are passed between the editor and canvas and should mostly

View File

@ -28,9 +28,9 @@ This is the general format for an extension:
export default {
name: 'extensionname',
init (_methods) {
return extensionData;
return extensionData
}
};
}
```
Extensions must export an object. (For the API docs of this object, see
@ -86,9 +86,9 @@ export default {
mouseUp (_opts) {
// ...
}
};
}
}
};
}
```
Note how the returned properties may include information on the buttons,
@ -145,15 +145,15 @@ import { importSetGlobalDefault } from '../external/dynamic-import-polyfill/impo
(async () => {
const url = `${svgEditor.curConfig.extPath}ext-locale/<extNameWithoutExtPrefix>/<lang>.js`;
const url = `${svgEditor.curConfig.extPath}ext-locale/<extNameWithoutExtPrefix>/<lang>.js`
const localeStrings = await importSetGlobalDefault(url, {
global: 'svgEditorExtensionLocale_imagelib_' + lang
});
})
// Use `localeStrings`
console.info(localeStrings);
console.info(localeStrings)
})();
})()
```
In addition to your own extension's locale strings,

View File

@ -120,7 +120,7 @@ these files). The default behavior is equivalent to this:
```js
svgEditor.setConfig({
stylesheets: [ '@default', '../svgedit-custom.css' ]
});
})
```
...which indicates that all default stylesheets will be loaded and then

View File

@ -1,16 +1,16 @@
module.exports = {
"statements": 45,
"branches": 34,
"lines": 46,
"functions": 45,
statements: 45,
branches: 34,
lines: 46,
functions: 45,
exclude: [
'editor/jquery.min.js',
'editor/jgraduate/**'
],
"reporter": [
"json-summary",
"text",
"html"
reporter: [
'json-summary',
'text',
'html'
]
};
}

4403
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,7 @@
"node": ">=10"
},
"scripts": {
"lint": "eslint --ext js,html,md .",
"lint": "standard .",
"test": "run-s cypress:instrument cypress:test",
"build": "rollup -c",
"build:watch": "rollup -c --watch",
@ -67,62 +67,55 @@
"not IE 11",
"not OperaMini all"
],
"standard": {
"ignore": [
"archive/"
],
"globals": [
"cy",
"assert"
],
"env": [
"mocha",
"browser"
]
},
"dependencies": {
"@babel/polyfill": "7.12.1",
"browser-fs-access": "0.23.0",
"canvg": "3.0.9",
"core-js": "3.19.3",
"core-js": "3.20.1",
"elix": "15.0.1",
"html2canvas": "1.3.3",
"i18next": "21.6.0",
"jspdf": "2.4.0",
"i18next": "21.6.4",
"jspdf": "2.5.0",
"pathseg": "1.2.1",
"regenerator-runtime": "0.13.9",
"rollup-plugin-polyfill-node": "0.8.0",
"svg2pdf.js": "2.2.0"
},
"devDependencies": {
"@babel/core": "7.16.0",
"@babel/preset-env": "7.16.4",
"@babel/register": "7.16.0",
"@babel/runtime-corejs3": "7.16.3",
"@babel/core": "7.16.5",
"@babel/preset-env": "7.16.5",
"@babel/register": "7.16.5",
"@babel/runtime-corejs3": "7.16.5",
"@cypress/code-coverage": "3.9.12",
"@cypress/fiddle": "1.19.3",
"@fintechstudios/eslint-plugin-chai-as-promised": "3.1.0",
"@rollup/plugin-babel": "5.3.0",
"@rollup/plugin-commonjs": "^18",
"@rollup/plugin-dynamic-import-vars": "1.4.1",
"@rollup/plugin-node-resolve": "13.0.6",
"@rollup/plugin-node-resolve": "13.1.1",
"@rollup/plugin-replace": "3.0.0",
"@rollup/plugin-url": "6.1.0",
"@web/dev-server": "0.1.28",
"@web/dev-server-esbuild": "^0.2.16",
"@web/dev-server-rollup": "0.3.13",
"babel-plugin-transform-object-rest-spread": "7.0.0-beta.3",
"copyfiles": "2.4.1",
"core-js-bundle": "3.19.3",
"core-js-bundle": "3.20.1",
"cp-cli": "2.0.0",
"cypress": "9.1.1",
"cypress": "9.2.0",
"cypress-multi-reporters": "1.5.0",
"cypress-plugin-snapshots": "1.4.4",
"eslint": "^7",
"eslint-config-standard": "16.0.3",
"eslint-plugin-array-func": "3.1.7",
"eslint-plugin-chai-expect": "3.0.0",
"eslint-plugin-chai-expect-keywords": "2.1.0",
"eslint-plugin-chai-friendly": "0.7.2",
"eslint-plugin-compat": "4.0.0",
"eslint-plugin-cypress": "2.12.1",
"eslint-plugin-eslint-comments": "3.2.0",
"eslint-plugin-html": "6.2.0",
"eslint-plugin-import": "2.25.3",
"eslint-plugin-jsdoc": "37.2.0",
"eslint-plugin-markdown": "2.2.1",
"eslint-plugin-no-unsanitized": "4.0.1",
"eslint-plugin-no-use-extend-native": "0.5.0",
"eslint-plugin-node": "11.1.0",
"eslint-plugin-promise": "5.2.0",
"eslint-plugin-standard": "4.1.0",
"jamilih": "0.54.0",
"jsdoc": "3.6.7",
"node-static": "0.7.11",
@ -135,7 +128,7 @@
"remark-cli": "10.0.1",
"remark-lint-ordered-list-marker-value": "3.1.1",
"rimraf": "3.0.2",
"rollup": "2.61.0",
"rollup": "2.62.0",
"rollup-plugin-copy": "3.4.0",
"rollup-plugin-filesize": "9.1.1",
"rollup-plugin-html": "^0.2.1",
@ -143,6 +136,7 @@
"rollup-plugin-progress": "1.1.2",
"rollup-plugin-re": "1.0.7",
"rollup-plugin-terser": "7.0.2",
"standard": "16.0.4",
"start-server-and-test": "1.14.0"
}
}

View File

@ -3,42 +3,42 @@
// This rollup script is run by the command:
// 'npm run build'
import path from 'path';
import { lstatSync, readdirSync } from 'fs';
import rimraf from 'rimraf';
import babel from '@rollup/plugin-babel';
import copy from 'rollup-plugin-copy';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import nodePolyfills from 'rollup-plugin-node-polyfills';
import url from '@rollup/plugin-url'; // for XML/SVG files
import path from 'path'
import { lstatSync, readdirSync } from 'fs'
import rimraf from 'rimraf'
import babel from '@rollup/plugin-babel'
import copy from 'rollup-plugin-copy'
import { nodeResolve } from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import nodePolyfills from 'rollup-plugin-node-polyfills'
import url from '@rollup/plugin-url' // for XML/SVG files
// eslint-disable-next-line node/no-extraneous-import
import html from 'rollup-plugin-html';
import html from 'rollup-plugin-html'
import dynamicImportVars from '@rollup/plugin-dynamic-import-vars';
import { terser } from 'rollup-plugin-terser';
import dynamicImportVars from '@rollup/plugin-dynamic-import-vars'
import { terser } from 'rollup-plugin-terser'
// import progress from 'rollup-plugin-progress';
import filesize from 'rollup-plugin-filesize';
import filesize from 'rollup-plugin-filesize'
// utility function
const getDirectories = (source) => {
const isDirectory = (dir) => {
return lstatSync(dir).isDirectory();
};
return readdirSync(source).map((name) => path.join(source, name)).filter((i) => isDirectory(i));
};
return lstatSync(dir).isDirectory()
}
return readdirSync(source).map((name) => path.join(source, name)).filter((i) => isDirectory(i))
}
// capture the list of files to build for extensions and ext-locales
const extensionDirs = getDirectories('src/editor/extensions');
const extensionDirs = getDirectories('src/editor/extensions')
const dest = [ 'dist/editor' ];
const dest = ['dist/editor']
// remove existing distribution
rimraf('./dist', () => console.info('recreating dist'));
rimraf('./dist', () => console.info('recreating dist'))
// config for svgedit core module
const config = [ {
input: [ 'src/editor/Editor.js' ],
const config = [{
input: ['src/editor/Editor.js'],
output: [
{
format: 'es',
@ -80,8 +80,8 @@ const config = [ {
dest: 'dist/editor',
rename: 'iife-index.html',
transform: (contents) => {
const replace1 = contents.toString().replace("import Editor from './Editor.js'", "/* import Editor from './xdomain-Editor.js' */");
return replace1.replace('<script type="module">', '<script src="./iife-Editor.js"></script><script>');
const replace1 = contents.toString().replace("import Editor from './Editor.js'", "/* import Editor from './xdomain-Editor.js' */")
return replace1.replace('<script type="module">', '<script src="./iife-Editor.js"></script><script>')
}
},
{ src: 'src/editor/images', dest },
@ -94,27 +94,29 @@ const config = [ {
{ src: 'src/editor/svgedit.css', dest }
]
}),
html({ include: [
'src/editor/panels/*.html',
'src/editor/templates/*.html',
'src/editor/dialogs/*.html'
] }),
html({
include: [
'src/editor/panels/*.html',
'src/editor/templates/*.html',
'src/editor/dialogs/*.html'
]
}),
nodeResolve({
browser: true,
preferBuiltins: false
}),
commonjs(),
dynamicImportVars({ include: `src/editor/locale.js` }),
babel({ babelHelpers: 'bundled', exclude: [ /\/core-js\// ] }), // exclude core-js to avoid circular dependencies.
dynamicImportVars({ include: 'src/editor/locale.js' }),
babel({ babelHelpers: 'bundled', exclude: [/\/core-js\//] }), // exclude core-js to avoid circular dependencies.
nodePolyfills(),
terser({ keep_fnames: true }), // keep_fnames is needed to avoid an error when calling extensions.
filesize()
]
} ];
}]
// config for dynamic extensions
extensionDirs.forEach((extensionDir) => {
const extensionName = path.basename(extensionDir);
const extensionName = path.basename(extensionDir)
extensionName && config.push(
{
input: `./src/editor/extensions/${extensionName}/${extensionName}.js`,
@ -128,25 +130,27 @@ extensionDirs.forEach((extensionDir) => {
],
plugins: [
url({
include: [ '**/*.svg', '**/*.xml' ],
include: ['**/*.svg', '**/*.xml'],
limit: 0,
fileName: '[name][extname]'
}),
html({ include: [
'src/editor/extensions/*/*.html'
] }),
html({
include: [
'src/editor/extensions/*/*.html'
]
}),
nodeResolve({
browser: true,
preferBuiltins: true
}),
commonjs({ exclude: `src/editor/extensions/${extensionName}/${extensionName}.js` }),
dynamicImportVars({ include: `src/editor/extensions/${extensionName}/${extensionName}.js` }),
babel({ babelHelpers: 'bundled', exclude: [ /\/core-js\// ] }),
babel({ babelHelpers: 'bundled', exclude: [/\/core-js\//] }),
nodePolyfills(),
terser({ keep_fnames: true })
]
}
);
});
)
})
export default config;
export default config

View File

@ -6,36 +6,36 @@
* @copyright 2010 Jeff Schiller, 2010 Alexis Deveria
*/
const NSSVG = 'http://www.w3.org/2000/svg';
const NSSVG = 'http://www.w3.org/2000/svg'
const { userAgent } = navigator;
const { userAgent } = navigator
// Note: Browser sniffing should only be used if no other detection method is possible
const isWebkit_ = userAgent.includes('AppleWebKit');
const isGecko_ = userAgent.includes('Gecko/');
const isChrome_ = userAgent.includes('Chrome/');
const isMac_ = userAgent.includes('Macintosh');
const isTouch_ = 'ontouchstart' in window;
const isWebkit_ = userAgent.includes('AppleWebKit')
const isGecko_ = userAgent.includes('Gecko/')
const isChrome_ = userAgent.includes('Chrome/')
const isMac_ = userAgent.includes('Macintosh')
const isTouch_ = 'ontouchstart' in window
// text character positioning (for IE9 and now Chrome)
const supportsGoodTextCharPos_ = (function () {
const svgroot = document.createElementNS(NSSVG, 'svg');
const svgContent = document.createElementNS(NSSVG, 'svg');
document.documentElement.append(svgroot);
svgContent.setAttribute('x', 5);
svgroot.append(svgContent);
const text = document.createElementNS(NSSVG, 'text');
text.textContent = 'a';
svgContent.append(text);
const svgroot = document.createElementNS(NSSVG, 'svg')
const svgContent = document.createElementNS(NSSVG, 'svg')
document.documentElement.append(svgroot)
svgContent.setAttribute('x', 5)
svgroot.append(svgContent)
const text = document.createElementNS(NSSVG, 'text')
text.textContent = 'a'
svgContent.append(text)
try { // Chrome now fails here
const pos = text.getStartPositionOfChar(0).x;
return (pos === 0);
const pos = text.getStartPositionOfChar(0).x
return (pos === 0)
} catch (err) {
return false;
return false
} finally {
svgroot.remove();
svgroot.remove()
}
}());
}())
// Public API
@ -43,31 +43,31 @@ const supportsGoodTextCharPos_ = (function () {
* @function module:browser.isWebkit
* @returns {boolean}
*/
export const isWebkit = () => isWebkit_;
export const isWebkit = () => isWebkit_
/**
* @function module:browser.isGecko
* @returns {boolean}
*/
export const isGecko = () => isGecko_;
export const isGecko = () => isGecko_
/**
* @function module:browser.isChrome
* @returns {boolean}
*/
export const isChrome = () => isChrome_;
export const isChrome = () => isChrome_
/**
* @function module:browser.isMac
* @returns {boolean}
*/
export const isMac = () => isMac_;
export const isMac = () => isMac_
/**
* @function module:browser.isTouch
* @returns {boolean}
*/
export const isTouch = () => isTouch_;
export const isTouch = () => isTouch_
/**
* @function module:browser.supportsGoodTextCharPos
* @returns {boolean}
*/
export const supportsGoodTextCharPos = () => supportsGoodTextCharPos_;
export const supportsGoodTextCharPos = () => supportsGoodTextCharPos_

View File

@ -6,17 +6,17 @@
* @copyright 2010 Alexis Deveria, 2010 Jeff Schiller
*/
const NSSVG = 'http://www.w3.org/2000/svg';
const NSSVG = 'http://www.w3.org/2000/svg'
const wAttrs = [ 'x', 'x1', 'cx', 'rx', 'width' ];
const hAttrs = [ 'y', 'y1', 'cy', 'ry', 'height' ];
const unitAttrs = [ 'r', 'radius', ...wAttrs, ...hAttrs ];
const wAttrs = ['x', 'x1', 'cx', 'rx', 'width']
const hAttrs = ['y', 'y1', 'cy', 'ry', 'height']
const unitAttrs = ['r', 'radius', ...wAttrs, ...hAttrs]
// Container of elements.
let elementContainer_;
let elementContainer_
// Stores mapping of unit type to user coordinates.
let typeMap_ = {};
let typeMap_ = {}
/**
* @interface module:units.ElementContainer
@ -63,20 +63,20 @@ let typeMap_ = {};
* @returns {void}
*/
export const init = function (elementContainer) {
elementContainer_ = elementContainer;
elementContainer_ = elementContainer
// Get correct em/ex values by creating a temporary SVG.
const svg = document.createElementNS(NSSVG, 'svg');
document.body.append(svg);
const rect = document.createElementNS(NSSVG, 'rect');
rect.setAttribute('width', '1em');
rect.setAttribute('height', '1ex');
rect.setAttribute('x', '1in');
svg.append(rect);
const bb = rect.getBBox();
svg.remove();
const svg = document.createElementNS(NSSVG, 'svg')
document.body.append(svg)
const rect = document.createElementNS(NSSVG, 'rect')
rect.setAttribute('width', '1em')
rect.setAttribute('height', '1ex')
rect.setAttribute('x', '1in')
svg.append(rect)
const bb = rect.getBBox()
svg.remove()
const inch = bb.x;
const inch = bb.x
typeMap_ = {
em: bb.width,
ex: bb.height,
@ -87,8 +87,8 @@ export const init = function (elementContainer) {
pc: inch / 6,
px: 1,
'%': 0
};
};
}
}
/**
* Group: Unit conversion functions.
@ -99,8 +99,8 @@ export const init = function (elementContainer) {
* @returns {module:units.TypeMap} The unit object with values for each unit
*/
export const getTypeMap = function () {
return typeMap_;
};
return typeMap_
}
/**
* @typedef {GenericArray} module:units.CompareNumbers
@ -119,15 +119,15 @@ export const getTypeMap = function () {
* with comma-separated floats
*/
export const shortFloat = function (val) {
const digits = elementContainer_.getRoundDigits();
const digits = elementContainer_.getRoundDigits()
if (!isNaN(val)) {
return Number(Number(val).toFixed(digits));
return Number(Number(val).toFixed(digits))
}
if (Array.isArray(val)) {
return shortFloat(val[0]) + ',' + shortFloat(val[1]);
return shortFloat(val[0]) + ',' + shortFloat(val[1])
}
return Number.parseFloat(val).toFixed(digits) - 0;
};
return Number.parseFloat(val).toFixed(digits) - 0
}
/**
* Converts the number to given unit or baseUnit.
@ -137,12 +137,12 @@ export const shortFloat = function (val) {
* @returns {Float}
*/
export const convertUnit = function (val, unit) {
unit = unit || elementContainer_.getBaseUnit();
unit = unit || elementContainer_.getBaseUnit()
// baseVal.convertToSpecifiedUnits(unitNumMap[unit]);
// const val = baseVal.valueInSpecifiedUnits;
// baseVal.convertToSpecifiedUnits(1);
return shortFloat(val / typeMap_[unit]);
};
return shortFloat(val / typeMap_[unit])
}
/**
* Sets an element's attribute based on the unit in its current value.
@ -185,19 +185,19 @@ export const setUnitAttr = function (elem, attr, val) {
// val += unit;
// }
// }
elem.setAttribute(attr, val);
};
elem.setAttribute(attr, val)
}
const attrsToConvert = {
line: [ 'x1', 'x2', 'y1', 'y2' ],
circle: [ 'cx', 'cy', 'r' ],
ellipse: [ 'cx', 'cy', 'rx', 'ry' ],
foreignObject: [ 'x', 'y', 'width', 'height' ],
rect: [ 'x', 'y', 'width', 'height' ],
image: [ 'x', 'y', 'width', 'height' ],
use: [ 'x', 'y', 'width', 'height' ],
text: [ 'x', 'y' ]
};
line: ['x1', 'x2', 'y1', 'y2'],
circle: ['cx', 'cy', 'r'],
ellipse: ['cx', 'cy', 'rx', 'ry'],
foreignObject: ['x', 'y', 'width', 'height'],
rect: ['x', 'y', 'width', 'height'],
image: ['x', 'y', 'width', 'height'],
use: ['x', 'y', 'width', 'height'],
text: ['x', 'y']
}
/**
* Converts all applicable attributes to the configured baseUnit.
@ -206,18 +206,18 @@ const attrsToConvert = {
* @returns {void}
*/
export const convertAttrs = function (element) {
const elName = element.tagName;
const unit = elementContainer_.getBaseUnit();
const attrs = attrsToConvert[elName];
if (!attrs) { return; }
const elName = element.tagName
const unit = elementContainer_.getBaseUnit()
const attrs = attrsToConvert[elName]
if (!attrs) { return }
attrs.forEach( (attr) => {
const cur = element.getAttribute(attr);
attrs.forEach((attr) => {
const cur = element.getAttribute(attr)
if (cur && !isNaN(cur)) {
element.setAttribute(attr, (cur / typeMap_[unit]) + unit);
element.setAttribute(attr, (cur / typeMap_[unit]) + unit)
}
});
};
})
}
/**
* Converts given values to numbers. Attributes must be supplied in
@ -230,26 +230,26 @@ export const convertAttrs = function (element) {
*/
export const convertToNum = function (attr, val) {
// Return a number if that's what it already is
if (!isNaN(val)) { return val - 0; }
if (!isNaN(val)) { return val - 0 }
if (val.substr(-1) === '%') {
// Deal with percentage, depends on attribute
const num = val.substr(0, val.length - 1) / 100;
const width = elementContainer_.getWidth();
const height = elementContainer_.getHeight();
const num = val.substr(0, val.length - 1) / 100
const width = elementContainer_.getWidth()
const height = elementContainer_.getHeight()
if (wAttrs.includes(attr)) {
return num * width;
return num * width
}
if (hAttrs.includes(attr)) {
return num * height;
return num * height
}
return num * Math.sqrt((width * width) + (height * height)) / Math.sqrt(2);
return num * Math.sqrt((width * width) + (height * height)) / Math.sqrt(2)
}
const unit = val.substr(-2);
const num = val.substr(0, val.length - 2);
const unit = val.substr(-2)
const num = val.substr(0, val.length - 2)
// Note that this multiplication turns the string into a number
return num * typeMap_[unit];
};
return num * typeMap_[unit]
}
/**
* Check if an attribute's value is in a valid format.
@ -263,29 +263,29 @@ export const isValidUnit = function (attr, val, selectedElement) {
if (unitAttrs.includes(attr)) {
// True if it's just a number
if (!isNaN(val)) {
return true;
return true
}
// Not a number, check if it has a valid unit
val = val.toLowerCase();
val = val.toLowerCase()
return Object.keys(typeMap_).some((unit) => {
const re = new RegExp('^-?[\\d\\.]+' + unit + '$');
return re.test(val);
});
const re = new RegExp('^-?[\\d\\.]+' + unit + '$')
return re.test(val)
})
}
if (attr === 'id') {
// if we're trying to change the id, make sure it's not already present in the doc
// and the id value is valid.
let result = false;
let result = false
// because getElem() can throw an exception in the case of an invalid id
// (according to https://www.w3.org/TR/xml-id/ IDs must be a NCName)
// we wrap it in an exception and only return true if the ID was valid and
// not already present
try {
const elem = elementContainer_.getElement(val);
result = (!elem || elem === selectedElement);
} catch (e) {/* empty fn */}
return result;
const elem = elementContainer_.getElement(val)
result = (!elem || elem === selectedElement)
} catch (e) { /* empty fn */ }
return result
}
return true;
};
return true
}

View File

@ -1,4 +1,4 @@
import { mergeDeep } from './components/jgraduate/Util.js';
import { mergeDeep } from './components/jgraduate/Util.js'
/**
* Escapes special characters in a regular expression.
@ -8,8 +8,8 @@ import { mergeDeep } from './components/jgraduate/Util.js';
*/
export const regexEscape = function (str) {
// Originally from: http://phpjs.org/functions
return String(str).replace(/[.\\+*?[^\]$(){}=!<>|:-]/g, '\\$&');
};
return String(str).replace(/[.\\+*?[^\]$(){}=!<>|:-]/g, '\\$&')
}
/**
* @class configObj
*/
@ -47,7 +47,7 @@ export default class ConfigObj {
// Only shows in UI as far as alert notices, but useful to remember, so keeping as pref
save_notice_done: false,
export_notice_done: false
};
}
/**
* @tutorial ConfigOptions
* @interface module:SVGEditor.Config
@ -134,7 +134,7 @@ export default class ConfigObj {
imgPath: './images',
// DOCUMENT PROPERTIES
// Change the following to a preference (already in the Document Properties dialog)?
dimensions: [ 640, 480 ],
dimensions: [640, 480],
// EDITOR OPTIONS
// Change the following to preferences (already in the Editor Options dialog)?
gridSnapping: false,
@ -158,13 +158,13 @@ export default class ConfigObj {
avoidClientSide: false, // Deprecated in favor of `avoidClientSideDownload`
avoidClientSideDownload: false,
avoidClientSideOpen: false
};
}
this.curPrefs = {};
this.curPrefs = {}
// Note: The difference between Prefs and Config is that Prefs
// can be changed in the UI and are stored in the browser,
// while config cannot
this.urldata = {};
this.urldata = {}
/**
* @name module:SVGEditor~defaultExtensions
* @type {string[]}
@ -182,7 +182,7 @@ export default class ConfigObj {
'ext-polystar',
'ext-storage',
'ext-opensave'
];
]
this.curConfig = {
// We do not put on defaultConfig to simplify object copying
// procedures (we obtain instead from defaultExtensions)
@ -203,61 +203,64 @@ export default class ConfigObj {
* @todo We might instead make as a user-facing preference.
*/
allowedOrigins: []
};
this.editor = editor;
}
this.editor = editor
}
/**
* @function setupCurPrefs
* @returns {void}
*/
setupCurPrefs () {
const curPrefs = { ...this.defaultPrefs, ...this.curPrefs }; // Now safe to merge with priority for curPrefs in the event any are already set
const curPrefs = { ...this.defaultPrefs, ...this.curPrefs } // Now safe to merge with priority for curPrefs in the event any are already set
// Export updated prefs
this.curPrefs = curPrefs;
this.curPrefs = curPrefs
}
/**
* Sets up current config based on defaults.
* @returns {void}
*/
setupCurConfig () {
const curConfig = { ...this.defaultConfig, ...this.curConfig }; // Now safe to merge with priority for curConfig in the event any are already set
const curConfig = { ...this.defaultConfig, ...this.curConfig } // Now safe to merge with priority for curConfig in the event any are already set
// Now deal with extensions and other array config
if (!curConfig.noDefaultExtensions) {
curConfig.extensions = [ ...this.defaultExtensions ];
curConfig.extensions = [...this.defaultExtensions]
}
// Export updated config
this.curConfig = curConfig;
this.curConfig = curConfig
}
/**
* @function loadFromURL Load config/data from URL if given
* @returns {void}
*/
loadFromURL () {
const self = this;
const { search, searchParams } = new URL(location);
const self = this
const { search, searchParams } = new URL(location)
if (search) {
this.urldata = {};
const entries = searchParams.entries();
for(const entry of entries) {
this.urldata[entry[0]] = entry[1];
this.urldata = {}
const entries = searchParams.entries()
for (const entry of entries) {
this.urldata[entry[0]] = entry[1]
}
[ 'initStroke', 'initFill' ].forEach((prop) => {
['initStroke', 'initFill'].forEach((prop) => {
if (searchParams.has(`${prop}[color]`)) {
// Restore back to original non-deparamed value to avoid color
// strings being converted to numbers
if(this.urldata[prop] === undefined) { this.urldata[prop] = {}; }
this.urldata[prop].color = searchParams.get(`${prop}[color]`);
if (this.urldata[prop] === undefined) { this.urldata[prop] = {} }
this.urldata[prop].color = searchParams.get(`${prop}[color]`)
}
});
})
if (searchParams.has('bkgd_color')) {
this.urldata.bkgd_color = '#' + searchParams.get('bkgd_color');
this.urldata.bkgd_color = '#' + searchParams.get('bkgd_color')
}
if (this.urldata.dimensions) {
this.urldata.dimensions = this.urldata.dimensions.split(',');
this.urldata.dimensions = this.urldata.dimensions.split(',')
}
if (this.urldata.extensions) {
@ -265,54 +268,55 @@ export default class ConfigObj {
// extensions via URL
this.urldata.extensions = (/[:/\\]/).test(this.urldata.extensions)
? ''
: this.urldata.extensions.split(',');
: this.urldata.extensions.split(',')
}
// Disallowing extension paths via URL for
// security reasons, even for same-domain
// ones given potential to interact in undesirable
// ways with other script resources
[ 'userExtensions', 'imgPath' ]
['userExtensions', 'imgPath']
.forEach(function (pathConfig) {
if (self.urldata[pathConfig]) {
delete self.urldata[pathConfig];
delete self.urldata[pathConfig]
}
});
})
// Note: `source` and `url` (as with `storagePrompt` later) are not
// set on config but are used below
this.setConfig(this.urldata, { overwrite: false });
this.setupCurConfig();
this.setConfig(this.urldata, { overwrite: false })
this.setupCurConfig()
if (!this.curConfig.preventURLContentLoading) {
let { source } = this.urldata;
let { source } = this.urldata
if (!source) { // urldata.source may have been null if it ended with '='
const src = searchParams.get('source');
const src = searchParams.get('source')
if (src && src.startsWith('data:')) {
source = src;
source = src
}
}
if (source) {
if (source.startsWith('data:')) {
this.editor.loadFromDataURI(source);
this.editor.loadFromDataURI(source)
} else {
this.editor.loadFromString(source);
this.editor.loadFromString(source)
}
return;
return
}
if (this.urldata.url) {
this.editor.loadFromURL(this.urldata.url);
return;
this.editor.loadFromURL(this.urldata.url)
return
}
}
if (!this.urldata.noStorageOnLoad || this.curConfig.forceStorage) {
this.loadContentAndPrefs();
this.loadContentAndPrefs()
}
} else {
this.setupCurConfig();
this.loadContentAndPrefs();
this.setupCurConfig()
this.loadContentAndPrefs()
}
}
/**
* Where permitted, sets canvas and/or `configObj.defaultPrefs` based on previous
* storage. This will override URL settings (for security reasons) but
@ -333,7 +337,7 @@ export default class ConfigObj {
!(/(?:^|;\s*)svgeditstore=(?:prefsAndContent|prefsOnly)/).test(document.cookie)
)
) {
return;
return
}
// LOAD CONTENT
@ -343,32 +347,32 @@ export default class ConfigObj {
(/(?:^|;\s*)svgeditstore=prefsAndContent/).test(document.cookie))
)
) {
const name = 'svgedit-' + this.curConfig.canvasName;
const cached = this.editor.storage.getItem(name);
const name = 'svgedit-' + this.curConfig.canvasName
const cached = this.editor.storage.getItem(name)
if (cached) {
this.editor.loadFromString(cached);
this.editor.loadFromString(cached)
}
}
// LOAD PREFS
Object.keys(this.defaultPrefs).forEach((key) => {
const storeKey = 'svg-edit-' + key;
const storeKey = 'svg-edit-' + key
if (this.editor.storage) {
const val = this.editor.storage.getItem(storeKey);
const val = this.editor.storage.getItem(storeKey)
if (val) {
this.defaultPrefs[key] = String(val); // Convert to string for FF (.value fails in Webkit)
this.defaultPrefs[key] = String(val) // Convert to string for FF (.value fails in Webkit)
}
} else if (window.widget) {
this.defaultPrefs[key] = window.widget.preferenceForKey(storeKey);
this.defaultPrefs[key] = window.widget.preferenceForKey(storeKey)
} else {
const result = document.cookie.match(
new RegExp('(?:^|;\\s*)' + regexEscape(
encodeURIComponent(storeKey)
) + '=([^;]+)')
);
this.defaultPrefs[key] = result ? decodeURIComponent(result[1]) : '';
)
this.defaultPrefs[key] = result ? decodeURIComponent(result[1]) : ''
}
});
})
}
/**
@ -402,61 +406,62 @@ export default class ConfigObj {
*/
const extendOrAdd = (cfgObj, key, val) => {
if (cfgObj[key] && typeof cfgObj[key] === 'object') {
cfgObj[key] = mergeDeep(cfgObj[key], val);
cfgObj[key] = mergeDeep(cfgObj[key], val)
} else {
cfgObj[key] = val;
cfgObj[key] = val
}
};
Object.entries(opts).forEach(([ key, val ]) => {
}
Object.entries(opts).forEach(([key, val]) => {
// Only allow prefs defined in configObj.defaultPrefs or...
if (this.defaultPrefs[key]) {
if (cfgCfg.overwrite === false && (
this.curConfig.preventAllURLConfig ||
this.curPrefs[key])
) {
return;
return
}
if (cfgCfg.allowInitialUserOverride === true) {
this.defaultPrefs[key] = val;
this.defaultPrefs[key] = val
} else {
this.pref(key, val);
this.pref(key, val)
}
} else if ([ 'extensions', 'userExtensions', 'allowedOrigins' ].includes(key)) {
} else if (['extensions', 'userExtensions', 'allowedOrigins'].includes(key)) {
if (cfgCfg.overwrite === false &&
(
this.curConfig.preventAllURLConfig ||
[ 'allowedOrigins' ].includes(key) ||
['allowedOrigins'].includes(key) ||
(key === 'extensions' && this.curConfig.lockExtensions)
)
) {
return;
return
}
this.curConfig[key] = this.curConfig[key].concat(val); // We will handle any dupes later
this.curConfig[key] = this.curConfig[key].concat(val) // We will handle any dupes later
// Only allow other configObj.curConfig if defined in configObj.defaultConfig
} else if ({}.hasOwnProperty.call(this.defaultConfig, key)) {
if (cfgCfg.overwrite === false && (
this.curConfig.preventAllURLConfig ||
{}.hasOwnProperty.call(this.curConfig, key)
)) {
return;
return
}
// Potentially overwriting of previously set config
if ({}.hasOwnProperty.call(this.curConfig, key)) {
if (cfgCfg.overwrite === false) {
return;
return
}
extendOrAdd(this.curConfig, key, val);
extendOrAdd(this.curConfig, key, val)
} else if (cfgCfg.allowInitialUserOverride === true) {
extendOrAdd(this.defaultConfig, key, val);
extendOrAdd(this.defaultConfig, key, val)
} else if (this.defaultConfig[key] && typeof this.defaultConfig[key] === 'object') {
this.curConfig[key] = Array.isArray(this.defaultConfig[key]) ? [] : {};
this.curConfig[key] = mergeDeep(this.curConfig[key], val);
this.curConfig[key] = Array.isArray(this.defaultConfig[key]) ? [] : {}
this.curConfig[key] = mergeDeep(this.curConfig[key], val)
} else {
this.curConfig[key] = val;
this.curConfig[key] = val
}
}
});
})
}
/**
* Store and retrieve preferences.
* @function pref
@ -475,17 +480,18 @@ export default class ConfigObj {
*/
pref (key, val, mayBeEmpty) {
if (mayBeEmpty || val) {
this.curPrefs[key] = val;
return undefined;
this.curPrefs[key] = val
return undefined
}
return (key in this.curPrefs) ? this.curPrefs[key] : this.defaultPrefs[key];
return (key in this.curPrefs) ? this.curPrefs[key] : this.defaultPrefs[key]
}
/**
* @function load load Config
* @returns {void}
*/
load () {
this.loadFromURL(this.editor);
this.setupCurPrefs(this.editor);
this.loadFromURL(this.editor)
this.setupCurPrefs(this.editor)
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
/* globals seConfirm, seAlert */
import SvgCanvas from "../svgcanvas/svgcanvas.js";
import { convertUnit, isValidUnit } from '../common/units.js';
import { isChrome } from '../common/browser.js';
import SvgCanvas from '../svgcanvas/svgcanvas.js'
import { convertUnit, isValidUnit } from '../common/units.js'
import { isChrome } from '../common/browser.js'
const { $id } = SvgCanvas;
const homePage = 'https://github.com/SVG-Edit/svgedit';
const { $id } = SvgCanvas
const homePage = 'https://github.com/SVG-Edit/svgedit'
/**
*
@ -13,89 +13,91 @@ class MainMenu {
/**
* @param {PlainObject} editor svgedit handler
*/
constructor(editor) {
this.editor = editor;
constructor (editor) {
this.editor = editor
/**
* @type {Integer}
*/
this.exportWindowCt = 0;
this.exportWindowCt = 0
}
/**
* @fires module:svgcanvas.SvgCanvas#event:ext_onNewDocument
* @returns {void}
*/
async clickClear() {
const [ x, y ] = this.editor.configObj.curConfig.dimensions;
const ok = await seConfirm(this.editor.i18next.t('notification.QwantToClear'));
if (ok === "Cancel") {
return;
async clickClear () {
const [x, y] = this.editor.configObj.curConfig.dimensions
const ok = await seConfirm(this.editor.i18next.t('notification.QwantToClear'))
if (ok === 'Cancel') {
return
}
this.editor.leftPanel.clickSelect();
this.editor.svgCanvas.clear();
this.editor.svgCanvas.setResolution(x, y);
this.editor.updateCanvas(true);
this.editor.zoomImage();
this.editor.layersPanel.populateLayers();
this.editor.topPanel.updateContextPanel();
this.editor.svgCanvas.runExtensions("onNewDocument");
}
/**
*
* @returns {void}
*/
hideDocProperties() {
const $imgDialog = $id("se-img-prop");
$imgDialog.setAttribute("dialog", "close");
$imgDialog.setAttribute("save", this.editor.configObj.pref("img_save"));
this.editor.docprops = false;
this.editor.leftPanel.clickSelect()
this.editor.svgCanvas.clear()
this.editor.svgCanvas.setResolution(x, y)
this.editor.updateCanvas(true)
this.editor.zoomImage()
this.editor.layersPanel.populateLayers()
this.editor.topPanel.updateContextPanel()
this.editor.svgCanvas.runExtensions('onNewDocument')
}
/**
*
* @returns {void}
*/
hidePreferences() {
const $editDialog = $id("se-edit-prefs");
$editDialog.setAttribute("dialog", "close");
this.editor.configObj.preferences = false;
hideDocProperties () {
const $imgDialog = $id('se-img-prop')
$imgDialog.setAttribute('dialog', 'close')
$imgDialog.setAttribute('save', this.editor.configObj.pref('img_save'))
this.editor.docprops = false
}
/**
*
* @returns {void}
*/
hidePreferences () {
const $editDialog = $id('se-edit-prefs')
$editDialog.setAttribute('dialog', 'close')
this.editor.configObj.preferences = false
}
/**
* @param {Event} e
* @returns {boolean} Whether there were problems saving the document properties
*/
saveDocProperties(e) {
saveDocProperties (e) {
// set title
const { title, w, h, save } = e.detail;
const { title, w, h, save } = e.detail
// set document title
this.editor.svgCanvas.setDocumentTitle(title);
this.editor.svgCanvas.setDocumentTitle(title)
if (w !== "fit" && !isValidUnit("width", w)) {
seAlert(this.editor.i18next.t('notification.invalidAttrValGiven'));
return false;
if (w !== 'fit' && !isValidUnit('width', w)) {
seAlert(this.editor.i18next.t('notification.invalidAttrValGiven'))
return false
}
if (h !== "fit" && !isValidUnit("height", h)) {
seAlert(this.editor.i18next.t('notification.invalidAttrValGiven'));
return false;
if (h !== 'fit' && !isValidUnit('height', h)) {
seAlert(this.editor.i18next.t('notification.invalidAttrValGiven'))
return false
}
if (!this.editor.svgCanvas.setResolution(w, h)) {
seAlert(this.editor.i18next.t('notification.noContentToFitTo'));
return false;
seAlert(this.editor.i18next.t('notification.noContentToFitTo'))
return false
}
// Set image save option
this.editor.configObj.pref("img_save", save);
this.editor.updateCanvas();
this.hideDocProperties();
return true;
this.editor.configObj.pref('img_save', save)
this.editor.updateCanvas()
this.hideDocProperties()
return true
}
/**
* Save user preferences based on current values in the UI.
* @param {Event} e
* @function module:SVGthis.savePreferences
* @returns {Promise<void>}
*/
async savePreferences(e) {
async savePreferences (e) {
const {
lang,
bgcolor,
@ -105,57 +107,58 @@ class MainMenu {
gridcolor,
showrulers,
baseunit
} = e.detail;
} = e.detail
// Set background
this.editor.setBackground(bgcolor, bgurl);
this.editor.setBackground(bgcolor, bgurl)
// set language
if (lang && lang !== this.editor.configObj.pref("lang")) {
this.editor.configObj.pref("lang", lang);
seAlert('Changing the language needs reload');
if (lang && lang !== this.editor.configObj.pref('lang')) {
this.editor.configObj.pref('lang', lang)
seAlert('Changing the language needs reload')
}
// set grid setting
this.editor.configObj.curConfig.gridSnapping = gridsnappingon;
this.editor.configObj.curConfig.snappingStep = gridsnappingstep;
this.editor.configObj.curConfig.gridColor = gridcolor;
this.editor.configObj.curConfig.showRulers = showrulers;
this.editor.configObj.curConfig.gridSnapping = gridsnappingon
this.editor.configObj.curConfig.snappingStep = gridsnappingstep
this.editor.configObj.curConfig.gridColor = gridcolor
this.editor.configObj.curConfig.showRulers = showrulers
if (this.editor.configObj.curConfig.showRulers) {
this.editor.rulers.updateRulers();
this.editor.rulers.updateRulers()
}
this.editor.configObj.curConfig.baseUnit = baseunit;
this.editor.svgCanvas.setConfig(this.editor.configObj.curConfig);
this.editor.updateCanvas();
this.hidePreferences();
this.editor.configObj.curConfig.baseUnit = baseunit
this.editor.svgCanvas.setConfig(this.editor.configObj.curConfig)
this.editor.updateCanvas()
this.hidePreferences()
}
/**
*
* @param e
* @returns {Promise<void>} Resolves to `undefined`
*/
async clickExport(e) {
if (e?.detail?.trigger !== "ok" || e?.detail?.imgType === undefined) {
return;
async clickExport (e) {
if (e?.detail?.trigger !== 'ok' || e?.detail?.imgType === undefined) {
return
}
const imgType = e?.detail?.imgType;
const quality = e?.detail?.quality ? e?.detail?.quality / 100 : 1;
const imgType = e?.detail?.imgType
const quality = e?.detail?.quality ? e?.detail?.quality / 100 : 1
// Open placeholder window (prevents popup)
let exportWindowName;
let exportWindowName
/**
*
* @returns {void}
*/
const openExportWindow = () => {
const loadingImage = this.editor.i18next.t('notification.loadingImage');
if (this.editor.configObj.curConfig.exportWindowType === "new") {
this.editor.exportWindowCt++;
const loadingImage = this.editor.i18next.t('notification.loadingImage')
if (this.editor.configObj.curConfig.exportWindowType === 'new') {
this.editor.exportWindowCt++
}
this.editor.exportWindowName =
this.editor.configObj.curConfig.canvasName + this.editor.exportWindowCt;
let popHTML; let popURL;
this.editor.configObj.curConfig.canvasName + this.editor.exportWindowCt
let popHTML; let popURL
if (this.editor.loadingURL) {
popURL = this.editor.loadingURL;
popURL = this.editor.loadingURL
} else {
popHTML = `<!DOCTYPE html><html>
<head>
@ -163,35 +166,35 @@ class MainMenu {
<title>${loadingImage}</title>
</head>
<body><h1>${loadingImage}</h1></body>
<html>`;
if (typeof URL !== "undefined" && URL.createObjectURL) {
const blob = new Blob([ popHTML ], { type: "text/html" });
popURL = URL.createObjectURL(blob);
<html>`
if (typeof URL !== 'undefined' && URL.createObjectURL) {
const blob = new Blob([popHTML], { type: 'text/html' })
popURL = URL.createObjectURL(blob)
} else {
popURL = "data:text/html;base64;charset=utf-8," + popHTML;
popURL = 'data:text/html;base64;charset=utf-8,' + popHTML
}
this.editor.loadingURL = popURL;
this.editor.loadingURL = popURL
}
this.editor.exportWindow = window.open(
popURL,
this.editor.exportWindowName
);
};
const chrome = isChrome();
if (imgType === "PDF") {
)
}
const chrome = isChrome()
if (imgType === 'PDF') {
if (!this.editor.customExportPDF && !chrome) {
openExportWindow();
openExportWindow()
}
this.editor.svgCanvas.exportPDF(exportWindowName);
this.editor.svgCanvas.exportPDF(exportWindowName)
} else {
if (!this.editor.customExportImage) {
openExportWindow();
openExportWindow()
}
/* const results = */ await this.editor.svgCanvas.rasterExport(
imgType,
quality,
this.editor.exportWindowName
);
)
}
}
@ -199,129 +202,129 @@ class MainMenu {
*
* @returns {void}
*/
showDocProperties() {
showDocProperties () {
if (this.editor.docprops) {
return;
return
}
this.editor.docprops = true;
const $imgDialog = $id("se-img-prop");
this.editor.docprops = true
const $imgDialog = $id('se-img-prop')
// update resolution option with actual resolution
const resolution = this.editor.svgCanvas.getResolution();
if (this.editor.configObj.curConfig.baseUnit !== "px") {
const resolution = this.editor.svgCanvas.getResolution()
if (this.editor.configObj.curConfig.baseUnit !== 'px') {
resolution.w =
convertUnit(resolution.w) + this.editor.configObj.curConfig.baseUnit;
convertUnit(resolution.w) + this.editor.configObj.curConfig.baseUnit
resolution.h =
convertUnit(resolution.h) + this.editor.configObj.curConfig.baseUnit;
convertUnit(resolution.h) + this.editor.configObj.curConfig.baseUnit
}
$imgDialog.setAttribute("save", this.editor.configObj.pref("img_save"));
$imgDialog.setAttribute("width", resolution.w);
$imgDialog.setAttribute("height", resolution.h);
$imgDialog.setAttribute("title", this.editor.svgCanvas.getDocumentTitle());
$imgDialog.setAttribute("dialog", "open");
$imgDialog.setAttribute('save', this.editor.configObj.pref('img_save'))
$imgDialog.setAttribute('width', resolution.w)
$imgDialog.setAttribute('height', resolution.h)
$imgDialog.setAttribute('title', this.editor.svgCanvas.getDocumentTitle())
$imgDialog.setAttribute('dialog', 'open')
}
/**
*
* @returns {void}
*/
showPreferences() {
showPreferences () {
if (this.editor.configObj.preferences) {
return;
return
}
this.editor.configObj.preferences = true;
const $editDialog = $id("se-edit-prefs");
this.editor.configObj.preferences = true
const $editDialog = $id('se-edit-prefs')
// Update background color with current one
const canvasBg = this.editor.configObj.curPrefs.bkgd_color;
const url = this.editor.configObj.pref("bkgd_url");
const canvasBg = this.editor.configObj.curPrefs.bkgd_color
const url = this.editor.configObj.pref('bkgd_url')
if (url) {
$editDialog.setAttribute("bgurl", url);
$editDialog.setAttribute('bgurl', url)
}
$editDialog.setAttribute(
"gridsnappingon",
'gridsnappingon',
this.editor.configObj.curConfig.gridSnapping
);
)
$editDialog.setAttribute(
"gridsnappingstep",
'gridsnappingstep',
this.editor.configObj.curConfig.snappingStep
);
)
$editDialog.setAttribute(
"gridcolor",
'gridcolor',
this.editor.configObj.curConfig.gridColor
);
$editDialog.setAttribute("canvasbg", canvasBg);
$editDialog.setAttribute("dialog", "open");
)
$editDialog.setAttribute('canvasbg', canvasBg)
$editDialog.setAttribute('dialog', 'open')
}
/**
*
* @returns {void}
*/
openHomePage() {
window.open(homePage, "_blank");
openHomePage () {
window.open(homePage, '_blank')
}
/**
* @type {module}
*/
init() {
init () {
// add Top panel
const template = document.createElement("template");
const template = document.createElement('template')
template.innerHTML = `
<se-menu id="main_button" label="SVG-Edit" src="logo.svg" alt="logo">
<se-menu-item id="tool_export" label="tools.export_img" src="export.svg"></se-menu-item>
<se-menu-item id="tool_docprops" label="tools.docprops" shortcut="D" src="docprop.svg"></se-menu-item>
<se-menu-item id="tool_editor_prefs" label="config.editor_prefs" src="editPref.svg"></se-menu-item>
<se-menu-item id="tool_editor_homepage" label="tools.editor_homepage" src="logo.svg"></se-menu-item>
</se-menu>`;
this.editor.$svgEditor.append(template.content.cloneNode(true));
</se-menu>`
this.editor.$svgEditor.append(template.content.cloneNode(true))
// register action to main menu entries
/**
* Associate all button actions as well as non-button keyboard shortcuts.
*/
$id("tool_export").addEventListener("click", function() {
$id('tool_export').addEventListener('click', function () {
document
.getElementById("se-export-dialog")
.setAttribute("dialog", "open");
});
$id("se-export-dialog").addEventListener(
"change",
.getElementById('se-export-dialog')
.setAttribute('dialog', 'open')
})
$id('se-export-dialog').addEventListener(
'change',
this.clickExport.bind(this)
);
$id("tool_docprops").addEventListener(
"click",
)
$id('tool_docprops').addEventListener(
'click',
this.showDocProperties.bind(this)
);
$id("tool_editor_prefs").addEventListener(
"click",
)
$id('tool_editor_prefs').addEventListener(
'click',
this.showPreferences.bind(this)
);
$id("tool_editor_homepage").addEventListener(
"click",
)
$id('tool_editor_homepage').addEventListener(
'click',
this.openHomePage.bind(this)
);
$id("se-img-prop").addEventListener(
"change",
function(e) {
if (e.detail.dialog === "closed") {
this.hideDocProperties();
)
$id('se-img-prop').addEventListener(
'change',
function (e) {
if (e.detail.dialog === 'closed') {
this.hideDocProperties()
} else {
this.saveDocProperties(e);
this.saveDocProperties(e)
}
}.bind(this)
);
$id("se-edit-prefs").addEventListener(
"change",
function(e) {
if (e.detail.dialog === "closed") {
this.hidePreferences();
)
$id('se-edit-prefs').addEventListener(
'change',
function (e) {
if (e.detail.dialog === 'closed') {
this.hidePreferences()
} else {
this.savePreferences(e);
this.savePreferences(e)
}
}.bind(this)
);
)
}
}
export default MainMenu;
export default MainMenu

View File

@ -1,6 +1,6 @@
import { getTypeMap } from '../common/units.js';
import rulersTemplate from './templates/rulersTemplate.html';
import SvgCanvas from '../svgcanvas/svgcanvas.js';
import { getTypeMap } from '../common/units.js'
import rulersTemplate from './templates/rulersTemplate.html'
import SvgCanvas from '../svgcanvas/svgcanvas.js'
/**
*
*/
@ -10,41 +10,42 @@ class Rulers {
*/
constructor (editor) {
// Make [1,2,5] array
this.rulerIntervals = [];
this.rulerIntervals = []
for (let i = 0.1; i < 1e5; i *= 10) {
this.rulerIntervals.push(i);
this.rulerIntervals.push(2 * i);
this.rulerIntervals.push(5 * i);
this.rulerIntervals.push(i)
this.rulerIntervals.push(2 * i)
this.rulerIntervals.push(5 * i)
}
this.svgCanvas = editor.svgCanvas;
this.editor = editor;
this.svgCanvas = editor.svgCanvas
this.editor = editor
// add rulers component to the DOM
const template = document.createElement('template');
// eslint-disable-next-line no-unsanitized/property
template.innerHTML = rulersTemplate;
this.editor.$svgEditor.append(template.content.cloneNode(true));
const { $id } = SvgCanvas;
this.rulerX = $id('ruler_x');
this.rulerY = $id('ruler_y');
this.rulerCorner = $id('ruler_corner');
const template = document.createElement('template')
template.innerHTML = rulersTemplate
this.editor.$svgEditor.append(template.content.cloneNode(true))
const { $id } = SvgCanvas
this.rulerX = $id('ruler_x')
this.rulerY = $id('ruler_y')
this.rulerCorner = $id('ruler_corner')
}
display (on) {
if (on) {
this.rulerX.style.removeProperty('display');
this.rulerY.style.removeProperty('display');
this.rulerCorner.style.removeProperty('display');
this.rulerX.style.removeProperty('display')
this.rulerY.style.removeProperty('display')
this.rulerCorner.style.removeProperty('display')
} else {
this.rulerX.style.display = 'none';
this.rulerY.style.display = 'none';
this.rulerCorner.style.display = 'none';
this.rulerX.style.display = 'none'
this.rulerY.style.display = 'none'
this.rulerCorner.style.display = 'none'
}
}
/**
* @type {Module}
*/
manageScroll () {
if (this.rulerX) this.rulerX.scrollLeft = this.editor.workarea.scrollLeft;
if (this.rulerY) this.rulerY.scrollTop = this.editor.workarea.scrollTop;
if (this.rulerX) this.rulerX.scrollLeft = this.editor.workarea.scrollLeft
if (this.rulerY) this.rulerY.scrollTop = this.editor.workarea.scrollTop
}
/**
@ -54,165 +55,165 @@ class Rulers {
* @returns {void}
*/
updateRulers (scanvas, zoom) {
if (!zoom) { zoom = this.svgCanvas.getZoom(); }
if (!scanvas) { scanvas = document.getElementById('svgcanvas'); }
if (!zoom) { zoom = this.svgCanvas.getZoom() }
if (!scanvas) { scanvas = document.getElementById('svgcanvas') }
let d; let i;
const limit = 30000;
const contentElem = this.svgCanvas.getSvgContent();
const units = getTypeMap();
const unit = units[this.editor.configObj.curConfig.baseUnit]; // 1 = 1px
let d; let i
const limit = 30000
const contentElem = this.svgCanvas.getSvgContent()
const units = getTypeMap()
const unit = units[this.editor.configObj.curConfig.baseUnit] // 1 = 1px
// draw x ruler then y ruler
for (d = 0; d < 2; d++) {
const isX = (d === 0);
const dim = isX ? 'x' : 'y';
const lentype = isX ? 'width' : 'height';
const contentDim = Number(contentElem.getAttribute(dim));
const { $id } = SvgCanvas;
const $hcanvOrig = $id('ruler_' + dim).querySelector('canvas');
const isX = (d === 0)
const dim = isX ? 'x' : 'y'
const lentype = isX ? 'width' : 'height'
const contentDim = Number(contentElem.getAttribute(dim))
const { $id } = SvgCanvas
const $hcanvOrig = $id('ruler_' + dim).querySelector('canvas')
// Bit of a hack to fully clear the canvas in Safari & IE9
const $hcanv = $hcanvOrig.cloneNode(true);
$hcanvOrig.replaceWith($hcanv);
const $hcanv = $hcanvOrig.cloneNode(true)
$hcanvOrig.replaceWith($hcanv)
const hcanv = $hcanv;
const hcanv = $hcanv
// Set the canvas size to the width of the container
let rulerLen;
if(lentype === 'width'){
rulerLen = parseFloat(getComputedStyle(scanvas, null).width.replace("px", ""));
} else if(lentype === 'height'){
rulerLen = parseFloat(getComputedStyle(scanvas, null).height.replace("px", ""));
let rulerLen
if (lentype === 'width') {
rulerLen = parseFloat(getComputedStyle(scanvas, null).width.replace('px', ''))
} else if (lentype === 'height') {
rulerLen = parseFloat(getComputedStyle(scanvas, null).height.replace('px', ''))
}
const totalLen = rulerLen;
hcanv.parentNode.style[lentype] = totalLen + 'px';
let ctx = hcanv.getContext('2d');
let ctxArr; let num; let ctxArrNum;
const totalLen = rulerLen
hcanv.parentNode.style[lentype] = totalLen + 'px'
let ctx = hcanv.getContext('2d')
let ctxArr; let num; let ctxArrNum
ctx.fillStyle = 'rgb(200,0,0)';
ctx.fillRect(0, 0, hcanv.width, hcanv.height);
ctx.fillStyle = 'rgb(200,0,0)'
ctx.fillRect(0, 0, hcanv.width, hcanv.height)
// Remove any existing canvasses
const elements = Array.prototype.filter.call($hcanv.parentNode.children, function(child){
return child !== $hcanv;
});
Array.from(elements).forEach(function(element) {
element.remove();
});
const elements = Array.prototype.filter.call($hcanv.parentNode.children, function (child) {
return child !== $hcanv
})
Array.from(elements).forEach(function (element) {
element.remove()
})
// Create multiple canvases when necessary (due to browser limits)
if (rulerLen >= limit) {
ctxArrNum = Number.parseInt(rulerLen / limit) + 1;
ctxArr = [];
ctxArr[0] = ctx;
let copy;
ctxArrNum = Number.parseInt(rulerLen / limit) + 1
ctxArr = []
ctxArr[0] = ctx
let copy
for (i = 1; i < ctxArrNum; i++) {
hcanv[lentype] = limit;
copy = hcanv.cloneNode(true);
hcanv.parentNode.append(copy);
ctxArr[i] = copy.getContext('2d');
hcanv[lentype] = limit
copy = hcanv.cloneNode(true)
hcanv.parentNode.append(copy)
ctxArr[i] = copy.getContext('2d')
}
copy[lentype] = rulerLen % limit;
copy[lentype] = rulerLen % limit
// set copy width to last
rulerLen = limit;
rulerLen = limit
}
hcanv[lentype] = rulerLen;
hcanv[lentype] = rulerLen
const uMulti = unit * zoom;
const uMulti = unit * zoom
// Calculate the main number interval
const rawM = 50 / uMulti;
let multi = 1;
const rawM = 50 / uMulti
let multi = 1
for (i = 0; i < this.rulerIntervals.length; i++) {
num = this.rulerIntervals[i];
multi = num;
num = this.rulerIntervals[i]
multi = num
if (rawM <= num) {
break;
break
}
}
const bigInt = multi * uMulti;
const bigInt = multi * uMulti
ctx.font = '9px sans-serif';
ctx.font = '9px sans-serif'
let rulerD = ((contentDim / uMulti) % multi) * uMulti;
let labelPos = rulerD - bigInt;
let rulerD = ((contentDim / uMulti) % multi) * uMulti
let labelPos = rulerD - bigInt
// draw big intervals
let ctxNum = 0;
let ctxNum = 0
while (rulerD < totalLen) {
labelPos += bigInt;
labelPos += bigInt
// const realD = rulerD - contentDim; // Currently unused
const curD = Math.round(rulerD) + 0.5;
const curD = Math.round(rulerD) + 0.5
if (isX) {
ctx.moveTo(curD, 15);
ctx.lineTo(curD, 0);
ctx.moveTo(curD, 15)
ctx.lineTo(curD, 0)
} else {
ctx.moveTo(15, curD);
ctx.lineTo(0, curD);
ctx.moveTo(15, curD)
ctx.lineTo(0, curD)
}
num = (labelPos - contentDim) / uMulti;
let label;
num = (labelPos - contentDim) / uMulti
let label
if (multi >= 1) {
label = Math.round(num);
label = Math.round(num)
} else {
const decs = String(multi).split('.')[1].length;
label = num.toFixed(decs);
const decs = String(multi).split('.')[1].length
label = num.toFixed(decs)
}
// Change 1000s to Ks
if (label !== 0 && label !== 1000 && label % 1000 === 0) {
label = (label / 1000) + 'K';
label = (label / 1000) + 'K'
}
if (isX) {
ctx.fillText(label, rulerD + 2, 8);
ctx.fillText(label, rulerD + 2, 8)
} else {
// draw label vertically
const str = String(label).split('');
const str = String(label).split('')
for (i = 0; i < str.length; i++) {
ctx.fillText(str[i], 1, (rulerD + 9) + i * 9);
ctx.fillText(str[i], 1, (rulerD + 9) + i * 9)
}
}
const part = bigInt / 10;
const part = bigInt / 10
// draw the small intervals
for (i = 1; i < 10; i++) {
let subD = Math.round(rulerD + part * i) + 0.5;
let subD = Math.round(rulerD + part * i) + 0.5
if (ctxArr && subD > rulerLen) {
ctxNum++;
ctx.stroke();
ctxNum++
ctx.stroke()
if (ctxNum >= ctxArrNum) {
i = 10;
rulerD = totalLen;
continue;
i = 10
rulerD = totalLen
continue
}
ctx = ctxArr[ctxNum];
rulerD -= limit;
subD = Math.round(rulerD + part * i) + 0.5;
ctx = ctxArr[ctxNum]
rulerD -= limit
subD = Math.round(rulerD + part * i) + 0.5
}
// odd lines are slighly longer
const lineNum = (i % 2) ? 12 : 10;
const lineNum = (i % 2) ? 12 : 10
if (isX) {
ctx.moveTo(subD, 15);
ctx.lineTo(subD, lineNum);
ctx.moveTo(subD, 15)
ctx.lineTo(subD, lineNum)
} else {
ctx.moveTo(15, subD);
ctx.lineTo(lineNum, subD);
ctx.moveTo(15, subD)
ctx.lineTo(lineNum, subD)
}
}
rulerD += bigInt;
rulerD += bigInt
}
ctx.strokeStyle = '#000';
ctx.stroke();
ctx.strokeStyle = '#000'
ctx.stroke()
}
}
}
export default Rulers;
export default Rulers

View File

@ -1,8 +1,8 @@
const supportsSvg = function () {
return Boolean(document.createElementNS && document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect);
};
return Boolean(document.createElementNS && document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect)
}
if (!supportsSvg()) {
window.location = './browser-not-supported.html';
window.location = './browser-not-supported.html'
}
export {};
export {}

View File

@ -1,4 +1,4 @@
import { jGraduate } from './jgraduate/jQuery.jGraduate.js';
import { jGraduate } from './jgraduate/jQuery.jGraduate.js'
/**
*
*/
@ -16,17 +16,17 @@ class PaintBox {
<defs><linearGradient id="gradbox_${PaintBox.ctr++}"/></defs>
</svg>`,
'text/xml'
);
)
let docElem = svgdocbox.documentElement;
docElem = document.importNode(docElem, true);
container.appendChild(docElem);
let docElem = svgdocbox.documentElement
docElem = document.importNode(docElem, true)
container.appendChild(docElem)
this.rect = docElem.firstElementChild;
this.defs = docElem.getElementsByTagName('defs')[0];
this.grad = this.defs.firstElementChild;
this.rect = docElem.firstElementChild
this.defs = docElem.getElementsByTagName('defs')[0]
this.grad = this.defs.firstElementChild
// this.paint = new $.jGraduate.Paint({solidColor: color});
this.type = type;
this.type = type
}
/**
@ -34,30 +34,31 @@ class PaintBox {
* @returns {void}
*/
setPaint (paint) {
this.paint = paint;
this.paint = paint
const ptype = paint.type;
const opac = paint.alpha / 100;
const ptype = paint.type
const opac = paint.alpha / 100
let fillAttr = 'none';
let fillAttr = 'none'
switch (ptype) {
case 'solidColor':
fillAttr = (paint[ptype] !== 'none') ? '#' + paint[ptype] : paint[ptype];
break;
case 'linearGradient':
case 'radialGradient': {
this.grad.remove();
this.grad = paint[ptype];
this.defs.appendChild(this.grad);
const id = this.grad.id = 'gradbox_' + this.type;
fillAttr = 'url(#' + id + ')';
break;
}
case 'solidColor':
fillAttr = (paint[ptype] !== 'none') ? '#' + paint[ptype] : paint[ptype]
break
case 'linearGradient':
case 'radialGradient': {
this.grad.remove()
this.grad = paint[ptype]
this.defs.appendChild(this.grad)
const id = this.grad.id = 'gradbox_' + this.type
fillAttr = 'url(#' + id + ')'
break
}
}
this.rect.setAttribute('fill', fillAttr);
this.rect.setAttribute('opacity', opac);
this.rect.setAttribute('fill', fillAttr)
this.rect.setAttribute('opacity', opac)
}
/**
* @param {PlainObject} svgCanvas
* @param {string} color
@ -67,20 +68,20 @@ class PaintBox {
*/
static getPaint (svgCanvas, color, opac, type) {
// update the editor's fill paint
const opts = { alpha: opac };
const opts = { alpha: opac }
if (color.startsWith('url(#')) {
let refElem = svgCanvas.getRefElem(color);
refElem = (refElem) ? refElem.cloneNode(true) : document.querySelectorAll('#' + type + '_color defs *')[0];
let refElem = svgCanvas.getRefElem(color)
refElem = (refElem) ? refElem.cloneNode(true) : document.querySelectorAll('#' + type + '_color defs *')[0]
if (!refElem) {
console.error(`the color ${color} is referenced by an url that can't be identified - using 'none'`);
opts.solidColor = 'none';
console.error(`the color ${color} is referenced by an url that can't be identified - using 'none'`)
opts.solidColor = 'none'
} else {
opts[refElem.tagName] = refElem;
opts[refElem.tagName] = refElem
}
} else if (color.startsWith('#')) {
opts.solidColor = color.substr(1);
opts.solidColor = color.substr(1)
}
return new jGraduate.Paint(opts);
return new jGraduate.Paint(opts)
}
/**
@ -89,59 +90,59 @@ class PaintBox {
* @returns {any}
*/
update (svgcanvas, selectedElement) {
if (!selectedElement) { return null; }
if (!selectedElement) { return null }
const { type } = this;
const { type } = this
switch (selectedElement.tagName) {
case 'use':
case 'image':
case 'foreignObject':
case 'use':
case 'image':
case 'foreignObject':
// These elements don't have fill or stroke, so don't change
// the current value
return null;
case 'g':
case 'a': {
const childs = selectedElement.getElementsByTagName('*');
return null
case 'g':
case 'a': {
const childs = selectedElement.getElementsByTagName('*')
let gPaint = null;
for (let i = 0, len = childs.length; i < len; i++) {
const elem = childs[i];
const p = elem.getAttribute(type);
if (i === 0) {
gPaint = p;
} else if (gPaint !== p) {
gPaint = null;
break;
let gPaint = null
for (let i = 0, len = childs.length; i < len; i++) {
const elem = childs[i]
const p = elem.getAttribute(type)
if (i === 0) {
gPaint = p
} else if (gPaint !== p) {
gPaint = null
break
}
}
}
if (gPaint === null) {
if (gPaint === null) {
// No common color, don't update anything
this._paintColor = null;
return null;
}
this._paintColor = gPaint;
this._paintOpacity = 1;
break;
} default: {
this._paintOpacity = Number.parseFloat(selectedElement.getAttribute(type + '-opacity'));
if (Number.isNaN(this._paintOpacity)) {
this._paintOpacity = 1.0;
}
this._paintColor = null
return null
}
this._paintColor = gPaint
this._paintOpacity = 1
break
} default: {
this._paintOpacity = Number.parseFloat(selectedElement.getAttribute(type + '-opacity'))
if (Number.isNaN(this._paintOpacity)) {
this._paintOpacity = 1.0
}
const defColor = type === 'fill' ? 'black' : 'none';
this._paintColor = selectedElement.getAttribute(type) || defColor;
}
const defColor = type === 'fill' ? 'black' : 'none'
this._paintColor = selectedElement.getAttribute(type) || defColor
}
}
this._paintOpacity *= 100;
this._paintOpacity *= 100
const paint = PaintBox.getPaint(svgcanvas, this._paintColor, this._paintOpacity, type);
const paint = PaintBox.getPaint(svgcanvas, this._paintColor, this._paintOpacity, type)
// update the rect inside #fill_color/#stroke_color
this.setPaint(paint);
return (paint);
this.setPaint(paint)
return (paint)
}
}
PaintBox.ctr = 0;
PaintBox.ctr = 0
export default PaintBox;
export default PaintBox

View File

@ -1,15 +1,14 @@
import './seButton.js';
import './seFlyingButton.js';
import './seExplorerButton.js';
import './seZoom.js';
import './seInput.js';
import './seSpinInput.js';
import './sePalette.js';
import './seMenu.js';
import './seMenuItem.js';
import './seList.js';
import './seListItem.js';
import './seColorPicker.js';
import './seSelect.js';
import './seText.js';
import './seButton.js'
import './seFlyingButton.js'
import './seExplorerButton.js'
import './seZoom.js'
import './seInput.js'
import './seSpinInput.js'
import './sePalette.js'
import './seMenu.js'
import './seMenuItem.js'
import './seList.js'
import './seListItem.js'
import './seColorPicker.js'
import './seSelect.js'
import './seText.js'

View File

@ -8,8 +8,8 @@
* @returns {Float}
*/
function toFixedNumeric (value, precision) {
if (precision === undefined) precision = 0;
return Math.round(value * (10 ** precision)) / (10 ** precision);
if (precision === undefined) precision = 0
return Math.round(value * (10 ** precision)) / (10 ** precision)
}
/**
* Whether a value is `null` or `undefined`.
@ -17,8 +17,8 @@ function toFixedNumeric (value, precision) {
* @returns {boolean}
*/
const isNullish = (val) => {
return val === null || val === undefined;
};
return val === null || val === undefined
}
/**
* Controls for all the input elements for the typing in color values.
*/
@ -30,8 +30,8 @@ export default class ColorValuePicker {
* @param {Float} alphaPrecision
*/
constructor (picker, color, bindedHex, alphaPrecision) {
const that = this; // private properties and methods
const inputs = picker.querySelectorAll('td.Text input');
const that = this // private properties and methods
const inputs = picker.querySelectorAll('td.Text input')
// input box key down - use arrows to alter color
/**
*
@ -39,95 +39,95 @@ export default class ColorValuePicker {
* @returns {Event|false|void}
*/
function keyDown (e) {
if (e.target.value === '' && e.target !== hex && ((!isNullish(bindedHex) && e.target !== bindedHex) || isNullish(bindedHex))) return undefined;
if (!validateKey(e)) return e;
if (e.target.value === '' && e.target !== hex && ((!isNullish(bindedHex) && e.target !== bindedHex) || isNullish(bindedHex))) return undefined
if (!validateKey(e)) return e
switch (e.target) {
case red:
switch (e.keyCode) {
case 38:
red.value = setValueInRange.call(that, (red.value << 0) + 1, 0, 255);
color.val('r', red.value, e.target);
return false;
case 40:
red.value = setValueInRange.call(that, (red.value << 0) - 1, 0, 255);
color.val('r', red.value, e.target);
return false;
}
break;
case green:
switch (e.keyCode) {
case 38:
green.value = setValueInRange.call(that, (green.value << 0) + 1, 0, 255);
color.val('g', green.value, e.target);
return false;
case 40:
green.value = setValueInRange.call(that, (green.value << 0) - 1, 0, 255);
color.val('g', green.value, e.target);
return false;
}
break;
case blue:
switch (e.keyCode) {
case 38:
blue.value = setValueInRange.call(that, (blue.value << 0) + 1, 0, 255);
color.val('b', blue.value, e.target);
return false;
case 40:
blue.value = setValueInRange.call(that, (blue.value << 0) - 1, 0, 255);
color.val('b', blue.value, e.target);
return false;
}
break;
case alpha:
switch (e.keyCode) {
case 38:
alpha.value = setValueInRange.call(that, Number.parseFloat(alpha.value) + 1, 0, 100);
color.val('a', toFixedNumeric((alpha.value * 255) / 100, alphaPrecision), e.target);
return false;
case 40:
alpha.value = setValueInRange.call(that, Number.parseFloat(alpha.value) - 1, 0, 100);
color.val('a', toFixedNumeric((alpha.value * 255) / 100, alphaPrecision), e.target);
return false;
}
break;
case hue:
switch (e.keyCode) {
case 38:
hue.value = setValueInRange.call(that, (hue.value << 0) + 1, 0, 360);
color.val('h', hue.value, e.target);
return false;
case 40:
hue.value =setValueInRange.call(that, (hue.value << 0) - 1, 0, 360);
color.val('h', hue.value, e.target);
return false;
}
break;
case saturation:
switch (e.keyCode) {
case 38:
saturation.value = setValueInRange.call(that, (saturation.value << 0) + 1, 0, 100);
color.val('s', saturation.value, e.target);
return false;
case 40:
saturation.value = setValueInRange.call(that, (saturation.value << 0) - 1, 0, 100);
color.val('s', saturation.value, e.target);
return false;
}
break;
case value:
switch (e.keyCode) {
case 38:
value.value = setValueInRange.call(that, (value.value << 0) + 1, 0, 100);
color.val('v', value.value, e.target);
return false;
case 40:
value.value = setValueInRange.call(that, (value.value << 0) - 1, 0, 100);
color.val('v', value.value, e.target);
return false;
}
break;
case red:
switch (e.keyCode) {
case 38:
red.value = setValueInRange.call(that, (red.value << 0) + 1, 0, 255)
color.val('r', red.value, e.target)
return false
case 40:
red.value = setValueInRange.call(that, (red.value << 0) - 1, 0, 255)
color.val('r', red.value, e.target)
return false
}
break
case green:
switch (e.keyCode) {
case 38:
green.value = setValueInRange.call(that, (green.value << 0) + 1, 0, 255)
color.val('g', green.value, e.target)
return false
case 40:
green.value = setValueInRange.call(that, (green.value << 0) - 1, 0, 255)
color.val('g', green.value, e.target)
return false
}
break
case blue:
switch (e.keyCode) {
case 38:
blue.value = setValueInRange.call(that, (blue.value << 0) + 1, 0, 255)
color.val('b', blue.value, e.target)
return false
case 40:
blue.value = setValueInRange.call(that, (blue.value << 0) - 1, 0, 255)
color.val('b', blue.value, e.target)
return false
}
break
case alpha:
switch (e.keyCode) {
case 38:
alpha.value = setValueInRange.call(that, Number.parseFloat(alpha.value) + 1, 0, 100)
color.val('a', toFixedNumeric((alpha.value * 255) / 100, alphaPrecision), e.target)
return false
case 40:
alpha.value = setValueInRange.call(that, Number.parseFloat(alpha.value) - 1, 0, 100)
color.val('a', toFixedNumeric((alpha.value * 255) / 100, alphaPrecision), e.target)
return false
}
break
case hue:
switch (e.keyCode) {
case 38:
hue.value = setValueInRange.call(that, (hue.value << 0) + 1, 0, 360)
color.val('h', hue.value, e.target)
return false
case 40:
hue.value = setValueInRange.call(that, (hue.value << 0) - 1, 0, 360)
color.val('h', hue.value, e.target)
return false
}
break
case saturation:
switch (e.keyCode) {
case 38:
saturation.value = setValueInRange.call(that, (saturation.value << 0) + 1, 0, 100)
color.val('s', saturation.value, e.target)
return false
case 40:
saturation.value = setValueInRange.call(that, (saturation.value << 0) - 1, 0, 100)
color.val('s', saturation.value, e.target)
return false
}
break
case value:
switch (e.keyCode) {
case 38:
value.value = setValueInRange.call(that, (value.value << 0) + 1, 0, 100)
color.val('v', value.value, e.target)
return false
case 40:
value.value = setValueInRange.call(that, (value.value << 0) - 1, 0, 100)
color.val('v', value.value, e.target)
return false
}
break
}
return undefined;
return undefined
}
// input box key up - validate value and set color
/**
@ -138,53 +138,53 @@ export default class ColorValuePicker {
function keyUp (e) {
if (e.target.value === '' && e.target !== hex &&
((!isNullish(bindedHex) && e.target !== bindedHex) ||
isNullish(bindedHex))) return undefined;
if (!validateKey(e)) return e;
isNullish(bindedHex))) return undefined
if (!validateKey(e)) return e
switch (e.target) {
case red:
red.value = setValueInRange.call(that, red.value, 0, 255);
color.val('r', red.value, e.target);
break;
case green:
green.value = setValueInRange.call(that, green.value, 0, 255);
color.val('g', green.value, e.target);
break;
case blue:
blue.value = setValueInRange.call(that, blue.value, 0, 255);
color.val('b', blue.value, e.target);
break;
case alpha:
alpha.value = setValueInRange.call(that, alpha.value, 0, 100);
color.val('a', toFixedNumeric((alpha.value * 255) / 100, alphaPrecision), e.target);
break;
case hue:
hue.value = setValueInRange.call(that, hue.value, 0, 360);
color.val('h', hue.value, e.target);
break;
case saturation:
saturation.value = setValueInRange.call(that, saturation.value, 0, 100);
color.val('s', saturation.value, e.target);
break;
case value:
value.value = setValueInRange.call(that, value.value, 0, 100);
color.val('v', value.value, e.target);
break;
case hex:
hex.value = hex.value.replace(/[^a-fA-F\d]/g, '').toLowerCase().substring(0, 6);
bindedHex && bindedHex.val(hex.value);
color.val('hex', hex.value !== '' ? hex.value : null, e.target);
break;
case bindedHex:
bindedHex.value = bindedHex.value.replace(/[^a-fA-F\d]/g, '').toLowerCase().substring(0, 6);
hex.val(bindedHex.value);
color.val('hex', bindedHex.value !== '' ? bindedHex.value : null, e.target);
break;
case ahex:
ahex.value = ahex.value.replace(/[^a-fA-F\d]/g, '').toLowerCase().substring(0, 2);
color.val('a', !isNullish(ahex.value) ? Number.parseInt(ahex.value, 16) : null, e.target);
break;
case red:
red.value = setValueInRange.call(that, red.value, 0, 255)
color.val('r', red.value, e.target)
break
case green:
green.value = setValueInRange.call(that, green.value, 0, 255)
color.val('g', green.value, e.target)
break
case blue:
blue.value = setValueInRange.call(that, blue.value, 0, 255)
color.val('b', blue.value, e.target)
break
case alpha:
alpha.value = setValueInRange.call(that, alpha.value, 0, 100)
color.val('a', toFixedNumeric((alpha.value * 255) / 100, alphaPrecision), e.target)
break
case hue:
hue.value = setValueInRange.call(that, hue.value, 0, 360)
color.val('h', hue.value, e.target)
break
case saturation:
saturation.value = setValueInRange.call(that, saturation.value, 0, 100)
color.val('s', saturation.value, e.target)
break
case value:
value.value = setValueInRange.call(that, value.value, 0, 100)
color.val('v', value.value, e.target)
break
case hex:
hex.value = hex.value.replace(/[^a-fA-F\d]/g, '').toLowerCase().substring(0, 6)
bindedHex && bindedHex.val(hex.value)
color.val('hex', hex.value !== '' ? hex.value : null, e.target)
break
case bindedHex:
bindedHex.value = bindedHex.value.replace(/[^a-fA-F\d]/g, '').toLowerCase().substring(0, 6)
hex.val(bindedHex.value)
color.val('hex', bindedHex.value !== '' ? bindedHex.value : null, e.target)
break
case ahex:
ahex.value = ahex.value.replace(/[^a-fA-F\d]/g, '').toLowerCase().substring(0, 2)
color.val('a', !isNullish(ahex.value) ? Number.parseInt(ahex.value, 16) : null, e.target)
break
}
return undefined;
return undefined
}
// input box blur - reset to original if value empty
/**
@ -194,44 +194,44 @@ export default class ColorValuePicker {
function blur (e) {
if (!isNullish(color.value)) {
switch (e.target) {
case red:
color.value = 'r';
red.value = color.value;
break;
case green:
color.value = 'g';
green.value = color.value;
break;
case blue:
color.value = 'b';
blue.value = color.value;
break;
case alpha:
color.value = 'a';
alpha.value = toFixedNumeric((color.value * 100) / 255, alphaPrecision);
break;
case hue:
color.value = 'h';
hue.value = color.value;
break;
case saturation:
color.value = 's';
saturation.value = color.value;
break;
case value:
color.value = 'v';
value.value = color.value;
break;
case hex:
case bindedHex:
color.value = 'hex';
hex.value = color.value;
bindedHex.value = color.value;
break;
case ahex:
color.value = 'ahex';
ahex.value = color.value.substring(6);
break;
case red:
color.value = 'r'
red.value = color.value
break
case green:
color.value = 'g'
green.value = color.value
break
case blue:
color.value = 'b'
blue.value = color.value
break
case alpha:
color.value = 'a'
alpha.value = toFixedNumeric((color.value * 100) / 255, alphaPrecision)
break
case hue:
color.value = 'h'
hue.value = color.value
break
case saturation:
color.value = 's'
saturation.value = color.value
break
case value:
color.value = 'v'
value.value = color.value
break
case hex:
case bindedHex:
color.value = 'hex'
hex.value = color.value
bindedHex.value = color.value
break
case ahex:
color.value = 'ahex'
ahex.value = color.value.substring(6)
break
}
}
}
@ -241,17 +241,17 @@ export default class ColorValuePicker {
*/
function validateKey (e) {
switch (e.keyCode) {
case 9:
case 16:
case 29:
case 37:
case 39:
return false;
case 'c'.charCodeAt():
case 'v'.charCodeAt():
if (e.ctrlKey) return false;
case 9:
case 16:
case 29:
case 37:
case 39:
return false
case 'c'.charCodeAt():
case 'v'.charCodeAt():
if (e.ctrlKey) return false
}
return true;
return true
}
/**
@ -262,10 +262,10 @@ export default class ColorValuePicker {
* @returns {Float|string} Returns a number or numeric string
*/
function setValueInRange (value, min, max) {
if (value === '' || isNaN(value)) return min;
if (value > max) return max;
if (value < min) return min;
return value;
if (value === '' || isNaN(value)) return min
if (value > max) return max
if (value < min) return min
return value
}
/**
* @param {external:jQuery} ui
@ -273,117 +273,117 @@ export default class ColorValuePicker {
* @returns {void}
*/
function colorChanged (ui, context) {
const all = ui.val('all');
if (context !== red) red.value = (!isNullish(all) ? all.r : '');
if (context !== green) green.value = (!isNullish(all) ? all.g : '');
if (context !== blue) blue.value = (!isNullish(all) ? all.b : '');
if (alpha && context !== alpha) alpha.value = (!isNullish(all) ? toFixedNumeric((all.a * 100) / 255, alphaPrecision) : '');
if (context !== hue) hue.value = (!isNullish(all) ? all.h : '');
if (context !== saturation) saturation.value = (!isNullish(all) ? all.s : '');
if (context !== value) value.value = (!isNullish(all) ? all.v : '');
if (context !== hex && ((bindedHex && context !== bindedHex) || !bindedHex)) hex.value = (!isNullish(all) ? all.hex : '');
if (bindedHex && context !== bindedHex && context !== hex) bindedHex.value = (!isNullish(all) ? all.hex : '');
if (ahex && context !== ahex) ahex.value = (!isNullish(all) ? all.ahex.substring(6) : '');
const all = ui.val('all')
if (context !== red) red.value = (!isNullish(all) ? all.r : '')
if (context !== green) green.value = (!isNullish(all) ? all.g : '')
if (context !== blue) blue.value = (!isNullish(all) ? all.b : '')
if (alpha && context !== alpha) alpha.value = (!isNullish(all) ? toFixedNumeric((all.a * 100) / 255, alphaPrecision) : '')
if (context !== hue) hue.value = (!isNullish(all) ? all.h : '')
if (context !== saturation) saturation.value = (!isNullish(all) ? all.s : '')
if (context !== value) value.value = (!isNullish(all) ? all.v : '')
if (context !== hex && ((bindedHex && context !== bindedHex) || !bindedHex)) hex.value = (!isNullish(all) ? all.hex : '')
if (bindedHex && context !== bindedHex && context !== hex) bindedHex.value = (!isNullish(all) ? all.hex : '')
if (ahex && context !== ahex) ahex.value = (!isNullish(all) ? all.ahex.substring(6) : '')
}
/**
* Unbind all events and null objects.
* @returns {void}
*/
function destroy () {
red.removeEventListener('keyup', keyUp);
green.removeEventListener('keyup', keyUp);
blue.removeEventListener('keyup', keyUp);
hue.removeEventListener('keyup', keyUp);
saturation.removeEventListener('keyup', keyUp);
value.removeEventListener('keyup', keyUp);
hex.removeEventListener('keyup', keyUp);
red.removeEventListener('keyup', keyUp)
green.removeEventListener('keyup', keyUp)
blue.removeEventListener('keyup', keyUp)
hue.removeEventListener('keyup', keyUp)
saturation.removeEventListener('keyup', keyUp)
value.removeEventListener('keyup', keyUp)
hex.removeEventListener('keyup', keyUp)
red.removeEventListener('blur', blur);
green.removeEventListener('blur', blur);
blue.removeEventListener('blur', blur);
hue.removeEventListener('blur', blur);
saturation.removeEventListener('blur', blur);
value.removeEventListener('blur', blur);
hex.removeEventListener('blur', blur);
red.removeEventListener('blur', blur)
green.removeEventListener('blur', blur)
blue.removeEventListener('blur', blur)
hue.removeEventListener('blur', blur)
saturation.removeEventListener('blur', blur)
value.removeEventListener('blur', blur)
hex.removeEventListener('blur', blur)
red.removeEventListener('keydown', keyDown);
green.removeEventListener('keydown', keyDown);
blue.removeEventListener('keydown', keyDown);
hue.removeEventListener('keydown', keyDown);
saturation.removeEventListener('keydown', keyDown);
value.removeEventListener('keydown', keyDown);
red.removeEventListener('keydown', keyDown)
green.removeEventListener('keydown', keyDown)
blue.removeEventListener('keydown', keyDown)
hue.removeEventListener('keydown', keyDown)
saturation.removeEventListener('keydown', keyDown)
value.removeEventListener('keydown', keyDown)
if (alpha !== null) {
alpha.removeEventListener('keyup', keyUp);
alpha.removeEventListener('blur', blur);
alpha.removeEventListener('keydown', keyDown);
alpha.removeEventListener('keyup', keyUp)
alpha.removeEventListener('blur', blur)
alpha.removeEventListener('keydown', keyDown)
}
if (ahex !== null) {
ahex.removeEventListener('keyup', keyUp);
ahex.removeEventListener('blur', blur);
ahex.removeEventListener('keyup', keyUp)
ahex.removeEventListener('blur', blur)
}
if (bindedHex !== null) {
bindedHex.removeEventListener('keyup', keyUp);
bindedHex.removeEventListener('blur', blur);
bindedHex.removeEventListener('keyup', keyUp)
bindedHex.removeEventListener('blur', blur)
}
color.unbind(colorChanged);
red = null;
green = null;
blue = null;
alpha = null;
hue = null;
saturation = null;
value = null;
hex = null;
ahex = null;
color.unbind(colorChanged)
red = null
green = null
blue = null
alpha = null
hue = null
saturation = null
value = null
hex = null
ahex = null
}
let
red = inputs[3];
let green = inputs[4];
let blue = inputs[5];
let alpha = inputs.length > 7 ? inputs[6] : null;
let hue = inputs[0];
let saturation = inputs[1];
let value = inputs[2];
let hex = inputs[(inputs.length > 7) ? 7 : 6];
let ahex = inputs.length > 7 ? inputs[8] : null;
Object.assign(that, { destroy });
red.addEventListener('keyup', keyUp);
green.addEventListener('keyup', keyUp);
blue.addEventListener('keyup', keyUp);
hue.addEventListener('keyup', keyUp);
saturation.addEventListener('keyup', keyUp);
value.addEventListener('keyup', keyUp);
hex.addEventListener('keyup', keyUp);
red = inputs[3]
let green = inputs[4]
let blue = inputs[5]
let alpha = inputs.length > 7 ? inputs[6] : null
let hue = inputs[0]
let saturation = inputs[1]
let value = inputs[2]
let hex = inputs[(inputs.length > 7) ? 7 : 6]
let ahex = inputs.length > 7 ? inputs[8] : null
Object.assign(that, { destroy })
red.addEventListener('keyup', keyUp)
green.addEventListener('keyup', keyUp)
blue.addEventListener('keyup', keyUp)
hue.addEventListener('keyup', keyUp)
saturation.addEventListener('keyup', keyUp)
value.addEventListener('keyup', keyUp)
hex.addEventListener('keyup', keyUp)
red.addEventListener('blur', blur);
green.addEventListener('blur', blur);
blue.addEventListener('blur', blur);
hue.addEventListener('blur', blur);
saturation.addEventListener('blur', blur);
value.addEventListener('blur', blur);
hex.addEventListener('blur', blur);
red.addEventListener('blur', blur)
green.addEventListener('blur', blur)
blue.addEventListener('blur', blur)
hue.addEventListener('blur', blur)
saturation.addEventListener('blur', blur)
value.addEventListener('blur', blur)
hex.addEventListener('blur', blur)
red.addEventListener('keydown', keyDown);
green.addEventListener('keydown', keyDown);
blue.addEventListener('keydown', keyDown);
hue.addEventListener('keydown', keyDown);
saturation.addEventListener('keydown', keyDown);
value.addEventListener('keydown', keyDown);
red.addEventListener('keydown', keyDown)
green.addEventListener('keydown', keyDown)
blue.addEventListener('keydown', keyDown)
hue.addEventListener('keydown', keyDown)
saturation.addEventListener('keydown', keyDown)
value.addEventListener('keydown', keyDown)
if (alpha !== null) {
alpha.addEventListener('keyup', keyUp);
alpha.addEventListener('blur', blur);
alpha.addEventListener('keydown', keyDown);
alpha.addEventListener('keyup', keyUp)
alpha.addEventListener('blur', blur)
alpha.addEventListener('keydown', keyDown)
}
if (ahex !== null) {
ahex.addEventListener('keyup', keyUp);
ahex.addEventListener('blur', blur);
ahex.addEventListener('keyup', keyUp)
ahex.addEventListener('blur', blur)
}
if (bindedHex !== null) {
bindedHex.addEventListener('keyup', keyUp);
bindedHex.addEventListener('blur', blur);
bindedHex.addEventListener('keyup', keyUp)
bindedHex.addEventListener('blur', blur)
}
color.bind(colorChanged);
color.bind(colorChanged)
}
}

View File

@ -1,12 +1,12 @@
import { findPos } from './Util.js';
import { findPos } from './Util.js'
/**
* Whether a value is `null` or `undefined`.
* @param {any} val
* @returns {boolean}
*/
const isNullish = (val) => {
return val === null || val === undefined;
};
return val === null || val === undefined
}
/**
* Encapsulate slider functionality for the ColorMap and ColorBar -
* could be useful to use a jQuery UI draggable for this with certain extensions.
@ -18,7 +18,7 @@ export default class Slider {
* @param {module:jPicker.SliderOptions} options
*/
constructor (bar, options) {
const that = this;
const that = this
/**
* Fire events on the supplied `context`
* @param {module:jPicker.JPickerInit} context
@ -26,8 +26,8 @@ export default class Slider {
*/
function fireChangeEvents (context) {
changeEvents.forEach((changeEvent) => {
changeEvent.call(that, that, context);
});
changeEvent.call(that, that, context)
})
}
/**
@ -36,17 +36,17 @@ export default class Slider {
* @returns {void}
*/
function mouseDown (e) {
const off = findPos(bar);
offset = { l: off.left | 0, t: off.top | 0 };
clearTimeout(timeout);
const off = findPos(bar)
offset = { l: off.left | 0, t: off.top | 0 }
clearTimeout(timeout)
// using setTimeout for visual updates - once the style is updated the browser will re-render internally allowing the next Javascript to run
timeout = setTimeout(function () {
setValuesFromMousePosition.call(that, e);
}, 0);
setValuesFromMousePosition.call(that, e)
}, 0)
// Bind mousemove and mouseup event to the document so it responds when dragged of of the bar - we will unbind these when on mouseup to save processing
document.addEventListener('mousemove', mouseMove);
document.addEventListener('mouseup', mouseUp);
e.preventDefault(); // don't try to select anything or drag the image to the desktop
document.addEventListener('mousemove', mouseMove)
document.addEventListener('mouseup', mouseUp)
e.preventDefault() // don't try to select anything or drag the image to the desktop
}
/**
* Set the values as the mouse moves.
@ -54,13 +54,13 @@ export default class Slider {
* @returns {false}
*/
function mouseMove (e) {
clearTimeout(timeout);
clearTimeout(timeout)
timeout = setTimeout(function () {
setValuesFromMousePosition.call(that, e);
}, 0);
e.stopPropagation();
e.preventDefault();
return false;
setValuesFromMousePosition.call(that, e)
}, 0)
e.stopPropagation()
e.preventDefault()
return false
}
/**
* Unbind the document events - they aren't needed when not dragging.
@ -68,11 +68,11 @@ export default class Slider {
* @returns {false}
*/
function mouseUp (e) {
document.removeEventListener('mousemove', mouseMove);
document.removeEventListener('mouseup', mouseUp);
e.stopPropagation();
e.preventDefault();
return false;
document.removeEventListener('mousemove', mouseMove)
document.removeEventListener('mouseup', mouseUp)
e.stopPropagation()
e.preventDefault()
return false
}
/**
@ -81,19 +81,19 @@ export default class Slider {
* @returns {void}
*/
function setValuesFromMousePosition (e) {
const barW = bar.w; // local copies for YUI compressor
const barH = bar.h;
let locX = e.pageX - offset.l;
let locY = e.pageY - offset.t;
const barW = bar.w // local copies for YUI compressor
const barH = bar.h
let locX = e.pageX - offset.l
let locY = e.pageY - offset.t
// keep the arrow within the bounds of the bar
if (locX < 0) locX = 0;
else if (locX > barW) locX = barW;
if (locY < 0) locY = 0;
else if (locY > barH) locY = barH;
if (locX < 0) locX = 0
else if (locX > barW) locX = barW
if (locY < 0) locY = 0
else if (locY > barH) locY = barH
val.call(that, 'xy', {
x: ((locX / barW) * rangeX) + minX,
y: ((locY / barH) * rangeY) + minY
});
})
}
/**
*
@ -101,33 +101,33 @@ export default class Slider {
*/
function draw () {
const
barW = bar.w;
const barH = bar.h;
const arrowW = arrow.w;
const arrowH = arrow.h;
let arrowOffsetX = 0;
let arrowOffsetY = 0;
barW = bar.w
const barH = bar.h
const arrowW = arrow.w
const arrowH = arrow.h
let arrowOffsetX = 0
let arrowOffsetY = 0
setTimeout(function () {
if (rangeX > 0) { // range is greater than zero
// constrain to bounds
if (x === maxX) arrowOffsetX = barW;
else arrowOffsetX = ((x / rangeX) * barW) | 0;
if (x === maxX) arrowOffsetX = barW
else arrowOffsetX = ((x / rangeX) * barW) | 0
}
if (rangeY > 0) { // range is greater than zero
// constrain to bounds
if (y === maxY) arrowOffsetY = barH;
else arrowOffsetY = ((y / rangeY) * barH) | 0;
if (y === maxY) arrowOffsetY = barH
else arrowOffsetY = ((y / rangeY) * barH) | 0
}
// if arrow width is greater than bar width, center arrow and prevent horizontal dragging
if (arrowW >= barW) arrowOffsetX = (barW >> 1) - (arrowW >> 1); // number >> 1 - superfast bitwise divide by two and truncate (move bits over one bit discarding lowest)
else arrowOffsetX -= arrowW >> 1;
if (arrowW >= barW) arrowOffsetX = (barW >> 1) - (arrowW >> 1) // number >> 1 - superfast bitwise divide by two and truncate (move bits over one bit discarding lowest)
else arrowOffsetX -= arrowW >> 1
// if arrow height is greater than bar height, center arrow and prevent vertical dragging
if (arrowH >= barH) arrowOffsetY = (barH >> 1) - (arrowH >> 1);
else arrowOffsetY -= arrowH >> 1;
if (arrowH >= barH) arrowOffsetY = (barH >> 1) - (arrowH >> 1)
else arrowOffsetY -= arrowH >> 1
// set the arrow position based on these offsets
arrow.style.left = arrowOffsetX + 'px';
arrow.style.top = arrowOffsetY + 'px';
});
arrow.style.left = arrowOffsetX + 'px'
arrow.style.top = arrowOffsetY + 'px'
})
}
/**
@ -138,52 +138,52 @@ export default class Slider {
* @returns {module:math.XYObject|Float|void}
*/
function val (name, value, context) {
const set = value !== undefined;
const set = value !== undefined
if (!set) {
if (isNullish(name)) name = 'xy';
if (isNullish(name)) name = 'xy'
switch (name.toLowerCase()) {
case 'x': return x;
case 'y': return y;
case 'xy':
default: return { x, y };
case 'x': return x
case 'y': return y
case 'xy':
default: return { x, y }
}
}
if (!isNullish(context) && context === that) return undefined;
let changed = false;
if (!isNullish(context) && context === that) return undefined
let changed = false
let newX; let newY;
if (isNullish(name)) name = 'xy';
let newX; let newY
if (isNullish(name)) name = 'xy'
switch (name.toLowerCase()) {
case 'x':
newX = (value && ((value.x && value.x | 0) || value | 0)) || 0;
break;
case 'y':
newY = (value && ((value.y && value.y | 0) || value | 0)) || 0;
break;
case 'xy':
default:
newX = (value && value.x && value.x | 0) || 0;
newY = (value && value.y && value.y | 0) || 0;
break;
case 'x':
newX = (value && ((value.x && value.x | 0) || value | 0)) || 0
break
case 'y':
newY = (value && ((value.y && value.y | 0) || value | 0)) || 0
break
case 'xy':
default:
newX = (value && value.x && value.x | 0) || 0
newY = (value && value.y && value.y | 0) || 0
break
}
if (!isNullish(newX)) {
if (newX < minX) newX = minX;
else if (newX > maxX) newX = maxX;
if (newX < minX) newX = minX
else if (newX > maxX) newX = maxX
if (x !== newX) {
x = newX;
changed = true;
x = newX
changed = true
}
}
if (!isNullish(newY)) {
if (newY < minY) newY = minY;
else if (newY > maxY) newY = maxY;
if (newY < minY) newY = minY
else if (newY > maxY) newY = maxY
if (y !== newY) {
y = newY;
changed = true;
y = newY
changed = true
}
}
changed && fireChangeEvents.call(that, context || that);
return undefined;
changed && fireChangeEvents.call(that, context || that)
return undefined
}
/**
@ -209,89 +209,89 @@ export default class Slider {
* @returns {module:jPicker.MinMaxRangeXY|module:jPicker.MinMaxRangeX|module:jPicker.MinMaxRangeY|void}
*/
function range (name, value) {
const set = value !== undefined;
const set = value !== undefined
if (!set) {
if (isNullish(name)) name = 'all';
if (isNullish(name)) name = 'all'
switch (name.toLowerCase()) {
case 'minx': return minX;
case 'maxx': return maxX;
case 'rangex': return { minX, maxX, rangeX };
case 'miny': return minY;
case 'maxy': return maxY;
case 'rangey': return { minY, maxY, rangeY };
case 'all':
default: return { minX, maxX, rangeX, minY, maxY, rangeY };
case 'minx': return minX
case 'maxx': return maxX
case 'rangex': return { minX, maxX, rangeX }
case 'miny': return minY
case 'maxy': return maxY
case 'rangey': return { minY, maxY, rangeY }
case 'all':
default: return { minX, maxX, rangeX, minY, maxY, rangeY }
}
}
let // changed = false,
newMinX;
let newMaxX;
let newMinY;
let newMaxY;
if (isNullish(name)) name = 'all';
newMinX
let newMaxX
let newMinY
let newMaxY
if (isNullish(name)) name = 'all'
switch (name.toLowerCase()) {
case 'minx':
newMinX = (value && ((value.minX && value.minX | 0) || value | 0)) || 0;
break;
case 'maxx':
newMaxX = (value && ((value.maxX && value.maxX | 0) || value | 0)) || 0;
break;
case 'rangex':
newMinX = (value && value.minX && value.minX | 0) || 0;
newMaxX = (value && value.maxX && value.maxX | 0) || 0;
break;
case 'miny':
newMinY = (value && ((value.minY && value.minY | 0) || value | 0)) || 0;
break;
case 'maxy':
newMaxY = (value && ((value.maxY && value.maxY | 0) || value | 0)) || 0;
break;
case 'rangey':
newMinY = (value && value.minY && value.minY | 0) || 0;
newMaxY = (value && value.maxY && value.maxY | 0) || 0;
break;
case 'all':
default:
newMinX = (value && value.minX && value.minX | 0) || 0;
newMaxX = (value && value.maxX && value.maxX | 0) || 0;
newMinY = (value && value.minY && value.minY | 0) || 0;
newMaxY = (value && value.maxY && value.maxY | 0) || 0;
break;
case 'minx':
newMinX = (value && ((value.minX && value.minX | 0) || value | 0)) || 0
break
case 'maxx':
newMaxX = (value && ((value.maxX && value.maxX | 0) || value | 0)) || 0
break
case 'rangex':
newMinX = (value && value.minX && value.minX | 0) || 0
newMaxX = (value && value.maxX && value.maxX | 0) || 0
break
case 'miny':
newMinY = (value && ((value.minY && value.minY | 0) || value | 0)) || 0
break
case 'maxy':
newMaxY = (value && ((value.maxY && value.maxY | 0) || value | 0)) || 0
break
case 'rangey':
newMinY = (value && value.minY && value.minY | 0) || 0
newMaxY = (value && value.maxY && value.maxY | 0) || 0
break
case 'all':
default:
newMinX = (value && value.minX && value.minX | 0) || 0
newMaxX = (value && value.maxX && value.maxX | 0) || 0
newMinY = (value && value.minY && value.minY | 0) || 0
newMaxY = (value && value.maxY && value.maxY | 0) || 0
break
}
if (!isNullish(newMinX) && minX !== newMinX) {
minX = newMinX;
rangeX = maxX - minX;
minX = newMinX
rangeX = maxX - minX
}
if (!isNullish(newMaxX) && maxX !== newMaxX) {
maxX = newMaxX;
rangeX = maxX - minX;
maxX = newMaxX
rangeX = maxX - minX
}
if (!isNullish(newMinY) && minY !== newMinY) {
minY = newMinY;
rangeY = maxY - minY;
minY = newMinY
rangeY = maxY - minY
}
if (!isNullish(newMaxY) && maxY !== newMaxY) {
maxY = newMaxY;
rangeY = maxY - minY;
maxY = newMaxY
rangeY = maxY - minY
}
return undefined;
return undefined
}
/**
* @param {GenericCallback} callback
* @returns {void}
*/
function bind (callback) {
if (typeof callback === 'function') changeEvents.push(callback);
if (typeof callback === 'function') changeEvents.push(callback)
}
/**
* @param {GenericCallback} callback
* @returns {void}
*/
function unbind (callback) {
if (typeof callback !== 'function') return;
let i;
while ((i = changeEvents.includes(callback))) changeEvents.splice(i, 1);
if (typeof callback !== 'function') return
let i
while ((i = changeEvents.includes(callback))) changeEvents.splice(i, 1)
}
/**
*
@ -299,39 +299,39 @@ export default class Slider {
*/
function destroy () {
// unbind all possible events and null objects
document.removeEventListener('mousemove', mouseMove);
document.removeEventListener('mouseup', mouseUp);
bar.removeEventListener('mousedown', mouseDown);
bar = null;
arrow = null;
changeEvents = null;
document.removeEventListener('mousemove', mouseMove)
document.removeEventListener('mouseup', mouseUp)
bar.removeEventListener('mousedown', mouseDown)
bar = null
arrow = null
changeEvents = null
}
let offset;
let timeout;
let x = 0;
let y = 0;
let minX = 0;
let maxX = 100;
let rangeX = 100;
let minY = 0;
let maxY = 100;
let rangeY = 100;
let arrow = bar.querySelector('img'); // the arrow image to drag
let changeEvents = [];
let offset
let timeout
let x = 0
let y = 0
let minX = 0
let maxX = 100
let rangeX = 100
let minY = 0
let maxY = 100
let rangeY = 100
let arrow = bar.querySelector('img') // the arrow image to drag
let changeEvents = []
Object.assign(that, {
val,
range,
bind,
unbind,
destroy
});
})
// initialize this control
arrow.src = options.arrow && options.arrow.image;
arrow.w = (options.arrow && options.arrow.width) || parseFloat(getComputedStyle(arrow, null).width.replace("px", ""));
arrow.h = (options.arrow && options.arrow.height) || parseFloat(getComputedStyle(arrow, null).height.replace("px", ""));
bar.w = (options.map && options.map.width) || parseFloat(getComputedStyle(bar, null).width.replace("px", ""));
bar.h = (options.map && options.map.height) || parseFloat(getComputedStyle(bar, null).height.replace("px", ""));
bar.addEventListener('mousedown', mouseDown);
bind.call(that, draw);
arrow.src = options.arrow && options.arrow.image
arrow.w = (options.arrow && options.arrow.width) || parseFloat(getComputedStyle(arrow, null).width.replace('px', ''))
arrow.h = (options.arrow && options.arrow.height) || parseFloat(getComputedStyle(arrow, null).height.replace('px', ''))
bar.w = (options.map && options.map.width) || parseFloat(getComputedStyle(bar, null).width.replace('px', ''))
bar.h = (options.map && options.map.height) || parseFloat(getComputedStyle(bar, null).height.replace('px', ''))
bar.addEventListener('mousedown', mouseDown)
bind.call(that, draw)
}
}

View File

@ -2,39 +2,36 @@
* @param {any} obj
* @returns {any}
*/
export function findPos(obj) {
let curleft = 0;
let curtop = 0;
export function findPos (obj) {
let curleft = 0
let curtop = 0
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
curleft += obj.offsetLeft
curtop += obj.offsetTop
// eslint-disable-next-line no-cond-assign
} while (obj = obj.offsetParent);
return { left: curleft, top: curtop };
} while (obj = obj.offsetParent)
return { left: curleft, top: curtop }
}
return { left: curleft, top: curtop };
return { left: curleft, top: curtop }
}
export function isObject(item) {
return (item && typeof item === 'object' && !Array.isArray(item));
export function isObject (item) {
return (item && typeof item === 'object' && !Array.isArray(item))
}
export function mergeDeep(target, source) {
const output = Object.assign({}, target);
export function mergeDeep (target, source) {
const output = Object.assign({}, target)
if (isObject(target) && isObject(source)) {
Object.keys(source).forEach((key) => {
if (isObject(source[key])) {
if (!(key in target))
Object.assign(output, { [key]: source[key] });
else
output[key] = mergeDeep(target[key], source[key]);
if (!(key in target)) { Object.assign(output, { [key]: source[key] }) } else { output[key] = mergeDeep(target[key], source[key]) }
} else {
Object.assign(output, { [key]: source[key] });
Object.assign(output, { [key]: source[key] })
}
});
})
}
return output;
return output
}
/**
@ -43,17 +40,17 @@ export function mergeDeep(target, source) {
* @param {String} selector Selector to match against (class, ID, data attribute, or tag)
* @return {Boolean|Element} Returns null if not match found
*/
export function getClosest(elem, selector) {
const firstChar = selector.charAt(0);
const supports = 'classList' in document.documentElement;
let attribute; let value;
export function getClosest (elem, selector) {
const firstChar = selector.charAt(0)
const supports = 'classList' in document.documentElement
let attribute; let value
// If selector is a data attribute, split attribute from value
if (firstChar === '[') {
selector = selector.substr(1, selector.length - 2);
attribute = selector.split('=');
selector = selector.substr(1, selector.length - 2)
attribute = selector.split('=')
if (attribute.length > 1) {
value = true;
attribute[1] = attribute[1].replace(/"/g, '').replace(/'/g, '');
value = true
attribute[1] = attribute[1].replace(/"/g, '').replace(/'/g, '')
}
}
// Get closest match
@ -62,18 +59,18 @@ export function getClosest(elem, selector) {
if (firstChar === '.') {
if (supports) {
if (elem.classList.contains(selector.substr(1))) {
return elem;
return elem
}
} else {
if (new RegExp('(^|\\s)' + selector.substr(1) + '(\\s|$)').test(elem.className)) {
return elem;
return elem
}
}
}
// If selector is an ID
if (firstChar === '#') {
if (elem.id === selector.substr(1)) {
return elem;
return elem
}
}
// If selector is a data attribute
@ -81,19 +78,19 @@ export function getClosest(elem, selector) {
if (elem.hasAttribute(attribute[0])) {
if (value) {
if (elem.getAttribute(attribute[0]) === attribute[1]) {
return elem;
return elem
}
} else {
return elem;
return elem
}
}
}
// If selector is a tag
if (elem.tagName.toLowerCase() === selector) {
return elem;
return elem
}
}
return null;
return null
}
/**
@ -102,100 +99,100 @@ export function getClosest(elem, selector) {
* @param {String} selector The class, id, data attribute, or tag to look for
* @return {Array} Null if no match
*/
export function getParents(elem, selector) {
const parents = [];
const firstChar = selector?.charAt(0);
export function getParents (elem, selector) {
const parents = []
const firstChar = selector?.charAt(0)
// Get matches
for ( ; elem && elem !== document; elem = elem.parentNode ) {
if ( selector ) {
for (; elem && elem !== document; elem = elem.parentNode) {
if (selector) {
// If selector is a class
if ( firstChar === '.' ) {
if ( elem.classList.contains( selector.substr(1) ) ) {
parents.push( elem );
if (firstChar === '.') {
if (elem.classList.contains(selector.substr(1))) {
parents.push(elem)
}
}
// If selector is an ID
if ( firstChar === '#' ) {
if ( elem.id === selector.substr(1) ) {
parents.push( elem );
if (firstChar === '#') {
if (elem.id === selector.substr(1)) {
parents.push(elem)
}
}
// If selector is a data attribute
if ( firstChar === '[' ) {
if ( elem.hasAttribute( selector.substr(1, selector.length - 1) ) ) {
parents.push( elem );
if (firstChar === '[') {
if (elem.hasAttribute(selector.substr(1, selector.length - 1))) {
parents.push(elem)
}
}
// If selector is a tag
if ( elem.tagName.toLowerCase() === selector ) {
parents.push( elem );
if (elem.tagName.toLowerCase() === selector) {
parents.push(elem)
}
} else {
parents.push( elem );
parents.push(elem)
}
}
// Return parents if any exist
return parents.length? parents : null;
return parents.length ? parents : null
}
export function getParentsUntil(elem, parent, selector) {
const parents = [];
const parentType = parent?.charAt(0);
const selectorType = selector?.selector.charAt(0);
export function getParentsUntil (elem, parent, selector) {
const parents = []
const parentType = parent?.charAt(0)
const selectorType = selector?.selector.charAt(0)
// Get matches
for ( ; elem && elem !== document; elem = elem.parentNode ) {
for (; elem && elem !== document; elem = elem.parentNode) {
// Check if parent has been reached
if ( parent ) {
if (parent) {
// If parent is a class
if ( parentType === '.' ) {
if ( elem.classList.contains( parent.substr(1) ) ) {
break;
if (parentType === '.') {
if (elem.classList.contains(parent.substr(1))) {
break
}
}
// If parent is an ID
if ( parentType === '#' ) {
if ( elem.id === parent.substr(1) ) {
break;
if (parentType === '#') {
if (elem.id === parent.substr(1)) {
break
}
}
// If parent is a data attribute
if ( parentType === '[' ) {
if ( elem.hasAttribute( parent.substr(1, parent.length - 1) ) ) {
break;
if (parentType === '[') {
if (elem.hasAttribute(parent.substr(1, parent.length - 1))) {
break
}
}
// If parent is a tag
if ( elem.tagName.toLowerCase() === parent ) {
break;
if (elem.tagName.toLowerCase() === parent) {
break
}
}
if ( selector ) {
if (selector) {
// If selector is a class
if ( selectorType === '.' ) {
if ( elem.classList.contains( selector.substr(1) ) ) {
parents.push( elem );
if (selectorType === '.') {
if (elem.classList.contains(selector.substr(1))) {
parents.push(elem)
}
}
// If selector is an ID
if ( selectorType === '#' ) {
if ( elem.id === selector.substr(1) ) {
parents.push( elem );
if (selectorType === '#') {
if (elem.id === selector.substr(1)) {
parents.push(elem)
}
}
// If selector is a data attribute
if ( selectorType === '[' ) {
if ( elem.hasAttribute( selector.substr(1, selector.length - 1) ) ) {
parents.push( elem );
if (selectorType === '[') {
if (elem.hasAttribute(selector.substr(1, selector.length - 1))) {
parents.push(elem)
}
}
// If selector is a tag
if ( elem.tagName.toLowerCase() === selector ) {
parents.push( elem );
if (elem.tagName.toLowerCase() === selector) {
parents.push(elem)
}
} else {
parents.push( elem );
parents.push(elem)
}
}
// Return parents if any exist
return parents.length? parents : null;
}
return parents.length ? parents : null
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -6,83 +6,83 @@ export default class Paint {
* @param {module:jGraduate.jGraduatePaintOptions} [opt]
*/
constructor (opt) {
const options = opt || {};
this.alpha = isNaN(options.alpha) ? 100 : options.alpha;
const options = opt || {}
this.alpha = isNaN(options.alpha) ? 100 : options.alpha
// copy paint object
if (options.copy) {
/**
* @name module:jGraduate~Paint#type
* @type {"none"|"solidColor"|"linearGradient"|"radialGradient"}
*/
this.type = options.copy.type;
this.type = options.copy.type
/**
* Represents opacity (0-100).
* @name module:jGraduate~Paint#alpha
* @type {Float}
*/
this.alpha = options.copy.alpha;
this.alpha = options.copy.alpha
/**
* Represents #RRGGBB hex of color.
* @name module:jGraduate~Paint#solidColor
* @type {string}
*/
this.solidColor = null;
this.solidColor = null
/**
* @name module:jGraduate~Paint#linearGradient
* @type {SVGLinearGradientElement}
*/
this.linearGradient = null;
this.linearGradient = null
/**
* @name module:jGraduate~Paint#radialGradient
* @type {SVGRadialGradientElement}
*/
this.radialGradient = null;
this.radialGradient = null
switch (this.type) {
case 'none':
break;
case 'solidColor':
this.solidColor = options.copy.solidColor;
break;
case 'linearGradient':
this.linearGradient = options.copy.linearGradient.cloneNode(true);
break;
case 'radialGradient':
this.radialGradient = options.copy.radialGradient.cloneNode(true);
break;
case 'none':
break
case 'solidColor':
this.solidColor = options.copy.solidColor
break
case 'linearGradient':
this.linearGradient = options.copy.linearGradient.cloneNode(true)
break
case 'radialGradient':
this.radialGradient = options.copy.radialGradient.cloneNode(true)
break
}
// create linear gradient paint
} else if (options.linearGradient) {
this.type = 'linearGradient';
this.solidColor = null;
this.radialGradient = null;
if(options.linearGradient.hasAttribute('xlink:href')) {
const xhref = document.getElementById(options.linearGradient.getAttribute('xlink:href').substr(1));
this.linearGradient = xhref.cloneNode(true);
this.type = 'linearGradient'
this.solidColor = null
this.radialGradient = null
if (options.linearGradient.hasAttribute('xlink:href')) {
const xhref = document.getElementById(options.linearGradient.getAttribute('xlink:href').substr(1))
this.linearGradient = xhref.cloneNode(true)
} else {
this.linearGradient = options.linearGradient.cloneNode(true);
this.linearGradient = options.linearGradient.cloneNode(true)
}
// create linear gradient paint
} else if (options.radialGradient) {
this.type = 'radialGradient';
this.solidColor = null;
this.linearGradient = null;
if(options.radialGradient.hasAttribute('xlink:href')) {
const xhref = document.getElementById(options.radialGradient.getAttribute('xlink:href').substr(1));
this.radialGradient = xhref.cloneNode(true);
this.type = 'radialGradient'
this.solidColor = null
this.linearGradient = null
if (options.radialGradient.hasAttribute('xlink:href')) {
const xhref = document.getElementById(options.radialGradient.getAttribute('xlink:href').substr(1))
this.radialGradient = xhref.cloneNode(true)
} else {
this.radialGradient = options.radialGradient.cloneNode(true);
this.radialGradient = options.radialGradient.cloneNode(true)
}
// create solid color paint
} else if (options.solidColor) {
this.type = 'solidColor';
this.solidColor = options.solidColor;
this.type = 'solidColor'
this.solidColor = options.solidColor
// create empty paint
} else {
this.type = 'none';
this.solidColor = null;
this.linearGradient = null;
this.radialGradient = null;
this.type = 'none'
this.solidColor = null
this.linearGradient = null
this.radialGradient = null
}
}
}
}

View File

@ -1,6 +1,6 @@
/* globals svgEditor */
import { t } from '../locale.js';
const template = document.createElement('template');
import { t } from '../locale.js'
const template = document.createElement('template')
template.innerHTML = `
<style>
:host(:hover) :not(.disabled)
@ -39,7 +39,7 @@ template.innerHTML = `
<div title="title">
<img alt="icon">
</div>
`;
`
/**
* @class ToolButton
*/
@ -48,22 +48,24 @@ export class ToolButton extends HTMLElement {
* @function constructor
*/
constructor () {
super();
super()
// create the shadowDom and insert the template
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.append(template.content.cloneNode(true));
this._shadowRoot = this.attachShadow({ mode: 'open' })
this._shadowRoot.append(template.content.cloneNode(true))
// locate the component
this.$div = this._shadowRoot.querySelector('div');
this.$img = this._shadowRoot.querySelector('img');
this.imgPath = svgEditor.configObj.curConfig.imgPath;
this.$div = this._shadowRoot.querySelector('div')
this.$img = this._shadowRoot.querySelector('img')
this.imgPath = svgEditor.configObj.curConfig.imgPath
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'title', 'src', 'pressed', 'disabled', 'size', 'style' ];
return ['title', 'src', 'pressed', 'disabled', 'size', 'style']
}
/**
* @function attributeChangedCallback
* @param {string} name
@ -72,56 +74,57 @@ export class ToolButton extends HTMLElement {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
if (oldValue === newValue) return;
if (oldValue === newValue) return
switch (name) {
case 'title':
{
const shortcut = this.getAttribute('shortcut');
this.$div.setAttribute('title', `${t(newValue)} ${shortcut ? `[${t(shortcut)}]` : ''}`);
}
break;
case 'style':
this.$div.style = newValue;
break;
case 'src':
if (newValue.indexOf("data:") !== -1) {
this.$img.setAttribute('src', newValue);
} else {
this.$img.setAttribute('src', this.imgPath + "/" + newValue);
}
break;
case 'pressed':
if (newValue === null) {
this.$div.classList.remove('pressed');
} else {
this.$div.classList.add('pressed');
}
break;
case 'size':
if (newValue === 'small') {
this.$div.classList.add('small');
} else {
this.$div.classList.remove('small');
}
break;
case 'disabled':
if (newValue) {
this.$div.classList.add('disabled');
} else {
this.$div.classList.remove('disabled');
}
break;
default:
console.error(`unknown attribute: ${name}`);
break;
case 'title':
{
const shortcut = this.getAttribute('shortcut')
this.$div.setAttribute('title', `${t(newValue)} ${shortcut ? `[${t(shortcut)}]` : ''}`)
}
break
case 'style':
this.$div.style = newValue
break
case 'src':
if (newValue.indexOf('data:') !== -1) {
this.$img.setAttribute('src', newValue)
} else {
this.$img.setAttribute('src', this.imgPath + '/' + newValue)
}
break
case 'pressed':
if (newValue === null) {
this.$div.classList.remove('pressed')
} else {
this.$div.classList.add('pressed')
}
break
case 'size':
if (newValue === 'small') {
this.$div.classList.add('small')
} else {
this.$div.classList.remove('small')
}
break
case 'disabled':
if (newValue) {
this.$div.classList.add('disabled')
} else {
this.$div.classList.remove('disabled')
}
break
default:
console.error(`unknown attribute: ${name}`)
break
}
}
/**
* @function get
* @returns {any}
*/
get title () {
return this.getAttribute('title');
return this.getAttribute('title')
}
/**
@ -129,14 +132,15 @@ export class ToolButton extends HTMLElement {
* @returns {void}
*/
set title (value) {
this.setAttribute('title', value);
this.setAttribute('title', value)
}
/**
* @function get
* @returns {any}
*/
get pressed () {
return this.hasAttribute('pressed');
return this.hasAttribute('pressed')
}
/**
@ -146,17 +150,18 @@ export class ToolButton extends HTMLElement {
set pressed (value) {
// boolean value => existence = true
if (value) {
this.setAttribute('pressed', 'true');
this.setAttribute('pressed', 'true')
} else {
this.removeAttribute('pressed');
this.removeAttribute('pressed')
}
}
/**
* @function get
* @returns {any}
*/
get disabled () {
return this.hasAttribute('disabled');
return this.hasAttribute('disabled')
}
/**
@ -166,17 +171,18 @@ export class ToolButton extends HTMLElement {
set disabled (value) {
// boolean value => existence = true
if (value) {
this.setAttribute('disabled', 'true');
this.setAttribute('disabled', 'true')
} else {
this.removeAttribute('disabled');
this.removeAttribute('disabled')
}
}
/**
* @function get
* @returns {any}
*/
get src () {
return this.getAttribute('src');
return this.getAttribute('src')
}
/**
@ -184,7 +190,7 @@ export class ToolButton extends HTMLElement {
* @returns {void}
*/
set src (value) {
this.setAttribute('src', value);
this.setAttribute('src', value)
}
/**
@ -192,7 +198,7 @@ export class ToolButton extends HTMLElement {
* @returns {any}
*/
get size () {
return this.getAttribute('size');
return this.getAttribute('size')
}
/**
@ -200,7 +206,7 @@ export class ToolButton extends HTMLElement {
* @returns {void}
*/
set size (value) {
this.setAttribute('size', value);
this.setAttribute('size', value)
}
/**
@ -209,22 +215,22 @@ export class ToolButton extends HTMLElement {
*/
connectedCallback () {
// capture shortcuts
const shortcut = this.getAttribute('shortcut');
const shortcut = this.getAttribute('shortcut')
if (shortcut) {
// register the keydown event
document.addEventListener('keydown', (e) => {
// only track keyboard shortcuts for the body containing the SVG-Editor
if (e.target.nodeName !== 'BODY') return;
if (e.target.nodeName !== 'BODY') return
// normalize key
const key = `${(e.metaKey) ? 'meta+' : ''}${(e.ctrlKey) ? 'ctrl+' : ''}${e.key.toUpperCase()}`;
if (shortcut !== key) return;
const key = `${(e.metaKey) ? 'meta+' : ''}${(e.ctrlKey) ? 'ctrl+' : ''}${e.key.toUpperCase()}`
if (shortcut !== key) return
// launch the click event
this.click();
e.preventDefault();
});
this.click()
e.preventDefault()
})
}
}
}
// Register
customElements.define('se-button', ToolButton);
customElements.define('se-button', ToolButton)

View File

@ -1,9 +1,9 @@
/* globals svgEditor */
import { jGraduate, jGraduateMethod } from './jgraduate/jQuery.jGraduate.js';
import PaintBox from './PaintBox.js';
import { t } from '../locale.js';
import { jGraduate, jGraduateMethod } from './jgraduate/jQuery.jGraduate.js'
import PaintBox from './PaintBox.js'
import { t } from '../locale.js'
const template = document.createElement('template');
const template = document.createElement('template')
template.innerHTML = `
<style>
.jPicker .Icon {
@ -645,7 +645,7 @@ div.jGraduate_Slider img {
</div>
<!-- hidden div -->
<div id="color_picker"></div>
`;
`
/**
* @class SeColorPicker
*/
@ -654,35 +654,38 @@ export class SeColorPicker extends HTMLElement {
* @function constructor
*/
constructor () {
super();
super()
// create the shadowDom and insert the template
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.append(template.content.cloneNode(true));
this.$logo = this._shadowRoot.getElementById('logo');
this.$label = this._shadowRoot.getElementById('label');
this.$block = this._shadowRoot.getElementById('block');
this.paintBox = null;
this.i18next = null;
this.$picker = this._shadowRoot.getElementById('picker');
this.$color_picker = this._shadowRoot.getElementById('color_picker');
this.imgPath = svgEditor.configObj.curConfig.imgPath;
this._shadowRoot = this.attachShadow({ mode: 'open' })
this._shadowRoot.append(template.content.cloneNode(true))
this.$logo = this._shadowRoot.getElementById('logo')
this.$label = this._shadowRoot.getElementById('label')
this.$block = this._shadowRoot.getElementById('block')
this.paintBox = null
this.i18next = null
this.$picker = this._shadowRoot.getElementById('picker')
this.$color_picker = this._shadowRoot.getElementById('color_picker')
this.imgPath = svgEditor.configObj.curConfig.imgPath
}
/**
* @function init
* @param {any} name
* @returns {void}
*/
init (i18next) {
this.i18next = i18next;
this.setAttribute('config-change_xxx_color', t('config.change_xxx_color'));
this.i18next = i18next
this.setAttribute('config-change_xxx_color', t('config.change_xxx_color'))
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'label', 'src', 'type', 'config-change_xxx_color' ];
return ['label', 'src', 'type', 'config-change_xxx_color']
}
/**
* @function attributeChangedCallback
* @param {string} name
@ -691,31 +694,32 @@ export class SeColorPicker extends HTMLElement {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
if (oldValue === newValue) return;
if (oldValue === newValue) return
switch (name) {
case 'src':
this.$logo.setAttribute('src', this.imgPath + '/' + newValue);
break;
case 'label':
this.setAttribute('title', t(newValue));
break;
case 'type':
this.$label.setAttribute('title', 'config.pick_paint_opavity');
break;
case 'config-change_xxx_color':
this.$label.setAttribute('title', newValue);
break;
default:
console.error(`unknown attribute: ${name}`);
break;
case 'src':
this.$logo.setAttribute('src', this.imgPath + '/' + newValue)
break
case 'label':
this.setAttribute('title', t(newValue))
break
case 'type':
this.$label.setAttribute('title', 'config.pick_paint_opavity')
break
case 'config-change_xxx_color':
this.$label.setAttribute('title', newValue)
break
default:
console.error(`unknown attribute: ${name}`)
break
}
}
/**
* @function get
* @returns {any}
*/
get label () {
return this.$label.getAttribute('title');
return this.$label.getAttribute('title')
}
/**
@ -723,14 +727,15 @@ export class SeColorPicker extends HTMLElement {
* @returns {void}
*/
set label (value) {
this.setAttribute('label', value);
this.setAttribute('label', value)
}
/**
* @function get
* @returns {any}
*/
get type () {
return this.getAttribute('type');
return this.getAttribute('type')
}
/**
@ -738,14 +743,15 @@ export class SeColorPicker extends HTMLElement {
* @returns {void}
*/
set type (value) {
this.setAttribute('type', value);
this.setAttribute('type', value)
}
/**
* @function get
* @returns {any}
*/
get src () {
return this.getAttribute('src');
return this.getAttribute('src')
}
/**
@ -753,7 +759,7 @@ export class SeColorPicker extends HTMLElement {
* @returns {void}
*/
set src (value) {
this.setAttribute('src', value);
this.setAttribute('src', value)
}
/**
@ -763,20 +769,23 @@ export class SeColorPicker extends HTMLElement {
* @returns {void}
*/
update (svgCanvas, selectedElement, apply) {
const paint = this.paintBox.update(svgCanvas, selectedElement);
const paint = this.paintBox.update(svgCanvas, selectedElement)
if (paint && apply) {
const changeEvent = new CustomEvent('change', { detail: {
paint
} });
this.dispatchEvent(changeEvent);
const changeEvent = new CustomEvent('change', {
detail: {
paint
}
})
this.dispatchEvent(changeEvent)
}
}
/**
* @param {PlainObject} paint
* @returns {void}
*/
setPaint (paint) {
this.paintBox.setPaint(paint);
this.paintBox.setPaint(paint)
}
/**
@ -784,9 +793,9 @@ export class SeColorPicker extends HTMLElement {
* @returns {void}
*/
connectedCallback () {
this.paintBox = new PaintBox(this.$block, this.type);
this.paintBox = new PaintBox(this.$block, this.type)
this.$picker.addEventListener('click', () => {
let { paint } = this.paintBox;
let { paint } = this.paintBox
jGraduateMethod(
this.$color_picker,
{
@ -796,22 +805,24 @@ export class SeColorPicker extends HTMLElement {
newstop: 'inverse'
},
(p) => {
paint = new jGraduate.Paint(p);
this.setPaint(paint);
const changeEvent = new CustomEvent('change', { detail: {
paint
} });
this.dispatchEvent(changeEvent);
this.$color_picker.style.display = 'none';
paint = new jGraduate.Paint(p)
this.setPaint(paint)
const changeEvent = new CustomEvent('change', {
detail: {
paint
}
})
this.dispatchEvent(changeEvent)
this.$color_picker.style.display = 'none'
},
() => {
this.$color_picker.style.display = 'none';
this.$color_picker.style.display = 'none'
},
this.i18next
);
});
)
})
}
}
// Register
customElements.define('se-colorpicker', SeColorPicker);
customElements.define('se-colorpicker', SeColorPicker)

View File

@ -1,8 +1,8 @@
import ListComboBox from 'elix/define/ListComboBox.js';
import { defaultState } from 'elix/src/base/internal.js';
import { templateFrom, fragmentFrom } from 'elix/src/core/htmlLiterals.js';
import { internal } from 'elix';
import NumberSpinBox from '../dialogs/se-elix/define/NumberSpinBox.js';
import ListComboBox from 'elix/define/ListComboBox.js'
import { defaultState } from 'elix/src/base/internal.js'
import { templateFrom, fragmentFrom } from 'elix/src/core/htmlLiterals.js'
import { internal } from 'elix'
import NumberSpinBox from '../dialogs/se-elix/define/NumberSpinBox.js'
/**
* @class Dropdown
@ -15,21 +15,22 @@ class Dropdown extends ListComboBox {
get [defaultState] () {
return Object.assign(super[defaultState], {
inputPartType: NumberSpinBox,
src: "logo.svg",
src: 'logo.svg',
inputsize: '100%'
});
})
}
/**
* @function get
* @returns {PlainObject}
*/
get [internal.template] () {
const result = super[internal.template];
const source = result.content.getElementById('source');
const result = super[internal.template]
const source = result.content.getElementById('source')
// add a icon before our dropdown
source.prepend(fragmentFrom.html`
<img src="dropdown.svg" alt="icon" width="18" height="18"></img>
`.cloneNode(true));
`.cloneNode(true))
// change the style so it fits in our toolbar
result.content.append(
templateFrom.html`
@ -48,16 +49,18 @@ class Dropdown extends ListComboBox {
}
</style>
`.content
);
return result;
)
return result
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'title', 'src', 'inputsize', 'value' ];
return ['title', 'src', 'inputsize', 'value']
}
/**
* @function attributeChangedCallback
* @param {string} name
@ -66,97 +69,104 @@ class Dropdown extends ListComboBox {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
if (oldValue === newValue) return;
if (oldValue === newValue) return
switch (name) {
case 'title':
case 'title':
// this.$span.setAttribute('title', `${newValue} ${shortcut ? `[${shortcut}]` : ''}`);
break;
case 'src':
this.src = newValue;
break;
case 'inputsize':
this.inputsize = newValue;
break;
default:
super.attributeChangedCallback(name, oldValue, newValue);
break;
break
case 'src':
this.src = newValue
break
case 'inputsize':
this.inputsize = newValue
break
default:
super.attributeChangedCallback(name, oldValue, newValue)
break
}
}
/**
* @function [internal.render]
* @param {PlainObject} changed
* @returns {void}
*/
[internal.render] (changed) {
super[internal.render](changed);
super[internal.render](changed)
if (this[internal.firstRender]) {
this.$img = this.shadowRoot.querySelector('img');
this.$input = this.shadowRoot.getElementById('input');
this.$img = this.shadowRoot.querySelector('img')
this.$input = this.shadowRoot.getElementById('input')
}
if (changed.src) {
this.$img.setAttribute('src', this[internal.state].src);
this.$img.setAttribute('src', this[internal.state].src)
}
if (changed.inputsize) {
this.$input.shadowRoot.querySelector('[part~="input"]').style.width = this[internal.state].inputsize;
this.$input.shadowRoot.querySelector('[part~="input"]').style.width = this[internal.state].inputsize
}
if (changed.inputPartType) {
// Wire up handler on new input.
this.addEventListener('close', (e) => {
e.preventDefault();
const value = e.detail?.closeResult?.getAttribute('value');
e.preventDefault()
const value = e.detail?.closeResult?.getAttribute('value')
if (value) {
const closeEvent = new CustomEvent('change', { detail: { value } });
this.dispatchEvent(closeEvent);
const closeEvent = new CustomEvent('change', { detail: { value } })
this.dispatchEvent(closeEvent)
}
});
})
}
}
/**
* @function src
* @returns {string} src
*/
get src () {
return this[internal.state].src;
return this[internal.state].src
}
/**
* @function src
* @returns {void}
*/
set src (src) {
this[internal.setState]({ src });
this[internal.setState]({ src })
}
/**
* @function inputsize
* @returns {string} src
*/
get inputsize () {
return this[internal.state].inputsize;
return this[internal.state].inputsize
}
/**
* @function src
* @returns {void}
*/
set inputsize (inputsize) {
this[internal.setState]({ inputsize });
this[internal.setState]({ inputsize })
}
/**
* @function value
* @returns {string} src
*/
get value () {
return this[internal.state].value;
return this[internal.state].value
}
/**
* @function value
* @returns {void}
*/
set value (value) {
this[internal.setState]({ value });
this[internal.setState]({ value })
}
}
// Register
customElements.define('se-dropdown', Dropdown);
customElements.define('se-dropdown', Dropdown)
/*
{TODO

View File

@ -1,6 +1,5 @@
/* globals svgEditor */
/* eslint-disable no-unsanitized/property */
const template = document.createElement('template');
const template = document.createElement('template')
template.innerHTML = `
<style>
:host {
@ -98,7 +97,7 @@ template.innerHTML = `
</div>
</div>
`;
`
/**
* @class ExplorerButton
*/
@ -107,28 +106,30 @@ export class ExplorerButton extends HTMLElement {
* @function constructor
*/
constructor () {
super();
super()
// create the shadowDom and insert the template
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.append(template.content.cloneNode(true));
this._shadowRoot = this.attachShadow({ mode: 'open' })
this._shadowRoot.append(template.content.cloneNode(true))
// locate the component
this.$button = this._shadowRoot.querySelector('.menu-button');
this.$overall = this._shadowRoot.querySelector('.overall');
this.$img = this._shadowRoot.querySelector('.menu-button img');
this.$menu = this._shadowRoot.querySelector('.menu');
this.$handle = this._shadowRoot.querySelector('.handle');
this.$lib = this._shadowRoot.querySelector('.image-lib');
this.files = [];
this.request = new XMLHttpRequest();
this.imgPath = svgEditor.configObj.curConfig.imgPath;
this.$button = this._shadowRoot.querySelector('.menu-button')
this.$overall = this._shadowRoot.querySelector('.overall')
this.$img = this._shadowRoot.querySelector('.menu-button img')
this.$menu = this._shadowRoot.querySelector('.menu')
this.$handle = this._shadowRoot.querySelector('.handle')
this.$lib = this._shadowRoot.querySelector('.image-lib')
this.files = []
this.request = new XMLHttpRequest()
this.imgPath = svgEditor.configObj.curConfig.imgPath
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'title', 'pressed', 'disabled', 'lib', 'src' ];
return ['title', 'pressed', 'disabled', 'lib', 'src']
}
/**
* @function attributeChangedCallback
* @param {string} name
@ -137,55 +138,56 @@ export class ExplorerButton extends HTMLElement {
* @returns {void}
*/
async attributeChangedCallback (name, oldValue, newValue) {
if (oldValue === newValue) return;
if (oldValue === newValue) return
switch (name) {
case 'title':
{
const shortcut = this.getAttribute('shortcut');
this.$button.setAttribute('title', `${newValue} [${shortcut}]`);
}
break;
case 'pressed':
if (newValue) {
this.$overall.classList.add('pressed');
} else {
this.$overall.classList.remove('pressed');
}
break;
case 'disabled':
if (newValue) {
this.$overall.classList.add('disabled');
} else {
this.$overall.classList.remove('disabled');
}
break;
case 'lib':
try {
const response = await fetch(`${newValue}index.json`);
const json = await response.json();
const { lib } = json;
this.$menu.innerHTML = lib.map((menu, i) => (
case 'title':
{
const shortcut = this.getAttribute('shortcut')
this.$button.setAttribute('title', `${newValue} [${shortcut}]`)
}
break
case 'pressed':
if (newValue) {
this.$overall.classList.add('pressed')
} else {
this.$overall.classList.remove('pressed')
}
break
case 'disabled':
if (newValue) {
this.$overall.classList.add('disabled')
} else {
this.$overall.classList.remove('disabled')
}
break
case 'lib':
try {
const response = await fetch(`${newValue}index.json`)
const json = await response.json()
const { lib } = json
this.$menu.innerHTML = lib.map((menu, i) => (
`<div data-menu="${menu}" class="menu-item ${(i === 0) ? 'pressed' : ''} ">${menu}</div>`
)).join('');
await this.updateLib(lib[0]);
} catch (error) {
console.error(error);
}
break;
case 'src':
this.$img.setAttribute('src', this.imgPath + '/' + newValue);
break;
default:
console.error(`unknown attribute: ${name}`);
break;
)).join('')
await this.updateLib(lib[0])
} catch (error) {
console.error(error)
}
break
case 'src':
this.$img.setAttribute('src', this.imgPath + '/' + newValue)
break
default:
console.error(`unknown attribute: ${name}`)
break
}
}
/**
* @function get
* @returns {any}
*/
get title () {
return this.getAttribute('title');
return this.getAttribute('title')
}
/**
@ -193,14 +195,15 @@ export class ExplorerButton extends HTMLElement {
* @returns {void}
*/
set title (value) {
this.setAttribute('title', value);
this.setAttribute('title', value)
}
/**
* @function get
* @returns {any}
*/
get pressed () {
return this.hasAttribute('pressed');
return this.hasAttribute('pressed')
}
/**
@ -210,17 +213,18 @@ export class ExplorerButton extends HTMLElement {
set pressed (value) {
// boolean value => existence = true
if (value) {
this.setAttribute('pressed', 'true');
this.setAttribute('pressed', 'true')
} else {
this.removeAttribute('pressed', '');
this.removeAttribute('pressed', '')
}
}
/**
* @function get
* @returns {any}
*/
get disabled () {
return this.hasAttribute('disabled');
return this.hasAttribute('disabled')
}
/**
@ -230,11 +234,12 @@ export class ExplorerButton extends HTMLElement {
set disabled (value) {
// boolean value => existence = true
if (value) {
this.setAttribute('disabled', 'true');
this.setAttribute('disabled', 'true')
} else {
this.removeAttribute('disabled', '');
this.removeAttribute('disabled', '')
}
}
/**
* @function connectedCallback
* @returns {void}
@ -242,73 +247,74 @@ export class ExplorerButton extends HTMLElement {
connectedCallback () {
// capture click event on the button to manage the logic
const onClickHandler = (ev) => {
ev.stopPropagation();
ev.stopPropagation()
switch (ev.target.nodeName) {
case 'SE-EXPLORERBUTTON':
this.$menu.classList.add('open');
this.$lib.classList.add('open-lib');
break;
case 'SE-BUTTON':
case 'SE-EXPLORERBUTTON':
this.$menu.classList.add('open')
this.$lib.classList.add('open-lib')
break
case 'SE-BUTTON':
// change to the current action
this.currentAction = ev.target;
this.$img.setAttribute('src', this.currentAction.getAttribute('src'));
this.dataset.draw = this.data[this.currentAction.dataset.shape];
this._shadowRoot.querySelectorAll('.image-lib [pressed]').forEach((b) => { b.pressed = false; });
this.currentAction.setAttribute('pressed', 'pressed');
// and close the menu
this.$menu.classList.remove('open');
this.$lib.classList.remove('open-lib');
break;
case 'DIV':
if (ev.target.classList[0] === 'handle') {
this.currentAction = ev.target
this.$img.setAttribute('src', this.currentAction.getAttribute('src'))
this.dataset.draw = this.data[this.currentAction.dataset.shape]
this._shadowRoot.querySelectorAll('.image-lib [pressed]').forEach((b) => { b.pressed = false })
this.currentAction.setAttribute('pressed', 'pressed')
// and close the menu
this.$menu.classList.remove('open')
this.$lib.classList.remove('open-lib')
break
case 'DIV':
if (ev.target.classList[0] === 'handle') {
// this is a click on the handle so let's open/close the menu.
this.$menu.classList.toggle('open');
this.$lib.classList.toggle('open-lib');
} else {
this._shadowRoot.querySelectorAll('.menu > .pressed').forEach((b) => { b.classList.remove('pressed'); });
ev.target.classList.add('pressed');
this.updateLib(ev.target.dataset.menu);
}
break;
default:
console.error('unknown nodeName for:', ev.target, ev.target.className);
this.$menu.classList.toggle('open')
this.$lib.classList.toggle('open-lib')
} else {
this._shadowRoot.querySelectorAll('.menu > .pressed').forEach((b) => { b.classList.remove('pressed') })
ev.target.classList.add('pressed')
this.updateLib(ev.target.dataset.menu)
}
break
default:
console.error('unknown nodeName for:', ev.target, ev.target.className)
}
};
}
// capture event from slots
this.addEventListener('click', onClickHandler);
this.$menu.addEventListener('click', onClickHandler);
this.$lib.addEventListener('click', onClickHandler);
this.$handle.addEventListener('click', onClickHandler);
this.addEventListener('click', onClickHandler)
this.$menu.addEventListener('click', onClickHandler)
this.$lib.addEventListener('click', onClickHandler)
this.$handle.addEventListener('click', onClickHandler)
}
/**
* @function updateLib
* @param {string} lib
* @returns {void}
*/
async updateLib (lib) {
const libDir = this.getAttribute('lib');
const libDir = this.getAttribute('lib')
try {
// initialize buttons for all shapes defined for this library
const response = await fetch(`${libDir}${lib}.json`);
const json = await response.json();
this.data = json.data;
const size = json.size ?? 300;
const fill = json.fill ? '#333' : 'none';
const off = size * 0.05;
const vb = [ -off, -off, size + off * 2, size + off * 2 ].join(' ');
const stroke = json.fill ? 0 : (size / 30);
this.$lib.innerHTML = Object.entries(this.data).map(([ key, path ]) => {
const response = await fetch(`${libDir}${lib}.json`)
const json = await response.json()
this.data = json.data
const size = json.size ?? 300
const fill = json.fill ? '#333' : 'none'
const off = size * 0.05
const vb = [-off, -off, size + off * 2, size + off * 2].join(' ')
const stroke = json.fill ? 0 : (size / 30)
this.$lib.innerHTML = Object.entries(this.data).map(([key, path]) => {
const encoded = btoa(`
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24">
<svg viewBox="${vb}"><path fill="${fill}" stroke="#f8bb00" stroke-width="${stroke}" d="${path}"></path></svg>
</svg>`);
return `<se-button data-shape="${key}"src="data:image/svg+xml;base64,${encoded}"></se-button>`;
}).join('');
</svg>`)
return `<se-button data-shape="${key}"src="data:image/svg+xml;base64,${encoded}"></se-button>`
}).join('')
} catch (error) {
console.error(`could not read file:${libDir}${lib}.json`, error);
console.error(`could not read file:${libDir}${lib}.json`, error)
}
}
}
// Register
customElements.define('se-explorerbutton', ExplorerButton);
customElements.define('se-explorerbutton', ExplorerButton)

View File

@ -1,6 +1,6 @@
/* globals svgEditor */
import { t } from '../locale.js';
const template = document.createElement('template');
import { t } from '../locale.js'
const template = document.createElement('template')
template.innerHTML = `
<style>
:host {
@ -79,7 +79,7 @@ template.innerHTML = `
</div>
`;
`
/**
* @class FlyingButton
*/
@ -88,28 +88,30 @@ export class FlyingButton extends HTMLElement {
* @function constructor
*/
constructor () {
super();
super()
// create the shadowDom and insert the template
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.append(template.content.cloneNode(true));
this._shadowRoot = this.attachShadow({ mode: 'open' })
this._shadowRoot.append(template.content.cloneNode(true))
// locate the component
this.$button = this._shadowRoot.querySelector('.menu-button');
this.$handle = this._shadowRoot.querySelector('.handle');
this.$overall = this._shadowRoot.querySelector('.overall');
this.$img = this._shadowRoot.querySelector('img');
this.$menu = this._shadowRoot.querySelector('.menu');
this.$button = this._shadowRoot.querySelector('.menu-button')
this.$handle = this._shadowRoot.querySelector('.handle')
this.$overall = this._shadowRoot.querySelector('.overall')
this.$img = this._shadowRoot.querySelector('img')
this.$menu = this._shadowRoot.querySelector('.menu')
// the last element of the div is the slot
// we retrieve all elements added in the slot (i.e. se-buttons)
this.$elements = this.$menu.lastElementChild.assignedElements();
this.imgPath = svgEditor.configObj.curConfig.imgPath;
this.$elements = this.$menu.lastElementChild.assignedElements()
this.imgPath = svgEditor.configObj.curConfig.imgPath
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'title', 'pressed', 'disabled', 'opened' ];
return ['title', 'pressed', 'disabled', 'opened']
}
/**
* @function attributeChangedCallback
* @param {string} name
@ -118,46 +120,47 @@ export class FlyingButton extends HTMLElement {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
if (oldValue === newValue) return;
if (oldValue === newValue) return
switch (name) {
case 'title':
{
const shortcut = this.getAttribute('shortcut');
this.$button.setAttribute('title', `${t(newValue)} ${shortcut ? `[${t(shortcut)}]` : ''}`);
}
break;
case 'pressed':
if (newValue) {
this.$overall.classList.add('pressed');
} else {
this.$overall.classList.remove('pressed');
}
break;
case 'opened':
if (newValue) {
this.$menu.classList.add('open');
} else {
this.$menu.classList.remove('open');
}
break;
case 'disabled':
if (newValue) {
this.$overall.classList.add('disabled');
} else {
this.$overall.classList.remove('disabled');
}
break;
default:
console.error(`unknown attribute: ${name}`);
break;
case 'title':
{
const shortcut = this.getAttribute('shortcut')
this.$button.setAttribute('title', `${t(newValue)} ${shortcut ? `[${t(shortcut)}]` : ''}`)
}
break
case 'pressed':
if (newValue) {
this.$overall.classList.add('pressed')
} else {
this.$overall.classList.remove('pressed')
}
break
case 'opened':
if (newValue) {
this.$menu.classList.add('open')
} else {
this.$menu.classList.remove('open')
}
break
case 'disabled':
if (newValue) {
this.$overall.classList.add('disabled')
} else {
this.$overall.classList.remove('disabled')
}
break
default:
console.error(`unknown attribute: ${name}`)
break
}
}
/**
* @function get
* @returns {any}
*/
get title () {
return this.getAttribute('title');
return this.getAttribute('title')
}
/**
@ -165,14 +168,15 @@ export class FlyingButton extends HTMLElement {
* @returns {void}
*/
set title (value) {
this.setAttribute('title', value);
this.setAttribute('title', value)
}
/**
* @function get
* @returns {any}
*/
get pressed () {
return this.hasAttribute('pressed');
return this.hasAttribute('pressed')
}
/**
@ -182,19 +186,20 @@ export class FlyingButton extends HTMLElement {
set pressed (value) {
// boolean value => existence = true
if (value) {
this.setAttribute('pressed', 'true');
this.setAttribute('pressed', 'true')
} else {
this.removeAttribute('pressed', '');
this.removeAttribute('pressed', '')
// close also the menu if open
this.removeAttribute('opened');
this.removeAttribute('opened')
}
}
/**
* @function get
* @returns {any}
*/
get opened () {
return this.hasAttribute('opened');
return this.hasAttribute('opened')
}
/**
@ -204,17 +209,18 @@ export class FlyingButton extends HTMLElement {
set opened (value) {
// boolean value => existence = true
if (value) {
this.setAttribute('opened', 'opened');
this.setAttribute('opened', 'opened')
} else {
this.removeAttribute('opened');
this.removeAttribute('opened')
}
}
/**
* @function get
* @returns {any}
*/
get disabled () {
return this.hasAttribute('disabled');
return this.hasAttribute('disabled')
}
/**
@ -224,59 +230,60 @@ export class FlyingButton extends HTMLElement {
set disabled (value) {
// boolean value => existence = true
if (value) {
this.setAttribute('disabled', 'true');
this.setAttribute('disabled', 'true')
} else {
this.removeAttribute('disabled', '');
this.removeAttribute('disabled', '')
}
}
/**
* @function connectedCallback
* @returns {void}
*/
connectedCallback () {
this.activeSlot = this.shadowRoot.querySelector('slot').assignedElements()[0];
this.$img.setAttribute('src', this.imgPath + '/' + this.activeSlot.getAttribute('src'));
this.activeSlot = this.shadowRoot.querySelector('slot').assignedElements()[0]
this.$img.setAttribute('src', this.imgPath + '/' + this.activeSlot.getAttribute('src'))
// capture click event on the button to manage the logic
const onClickHandler = (ev) => {
ev.stopPropagation();
ev.stopPropagation()
switch (ev.target.nodeName) {
case 'SE-FLYINGBUTTON':
if (this.pressed) {
this.setAttribute('opened', 'opened');
} else {
case 'SE-FLYINGBUTTON':
if (this.pressed) {
this.setAttribute('opened', 'opened')
} else {
// launch current action
this.activeSlot.click();
this.setAttribute('pressed', 'pressed');
}
break;
case 'SE-BUTTON':
this.activeSlot.click()
this.setAttribute('pressed', 'pressed')
}
break
case 'SE-BUTTON':
// change to the current action
this.$img.setAttribute('src', this.imgPath + '/' + ev.target.getAttribute('src'));
this.activeSlot = ev.target;
this.setAttribute('pressed', 'pressed');
// and close the menu
this.$menu.classList.remove('open');
break;
case 'DIV':
this.$img.setAttribute('src', this.imgPath + '/' + ev.target.getAttribute('src'))
this.activeSlot = ev.target
this.setAttribute('pressed', 'pressed')
// and close the menu
this.$menu.classList.remove('open')
break
case 'DIV':
// this is a click on the handle so let's open/close the menu.
if (this.opened) {
this.removeAttribute('opened');
} else {
this.setAttribute('opened', 'opened');
// In case menu scroll on top or bottom position based popup position set
const rect = this.getBoundingClientRect();
this.$menu.style.top = rect.top + "px";
}
break;
default:
console.error('unkonw nodeName for:', ev.target, ev.target.className);
if (this.opened) {
this.removeAttribute('opened')
} else {
this.setAttribute('opened', 'opened')
// In case menu scroll on top or bottom position based popup position set
const rect = this.getBoundingClientRect()
this.$menu.style.top = rect.top + 'px'
}
break
default:
console.error('unkonw nodeName for:', ev.target, ev.target.className)
}
};
}
// capture event from slots
this.addEventListener('click', onClickHandler);
this.$handle.addEventListener('click', onClickHandler);
this.addEventListener('click', onClickHandler)
this.$handle.addEventListener('click', onClickHandler)
}
}
// Register
customElements.define('se-flyingbutton', FlyingButton);
customElements.define('se-flyingbutton', FlyingButton)

View File

@ -1,7 +1,7 @@
import 'elix/define/Input.js';
import { t } from '../locale.js';
import 'elix/define/Input.js'
import { t } from '../locale.js'
const template = document.createElement('template');
const template = document.createElement('template')
template.innerHTML = `
<style>
div {
@ -32,7 +32,7 @@ template.innerHTML = `
<span id="label">label</span>
<elix-input></elix-input>
</div>
`;
`
/**
* @class SEInput
@ -42,24 +42,26 @@ export class SEInput extends HTMLElement {
* @function constructor
*/
constructor () {
super();
super()
// create the shadowDom and insert the template
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.append(template.content.cloneNode(true));
this._shadowRoot = this.attachShadow({ mode: 'open' })
this._shadowRoot.append(template.content.cloneNode(true))
// locate the component
this.$div = this._shadowRoot.querySelector('div');
this.$img = this._shadowRoot.querySelector('img');
this.$label = this.shadowRoot.getElementById('label');
this.$event = new CustomEvent('change');
this.$input = this._shadowRoot.querySelector('elix-input');
this.$div = this._shadowRoot.querySelector('div')
this.$img = this._shadowRoot.querySelector('img')
this.$label = this.shadowRoot.getElementById('label')
this.$event = new CustomEvent('change')
this.$input = this._shadowRoot.querySelector('elix-input')
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'value', 'label', 'src', 'size', 'title' ];
return ['value', 'label', 'src', 'size', 'title']
}
/**
* @function attributeChangedCallback
* @param {string} name
@ -68,36 +70,37 @@ export class SEInput extends HTMLElement {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
if (oldValue === newValue) return;
if (oldValue === newValue) return
switch (name) {
case 'title':
this.$div.setAttribute('title', `${t(newValue)}`);
break;
case 'src':
this.$img.setAttribute('src', newValue);
this.$label.remove();
break;
case 'size':
this.$input.setAttribute('size', newValue);
break;
case 'label':
this.$label.textContent = t(newValue);
this.$img.remove();
break;
case 'value':
this.$input.value = newValue;
break;
default:
console.error(`unknown attribute: ${name}`);
break;
case 'title':
this.$div.setAttribute('title', `${t(newValue)}`)
break
case 'src':
this.$img.setAttribute('src', newValue)
this.$label.remove()
break
case 'size':
this.$input.setAttribute('size', newValue)
break
case 'label':
this.$label.textContent = t(newValue)
this.$img.remove()
break
case 'value':
this.$input.value = newValue
break
default:
console.error(`unknown attribute: ${name}`)
break
}
}
/**
* @function get
* @returns {any}
*/
get title () {
return this.getAttribute('title');
return this.getAttribute('title')
}
/**
@ -105,14 +108,15 @@ export class SEInput extends HTMLElement {
* @returns {void}
*/
set title (value) {
this.setAttribute('title', value);
this.setAttribute('title', value)
}
/**
* @function get
* @returns {any}
*/
get label () {
return this.getAttribute('label');
return this.getAttribute('label')
}
/**
@ -120,14 +124,15 @@ export class SEInput extends HTMLElement {
* @returns {void}
*/
set label (value) {
this.setAttribute('label', value);
this.setAttribute('label', value)
}
/**
* @function get
* @returns {any}
*/
get value () {
return this.$input.value;
return this.$input.value
}
/**
@ -135,14 +140,15 @@ export class SEInput extends HTMLElement {
* @returns {void}
*/
set value (value) {
this.$input.value = value;
this.$input.value = value
}
/**
* @function get
* @returns {any}
*/
get src () {
return this.getAttribute('src');
return this.getAttribute('src')
}
/**
@ -150,7 +156,7 @@ export class SEInput extends HTMLElement {
* @returns {void}
*/
set src (value) {
this.setAttribute('src', value);
this.setAttribute('src', value)
}
/**
@ -158,7 +164,7 @@ export class SEInput extends HTMLElement {
* @returns {any}
*/
get size () {
return this.getAttribute('size');
return this.getAttribute('size')
}
/**
@ -166,7 +172,7 @@ export class SEInput extends HTMLElement {
* @returns {void}
*/
set size (value) {
this.setAttribute('size', value);
this.setAttribute('size', value)
}
/**
@ -175,16 +181,16 @@ export class SEInput extends HTMLElement {
*/
connectedCallback () {
this.$input.addEventListener('change', (e) => {
e.preventDefault();
this.value = e.target.value;
this.dispatchEvent(this.$event);
});
e.preventDefault()
this.value = e.target.value
this.dispatchEvent(this.$event)
})
this.$input.addEventListener('keyup', (e) => {
e.preventDefault();
this.value = e.target.value;
this.dispatchEvent(this.$event);
});
e.preventDefault()
this.value = e.target.value
this.dispatchEvent(this.$event)
})
}
}
// Register
customElements.define('se-input', SEInput);
customElements.define('se-input', SEInput)

View File

@ -1,8 +1,8 @@
/* globals svgEditor */
import 'elix/define/DropdownList.js';
import { t } from '../locale.js';
import 'elix/define/DropdownList.js'
import { t } from '../locale.js'
const template = document.createElement('template');
const template = document.createElement('template')
template.innerHTML = `
<style>
elix-dropdown-list {
@ -30,7 +30,7 @@ elix-dropdown-list::part(popup-toggle) {
<slot></slot>
</elix-dropdown-list>
`;
`
/**
* @class SeList
*/
@ -39,22 +39,23 @@ export class SeList extends HTMLElement {
* @function constructor
*/
constructor () {
super();
super()
// create the shadowDom and insert the template
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.append(template.content.cloneNode(true));
this.$dropdown = this._shadowRoot.querySelector('elix-dropdown-list');
this.$label = this._shadowRoot.querySelector('label');
this.$selection = this.$dropdown.shadowRoot.querySelector('#value');
this.items = this.querySelectorAll("se-list-item");
this.imgPath = svgEditor.configObj.curConfig.imgPath;
this._shadowRoot = this.attachShadow({ mode: 'open' })
this._shadowRoot.append(template.content.cloneNode(true))
this.$dropdown = this._shadowRoot.querySelector('elix-dropdown-list')
this.$label = this._shadowRoot.querySelector('label')
this.$selection = this.$dropdown.shadowRoot.querySelector('#value')
this.items = this.querySelectorAll('se-list-item')
this.imgPath = svgEditor.configObj.curConfig.imgPath
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'label', 'width', 'height', 'title', 'value' ];
return ['label', 'width', 'height', 'title', 'value']
}
/**
@ -65,51 +66,51 @@ export class SeList extends HTMLElement {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
const currentObj = this;
if (oldValue === newValue) return;
const currentObj = this
if (oldValue === newValue) return
switch (name) {
case 'title':
this.$dropdown.setAttribute('title', t(newValue));
break;
case 'label':
this.$label.textContent = t(newValue);
break;
case 'height':
this.$dropdown.style.height = newValue;
break;
case 'width':
this.$dropdown.style.width = newValue;
break;
case 'value':
Array.from(this.items).forEach(function (element) {
if(element.getAttribute("value") === newValue) {
if (element.hasAttribute("src")) {
case 'title':
this.$dropdown.setAttribute('title', t(newValue))
break
case 'label':
this.$label.textContent = t(newValue)
break
case 'height':
this.$dropdown.style.height = newValue
break
case 'width':
this.$dropdown.style.width = newValue
break
case 'value':
Array.from(this.items).forEach(function (element) {
if (element.getAttribute('value') === newValue) {
if (element.hasAttribute('src')) {
// empty current selection children
while(currentObj.$selection.firstChild)
currentObj.$selection.removeChild(currentObj.$selection.firstChild);
// replace selection child with image of new value
const img = document.createElement('img');
img.src = currentObj.imgPath + '/' + element.getAttribute("src");
img.style.height = element.getAttribute("img-height");
img.setAttribute('title', t(element.getAttribute("title")));
currentObj.$selection.append(img);
} else {
currentObj.$selection.textContent = t(element.getAttribute('option'));
while (currentObj.$selection.firstChild) { currentObj.$selection.removeChild(currentObj.$selection.firstChild) }
// replace selection child with image of new value
const img = document.createElement('img')
img.src = currentObj.imgPath + '/' + element.getAttribute('src')
img.style.height = element.getAttribute('img-height')
img.setAttribute('title', t(element.getAttribute('title')))
currentObj.$selection.append(img)
} else {
currentObj.$selection.textContent = t(element.getAttribute('option'))
}
}
}
});
break;
default:
console.error(`unknown attribute: ${name}`);
break;
})
break
default:
console.error(`unknown attribute: ${name}`)
break
}
}
/**
* @function get
* @returns {any}
*/
get title () {
return this.getAttribute('title');
return this.getAttribute('title')
}
/**
@ -117,14 +118,15 @@ export class SeList extends HTMLElement {
* @returns {void}
*/
set title (value) {
this.setAttribute('title', value);
this.setAttribute('title', value)
}
/**
* @function get
* @returns {any}
*/
get label () {
return this.getAttribute('label');
return this.getAttribute('label')
}
/**
@ -132,14 +134,15 @@ export class SeList extends HTMLElement {
* @returns {void}
*/
set label (value) {
this.setAttribute('label', value);
this.setAttribute('label', value)
}
/**
* @function get
* @returns {any}
*/
get width () {
return this.getAttribute('width');
return this.getAttribute('width')
}
/**
@ -147,14 +150,15 @@ export class SeList extends HTMLElement {
* @returns {void}
*/
set width (value) {
this.setAttribute('width', value);
this.setAttribute('width', value)
}
/**
* @function get
* @returns {any}
*/
get height () {
return this.getAttribute('height');
return this.getAttribute('height')
}
/**
@ -162,31 +166,32 @@ export class SeList extends HTMLElement {
* @returns {void}
*/
set height (value) {
this.setAttribute('height', value);
this.setAttribute('height', value)
}
/**
* @function connectedCallback
* @returns {void}
*/
connectedCallback () {
const currentObj = this;
const currentObj = this
this.$dropdown.addEventListener('selectedindexchange', (e) => {
if (e?.detail?.selectedIndex !== undefined) {
const value = this.$dropdown.selectedItem.getAttribute('value');
const closeEvent = new CustomEvent('change', { detail: { value } });
currentObj.dispatchEvent(closeEvent);
currentObj.value = value;
currentObj.setAttribute("value", value);
const value = this.$dropdown.selectedItem.getAttribute('value')
const closeEvent = new CustomEvent('change', { detail: { value } })
currentObj.dispatchEvent(closeEvent)
currentObj.value = value
currentObj.setAttribute('value', value)
}
});
})
this.$dropdown.addEventListener('close', (_e) => {
/** with Chrome, selectedindexchange does not fire consistently
* unless you forec change in this close event
*/
this.$dropdown.selectedIndex = this.$dropdown.currentIndex;
});
this.$dropdown.selectedIndex = this.$dropdown.currentIndex
})
}
}
// Register
customElements.define('se-list', SeList);
customElements.define('se-list', SeList)

View File

@ -1,8 +1,8 @@
/* globals svgEditor */
import 'elix/define/Option.js';
import { t } from '../locale.js';
import 'elix/define/Option.js'
import { t } from '../locale.js'
const template = document.createElement('template');
const template = document.createElement('template')
template.innerHTML = `
<style>
elix-option{
@ -17,7 +17,7 @@ template.innerHTML = `
<img alt="icon" />
<slot></slot>
</elix-option>
`;
`
/**
* @class SeMenu
*/
@ -26,23 +26,24 @@ export class SeListItem extends HTMLElement {
* @function constructor
*/
constructor () {
super();
super()
// create the shadowDom and insert the template
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.append(template.content.cloneNode(true));
this.$menuitem = this._shadowRoot.querySelector('elix-option');
this.$svg = this.$menuitem.shadowRoot.querySelector('#checkmark');
this.$svg.setAttribute('style', 'display: none;');
this.$img = this._shadowRoot.querySelector('img');
this.$img.setAttribute('style', 'display: none;');
this.imgPath = svgEditor.configObj.curConfig.imgPath;
this._shadowRoot = this.attachShadow({ mode: 'open' })
this._shadowRoot.append(template.content.cloneNode(true))
this.$menuitem = this._shadowRoot.querySelector('elix-option')
this.$svg = this.$menuitem.shadowRoot.querySelector('#checkmark')
this.$svg.setAttribute('style', 'display: none;')
this.$img = this._shadowRoot.querySelector('img')
this.$img.setAttribute('style', 'display: none;')
this.imgPath = svgEditor.configObj.curConfig.imgPath
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'option', 'src', 'title', 'img-height' ];
return ['option', 'src', 'title', 'img-height']
}
/**
@ -53,33 +54,34 @@ export class SeListItem extends HTMLElement {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
if (oldValue === newValue) return;
if (oldValue === newValue) return
switch (name) {
case 'option':
this.$menuitem.setAttribute('option', newValue);
this.$menuitem.textContent = t(newValue);
break;
case 'src':
this.$img.setAttribute('style', 'display: block;');
this.$img.setAttribute('src', this.imgPath + '/' + newValue);
break;
case 'title':
this.$img.setAttribute('title', t(newValue));
break;
case 'img-height':
this.$img.setAttribute('height', newValue);
break;
default:
console.error(`unknown attribute: ${name}`);
break;
case 'option':
this.$menuitem.setAttribute('option', newValue)
this.$menuitem.textContent = t(newValue)
break
case 'src':
this.$img.setAttribute('style', 'display: block;')
this.$img.setAttribute('src', this.imgPath + '/' + newValue)
break
case 'title':
this.$img.setAttribute('title', t(newValue))
break
case 'img-height':
this.$img.setAttribute('height', newValue)
break
default:
console.error(`unknown attribute: ${name}`)
break
}
}
/**
* @function get
* @returns {any}
*/
get option () {
return this.getAttribute('option');
return this.getAttribute('option')
}
/**
@ -87,14 +89,15 @@ export class SeListItem extends HTMLElement {
* @returns {void}
*/
set option (value) {
this.setAttribute('option', value);
this.setAttribute('option', value)
}
/**
* @function get
* @returns {any}
*/
get title () {
return this.getAttribute('title');
return this.getAttribute('title')
}
/**
@ -102,14 +105,15 @@ export class SeListItem extends HTMLElement {
* @returns {void}
*/
set title (value) {
this.setAttribute('title', value);
this.setAttribute('title', value)
}
/**
* @function get
* @returns {any}
*/
get imgHeight () {
return this.getAttribute('img-height');
return this.getAttribute('img-height')
}
/**
@ -117,14 +121,15 @@ export class SeListItem extends HTMLElement {
* @returns {void}
*/
set imgHeight (value) {
this.setAttribute('img-height', value);
this.setAttribute('img-height', value)
}
/**
* @function get
* @returns {any}
*/
get src () {
return this.getAttribute('src');
return this.getAttribute('src')
}
/**
@ -132,9 +137,9 @@ export class SeListItem extends HTMLElement {
* @returns {void}
*/
set src (value) {
this.setAttribute('src', value);
this.setAttribute('src', value)
}
}
// Register
customElements.define('se-list-item', SeListItem);
customElements.define('se-list-item', SeListItem)

View File

@ -1,8 +1,8 @@
/* globals svgEditor */
import 'elix/define/MenuItem.js';
import './sePlainMenuButton.js';
import 'elix/define/MenuItem.js'
import './sePlainMenuButton.js'
const template = document.createElement('template');
const template = document.createElement('template')
template.innerHTML = `
<style>
:host {
@ -29,7 +29,7 @@ template.innerHTML = `
<slot></slot>
</elix-menu-button>
`;
`
/**
* @class SeMenu
*/
@ -38,20 +38,21 @@ export class SeMenu extends HTMLElement {
* @function constructor
*/
constructor () {
super();
super()
// create the shadowDom and insert the template
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.append(template.content.cloneNode(true));
this.$menu = this._shadowRoot.querySelector('elix-menu-button');
this.$label = this.$menu.shadowRoot.querySelector('#popupToggle').shadowRoot;
this.imgPath = svgEditor.configObj.curConfig.imgPath;
this._shadowRoot = this.attachShadow({ mode: 'open' })
this._shadowRoot.append(template.content.cloneNode(true))
this.$menu = this._shadowRoot.querySelector('elix-menu-button')
this.$label = this.$menu.shadowRoot.querySelector('#popupToggle').shadowRoot
this.imgPath = svgEditor.configObj.curConfig.imgPath
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'label', 'src' ];
return ['label', 'src']
}
/**
@ -62,29 +63,30 @@ export class SeMenu extends HTMLElement {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
const image = new Image();
if (oldValue === newValue) return;
const image = new Image()
if (oldValue === newValue) return
switch (name) {
case 'src':
image.src = this.imgPath + '/' + newValue;
image.width = 24;
image.height = 24;
this.$label.prepend(image);
break;
case 'label':
this.$label.prepend(newValue);
break;
default:
console.error(`unknown attribute: ${name}`);
break;
case 'src':
image.src = this.imgPath + '/' + newValue
image.width = 24
image.height = 24
this.$label.prepend(image)
break
case 'label':
this.$label.prepend(newValue)
break
default:
console.error(`unknown attribute: ${name}`)
break
}
}
/**
* @function get
* @returns {any}
*/
get label () {
return this.getAttribute('label');
return this.getAttribute('label')
}
/**
@ -92,14 +94,15 @@ export class SeMenu extends HTMLElement {
* @returns {void}
*/
set label (value) {
this.setAttribute('label', value);
this.setAttribute('label', value)
}
/**
* @function get
* @returns {any}
*/
get src () {
return this.getAttribute('src');
return this.getAttribute('src')
}
/**
@ -107,7 +110,7 @@ export class SeMenu extends HTMLElement {
* @returns {void}
*/
set src (value) {
this.setAttribute('src', value);
this.setAttribute('src', value)
}
/**
* @function connectedCallback
@ -125,4 +128,4 @@ export class SeMenu extends HTMLElement {
}
// Register
customElements.define('se-menu', SeMenu);
customElements.define('se-menu', SeMenu)

View File

@ -1,8 +1,8 @@
/* globals svgEditor */
import 'elix/define/Menu.js';
import 'elix/define/MenuItem.js';
import { t } from '../locale.js';
const template = document.createElement('template');
import 'elix/define/Menu.js'
import 'elix/define/MenuItem.js'
import { t } from '../locale.js'
const template = document.createElement('template')
template.innerHTML = `
<style>
</style>
@ -12,7 +12,7 @@ template.innerHTML = `
<span style="margin-left: 7px;"></span>
</div>
</elix-menu-item>
`;
`
/**
* @class SeMenuItem
*/
@ -21,24 +21,26 @@ export class SeMenuItem extends HTMLElement {
* @function constructor
*/
constructor () {
super();
super()
// create the shadowDom and insert the template
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.append(template.content.cloneNode(true));
this.$img = this._shadowRoot.querySelector('img');
this.$label = this._shadowRoot.querySelector('span');
this.$menuitem = this._shadowRoot.querySelector('elix-menu-item');
this.$svg = this.$menuitem.shadowRoot.querySelector('#checkmark');
this.$svg.setAttribute('style', 'display: none;');
this.imgPath = svgEditor.configObj.curConfig.imgPath;
this._shadowRoot = this.attachShadow({ mode: 'open' })
this._shadowRoot.append(template.content.cloneNode(true))
this.$img = this._shadowRoot.querySelector('img')
this.$label = this._shadowRoot.querySelector('span')
this.$menuitem = this._shadowRoot.querySelector('elix-menu-item')
this.$svg = this.$menuitem.shadowRoot.querySelector('#checkmark')
this.$svg.setAttribute('style', 'display: none;')
this.imgPath = svgEditor.configObj.curConfig.imgPath
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'label', 'src' ];
return ['label', 'src']
}
/**
* @function attributeChangedCallback
* @param {string} name
@ -47,28 +49,29 @@ export class SeMenuItem extends HTMLElement {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
let shortcut = '';
if (oldValue === newValue) return;
let shortcut = ''
if (oldValue === newValue) return
switch (name) {
case 'src':
this.$img.style.display = 'inline-block';
this.$img.setAttribute('src', this.imgPath + '/' + newValue);
break;
case 'label':
shortcut = this.getAttribute('shortcut');
this.$label.textContent = `${t(newValue)} ${shortcut ? `(${shortcut})` : ''}`;
break;
default:
console.error(`unknown attribute: ${name}`);
break;
case 'src':
this.$img.style.display = 'inline-block'
this.$img.setAttribute('src', this.imgPath + '/' + newValue)
break
case 'label':
shortcut = this.getAttribute('shortcut')
this.$label.textContent = `${t(newValue)} ${shortcut ? `(${shortcut})` : ''}`
break
default:
console.error(`unknown attribute: ${name}`)
break
}
}
/**
* @function get
* @returns {any}
*/
get label () {
return this.getAttribute('label');
return this.getAttribute('label')
}
/**
@ -76,14 +79,15 @@ export class SeMenuItem extends HTMLElement {
* @returns {void}
*/
set label (value) {
this.setAttribute('label', value);
this.setAttribute('label', value)
}
/**
* @function get
* @returns {any}
*/
get src () {
return this.getAttribute('src');
return this.getAttribute('src')
}
/**
@ -91,7 +95,7 @@ export class SeMenuItem extends HTMLElement {
* @returns {void}
*/
set src (value) {
this.setAttribute('src', value);
this.setAttribute('src', value)
}
/**
@ -100,24 +104,24 @@ export class SeMenuItem extends HTMLElement {
*/
connectedCallback () {
// capture shortcuts
const shortcut = this.getAttribute('shortcut');
const shortcut = this.getAttribute('shortcut')
if (shortcut) {
// register the keydown event
document.addEventListener('keydown', (e) => {
// only track keyboard shortcuts for the body containing the SVG-Editor
if (e.target.nodeName !== 'BODY') return;
if (e.target.nodeName !== 'BODY') return
// normalize key
const key = `${(e.metaKey) ? 'meta+' : ''}${(e.ctrlKey) ? 'ctrl+' : ''}${e.key.toUpperCase()}`;
if (shortcut !== key) return;
const key = `${(e.metaKey) ? 'meta+' : ''}${(e.ctrlKey) ? 'ctrl+' : ''}${e.key.toUpperCase()}`
if (shortcut !== key) return
// launch the click event
if (this.id) {
document.getElementById(this.id).click();
document.getElementById(this.id).click()
}
e.preventDefault();
});
e.preventDefault()
})
}
}
}
// Register
customElements.define('se-menu-item', SeMenuItem);
customElements.define('se-menu-item', SeMenuItem)

View File

@ -11,9 +11,9 @@ const palette = [
'#ffaaaa', '#ffd4aa', '#ffffaa', '#d4ffaa',
'#aaffaa', '#aaffd4', '#aaffff', '#aad4ff',
'#aaaaff', '#d4aaff', '#ffaaff', '#ffaad4'
];
]
const template = document.createElement('template');
const template = document.createElement('template')
template.innerHTML = `
<style>
.square {
@ -50,7 +50,7 @@ template.innerHTML = `
<div id="js-se-palette">
</div>
</div>
`;
`
/**
* @class SEPalette
@ -60,38 +60,38 @@ export class SEPalette extends HTMLElement {
* @function constructor
*/
constructor () {
super();
super()
// create the shadowDom and insert the template
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.append(template.content.cloneNode(true));
this.$strip = this._shadowRoot.querySelector('#js-se-palette');
this._shadowRoot = this.attachShadow({ mode: 'open' })
this._shadowRoot.append(template.content.cloneNode(true))
this.$strip = this._shadowRoot.querySelector('#js-se-palette')
palette.forEach((rgb) => {
const newDiv = document.createElement('div');
newDiv.classList.add('square');
if(rgb === 'none') {
const img = document.createElement('img');
img.src = `data:image/svg+xml;charset=utf-8;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgY2xhc3M9InN2Z19pY29uIj48c3ZnIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+CiAgICA8bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiNkNDAwMDAiIGlkPSJzdmdfOTAiIHkyPSIyNCIgeDI9IjI0IiB5MT0iMCIgeDE9IjAiLz4KICAgIDxsaW5lIGlkPSJzdmdfOTIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2Q0MDAwMCIgeTI9IjI0IiB4Mj0iMCIgeTE9IjAiIHgxPSIyNCIvPgogIDwvc3ZnPjwvc3ZnPg==`;
img.style.width = "15px";
img.style.height = "15px";
newDiv.append(img);
const newDiv = document.createElement('div')
newDiv.classList.add('square')
if (rgb === 'none') {
const img = document.createElement('img')
img.src = 'data:image/svg+xml;charset=utf-8;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgY2xhc3M9InN2Z19pY29uIj48c3ZnIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+CiAgICA8bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiNkNDAwMDAiIGlkPSJzdmdfOTAiIHkyPSIyNCIgeDI9IjI0IiB5MT0iMCIgeDE9IjAiLz4KICAgIDxsaW5lIGlkPSJzdmdfOTIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2Q0MDAwMCIgeTI9IjI0IiB4Mj0iMCIgeTE9IjAiIHgxPSIyNCIvPgogIDwvc3ZnPjwvc3ZnPg=='
img.style.width = '15px'
img.style.height = '15px'
newDiv.append(img)
} else {
newDiv.style.backgroundColor = rgb;
newDiv.style.backgroundColor = rgb
}
newDiv.dataset.rgb = rgb;
newDiv.dataset.rgb = rgb
newDiv.addEventListener('click', (evt) => {
evt.preventDefault();
evt.preventDefault()
// shift key or right click for stroke
const picker = evt.shiftKey || evt.button === 2 ? 'stroke' : 'fill';
let color = newDiv.dataset.rgb;
const picker = evt.shiftKey || evt.button === 2 ? 'stroke' : 'fill'
let color = newDiv.dataset.rgb
// Webkit-based browsers returned 'initial' here for no stroke
if (color === 'none' || color === 'transparent' || color === 'initial') {
color = 'none';
color = 'none'
}
const paletteEvent = new CustomEvent('change', { detail: { picker, color }, bubbles: false });
this.dispatchEvent(paletteEvent);
});
this.$strip.append(newDiv);
});
const paletteEvent = new CustomEvent('change', { detail: { picker, color }, bubbles: false })
this.dispatchEvent(paletteEvent)
})
this.$strip.append(newDiv)
})
}
/**
@ -100,15 +100,17 @@ export class SEPalette extends HTMLElement {
* @returns {void}
*/
init (i18next) {
this.setAttribute('ui-palette_info', i18next.t('ui.palette_info'));
this.setAttribute('ui-palette_info', i18next.t('ui.palette_info'))
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'ui-palette_info' ];
return ['ui-palette_info']
}
/**
* @function attributeChangedCallback
* @param {string} name
@ -117,12 +119,13 @@ export class SEPalette extends HTMLElement {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
let node;
let node
if (name === 'ui-palette_info') {
node = this._shadowRoot.querySelector('#palette_holder');
node.setAttribute('title', newValue);
node = this._shadowRoot.querySelector('#palette_holder')
node.setAttribute('title', newValue)
}
}
/**
* @function connectedCallback
* @returns {void}
@ -132,4 +135,4 @@ export class SEPalette extends HTMLElement {
}
// Register
customElements.define('se-palette', SEPalette);
customElements.define('se-palette', SEPalette)

View File

@ -1,6 +1,6 @@
import { template } from 'elix/src/base/internal.js';
import { fragmentFrom } from 'elix/src/core/htmlLiterals.js';
import PlainButton from 'elix/src/plain/PlainButton.js';
import { template } from 'elix/src/base/internal.js'
import { fragmentFrom } from 'elix/src/core/htmlLiterals.js'
import PlainButton from 'elix/src/plain/PlainButton.js'
/**
* @class SePlainBorderButton
@ -13,7 +13,7 @@ class SePlainBorderButton extends PlainButton {
* @returns {PlainObject}
*/
get [template] () {
const result = super[template];
const result = super[template]
result.content.append(
fragmentFrom.html`
<style>
@ -23,9 +23,9 @@ class SePlainBorderButton extends PlainButton {
}
</style>
`
);
return result;
)
return result
}
}
export default SePlainBorderButton;
export default SePlainBorderButton

View File

@ -1,6 +1,6 @@
import PlainMenuButton from 'elix/src/plain/PlainMenuButton.js';
import { defaultState } from 'elix/src/base/internal.js';
import sePlainBorderButton from './sePlainBorderButton.js';
import PlainMenuButton from 'elix/src/plain/PlainMenuButton.js'
import { defaultState } from 'elix/src/base/internal.js'
import sePlainBorderButton from './sePlainBorderButton.js'
/**
* @class ElixMenuButton
@ -13,8 +13,8 @@ export default class ElixMenuButton extends PlainMenuButton {
get [defaultState] () {
return Object.assign(super[defaultState], {
sourcePartType: sePlainBorderButton
});
})
}
}
customElements.define('elix-menu-button', ElixMenuButton);
customElements.define('elix-menu-button', ElixMenuButton)

View File

@ -1,5 +1,5 @@
import { t } from '../locale.js';
const template = document.createElement('template');
import { t } from '../locale.js'
const template = document.createElement('template')
template.innerHTML = `
<style>
select {
@ -21,7 +21,7 @@ label {
<select>
</select>
`;
`
/**
* @class SeList
*/
@ -30,19 +30,20 @@ export class SeSelect extends HTMLElement {
* @function constructor
*/
constructor () {
super();
super()
// create the shadowDom and insert the template
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.append(template.content.cloneNode(true));
this.$select = this._shadowRoot.querySelector('select');
this.$label = this._shadowRoot.querySelector('label');
this._shadowRoot = this.attachShadow({ mode: 'open' })
this._shadowRoot.append(template.content.cloneNode(true))
this.$select = this._shadowRoot.querySelector('select')
this.$label = this._shadowRoot.querySelector('label')
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'label', 'width', 'height', 'options', 'values', 'title', 'disabled' ];
return ['label', 'width', 'height', 'options', 'values', 'title', 'disabled']
}
/**
@ -53,64 +54,63 @@ export class SeSelect extends HTMLElement {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
let options;
if (oldValue === newValue) return;
let options
if (oldValue === newValue) return
switch (name) {
case 'label':
this.$label.textContent = t(newValue);
break;
case 'title':
this.$select.setAttribute("title", t(newValue));
break;
case 'disabled':
if(newValue === null) {
this.$select.removeAttribute("disabled");
} else {
this.$select.setAttribute("disabled", newValue);
}
break;
case 'height':
this.$select.style.height = newValue;
break;
case 'width':
this.$select.style.width = newValue;
break;
case 'options':
if(newValue === "") {
while(this.$select.firstChild)
this.$select.removeChild(this.$select.firstChild);
} else {
options = newValue.split(',');
options.forEach((option) => {
const optionNode = document.createElement("OPTION");
const text = document.createTextNode(t(option));
optionNode.appendChild(text);
this.$select.appendChild(optionNode);
});
}
break;
case 'values':
if(newValue === "") {
while(this.$select.firstChild)
this.$select.removeChild(this.$select.firstChild);
} else {
options = newValue.split('::');
options.forEach((option, index) => {
this.$select.children[index].setAttribute('value', option);
});
}
break;
default:
console.error(`unknown attribute: ${name}`);
break;
case 'label':
this.$label.textContent = t(newValue)
break
case 'title':
this.$select.setAttribute('title', t(newValue))
break
case 'disabled':
if (newValue === null) {
this.$select.removeAttribute('disabled')
} else {
this.$select.setAttribute('disabled', newValue)
}
break
case 'height':
this.$select.style.height = newValue
break
case 'width':
this.$select.style.width = newValue
break
case 'options':
if (newValue === '') {
while (this.$select.firstChild) { this.$select.removeChild(this.$select.firstChild) }
} else {
options = newValue.split(',')
options.forEach((option) => {
const optionNode = document.createElement('OPTION')
const text = document.createTextNode(t(option))
optionNode.appendChild(text)
this.$select.appendChild(optionNode)
})
}
break
case 'values':
if (newValue === '') {
while (this.$select.firstChild) { this.$select.removeChild(this.$select.firstChild) }
} else {
options = newValue.split('::')
options.forEach((option, index) => {
this.$select.children[index].setAttribute('value', option)
})
}
break
default:
console.error(`unknown attribute: ${name}`)
break
}
}
/**
* @function get
* @returns {any}
*/
get label () {
return this.getAttribute('label');
return this.getAttribute('label')
}
/**
@ -118,14 +118,15 @@ export class SeSelect extends HTMLElement {
* @returns {void}
*/
set label (value) {
this.setAttribute('label', value);
this.setAttribute('label', value)
}
/**
* @function get
* @returns {any}
*/
get width () {
return this.getAttribute('width');
return this.getAttribute('width')
}
/**
@ -133,14 +134,15 @@ export class SeSelect extends HTMLElement {
* @returns {void}
*/
set width (value) {
this.setAttribute('width', value);
this.setAttribute('width', value)
}
/**
* @function get
* @returns {any}
*/
get height () {
return this.getAttribute('height');
return this.getAttribute('height')
}
/**
@ -148,14 +150,15 @@ export class SeSelect extends HTMLElement {
* @returns {void}
*/
set height (value) {
this.setAttribute('height', value);
this.setAttribute('height', value)
}
/**
* @function get
* @returns {any}
*/
get value () {
return this.$select.value;
return this.$select.value
}
/**
@ -163,14 +166,15 @@ export class SeSelect extends HTMLElement {
* @returns {void}
*/
set value (value) {
this.$select.value = value;
this.$select.value = value
}
/**
* @function get
* @returns {any}
*/
get disabled () {
return this.$select.getAttribute('disabled');
return this.$select.getAttribute('disabled')
}
/**
@ -178,22 +182,23 @@ export class SeSelect extends HTMLElement {
* @returns {void}
*/
set disabled (value) {
this.$select.setAttribute('disabled', value);
this.$select.setAttribute('disabled', value)
}
/**
* @function connectedCallback
* @returns {void}
*/
connectedCallback () {
const currentObj = this;
const currentObj = this
this.$select.addEventListener('change', () => {
const value = this.$select.value;
const closeEvent = new CustomEvent('change', { detail: { value } });
currentObj.dispatchEvent(closeEvent);
currentObj.value = value;
});
const value = this.$select.value
const closeEvent = new CustomEvent('change', { detail: { value } })
currentObj.dispatchEvent(closeEvent)
currentObj.value = value
})
}
}
// Register
customElements.define('se-select', SeSelect);
customElements.define('se-select', SeSelect)

View File

@ -1,8 +1,8 @@
/* globals svgEditor */
import '../dialogs/se-elix/define/NumberSpinBox.js';
import { t } from '../locale.js';
import '../dialogs/se-elix/define/NumberSpinBox.js'
import { t } from '../locale.js'
const template = document.createElement('template');
const template = document.createElement('template')
template.innerHTML = `
<style>
div {
@ -49,7 +49,7 @@ template.innerHTML = `
<span id="label">label</span>
<elix-number-spin-box min="1" step="1"></elix-number-spin-box>
</div>
`;
`
/**
* @class SESpinInput
@ -59,25 +59,27 @@ export class SESpinInput extends HTMLElement {
* @function constructor
*/
constructor () {
super();
super()
// create the shadowDom and insert the template
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.append(template.content.cloneNode(true));
this._shadowRoot = this.attachShadow({ mode: 'open' })
this._shadowRoot.append(template.content.cloneNode(true))
// locate the component
this.$div = this._shadowRoot.querySelector('div');
this.$img = this._shadowRoot.querySelector('img');
this.$label = this.shadowRoot.getElementById('label');
this.$event = new CustomEvent('change');
this.$input = this._shadowRoot.querySelector('elix-number-spin-box');
this.imgPath = svgEditor.configObj.curConfig.imgPath;
this.$div = this._shadowRoot.querySelector('div')
this.$img = this._shadowRoot.querySelector('img')
this.$label = this.shadowRoot.getElementById('label')
this.$event = new CustomEvent('change')
this.$input = this._shadowRoot.querySelector('elix-number-spin-box')
this.imgPath = svgEditor.configObj.curConfig.imgPath
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'value', 'label', 'src', 'size', 'min', 'max', 'step', 'title' ];
return ['value', 'label', 'src', 'size', 'min', 'max', 'step', 'title']
}
/**
* @function attributeChangedCallback
* @param {string} name
@ -86,52 +88,53 @@ export class SESpinInput extends HTMLElement {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
if (oldValue === newValue) return;
if (oldValue === newValue) return
switch (name) {
case 'title':
{
const shortcut = this.getAttribute('shortcut');
this.$div.setAttribute('title', `${t(newValue)} ${shortcut ? `[${t(shortcut)}]` : ''}`);
}
break;
case 'src':
this.$img.setAttribute('src', this.imgPath + '/' + newValue);
this.$label.remove();
this.$div.classList.add('imginside');
break;
case 'size':
case 'title':
{
const shortcut = this.getAttribute('shortcut')
this.$div.setAttribute('title', `${t(newValue)} ${shortcut ? `[${t(shortcut)}]` : ''}`)
}
break
case 'src':
this.$img.setAttribute('src', this.imgPath + '/' + newValue)
this.$label.remove()
this.$div.classList.add('imginside')
break
case 'size':
// access to the underlying input box
this.$input.shadowRoot.getElementById('input').size = newValue;
// below seems mandatory to override the default width style that takes precedence on size
this.$input.shadowRoot.getElementById('input').style.width = 'unset';
break;
case 'step':
this.$input.setAttribute('step', newValue);
break;
case 'min':
this.$input.setAttribute('min', newValue);
break;
case 'max':
this.$input.setAttribute('max', newValue);
break;
case 'label':
this.$label.textContent = t(newValue);
this.$img.remove();
break;
case 'value':
this.$input.value = newValue;
break;
default:
console.error(`unknown attribute: ${name}`);
break;
this.$input.shadowRoot.getElementById('input').size = newValue
// below seems mandatory to override the default width style that takes precedence on size
this.$input.shadowRoot.getElementById('input').style.width = 'unset'
break
case 'step':
this.$input.setAttribute('step', newValue)
break
case 'min':
this.$input.setAttribute('min', newValue)
break
case 'max':
this.$input.setAttribute('max', newValue)
break
case 'label':
this.$label.textContent = t(newValue)
this.$img.remove()
break
case 'value':
this.$input.value = newValue
break
default:
console.error(`unknown attribute: ${name}`)
break
}
}
/**
* @function get
* @returns {any}
*/
get title () {
return this.getAttribute('title');
return this.getAttribute('title')
}
/**
@ -139,14 +142,15 @@ export class SESpinInput extends HTMLElement {
* @returns {void}
*/
set title (value) {
this.setAttribute('title', value);
this.setAttribute('title', value)
}
/**
* @function get
* @returns {any}
*/
get label () {
return this.getAttribute('label');
return this.getAttribute('label')
}
/**
@ -154,14 +158,15 @@ export class SESpinInput extends HTMLElement {
* @returns {void}
*/
set label (value) {
this.setAttribute('label', value);
this.setAttribute('label', value)
}
/**
* @function get
* @returns {any}
*/
get value () {
return this.$input.value;
return this.$input.value
}
/**
@ -169,14 +174,15 @@ export class SESpinInput extends HTMLElement {
* @returns {void}
*/
set value (value) {
this.$input.value = value;
this.$input.value = value
}
/**
* @function get
* @returns {any}
*/
get src () {
return this.getAttribute('src');
return this.getAttribute('src')
}
/**
@ -184,7 +190,7 @@ export class SESpinInput extends HTMLElement {
* @returns {void}
*/
set src (value) {
this.setAttribute('src', value);
this.setAttribute('src', value)
}
/**
@ -192,7 +198,7 @@ export class SESpinInput extends HTMLElement {
* @returns {any}
*/
get size () {
return this.getAttribute('size');
return this.getAttribute('size')
}
/**
@ -200,7 +206,7 @@ export class SESpinInput extends HTMLElement {
* @returns {void}
*/
set size (value) {
this.setAttribute('size', value);
this.setAttribute('size', value)
}
/**
@ -208,31 +214,31 @@ export class SESpinInput extends HTMLElement {
* @returns {void}
*/
connectedCallback () {
const shadow = this.$input.shadowRoot;
const childNodes = Array.from(shadow.childNodes);
childNodes.forEach( (childNode) => {
if(childNode?.id === "input") {
const shadow = this.$input.shadowRoot
const childNodes = Array.from(shadow.childNodes)
childNodes.forEach((childNode) => {
if (childNode?.id === 'input') {
childNode.addEventListener('keyup', (e) => {
e.preventDefault();
e.preventDefault()
if (!isNaN(e.target.value)) {
this.value = e.target.value;
this.dispatchEvent(this.$event);
this.value = e.target.value
this.dispatchEvent(this.$event)
}
});
})
}
});
})
this.$input.addEventListener('change', (e) => {
e.preventDefault();
this.value = e.target.value;
this.dispatchEvent(this.$event);
});
e.preventDefault()
this.value = e.target.value
this.dispatchEvent(this.$event)
})
this.$input.addEventListener('click', (e) => {
e.preventDefault();
this.value = e.target.value;
this.dispatchEvent(this.$event);
});
e.preventDefault()
this.value = e.target.value
this.dispatchEvent(this.$event)
})
}
}
// Register
customElements.define('se-spin-input', SESpinInput);
customElements.define('se-spin-input', SESpinInput)

View File

@ -1,5 +1,5 @@
import { t } from '../locale.js';
const template = document.createElement('template');
import { t } from '../locale.js'
const template = document.createElement('template')
template.innerHTML = `
<style>
#layersLabel {
@ -9,7 +9,7 @@ template.innerHTML = `
}
</style>
<div></div>
`;
`
/**
* @class SeText
*/
@ -18,20 +18,22 @@ export class SeText extends HTMLElement {
* @function constructor
*/
constructor () {
super();
super()
// create the shadowDom and insert the template
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.append(template.content.cloneNode(true));
this._shadowRoot = this.attachShadow({ mode: 'open' })
this._shadowRoot.append(template.content.cloneNode(true))
// locate the component
this.$div = this._shadowRoot.querySelector('div');
this.$div = this._shadowRoot.querySelector('div')
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'text', 'value', 'style', 'title', 'id' ];
return ['text', 'value', 'style', 'title', 'id']
}
/**
* @function attributeChangedCallback
* @param {string} name
@ -40,35 +42,36 @@ export class SeText extends HTMLElement {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
if (oldValue === newValue) return;
if (oldValue === newValue) return
switch (name) {
case 'text':
this.$div.textContent = t(newValue);
break;
case 'title':
this.$div.setAttribute("title", t(newValue));
break;
case 'style':
this.$div.style = newValue;
break;
case 'id':
this.$div.id = newValue;
break;
case 'value':
this.$div.value = newValue;
//this.$div.setAttribute("value", newValue);
break;
default:
console.error(`unknown attribute: ${name}`);
break;
case 'text':
this.$div.textContent = t(newValue)
break
case 'title':
this.$div.setAttribute('title', t(newValue))
break
case 'style':
this.$div.style = newValue
break
case 'id':
this.$div.id = newValue
break
case 'value':
this.$div.value = newValue
// this.$div.setAttribute("value", newValue);
break
default:
console.error(`unknown attribute: ${name}`)
break
}
}
/**
* @function get
* @returns {any}
*/
get text () {
return this.$div.textContent;
return this.$div.textContent
}
/**
@ -76,14 +79,15 @@ export class SeText extends HTMLElement {
* @returns {void}
*/
set text (value) {
this.$div.setAttribute("title", t(value));
this.$div.setAttribute('title', t(value))
}
/**
* @function get
* @returns {any}
*/
get value () {
return this.value;
return this.value
}
/**
@ -91,14 +95,15 @@ export class SeText extends HTMLElement {
* @returns {void}
*/
set value (value) {
this.value = value;
this.value = value
}
/**
* @function get
* @returns {any}
*/
get title () {
return this.getAttribute('title');
return this.getAttribute('title')
}
/**
@ -106,8 +111,9 @@ export class SeText extends HTMLElement {
* @returns {void}
*/
set title (value) {
this.setAttribute('title', value);
this.setAttribute('title', value)
}
/**
* @function connectedCallback
* @returns {void}
@ -118,4 +124,4 @@ export class SeText extends HTMLElement {
}
// Register
customElements.define('se-text', SeText);
customElements.define('se-text', SeText)

View File

@ -1,8 +1,8 @@
/* globals svgEditor */
import ListComboBox from 'elix/define/ListComboBox.js';
import * as internal from 'elix/src/base/internal.js';
import { templateFrom, fragmentFrom } from 'elix/src/core/htmlLiterals.js';
import NumberSpinBox from '../dialogs/se-elix/define/NumberSpinBox.js';
import ListComboBox from 'elix/define/ListComboBox.js'
import * as internal from 'elix/src/base/internal.js'
import { templateFrom, fragmentFrom } from 'elix/src/core/htmlLiterals.js'
import NumberSpinBox from '../dialogs/se-elix/define/NumberSpinBox.js'
/**
* @class Dropdown
@ -17,20 +17,21 @@ class Zoom extends ListComboBox {
inputPartType: NumberSpinBox,
src: 'logo.svg',
inputsize: '100%'
});
})
}
/**
* @function get
* @returns {PlainObject}
*/
get [internal.template] () {
const result = super[internal.template];
const source = result.content.getElementById('source');
const result = super[internal.template]
const source = result.content.getElementById('source')
// add a icon before our dropdown
source.prepend(fragmentFrom.html`
<img src="zoom" alt="icon" width="18" height="18">
</img>
`.cloneNode(true));
`.cloneNode(true))
// change the style so it fits in our toolbar
result.content.append(
templateFrom.html`
@ -57,16 +58,18 @@ class Zoom extends ListComboBox {
</style>
`.content
);
return result;
)
return result
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'title', 'src', 'inputsize', 'value' ];
return ['title', 'src', 'inputsize', 'value']
}
/**
* @function attributeChangedCallback
* @param {string} name
@ -75,97 +78,104 @@ class Zoom extends ListComboBox {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
if (oldValue === newValue && name !== "src") return;
if (oldValue === newValue && name !== 'src') return
switch (name) {
case 'title':
case 'title':
// this.$span.setAttribute('title', `${newValue} ${shortcut ? `[${shortcut}]` : ''}`);
break;
case 'src':
{
const { imgPath } = svgEditor.configObj.curConfig;
this.src = imgPath + '/' + newValue;
}
break;
case 'inputsize':
this.inputsize = newValue;
break;
default:
super.attributeChangedCallback(name, oldValue, newValue);
break;
break
case 'src':
{
const { imgPath } = svgEditor.configObj.curConfig
this.src = imgPath + '/' + newValue
}
break
case 'inputsize':
this.inputsize = newValue
break
default:
super.attributeChangedCallback(name, oldValue, newValue)
break
}
}
/**
* @function [internal.render]
* @param {PlainObject} changed
* @returns {void}
*/
[internal.render] (changed) {
super[internal.render](changed);
super[internal.render](changed)
if (this[internal.firstRender]) {
this.$img = this.shadowRoot.querySelector('img');
this.$input = this.shadowRoot.getElementById('input');
this.$img = this.shadowRoot.querySelector('img')
this.$input = this.shadowRoot.getElementById('input')
}
if (changed.src) {
this.$img.setAttribute('src', this[internal.state].src);
this.$img.setAttribute('src', this[internal.state].src)
}
if (changed.inputsize) {
this.$input.shadowRoot.querySelector('[part~="input"]').style.width = this[internal.state].inputsize;
this.$input.shadowRoot.querySelector('[part~="input"]').style.width = this[internal.state].inputsize
}
if (changed.inputPartType) {
// Wire up handler on new input.
this.addEventListener('close', (e) => {
e.preventDefault();
const value = e.detail?.closeResult?.getAttribute('value');
e.preventDefault()
const value = e.detail?.closeResult?.getAttribute('value')
if (value) {
const closeEvent = new CustomEvent('change', { detail: { value } });
this.dispatchEvent(closeEvent);
const closeEvent = new CustomEvent('change', { detail: { value } })
this.dispatchEvent(closeEvent)
}
});
})
}
}
/**
* @function src
* @returns {string} src
*/
get src () {
return this[internal.state].src;
return this[internal.state].src
}
/**
* @function src
* @returns {void}
*/
set src (src) {
this[internal.setState]({ src });
this[internal.setState]({ src })
}
/**
* @function inputsize
* @returns {string} src
*/
get inputsize () {
return this[internal.state].inputsize;
return this[internal.state].inputsize
}
/**
* @function src
* @returns {void}
*/
set inputsize (inputsize) {
this[internal.setState]({ inputsize });
this[internal.setState]({ inputsize })
}
/**
* @function value
* @returns {string} src
*/
get value () {
return this[internal.state].value;
return this[internal.state].value
}
/**
* @function value
* @returns {void}
*/
set value (value) {
this[internal.setState]({ value });
this[internal.setState]({ value })
}
}
// Register
customElements.define('se-zoom', Zoom);
customElements.define('se-zoom', Zoom)

View File

@ -5,7 +5,7 @@
* @author Adam Bender
*/
let contextMenuExtensions = {};
let contextMenuExtensions = {}
/**
* Signature depends on what the user adds; in the case of our uses with
@ -27,8 +27,8 @@ let contextMenuExtensions = {};
* @returns {boolean}
*/
const menuItemIsValid = function (menuItem) {
return menuItem && menuItem.id && menuItem.label && menuItem.action && typeof menuItem.action === 'function';
};
return menuItem && menuItem.id && menuItem.label && menuItem.action && typeof menuItem.action === 'function'
}
/**
* @function module:contextmenu.add
@ -42,15 +42,15 @@ export const add = function (menuItem) {
throw new TypeError(
'Menu items must be defined and have at least properties: ' +
'id, label, action, where action must be a function'
);
)
}
if (menuItem.id in contextMenuExtensions) {
throw new Error('Cannot add extension "' + menuItem.id + '", an extension by that name already exists"');
throw new Error('Cannot add extension "' + menuItem.id + '", an extension by that name already exists"')
}
// Register menuItem action, see below for deferred menu dom injection
contextMenuExtensions[menuItem.id] = menuItem;
contextMenuExtensions[menuItem.id] = menuItem
// TODO: Need to consider how to handle custom enable/disable behavior
};
}
/**
* @function module:contextmenu.hasCustomHandler
@ -58,8 +58,8 @@ export const add = function (menuItem) {
* @returns {boolean}
*/
export const hasCustomHandler = function (handlerKey) {
return Boolean(contextMenuExtensions[handlerKey]);
};
return Boolean(contextMenuExtensions[handlerKey])
}
/**
* @function module:contextmenu.getCustomHandler
@ -67,8 +67,8 @@ export const hasCustomHandler = function (handlerKey) {
* @returns {module:contextmenu.MenuItemAction}
*/
export const getCustomHandler = function (handlerKey) {
return contextMenuExtensions[handlerKey].action;
};
return contextMenuExtensions[handlerKey].action
}
/**
* @param {module:contextmenu.MenuItem} menuItem
@ -78,12 +78,12 @@ const injectExtendedContextMenuItemIntoDom = function (menuItem) {
if (!Object.keys(contextMenuExtensions).length) {
// all menuItems appear at the bottom of the menu in their own container.
// if this is the first extension menu we need to add the separator.
document.getElementById('cmenu_canvas').appendChild(`<li class='separator'>`);
document.getElementById('cmenu_canvas').appendChild('<li class=\'separator\'>')
}
const shortcut = menuItem.shortcut || '';
const shortcut = menuItem.shortcut || ''
document.getElementById('cmenu_canvas').appendChild(`
<li class='disabled'><a href='#${menuItem.id}'>${menuItem.label}<span class='shortcut'>${shortcut}</span></a></li>`);
};
<li class='disabled'><a href='#${menuItem.id}'>${menuItem.label}<span class='shortcut'>${shortcut}</span></a></li>`)
}
/**
* @function module:contextmenu.injectExtendedContextMenuItemsIntoDom
@ -91,11 +91,11 @@ const injectExtendedContextMenuItemIntoDom = function (menuItem) {
*/
export const injectExtendedContextMenuItemsIntoDom = function () {
Object.values(contextMenuExtensions).forEach((menuItem) => {
injectExtendedContextMenuItemIntoDom(menuItem);
});
};
injectExtendedContextMenuItemIntoDom(menuItem)
})
}
/**
* @function module:contextmenu.resetCustomMenus
* @returns {void}
*/
export const resetCustomMenus = function () { contextMenuExtensions = {}; };
export const resetCustomMenus = function () { contextMenuExtensions = {} }

View File

@ -1,6 +1,6 @@
import PlainAlertDialog from 'elix/src/plain/PlainAlertDialog.js';
import { template } from 'elix/src/base/internal.js';
import { fragmentFrom } from 'elix/src/core/htmlLiterals.js';
import PlainAlertDialog from 'elix/src/plain/PlainAlertDialog.js'
import { template } from 'elix/src/base/internal.js'
import { fragmentFrom } from 'elix/src/core/htmlLiterals.js'
/**
* @class SePlainAlertDialog
@ -11,9 +11,9 @@ export default class SePlainAlertDialog extends PlainAlertDialog {
* @returns {PlainObject}
*/
get [template] () {
const result = super[template];
const result = super[template]
// Replace the default slot with a new default slot and a button container.
const defaultSlot = result.content.querySelector('#frameContent');
const defaultSlot = result.content.querySelector('#frameContent')
if (defaultSlot) {
defaultSlot.replaceWith(fragmentFrom.html`
<div id="alertDialogContent">
@ -22,7 +22,7 @@ export default class SePlainAlertDialog extends PlainAlertDialog {
</div>
<div id="choiceButtonContainer" part="choice-button-container"></div>
</div>
`);
`)
}
result.content.append(
fragmentFrom.html`
@ -60,9 +60,9 @@ export default class SePlainAlertDialog extends PlainAlertDialog {
}
</style>
`
);
return result;
)
return result
}
}
customElements.define('se-elix-alert-dialog', SePlainAlertDialog);
customElements.define('se-elix-alert-dialog', SePlainAlertDialog)

View File

@ -1,7 +1,6 @@
import cMenuDialogHTML from './cmenuDialog.html';
const template = document.createElement('template');
// eslint-disable-next-line no-unsanitized/property
template.innerHTML = cMenuDialogHTML;
import cMenuDialogHTML from './cmenuDialog.html'
const template = document.createElement('template')
template.innerHTML = cMenuDialogHTML
/**
* @class SeCMenuDialog
*/
@ -10,52 +9,55 @@ export class SeCMenuDialog extends HTMLElement {
* @function constructor
*/
constructor () {
super();
super()
// create the shadowDom and insert the template
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.append(template.content.cloneNode(true));
this._workarea = document.getElementById('workarea');
this.$dialog = this._shadowRoot.querySelector('#cmenu_canvas');
this.$copyLink = this._shadowRoot.querySelector('#se-copy');
this.$cutLink = this._shadowRoot.querySelector('#se-cut');
this.$pasteLink = this._shadowRoot.querySelector('#se-paste');
this.$pasteInPlaceLink = this._shadowRoot.querySelector('#se-paste-in-place');
this.$deleteLink = this._shadowRoot.querySelector('#se-delete');
this.$groupLink = this._shadowRoot.querySelector('#se-group');
this.$ungroupLink = this._shadowRoot.querySelector('#se-ungroup');
this.$moveFrontLink = this._shadowRoot.querySelector('#se-move-front');
this.$moveUpLink = this._shadowRoot.querySelector('#se-move-up');
this.$moveDownLink = this._shadowRoot.querySelector('#se-move-down');
this.$moveBackLink = this._shadowRoot.querySelector('#se-move-back');
this._shadowRoot = this.attachShadow({ mode: 'open' })
this._shadowRoot.append(template.content.cloneNode(true))
this._workarea = document.getElementById('workarea')
this.$dialog = this._shadowRoot.querySelector('#cmenu_canvas')
this.$copyLink = this._shadowRoot.querySelector('#se-copy')
this.$cutLink = this._shadowRoot.querySelector('#se-cut')
this.$pasteLink = this._shadowRoot.querySelector('#se-paste')
this.$pasteInPlaceLink = this._shadowRoot.querySelector('#se-paste-in-place')
this.$deleteLink = this._shadowRoot.querySelector('#se-delete')
this.$groupLink = this._shadowRoot.querySelector('#se-group')
this.$ungroupLink = this._shadowRoot.querySelector('#se-ungroup')
this.$moveFrontLink = this._shadowRoot.querySelector('#se-move-front')
this.$moveUpLink = this._shadowRoot.querySelector('#se-move-up')
this.$moveDownLink = this._shadowRoot.querySelector('#se-move-down')
this.$moveBackLink = this._shadowRoot.querySelector('#se-move-back')
}
/**
* @function init
* @param {any} name
* @returns {void}
*/
init (i18next) {
this.setAttribute('tools-cut', i18next.t('tools.cut'));
this.setAttribute('tools-copy', i18next.t('tools.copy'));
this.setAttribute('tools-paste', i18next.t('tools.paste'));
this.setAttribute('tools-paste_in_place', i18next.t('tools.paste_in_place'));
this.setAttribute('tools-delete', i18next.t('tools.delete'));
this.setAttribute('tools-group', i18next.t('tools.group'));
this.setAttribute('tools-ungroup', i18next.t('tools.ungroup'));
this.setAttribute('tools-move_front', i18next.t('tools.move_front'));
this.setAttribute('tools-move_up', i18next.t('tools.move_up'));
this.setAttribute('tools-move_down', i18next.t('tools.move_down'));
this.setAttribute('tools-move_back', i18next.t('tools.move_back'));
this.setAttribute('tools-cut', i18next.t('tools.cut'))
this.setAttribute('tools-copy', i18next.t('tools.copy'))
this.setAttribute('tools-paste', i18next.t('tools.paste'))
this.setAttribute('tools-paste_in_place', i18next.t('tools.paste_in_place'))
this.setAttribute('tools-delete', i18next.t('tools.delete'))
this.setAttribute('tools-group', i18next.t('tools.group'))
this.setAttribute('tools-ungroup', i18next.t('tools.ungroup'))
this.setAttribute('tools-move_front', i18next.t('tools.move_front'))
this.setAttribute('tools-move_up', i18next.t('tools.move_up'))
this.setAttribute('tools-move_down', i18next.t('tools.move_down'))
this.setAttribute('tools-move_back', i18next.t('tools.move_back'))
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'disableallmenu', 'enablemenuitems', 'disablemenuitems', 'tools-cut',
return ['disableallmenu', 'enablemenuitems', 'disablemenuitems', 'tools-cut',
'tools-copy', 'tools-paste', 'tools-paste_in_place', 'tools-delete', 'tools-group',
'tools-ungroup', 'tools-move_front', 'tools-move_up', 'tools-move_down',
'tools-move_back' ];
'tools-move_back']
}
/**
* @function attributeChangedCallback
* @param {string} name
@ -64,85 +66,86 @@ export class SeCMenuDialog extends HTMLElement {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
let eles = [];
let textnode;
const sdowRoot = this._shadowRoot;
let eles = []
let textnode
const sdowRoot = this._shadowRoot
switch (name) {
case 'disableallmenu':
if (newValue === 'true') {
const elesli = sdowRoot.querySelectorAll('li');
elesli.forEach(function (eleli) {
eleli.classList.add('disabled');
});
}
break;
case 'enablemenuitems':
eles = newValue.split(',');
eles.forEach(function (ele) {
const selEle = sdowRoot.querySelector('a[href*="' + ele + '"]');
selEle.parentElement.classList.remove('disabled');
});
break;
case 'disablemenuitems':
eles = newValue.split(',');
eles.forEach(function (ele) {
const selEle = sdowRoot.querySelector('a[href*="' + ele + '"]');
selEle.parentElement.classList.add('disabled');
});
break;
case 'tools-cut':
textnode = document.createTextNode(newValue);
this.$cutLink.prepend(textnode);
break;
case 'tools-copy':
textnode = document.createTextNode(newValue);
this.$copyLink.prepend(textnode);
break;
case 'tools-paste':
this.$pasteLink.textContent = newValue;
break;
case 'tools-paste_in_place':
this.$pasteInPlaceLink.textContent = newValue;
break;
case 'tools-delete':
textnode = document.createTextNode(newValue);
this.$deleteLink.prepend(textnode);
break;
case 'tools-group':
textnode = document.createTextNode(newValue);
this.$groupLink.prepend(textnode);
break;
case 'tools-ungroup':
textnode = document.createTextNode(newValue);
this.$ungroupLink.prepend(textnode);
break;
case 'tools-move_front':
textnode = document.createTextNode(newValue);
this.$moveFrontLink.prepend(textnode);
break;
case 'tools-move_up':
textnode = document.createTextNode(newValue);
this.$moveUpLink.prepend(textnode);
break;
case 'tools-move_down':
textnode = document.createTextNode(newValue);
this.$moveDownLink.prepend(textnode);
break;
case 'tools-move_back':
textnode = document.createTextNode(newValue);
this.$moveBackLink.prepend(textnode);
break;
default:
case 'disableallmenu':
if (newValue === 'true') {
const elesli = sdowRoot.querySelectorAll('li')
elesli.forEach(function (eleli) {
eleli.classList.add('disabled')
})
}
break
case 'enablemenuitems':
eles = newValue.split(',')
eles.forEach(function (ele) {
const selEle = sdowRoot.querySelector('a[href*="' + ele + '"]')
selEle.parentElement.classList.remove('disabled')
})
break
case 'disablemenuitems':
eles = newValue.split(',')
eles.forEach(function (ele) {
const selEle = sdowRoot.querySelector('a[href*="' + ele + '"]')
selEle.parentElement.classList.add('disabled')
})
break
case 'tools-cut':
textnode = document.createTextNode(newValue)
this.$cutLink.prepend(textnode)
break
case 'tools-copy':
textnode = document.createTextNode(newValue)
this.$copyLink.prepend(textnode)
break
case 'tools-paste':
this.$pasteLink.textContent = newValue
break
case 'tools-paste_in_place':
this.$pasteInPlaceLink.textContent = newValue
break
case 'tools-delete':
textnode = document.createTextNode(newValue)
this.$deleteLink.prepend(textnode)
break
case 'tools-group':
textnode = document.createTextNode(newValue)
this.$groupLink.prepend(textnode)
break
case 'tools-ungroup':
textnode = document.createTextNode(newValue)
this.$ungroupLink.prepend(textnode)
break
case 'tools-move_front':
textnode = document.createTextNode(newValue)
this.$moveFrontLink.prepend(textnode)
break
case 'tools-move_up':
textnode = document.createTextNode(newValue)
this.$moveUpLink.prepend(textnode)
break
case 'tools-move_down':
textnode = document.createTextNode(newValue)
this.$moveDownLink.prepend(textnode)
break
case 'tools-move_back':
textnode = document.createTextNode(newValue)
this.$moveBackLink.prepend(textnode)
break
default:
// super.attributeChangedCallback(name, oldValue, newValue);
break;
break
}
}
/**
* @function get
* @returns {any}
*/
get disableallmenu () {
return this.getAttribute('disableallmenu');
return this.getAttribute('disableallmenu')
}
/**
@ -150,14 +153,15 @@ export class SeCMenuDialog extends HTMLElement {
* @returns {void}
*/
set disableallmenu (value) {
this.setAttribute('disableallmenu', value);
this.setAttribute('disableallmenu', value)
}
/**
* @function get
* @returns {any}
*/
get enablemenuitems () {
return this.getAttribute('enablemenuitems');
return this.getAttribute('enablemenuitems')
}
/**
@ -165,14 +169,15 @@ export class SeCMenuDialog extends HTMLElement {
* @returns {void}
*/
set enablemenuitems (value) {
this.setAttribute('enablemenuitems', value);
this.setAttribute('enablemenuitems', value)
}
/**
* @function get
* @returns {any}
*/
get disablemenuitems () {
return this.getAttribute('disablemenuitems');
return this.getAttribute('disablemenuitems')
}
/**
@ -180,59 +185,62 @@ export class SeCMenuDialog extends HTMLElement {
* @returns {void}
*/
set disablemenuitems (value) {
this.setAttribute('disablemenuitems', value);
this.setAttribute('disablemenuitems', value)
}
/**
* @function connectedCallback
* @returns {void}
*/
connectedCallback () {
const current = this;
const current = this
const onMenuOpenHandler = (e) => {
e.preventDefault();
e.preventDefault()
// Detect mouse position
let x = e.pageX;
let y = e.pageY;
let x = e.pageX
let y = e.pageY
const xOff = screen.width - 250; // menu width
const yOff = screen.height - (276 + 150); // menu height + bottom panel height and scroll bar
const xOff = screen.width - 250 // menu width
const yOff = screen.height - (276 + 150) // menu height + bottom panel height and scroll bar
if (x > xOff) {
x = xOff;
x = xOff
}
if (y > yOff) {
y = yOff;
y = yOff
}
current.$dialog.style.top = y + 'px';
current.$dialog.style.left = x + 'px';
current.$dialog.style.display = 'block';
};
current.$dialog.style.top = y + 'px'
current.$dialog.style.left = x + 'px'
current.$dialog.style.display = 'block'
}
const onMenuCloseHandler = (e) => {
if (e.button !== 2) {
current.$dialog.style.display = 'none';
current.$dialog.style.display = 'none'
}
};
}
const onMenuClickHandler = (e, action) => {
const triggerEvent = new CustomEvent('change', { detail: {
trigger: action
} });
this.dispatchEvent(triggerEvent);
};
this._workarea.addEventListener('contextmenu', onMenuOpenHandler);
this._workarea.addEventListener('mousedown', onMenuCloseHandler);
this.$cutLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'cut'));
this.$copyLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'copy'));
this.$pasteLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'paste'));
this.$pasteInPlaceLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'paste_in_place'));
this.$deleteLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'delete'));
this.$groupLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'group'));
this.$ungroupLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'ungroup'));
this.$moveFrontLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'move_front'));
this.$moveUpLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'move_up'));
this.$moveDownLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'move_down'));
this.$moveBackLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'move_back'));
const triggerEvent = new CustomEvent('change', {
detail: {
trigger: action
}
})
this.dispatchEvent(triggerEvent)
}
this._workarea.addEventListener('contextmenu', onMenuOpenHandler)
this._workarea.addEventListener('mousedown', onMenuCloseHandler)
this.$cutLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'cut'))
this.$copyLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'copy'))
this.$pasteLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'paste'))
this.$pasteInPlaceLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'paste_in_place'))
this.$deleteLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'delete'))
this.$groupLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'group'))
this.$ungroupLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'ungroup'))
this.$moveFrontLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'move_front'))
this.$moveUpLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'move_up'))
this.$moveDownLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'move_down'))
this.$moveBackLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'move_back'))
}
}
// Register
customElements.define('se-cmenu_canvas-dialog', SeCMenuDialog);
customElements.define('se-cmenu_canvas-dialog', SeCMenuDialog)

View File

@ -1,8 +1,7 @@
import cMenuLayersDialog from './cmenuLayersDialog.html';
import cMenuLayersDialog from './cmenuLayersDialog.html'
const template = document.createElement('template');
// eslint-disable-next-line no-unsanitized/property
template.innerHTML = cMenuLayersDialog;
const template = document.createElement('template')
template.innerHTML = cMenuLayersDialog
/**
* @class SeCMenuLayerDialog
*/
@ -11,37 +10,40 @@ export class SeCMenuLayerDialog extends HTMLElement {
* @function constructor
*/
constructor () {
super();
super()
// create the shadowDom and insert the template
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.append(template.content.cloneNode(true));
this.source = '';
this._workarea = undefined;
this.$sidePanels = document.getElementById('sidepanels');
this.$dialog = this._shadowRoot.querySelector('#cmenu_layers');
this.$duplicateLink = this._shadowRoot.querySelector('#se-dupe');
this.$deleteLink = this._shadowRoot.querySelector('#se-layer-delete');
this.$mergeDownLink = this._shadowRoot.querySelector('#se-merge-down');
this.$mergeAllLink = this._shadowRoot.querySelector('#se-merge-all');
this._shadowRoot = this.attachShadow({ mode: 'open' })
this._shadowRoot.append(template.content.cloneNode(true))
this.source = ''
this._workarea = undefined
this.$sidePanels = document.getElementById('sidepanels')
this.$dialog = this._shadowRoot.querySelector('#cmenu_layers')
this.$duplicateLink = this._shadowRoot.querySelector('#se-dupe')
this.$deleteLink = this._shadowRoot.querySelector('#se-layer-delete')
this.$mergeDownLink = this._shadowRoot.querySelector('#se-merge-down')
this.$mergeAllLink = this._shadowRoot.querySelector('#se-merge-all')
}
/**
* @function init
* @param {any} name
* @returns {void}
*/
init (i18next) {
this.setAttribute('layers-dupe', i18next.t('layers.dupe'));
this.setAttribute('layers-del', i18next.t('layers.del'));
this.setAttribute('layers-merge_down', i18next.t('layers.merge_down'));
this.setAttribute('layers-merge_all', i18next.t('layers.merge_all'));
this.setAttribute('layers-dupe', i18next.t('layers.dupe'))
this.setAttribute('layers-del', i18next.t('layers.del'))
this.setAttribute('layers-merge_down', i18next.t('layers.merge_down'))
this.setAttribute('layers-merge_all', i18next.t('layers.merge_all'))
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'value', 'leftclick', 'layers-dupe', 'layers-del', 'layers-merge_down', 'layers-merge_all' ];
return ['value', 'leftclick', 'layers-dupe', 'layers-del', 'layers-merge_down', 'layers-merge_all']
}
/**
* @function attributeChangedCallback
* @param {string} name
@ -50,37 +52,38 @@ export class SeCMenuLayerDialog extends HTMLElement {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
if (oldValue === newValue) return;
if (oldValue === newValue) return
switch (name) {
case 'value':
this.source = newValue;
if (newValue !== '' && newValue !== undefined) {
this._workarea = document.getElementById(this.source);
}
break;
case 'layers-dupe':
this.$duplicateLink.textContent = newValue;
break;
case 'layers-del':
this.$deleteLink.textContent = newValue;
break;
case 'layers-merge_down':
this.$mergeDownLink.textContent = newValue;
break;
case 'layers-merge_all':
this.$mergeAllLink.textContent = newValue;
break;
default:
case 'value':
this.source = newValue
if (newValue !== '' && newValue !== undefined) {
this._workarea = document.getElementById(this.source)
}
break
case 'layers-dupe':
this.$duplicateLink.textContent = newValue
break
case 'layers-del':
this.$deleteLink.textContent = newValue
break
case 'layers-merge_down':
this.$mergeDownLink.textContent = newValue
break
case 'layers-merge_all':
this.$mergeAllLink.textContent = newValue
break
default:
// super.attributeChangedCallback(name, oldValue, newValue);
break;
break
}
}
/**
* @function get
* @returns {any}
*/
get value () {
return this.getAttribute('value');
return this.getAttribute('value')
}
/**
@ -88,14 +91,15 @@ export class SeCMenuLayerDialog extends HTMLElement {
* @returns {void}
*/
set value (value) {
this.setAttribute('value', value);
this.setAttribute('value', value)
}
/**
* @function get
* @returns {any}
*/
get leftclick () {
return this.getAttribute('leftclick');
return this.getAttribute('leftclick')
}
/**
@ -103,47 +107,50 @@ export class SeCMenuLayerDialog extends HTMLElement {
* @returns {void}
*/
set leftclick (value) {
this.setAttribute('leftclick', value);
this.setAttribute('leftclick', value)
}
/**
* @function connectedCallback
* @returns {void}
*/
connectedCallback () {
const current = this;
const current = this
const onMenuOpenHandler = (e) => {
e.preventDefault();
current.$dialog.style.top = e.pageY + 'px';
current.$dialog.style.left = e.pageX - 126 + 'px';
current.$dialog.style.display = 'block';
};
e.preventDefault()
current.$dialog.style.top = e.pageY + 'px'
current.$dialog.style.left = e.pageX - 126 + 'px'
current.$dialog.style.display = 'block'
}
const onMenuCloseHandler = (e) => {
if (e.button !== 2) {
current.$dialog.style.display = 'none';
current.$dialog.style.display = 'none'
}
};
const onMenuClickHandler = (e, action, id) => {
const triggerEvent = new CustomEvent('change', { detail: {
trigger: action,
source: id
} });
this.dispatchEvent(triggerEvent);
current.$dialog.style.display = 'none';
};
if (this._workarea !== undefined) {
this._workarea.addEventListener('contextmenu', onMenuOpenHandler);
if (this.getAttribute('leftclick') === 'true') {
this._workarea.addEventListener('click', onMenuOpenHandler);
}
this._workarea.addEventListener('mousedown', onMenuCloseHandler);
this.$sidePanels.addEventListener('mousedown', onMenuCloseHandler);
}
this.$duplicateLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'dupe', this.source));
this.$deleteLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'delete', this.source));
this.$mergeDownLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'merge_down', this.source));
this.$mergeAllLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'merge_all', this.source));
const onMenuClickHandler = (e, action, id) => {
const triggerEvent = new CustomEvent('change', {
detail: {
trigger: action,
source: id
}
})
this.dispatchEvent(triggerEvent)
current.$dialog.style.display = 'none'
}
if (this._workarea !== undefined) {
this._workarea.addEventListener('contextmenu', onMenuOpenHandler)
if (this.getAttribute('leftclick') === 'true') {
this._workarea.addEventListener('click', onMenuOpenHandler)
}
this._workarea.addEventListener('mousedown', onMenuCloseHandler)
this.$sidePanels.addEventListener('mousedown', onMenuCloseHandler)
}
this.$duplicateLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'dupe', this.source))
this.$deleteLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'delete', this.source))
this.$mergeDownLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'merge_down', this.source))
this.$mergeAllLink.addEventListener('click', (evt) => onMenuClickHandler(evt, 'merge_all', this.source))
}
}
// Register
customElements.define('se-cmenu-layers', SeCMenuLayerDialog);
customElements.define('se-cmenu-layers', SeCMenuLayerDialog)

View File

@ -1,7 +1,6 @@
import editorPreferencesDialog from './editorPreferencesDialog.html';
const template = document.createElement('template');
// eslint-disable-next-line no-unsanitized/property
template.innerHTML = editorPreferencesDialog;
import editorPreferencesDialog from './editorPreferencesDialog.html'
const template = document.createElement('template')
template.innerHTML = editorPreferencesDialog
/**
* @class SeEditPrefsDialog
*/
@ -10,52 +9,55 @@ export class SeEditPrefsDialog extends HTMLElement {
* @function constructor
*/
constructor () {
super();
super()
// create the shadowDom and insert the template
this.colorBlocks = [ '#FFF', '#888', '#000', 'chessboard' ];
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.append(template.content.cloneNode(true));
this.$dialog = this._shadowRoot.querySelector('#svg_prefs');
this.$saveBtn = this._shadowRoot.querySelector('#tool_prefs_save');
this.$cancelBtn = this._shadowRoot.querySelector('#tool_prefs_cancel');
this.$langSelect = this._shadowRoot.querySelector('#lang_select');
this.$bgBlocks = this._shadowRoot.querySelector('#bg_blocks');
this.$bgURL = this._shadowRoot.querySelector('#canvas_bg_url');
this.$gridSnappingOn = this._shadowRoot.querySelector('#grid_snapping_on');
this.$gridSnappingStep = this._shadowRoot.querySelector('#grid_snapping_step');
this.$gridColor = this._shadowRoot.querySelector('#grid_color');
this.$showRulers = this._shadowRoot.querySelector('#show_rulers');
this.$baseUnit = this._shadowRoot.querySelector('#base_unit');
this.colorBlocks = ['#FFF', '#888', '#000', 'chessboard']
this._shadowRoot = this.attachShadow({ mode: 'open' })
this._shadowRoot.append(template.content.cloneNode(true))
this.$dialog = this._shadowRoot.querySelector('#svg_prefs')
this.$saveBtn = this._shadowRoot.querySelector('#tool_prefs_save')
this.$cancelBtn = this._shadowRoot.querySelector('#tool_prefs_cancel')
this.$langSelect = this._shadowRoot.querySelector('#lang_select')
this.$bgBlocks = this._shadowRoot.querySelector('#bg_blocks')
this.$bgURL = this._shadowRoot.querySelector('#canvas_bg_url')
this.$gridSnappingOn = this._shadowRoot.querySelector('#grid_snapping_on')
this.$gridSnappingStep = this._shadowRoot.querySelector('#grid_snapping_step')
this.$gridColor = this._shadowRoot.querySelector('#grid_color')
this.$showRulers = this._shadowRoot.querySelector('#show_rulers')
this.$baseUnit = this._shadowRoot.querySelector('#base_unit')
}
/**
* @function init
* @param {any} name
* @returns {void}
*/
init (i18next) {
this.setAttribute('common-ok', i18next.t('common.ok'));
this.setAttribute('common-cancel', i18next.t('common.cancel'));
this.setAttribute('config-editor_prefs', i18next.t('config.editor_prefs'));
this.setAttribute('config-language', i18next.t('config.language'));
this.setAttribute('config-background', i18next.t('config.background'));
this.setAttribute('common-url', i18next.t('common.url'));
this.setAttribute('config-editor_bg_note', i18next.t('config.editor_bg_note'));
this.setAttribute('config-grid', i18next.t('config.grid'));
this.setAttribute('config-snapping_onoff', i18next.t('config.snapping_onoff'));
this.setAttribute('config-snapping_stepsize', i18next.t('config.snapping_stepsize'));
this.setAttribute('config-grid_color', i18next.t('config.grid_color'));
this.setAttribute('config-units_and_rulers', i18next.t('config.units_and_rulers'));
this.setAttribute('config-show_rulers', i18next.t('config.show_rulers'));
this.setAttribute('config-base_unit', i18next.t('config.base_unit'));
this.setAttribute('common-ok', i18next.t('common.ok'))
this.setAttribute('common-cancel', i18next.t('common.cancel'))
this.setAttribute('config-editor_prefs', i18next.t('config.editor_prefs'))
this.setAttribute('config-language', i18next.t('config.language'))
this.setAttribute('config-background', i18next.t('config.background'))
this.setAttribute('common-url', i18next.t('common.url'))
this.setAttribute('config-editor_bg_note', i18next.t('config.editor_bg_note'))
this.setAttribute('config-grid', i18next.t('config.grid'))
this.setAttribute('config-snapping_onoff', i18next.t('config.snapping_onoff'))
this.setAttribute('config-snapping_stepsize', i18next.t('config.snapping_stepsize'))
this.setAttribute('config-grid_color', i18next.t('config.grid_color'))
this.setAttribute('config-units_and_rulers', i18next.t('config.units_and_rulers'))
this.setAttribute('config-show_rulers', i18next.t('config.show_rulers'))
this.setAttribute('config-base_unit', i18next.t('config.base_unit'))
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
// eslint-disable-next-line max-len
return [ 'dialog', 'lang', 'canvasbg', 'bgurl', 'gridsnappingon', 'gridsnappingstep', 'gridcolor', 'showrulers', 'baseunit', 'common-ok', 'common-cancel', 'config-editor_prefs', 'config-language', 'config-background', 'common-url', 'config-editor_bg_note', 'config-grid', 'config-snapping_onoff', 'config-snapping_stepsize', 'config-grid_color', 'config-units_and_rulers', 'config-show_rulers', 'config-base_unit' ];
return ['dialog', 'lang', 'canvasbg', 'bgurl', 'gridsnappingon', 'gridsnappingstep', 'gridcolor', 'showrulers', 'baseunit', 'common-ok', 'common-cancel', 'config-editor_prefs', 'config-language', 'config-background', 'common-url', 'config-editor_bg_note', 'config-grid', 'config-snapping_onoff', 'config-snapping_stepsize', 'config-grid_color', 'config-units_and_rulers', 'config-show_rulers', 'config-base_unit']
}
/**
* @function attributeChangedCallback
* @param {string} name
@ -64,128 +66,129 @@ export class SeEditPrefsDialog extends HTMLElement {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
if (oldValue === newValue) return;
const blocks = this.$bgBlocks.querySelectorAll('div');
const curBg = 'cur_background';
let node;
if (oldValue === newValue) return
const blocks = this.$bgBlocks.querySelectorAll('div')
const curBg = 'cur_background'
let node
switch (name) {
case 'dialog':
if (newValue === 'open') {
this.$dialog.open();
} else {
this.$dialog.close();
}
break;
case 'lang':
this.$langSelect.value = newValue;
break;
case 'canvasbg':
if (!newValue) {
if (blocks.length > 0) {
blocks[0].classList.add(curBg);
case 'dialog':
if (newValue === 'open') {
this.$dialog.open()
} else {
this.$dialog.close()
}
} else {
blocks.forEach(function (blk) {
const isBg = blk.dataset.bgColor === newValue;
if (isBg) {
blk.classList.add(curBg);
} else {
blk.classList.remove(curBg);
break
case 'lang':
this.$langSelect.value = newValue
break
case 'canvasbg':
if (!newValue) {
if (blocks.length > 0) {
blocks[0].classList.add(curBg)
}
});
}
break;
case 'bgurl':
this.$bgURL.value = newValue;
break;
case 'gridsnappingon':
if (newValue === 'true') {
this.$gridSnappingOn.checked = true;
} else if (newValue === 'false') {
this.$gridSnappingOn.checked = false;
}
break;
case 'gridsnappingstep':
this.$gridSnappingStep.value = newValue;
break;
case 'gridcolor':
this.$gridColor.value = newValue;
break;
case 'showrulers':
if (newValue === 'true') {
this.$showRulers.checked = true;
} else if (newValue === 'false') {
this.$showRulers.checked = false;
}
break;
case 'baseunit':
this.$baseUnit.value = newValue;
break;
case 'common-ok':
this.$saveBtn.textContent = newValue;
break;
case 'common-cancel':
this.$cancelBtn.textContent = newValue;
break;
case 'config-editor_prefs':
node = this._shadowRoot.querySelector('#svginfo_editor_prefs');
node.textContent = newValue;
break;
case 'config-language':
node = this._shadowRoot.querySelector('#svginfo_lang');
node.textContent = newValue;
break;
case 'config-background':
node = this._shadowRoot.querySelector('#svginfo_change_background');
node.textContent = newValue;
break;
case 'common-url':
node = this._shadowRoot.querySelector('#svginfo_bg_url');
node.textContent = newValue;
break;
case 'config-editor_bg_note':
node = this._shadowRoot.querySelector('#svginfo_bg_note');
node.textContent = newValue;
break;
case 'config-grid':
node = this._shadowRoot.querySelector('#svginfo_grid_settings');
node.textContent = newValue;
break;
case 'config-snapping_onoff':
node = this._shadowRoot.querySelector('#svginfo_snap_onoff');
node.textContent = newValue;
break;
case 'config-snapping_stepsize':
node = this._shadowRoot.querySelector('#svginfo_snap_step');
node.textContent = newValue;
break;
case 'config-grid_color':
node = this._shadowRoot.querySelector('#svginfo_grid_color');
node.textContent = newValue;
break;
case 'config-units_and_rulers':
node = this._shadowRoot.querySelector('#svginfo_units_rulers');
node.textContent = newValue;
break;
case 'config-show_rulers':
node = this._shadowRoot.querySelector('#svginfo_rulers_onoff');
node.textContent = newValue;
break;
case 'config-base_unit':
node = this._shadowRoot.querySelector('#svginfo_unit');
node.textContent = newValue;
break;
default:
super.attributeChangedCallback(name, oldValue, newValue);
break;
} else {
blocks.forEach(function (blk) {
const isBg = blk.dataset.bgColor === newValue
if (isBg) {
blk.classList.add(curBg)
} else {
blk.classList.remove(curBg)
}
})
}
break
case 'bgurl':
this.$bgURL.value = newValue
break
case 'gridsnappingon':
if (newValue === 'true') {
this.$gridSnappingOn.checked = true
} else if (newValue === 'false') {
this.$gridSnappingOn.checked = false
}
break
case 'gridsnappingstep':
this.$gridSnappingStep.value = newValue
break
case 'gridcolor':
this.$gridColor.value = newValue
break
case 'showrulers':
if (newValue === 'true') {
this.$showRulers.checked = true
} else if (newValue === 'false') {
this.$showRulers.checked = false
}
break
case 'baseunit':
this.$baseUnit.value = newValue
break
case 'common-ok':
this.$saveBtn.textContent = newValue
break
case 'common-cancel':
this.$cancelBtn.textContent = newValue
break
case 'config-editor_prefs':
node = this._shadowRoot.querySelector('#svginfo_editor_prefs')
node.textContent = newValue
break
case 'config-language':
node = this._shadowRoot.querySelector('#svginfo_lang')
node.textContent = newValue
break
case 'config-background':
node = this._shadowRoot.querySelector('#svginfo_change_background')
node.textContent = newValue
break
case 'common-url':
node = this._shadowRoot.querySelector('#svginfo_bg_url')
node.textContent = newValue
break
case 'config-editor_bg_note':
node = this._shadowRoot.querySelector('#svginfo_bg_note')
node.textContent = newValue
break
case 'config-grid':
node = this._shadowRoot.querySelector('#svginfo_grid_settings')
node.textContent = newValue
break
case 'config-snapping_onoff':
node = this._shadowRoot.querySelector('#svginfo_snap_onoff')
node.textContent = newValue
break
case 'config-snapping_stepsize':
node = this._shadowRoot.querySelector('#svginfo_snap_step')
node.textContent = newValue
break
case 'config-grid_color':
node = this._shadowRoot.querySelector('#svginfo_grid_color')
node.textContent = newValue
break
case 'config-units_and_rulers':
node = this._shadowRoot.querySelector('#svginfo_units_rulers')
node.textContent = newValue
break
case 'config-show_rulers':
node = this._shadowRoot.querySelector('#svginfo_rulers_onoff')
node.textContent = newValue
break
case 'config-base_unit':
node = this._shadowRoot.querySelector('#svginfo_unit')
node.textContent = newValue
break
default:
super.attributeChangedCallback(name, oldValue, newValue)
break
}
}
/**
* @function get
* @returns {any}
*/
get lang () {
return this.getAttribute('lang');
return this.getAttribute('lang')
}
/**
@ -193,173 +196,194 @@ export class SeEditPrefsDialog extends HTMLElement {
* @returns {void}
*/
set lang (value) {
this.setAttribute('lang', value);
this.setAttribute('lang', value)
}
/**
* @function get
* @returns {any}
*/
get canvasbg () {
return this.getAttribute('canvasbg');
return this.getAttribute('canvasbg')
}
/**
* @function set
* @returns {void}
*/
set canvasbg (value) {
this.setAttribute('canvasbg', value);
this.setAttribute('canvasbg', value)
}
/**
* @function get
* @returns {any}
*/
get bgurl () {
return this.getAttribute('bgurl');
return this.getAttribute('bgurl')
}
/**
* @function set
* @returns {void}
*/
set bgurl (value) {
this.setAttribute('bgurl', value);
this.setAttribute('bgurl', value)
}
/**
* @function get
* @returns {any}
*/
get dialog () {
return this.getAttribute('dialog');
return this.getAttribute('dialog')
}
/**
* @function set
* @returns {void}
*/
set dialog (value) {
this.setAttribute('dialog', value);
this.setAttribute('dialog', value)
}
/**
* @function get
* @returns {any}
*/
get gridsnappingon () {
return this.getAttribute('gridsnappingon');
return this.getAttribute('gridsnappingon')
}
/**
* @function set
* @returns {void}
*/
set gridsnappingon (value) {
this.setAttribute('gridsnappingon', value);
this.setAttribute('gridsnappingon', value)
}
/**
* @function get
* @returns {any}
*/
get gridsnappingstep () {
return this.getAttribute('gridsnappingstep');
return this.getAttribute('gridsnappingstep')
}
/**
* @function set
* @returns {void}
*/
set gridsnappingstep (value) {
this.setAttribute('gridsnappingstep', value);
this.setAttribute('gridsnappingstep', value)
}
/**
* @function get
* @returns {any}
*/
get gridcolor () {
return this.getAttribute('gridcolor');
return this.getAttribute('gridcolor')
}
/**
* @function set
* @returns {void}
*/
set gridcolor (value) {
this.setAttribute('gridcolor', value);
this.setAttribute('gridcolor', value)
}
/**
* @function get
* @returns {any}
*/
get showrulers () {
return this.getAttribute('showrulers');
return this.getAttribute('showrulers')
}
/**
* @function set
* @returns {void}
*/
set showrulers (value) {
this.setAttribute('showrulers', value);
this.setAttribute('showrulers', value)
}
/**
* @function get
* @returns {any}
*/
get baseunit () {
return this.getAttribute('baseunit');
return this.getAttribute('baseunit')
}
/**
* @function set
* @returns {void}
*/
set baseunit (value) {
this.setAttribute('baseunit', value);
this.setAttribute('baseunit', value)
}
/**
* @function connectedCallback
* @returns {void}
*/
connectedCallback () {
const onCancelHandler = () => {
const closeEvent = new CustomEvent('change', { detail: {
dialog: 'closed'
} });
this.dispatchEvent(closeEvent);
};
const closeEvent = new CustomEvent('change', {
detail: {
dialog: 'closed'
}
})
this.dispatchEvent(closeEvent)
}
const onSaveHandler = () => {
const color = this.$bgBlocks.querySelector('.cur_background').dataset.bgColor || '#FFF';
const closeEvent = new CustomEvent('change', { detail: {
lang: this.$langSelect.value,
dialog: 'close',
bgcolor: color,
bgurl: this.$bgURL.value,
gridsnappingon: this.$gridSnappingOn.checked,
gridsnappingstep: this.$gridSnappingStep.value,
showrulers: this.$showRulers.checked,
baseunit: this.$baseUnit.value
} });
this.dispatchEvent(closeEvent);
};
const color = this.$bgBlocks.querySelector('.cur_background').dataset.bgColor || '#FFF'
const closeEvent = new CustomEvent('change', {
detail: {
lang: this.$langSelect.value,
dialog: 'close',
bgcolor: color,
bgurl: this.$bgURL.value,
gridsnappingon: this.$gridSnappingOn.checked,
gridsnappingstep: this.$gridSnappingStep.value,
showrulers: this.$showRulers.checked,
baseunit: this.$baseUnit.value
}
})
this.dispatchEvent(closeEvent)
}
// Set up editor background functionality
const currentObj = this;
const currentObj = this
this.colorBlocks.forEach(function (e) {
const newdiv = document.createElement('div');
const newdiv = document.createElement('div')
if (e === 'chessboard') {
newdiv.dataset.bgColor = e;
newdiv.style.backgroundImage = 'url(data:image/gif;base64,R0lGODlhEAAQAIAAAP///9bW1iH5BAAAAAAALAAAAAAQABAAAAIfjG+gq4jM3IFLJgpswNly/XkcBpIiVaInlLJr9FZWAQA7)';
newdiv.classList.add('color_block');
newdiv.dataset.bgColor = e
newdiv.style.backgroundImage = 'url(data:image/gif;base64,R0lGODlhEAAQAIAAAP///9bW1iH5BAAAAAAALAAAAAAQABAAAAIfjG+gq4jM3IFLJgpswNly/XkcBpIiVaInlLJr9FZWAQA7)'
newdiv.classList.add('color_block')
} else {
newdiv.dataset.bgColor = e; // setAttribute('data-bgcolor', e);
newdiv.style.backgroundColor = e;
newdiv.classList.add('color_block');
newdiv.dataset.bgColor = e // setAttribute('data-bgcolor', e);
newdiv.style.backgroundColor = e
newdiv.classList.add('color_block')
}
currentObj.$bgBlocks.append(newdiv);
});
const blocks = this.$bgBlocks.querySelectorAll('div');
const curBg = 'cur_background';
currentObj.$bgBlocks.append(newdiv)
})
const blocks = this.$bgBlocks.querySelectorAll('div')
const curBg = 'cur_background'
blocks.forEach(function (blk) {
blk.addEventListener('click', function () {
blocks.forEach((el) => el.classList.remove(curBg));
blk.classList.add(curBg);
});
});
this.$saveBtn.addEventListener('click', onSaveHandler);
this.$cancelBtn.addEventListener('click', onCancelHandler);
this.$dialog.addEventListener('close', onCancelHandler);
blocks.forEach((el) => el.classList.remove(curBg))
blk.classList.add(curBg)
})
})
this.$saveBtn.addEventListener('click', onSaveHandler)
this.$cancelBtn.addEventListener('click', onCancelHandler)
this.$dialog.addEventListener('close', onCancelHandler)
}
}
// Register
customElements.define('se-edit-prefs-dialog', SeEditPrefsDialog);
customElements.define('se-edit-prefs-dialog', SeEditPrefsDialog)

View File

@ -1,9 +1,8 @@
import './se-elix/define/NumberSpinBox.js';
import './se-elix/define/NumberSpinBox.js'
import exportDialogHTML from './exportDialog.html';
const template = document.createElement('template');
// eslint-disable-next-line no-unsanitized/property
template.innerHTML = exportDialogHTML;
import exportDialogHTML from './exportDialog.html'
const template = document.createElement('template')
template.innerHTML = exportDialogHTML
/**
* @class SeExportDialog
*/
@ -12,36 +11,39 @@ export class SeExportDialog extends HTMLElement {
* @function constructor
*/
constructor () {
super();
super()
// create the shadowDom and insert the template
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.append(template.content.cloneNode(true));
this.$dialog = this._shadowRoot.querySelector('#export_box');
this.$okBtn = this._shadowRoot.querySelector('#export_ok');
this.$cancelBtn = this._shadowRoot.querySelector('#export_cancel');
this.$exportOption = this._shadowRoot.querySelector('#se-storage-pref');
this.$qualityCont = this._shadowRoot.querySelector('#se-quality');
this.$input = this._shadowRoot.querySelector('elix-number-spin-box');
this.value = 1;
this._shadowRoot = this.attachShadow({ mode: 'open' })
this._shadowRoot.append(template.content.cloneNode(true))
this.$dialog = this._shadowRoot.querySelector('#export_box')
this.$okBtn = this._shadowRoot.querySelector('#export_ok')
this.$cancelBtn = this._shadowRoot.querySelector('#export_cancel')
this.$exportOption = this._shadowRoot.querySelector('#se-storage-pref')
this.$qualityCont = this._shadowRoot.querySelector('#se-quality')
this.$input = this._shadowRoot.querySelector('elix-number-spin-box')
this.value = 1
}
/**
* @function init
* @param {any} name
* @returns {void}
*/
init (i18next) {
this.setAttribute('common-ok', i18next.t('common.ok'));
this.setAttribute('common-cancel', i18next.t('common.cancel'));
this.setAttribute('ui-quality', i18next.t('ui.quality'));
this.setAttribute('ui-export_type_label', i18next.t('ui.export_type_label'));
this.setAttribute('common-ok', i18next.t('common.ok'))
this.setAttribute('common-cancel', i18next.t('common.cancel'))
this.setAttribute('ui-quality', i18next.t('ui.quality'))
this.setAttribute('ui-export_type_label', i18next.t('ui.export_type_label'))
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'dialog', 'common-ok', 'common-cancel', 'ui-quality', 'ui-export_type_label' ];
return ['dialog', 'common-ok', 'common-cancel', 'ui-quality', 'ui-export_type_label']
}
/**
* @function attributeChangedCallback
* @param {string} name
@ -50,86 +52,91 @@ export class SeExportDialog extends HTMLElement {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
let node;
let node
switch (name) {
case 'dialog':
if (newValue === 'open') {
this.$dialog.open();
} else {
this.$dialog.close();
}
break;
case 'common-ok':
this.$okBtn.textContent = newValue;
break;
case 'common-cancel':
this.$cancelBtn.textContent = newValue;
break;
case 'ui-quality':
node = this._shadowRoot.querySelector('#se-quality');
node.prepend(newValue);
break;
case 'ui-export_type_label':
node = this._shadowRoot.querySelector('#export_select');
node.textContent = newValue;
break;
default:
case 'dialog':
if (newValue === 'open') {
this.$dialog.open()
} else {
this.$dialog.close()
}
break
case 'common-ok':
this.$okBtn.textContent = newValue
break
case 'common-cancel':
this.$cancelBtn.textContent = newValue
break
case 'ui-quality':
node = this._shadowRoot.querySelector('#se-quality')
node.prepend(newValue)
break
case 'ui-export_type_label':
node = this._shadowRoot.querySelector('#export_select')
node.textContent = newValue
break
default:
// super.attributeChangedCallback(name, oldValue, newValue);
break;
break
}
}
/**
* @function get
* @returns {any}
*/
get dialog () {
return this.getAttribute('dialog');
return this.getAttribute('dialog')
}
/**
* @function set
* @returns {void}
*/
set dialog (value) {
this.setAttribute('dialog', value);
this.setAttribute('dialog', value)
}
/**
* @function connectedCallback
* @returns {void}
*/
connectedCallback () {
this.$input.addEventListener('change', (e) => {
e.preventDefault();
this.value = e.target.value;
});
e.preventDefault()
this.value = e.target.value
})
this.$input.addEventListener('click', (e) => {
e.preventDefault();
this.value = e.target.value;
});
e.preventDefault()
this.value = e.target.value
})
const onSubmitHandler = (e, action) => {
if (action === 'cancel') {
document.getElementById('se-export-dialog').setAttribute('dialog', 'close');
document.getElementById('se-export-dialog').setAttribute('dialog', 'close')
} else {
const triggerEvent = new CustomEvent('change', { detail: {
trigger: action,
imgType: this.$exportOption.value,
quality: this.value
} });
this.dispatchEvent(triggerEvent);
document.getElementById('se-export-dialog').setAttribute('dialog', 'close');
const triggerEvent = new CustomEvent('change', {
detail: {
trigger: action,
imgType: this.$exportOption.value,
quality: this.value
}
})
this.dispatchEvent(triggerEvent)
document.getElementById('se-export-dialog').setAttribute('dialog', 'close')
}
};
}
const onChangeHandler = (e) => {
if (e.target.value === 'PDF') {
this.$qualityCont.style.display = 'none';
this.$qualityCont.style.display = 'none'
} else {
this.$qualityCont.style.display = 'block';
this.$qualityCont.style.display = 'block'
}
};
this.$okBtn.addEventListener('click', (evt) => onSubmitHandler(evt, 'ok'));
this.$cancelBtn.addEventListener('click', (evt) => onSubmitHandler(evt, 'cancel'));
this.$exportOption.addEventListener('change', (evt) => onChangeHandler(evt));
}
this.$okBtn.addEventListener('click', (evt) => onSubmitHandler(evt, 'ok'))
this.$cancelBtn.addEventListener('click', (evt) => onSubmitHandler(evt, 'cancel'))
this.$exportOption.addEventListener('change', (evt) => onChangeHandler(evt))
}
}
// Register
customElements.define('se-export-dialog', SeExportDialog);
customElements.define('se-export-dialog', SeExportDialog)

View File

@ -1,9 +1,8 @@
import { isValidUnit } from '../../common/units.js';
import imagePropertiesDialogHTML from './imagePropertiesDialog.html';
import { isValidUnit } from '../../common/units.js'
import imagePropertiesDialogHTML from './imagePropertiesDialog.html'
const template = document.createElement('template');
// eslint-disable-next-line no-unsanitized/property
template.innerHTML = imagePropertiesDialogHTML;
const template = document.createElement('template')
template.innerHTML = imagePropertiesDialogHTML
/**
* @class SeImgPropDialog
*/
@ -12,39 +11,40 @@ export class SeImgPropDialog extends HTMLElement {
* @function constructor
*/
constructor () {
super();
super()
// create the shadowDom and insert the template
this.eventlisten = false;
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.append(template.content.cloneNode(true));
this.$saveBtn = this._shadowRoot.querySelector('#tool_docprops_save');
this.$cancelBtn = this._shadowRoot.querySelector('#tool_docprops_cancel');
this.$resolution = this._shadowRoot.querySelector('#resolution');
this.$canvasTitle = this._shadowRoot.querySelector('#canvas_title');
this.$canvasWidth = this._shadowRoot.querySelector('#canvas_width');
this.$canvasHeight = this._shadowRoot.querySelector('#canvas_height');
this.$imageOptEmbed = this._shadowRoot.querySelector('#image_embed');
this.$imageOptRef = this._shadowRoot.querySelector('#image_ref');
this.$dialog = this._shadowRoot.querySelector('#svg_docprops');
this.eventlisten = false
this._shadowRoot = this.attachShadow({ mode: 'open' })
this._shadowRoot.append(template.content.cloneNode(true))
this.$saveBtn = this._shadowRoot.querySelector('#tool_docprops_save')
this.$cancelBtn = this._shadowRoot.querySelector('#tool_docprops_cancel')
this.$resolution = this._shadowRoot.querySelector('#resolution')
this.$canvasTitle = this._shadowRoot.querySelector('#canvas_title')
this.$canvasWidth = this._shadowRoot.querySelector('#canvas_width')
this.$canvasHeight = this._shadowRoot.querySelector('#canvas_height')
this.$imageOptEmbed = this._shadowRoot.querySelector('#image_embed')
this.$imageOptRef = this._shadowRoot.querySelector('#image_ref')
this.$dialog = this._shadowRoot.querySelector('#svg_docprops')
}
/**
* @function init
* @param {any} name
* @returns {void}
*/
init (i18next) {
this.setAttribute('common-ok', i18next.t('common.ok'));
this.setAttribute('common-cancel', i18next.t('common.cancel'));
this.setAttribute('config-image_props', i18next.t('config.image_props'));
this.setAttribute('config-doc_title', i18next.t('config.doc_title'));
this.setAttribute('config-doc_dims', i18next.t('config.doc_dims'));
this.setAttribute('common-width', i18next.t('common.width'));
this.setAttribute('common-height', i18next.t('common.height'));
this.setAttribute('config-select_predefined', i18next.t('config.select_predefined'));
this.setAttribute('tools-fit-to-content', i18next.t('tools.fitToContent'));
this.setAttribute('config-included_images', i18next.t('config.included_images'));
this.setAttribute('config-image_opt_embed', i18next.t('config.image_opt_embed'));
this.setAttribute('config-image_opt_ref', i18next.t('config.image_opt_ref'));
this.setAttribute('common-ok', i18next.t('common.ok'))
this.setAttribute('common-cancel', i18next.t('common.cancel'))
this.setAttribute('config-image_props', i18next.t('config.image_props'))
this.setAttribute('config-doc_title', i18next.t('config.doc_title'))
this.setAttribute('config-doc_dims', i18next.t('config.doc_dims'))
this.setAttribute('common-width', i18next.t('common.width'))
this.setAttribute('common-height', i18next.t('common.height'))
this.setAttribute('config-select_predefined', i18next.t('config.select_predefined'))
this.setAttribute('tools-fit-to-content', i18next.t('tools.fitToContent'))
this.setAttribute('config-included_images', i18next.t('config.included_images'))
this.setAttribute('config-image_opt_embed', i18next.t('config.image_opt_embed'))
this.setAttribute('config-image_opt_ref', i18next.t('config.image_opt_ref'))
}
/**
@ -52,12 +52,13 @@ export class SeImgPropDialog extends HTMLElement {
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'title', 'width', 'height', 'save', 'dialog', 'embed', 'common-ok',
return ['title', 'width', 'height', 'save', 'dialog', 'embed', 'common-ok',
'common-cancel', 'config-image_props', 'config-doc_title', 'config-doc_dims',
'common-width', 'common-height', 'config-select_predefined',
'tools-fit-to-content', 'config-included_images', 'config-image_opt_embed',
'config-image_opt_ref' ];
'config-image_opt_ref']
}
/**
* @function attributeChangedCallback
* @param {string} name
@ -66,117 +67,118 @@ export class SeImgPropDialog extends HTMLElement {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
if (oldValue === newValue) return;
let node ;
if (oldValue === newValue) return
let node
switch (name) {
case 'title':
this.$canvasTitle.value = newValue;
break;
case 'width':
if (newValue === 'fit') {
this.$canvasWidth.removeAttribute('disabled');
this.$canvasWidth.value = 100;
this.$canvasHeight.removeAttribute('disabled');
this.$canvasHeight.value = 100;
} else {
this.$canvasWidth.value = newValue;
}
break;
case 'height':
if (newValue === 'fit') {
this.$canvasWidth.removeAttribute('disabled');
this.$canvasWidth.value = 100;
this.$canvasHeight.removeAttribute('disabled');
this.$canvasHeight.value = 100;
} else {
this.$canvasHeight.value = newValue;
}
break;
case 'dialog':
if (this.eventlisten) {
if (newValue === 'open') {
this.$dialog.open();
case 'title':
this.$canvasTitle.value = newValue
break
case 'width':
if (newValue === 'fit') {
this.$canvasWidth.removeAttribute('disabled')
this.$canvasWidth.value = 100
this.$canvasHeight.removeAttribute('disabled')
this.$canvasHeight.value = 100
} else {
this.$dialog.close();
this.$canvasWidth.value = newValue
}
}
break;
case 'save':
if (newValue === 'ref') {
this.$imageOptEmbed.setAttribute('checked', false);
this.$imageOptRef.setAttribute('checked', true);
} else {
this.$imageOptEmbed.setAttribute('checked', true);
this.$imageOptRef.setAttribute('checked', false);
}
break;
case 'embed':
if (newValue.includes('one')) {
const data = newValue.split('|');
if (data.length > 1) {
this._shadowRoot.querySelector('#image_opt_embed').setAttribute('title', data[1]);
this._shadowRoot.querySelector('#image_opt_embed').setAttribute('disabled', 'disabled');
this._shadowRoot.querySelector('#image_opt_embed').style.color = '#666';
break
case 'height':
if (newValue === 'fit') {
this.$canvasWidth.removeAttribute('disabled')
this.$canvasWidth.value = 100
this.$canvasHeight.removeAttribute('disabled')
this.$canvasHeight.value = 100
} else {
this.$canvasHeight.value = newValue
}
}
break;
case 'common-ok':
this.$saveBtn.textContent = newValue;
break;
case 'common-cancel':
this.$cancelBtn.textContent = newValue;
break;
case 'config-image_props':
node = this._shadowRoot.querySelector('#svginfo_image_props');
node.textContent = newValue;
break;
case 'config-doc_title':
node = this._shadowRoot.querySelector('#svginfo_title');
node.textContent = newValue;
break;
case 'config-doc_dims':
node = this._shadowRoot.querySelector('#svginfo_dim');
node.textContent = newValue;
break;
case 'common-width':
node = this._shadowRoot.querySelector('#svginfo_width');
node.textContent = newValue;
break;
case 'common-height':
node = this._shadowRoot.querySelector('#svginfo_height');
node.textContent = newValue;
break;
case 'config-select_predefined':
node = this._shadowRoot.querySelector('#selectedPredefined');
node.textContent = newValue;
break;
case 'tools-fit-to-content':
node = this._shadowRoot.querySelector('#fitToContent');
node.textContent = newValue;
break;
case 'config-included_images':
node = this._shadowRoot.querySelector('#includedImages');
node.textContent = newValue;
break;
case 'config-image_opt_embed':
node = this._shadowRoot.querySelector('#image_opt_embed');
node.textContent = newValue;
break;
case 'config-image_opt_ref':
node = this._shadowRoot.querySelector('#image_opt_ref');
node.textContent = newValue;
break;
default:
super.attributeChangedCallback(name, oldValue, newValue);
break;
break
case 'dialog':
if (this.eventlisten) {
if (newValue === 'open') {
this.$dialog.open()
} else {
this.$dialog.close()
}
}
break
case 'save':
if (newValue === 'ref') {
this.$imageOptEmbed.setAttribute('checked', false)
this.$imageOptRef.setAttribute('checked', true)
} else {
this.$imageOptEmbed.setAttribute('checked', true)
this.$imageOptRef.setAttribute('checked', false)
}
break
case 'embed':
if (newValue.includes('one')) {
const data = newValue.split('|')
if (data.length > 1) {
this._shadowRoot.querySelector('#image_opt_embed').setAttribute('title', data[1])
this._shadowRoot.querySelector('#image_opt_embed').setAttribute('disabled', 'disabled')
this._shadowRoot.querySelector('#image_opt_embed').style.color = '#666'
}
}
break
case 'common-ok':
this.$saveBtn.textContent = newValue
break
case 'common-cancel':
this.$cancelBtn.textContent = newValue
break
case 'config-image_props':
node = this._shadowRoot.querySelector('#svginfo_image_props')
node.textContent = newValue
break
case 'config-doc_title':
node = this._shadowRoot.querySelector('#svginfo_title')
node.textContent = newValue
break
case 'config-doc_dims':
node = this._shadowRoot.querySelector('#svginfo_dim')
node.textContent = newValue
break
case 'common-width':
node = this._shadowRoot.querySelector('#svginfo_width')
node.textContent = newValue
break
case 'common-height':
node = this._shadowRoot.querySelector('#svginfo_height')
node.textContent = newValue
break
case 'config-select_predefined':
node = this._shadowRoot.querySelector('#selectedPredefined')
node.textContent = newValue
break
case 'tools-fit-to-content':
node = this._shadowRoot.querySelector('#fitToContent')
node.textContent = newValue
break
case 'config-included_images':
node = this._shadowRoot.querySelector('#includedImages')
node.textContent = newValue
break
case 'config-image_opt_embed':
node = this._shadowRoot.querySelector('#image_opt_embed')
node.textContent = newValue
break
case 'config-image_opt_ref':
node = this._shadowRoot.querySelector('#image_opt_ref')
node.textContent = newValue
break
default:
super.attributeChangedCallback(name, oldValue, newValue)
break
}
}
/**
* @function get
* @returns {any}
*/
get title () {
return this.getAttribute('title');
return this.getAttribute('title')
}
/**
@ -184,78 +186,89 @@ export class SeImgPropDialog extends HTMLElement {
* @returns {void}
*/
set title (value) {
this.setAttribute('title', value);
this.setAttribute('title', value)
}
/**
* @function get
* @returns {any}
*/
get width () {
return this.getAttribute('width');
return this.getAttribute('width')
}
/**
* @function set
* @returns {void}
*/
set width (value) {
this.setAttribute('width', value);
this.setAttribute('width', value)
}
/**
* @function get
* @returns {any}
*/
get height () {
return this.getAttribute('height');
return this.getAttribute('height')
}
/**
* @function set
* @returns {void}
*/
set height (value) {
this.setAttribute('height', value);
this.setAttribute('height', value)
}
/**
* @function get
* @returns {any}
*/
get save () {
return this.getAttribute('save');
return this.getAttribute('save')
}
/**
* @function set
* @returns {void}
*/
set save (value) {
this.setAttribute('save', value);
this.setAttribute('save', value)
}
/**
* @function get
* @returns {any}
*/
get dialog () {
return this.getAttribute('dialog');
return this.getAttribute('dialog')
}
/**
* @function set
* @returns {void}
*/
set dialog (value) {
this.setAttribute('dialog', value);
this.setAttribute('dialog', value)
}
/**
* @function get
* @returns {any}
*/
get embed () {
return this.getAttribute('embed');
return this.getAttribute('embed')
}
/**
* @function set
* @returns {void}
*/
set embed (value) {
this.setAttribute('embed', value);
this.setAttribute('embed', value)
}
/**
* @function connectedCallback
* @returns {void}
@ -264,72 +277,76 @@ export class SeImgPropDialog extends HTMLElement {
const onChangeHandler = (ev) => {
if (!ev.target.selectedIndex) {
if (this.$canvasWidth.getAttribute('value') === 'fit') {
this.$canvasWidth.removeAttribute('disabled');
this.$canvasWidth.value = 100;
this.$canvasHeight.removeAttribute('disabled');
this.$canvasHeight.value = 100;
this.$canvasWidth.removeAttribute('disabled')
this.$canvasWidth.value = 100
this.$canvasHeight.removeAttribute('disabled')
this.$canvasHeight.value = 100
}
} else if (ev.target.value === 'content') {
this.$canvasWidth.setAttribute('disabled', 'disabled');
this.$canvasWidth.value = 'fit';
this.$canvasHeight.setAttribute('disabled', 'disabled');
this.$canvasHeight.value = 'fit';
this.$canvasWidth.setAttribute('disabled', 'disabled')
this.$canvasWidth.value = 'fit'
this.$canvasHeight.setAttribute('disabled', 'disabled')
this.$canvasHeight.value = 'fit'
} else {
const dims = ev.target.value.split('x');
this.$canvasWidth.value = dims[0];
this.$canvasWidth.removeAttribute('disabled');
this.$canvasHeight.value = dims[1];
this.$canvasHeight.removeAttribute('disabled');
const dims = ev.target.value.split('x')
this.$canvasWidth.value = dims[0]
this.$canvasWidth.removeAttribute('disabled')
this.$canvasHeight.value = dims[1]
this.$canvasHeight.removeAttribute('disabled')
}
};
}
const onSaveHandler = () => {
let saveOpt = '';
const w = this.$canvasWidth.value;
const h = this.$canvasHeight.value;
let saveOpt = ''
const w = this.$canvasWidth.value
const h = this.$canvasHeight.value
if (w !== 'fit' && !isValidUnit('width', w)) {
this.$canvasWidth.parentElement.classList.add('error');
this.$canvasWidth.parentElement.classList.add('error')
} else {
this.$canvasWidth.parentElement.classList.remove('error');
this.$canvasWidth.parentElement.classList.remove('error')
}
if (h !== 'fit' && !isValidUnit('height', w)) {
this.$canvasHeight.parentElement.classList.add('error');
this.$canvasHeight.parentElement.classList.add('error')
} else {
this.$canvasHeight.parentElement.classList.remove('error');
this.$canvasHeight.parentElement.classList.remove('error')
}
if (this.$imageOptEmbed.getAttribute('checked') === 'true') {
saveOpt = 'embed';
saveOpt = 'embed'
}
if (this.$imageOptRef.getAttribute('checked') === 'true') {
saveOpt = 'ref';
saveOpt = 'ref'
}
const closeEvent = new CustomEvent('change', { detail: {
title: this.$canvasTitle.value,
w: this.$canvasWidth.value,
h: this.$canvasHeight.value,
save: saveOpt,
dialog: 'close'
} });
this.$canvasWidth.removeAttribute('disabled');
this.$canvasHeight.removeAttribute('disabled');
this.$resolution.selectedIndex = 0;
this.dispatchEvent(closeEvent);
};
const closeEvent = new CustomEvent('change', {
detail: {
title: this.$canvasTitle.value,
w: this.$canvasWidth.value,
h: this.$canvasHeight.value,
save: saveOpt,
dialog: 'close'
}
})
this.$canvasWidth.removeAttribute('disabled')
this.$canvasHeight.removeAttribute('disabled')
this.$resolution.selectedIndex = 0
this.dispatchEvent(closeEvent)
}
const onCancelHandler = () => {
const closeEvent = new CustomEvent('change', { detail: {
dialog: 'closed'
} });
this.$canvasWidth.removeAttribute('disabled');
this.$canvasHeight.removeAttribute('disabled');
this.$resolution.selectedIndex = 0;
this.dispatchEvent(closeEvent);
};
this.$resolution.addEventListener('change', onChangeHandler);
this.$saveBtn.addEventListener('click', onSaveHandler);
this.$cancelBtn.addEventListener('click', onCancelHandler);
this.$dialog.addEventListener('close', onCancelHandler);
this.eventlisten = true;
const closeEvent = new CustomEvent('change', {
detail: {
dialog: 'closed'
}
})
this.$canvasWidth.removeAttribute('disabled')
this.$canvasHeight.removeAttribute('disabled')
this.$resolution.selectedIndex = 0
this.dispatchEvent(closeEvent)
}
this.$resolution.addEventListener('change', onChangeHandler)
this.$saveBtn.addEventListener('click', onSaveHandler)
this.$cancelBtn.addEventListener('click', onCancelHandler)
this.$dialog.addEventListener('close', onCancelHandler)
this.eventlisten = true
}
}
// Register
customElements.define('se-img-prop-dialog', SeImgPropDialog);
customElements.define('se-img-prop-dialog', SeImgPropDialog)

View File

@ -1,11 +1,11 @@
import 'elix/define/Dialog.js';
import './imagePropertiesDialog.js';
import './editorPreferencesDialog.js';
import './svgSourceDialog.js';
import './cmenuDialog.js';
import './cmenuLayersDialog.js';
import './seSelectDialog.js';
import './seConfirmDialog.js';
import './sePromptDialog.js';
import './seAlertDialog.js';
import './exportDialog.js';
import 'elix/define/Dialog.js'
import './imagePropertiesDialog.js'
import './editorPreferencesDialog.js'
import './svgSourceDialog.js'
import './cmenuDialog.js'
import './cmenuLayersDialog.js'
import './seSelectDialog.js'
import './seConfirmDialog.js'
import './sePromptDialog.js'
import './seAlertDialog.js'
import './exportDialog.js'

View File

@ -1,8 +1,7 @@
import PlainNumberSpinBox from '../src/plain/PlainNumberSpinBox.js';
import PlainNumberSpinBox from '../src/plain/PlainNumberSpinBox.js'
/**
* @class ElixNumberSpinBox
*/
export default class ElixNumberSpinBox extends PlainNumberSpinBox {}
customElements.define('elix-number-spin-box', ElixNumberSpinBox);
customElements.define('elix-number-spin-box', ElixNumberSpinBox)

View File

@ -3,10 +3,10 @@ import {
setState,
state,
stateEffects
} from 'elix/src/base/internal.js';
} from 'elix/src/base/internal.js'
import {
SpinBox
} from 'elix/src/base/SpinBox.js';
} from 'elix/src/base/SpinBox.js'
/**
* @class NumberSpinBox
@ -21,15 +21,16 @@ class NumberSpinBox extends SpinBox {
*/
attributeChangedCallback (name, oldValue, newValue) {
if (name === 'max') {
this.max = parseFloat(newValue);
this.max = parseFloat(newValue)
} else if (name === 'min') {
this.min = parseFloat(newValue);
this.min = parseFloat(newValue)
} else if (name === 'step') {
this.step = parseFloat(newValue);
this.step = parseFloat(newValue)
} else {
super.attributeChangedCallback(name, oldValue, newValue);
super.attributeChangedCallback(name, oldValue, newValue)
}
}
/**
* @function observedAttributes
* @returns {any} observed
@ -39,7 +40,7 @@ class NumberSpinBox extends SpinBox {
max: null,
min: null,
step: 1
});
})
}
/**
@ -54,7 +55,7 @@ class NumberSpinBox extends SpinBox {
* @returns {number}
*/
formatValue (value, precision) {
return Number(value).toFixed(precision);
return Number(value).toFixed(precision)
}
/**
@ -64,8 +65,9 @@ class NumberSpinBox extends SpinBox {
* @default 1
*/
get max () {
return this[state].max;
return this[state].max
}
/**
* The maximum allowable value of the `value` property.
*
@ -75,7 +77,7 @@ class NumberSpinBox extends SpinBox {
set max (max) {
this[setState]({
max
});
})
}
/**
@ -85,8 +87,9 @@ class NumberSpinBox extends SpinBox {
* @default 1
*/
get min () {
return this[state].min;
return this[state].min
}
/**
* @function set
* @returns {void}
@ -94,7 +97,7 @@ class NumberSpinBox extends SpinBox {
set min (min) {
this[setState]({
min
});
})
}
/**
@ -104,9 +107,10 @@ class NumberSpinBox extends SpinBox {
* @returns {int}
*/
parseValue (value, precision) {
const parsed = precision === 0 ? parseInt(value) : parseFloat(value);
return isNaN(parsed) ? 0 : parsed;
const parsed = precision === 0 ? parseInt(value) : parseFloat(value)
return isNaN(parsed) ? 0 : parsed
}
/**
* @function stateEffects
* @param {any} state
@ -114,19 +118,19 @@ class NumberSpinBox extends SpinBox {
* @returns {any}
*/
[stateEffects] (state, changed) {
const effects = super[stateEffects];
const effects = super[stateEffects]
// If step changed, calculate its precision (number of digits after
// the decimal).
if (changed.step) {
const {
step
} = state;
const decimalRegex = /\.(\d)+$/;
const match = decimalRegex.exec(String(step));
const precision = match && match[1] ? match[1].length : 0;
} = state
const decimalRegex = /\.(\d)+$/
const match = decimalRegex.exec(String(step))
const precision = match && match[1] ? match[1].length : 0
Object.assign(effects, {
precision
});
})
}
if (changed.max || changed.min || changed.value) {
@ -140,41 +144,41 @@ class NumberSpinBox extends SpinBox {
min,
precision,
value
} = state;
const parsed = parseInt(value, precision);
} = state
const parsed = parseInt(value, precision)
if (value !== '' && isNaN(parsed)) {
Object.assign(effects, {
valid: false,
validationMessage: 'Value must be a number'
});
})
} else if (!(max === null || parsed <= max)) {
Object.assign(effects, {
valid: false,
validationMessage: `Value must be less than or equal to ${max}.`
});
})
} else if (!(min === null || parsed >= min)) {
Object.assign(effects, {
valid: false,
validationMessage: `Value must be greater than or equal to ${min}.`
});
})
} else {
Object.assign(effects, {
valid: true,
validationMessage: ''
});
})
}
// We can only go up if we're below max.
Object.assign(effects, {
canGoUp: isNaN(parsed) || state.max === null || parsed <= state.max
});
})
// We can only go down if we're above min.
Object.assign(effects, {
canGoDown: isNaN(parsed) || state.min === null || parsed >= state.min
});
})
}
return effects;
return effects
}
/**
@ -182,8 +186,9 @@ class NumberSpinBox extends SpinBox {
* @returns {any}
*/
get step () {
return this[state].step;
return this[state].step
}
/**
* @function set
* @returns {void}
@ -192,7 +197,7 @@ class NumberSpinBox extends SpinBox {
if (!isNaN(step)) {
this[setState]({
step
});
})
}
}
@ -201,21 +206,21 @@ class NumberSpinBox extends SpinBox {
* @returns {void}
*/
stepDown () {
super.stepDown();
super.stepDown()
const {
max,
precision,
value
} = this[state];
let result = this.parseValue(value, precision) - this.step;
} = this[state]
let result = this.parseValue(value, precision) - this.step
if (max !== null) {
result = Math.min(result, max);
result = Math.min(result, max)
}
const {
min
} = this[state];
} = this[state]
if (min === null || result >= min) {
this.value = this.formatValue(result, precision);
this.value = this.formatValue(result, precision)
}
}
@ -224,23 +229,23 @@ class NumberSpinBox extends SpinBox {
* @returns {void}
*/
stepUp () {
super.stepUp();
super.stepUp()
const {
min,
precision,
value
} = this[state];
let result = this.parseValue(value, precision) + this.step;
} = this[state]
let result = this.parseValue(value, precision) + this.step
if (min !== null) {
result = Math.max(result, min);
result = Math.max(result, min)
}
const {
max
} = this[state];
} = this[state]
if (max === null || result <= max) {
this.value = this.formatValue(result, precision);
this.value = this.formatValue(result, precision)
}
}
}
export default NumberSpinBox;
export default NumberSpinBox

View File

@ -1,9 +1,9 @@
import PlainSpinBoxMixin from 'elix/src/plain/PlainSpinBoxMixin.js';
import NumberSpinBox from '../base/NumberSpinBox.js';
import PlainSpinBoxMixin from 'elix/src/plain/PlainSpinBoxMixin.js'
import NumberSpinBox from '../base/NumberSpinBox.js'
/**
* @class PlainNumberSpinBox
*/
class PlainNumberSpinBox extends PlainSpinBoxMixin(NumberSpinBox) {}
export default PlainNumberSpinBox;
export default PlainNumberSpinBox

Some files were not shown because too many files have changed in this diff Show More