move to standard linter for simpler configuration
This commit is contained in:
@@ -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_
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 = {} }
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import SePlainAlertDialog from './SePlainAlertDialog.js';
|
||||
import SePlainAlertDialog from './SePlainAlertDialog.js'
|
||||
|
||||
const seAlert = (text) => {
|
||||
const dialog = new SePlainAlertDialog();
|
||||
dialog.textContent = text;
|
||||
dialog.choices = [ 'Ok' ];
|
||||
dialog.open();
|
||||
};
|
||||
const dialog = new SePlainAlertDialog()
|
||||
dialog.textContent = text
|
||||
dialog.choices = ['Ok']
|
||||
dialog.open()
|
||||
}
|
||||
|
||||
window.seAlert = seAlert;
|
||||
window.seAlert = seAlert
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import SePlainAlertDialog from './SePlainAlertDialog.js';
|
||||
import SePlainAlertDialog from './SePlainAlertDialog.js'
|
||||
|
||||
const seConfirm = async (text, choices) => {
|
||||
const dialog = new SePlainAlertDialog();
|
||||
dialog.textContent = text;
|
||||
dialog.choices = (choices === undefined) ? [ 'Ok', 'Cancel' ] : choices;
|
||||
dialog.open();
|
||||
const response = await dialog.whenClosed();
|
||||
return response.choice;
|
||||
};
|
||||
const dialog = new SePlainAlertDialog()
|
||||
dialog.textContent = text
|
||||
dialog.choices = (choices === undefined) ? ['Ok', 'Cancel'] : choices
|
||||
dialog.open()
|
||||
const response = await dialog.whenClosed()
|
||||
return response.choice
|
||||
}
|
||||
|
||||
window.seConfirm = seConfirm;
|
||||
window.seConfirm = seConfirm
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import SePlainAlertDialog from './SePlainAlertDialog.js';
|
||||
import SePlainAlertDialog from './SePlainAlertDialog.js'
|
||||
/**
|
||||
* @class SePromptDialog
|
||||
*/
|
||||
@@ -7,18 +7,20 @@ export class SePromptDialog extends HTMLElement {
|
||||
* @function constructor
|
||||
*/
|
||||
constructor () {
|
||||
super();
|
||||
super()
|
||||
// create the shadowDom and insert the template
|
||||
this._shadowRoot = this.attachShadow({ mode: 'open' });
|
||||
this.dialog = new SePlainAlertDialog();
|
||||
this._shadowRoot = this.attachShadow({ mode: 'open' })
|
||||
this.dialog = new SePlainAlertDialog()
|
||||
}
|
||||
|
||||
/**
|
||||
* @function observedAttributes
|
||||
* @returns {any} observed
|
||||
*/
|
||||
static get observedAttributes () {
|
||||
return [ 'title', 'close' ];
|
||||
return ['title', 'close']
|
||||
}
|
||||
|
||||
/**
|
||||
* @function attributeChangedCallback
|
||||
* @param {string} name
|
||||
@@ -28,32 +30,33 @@ export class SePromptDialog extends HTMLElement {
|
||||
*/
|
||||
attributeChangedCallback (name, oldValue, newValue) {
|
||||
switch (name) {
|
||||
case 'title':
|
||||
if (this.dialog.opened) {
|
||||
this.dialog.close();
|
||||
}
|
||||
this.dialog.textContent = newValue;
|
||||
this.dialog.choices = [ 'Cancel' ];
|
||||
this.dialog.open();
|
||||
break;
|
||||
case 'close':
|
||||
if (this.dialog.opened) {
|
||||
this.dialog.close();
|
||||
} else {
|
||||
this.dialog.open();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.error('unknown attr for:', name, 'newValue =', newValue);
|
||||
break;
|
||||
case 'title':
|
||||
if (this.dialog.opened) {
|
||||
this.dialog.close()
|
||||
}
|
||||
this.dialog.textContent = newValue
|
||||
this.dialog.choices = ['Cancel']
|
||||
this.dialog.open()
|
||||
break
|
||||
case 'close':
|
||||
if (this.dialog.opened) {
|
||||
this.dialog.close()
|
||||
} else {
|
||||
this.dialog.open()
|
||||
}
|
||||
break
|
||||
default:
|
||||
console.error('unknown attr for:', name, 'newValue =', newValue)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @function get
|
||||
* @returns {any}
|
||||
*/
|
||||
get title () {
|
||||
return this.getAttribute('title');
|
||||
return this.getAttribute('title')
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,14 +64,15 @@ export class SePromptDialog extends HTMLElement {
|
||||
* @returns {void}
|
||||
*/
|
||||
set title (value) {
|
||||
this.setAttribute('title', value);
|
||||
this.setAttribute('title', value)
|
||||
}
|
||||
|
||||
/**
|
||||
* @function get
|
||||
* @returns {any}
|
||||
*/
|
||||
get close () {
|
||||
return this.getAttribute('close');
|
||||
return this.getAttribute('close')
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,12 +82,12 @@ export class SePromptDialog extends HTMLElement {
|
||||
set close (value) {
|
||||
// boolean value => existence = true
|
||||
if (value) {
|
||||
this.setAttribute('close', 'true');
|
||||
this.setAttribute('close', 'true')
|
||||
} else {
|
||||
this.removeAttribute('close');
|
||||
this.removeAttribute('close')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Register
|
||||
customElements.define('se-prompt-dialog', SePromptDialog);
|
||||
customElements.define('se-prompt-dialog', SePromptDialog)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import SePlainAlertDialog from './SePlainAlertDialog.js';
|
||||
import SePlainAlertDialog from './SePlainAlertDialog.js'
|
||||
|
||||
const seSelect = async (text, choices) => {
|
||||
const dialog = new SePlainAlertDialog();
|
||||
dialog.textContent = text;
|
||||
dialog.choices = choices;
|
||||
dialog.open();
|
||||
const response = await dialog.whenClosed();
|
||||
return response.choice;
|
||||
};
|
||||
const dialog = new SePlainAlertDialog()
|
||||
dialog.textContent = text
|
||||
dialog.choices = choices
|
||||
dialog.open()
|
||||
const response = await dialog.whenClosed()
|
||||
return response.choice
|
||||
}
|
||||
|
||||
window.seSelect = seSelect;
|
||||
window.seSelect = seSelect
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import svgSourceDialogHTML from './svgSourceDialog.html';
|
||||
import svgSourceDialogHTML from './svgSourceDialog.html'
|
||||
|
||||
const template = document.createElement('template');
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
template.innerHTML = svgSourceDialogHTML;
|
||||
const template = document.createElement('template')
|
||||
template.innerHTML = svgSourceDialogHTML
|
||||
/**
|
||||
* @class SeSvgSourceEditorDialog
|
||||
*/
|
||||
@@ -11,36 +10,39 @@ export class SeSvgSourceEditorDialog 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('#svg_source_editor');
|
||||
this.$copyBtn = this._shadowRoot.querySelector('#copy_save_done');
|
||||
this.$saveBtn = this._shadowRoot.querySelector('#tool_source_save');
|
||||
this.$cancelBtn = this._shadowRoot.querySelector('#tool_source_cancel');
|
||||
this.$sourceTxt = this._shadowRoot.querySelector('#svg_source_textarea');
|
||||
this.$copySec = this._shadowRoot.querySelector('#save_output_btns');
|
||||
this.$applySec = this._shadowRoot.querySelector('#tool_source_back');
|
||||
this._shadowRoot = this.attachShadow({ mode: 'open' })
|
||||
this._shadowRoot.append(template.content.cloneNode(true))
|
||||
this.$dialog = this._shadowRoot.querySelector('#svg_source_editor')
|
||||
this.$copyBtn = this._shadowRoot.querySelector('#copy_save_done')
|
||||
this.$saveBtn = this._shadowRoot.querySelector('#tool_source_save')
|
||||
this.$cancelBtn = this._shadowRoot.querySelector('#tool_source_cancel')
|
||||
this.$sourceTxt = this._shadowRoot.querySelector('#svg_source_textarea')
|
||||
this.$copySec = this._shadowRoot.querySelector('#save_output_btns')
|
||||
this.$applySec = this._shadowRoot.querySelector('#tool_source_back')
|
||||
}
|
||||
|
||||
/**
|
||||
* @function init
|
||||
* @param {any} name
|
||||
* @returns {void}
|
||||
*/
|
||||
init (i18next) {
|
||||
this.setAttribute('tools-source_save', i18next.t('tools.source_save'));
|
||||
this.setAttribute('common-cancel', i18next.t('common.cancel'));
|
||||
this.setAttribute('notification-source_dialog_note', i18next.t('notification.source_dialog_note'));
|
||||
this.setAttribute('config-done', i18next.t('config.done'));
|
||||
this.setAttribute('tools-source_save', i18next.t('tools.source_save'))
|
||||
this.setAttribute('common-cancel', i18next.t('common.cancel'))
|
||||
this.setAttribute('notification-source_dialog_note', i18next.t('notification.source_dialog_note'))
|
||||
this.setAttribute('config-done', i18next.t('config.done'))
|
||||
}
|
||||
|
||||
/**
|
||||
* @function observedAttributes
|
||||
* @returns {any} observed
|
||||
*/
|
||||
static get observedAttributes () {
|
||||
return [ 'dialog', 'value', 'applysec', 'copysec', 'tools-source_save', 'common-cancel', 'notification-source_dialog_note', 'config-done' ];
|
||||
return ['dialog', 'value', 'applysec', 'copysec', 'tools-source_save', 'common-cancel', 'notification-source_dialog_note', 'config-done']
|
||||
}
|
||||
|
||||
/**
|
||||
* @function attributeChangedCallback
|
||||
* @param {string} name
|
||||
@@ -49,51 +51,51 @@ export class SeSvgSourceEditorDialog extends HTMLElement {
|
||||
* @returns {void}
|
||||
*/
|
||||
attributeChangedCallback (name, oldValue, newValue) {
|
||||
if (oldValue === newValue) return;
|
||||
let node;
|
||||
if (oldValue === newValue) return
|
||||
let node
|
||||
switch (name) {
|
||||
case 'dialog':
|
||||
if (newValue === 'open') {
|
||||
this.$sourceTxt.focus();
|
||||
this.$dialog.open();
|
||||
} else {
|
||||
this.$dialog.close();
|
||||
this.$sourceTxt.blur();
|
||||
}
|
||||
break;
|
||||
case 'applysec':
|
||||
if (newValue === 'false') {
|
||||
this.$applySec.style.display = 'none';
|
||||
} else {
|
||||
this.$applySec.style.display = 'block';
|
||||
}
|
||||
break;
|
||||
case 'copysec':
|
||||
if (newValue === 'false') {
|
||||
this.$copySec.style.display = 'none';
|
||||
} else {
|
||||
this.$copySec.style.display = 'block';
|
||||
}
|
||||
break;
|
||||
case 'value':
|
||||
this.$sourceTxt.value = newValue;
|
||||
break;
|
||||
case 'tools-source_save':
|
||||
this.$saveBtn.textContent = newValue;
|
||||
break;
|
||||
case 'common-cancel':
|
||||
this.$cancelBtn.textContent = newValue;
|
||||
break;
|
||||
case 'notification-source_dialog_note':
|
||||
node = this._shadowRoot.querySelector('#copy_save_note');
|
||||
node.textContent = newValue;
|
||||
break;
|
||||
case 'config-done':
|
||||
this.$copyBtn.textContent = newValue;
|
||||
break;
|
||||
default:
|
||||
super.attributeChangedCallback(name, oldValue, newValue);
|
||||
break;
|
||||
case 'dialog':
|
||||
if (newValue === 'open') {
|
||||
this.$sourceTxt.focus()
|
||||
this.$dialog.open()
|
||||
} else {
|
||||
this.$dialog.close()
|
||||
this.$sourceTxt.blur()
|
||||
}
|
||||
break
|
||||
case 'applysec':
|
||||
if (newValue === 'false') {
|
||||
this.$applySec.style.display = 'none'
|
||||
} else {
|
||||
this.$applySec.style.display = 'block'
|
||||
}
|
||||
break
|
||||
case 'copysec':
|
||||
if (newValue === 'false') {
|
||||
this.$copySec.style.display = 'none'
|
||||
} else {
|
||||
this.$copySec.style.display = 'block'
|
||||
}
|
||||
break
|
||||
case 'value':
|
||||
this.$sourceTxt.value = newValue
|
||||
break
|
||||
case 'tools-source_save':
|
||||
this.$saveBtn.textContent = newValue
|
||||
break
|
||||
case 'common-cancel':
|
||||
this.$cancelBtn.textContent = newValue
|
||||
break
|
||||
case 'notification-source_dialog_note':
|
||||
node = this._shadowRoot.querySelector('#copy_save_note')
|
||||
node.textContent = newValue
|
||||
break
|
||||
case 'config-done':
|
||||
this.$copyBtn.textContent = newValue
|
||||
break
|
||||
default:
|
||||
super.attributeChangedCallback(name, oldValue, newValue)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,14 +104,15 @@ export class SeSvgSourceEditorDialog extends HTMLElement {
|
||||
* @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)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,14 +120,15 @@ export class SeSvgSourceEditorDialog extends HTMLElement {
|
||||
* @returns {any}
|
||||
*/
|
||||
get value () {
|
||||
return this.getAttribute('value');
|
||||
return this.getAttribute('value')
|
||||
}
|
||||
|
||||
/**
|
||||
* @function set
|
||||
* @returns {void}
|
||||
*/
|
||||
set value (value) {
|
||||
this.setAttribute('value', value);
|
||||
this.setAttribute('value', value)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,14 +136,15 @@ export class SeSvgSourceEditorDialog extends HTMLElement {
|
||||
* @returns {any}
|
||||
*/
|
||||
get applysec () {
|
||||
return this.getAttribute('applysec');
|
||||
return this.getAttribute('applysec')
|
||||
}
|
||||
|
||||
/**
|
||||
* @function set
|
||||
* @returns {void}
|
||||
*/
|
||||
set applysec (value) {
|
||||
this.setAttribute('applysec', value);
|
||||
this.setAttribute('applysec', value)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -147,48 +152,54 @@ export class SeSvgSourceEditorDialog extends HTMLElement {
|
||||
* @returns {any}
|
||||
*/
|
||||
get copysec () {
|
||||
return this.getAttribute('copysec');
|
||||
return this.getAttribute('copysec')
|
||||
}
|
||||
|
||||
/**
|
||||
* @function set
|
||||
* @returns {void}
|
||||
*/
|
||||
set copysec (value) {
|
||||
this.setAttribute('copysec', value);
|
||||
this.setAttribute('copysec', 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 onCopyHandler = () => {
|
||||
const closeEvent = new CustomEvent('change', {
|
||||
detail: {
|
||||
copy: 'click',
|
||||
value: this.$sourceTxt.value
|
||||
}
|
||||
});
|
||||
this.dispatchEvent(closeEvent);
|
||||
};
|
||||
})
|
||||
this.dispatchEvent(closeEvent)
|
||||
}
|
||||
const onSaveHandler = () => {
|
||||
const closeEvent = new CustomEvent('change', { detail: {
|
||||
value: this.$sourceTxt.value,
|
||||
dialog: 'close'
|
||||
} });
|
||||
this.dispatchEvent(closeEvent);
|
||||
};
|
||||
this.$copyBtn.addEventListener('click', onCopyHandler);
|
||||
this.$saveBtn.addEventListener('click', onSaveHandler);
|
||||
this.$cancelBtn.addEventListener('click', onCancelHandler);
|
||||
this.$dialog.addEventListener('close', onCancelHandler);
|
||||
const closeEvent = new CustomEvent('change', {
|
||||
detail: {
|
||||
value: this.$sourceTxt.value,
|
||||
dialog: 'close'
|
||||
}
|
||||
})
|
||||
this.dispatchEvent(closeEvent)
|
||||
}
|
||||
this.$copyBtn.addEventListener('click', onCopyHandler)
|
||||
this.$saveBtn.addEventListener('click', onSaveHandler)
|
||||
this.$cancelBtn.addEventListener('click', onCancelHandler)
|
||||
this.$dialog.addEventListener('close', onCancelHandler)
|
||||
}
|
||||
}
|
||||
|
||||
// Register
|
||||
customElements.define('se-svg-source-editor-dialog', SeSvgSourceEditorDialog);
|
||||
customElements.define('se-svg-source-editor-dialog', SeSvgSourceEditorDialog)
|
||||
|
||||
@@ -8,39 +8,41 @@
|
||||
*
|
||||
*/
|
||||
|
||||
const name = "eyedropper";
|
||||
const name = 'eyedropper'
|
||||
|
||||
const loadExtensionTranslation = async function (svgEditor) {
|
||||
let translationModule;
|
||||
const lang = svgEditor.configObj.pref('lang');
|
||||
let translationModule
|
||||
const lang = svgEditor.configObj.pref('lang')
|
||||
try {
|
||||
// eslint-disable-next-line no-unsanitized/method
|
||||
translationModule = await import(`./locale/${lang}.js`);
|
||||
translationModule = await import(`./locale/${lang}.js`)
|
||||
} catch (_error) {
|
||||
console.warn(`Missing translation (${lang}) for ${name} - using 'en'`);
|
||||
translationModule = await import(`./locale/en.js`);
|
||||
console.warn(`Missing translation (${lang}) for ${name} - using 'en'`)
|
||||
translationModule = await import('./locale/en.js')
|
||||
}
|
||||
svgEditor.i18next.addResourceBundle(lang, name, translationModule.default);
|
||||
};
|
||||
svgEditor.i18next.addResourceBundle(lang, name, translationModule.default)
|
||||
}
|
||||
|
||||
export default {
|
||||
name,
|
||||
async init() {
|
||||
const svgEditor = this;
|
||||
const { svgCanvas } = svgEditor;
|
||||
await loadExtensionTranslation(svgEditor);
|
||||
const { ChangeElementCommand } = svgCanvas.history;
|
||||
async init () {
|
||||
const svgEditor = this
|
||||
const { svgCanvas } = svgEditor
|
||||
await loadExtensionTranslation(svgEditor)
|
||||
const { ChangeElementCommand } = svgCanvas.history
|
||||
// svgdoc = S.svgroot.parentNode.ownerDocument,
|
||||
const addToHistory = function (cmd) { svgCanvas.undoMgr.addCommandToHistory(cmd); };
|
||||
const addToHistory = function (cmd) { svgCanvas.undoMgr.addCommandToHistory(cmd) }
|
||||
const currentStyle = {
|
||||
fillPaint: 'red', fillOpacity: 1.0,
|
||||
strokePaint: 'black', strokeOpacity: 1.0,
|
||||
strokeWidth: 5, strokeDashArray: null,
|
||||
fillPaint: 'red',
|
||||
fillOpacity: 1.0,
|
||||
strokePaint: 'black',
|
||||
strokeOpacity: 1.0,
|
||||
strokeWidth: 5,
|
||||
strokeDashArray: null,
|
||||
opacity: 1.0,
|
||||
strokeLinecap: 'butt',
|
||||
strokeLinejoin: 'miter'
|
||||
};
|
||||
const { $id } = svgCanvas;
|
||||
}
|
||||
const { $id } = svgCanvas
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -49,79 +51,79 @@ export default {
|
||||
*/
|
||||
const getStyle = (opts) => {
|
||||
// if we are in eyedropper mode, we don't want to disable the eye-dropper tool
|
||||
const mode = svgCanvas.getMode();
|
||||
if (mode === 'eyedropper') { return; }
|
||||
const mode = svgCanvas.getMode()
|
||||
if (mode === 'eyedropper') { return }
|
||||
|
||||
const tool = $id('tool_eyedropper');
|
||||
const tool = $id('tool_eyedropper')
|
||||
// enable-eye-dropper if one element is selected
|
||||
let elem = null;
|
||||
let elem = null
|
||||
if (!opts.multiselected && opts.elems[0] &&
|
||||
![ 'svg', 'g', 'use' ].includes(opts.elems[0].nodeName)
|
||||
!['svg', 'g', 'use'].includes(opts.elems[0].nodeName)
|
||||
) {
|
||||
elem = opts.elems[0];
|
||||
tool.classList.remove('disabled');
|
||||
elem = opts.elems[0]
|
||||
tool.classList.remove('disabled')
|
||||
// grab the current style
|
||||
currentStyle.fillPaint = elem.getAttribute('fill') || 'black';
|
||||
currentStyle.fillOpacity = elem.getAttribute('fill-opacity') || 1.0;
|
||||
currentStyle.strokePaint = elem.getAttribute('stroke');
|
||||
currentStyle.strokeOpacity = elem.getAttribute('stroke-opacity') || 1.0;
|
||||
currentStyle.strokeWidth = elem.getAttribute('stroke-width');
|
||||
currentStyle.strokeDashArray = elem.getAttribute('stroke-dasharray');
|
||||
currentStyle.strokeLinecap = elem.getAttribute('stroke-linecap');
|
||||
currentStyle.strokeLinejoin = elem.getAttribute('stroke-linejoin');
|
||||
currentStyle.opacity = elem.getAttribute('opacity') || 1.0;
|
||||
currentStyle.fillPaint = elem.getAttribute('fill') || 'black'
|
||||
currentStyle.fillOpacity = elem.getAttribute('fill-opacity') || 1.0
|
||||
currentStyle.strokePaint = elem.getAttribute('stroke')
|
||||
currentStyle.strokeOpacity = elem.getAttribute('stroke-opacity') || 1.0
|
||||
currentStyle.strokeWidth = elem.getAttribute('stroke-width')
|
||||
currentStyle.strokeDashArray = elem.getAttribute('stroke-dasharray')
|
||||
currentStyle.strokeLinecap = elem.getAttribute('stroke-linecap')
|
||||
currentStyle.strokeLinejoin = elem.getAttribute('stroke-linejoin')
|
||||
currentStyle.opacity = elem.getAttribute('opacity') || 1.0
|
||||
// disable eye-dropper tool
|
||||
} else {
|
||||
tool.classList.add('disabled');
|
||||
tool.classList.add('disabled')
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
name: svgEditor.i18next.t(`${name}:name`),
|
||||
callback() {
|
||||
callback () {
|
||||
// Add the button and its handler(s)
|
||||
const title = `${name}:buttons.0.title`;
|
||||
const key = `${name}:buttons.0.key`;
|
||||
const title = `${name}:buttons.0.title`
|
||||
const key = `${name}:buttons.0.key`
|
||||
const buttonTemplate = `
|
||||
<se-button id="tool_eyedropper" title="${title}" src="eye_dropper.svg" shortcut=${key}></se-button>
|
||||
`;
|
||||
svgCanvas.insertChildAtIndex($id('tools_left'), buttonTemplate, 12);
|
||||
$id('tool_eyedropper').addEventListener("click", () => {
|
||||
if (this.leftPanel.updateLeftPanel("tool_eyedropper")) {
|
||||
svgCanvas.setMode('eyedropper');
|
||||
`
|
||||
svgCanvas.insertChildAtIndex($id('tools_left'), buttonTemplate, 12)
|
||||
$id('tool_eyedropper').addEventListener('click', () => {
|
||||
if (this.leftPanel.updateLeftPanel('tool_eyedropper')) {
|
||||
svgCanvas.setMode('eyedropper')
|
||||
}
|
||||
});
|
||||
})
|
||||
},
|
||||
// if we have selected an element, grab its paint and enable the eye dropper button
|
||||
selectedChanged: getStyle,
|
||||
elementChanged: getStyle,
|
||||
mouseDown(opts) {
|
||||
const mode = svgCanvas.getMode();
|
||||
mouseDown (opts) {
|
||||
const mode = svgCanvas.getMode()
|
||||
if (mode === 'eyedropper') {
|
||||
const e = opts.event;
|
||||
const { target } = e;
|
||||
if (![ 'svg', 'g', 'use' ].includes(target.nodeName)) {
|
||||
const changes = {};
|
||||
const e = opts.event
|
||||
const { target } = e
|
||||
if (!['svg', 'g', 'use'].includes(target.nodeName)) {
|
||||
const changes = {}
|
||||
|
||||
const change = function (elem, attrname, newvalue) {
|
||||
changes[attrname] = elem.getAttribute(attrname);
|
||||
elem.setAttribute(attrname, newvalue);
|
||||
};
|
||||
changes[attrname] = elem.getAttribute(attrname)
|
||||
elem.setAttribute(attrname, newvalue)
|
||||
}
|
||||
|
||||
if (currentStyle.fillPaint) { change(target, 'fill', currentStyle.fillPaint); }
|
||||
if (currentStyle.fillOpacity) { change(target, 'fill-opacity', currentStyle.fillOpacity); }
|
||||
if (currentStyle.strokePaint) { change(target, 'stroke', currentStyle.strokePaint); }
|
||||
if (currentStyle.strokeOpacity) { change(target, 'stroke-opacity', currentStyle.strokeOpacity); }
|
||||
if (currentStyle.strokeWidth) { change(target, 'stroke-width', currentStyle.strokeWidth); }
|
||||
if (currentStyle.strokeDashArray) { change(target, 'stroke-dasharray', currentStyle.strokeDashArray); }
|
||||
if (currentStyle.opacity) { change(target, 'opacity', currentStyle.opacity); }
|
||||
if (currentStyle.strokeLinecap) { change(target, 'stroke-linecap', currentStyle.strokeLinecap); }
|
||||
if (currentStyle.strokeLinejoin) { change(target, 'stroke-linejoin', currentStyle.strokeLinejoin); }
|
||||
if (currentStyle.fillPaint) { change(target, 'fill', currentStyle.fillPaint) }
|
||||
if (currentStyle.fillOpacity) { change(target, 'fill-opacity', currentStyle.fillOpacity) }
|
||||
if (currentStyle.strokePaint) { change(target, 'stroke', currentStyle.strokePaint) }
|
||||
if (currentStyle.strokeOpacity) { change(target, 'stroke-opacity', currentStyle.strokeOpacity) }
|
||||
if (currentStyle.strokeWidth) { change(target, 'stroke-width', currentStyle.strokeWidth) }
|
||||
if (currentStyle.strokeDashArray) { change(target, 'stroke-dasharray', currentStyle.strokeDashArray) }
|
||||
if (currentStyle.opacity) { change(target, 'opacity', currentStyle.opacity) }
|
||||
if (currentStyle.strokeLinecap) { change(target, 'stroke-linecap', currentStyle.strokeLinecap) }
|
||||
if (currentStyle.strokeLinejoin) { change(target, 'stroke-linejoin', currentStyle.strokeLinejoin) }
|
||||
|
||||
addToHistory(new ChangeElementCommand(target, changes));
|
||||
addToHistory(new ChangeElementCommand(target, changes))
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,4 +6,4 @@ export default {
|
||||
key: 'I'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,4 +6,4 @@ export default {
|
||||
key: 'I'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,4 +6,4 @@ export default {
|
||||
key: 'I'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,40 +7,39 @@
|
||||
*
|
||||
*/
|
||||
|
||||
const name = "grid";
|
||||
const name = 'grid'
|
||||
|
||||
const loadExtensionTranslation = async function (svgEditor) {
|
||||
let translationModule;
|
||||
const lang = svgEditor.configObj.pref('lang');
|
||||
let translationModule
|
||||
const lang = svgEditor.configObj.pref('lang')
|
||||
try {
|
||||
// eslint-disable-next-line no-unsanitized/method
|
||||
translationModule = await import(`./locale/${lang}.js`);
|
||||
translationModule = await import(`./locale/${lang}.js`)
|
||||
} catch (_error) {
|
||||
console.warn(`Missing translation (${lang}) for ${name} - using 'en'`);
|
||||
translationModule = await import(`./locale/en.js`);
|
||||
console.warn(`Missing translation (${lang}) for ${name} - using 'en'`)
|
||||
translationModule = await import('./locale/en.js')
|
||||
}
|
||||
svgEditor.i18next.addResourceBundle(lang, name, translationModule.default);
|
||||
};
|
||||
svgEditor.i18next.addResourceBundle(lang, name, translationModule.default)
|
||||
}
|
||||
|
||||
export default {
|
||||
name,
|
||||
async init () {
|
||||
const svgEditor = this;
|
||||
await loadExtensionTranslation(svgEditor);
|
||||
const { svgCanvas } = svgEditor;
|
||||
const { $id, NS } = svgCanvas;
|
||||
const svgdoc = $id('svgcanvas').ownerDocument;
|
||||
const { assignAttributes } = svgCanvas;
|
||||
const hcanvas = document.createElement('canvas');
|
||||
const canvBG = $id('canvasBackground');
|
||||
const units = svgCanvas.getTypeMap(); // Assumes prior `init()` call on `units.js` module
|
||||
const intervals = [ 0.01, 0.1, 1, 10, 100, 1000 ];
|
||||
let showGrid = svgEditor.configObj.curConfig.showGrid || false;
|
||||
const svgEditor = this
|
||||
await loadExtensionTranslation(svgEditor)
|
||||
const { svgCanvas } = svgEditor
|
||||
const { $id, NS } = svgCanvas
|
||||
const svgdoc = $id('svgcanvas').ownerDocument
|
||||
const { assignAttributes } = svgCanvas
|
||||
const hcanvas = document.createElement('canvas')
|
||||
const canvBG = $id('canvasBackground')
|
||||
const units = svgCanvas.getTypeMap() // Assumes prior `init()` call on `units.js` module
|
||||
const intervals = [0.01, 0.1, 1, 10, 100, 1000]
|
||||
let showGrid = svgEditor.configObj.curConfig.showGrid || false
|
||||
|
||||
hcanvas.style.display = 'none';
|
||||
svgEditor.$svgEditor.appendChild(hcanvas);
|
||||
hcanvas.style.display = 'none'
|
||||
svgEditor.$svgEditor.appendChild(hcanvas)
|
||||
|
||||
const canvasGrid = svgdoc.createElementNS(NS.SVG, 'svg');
|
||||
const canvasGrid = svgdoc.createElementNS(NS.SVG, 'svg')
|
||||
assignAttributes(canvasGrid, {
|
||||
id: 'canvasGrid',
|
||||
width: '100%',
|
||||
@@ -49,11 +48,11 @@ export default {
|
||||
y: 0,
|
||||
overflow: 'visible',
|
||||
display: 'none'
|
||||
});
|
||||
canvBG.appendChild(canvasGrid);
|
||||
const gridDefs = svgdoc.createElementNS(NS.SVG, 'defs');
|
||||
})
|
||||
canvBG.appendChild(canvasGrid)
|
||||
const gridDefs = svgdoc.createElementNS(NS.SVG, 'defs')
|
||||
// grid-pattern
|
||||
const gridPattern = svgdoc.createElementNS(NS.SVG, 'pattern');
|
||||
const gridPattern = svgdoc.createElementNS(NS.SVG, 'pattern')
|
||||
assignAttributes(gridPattern, {
|
||||
id: 'gridpattern',
|
||||
patternUnits: 'userSpaceOnUse',
|
||||
@@ -61,21 +60,21 @@ export default {
|
||||
y: 0, // -(value.strokeWidth / 2), // position for strokewidth
|
||||
width: 100,
|
||||
height: 100
|
||||
});
|
||||
})
|
||||
|
||||
const gridimg = svgdoc.createElementNS(NS.SVG, 'image');
|
||||
const gridimg = svgdoc.createElementNS(NS.SVG, 'image')
|
||||
assignAttributes(gridimg, {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 100,
|
||||
height: 100
|
||||
});
|
||||
gridPattern.append(gridimg);
|
||||
gridDefs.append(gridPattern);
|
||||
$id('canvasGrid').appendChild(gridDefs);
|
||||
})
|
||||
gridPattern.append(gridimg)
|
||||
gridDefs.append(gridPattern)
|
||||
$id('canvasGrid').appendChild(gridDefs)
|
||||
|
||||
// grid-box
|
||||
const gridBox = svgdoc.createElementNS(NS.SVG, 'rect');
|
||||
const gridBox = svgdoc.createElementNS(NS.SVG, 'rect')
|
||||
assignAttributes(gridBox, {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
@@ -85,8 +84,8 @@ export default {
|
||||
stroke: 'none',
|
||||
fill: 'url(#gridpattern)',
|
||||
style: 'pointer-events: none; display:visible;'
|
||||
});
|
||||
$id('canvasGrid').appendChild(gridBox);
|
||||
})
|
||||
$id('canvasGrid').appendChild(gridBox)
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -95,52 +94,52 @@ export default {
|
||||
*/
|
||||
const updateGrid = (zoom) => {
|
||||
// TODO: Try this with <line> elements, then compare performance difference
|
||||
const unit = units[svgEditor.configObj.curConfig.baseUnit]; // 1 = 1px
|
||||
const uMulti = unit * zoom;
|
||||
const unit = units[svgEditor.configObj.curConfig.baseUnit] // 1 = 1px
|
||||
const uMulti = unit * zoom
|
||||
// Calculate the main number interval
|
||||
const rawM = 100 / uMulti;
|
||||
let multi = 1;
|
||||
const rawM = 100 / uMulti
|
||||
let multi = 1
|
||||
intervals.some((num) => {
|
||||
multi = num;
|
||||
return rawM <= num;
|
||||
});
|
||||
const bigInt = multi * uMulti;
|
||||
multi = num
|
||||
return rawM <= num
|
||||
})
|
||||
const bigInt = multi * uMulti
|
||||
|
||||
// Set the canvas size to the width of the container
|
||||
hcanvas.width = bigInt;
|
||||
hcanvas.height = bigInt;
|
||||
const ctx = hcanvas.getContext('2d');
|
||||
const curD = 0.5;
|
||||
const part = bigInt / 10;
|
||||
hcanvas.width = bigInt
|
||||
hcanvas.height = bigInt
|
||||
const ctx = hcanvas.getContext('2d')
|
||||
const curD = 0.5
|
||||
const part = bigInt / 10
|
||||
|
||||
ctx.globalAlpha = 0.2;
|
||||
ctx.strokeStyle = svgEditor.configObj.curConfig.gridColor;
|
||||
ctx.globalAlpha = 0.2
|
||||
ctx.strokeStyle = svgEditor.configObj.curConfig.gridColor
|
||||
for (let i = 1; i < 10; i++) {
|
||||
const subD = Math.round(part * i) + 0.5;
|
||||
const subD = Math.round(part * i) + 0.5
|
||||
// const lineNum = (i % 2)?12:10;
|
||||
const lineNum = 0;
|
||||
ctx.moveTo(subD, bigInt);
|
||||
ctx.lineTo(subD, lineNum);
|
||||
ctx.moveTo(bigInt, subD);
|
||||
ctx.lineTo(lineNum, subD);
|
||||
const lineNum = 0
|
||||
ctx.moveTo(subD, bigInt)
|
||||
ctx.lineTo(subD, lineNum)
|
||||
ctx.moveTo(bigInt, subD)
|
||||
ctx.lineTo(lineNum, subD)
|
||||
}
|
||||
ctx.stroke();
|
||||
ctx.beginPath();
|
||||
ctx.globalAlpha = 0.5;
|
||||
ctx.moveTo(curD, bigInt);
|
||||
ctx.lineTo(curD, 0);
|
||||
ctx.stroke()
|
||||
ctx.beginPath()
|
||||
ctx.globalAlpha = 0.5
|
||||
ctx.moveTo(curD, bigInt)
|
||||
ctx.lineTo(curD, 0)
|
||||
|
||||
ctx.moveTo(bigInt, curD);
|
||||
ctx.lineTo(0, curD);
|
||||
ctx.stroke();
|
||||
ctx.moveTo(bigInt, curD)
|
||||
ctx.lineTo(0, curD)
|
||||
ctx.stroke()
|
||||
|
||||
const datauri = hcanvas.toDataURL('image/png');
|
||||
gridimg.setAttribute('width', bigInt);
|
||||
gridimg.setAttribute('height', bigInt);
|
||||
gridimg.parentNode.setAttribute('width', bigInt);
|
||||
gridimg.parentNode.setAttribute('height', bigInt);
|
||||
svgCanvas.setHref(gridimg, datauri);
|
||||
};
|
||||
const datauri = hcanvas.toDataURL('image/png')
|
||||
gridimg.setAttribute('width', bigInt)
|
||||
gridimg.setAttribute('height', bigInt)
|
||||
gridimg.parentNode.setAttribute('width', bigInt)
|
||||
gridimg.parentNode.setAttribute('height', bigInt)
|
||||
svgCanvas.setHref(gridimg, datauri)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -148,34 +147,32 @@ export default {
|
||||
*/
|
||||
const gridUpdate = () => {
|
||||
if (showGrid) {
|
||||
updateGrid(svgCanvas.getZoom());
|
||||
updateGrid(svgCanvas.getZoom())
|
||||
}
|
||||
$id('canvasGrid').style.display = (showGrid) ? 'block' : 'none';
|
||||
$id('view_grid').pressed = showGrid;
|
||||
};
|
||||
$id('canvasGrid').style.display = (showGrid) ? 'block' : 'none'
|
||||
$id('view_grid').pressed = showGrid
|
||||
}
|
||||
return {
|
||||
name: svgEditor.i18next.t(`${name}:name`),
|
||||
zoomChanged (zoom) {
|
||||
if (showGrid) { updateGrid(zoom); }
|
||||
if (showGrid) { updateGrid(zoom) }
|
||||
},
|
||||
callback () {
|
||||
// Add the button and its handler(s)
|
||||
const buttonTemplate = document.createElement("template");
|
||||
const title = `${name}:buttons.0.title`;
|
||||
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
const buttonTemplate = document.createElement('template')
|
||||
const title = `${name}:buttons.0.title`
|
||||
buttonTemplate.innerHTML = `
|
||||
<se-button id="view_grid" title="${title}" src="grid.svg"></se-button>
|
||||
`;
|
||||
$id('editor_panel').append(buttonTemplate.content.cloneNode(true));
|
||||
$id('view_grid').addEventListener("click", () => {
|
||||
svgEditor.configObj.curConfig.showGrid = showGrid = !showGrid;
|
||||
gridUpdate();
|
||||
});
|
||||
`
|
||||
$id('editor_panel').append(buttonTemplate.content.cloneNode(true))
|
||||
$id('view_grid').addEventListener('click', () => {
|
||||
svgEditor.configObj.curConfig.showGrid = showGrid = !showGrid
|
||||
gridUpdate()
|
||||
})
|
||||
if (showGrid) {
|
||||
gridUpdate();
|
||||
gridUpdate()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,4 +5,4 @@ export default {
|
||||
title: 'Show/Hide Grid'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,4 +5,4 @@ export default {
|
||||
title: 'Afficher/Cacher Grille'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,4 +5,4 @@ export default {
|
||||
title: '显示/隐藏网格'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,42 +13,40 @@
|
||||
* will show the user the point on the canvas that was clicked on.
|
||||
*/
|
||||
|
||||
const name = "helloworld";
|
||||
const name = 'helloworld'
|
||||
|
||||
const loadExtensionTranslation = async function (svgEditor) {
|
||||
let translationModule;
|
||||
const lang = svgEditor.configObj.pref('lang');
|
||||
let translationModule
|
||||
const lang = svgEditor.configObj.pref('lang')
|
||||
try {
|
||||
// eslint-disable-next-line no-unsanitized/method
|
||||
translationModule = await import(`./locale/${lang}.js`);
|
||||
translationModule = await import(`./locale/${lang}.js`)
|
||||
} catch (_error) {
|
||||
console.warn(`Missing translation (${lang}) for ${name} - using 'en'`);
|
||||
translationModule = await import(`./locale/en.js`);
|
||||
console.warn(`Missing translation (${lang}) for ${name} - using 'en'`)
|
||||
translationModule = await import('./locale/en.js')
|
||||
}
|
||||
svgEditor.i18next.addResourceBundle(lang, name, translationModule.default);
|
||||
};
|
||||
svgEditor.i18next.addResourceBundle(lang, name, translationModule.default)
|
||||
}
|
||||
|
||||
export default {
|
||||
name,
|
||||
async init ({ _importLocale }) {
|
||||
const svgEditor = this;
|
||||
await loadExtensionTranslation(svgEditor);
|
||||
const { svgCanvas } = svgEditor;
|
||||
const { $id } = svgCanvas;
|
||||
const svgEditor = this
|
||||
await loadExtensionTranslation(svgEditor)
|
||||
const { svgCanvas } = svgEditor
|
||||
const { $id } = svgCanvas
|
||||
return {
|
||||
name: svgEditor.i18next.t(`${name}:name`),
|
||||
callback() {
|
||||
callback () {
|
||||
// Add the button and its handler(s)
|
||||
const buttonTemplate = document.createElement("template");
|
||||
const title = `${name}:buttons.0.title`;
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
const buttonTemplate = document.createElement('template')
|
||||
const title = `${name}:buttons.0.title`
|
||||
buttonTemplate.innerHTML = `
|
||||
<se-button id="hello_world" title="${title}" src="hello_world.svg"></se-button>
|
||||
`;
|
||||
$id('tools_left').append(buttonTemplate.content.cloneNode(true));
|
||||
$id('hello_world').addEventListener("click", () => {
|
||||
svgCanvas.setMode('hello_world');
|
||||
});
|
||||
`
|
||||
$id('tools_left').append(buttonTemplate.content.cloneNode(true))
|
||||
$id('hello_world').addEventListener('click', () => {
|
||||
svgCanvas.setMode('hello_world')
|
||||
})
|
||||
},
|
||||
// This is triggered when the main mouse button is pressed down
|
||||
// on the editor canvas (not the tool panels)
|
||||
@@ -57,9 +55,9 @@ export default {
|
||||
if (svgCanvas.getMode() === 'hello_world') {
|
||||
// The returned object must include "started" with
|
||||
// a value of true in order for mouseUp to be triggered
|
||||
return { started: true };
|
||||
return { started: true }
|
||||
}
|
||||
return undefined;
|
||||
return undefined
|
||||
},
|
||||
|
||||
// This is triggered from anywhere, but "started" must have been set
|
||||
@@ -67,18 +65,18 @@ export default {
|
||||
mouseUp (opts) {
|
||||
// Check the mode on mouseup
|
||||
if (svgCanvas.getMode() === 'hello_world') {
|
||||
const zoom = svgCanvas.getZoom();
|
||||
const zoom = svgCanvas.getZoom()
|
||||
|
||||
// Get the actual coordinate by dividing by the zoom value
|
||||
const x = opts.mouse_x / zoom;
|
||||
const y = opts.mouse_y / zoom;
|
||||
const x = opts.mouse_x / zoom
|
||||
const y = opts.mouse_y / zoom
|
||||
|
||||
// We do our own formatting
|
||||
const text = svgEditor.i18next.t(`${name}:text`, { x, y });
|
||||
const text = svgEditor.i18next.t(`${name}:text`, { x, y })
|
||||
// Show the text using the custom alert function
|
||||
alert(text);
|
||||
alert(text)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,4 +6,4 @@ export default {
|
||||
title: "Say 'Hello World'"
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,4 +6,4 @@ export default {
|
||||
title: "Dire 'Bonjour le Monde'"
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,4 +6,4 @@ export default {
|
||||
title: "输出 'Hello World'"
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-unsanitized/property */
|
||||
/* globals seConfirm */
|
||||
/**
|
||||
* @file ext-imagelib.js
|
||||
@@ -9,32 +8,31 @@
|
||||
*
|
||||
*/
|
||||
|
||||
const name = "imagelib";
|
||||
const name = 'imagelib'
|
||||
|
||||
const loadExtensionTranslation = async function (svgEditor) {
|
||||
let translationModule;
|
||||
const lang = svgEditor.configObj.pref('lang');
|
||||
let translationModule
|
||||
const lang = svgEditor.configObj.pref('lang')
|
||||
try {
|
||||
// eslint-disable-next-line no-unsanitized/method
|
||||
translationModule = await import(`./locale/${lang}.js`);
|
||||
translationModule = await import(`./locale/${lang}.js`)
|
||||
} catch (_error) {
|
||||
console.warn(`Missing translation (${lang}) for ${name} - using 'en'`);
|
||||
translationModule = await import(`./locale/en.js`);
|
||||
console.warn(`Missing translation (${lang}) for ${name} - using 'en'`)
|
||||
translationModule = await import('./locale/en.js')
|
||||
}
|
||||
svgEditor.i18next.addResourceBundle(lang, name, translationModule.default);
|
||||
};
|
||||
svgEditor.i18next.addResourceBundle(lang, name, translationModule.default)
|
||||
}
|
||||
|
||||
export default {
|
||||
name,
|
||||
async init({ decode64, dropXMLInternalSubset }) {
|
||||
const svgEditor = this;
|
||||
const { $id } = svgEditor.svgCanvas;
|
||||
const { $svgEditor } = svgEditor;
|
||||
const { imgPath } = svgEditor.configObj.curConfig;
|
||||
async init ({ decode64, dropXMLInternalSubset }) {
|
||||
const svgEditor = this
|
||||
const { $id } = svgEditor.svgCanvas
|
||||
const { $svgEditor } = svgEditor
|
||||
const { imgPath } = svgEditor.configObj.curConfig
|
||||
|
||||
await loadExtensionTranslation(svgEditor);
|
||||
await loadExtensionTranslation(svgEditor)
|
||||
|
||||
const { svgCanvas } = svgEditor;
|
||||
const { svgCanvas } = svgEditor
|
||||
|
||||
const imgLibs = [
|
||||
{
|
||||
@@ -47,24 +45,24 @@ export default {
|
||||
url: 'https://ian.umces.edu/symbols/catalog/svgedit/album_chooser.php?svgedit=3',
|
||||
description: svgEditor.i18next.t(`${name}:imgLibs_1_description`)
|
||||
}
|
||||
];
|
||||
]
|
||||
|
||||
const allowedImageLibOrigins = imgLibs.map(({ url }) => {
|
||||
try {
|
||||
return new URL(url).origin;
|
||||
return new URL(url).origin
|
||||
} catch (err) {
|
||||
return location.origin;
|
||||
return location.origin
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
const closeBrowser = () => {
|
||||
$id("imgbrowse_holder").style.display = 'none';
|
||||
document.activeElement.blur(); // make sure focus is the body to correct issue #417
|
||||
};
|
||||
$id('imgbrowse_holder').style.display = 'none'
|
||||
document.activeElement.blur() // make sure focus is the body to correct issue #417
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} url
|
||||
@@ -81,18 +79,18 @@ export default {
|
||||
id: svgCanvas.getNextId(),
|
||||
style: 'pointer-events:inherit'
|
||||
}
|
||||
});
|
||||
svgCanvas.clearSelection();
|
||||
svgCanvas.addToSelection([ newImage ]);
|
||||
svgCanvas.setImageURL(url);
|
||||
};
|
||||
})
|
||||
svgCanvas.clearSelection()
|
||||
svgCanvas.addToSelection([newImage])
|
||||
svgCanvas.setImageURL(url)
|
||||
}
|
||||
|
||||
const pending = {};
|
||||
const pending = {}
|
||||
|
||||
let mode = 's';
|
||||
let multiArr = [];
|
||||
let transferStopped = false;
|
||||
let preview; let submit;
|
||||
let mode = 's'
|
||||
let multiArr = []
|
||||
let transferStopped = false
|
||||
let preview; let submit
|
||||
|
||||
/**
|
||||
* Contains the SVG to insert.
|
||||
@@ -130,403 +128,401 @@ export default {
|
||||
* @param {ImageLibMetaMessage|ImageLibMessage|string} cfg.data String is deprecated when parsed to JSON `ImageLibMessage`
|
||||
* @returns {void}
|
||||
*/
|
||||
async function onMessage({ origin, data }) {
|
||||
let response = data;
|
||||
if (!response || ![ 'string', 'object' ].includes(typeof response)) {
|
||||
async function onMessage ({ origin, data }) {
|
||||
let response = data
|
||||
if (!response || !['string', 'object'].includes(typeof response)) {
|
||||
// Do nothing
|
||||
return;
|
||||
return
|
||||
}
|
||||
let id;
|
||||
let type;
|
||||
let id
|
||||
let type
|
||||
try {
|
||||
// Todo: This block can be removed (and the above check changed to
|
||||
// insist on an object) if embedAPI moves away from a string to
|
||||
// an object (if IE9 support not needed)
|
||||
response = typeof response === 'object' ? response : JSON.parse(response);
|
||||
response = typeof response === 'object' ? response : JSON.parse(response)
|
||||
if (response.namespace !== 'imagelib') {
|
||||
return;
|
||||
return
|
||||
}
|
||||
if (!allowedImageLibOrigins.includes('*') && !allowedImageLibOrigins.includes(origin)) {
|
||||
// Todo: Surface this error to user?
|
||||
console.error(`Origin ${origin} not whitelisted for posting to ${window.origin}`);
|
||||
return;
|
||||
console.error(`Origin ${origin} not whitelisted for posting to ${window.origin}`)
|
||||
return
|
||||
}
|
||||
const hasName = 'name' in response;
|
||||
const hasHref = 'href' in response;
|
||||
const hasName = 'name' in response
|
||||
const hasHref = 'href' in response
|
||||
|
||||
if (!hasName && transferStopped) {
|
||||
transferStopped = false;
|
||||
return;
|
||||
transferStopped = false
|
||||
return
|
||||
}
|
||||
|
||||
if (hasHref) {
|
||||
id = response.href;
|
||||
response = response.data;
|
||||
id = response.href
|
||||
response = response.data
|
||||
}
|
||||
|
||||
// Hide possible transfer dialog box
|
||||
if (document.querySelector('se-elix-alert-dialog')) {
|
||||
document.querySelector('se-elix-alert-dialog').remove();
|
||||
document.querySelector('se-elix-alert-dialog').remove()
|
||||
}
|
||||
type = hasName
|
||||
? 'meta'
|
||||
: response.charAt(0);
|
||||
: response.charAt(0)
|
||||
} catch (e) {
|
||||
// This block is for backward compatibility (for IAN and Openclipart);
|
||||
// should otherwise return
|
||||
if (typeof response === 'string') {
|
||||
const char1 = response.charAt(0);
|
||||
const char1 = response.charAt(0)
|
||||
|
||||
if (char1 !== '{' && transferStopped) {
|
||||
transferStopped = false;
|
||||
return;
|
||||
transferStopped = false
|
||||
return
|
||||
}
|
||||
|
||||
if (char1 === '|') {
|
||||
const secondpos = response.indexOf('|', 1);
|
||||
id = response.substr(1, secondpos - 1);
|
||||
response = response.substr(secondpos + 1);
|
||||
type = response.charAt(0);
|
||||
const secondpos = response.indexOf('|', 1)
|
||||
id = response.substr(1, secondpos - 1)
|
||||
response = response.substr(secondpos + 1)
|
||||
type = response.charAt(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let entry; let curMeta; let svgStr; let imgStr;
|
||||
let entry; let curMeta; let svgStr; let imgStr
|
||||
switch (type) {
|
||||
case 'meta': {
|
||||
case 'meta': {
|
||||
// Metadata
|
||||
transferStopped = false;
|
||||
curMeta = response;
|
||||
transferStopped = false
|
||||
curMeta = response
|
||||
|
||||
// Should be safe to add dynamic property as passed metadata
|
||||
pending[curMeta.id] = curMeta; // lgtm [js/remote-property-injection]
|
||||
// Should be safe to add dynamic property as passed metadata
|
||||
pending[curMeta.id] = curMeta // lgtm [js/remote-property-injection]
|
||||
|
||||
const name = (curMeta.name || 'file');
|
||||
const name = (curMeta.name || 'file')
|
||||
|
||||
const message = svgEditor.i18next.t('notification.retrieving').replace('%s', name);
|
||||
const message = svgEditor.i18next.t('notification.retrieving').replace('%s', name)
|
||||
|
||||
if (mode !== 'm') {
|
||||
await seConfirm(message);
|
||||
transferStopped = true;
|
||||
} else {
|
||||
entry = document.createElement('div');
|
||||
entry.textContent = message;
|
||||
entry.dataset.id = curMeta.id;
|
||||
preview.appendChild(entry);
|
||||
curMeta.entry = entry;
|
||||
if (mode !== 'm') {
|
||||
await seConfirm(message)
|
||||
transferStopped = true
|
||||
} else {
|
||||
entry = document.createElement('div')
|
||||
entry.textContent = message
|
||||
entry.dataset.id = curMeta.id
|
||||
preview.appendChild(entry)
|
||||
curMeta.entry = entry
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
case '<':
|
||||
svgStr = true;
|
||||
break;
|
||||
case 'd': {
|
||||
if (response.startsWith('data:image/svg+xml')) {
|
||||
const pre = 'data:image/svg+xml;base64,';
|
||||
const src = response.substring(pre.length);
|
||||
response = decode64(src);
|
||||
svgStr = true;
|
||||
break;
|
||||
} else if (response.startsWith('data:image/')) {
|
||||
imgStr = true;
|
||||
break;
|
||||
case '<':
|
||||
svgStr = true
|
||||
break
|
||||
case 'd': {
|
||||
if (response.startsWith('data:image/svg+xml')) {
|
||||
const pre = 'data:image/svg+xml;base64,'
|
||||
const src = response.substring(pre.length)
|
||||
response = decode64(src)
|
||||
svgStr = true
|
||||
break
|
||||
} else if (response.startsWith('data:image/')) {
|
||||
imgStr = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
// Else fall through
|
||||
default:
|
||||
// Else fall through
|
||||
default:
|
||||
// TODO: See if there's a way to base64 encode the binary data stream
|
||||
// const str = 'data:;base64,' + svgedit.utilities.encode64(response, true);
|
||||
|
||||
// Assume it's raw image data
|
||||
// importImage(str);
|
||||
// Assume it's raw image data
|
||||
// importImage(str);
|
||||
|
||||
// Don't give warning as postMessage may have been used by something else
|
||||
if (mode !== 'm') {
|
||||
closeBrowser();
|
||||
} else {
|
||||
pending[id].entry.remove();
|
||||
}
|
||||
// await alert('Unexpected data was returned: ' + response, function() {
|
||||
// if (mode !== 'm') {
|
||||
// closeBrowser();
|
||||
// } else {
|
||||
// pending[id].entry.remove();
|
||||
// }
|
||||
// });
|
||||
return;
|
||||
// Don't give warning as postMessage may have been used by something else
|
||||
if (mode !== 'm') {
|
||||
closeBrowser()
|
||||
} else {
|
||||
pending[id].entry.remove()
|
||||
}
|
||||
// await alert('Unexpected data was returned: ' + response, function() {
|
||||
// if (mode !== 'm') {
|
||||
// closeBrowser();
|
||||
// } else {
|
||||
// pending[id].entry.remove();
|
||||
// }
|
||||
// });
|
||||
return
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case 's':
|
||||
case 's':
|
||||
// Import one
|
||||
if (svgStr) {
|
||||
svgEditor.svgCanvas.importSvgString(response);
|
||||
} else if (imgStr) {
|
||||
importImage(response);
|
||||
}
|
||||
closeBrowser();
|
||||
break;
|
||||
case 'm': {
|
||||
if (svgStr) {
|
||||
svgEditor.svgCanvas.importSvgString(response)
|
||||
} else if (imgStr) {
|
||||
importImage(response)
|
||||
}
|
||||
closeBrowser()
|
||||
break
|
||||
case 'm': {
|
||||
// Import multiple
|
||||
multiArr.push([ (svgStr ? 'svg' : 'img'), response ]);
|
||||
curMeta = pending[id];
|
||||
let title;
|
||||
if (svgStr) {
|
||||
if (curMeta && curMeta.name) {
|
||||
title = curMeta.name;
|
||||
} else {
|
||||
multiArr.push([(svgStr ? 'svg' : 'img'), response])
|
||||
curMeta = pending[id]
|
||||
let title
|
||||
if (svgStr) {
|
||||
if (curMeta && curMeta.name) {
|
||||
title = curMeta.name
|
||||
} else {
|
||||
// Try to find a title
|
||||
// `dropXMLInternalSubset` is to help prevent the billion laughs attack
|
||||
const xml = new DOMParser().parseFromString(dropXMLInternalSubset(response), 'text/xml').documentElement; // lgtm [js/xml-bomb]
|
||||
title = xml.querySelector('title').textContent || '(SVG #' + response.length + ')';
|
||||
}
|
||||
if (curMeta) {
|
||||
Array.from(preview.children).forEach(function (element) {
|
||||
if (element.dataset.id === id) {
|
||||
if (curMeta.preview_url) {
|
||||
const img = document.createElement("img");
|
||||
img.src = curMeta.preview_url;
|
||||
const span = document.createElement("span");
|
||||
span.appendChild(img);
|
||||
element.append(span);
|
||||
} else {
|
||||
element.textContent = title;
|
||||
const xml = new DOMParser().parseFromString(dropXMLInternalSubset(response), 'text/xml').documentElement // lgtm [js/xml-bomb]
|
||||
title = xml.querySelector('title').textContent || '(SVG #' + response.length + ')'
|
||||
}
|
||||
if (curMeta) {
|
||||
Array.from(preview.children).forEach(function (element) {
|
||||
if (element.dataset.id === id) {
|
||||
if (curMeta.preview_url) {
|
||||
const img = document.createElement('img')
|
||||
img.src = curMeta.preview_url
|
||||
const span = document.createElement('span')
|
||||
span.appendChild(img)
|
||||
element.append(span)
|
||||
} else {
|
||||
element.textContent = title
|
||||
}
|
||||
submit.removeAttribute('disabled')
|
||||
}
|
||||
submit.removeAttribute('disabled');
|
||||
}
|
||||
});
|
||||
})
|
||||
} else {
|
||||
const div = document.createElement('div')
|
||||
div.textContent = title
|
||||
preview.appendChild(div)
|
||||
submit.removeAttribute('disabled')
|
||||
}
|
||||
} else {
|
||||
const div = document.createElement("div");
|
||||
div.textContent = title;
|
||||
preview.appendChild(div);
|
||||
submit.removeAttribute('disabled');
|
||||
}
|
||||
} else {
|
||||
if (curMeta && curMeta.preview_url) {
|
||||
title = curMeta.name || '';
|
||||
entry = document.createElement('span');
|
||||
const img = document.createElement("img");
|
||||
img.src = curMeta.preview_url;
|
||||
entry.appendChild(img);
|
||||
entry.appendChild(document.createTextNode(title));
|
||||
} else {
|
||||
entry = document.createElement("img");
|
||||
entry.src = response;
|
||||
}
|
||||
if (curMeta && curMeta.preview_url) {
|
||||
title = curMeta.name || ''
|
||||
entry = document.createElement('span')
|
||||
const img = document.createElement('img')
|
||||
img.src = curMeta.preview_url
|
||||
entry.appendChild(img)
|
||||
entry.appendChild(document.createTextNode(title))
|
||||
} else {
|
||||
entry = document.createElement('img')
|
||||
entry.src = response
|
||||
}
|
||||
|
||||
if (curMeta) {
|
||||
Array.from(preview.children).forEach(function (element) {
|
||||
if (element.dataset.id === id) {
|
||||
element.appendChild(entry);
|
||||
submit.removeAttribute('disabled');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const div = document.createElement("div");
|
||||
div.appendChild(entry);
|
||||
preview.appendChild(div);
|
||||
submit.removeAttribute('disabled');
|
||||
if (curMeta) {
|
||||
Array.from(preview.children).forEach(function (element) {
|
||||
if (element.dataset.id === id) {
|
||||
element.appendChild(entry)
|
||||
submit.removeAttribute('disabled')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
const div = document.createElement('div')
|
||||
div.appendChild(entry)
|
||||
preview.appendChild(div)
|
||||
submit.removeAttribute('disabled')
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
} case 'o': {
|
||||
break
|
||||
} case 'o': {
|
||||
// Open
|
||||
if (!svgStr) { break; }
|
||||
closeBrowser();
|
||||
const ok = await svgEditor.openPrep();
|
||||
if (!ok) { return; }
|
||||
svgCanvas.clear();
|
||||
svgCanvas.setSvgString(response);
|
||||
// updateCanvas();
|
||||
break;
|
||||
}
|
||||
if (!svgStr) { break }
|
||||
closeBrowser()
|
||||
const ok = await svgEditor.openPrep()
|
||||
if (!ok) { return }
|
||||
svgCanvas.clear()
|
||||
svgCanvas.setSvgString(response)
|
||||
// updateCanvas();
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Receive `postMessage` data
|
||||
window.addEventListener('message', onMessage, true);
|
||||
window.addEventListener('message', onMessage, true)
|
||||
|
||||
const insertAfter = (referenceNode, newNode) => {
|
||||
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
|
||||
};
|
||||
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling)
|
||||
}
|
||||
|
||||
const toggleMultiLoop = () => {
|
||||
multiArr.forEach(function(item, i){
|
||||
const type = item[0];
|
||||
const data = item[1];
|
||||
multiArr.forEach(function (item, i) {
|
||||
const type = item[0]
|
||||
const data = item[1]
|
||||
if (type === 'svg') {
|
||||
svgCanvas.importSvgString(data);
|
||||
svgCanvas.importSvgString(data)
|
||||
} else {
|
||||
importImage(data);
|
||||
importImage(data)
|
||||
}
|
||||
svgCanvas.moveSelectedElements(i * 20, i * 20, false);
|
||||
});
|
||||
while (preview.firstChild)
|
||||
preview.removeChild(preview.firstChild);
|
||||
multiArr = [];
|
||||
$id("imgbrowse_holder").style.display = 'none';
|
||||
};
|
||||
svgCanvas.moveSelectedElements(i * 20, i * 20, false)
|
||||
})
|
||||
while (preview.firstChild) { preview.removeChild(preview.firstChild) }
|
||||
multiArr = []
|
||||
$id('imgbrowse_holder').style.display = 'none'
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {boolean} show
|
||||
* @returns {void}
|
||||
*/
|
||||
const toggleMulti = (show) => {
|
||||
$id('lib_framewrap').style.right = (show ? 200 : 10);
|
||||
$id('imglib_opts').style.right = (show ? 200 : 10);
|
||||
$id('lib_framewrap').style.right = (show ? 200 : 10)
|
||||
$id('imglib_opts').style.right = (show ? 200 : 10)
|
||||
if (!preview) {
|
||||
preview = document.createElement('div');
|
||||
preview.setAttribute('id', 'imglib_preview');
|
||||
preview.setAttribute('style', `position: absolute;top: 45px;right: 10px;width: 180px;bottom: 45px;background: #fff;overflow: auto;`);
|
||||
insertAfter($id('lib_framewrap'), preview);
|
||||
preview = document.createElement('div')
|
||||
preview.setAttribute('id', 'imglib_preview')
|
||||
preview.setAttribute('style', 'position: absolute;top: 45px;right: 10px;width: 180px;bottom: 45px;background: #fff;overflow: auto;')
|
||||
insertAfter($id('lib_framewrap'), preview)
|
||||
|
||||
submit = document.createElement('button');
|
||||
submit.setAttribute('content', 'Import selected');
|
||||
submit.setAttribute('disabled', true);
|
||||
submit.textContent = 'Import selected';
|
||||
submit.setAttribute('style', `position: absolute;bottom: 10px;right: -10px;`);
|
||||
$id('imgbrowse').appendChild(submit);
|
||||
submit.addEventListener('click', toggleMultiLoop);
|
||||
submit.addEventListener('touchend', toggleMultiLoop);
|
||||
submit = document.createElement('button')
|
||||
submit.setAttribute('content', 'Import selected')
|
||||
submit.setAttribute('disabled', true)
|
||||
submit.textContent = 'Import selected'
|
||||
submit.setAttribute('style', 'position: absolute;bottom: 10px;right: -10px;')
|
||||
$id('imgbrowse').appendChild(submit)
|
||||
submit.addEventListener('click', toggleMultiLoop)
|
||||
submit.addEventListener('touchend', toggleMultiLoop)
|
||||
}
|
||||
submit.style.display = (show) ? 'block' : 'none';
|
||||
preview.style.display = (show) ? 'block' : 'none';
|
||||
|
||||
};
|
||||
submit.style.display = (show) ? 'block' : 'none'
|
||||
preview.style.display = (show) ? 'block' : 'none'
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
const showBrowser = () => {
|
||||
let browser = $id('imgbrowse');
|
||||
let browser = $id('imgbrowse')
|
||||
if (!browser) {
|
||||
const div = document.createElement('div');
|
||||
div.id = 'imgbrowse_holder';
|
||||
div.innerHTML = '<div id=imgbrowse class=toolbar_button></div>';
|
||||
insertAfter($svgEditor, div);
|
||||
browser = $id('imgbrowse');
|
||||
const div = document.createElement('div')
|
||||
div.id = 'imgbrowse_holder'
|
||||
div.innerHTML = '<div id=imgbrowse class=toolbar_button></div>'
|
||||
insertAfter($svgEditor, div)
|
||||
browser = $id('imgbrowse')
|
||||
|
||||
const allLibs = svgEditor.i18next.t(`${name}:select_lib`);
|
||||
const allLibs = svgEditor.i18next.t(`${name}:select_lib`)
|
||||
|
||||
const divFrameWrap = document.createElement('div');
|
||||
divFrameWrap.id = 'lib_framewrap';
|
||||
const divFrameWrap = document.createElement('div')
|
||||
divFrameWrap.id = 'lib_framewrap'
|
||||
|
||||
const libOpts = document.createElement('ul');
|
||||
libOpts.id = 'imglib_opts';
|
||||
browser.append(libOpts);
|
||||
const frame = document.createElement('iframe');
|
||||
frame.src = "javascript:0";
|
||||
frame.style.display = 'none';
|
||||
divFrameWrap.append(frame);
|
||||
browser.prepend(divFrameWrap);
|
||||
const libOpts = document.createElement('ul')
|
||||
libOpts.id = 'imglib_opts'
|
||||
browser.append(libOpts)
|
||||
const frame = document.createElement('iframe')
|
||||
frame.src = 'javascript:0'
|
||||
frame.style.display = 'none'
|
||||
divFrameWrap.append(frame)
|
||||
browser.prepend(divFrameWrap)
|
||||
|
||||
const header = document.createElement('h1');
|
||||
browser.prepend(header);
|
||||
header.textContent = allLibs;
|
||||
header.setAttribute('style', `position: absolute;top: 0px;left: 0px;width: 100%;`);
|
||||
const header = document.createElement('h1')
|
||||
browser.prepend(header)
|
||||
header.textContent = allLibs
|
||||
header.setAttribute('style', 'position: absolute;top: 0px;left: 0px;width: 100%;')
|
||||
|
||||
const button = document.createElement('button');
|
||||
button.innerHTML = svgEditor.i18next.t('common.cancel');
|
||||
browser.appendChild(button);
|
||||
const button = document.createElement('button')
|
||||
button.innerHTML = svgEditor.i18next.t('common.cancel')
|
||||
browser.appendChild(button)
|
||||
button.addEventListener('click', function () {
|
||||
$id("imgbrowse_holder").style.display = 'none';
|
||||
});
|
||||
$id('imgbrowse_holder').style.display = 'none'
|
||||
})
|
||||
button.addEventListener('touchend', function () {
|
||||
$id("imgbrowse_holder").style.display = 'none';
|
||||
});
|
||||
button.setAttribute('style', `position: absolute;top: 5px;right: 10px;`);
|
||||
$id('imgbrowse_holder').style.display = 'none'
|
||||
})
|
||||
button.setAttribute('style', 'position: absolute;top: 5px;right: 10px;')
|
||||
|
||||
const leftBlock = document.createElement('span');
|
||||
leftBlock.setAttribute('style', `position: absolute;top: 5px;left: 10px;display: inline-flex;`);
|
||||
browser.appendChild(leftBlock);
|
||||
const leftBlock = document.createElement('span')
|
||||
leftBlock.setAttribute('style', 'position: absolute;top: 5px;left: 10px;display: inline-flex;')
|
||||
browser.appendChild(leftBlock)
|
||||
|
||||
const back = document.createElement('button');
|
||||
back.style.visibility = "hidden";
|
||||
back.innerHTML = `<img class="svg_icon" src="${imgPath}/library.svg" alt="icon" width="16" height="16" />` + svgEditor.i18next.t(`${name}:show_list`);
|
||||
leftBlock.appendChild(back);
|
||||
const back = document.createElement('button')
|
||||
back.style.visibility = 'hidden'
|
||||
back.innerHTML = `<img class="svg_icon" src="${imgPath}/library.svg" alt="icon" width="16" height="16" />` + svgEditor.i18next.t(`${name}:show_list`)
|
||||
leftBlock.appendChild(back)
|
||||
back.addEventListener('click', function () {
|
||||
frame.setAttribute('src', 'about:blank');
|
||||
frame.style.display = 'none';
|
||||
libOpts.style.display = 'block';
|
||||
header.textContent = allLibs;
|
||||
back.style.display = 'none';
|
||||
});
|
||||
frame.setAttribute('src', 'about:blank')
|
||||
frame.style.display = 'none'
|
||||
libOpts.style.display = 'block'
|
||||
header.textContent = allLibs
|
||||
back.style.display = 'none'
|
||||
})
|
||||
back.addEventListener('touchend', function () {
|
||||
frame.setAttribute('src', 'about:blank');
|
||||
frame.style.display = 'none';
|
||||
libOpts.style.display = 'block';
|
||||
header.textContent = allLibs;
|
||||
back.style.display = 'none';
|
||||
});
|
||||
back.setAttribute('style', `margin-right: 5px;`);
|
||||
back.style.display = 'none';
|
||||
frame.setAttribute('src', 'about:blank')
|
||||
frame.style.display = 'none'
|
||||
libOpts.style.display = 'block'
|
||||
header.textContent = allLibs
|
||||
back.style.display = 'none'
|
||||
})
|
||||
back.setAttribute('style', 'margin-right: 5px;')
|
||||
back.style.display = 'none'
|
||||
|
||||
const select = document.createElement('select');
|
||||
const select = document.createElement('select')
|
||||
select.innerHTML = '<select><option value=s>' +
|
||||
svgEditor.i18next.t(`${name}:import_single`) + '</option><option value=m>' +
|
||||
svgEditor.i18next.t(`${name}:import_multi`) + '</option><option value=o>' +
|
||||
svgEditor.i18next.t(`${name}:open`) + '</option>';
|
||||
leftBlock.appendChild(select);
|
||||
svgEditor.i18next.t(`${name}:open`) + '</option>'
|
||||
leftBlock.appendChild(select)
|
||||
select.addEventListener('change', function () {
|
||||
mode = this.value;
|
||||
mode = this.value
|
||||
switch (mode) {
|
||||
case 's':
|
||||
case 'o':
|
||||
toggleMulti(false);
|
||||
break;
|
||||
case 's':
|
||||
case 'o':
|
||||
toggleMulti(false)
|
||||
break
|
||||
|
||||
case 'm':
|
||||
case 'm':
|
||||
// Import multiple
|
||||
toggleMulti(true);
|
||||
break;
|
||||
toggleMulti(true)
|
||||
break
|
||||
}
|
||||
});
|
||||
select.setAttribute('style', `margin-top: 10px;`);
|
||||
})
|
||||
select.setAttribute('style', 'margin-top: 10px;')
|
||||
|
||||
imgLibs.forEach(function ({ name, url, description }) {
|
||||
const li = document.createElement('li');
|
||||
libOpts.appendChild(li);
|
||||
li.textContent = name;
|
||||
const li = document.createElement('li')
|
||||
libOpts.appendChild(li)
|
||||
li.textContent = name
|
||||
li.addEventListener('click', function () {
|
||||
frame.setAttribute('src', url);
|
||||
frame.style.display = 'block';
|
||||
header.textContent = name;
|
||||
libOpts.style.display = 'none';
|
||||
back.style.display = 'block';
|
||||
});
|
||||
frame.setAttribute('src', url)
|
||||
frame.style.display = 'block'
|
||||
header.textContent = name
|
||||
libOpts.style.display = 'none'
|
||||
back.style.display = 'block'
|
||||
})
|
||||
li.addEventListener('touchend', function () {
|
||||
frame.setAttribute('src', url);
|
||||
frame.style.display = 'block';
|
||||
header.textContent = name;
|
||||
libOpts.style.display = 'none';
|
||||
back.style.display = 'block';
|
||||
});
|
||||
const span = document.createElement("span");
|
||||
span.textContent = description;
|
||||
li.appendChild(span);
|
||||
});
|
||||
frame.setAttribute('src', url)
|
||||
frame.style.display = 'block'
|
||||
header.textContent = name
|
||||
libOpts.style.display = 'none'
|
||||
back.style.display = 'block'
|
||||
})
|
||||
const span = document.createElement('span')
|
||||
span.textContent = description
|
||||
li.appendChild(span)
|
||||
})
|
||||
} else {
|
||||
$id("imgbrowse_holder").style.display = 'block';
|
||||
$id('imgbrowse_holder').style.display = 'block'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
svgicons: 'ext-imagelib.xml',
|
||||
callback() {
|
||||
callback () {
|
||||
// Add the button and its handler(s)
|
||||
const buttonTemplate = document.createElement("template");
|
||||
const key = name + `:buttons.0.title`;
|
||||
const buttonTemplate = document.createElement('template')
|
||||
const key = name + ':buttons.0.title'
|
||||
buttonTemplate.innerHTML = `
|
||||
<se-menu-item id="tool_imagelib" label="${key}" src="library.svg"></se-menu-item>
|
||||
`;
|
||||
insertAfter($id('tool_export'), buttonTemplate.content.cloneNode(true));
|
||||
$id('tool_imagelib').addEventListener("click", () => {
|
||||
showBrowser();
|
||||
});
|
||||
`
|
||||
insertAfter($id('tool_export'), buttonTemplate.content.cloneNode(true))
|
||||
$id('tool_imagelib').addEventListener('click', () => {
|
||||
showBrowser()
|
||||
})
|
||||
|
||||
const style = document.createElement('style');
|
||||
const style = document.createElement('style')
|
||||
style.textContent = '#imgbrowse_holder {' +
|
||||
'position: absolute;' +
|
||||
'top: 0;' +
|
||||
@@ -599,9 +595,9 @@ export default {
|
||||
'width: 100%;' +
|
||||
'height: 100%;' +
|
||||
'border: 0;' +
|
||||
'}';
|
||||
document.head.appendChild(style);
|
||||
'}'
|
||||
document.head.appendChild(style)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
const atags = document.querySelectorAll('a');
|
||||
const atags = document.querySelectorAll('a')
|
||||
Array.prototype.forEach.call(atags, function (aEle) {
|
||||
aEle.addEventListener('click', function (event) {
|
||||
event.preventDefault();
|
||||
const { href } = event.currentTarget;
|
||||
const target = window.parent;
|
||||
event.preventDefault()
|
||||
const { href } = event.currentTarget
|
||||
const target = window.parent
|
||||
const post = (message) => {
|
||||
// Todo: Make origin customizable as set by opening window
|
||||
// Todo: If dropping IE9, avoid stringifying
|
||||
target.postMessage(JSON.stringify({
|
||||
namespace: 'imagelib',
|
||||
...message
|
||||
}), '*');
|
||||
};
|
||||
}), '*')
|
||||
}
|
||||
// Convert Non-SVG images to data URL first
|
||||
// (this could also have been done server-side by the library)
|
||||
// Send metadata (also indicates file is about to be sent)
|
||||
post({
|
||||
name: event.currentTarget.textContent,
|
||||
id: href
|
||||
});
|
||||
})
|
||||
if (!href.includes('.svg')) {
|
||||
const img = new Image();
|
||||
const img = new Image()
|
||||
img.addEventListener('load', function () {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = this.width;
|
||||
canvas.height = this.height;
|
||||
const canvas = document.createElement('canvas')
|
||||
canvas.width = this.width
|
||||
canvas.height = this.height
|
||||
// load the raster image into the canvas
|
||||
canvas.getContext('2d').drawImage(this, 0, 0);
|
||||
canvas.getContext('2d').drawImage(this, 0, 0)
|
||||
// retrieve the data: URL
|
||||
let data;
|
||||
let data
|
||||
try {
|
||||
data = canvas.toDataURL();
|
||||
data = canvas.toDataURL()
|
||||
} catch (err) {
|
||||
// This fails in Firefox with `file:///` URLs :(
|
||||
// Todo: This could use a generic alert library instead
|
||||
alert('Data URL conversion failed: ' + err);
|
||||
data = '';
|
||||
alert('Data URL conversion failed: ' + err)
|
||||
data = ''
|
||||
}
|
||||
post({ href, data });
|
||||
});
|
||||
img.src = href;
|
||||
post({ href, data })
|
||||
})
|
||||
img.src = href
|
||||
} else {
|
||||
fetch(href)
|
||||
.then( (r) => r.text())
|
||||
.then( (data) => {
|
||||
post({ href, data });
|
||||
return data;
|
||||
.then((r) => r.text())
|
||||
.then((data) => {
|
||||
post({ href, data })
|
||||
return data
|
||||
})
|
||||
.catch( (error) => console.error(error));
|
||||
.catch((error) => console.error(error))
|
||||
}
|
||||
return false;
|
||||
});
|
||||
});
|
||||
return false
|
||||
})
|
||||
})
|
||||
|
||||
@@ -13,4 +13,4 @@ export default {
|
||||
imgLibs_0_description: 'Demonstration library for SVG-edit on this server',
|
||||
imgLibs_1_name: 'IAN Symbol Libraries',
|
||||
imgLibs_1_description: 'Free library of illustrations'
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,4 +13,4 @@ export default {
|
||||
imgLibs_0_description: 'Demonstration library for SVG-edit on this server',
|
||||
imgLibs_1_name: 'IAN Symbol Libraries',
|
||||
imgLibs_1_description: 'Free library of illustrations'
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,4 +13,4 @@ export default {
|
||||
imgLibs_0_description: 'Demonstration library for SVG-edit on this server',
|
||||
imgLibs_1_name: 'IAN Symbol Libraries',
|
||||
imgLibs_1_description: 'Free library of illustrations'
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,4 +13,4 @@ export default {
|
||||
imgLibs_0_description: 'Demonstration library for SVG-edit on this server',
|
||||
imgLibs_1_name: 'IAN Symbol Libraries',
|
||||
imgLibs_1_description: 'Free library of illustrations'
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,4 +13,4 @@ export default {
|
||||
imgLibs_0_description: 'Demonstration library for SVG-edit on this server',
|
||||
imgLibs_1_name: 'IAN Symbol Libraries',
|
||||
imgLibs_1_description: 'Free library of illustrations'
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,4 +13,4 @@ export default {
|
||||
imgLibs_0_description: 'Demonstration library for SVG-edit on this server',
|
||||
imgLibs_1_name: 'IAN Symbol Libraries',
|
||||
imgLibs_1_description: 'Free library of illustrations'
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,4 +13,4 @@ export default {
|
||||
imgLibs_0_description: 'Demonstration library for SVG-edit on this server',
|
||||
imgLibs_1_name: 'IAN Symbol Libraries',
|
||||
imgLibs_1_description: 'Free library of illustrations'
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,4 +13,4 @@ export default {
|
||||
imgLibs_0_description: 'Demonstration library for SVG-edit on this server',
|
||||
imgLibs_1_name: 'IAN Symbol Libraries',
|
||||
imgLibs_1_description: 'Free library of illustrations'
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,4 +13,4 @@ export default {
|
||||
imgLibs_0_description: 'Demonstration library for SVG-edit on this server',
|
||||
imgLibs_1_name: 'IAN Symbol Libraries',
|
||||
imgLibs_1_description: 'Free library of illustrations'
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/* eslint-disable node/no-unpublished-import */
|
||||
import { jml, body, nbsp } from 'jamilih';
|
||||
import $ from 'query-result';
|
||||
import { manipulation } from 'qr-manipulation';
|
||||
import { jml, body, nbsp } from 'jamilih'
|
||||
import $ from 'query-result'
|
||||
import { manipulation } from 'qr-manipulation'
|
||||
|
||||
manipulation($, jml);
|
||||
manipulation($, jml)
|
||||
|
||||
const baseAPIURL = 'https://openclipart.org/search/json/';
|
||||
const baseAPIURL = 'https://openclipart.org/search/json/'
|
||||
|
||||
const jsVoid = 'javascript: void(0);';
|
||||
const jsVoid = 'javascript: void(0);'
|
||||
|
||||
/**
|
||||
* Shows results after query submission.
|
||||
@@ -20,31 +20,35 @@ async function processResults (url) {
|
||||
* @returns {external:JamilihArray}
|
||||
*/
|
||||
function queryLink (query) {
|
||||
return [ 'a', {
|
||||
return ['a', {
|
||||
href: jsVoid,
|
||||
dataset: { value: query },
|
||||
$on: { click (e) {
|
||||
e.preventDefault();
|
||||
const { value } = this.dataset;
|
||||
$('#query')[0].$set(value);
|
||||
$('#openclipart')[0].$submit();
|
||||
} }
|
||||
}, [ query ] ];
|
||||
$on: {
|
||||
click (e) {
|
||||
e.preventDefault()
|
||||
const { value } = this.dataset
|
||||
$('#query')[0].$set(value)
|
||||
$('#openclipart')[0].$submit()
|
||||
}
|
||||
}
|
||||
}, [query]]
|
||||
}
|
||||
|
||||
const r = await fetch(url);
|
||||
const json = await r.json();
|
||||
const r = await fetch(url)
|
||||
const json = await r.json()
|
||||
|
||||
if (!json || json.msg !== 'success') {
|
||||
// Todo: This could use a generic alert library instead
|
||||
alert('There was a problem downloading the results');
|
||||
return;
|
||||
alert('There was a problem downloading the results')
|
||||
return
|
||||
}
|
||||
const { payload, info: {
|
||||
results: numResults,
|
||||
pages,
|
||||
current_page: currentPage
|
||||
} } = json;
|
||||
const {
|
||||
payload, info: {
|
||||
results: numResults,
|
||||
pages,
|
||||
current_page: currentPage
|
||||
}
|
||||
} = json
|
||||
|
||||
// $('#page')[0].value = currentPage;
|
||||
// $('#page')[0].max = pages;
|
||||
@@ -57,19 +61,19 @@ async function processResults (url) {
|
||||
// }` object of relevance?
|
||||
// - No need for `tags` with `tags_array`
|
||||
// - `svg`'s: `png_thumb`, `png_full_lossy`, `png_2400px`
|
||||
const semiColonSep = '; ' + nbsp;
|
||||
const semiColonSep = '; ' + nbsp
|
||||
$('#results').jml('div', [
|
||||
[ 'span', [
|
||||
['span', [
|
||||
'Number of results: ',
|
||||
numResults
|
||||
] ],
|
||||
]],
|
||||
semiColonSep,
|
||||
[ 'span', [
|
||||
['span', [
|
||||
'page ',
|
||||
currentPage,
|
||||
' out of ',
|
||||
pages
|
||||
] ],
|
||||
]],
|
||||
...payload.map(({
|
||||
title, description, id,
|
||||
uploader, created,
|
||||
@@ -79,170 +83,174 @@ async function processResults (url) {
|
||||
downloaded_by: downloadedBy,
|
||||
total_favorites: totalFavorites
|
||||
}) => {
|
||||
const imgHW = '100px';
|
||||
const colonSep = ': ' + nbsp;
|
||||
return [ 'div', [
|
||||
[ 'button', { style: 'margin-right: 8px; border: 2px solid black;', dataset: { id, value: svgURL }, $on: {
|
||||
async click (e) {
|
||||
e.preventDefault();
|
||||
const { value: svgurl } = this.dataset;
|
||||
const post = (message) => {
|
||||
const imgHW = '100px'
|
||||
const colonSep = ': ' + nbsp
|
||||
return ['div', [
|
||||
['button', {
|
||||
style: 'margin-right: 8px; border: 2px solid black;',
|
||||
dataset: { id, value: svgURL },
|
||||
$on: {
|
||||
async click (e) {
|
||||
e.preventDefault()
|
||||
const { value: svgurl } = this.dataset
|
||||
const post = (message) => {
|
||||
// Todo: Make origin customizable as set by opening window
|
||||
// Todo: If dropping IE9, avoid stringifying
|
||||
window.parent.postMessage(JSON.stringify({
|
||||
namespace: 'imagelib',
|
||||
...message
|
||||
}), '*');
|
||||
};
|
||||
// Send metadata (also indicates file is about to be sent)
|
||||
post({
|
||||
name: title,
|
||||
id: svgurl
|
||||
});
|
||||
const result = await fetch(svgurl);
|
||||
const svg = await result.text();
|
||||
post({
|
||||
href: svgurl,
|
||||
data: svg
|
||||
});
|
||||
window.parent.postMessage(JSON.stringify({
|
||||
namespace: 'imagelib',
|
||||
...message
|
||||
}), '*')
|
||||
}
|
||||
// Send metadata (also indicates file is about to be sent)
|
||||
post({
|
||||
name: title,
|
||||
id: svgurl
|
||||
})
|
||||
const result = await fetch(svgurl)
|
||||
const svg = await result.text()
|
||||
post({
|
||||
href: svgurl,
|
||||
data: svg
|
||||
})
|
||||
}
|
||||
}
|
||||
} }, [
|
||||
}, [
|
||||
// If we wanted interactive versions despite security risk:
|
||||
// ['object', {data: svgURL, type: 'image/svg+xml'}]
|
||||
[ 'img', { src: svgURL, style: `width: ${imgHW}; height: ${imgHW};` } ]
|
||||
] ],
|
||||
[ 'b', [ title ] ],
|
||||
['img', { src: svgURL, style: `width: ${imgHW}; height: ${imgHW};` }]
|
||||
]],
|
||||
['b', [title]],
|
||||
' ',
|
||||
[ 'i', [ description ] ],
|
||||
['i', [description]],
|
||||
' ',
|
||||
[ 'span', [
|
||||
['span', [
|
||||
'(ID: ',
|
||||
[ 'a', {
|
||||
['a', {
|
||||
href: jsVoid,
|
||||
dataset: { value: id },
|
||||
$on: {
|
||||
click (e) {
|
||||
e.preventDefault();
|
||||
const { value } = this.dataset;
|
||||
$('#byids')[0].$set(value);
|
||||
$('#openclipart')[0].$submit();
|
||||
e.preventDefault()
|
||||
const { value } = this.dataset
|
||||
$('#byids')[0].$set(value)
|
||||
$('#openclipart')[0].$submit()
|
||||
}
|
||||
}
|
||||
}, [ id ] ],
|
||||
}, [id]],
|
||||
')'
|
||||
] ],
|
||||
]],
|
||||
' ',
|
||||
[ 'i', [
|
||||
[ 'a', {
|
||||
['i', [
|
||||
['a', {
|
||||
href: detailLink,
|
||||
target: '_blank'
|
||||
}, [ 'Details' ] ]
|
||||
] ],
|
||||
[ 'br' ],
|
||||
[ 'span', [
|
||||
[ 'u', [ 'Uploaded by' ] ], colonSep,
|
||||
}, ['Details']]
|
||||
]],
|
||||
['br'],
|
||||
['span', [
|
||||
['u', ['Uploaded by']], colonSep,
|
||||
queryLink(uploader),
|
||||
semiColonSep
|
||||
] ],
|
||||
[ 'span', [
|
||||
[ 'u', [ 'Download count' ] ], colonSep,
|
||||
]],
|
||||
['span', [
|
||||
['u', ['Download count']], colonSep,
|
||||
downloadedBy,
|
||||
semiColonSep
|
||||
] ],
|
||||
[ 'span', [
|
||||
[ 'u', [ 'Times used as favorite' ] ], colonSep,
|
||||
]],
|
||||
['span', [
|
||||
['u', ['Times used as favorite']], colonSep,
|
||||
totalFavorites,
|
||||
semiColonSep
|
||||
] ],
|
||||
[ 'span', [
|
||||
[ 'u', [ 'Created date' ] ], colonSep,
|
||||
]],
|
||||
['span', [
|
||||
['u', ['Created date']], colonSep,
|
||||
created
|
||||
] ],
|
||||
[ 'br' ],
|
||||
[ 'u', [ 'Tags' ] ], colonSep,
|
||||
]],
|
||||
['br'],
|
||||
['u', ['Tags']], colonSep,
|
||||
...tagsArray.map((tag) => {
|
||||
return [ 'span', [
|
||||
return ['span', [
|
||||
' ',
|
||||
queryLink(tag)
|
||||
] ];
|
||||
]]
|
||||
})
|
||||
] ];
|
||||
]]
|
||||
}),
|
||||
[ 'br' ], [ 'br' ],
|
||||
['br'], ['br'],
|
||||
(currentPage === 1 || pages <= 2
|
||||
? ''
|
||||
: [ 'span', [
|
||||
[ 'a', {
|
||||
href: jsVoid,
|
||||
$on: {
|
||||
click (e) {
|
||||
e.preventDefault();
|
||||
$('#page')[0].value = 1;
|
||||
$('#openclipart')[0].$submit();
|
||||
: ['span', [
|
||||
['a', {
|
||||
href: jsVoid,
|
||||
$on: {
|
||||
click (e) {
|
||||
e.preventDefault()
|
||||
$('#page')[0].value = 1
|
||||
$('#openclipart')[0].$submit()
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [ 'First' ] ],
|
||||
' '
|
||||
] ]
|
||||
}, ['First']],
|
||||
' '
|
||||
]]
|
||||
),
|
||||
(currentPage === 1
|
||||
? ''
|
||||
: [ 'span', [
|
||||
[ 'a', {
|
||||
href: jsVoid,
|
||||
$on: {
|
||||
click (e) {
|
||||
e.preventDefault();
|
||||
$('#page')[0].value = currentPage - 1;
|
||||
$('#openclipart')[0].$submit();
|
||||
: ['span', [
|
||||
['a', {
|
||||
href: jsVoid,
|
||||
$on: {
|
||||
click (e) {
|
||||
e.preventDefault()
|
||||
$('#page')[0].value = currentPage - 1
|
||||
$('#openclipart')[0].$submit()
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [ 'Prev' ] ],
|
||||
' '
|
||||
] ]
|
||||
}, ['Prev']],
|
||||
' '
|
||||
]]
|
||||
),
|
||||
(currentPage === pages
|
||||
? ''
|
||||
: [ 'span', [
|
||||
[ 'a', {
|
||||
href: jsVoid,
|
||||
$on: {
|
||||
click (e) {
|
||||
e.preventDefault();
|
||||
$('#page')[0].value = currentPage + 1;
|
||||
$('#openclipart')[0].$submit();
|
||||
: ['span', [
|
||||
['a', {
|
||||
href: jsVoid,
|
||||
$on: {
|
||||
click (e) {
|
||||
e.preventDefault()
|
||||
$('#page')[0].value = currentPage + 1
|
||||
$('#openclipart')[0].$submit()
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [ 'Next' ] ],
|
||||
' '
|
||||
] ]
|
||||
}, ['Next']],
|
||||
' '
|
||||
]]
|
||||
),
|
||||
(currentPage === pages || pages <= 2
|
||||
? ''
|
||||
: [ 'span', [
|
||||
[ 'a', {
|
||||
href: jsVoid,
|
||||
$on: {
|
||||
click (e) {
|
||||
e.preventDefault();
|
||||
$('#page')[0].value = pages;
|
||||
$('#openclipart')[0].$submit();
|
||||
: ['span', [
|
||||
['a', {
|
||||
href: jsVoid,
|
||||
$on: {
|
||||
click (e) {
|
||||
e.preventDefault()
|
||||
$('#page')[0].value = pages
|
||||
$('#openclipart')[0].$submit()
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [ 'Last' ] ],
|
||||
' '
|
||||
] ]
|
||||
}, ['Last']],
|
||||
' '
|
||||
]]
|
||||
)
|
||||
]);
|
||||
])
|
||||
}
|
||||
|
||||
jml('div', [
|
||||
[ 'style', [
|
||||
['style', [
|
||||
`.control {
|
||||
padding-top: 10px;
|
||||
}`
|
||||
] ],
|
||||
[ 'form', {
|
||||
]],
|
||||
['form', {
|
||||
id: 'openclipart',
|
||||
$custom: {
|
||||
async $submit () {
|
||||
@@ -250,95 +258,120 @@ jml('div', [
|
||||
[
|
||||
'query', 'sort', 'amount', 'page', 'byids'
|
||||
].forEach((prop) => {
|
||||
const { value } = $('#' + prop)[0];
|
||||
const { value } = $('#' + prop)[0]
|
||||
if (value) {
|
||||
url.searchParams.set(prop, value);
|
||||
url.searchParams.set(prop, value)
|
||||
}
|
||||
});
|
||||
await processResults(url);
|
||||
})
|
||||
await processResults(url)
|
||||
}
|
||||
},
|
||||
$on: {
|
||||
submit (e) {
|
||||
e.preventDefault();
|
||||
this.$submit();
|
||||
e.preventDefault()
|
||||
this.$submit()
|
||||
}
|
||||
}
|
||||
}, [
|
||||
// Todo: i18nize
|
||||
[ 'fieldset', [
|
||||
[ 'legend', [ 'Search terms' ] ],
|
||||
[ 'div', { class: 'control' }, [
|
||||
[ 'label', [
|
||||
['fieldset', [
|
||||
['legend', ['Search terms']],
|
||||
['div', { class: 'control' }, [
|
||||
['label', [
|
||||
'Query (Title, description, uploader, or tag): ',
|
||||
[ 'input', { id: 'query', name: 'query', placeholder: 'cat', $custom: {
|
||||
$set (value) {
|
||||
$('#byids')[0].value = '';
|
||||
this.value = value;
|
||||
['input', {
|
||||
id: 'query',
|
||||
name: 'query',
|
||||
placeholder: 'cat',
|
||||
$custom: {
|
||||
$set (value) {
|
||||
$('#byids')[0].value = ''
|
||||
this.value = value
|
||||
}
|
||||
},
|
||||
$on: {
|
||||
change () {
|
||||
$('#byids')[0].value = ''
|
||||
}
|
||||
}
|
||||
}, $on: {
|
||||
change () {
|
||||
$('#byids')[0].value = '';
|
||||
}
|
||||
} } ]
|
||||
] ]
|
||||
] ],
|
||||
[ 'br' ],
|
||||
}]
|
||||
]]
|
||||
]],
|
||||
['br'],
|
||||
' OR ',
|
||||
[ 'br' ],
|
||||
[ 'div', { class: 'control' }, [
|
||||
[ 'label', [
|
||||
['br'],
|
||||
['div', { class: 'control' }, [
|
||||
['label', [
|
||||
'IDs (single or comma-separated): ',
|
||||
[ 'input', { id: 'byids', name: 'ids', placeholder: '271380, 265741', $custom: {
|
||||
$set (value) {
|
||||
$('#query')[0].value = '';
|
||||
this.value = value;
|
||||
['input', {
|
||||
id: 'byids',
|
||||
name: 'ids',
|
||||
placeholder: '271380, 265741',
|
||||
$custom: {
|
||||
$set (value) {
|
||||
$('#query')[0].value = ''
|
||||
this.value = value
|
||||
}
|
||||
},
|
||||
$on: {
|
||||
change () {
|
||||
$('#query')[0].value = ''
|
||||
}
|
||||
}
|
||||
}, $on: {
|
||||
change () {
|
||||
$('#query')[0].value = '';
|
||||
}
|
||||
} } ]
|
||||
] ]
|
||||
] ]
|
||||
] ],
|
||||
[ 'fieldset', [
|
||||
[ 'legend', [ 'Configuring results' ] ],
|
||||
[ 'div', { class: 'control' }, [
|
||||
[ 'label', [
|
||||
}]
|
||||
]]
|
||||
]]
|
||||
]],
|
||||
['fieldset', [
|
||||
['legend', ['Configuring results']],
|
||||
['div', { class: 'control' }, [
|
||||
['label', [
|
||||
'Sort by: ',
|
||||
[ 'select', { id: 'sort' }, [
|
||||
['select', { id: 'sort' }, [
|
||||
// Todo: i18nize first values
|
||||
[ 'Date', 'date' ],
|
||||
[ 'Downloads', 'downloads' ],
|
||||
[ 'Favorited', 'favorites' ]
|
||||
].map(([ text, value = text ]) => {
|
||||
return [ 'option', { value }, [ text ] ];
|
||||
}) ]
|
||||
] ]
|
||||
] ],
|
||||
[ 'div', { class: 'control' }, [
|
||||
[ 'label', [
|
||||
['Date', 'date'],
|
||||
['Downloads', 'downloads'],
|
||||
['Favorited', 'favorites']
|
||||
].map(([text, value = text]) => {
|
||||
return ['option', { value }, [text]]
|
||||
})]
|
||||
]]
|
||||
]],
|
||||
['div', { class: 'control' }, [
|
||||
['label', [
|
||||
'Results per page: ',
|
||||
[ 'input', {
|
||||
id: 'amount', name: 'amount', value: 10,
|
||||
type: 'number', min: 1, max: 200, step: 1, pattern: '\\d+' } ]
|
||||
] ]
|
||||
] ],
|
||||
[ 'div', { class: 'control' }, [
|
||||
[ 'label', [
|
||||
['input', {
|
||||
id: 'amount',
|
||||
name: 'amount',
|
||||
value: 10,
|
||||
type: 'number',
|
||||
min: 1,
|
||||
max: 200,
|
||||
step: 1,
|
||||
pattern: '\\d+'
|
||||
}]
|
||||
]]
|
||||
]],
|
||||
['div', { class: 'control' }, [
|
||||
['label', [
|
||||
'Page number: ',
|
||||
[ 'input', {
|
||||
['input', {
|
||||
// max: 1, // We'll change this based on available results
|
||||
id: 'page', name: 'page', value: 1, style: 'width: 40px;',
|
||||
type: 'number', min: 1, step: 1, pattern: '\\d+'
|
||||
} ]
|
||||
] ]
|
||||
] ]
|
||||
] ],
|
||||
[ 'div', { class: 'control' }, [
|
||||
[ 'input', { type: 'submit' } ]
|
||||
] ]
|
||||
] ],
|
||||
[ 'div', { id: 'results' } ]
|
||||
], body);
|
||||
id: 'page',
|
||||
name: 'page',
|
||||
value: 1,
|
||||
style: 'width: 40px;',
|
||||
type: 'number',
|
||||
min: 1,
|
||||
step: 1,
|
||||
pattern: '\\d+'
|
||||
}]
|
||||
]]
|
||||
]]
|
||||
]],
|
||||
['div', { class: 'control' }, [
|
||||
['input', { type: 'submit' }]
|
||||
]]
|
||||
]],
|
||||
['div', { id: 'results' }]
|
||||
], body)
|
||||
|
||||
@@ -30,12 +30,12 @@
|
||||
export default {
|
||||
name: 'markers',
|
||||
async init () {
|
||||
const svgEditor = this;
|
||||
const { svgCanvas } = svgEditor;
|
||||
const { BatchCommand, RemoveElementCommand, InsertElementCommand } = svgCanvas.history;
|
||||
const { $id, addSVGElemensFromJson: addElem } = svgCanvas;
|
||||
const mtypes = [ 'start', 'mid', 'end' ];
|
||||
const markerElems = [ 'line', 'path', 'polyline', 'polygon' ];
|
||||
const svgEditor = this
|
||||
const { svgCanvas } = svgEditor
|
||||
const { BatchCommand, RemoveElementCommand, InsertElementCommand } = svgCanvas.history
|
||||
const { $id, addSVGElemensFromJson: addElem } = svgCanvas
|
||||
const mtypes = ['start', 'mid', 'end']
|
||||
const markerElems = ['line', 'path', 'polyline', 'polygon']
|
||||
|
||||
// note - to add additional marker types add them below with a unique id
|
||||
// and add the associated icon(s) to marker-icons.svg
|
||||
@@ -55,25 +55,25 @@ export default {
|
||||
};
|
||||
|
||||
// duplicate shapes to support unfilled (open) marker types with an _o suffix
|
||||
[ 'leftarrow', 'rightarrow', 'box', 'mcircle' ].forEach((v) => {
|
||||
markerTypes[v + '_o'] = markerTypes[v];
|
||||
});
|
||||
['leftarrow', 'rightarrow', 'box', 'mcircle'].forEach((v) => {
|
||||
markerTypes[v + '_o'] = markerTypes[v]
|
||||
})
|
||||
|
||||
/**
|
||||
* @param {Element} elem - A graphic element will have an attribute like marker-start
|
||||
* @param {"marker-start"|"marker-mid"|"marker-end"} attr
|
||||
* @returns {Element} The marker element that is linked to the graphic element
|
||||
*/
|
||||
const getLinked = (elem, attr) => {
|
||||
const str = elem.getAttribute(attr);
|
||||
if (!str) { return null; }
|
||||
const m = str.match(/\(#(.*)\)/);
|
||||
const getLinked = (elem, attr) => {
|
||||
const str = elem.getAttribute(attr)
|
||||
if (!str) { return null }
|
||||
const m = str.match(/\(#(.*)\)/)
|
||||
// "url(#mkr_end_svg_1)" would give m[1] = "mkr_end_svg_1"
|
||||
if (!m || m.length !== 2) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
return svgCanvas.getElem(m[1]);
|
||||
};
|
||||
return svgCanvas.getElem(m[1])
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles context tool panel off/on.
|
||||
@@ -81,18 +81,18 @@ export default {
|
||||
* @returns {void}
|
||||
*/
|
||||
const showPanel = (on, elem) => {
|
||||
$id('marker_panel').style.display = (on) ? 'block' : 'none';
|
||||
$id('marker_panel').style.display = (on) ? 'block' : 'none'
|
||||
if (on && elem) {
|
||||
mtypes.forEach((pos) => {
|
||||
const marker = getLinked(elem, 'marker-' + pos);
|
||||
const marker = getLinked(elem, 'marker-' + pos)
|
||||
if (marker?.attributes?.se_type) {
|
||||
$id(`${pos}_marker_list_opts`).setAttribute('value', marker.attributes.se_type.value);
|
||||
$id(`${pos}_marker_list_opts`).setAttribute('value', marker.attributes.se_type.value)
|
||||
} else {
|
||||
$id(`${pos}_marker_list_opts`).setAttribute('value', 'nomarker');
|
||||
$id(`${pos}_marker_list_opts`).setAttribute('value', 'nomarker')
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} id
|
||||
@@ -100,22 +100,22 @@ export default {
|
||||
* @returns {SVGMarkerElement}
|
||||
*/
|
||||
const addMarker = (id, seType) => {
|
||||
const selElems = svgCanvas.getSelectedElements();
|
||||
let marker = svgCanvas.getElem(id);
|
||||
if (marker) { return undefined; }
|
||||
if (seType === '' || seType === 'nomarker') { return undefined; }
|
||||
const el = selElems[0];
|
||||
const color = el.getAttribute('stroke');
|
||||
const strokeWidth = 10;
|
||||
const refX = 50;
|
||||
const refY = 50;
|
||||
const viewBox = '0 0 100 100';
|
||||
const markerWidth = 5;
|
||||
const markerHeight = 5;
|
||||
const selElems = svgCanvas.getSelectedElements()
|
||||
let marker = svgCanvas.getElem(id)
|
||||
if (marker) { return undefined }
|
||||
if (seType === '' || seType === 'nomarker') { return undefined }
|
||||
const el = selElems[0]
|
||||
const color = el.getAttribute('stroke')
|
||||
const strokeWidth = 10
|
||||
const refX = 50
|
||||
const refY = 50
|
||||
const viewBox = '0 0 100 100'
|
||||
const markerWidth = 5
|
||||
const markerHeight = 5
|
||||
|
||||
if (!markerTypes[seType]) {
|
||||
console.error(`unknown marker type: ${seType}`);
|
||||
return undefined;
|
||||
console.error(`unknown marker type: ${seType}`)
|
||||
return undefined
|
||||
}
|
||||
|
||||
// create a generic marker
|
||||
@@ -128,27 +128,27 @@ export default {
|
||||
style: 'pointer-events:none',
|
||||
se_type: seType
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
const mel = addElem(markerTypes[seType]);
|
||||
const mel = addElem(markerTypes[seType])
|
||||
const fillcolor = (seType.substr(-2) === '_o')
|
||||
? 'none'
|
||||
: color;
|
||||
: color
|
||||
|
||||
mel.setAttribute('fill', fillcolor);
|
||||
mel.setAttribute('stroke', color);
|
||||
mel.setAttribute('stroke-width', strokeWidth);
|
||||
marker.append(mel);
|
||||
mel.setAttribute('fill', fillcolor)
|
||||
mel.setAttribute('stroke', color)
|
||||
mel.setAttribute('stroke-width', strokeWidth)
|
||||
marker.append(mel)
|
||||
|
||||
marker.setAttribute('viewBox', viewBox);
|
||||
marker.setAttribute('markerWidth', markerWidth);
|
||||
marker.setAttribute('markerHeight', markerHeight);
|
||||
marker.setAttribute('refX', refX);
|
||||
marker.setAttribute('refY', refY);
|
||||
svgCanvas.findDefs().append(marker);
|
||||
marker.setAttribute('viewBox', viewBox)
|
||||
marker.setAttribute('markerWidth', markerWidth)
|
||||
marker.setAttribute('markerHeight', markerHeight)
|
||||
marker.setAttribute('refX', refX)
|
||||
marker.setAttribute('refY', refY)
|
||||
svgCanvas.findDefs().append(marker)
|
||||
|
||||
return marker;
|
||||
};
|
||||
return marker
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} elem
|
||||
@@ -157,16 +157,16 @@ export default {
|
||||
const convertline = (elem) => {
|
||||
// this routine came from the connectors extension
|
||||
// it is needed because midpoint markers don't work with line elements
|
||||
if (elem.tagName !== 'line') { return elem; }
|
||||
if (elem.tagName !== 'line') { return elem }
|
||||
|
||||
// Convert to polyline to accept mid-arrow
|
||||
const x1 = Number(elem.getAttribute('x1'));
|
||||
const x2 = Number(elem.getAttribute('x2'));
|
||||
const y1 = Number(elem.getAttribute('y1'));
|
||||
const y2 = Number(elem.getAttribute('y2'));
|
||||
const { id } = elem;
|
||||
const x1 = Number(elem.getAttribute('x1'))
|
||||
const x2 = Number(elem.getAttribute('x2'))
|
||||
const y1 = Number(elem.getAttribute('y1'))
|
||||
const y2 = Number(elem.getAttribute('y2'))
|
||||
const { id } = elem
|
||||
|
||||
const midPt = (' ' + ((x1 + x2) / 2) + ',' + ((y1 + y2) / 2) + ' ');
|
||||
const midPt = (' ' + ((x1 + x2) / 2) + ',' + ((y1 + y2) / 2) + ' ')
|
||||
const pline = addElem({
|
||||
element: 'polyline',
|
||||
attr: {
|
||||
@@ -176,53 +176,53 @@ export default {
|
||||
fill: 'none',
|
||||
opacity: elem.getAttribute('opacity') || 1
|
||||
}
|
||||
});
|
||||
})
|
||||
mtypes.forEach((pos) => { // get any existing marker definitions
|
||||
const nam = 'marker-' + pos;
|
||||
const m = elem.getAttribute(nam);
|
||||
if (m) { pline.setAttribute(nam, elem.getAttribute(nam)); }
|
||||
});
|
||||
const nam = 'marker-' + pos
|
||||
const m = elem.getAttribute(nam)
|
||||
if (m) { pline.setAttribute(nam, elem.getAttribute(nam)) }
|
||||
})
|
||||
|
||||
const batchCmd = new BatchCommand();
|
||||
batchCmd.addSubCommand(new RemoveElementCommand(elem, elem.parentNode));
|
||||
batchCmd.addSubCommand(new InsertElementCommand(pline));
|
||||
const batchCmd = new BatchCommand()
|
||||
batchCmd.addSubCommand(new RemoveElementCommand(elem, elem.parentNode))
|
||||
batchCmd.addSubCommand(new InsertElementCommand(pline))
|
||||
|
||||
elem.insertAdjacentElement('afterend', pline);
|
||||
elem.remove();
|
||||
svgCanvas.clearSelection();
|
||||
pline.id = id;
|
||||
svgCanvas.addToSelection([ pline ]);
|
||||
svgCanvas.addCommandToHistory(batchCmd);
|
||||
return pline;
|
||||
};
|
||||
elem.insertAdjacentElement('afterend', pline)
|
||||
elem.remove()
|
||||
svgCanvas.clearSelection()
|
||||
pline.id = id
|
||||
svgCanvas.addToSelection([pline])
|
||||
svgCanvas.addCommandToHistory(batchCmd)
|
||||
return pline
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
const setMarker = (pos, markerType) => {
|
||||
const selElems = svgCanvas.getSelectedElements();
|
||||
if (selElems.length === 0) return;
|
||||
const markerName = 'marker-' + pos;
|
||||
const el = selElems[0];
|
||||
const marker = getLinked(el, markerName);
|
||||
if (marker) { marker.remove(); }
|
||||
el.removeAttribute(markerName);
|
||||
let val = markerType;
|
||||
if (val === '') { val = 'nomarker'; }
|
||||
const selElems = svgCanvas.getSelectedElements()
|
||||
if (selElems.length === 0) return
|
||||
const markerName = 'marker-' + pos
|
||||
const el = selElems[0]
|
||||
const marker = getLinked(el, markerName)
|
||||
if (marker) { marker.remove() }
|
||||
el.removeAttribute(markerName)
|
||||
let val = markerType
|
||||
if (val === '') { val = 'nomarker' }
|
||||
if (val === 'nomarker') {
|
||||
svgCanvas.call('changed', selElems);
|
||||
return;
|
||||
svgCanvas.call('changed', selElems)
|
||||
return
|
||||
}
|
||||
// Set marker on element
|
||||
const id = 'mkr_' + pos + '_' + el.id;
|
||||
addMarker(id, val);
|
||||
svgCanvas.changeSelectedAttribute(markerName, 'url(#' + id + ')');
|
||||
const id = 'mkr_' + pos + '_' + el.id
|
||||
addMarker(id, val)
|
||||
svgCanvas.changeSelectedAttribute(markerName, 'url(#' + id + ')')
|
||||
if (el.tagName === 'line' && pos === 'mid') {
|
||||
convertline(el);
|
||||
convertline(el)
|
||||
}
|
||||
svgCanvas.call('changed', selElems);
|
||||
};
|
||||
svgCanvas.call('changed', selElems)
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the main system modifies an object. This routine changes
|
||||
@@ -231,20 +231,20 @@ export default {
|
||||
* @returns {void}
|
||||
*/
|
||||
const colorChanged = (elem) => {
|
||||
const color = elem.getAttribute('stroke');
|
||||
const color = elem.getAttribute('stroke')
|
||||
|
||||
mtypes.forEach((pos) => {
|
||||
const marker = getLinked(elem, 'marker-' + pos);
|
||||
if (!marker) { return; }
|
||||
if (!marker.attributes.se_type) { return; } // not created by this extension
|
||||
const ch = marker.lastElementChild;
|
||||
if (!ch) { return; }
|
||||
const curfill = ch.getAttribute('fill');
|
||||
const curstroke = ch.getAttribute('stroke');
|
||||
if (curfill && curfill !== 'none') { ch.setAttribute('fill', color); }
|
||||
if (curstroke && curstroke !== 'none') { ch.setAttribute('stroke', color); }
|
||||
});
|
||||
};
|
||||
const marker = getLinked(elem, 'marker-' + pos)
|
||||
if (!marker) { return }
|
||||
if (!marker.attributes.se_type) { return } // not created by this extension
|
||||
const ch = marker.lastElementChild
|
||||
if (!ch) { return }
|
||||
const curfill = ch.getAttribute('fill')
|
||||
const curstroke = ch.getAttribute('stroke')
|
||||
if (curfill && curfill !== 'none') { ch.setAttribute('fill', color) }
|
||||
if (curstroke && curstroke !== 'none') { ch.setAttribute('stroke', color) }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the main system creates or modifies an object.
|
||||
@@ -253,78 +253,77 @@ export default {
|
||||
* @returns {void}
|
||||
*/
|
||||
const updateReferences = (el) => {
|
||||
const selElems = svgCanvas.getSelectedElements();
|
||||
const selElems = svgCanvas.getSelectedElements()
|
||||
mtypes.forEach((pos) => {
|
||||
const markerName = 'marker-' + pos;
|
||||
const marker = getLinked(el, markerName);
|
||||
if (!marker || !marker.attributes.se_type) { return; } // not created by this extension
|
||||
const url = el.getAttribute(markerName);
|
||||
const markerName = 'marker-' + pos
|
||||
const marker = getLinked(el, markerName)
|
||||
if (!marker || !marker.attributes.se_type) { return } // not created by this extension
|
||||
const url = el.getAttribute(markerName)
|
||||
if (url) {
|
||||
const len = el.id.length;
|
||||
const linkid = url.substr(-len - 1, len);
|
||||
const len = el.id.length
|
||||
const linkid = url.substr(-len - 1, len)
|
||||
if (el.id !== linkid) {
|
||||
const newMarkerId = 'mkr_' + pos + '_' + el.id;
|
||||
addMarker(newMarkerId, marker.attributes.se_type.value);
|
||||
svgCanvas.changeSelectedAttribute(markerName, 'url(#' + newMarkerId + ')');
|
||||
svgCanvas.call('changed', selElems);
|
||||
const newMarkerId = 'mkr_' + pos + '_' + el.id
|
||||
addMarker(newMarkerId, marker.attributes.se_type.value)
|
||||
svgCanvas.changeSelectedAttribute(markerName, 'url(#' + newMarkerId + ')')
|
||||
svgCanvas.call('changed', selElems)
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
name: svgEditor.i18next.t(`${name}:name`),
|
||||
// The callback should be used to load the DOM with the appropriate UI items
|
||||
callback() {
|
||||
callback () {
|
||||
// Add the context panel and its handler(s)
|
||||
const panelTemplate = document.createElement("template");
|
||||
const panelTemplate = document.createElement('template')
|
||||
// create the marker panel
|
||||
let innerHTML = '<div id="marker_panel">';
|
||||
let innerHTML = '<div id="marker_panel">'
|
||||
mtypes.forEach((pos) => {
|
||||
innerHTML += `<se-list id="${pos}_marker_list_opts" title="tools.${pos}_marker_list_opts" label="" width="22px" height="22px">`;
|
||||
Object.entries(markerTypes).forEach(([ marker, _mkr ]) => {
|
||||
innerHTML += `<se-list-item id="mkr_${pos}_${marker}" value="${marker}" title="tools.mkr_${marker}" src="${marker}.svg" img-height="22px"></se-list-item>`;
|
||||
});
|
||||
innerHTML += '</se-list>';
|
||||
});
|
||||
innerHTML += '</div>';
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
panelTemplate.innerHTML = innerHTML;
|
||||
$id("tools_top").appendChild(panelTemplate.content.cloneNode(true));
|
||||
innerHTML += `<se-list id="${pos}_marker_list_opts" title="tools.${pos}_marker_list_opts" label="" width="22px" height="22px">`
|
||||
Object.entries(markerTypes).forEach(([marker, _mkr]) => {
|
||||
innerHTML += `<se-list-item id="mkr_${pos}_${marker}" value="${marker}" title="tools.mkr_${marker}" src="${marker}.svg" img-height="22px"></se-list-item>`
|
||||
})
|
||||
innerHTML += '</se-list>'
|
||||
})
|
||||
innerHTML += '</div>'
|
||||
panelTemplate.innerHTML = innerHTML
|
||||
$id('tools_top').appendChild(panelTemplate.content.cloneNode(true))
|
||||
// don't display the panels on start
|
||||
showPanel(false);
|
||||
showPanel(false)
|
||||
mtypes.forEach((pos) => {
|
||||
$id(`${pos}_marker_list_opts`).addEventListener('change', (evt) => {
|
||||
setMarker(pos, evt.detail.value);
|
||||
});
|
||||
});
|
||||
setMarker(pos, evt.detail.value)
|
||||
})
|
||||
})
|
||||
},
|
||||
selectedChanged (opts) {
|
||||
// Use this to update the current selected elements
|
||||
if (opts.elems.length === 0) showPanel(false);
|
||||
opts.elems.forEach( (elem) => {
|
||||
if (opts.elems.length === 0) showPanel(false)
|
||||
opts.elems.forEach((elem) => {
|
||||
if (elem && markerElems.includes(elem.tagName)) {
|
||||
if (opts.selectedElement && !opts.multiselected) {
|
||||
showPanel(true, elem);
|
||||
showPanel(true, elem)
|
||||
} else {
|
||||
showPanel(false);
|
||||
showPanel(false)
|
||||
}
|
||||
} else {
|
||||
showPanel(false);
|
||||
showPanel(false)
|
||||
}
|
||||
});
|
||||
})
|
||||
},
|
||||
elementChanged (opts) {
|
||||
const elem = opts.elems[0];
|
||||
const elem = opts.elems[0]
|
||||
if (elem && (
|
||||
elem.getAttribute('marker-start') ||
|
||||
elem.getAttribute('marker-mid') ||
|
||||
elem.getAttribute('marker-end')
|
||||
)) {
|
||||
colorChanged(elem);
|
||||
updateReferences(elem);
|
||||
colorChanged(elem)
|
||||
updateReferences(elem)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -43,4 +43,4 @@ export default {
|
||||
title: 'Select end marker type'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -43,4 +43,4 @@ export default {
|
||||
title: '选择末端标记类型'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,66 +15,65 @@
|
||||
* @listens module:svgcanvas.SvgCanvas#event:saved
|
||||
* @returns {void}
|
||||
*/
|
||||
import { fileOpen, fileSave } from 'browser-fs-access';
|
||||
import { fileOpen, fileSave } from 'browser-fs-access'
|
||||
|
||||
const name = "opensave";
|
||||
let handle = null;
|
||||
const name = 'opensave'
|
||||
let handle = null
|
||||
|
||||
const loadExtensionTranslation = async function (svgEditor) {
|
||||
let translationModule;
|
||||
const lang = svgEditor.configObj.pref('lang');
|
||||
let translationModule
|
||||
const lang = svgEditor.configObj.pref('lang')
|
||||
try {
|
||||
// eslint-disable-next-line no-unsanitized/method
|
||||
translationModule = await import(`./locale/${lang}.js`);
|
||||
translationModule = await import(`./locale/${lang}.js`)
|
||||
} catch (_error) {
|
||||
console.warn(`Missing translation (${lang}) for ${name} - using 'en'`);
|
||||
translationModule = await import(`./locale/en.js`);
|
||||
console.warn(`Missing translation (${lang}) for ${name} - using 'en'`)
|
||||
translationModule = await import('./locale/en.js')
|
||||
}
|
||||
svgEditor.i18next.addResourceBundle(lang, 'translation', translationModule.default, true, true);
|
||||
};
|
||||
svgEditor.i18next.addResourceBundle(lang, 'translation', translationModule.default, true, true)
|
||||
}
|
||||
|
||||
export default {
|
||||
name,
|
||||
async init(_S) {
|
||||
const svgEditor = this;
|
||||
const { svgCanvas } = svgEditor;
|
||||
const { $id } = svgCanvas;
|
||||
await loadExtensionTranslation(svgEditor);
|
||||
async init (_S) {
|
||||
const svgEditor = this
|
||||
const { svgCanvas } = svgEditor
|
||||
const { $id } = svgCanvas
|
||||
await loadExtensionTranslation(svgEditor)
|
||||
/**
|
||||
* @param {Event} e
|
||||
* @returns {void}
|
||||
*/
|
||||
const importImage = (e) => {
|
||||
$id('se-prompt-dialog').title = this.i18next.t('notification.loadingImage');
|
||||
$id('se-prompt-dialog').setAttribute('close', false);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
const file = (e.type === 'drop') ? e.dataTransfer.files[0] : e.currentTarget.files[0];
|
||||
$id('se-prompt-dialog').title = this.i18next.t('notification.loadingImage')
|
||||
$id('se-prompt-dialog').setAttribute('close', false)
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
const file = (e.type === 'drop') ? e.dataTransfer.files[0] : e.currentTarget.files[0]
|
||||
if (!file) {
|
||||
$id('se-prompt-dialog').setAttribute('close', true);
|
||||
return;
|
||||
$id('se-prompt-dialog').setAttribute('close', true)
|
||||
return
|
||||
}
|
||||
|
||||
if (!file.type.includes('image')) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
// Detected an image
|
||||
// svg handling
|
||||
let reader;
|
||||
let reader
|
||||
if (file.type.includes('svg')) {
|
||||
reader = new FileReader();
|
||||
reader.onloadend = (ev) => {
|
||||
const newElement = this.svgCanvas.importSvgString(ev.target.result, true);
|
||||
this.svgCanvas.alignSelectedElements('m', 'page');
|
||||
this.svgCanvas.alignSelectedElements('c', 'page');
|
||||
reader = new FileReader()
|
||||
reader.onloadend = (ev) => {
|
||||
const newElement = this.svgCanvas.importSvgString(ev.target.result, true)
|
||||
this.svgCanvas.alignSelectedElements('m', 'page')
|
||||
this.svgCanvas.alignSelectedElements('c', 'page')
|
||||
// highlight imported element, otherwise we get strange empty selectbox
|
||||
this.svgCanvas.selectOnly([ newElement ]);
|
||||
$id('se-prompt-dialog').setAttribute('close', true);
|
||||
};
|
||||
reader.readAsText(file);
|
||||
this.svgCanvas.selectOnly([newElement])
|
||||
$id('se-prompt-dialog').setAttribute('close', true)
|
||||
}
|
||||
reader.readAsText(file)
|
||||
} else {
|
||||
// bitmap handling
|
||||
reader = new FileReader();
|
||||
reader = new FileReader()
|
||||
reader.onloadend = function ({ target: { result } }) {
|
||||
/**
|
||||
* Insert the new image until we know its dimensions.
|
||||
@@ -93,54 +92,54 @@ export default {
|
||||
id: this.svgCanvas.getNextId(),
|
||||
style: 'pointer-events:inherit'
|
||||
}
|
||||
});
|
||||
this.svgCanvas.setHref(newImage, result);
|
||||
this.svgCanvas.selectOnly([ newImage ]);
|
||||
this.svgCanvas.alignSelectedElements('m', 'page');
|
||||
this.svgCanvas.alignSelectedElements('c', 'page');
|
||||
this.topPanel.updateContextPanel();
|
||||
$id('se-prompt-dialog').setAttribute('close', true);
|
||||
};
|
||||
})
|
||||
this.svgCanvas.setHref(newImage, result)
|
||||
this.svgCanvas.selectOnly([newImage])
|
||||
this.svgCanvas.alignSelectedElements('m', 'page')
|
||||
this.svgCanvas.alignSelectedElements('c', 'page')
|
||||
this.topPanel.updateContextPanel()
|
||||
$id('se-prompt-dialog').setAttribute('close', true)
|
||||
}
|
||||
// create dummy img so we know the default dimensions
|
||||
let imgWidth = 100;
|
||||
let imgHeight = 100;
|
||||
const img = new Image();
|
||||
img.style.opacity = 0;
|
||||
let imgWidth = 100
|
||||
let imgHeight = 100
|
||||
const img = new Image()
|
||||
img.style.opacity = 0
|
||||
img.addEventListener('load', () => {
|
||||
imgWidth = img.offsetWidth || img.naturalWidth || img.width;
|
||||
imgHeight = img.offsetHeight || img.naturalHeight || img.height;
|
||||
insertNewImage(imgWidth, imgHeight);
|
||||
});
|
||||
img.src = result;
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
imgWidth = img.offsetWidth || img.naturalWidth || img.width
|
||||
imgHeight = img.offsetHeight || img.naturalHeight || img.height
|
||||
insertNewImage(imgWidth, imgHeight)
|
||||
})
|
||||
img.src = result
|
||||
}
|
||||
reader.readAsDataURL(file)
|
||||
}
|
||||
};
|
||||
}
|
||||
// create an input with type file to open the filesystem dialog
|
||||
const imgImport = document.createElement('input');
|
||||
imgImport.type="file";
|
||||
imgImport.addEventListener('change', importImage);
|
||||
const imgImport = document.createElement('input')
|
||||
imgImport.type = 'file'
|
||||
imgImport.addEventListener('change', importImage)
|
||||
// dropping a svg file will import it in the svg as well
|
||||
this.workarea.addEventListener('drop', importImage);
|
||||
this.workarea.addEventListener('drop', importImage)
|
||||
/**
|
||||
* @fires module:svgcanvas.SvgCanvas#event:ext_onNewDocument
|
||||
* @returns {void}
|
||||
*/
|
||||
const clickClear = async function () {
|
||||
const [ x, y ] = svgEditor.configObj.curConfig.dimensions;
|
||||
const ok = await seConfirm(svgEditor.i18next.t('notification.QwantToClear'));
|
||||
if (ok === "Cancel") {
|
||||
return;
|
||||
const [x, y] = svgEditor.configObj.curConfig.dimensions
|
||||
const ok = await seConfirm(svgEditor.i18next.t('notification.QwantToClear'))
|
||||
if (ok === 'Cancel') {
|
||||
return
|
||||
}
|
||||
svgEditor.leftPanel.clickSelect();
|
||||
svgEditor.svgCanvas.clear();
|
||||
svgEditor.svgCanvas.setResolution(x, y);
|
||||
svgEditor.updateCanvas(true);
|
||||
svgEditor.zoomImage();
|
||||
svgEditor.layersPanel.populateLayers();
|
||||
svgEditor.topPanel.updateContextPanel();
|
||||
svgEditor.svgCanvas.runExtensions("onNewDocument");
|
||||
};
|
||||
svgEditor.leftPanel.clickSelect()
|
||||
svgEditor.svgCanvas.clear()
|
||||
svgEditor.svgCanvas.setResolution(x, y)
|
||||
svgEditor.updateCanvas(true)
|
||||
svgEditor.zoomImage()
|
||||
svgEditor.layersPanel.populateLayers()
|
||||
svgEditor.topPanel.updateContextPanel()
|
||||
svgEditor.svgCanvas.runExtensions('onNewDocument')
|
||||
}
|
||||
|
||||
/**
|
||||
* By default, this.editor.svgCanvas.open() is a no-op. It is up to an extension
|
||||
@@ -150,113 +149,113 @@ export default {
|
||||
*/
|
||||
const clickOpen = async function () {
|
||||
// ask user before clearing an unsaved SVG
|
||||
const response = await svgEditor.openPrep();
|
||||
if (response === 'Cancel') { return; }
|
||||
svgCanvas.clear();
|
||||
const response = await svgEditor.openPrep()
|
||||
if (response === 'Cancel') { return }
|
||||
svgCanvas.clear()
|
||||
try {
|
||||
const blob = await fileOpen({
|
||||
mimeTypes: [ 'image/*' ]
|
||||
});
|
||||
const svgContent = await blob.text();
|
||||
await svgEditor.loadSvgString(svgContent);
|
||||
svgEditor.updateCanvas();
|
||||
mimeTypes: ['image/*']
|
||||
})
|
||||
const svgContent = await blob.text()
|
||||
await svgEditor.loadSvgString(svgContent)
|
||||
svgEditor.updateCanvas()
|
||||
} catch (err) {
|
||||
if (err.name !== 'AbortError') {
|
||||
return console.error(err);
|
||||
return console.error(err)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const b64toBlob = (b64Data, contentType='', sliceSize=512) => {
|
||||
const byteCharacters = atob(b64Data);
|
||||
const byteArrays = [];
|
||||
const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => {
|
||||
const byteCharacters = atob(b64Data)
|
||||
const byteArrays = []
|
||||
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
|
||||
const slice = byteCharacters.slice(offset, offset + sliceSize);
|
||||
const byteNumbers = new Array(slice.length);
|
||||
const slice = byteCharacters.slice(offset, offset + sliceSize)
|
||||
const byteNumbers = new Array(slice.length)
|
||||
for (let i = 0; i < slice.length; i++) {
|
||||
byteNumbers[i] = slice.charCodeAt(i);
|
||||
byteNumbers[i] = slice.charCodeAt(i)
|
||||
}
|
||||
const byteArray = new Uint8Array(byteNumbers);
|
||||
byteArrays.push(byteArray);
|
||||
const byteArray = new Uint8Array(byteNumbers)
|
||||
byteArrays.push(byteArray)
|
||||
}
|
||||
const blob = new Blob(byteArrays, { type: contentType });
|
||||
return blob;
|
||||
};
|
||||
const blob = new Blob(byteArrays, { type: contentType })
|
||||
return blob
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
const clickSave = async function (type, _) {
|
||||
const $editorDialog = $id("se-svg-editor-dialog");
|
||||
const editingsource = $editorDialog.getAttribute("dialog") === "open";
|
||||
const $editorDialog = $id('se-svg-editor-dialog')
|
||||
const editingsource = $editorDialog.getAttribute('dialog') === 'open'
|
||||
if (editingsource) {
|
||||
svgEditor.saveSourceEditor();
|
||||
svgEditor.saveSourceEditor()
|
||||
} else {
|
||||
// In the future, more options can be provided here
|
||||
const saveOpts = {
|
||||
images: svgEditor.configObj.pref("img_save"),
|
||||
images: svgEditor.configObj.pref('img_save'),
|
||||
round_digits: 6
|
||||
};
|
||||
}
|
||||
// remove the selected outline before serializing
|
||||
svgCanvas.clearSelection();
|
||||
svgCanvas.clearSelection()
|
||||
// Update save options if provided
|
||||
if (saveOpts) {
|
||||
const saveOptions = svgCanvas.mergeDeep(svgCanvas.getSvgOption(), saveOpts);
|
||||
for (const [ key, value ] of Object.entries(saveOptions)) {
|
||||
svgCanvas.setSvgOption(key, value);
|
||||
const saveOptions = svgCanvas.mergeDeep(svgCanvas.getSvgOption(), saveOpts)
|
||||
for (const [key, value] of Object.entries(saveOptions)) {
|
||||
svgCanvas.setSvgOption(key, value)
|
||||
}
|
||||
}
|
||||
svgCanvas.setSvgOption('apply', true);
|
||||
svgCanvas.setSvgOption('apply', true)
|
||||
|
||||
// no need for doctype, see https://jwatt.org/svg/authoring/#doctype-declaration
|
||||
const svg = '<?xml version="1.0"?>\n' + svgCanvas.svgCanvasToString();
|
||||
const b64Data = svgCanvas.encode64(svg);
|
||||
const blob = b64toBlob(b64Data, 'image/svg+xml');
|
||||
const svg = '<?xml version="1.0"?>\n' + svgCanvas.svgCanvasToString()
|
||||
const b64Data = svgCanvas.encode64(svg)
|
||||
const blob = b64toBlob(b64Data, 'image/svg+xml')
|
||||
try {
|
||||
if(type === "save" && handle !== null) {
|
||||
const throwIfExistingHandleNotGood = false;
|
||||
if (type === 'save' && handle !== null) {
|
||||
const throwIfExistingHandleNotGood = false
|
||||
handle = await fileSave(blob, {
|
||||
fileName: 'icon.svg',
|
||||
extensions: [ '.svg' ]
|
||||
}, handle, throwIfExistingHandleNotGood);
|
||||
extensions: ['.svg']
|
||||
}, handle, throwIfExistingHandleNotGood)
|
||||
} else {
|
||||
handle = await fileSave(blob, {
|
||||
fileName: 'icon.svg',
|
||||
extensions: [ '.svg' ]
|
||||
});
|
||||
extensions: ['.svg']
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
if (err.name !== 'AbortError') {
|
||||
return console.error(err);
|
||||
return console.error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
name: svgEditor.i18next.t(`${name}:name`),
|
||||
// The callback should be used to load the DOM with the appropriate UI items
|
||||
callback() {
|
||||
callback () {
|
||||
const buttonTemplate = `
|
||||
<se-menu-item id="tool_clear" label="opensave.new_doc" shortcut="N" src="new.svg"></se-menu-item>`;
|
||||
svgCanvas.insertChildAtIndex($id('main_button'), buttonTemplate, 0);
|
||||
const openButtonTemplate = `<se-menu-item id="tool_open" label="opensave.open_image_doc" src="open.svg"></se-menu-item>`;
|
||||
svgCanvas.insertChildAtIndex($id('main_button'), openButtonTemplate, 1);
|
||||
const saveButtonTemplate = `<se-menu-item id="tool_save" label="opensave.save_doc" shortcut="S" src="saveImg.svg"></se-menu-item>`;
|
||||
svgCanvas.insertChildAtIndex($id('main_button'), saveButtonTemplate, 2);
|
||||
const saveAsButtonTemplate = `<se-menu-item id="tool_save_as" label="opensave.save_as_doc" src="saveImg.svg"></se-menu-item>`;
|
||||
svgCanvas.insertChildAtIndex($id('main_button'), saveAsButtonTemplate, 3);
|
||||
const importButtonTemplate = `<se-menu-item id="tool_import" label="tools.import_doc" src="importImg.svg"></se-menu-item>`;
|
||||
svgCanvas.insertChildAtIndex($id('main_button'), importButtonTemplate, 4);
|
||||
<se-menu-item id="tool_clear" label="opensave.new_doc" shortcut="N" src="new.svg"></se-menu-item>`
|
||||
svgCanvas.insertChildAtIndex($id('main_button'), buttonTemplate, 0)
|
||||
const openButtonTemplate = '<se-menu-item id="tool_open" label="opensave.open_image_doc" src="open.svg"></se-menu-item>'
|
||||
svgCanvas.insertChildAtIndex($id('main_button'), openButtonTemplate, 1)
|
||||
const saveButtonTemplate = '<se-menu-item id="tool_save" label="opensave.save_doc" shortcut="S" src="saveImg.svg"></se-menu-item>'
|
||||
svgCanvas.insertChildAtIndex($id('main_button'), saveButtonTemplate, 2)
|
||||
const saveAsButtonTemplate = '<se-menu-item id="tool_save_as" label="opensave.save_as_doc" src="saveImg.svg"></se-menu-item>'
|
||||
svgCanvas.insertChildAtIndex($id('main_button'), saveAsButtonTemplate, 3)
|
||||
const importButtonTemplate = '<se-menu-item id="tool_import" label="tools.import_doc" src="importImg.svg"></se-menu-item>'
|
||||
svgCanvas.insertChildAtIndex($id('main_button'), importButtonTemplate, 4)
|
||||
|
||||
// handler
|
||||
$id("tool_clear").addEventListener("click", clickClear.bind(this));
|
||||
$id("tool_open").addEventListener("click", clickOpen.bind(this));
|
||||
$id("tool_save").addEventListener("click", clickSave.bind(this, "save"));
|
||||
$id("tool_save_as").addEventListener("click", clickSave.bind(this, "saveas"));
|
||||
$id("tool_import").addEventListener("click", () => imgImport.click());
|
||||
$id('tool_clear').addEventListener('click', clickClear.bind(this))
|
||||
$id('tool_open').addEventListener('click', clickOpen.bind(this))
|
||||
$id('tool_save').addEventListener('click', clickSave.bind(this, 'save'))
|
||||
$id('tool_save_as').addEventListener('click', clickSave.bind(this, 'saveas'))
|
||||
$id('tool_import').addEventListener('click', () => imgImport.click())
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,4 +5,4 @@ export default {
|
||||
save_doc: 'Save SVG',
|
||||
save_as_doc: 'Save as SVG'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,4 +5,4 @@ export default {
|
||||
save_doc: 'Enregistrer l\'image',
|
||||
save_as_doc: 'Enregistrer en tant qu\'image'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,4 +5,4 @@ export default {
|
||||
save_doc: '保存图像',
|
||||
save_as_doc: '另存为图像'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,95 +3,95 @@
|
||||
// MIT License.
|
||||
// can't use npm version as the dragmove is different.
|
||||
|
||||
let _loaded = false;
|
||||
const _callbacks = [];
|
||||
const _isTouch = window.ontouchstart !== undefined;
|
||||
let _loaded = false
|
||||
const _callbacks = []
|
||||
const _isTouch = window.ontouchstart !== undefined
|
||||
|
||||
export const dragmove = function(target, handler, parent, onStart, onEnd, onDrag) {
|
||||
export const dragmove = function (target, handler, parent, onStart, onEnd, onDrag) {
|
||||
// Register a global event to capture mouse moves (once).
|
||||
if (!_loaded) {
|
||||
document.addEventListener(_isTouch ? "touchmove" : "mousemove", function(e) {
|
||||
let c = e;
|
||||
document.addEventListener(_isTouch ? 'touchmove' : 'mousemove', function (e) {
|
||||
let c = e
|
||||
if (e.touches) {
|
||||
c = e.touches[0];
|
||||
c = e.touches[0]
|
||||
}
|
||||
|
||||
// On mouse move, dispatch the coords to all registered callbacks.
|
||||
for (let i = 0; i < _callbacks.length; i++) {
|
||||
_callbacks[i](c.clientX, c.clientY);
|
||||
_callbacks[i](c.clientX, c.clientY)
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
_loaded = true;
|
||||
let isMoving = false; let hasStarted = false;
|
||||
let startX = 0; let startY = 0; let lastX = 0; let lastY = 0;
|
||||
_loaded = true
|
||||
let isMoving = false; let hasStarted = false
|
||||
let startX = 0; let startY = 0; let lastX = 0; let lastY = 0
|
||||
|
||||
// On the first click and hold, record the offset of the pointer in relation
|
||||
// to the point of click inside the element.
|
||||
handler.addEventListener(_isTouch ? "touchstart" : "mousedown", function(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
if (target.dataset.dragEnabled === "false") {
|
||||
return;
|
||||
handler.addEventListener(_isTouch ? 'touchstart' : 'mousedown', function (e) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
if (target.dataset.dragEnabled === 'false') {
|
||||
return
|
||||
}
|
||||
|
||||
let c = e;
|
||||
let c = e
|
||||
if (e.touches) {
|
||||
c = e.touches[0];
|
||||
c = e.touches[0]
|
||||
}
|
||||
|
||||
isMoving = true;
|
||||
startX = target.offsetLeft - c.clientX;
|
||||
startY = target.offsetTop - c.clientY;
|
||||
});
|
||||
isMoving = true
|
||||
startX = target.offsetLeft - c.clientX
|
||||
startY = target.offsetTop - c.clientY
|
||||
})
|
||||
|
||||
// On leaving click, stop moving.
|
||||
document.addEventListener(_isTouch ? "touchend" : "mouseup", function() {
|
||||
document.addEventListener(_isTouch ? 'touchend' : 'mouseup', function () {
|
||||
if (onEnd && hasStarted) {
|
||||
onEnd(target, parent, parseInt(target.style.left), parseInt(target.style.top));
|
||||
onEnd(target, parent, parseInt(target.style.left), parseInt(target.style.top))
|
||||
}
|
||||
|
||||
isMoving = false;
|
||||
hasStarted = false;
|
||||
});
|
||||
isMoving = false
|
||||
hasStarted = false
|
||||
})
|
||||
|
||||
// On leaving click, stop moving.
|
||||
document.addEventListener(_isTouch ? "touchmove" : "mousemove", function() {
|
||||
document.addEventListener(_isTouch ? 'touchmove' : 'mousemove', function () {
|
||||
if (onDrag && hasStarted) {
|
||||
onDrag(target, parseInt(target.style.left), parseInt(target.style.top));
|
||||
onDrag(target, parseInt(target.style.left), parseInt(target.style.top))
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
// Register mouse-move callback to move the element.
|
||||
_callbacks.push(function move(x, y) {
|
||||
_callbacks.push(function move (x, y) {
|
||||
if (!isMoving) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
if (!hasStarted) {
|
||||
hasStarted = true;
|
||||
hasStarted = true
|
||||
if (onStart) {
|
||||
onStart(target, lastX, lastY);
|
||||
onStart(target, lastX, lastY)
|
||||
}
|
||||
}
|
||||
|
||||
lastX = x + startX;
|
||||
lastY = y + startY;
|
||||
lastX = x + startX
|
||||
lastY = y + startY
|
||||
|
||||
// If boundary checking is on, don't let the element cross the viewport.
|
||||
if (target.dataset.dragBoundary === "true") {
|
||||
if (target.dataset.dragBoundary === 'true') {
|
||||
if (lastX < 1 || lastX >= window.innerWidth - target.offsetWidth) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
if (lastY < 1 || lastY >= window.innerHeight - target.offsetHeight) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
target.style.left = lastX + "px";
|
||||
target.style.top = lastY + "px";
|
||||
});
|
||||
};
|
||||
target.style.left = lastX + 'px'
|
||||
target.style.top = lastY + 'px'
|
||||
})
|
||||
}
|
||||
|
||||
export { dragmove as default };
|
||||
export { dragmove as default }
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
* @copyright 2013 James Sacksteder
|
||||
*
|
||||
*/
|
||||
import { dragmove } from './dragmove/dragmove.js';
|
||||
import { dragmove } from './dragmove/dragmove.js'
|
||||
|
||||
export default {
|
||||
name: 'overview_window',
|
||||
init ({ _$ }) {
|
||||
const svgEditor = this;
|
||||
const { $id } = svgEditor.svgCanvas;
|
||||
const overviewWindowGlobals = {};
|
||||
const svgEditor = this
|
||||
const { $id } = svgEditor.svgCanvas
|
||||
const overviewWindowGlobals = {}
|
||||
|
||||
// Define and insert the base html element.
|
||||
const propsWindowHtml =
|
||||
@@ -29,129 +29,128 @@ export default {
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
$id("sidepanel_content").insertAdjacentHTML( 'beforeend', propsWindowHtml );
|
||||
'</div>'
|
||||
$id('sidepanel_content').insertAdjacentHTML('beforeend', propsWindowHtml)
|
||||
|
||||
// Define dynamic animation of the view box.
|
||||
const updateViewBox = () => {
|
||||
const { workarea } = svgEditor;
|
||||
const portHeight = parseFloat(getComputedStyle(workarea, null).height.replace("px", ""));
|
||||
const portWidth = parseFloat(getComputedStyle(workarea, null).width.replace("px", ""));
|
||||
const portX = workarea.scrollLeft;
|
||||
const portY = workarea.scrollTop;
|
||||
const windowWidth = parseFloat(getComputedStyle($id("svgcanvas"), null).width.replace("px", ""));
|
||||
const windowHeight = parseFloat(getComputedStyle($id("svgcanvas"), null).height.replace("px", ""));
|
||||
const overviewWidth = parseFloat(getComputedStyle($id("overviewMiniView"), null).width.replace("px", ""));
|
||||
const overviewHeight = parseFloat(getComputedStyle($id("overviewMiniView"), null).height.replace("px", ""));
|
||||
const { workarea } = svgEditor
|
||||
const portHeight = parseFloat(getComputedStyle(workarea, null).height.replace('px', ''))
|
||||
const portWidth = parseFloat(getComputedStyle(workarea, null).width.replace('px', ''))
|
||||
const portX = workarea.scrollLeft
|
||||
const portY = workarea.scrollTop
|
||||
const windowWidth = parseFloat(getComputedStyle($id('svgcanvas'), null).width.replace('px', ''))
|
||||
const windowHeight = parseFloat(getComputedStyle($id('svgcanvas'), null).height.replace('px', ''))
|
||||
const overviewWidth = parseFloat(getComputedStyle($id('overviewMiniView'), null).width.replace('px', ''))
|
||||
const overviewHeight = parseFloat(getComputedStyle($id('overviewMiniView'), null).height.replace('px', ''))
|
||||
|
||||
const viewBoxX = portX / windowWidth * overviewWidth;
|
||||
const viewBoxY = portY / windowHeight * overviewHeight;
|
||||
const viewBoxWidth = portWidth / windowWidth * overviewWidth;
|
||||
const viewBoxHeight = portHeight / windowHeight * overviewHeight;
|
||||
const viewBoxX = portX / windowWidth * overviewWidth
|
||||
const viewBoxY = portY / windowHeight * overviewHeight
|
||||
const viewBoxWidth = portWidth / windowWidth * overviewWidth
|
||||
const viewBoxHeight = portHeight / windowHeight * overviewHeight
|
||||
|
||||
$id("overview_window_view_box").style.minWidth = viewBoxWidth + 'px';
|
||||
$id("overview_window_view_box").style.minHeight = viewBoxHeight + 'px';
|
||||
$id("overview_window_view_box").style.top = viewBoxY + 'px';
|
||||
$id("overview_window_view_box").style.left = viewBoxX + 'px';
|
||||
};
|
||||
$id('overview_window_view_box').style.minWidth = viewBoxWidth + 'px'
|
||||
$id('overview_window_view_box').style.minHeight = viewBoxHeight + 'px'
|
||||
$id('overview_window_view_box').style.top = viewBoxY + 'px'
|
||||
$id('overview_window_view_box').style.left = viewBoxX + 'px'
|
||||
}
|
||||
$id('workarea').addEventListener('scroll', () => {
|
||||
if (!(overviewWindowGlobals.viewBoxDragging)) {
|
||||
updateViewBox();
|
||||
updateViewBox()
|
||||
}
|
||||
});
|
||||
$id('workarea').addEventListener('resize', updateViewBox);
|
||||
updateViewBox();
|
||||
})
|
||||
$id('workarea').addEventListener('resize', updateViewBox)
|
||||
updateViewBox()
|
||||
|
||||
// Compensate for changes in zoom and canvas size.
|
||||
const updateViewDimensions = function () {
|
||||
const viewWidth = parseFloat(getComputedStyle($id("svgroot"), null).width.replace("px", ""));
|
||||
const viewHeight = parseFloat(getComputedStyle($id("svgroot"), null).height.replace("px", ""));
|
||||
const viewWidth = parseFloat(getComputedStyle($id('svgroot'), null).width.replace('px', ''))
|
||||
const viewHeight = parseFloat(getComputedStyle($id('svgroot'), null).height.replace('px', ''))
|
||||
|
||||
const viewX = 640;
|
||||
const viewY = 480;
|
||||
const viewX = 640
|
||||
const viewY = 480
|
||||
|
||||
const svgWidthOld = parseFloat(getComputedStyle($id("overviewMiniView"), null).width.replace("px", ""));
|
||||
const svgHeightNew = viewHeight / viewWidth * svgWidthOld;
|
||||
$id('overviewMiniView').setAttribute('viewBox', viewX + ' ' + viewY + ' ' + viewWidth + ' ' + viewHeight);
|
||||
$id('overviewMiniView').setAttribute('height', svgHeightNew);
|
||||
updateViewBox();
|
||||
};
|
||||
updateViewDimensions();
|
||||
const svgWidthOld = parseFloat(getComputedStyle($id('overviewMiniView'), null).width.replace('px', ''))
|
||||
const svgHeightNew = viewHeight / viewWidth * svgWidthOld
|
||||
$id('overviewMiniView').setAttribute('viewBox', viewX + ' ' + viewY + ' ' + viewWidth + ' ' + viewHeight)
|
||||
$id('overviewMiniView').setAttribute('height', svgHeightNew)
|
||||
updateViewBox()
|
||||
}
|
||||
updateViewDimensions()
|
||||
|
||||
// Set up the overview window as a controller for the view port.
|
||||
overviewWindowGlobals.viewBoxDragging = false;
|
||||
overviewWindowGlobals.viewBoxDragging = false
|
||||
const updateViewPortFromViewBox = function () {
|
||||
const windowWidth = parseFloat(getComputedStyle($id("svgcanvas"), null).width.replace("px", ""));
|
||||
const windowHeight = parseFloat(getComputedStyle($id("svgcanvas"), null).height.replace("px", ""));
|
||||
const overviewWidth = parseFloat(getComputedStyle($id("overviewMiniView"), null).width.replace("px", ""));
|
||||
const overviewHeight = parseFloat(getComputedStyle($id("overviewMiniView"), null).height.replace("px", ""));
|
||||
const viewBoxX = parseFloat(getComputedStyle($id("overview_window_view_box"), null).getPropertyValue('left').replace("px", ""));
|
||||
const viewBoxY = parseFloat(getComputedStyle($id("overview_window_view_box"), null).getPropertyValue('top').replace("px", ""));
|
||||
const windowWidth = parseFloat(getComputedStyle($id('svgcanvas'), null).width.replace('px', ''))
|
||||
const windowHeight = parseFloat(getComputedStyle($id('svgcanvas'), null).height.replace('px', ''))
|
||||
const overviewWidth = parseFloat(getComputedStyle($id('overviewMiniView'), null).width.replace('px', ''))
|
||||
const overviewHeight = parseFloat(getComputedStyle($id('overviewMiniView'), null).height.replace('px', ''))
|
||||
const viewBoxX = parseFloat(getComputedStyle($id('overview_window_view_box'), null).getPropertyValue('left').replace('px', ''))
|
||||
const viewBoxY = parseFloat(getComputedStyle($id('overview_window_view_box'), null).getPropertyValue('top').replace('px', ''))
|
||||
|
||||
|
||||
const portX = viewBoxX / overviewWidth * windowWidth;
|
||||
const portY = viewBoxY / overviewHeight * windowHeight;
|
||||
$id('workarea').scrollLeft = portX;
|
||||
$id('workarea').scrollTop = portY;
|
||||
};
|
||||
const portX = viewBoxX / overviewWidth * windowWidth
|
||||
const portY = viewBoxY / overviewHeight * windowHeight
|
||||
$id('workarea').scrollLeft = portX
|
||||
$id('workarea').scrollTop = portY
|
||||
}
|
||||
const onStart = () => {
|
||||
overviewWindowGlobals.viewBoxDragging = true;
|
||||
updateViewPortFromViewBox();
|
||||
};
|
||||
overviewWindowGlobals.viewBoxDragging = true
|
||||
updateViewPortFromViewBox()
|
||||
}
|
||||
const onEnd = (el, parent, _x, _y) => {
|
||||
if((el.offsetLeft + el.offsetWidth) > parseFloat(getComputedStyle(parent, null).width.replace("px", ""))){
|
||||
el.style.left = (parseFloat(getComputedStyle(parent, null).width.replace("px", "")) - el.offsetWidth) + 'px';
|
||||
} else if(el.offsetLeft < 0){
|
||||
el.style.left = "0px";
|
||||
if ((el.offsetLeft + el.offsetWidth) > parseFloat(getComputedStyle(parent, null).width.replace('px', ''))) {
|
||||
el.style.left = (parseFloat(getComputedStyle(parent, null).width.replace('px', '')) - el.offsetWidth) + 'px'
|
||||
} else if (el.offsetLeft < 0) {
|
||||
el.style.left = '0px'
|
||||
}
|
||||
if((el.offsetTop + el.offsetHeight) > parseFloat(getComputedStyle(parent, null).height.replace("px", ""))){
|
||||
el.style.top = (parseFloat(getComputedStyle(parent, null).height.replace("px", "")) - el.offsetHeight) + 'px';
|
||||
} else if(el.offsetTop < 0){
|
||||
el.style.top = "0px";
|
||||
if ((el.offsetTop + el.offsetHeight) > parseFloat(getComputedStyle(parent, null).height.replace('px', ''))) {
|
||||
el.style.top = (parseFloat(getComputedStyle(parent, null).height.replace('px', '')) - el.offsetHeight) + 'px'
|
||||
} else if (el.offsetTop < 0) {
|
||||
el.style.top = '0px'
|
||||
}
|
||||
overviewWindowGlobals.viewBoxDragging = false;
|
||||
updateViewPortFromViewBox();
|
||||
};
|
||||
overviewWindowGlobals.viewBoxDragging = false
|
||||
updateViewPortFromViewBox()
|
||||
}
|
||||
const onDrag = function () {
|
||||
updateViewPortFromViewBox();
|
||||
};
|
||||
const dragElem = document.querySelector("#overview_window_view_box");
|
||||
const parentElem = document.querySelector("#overviewMiniView");
|
||||
dragmove(dragElem, dragElem, parentElem, onStart, onEnd, onDrag);
|
||||
updateViewPortFromViewBox()
|
||||
}
|
||||
const dragElem = document.querySelector('#overview_window_view_box')
|
||||
const parentElem = document.querySelector('#overviewMiniView')
|
||||
dragmove(dragElem, dragElem, parentElem, onStart, onEnd, onDrag)
|
||||
|
||||
$id("overviewMiniView").addEventListener("click", (evt) => {
|
||||
$id('overviewMiniView').addEventListener('click', (evt) => {
|
||||
// Firefox doesn't support evt.offsetX and evt.offsetY.
|
||||
const mouseX = (evt.offsetX || evt.originalEvent.layerX);
|
||||
const mouseY = (evt.offsetY || evt.originalEvent.layerY);
|
||||
const overviewWidth = parseFloat(getComputedStyle($id("overviewMiniView"), null).width.replace("px", ""));
|
||||
const overviewHeight = parseFloat(getComputedStyle($id("overviewMiniView"), null).height.replace("px", ""));
|
||||
const viewBoxWidth = parseFloat(getComputedStyle($id("overview_window_view_box"), null).getPropertyValue('min-width').replace("px", ""));
|
||||
const viewBoxHeight = parseFloat(getComputedStyle($id("overview_window_view_box"), null).getPropertyValue('min-height').replace("px", ""));
|
||||
const mouseX = (evt.offsetX || evt.originalEvent.layerX)
|
||||
const mouseY = (evt.offsetY || evt.originalEvent.layerY)
|
||||
const overviewWidth = parseFloat(getComputedStyle($id('overviewMiniView'), null).width.replace('px', ''))
|
||||
const overviewHeight = parseFloat(getComputedStyle($id('overviewMiniView'), null).height.replace('px', ''))
|
||||
const viewBoxWidth = parseFloat(getComputedStyle($id('overview_window_view_box'), null).getPropertyValue('min-width').replace('px', ''))
|
||||
const viewBoxHeight = parseFloat(getComputedStyle($id('overview_window_view_box'), null).getPropertyValue('min-height').replace('px', ''))
|
||||
|
||||
let viewBoxX = mouseX - 0.5 * viewBoxWidth;
|
||||
let viewBoxY = mouseY - 0.5 * viewBoxHeight;
|
||||
let viewBoxX = mouseX - 0.5 * viewBoxWidth
|
||||
let viewBoxY = mouseY - 0.5 * viewBoxHeight
|
||||
// deal with constraints
|
||||
if (viewBoxX < 0) {
|
||||
viewBoxX = 0;
|
||||
viewBoxX = 0
|
||||
}
|
||||
if (viewBoxY < 0) {
|
||||
viewBoxY = 0;
|
||||
viewBoxY = 0
|
||||
}
|
||||
if (viewBoxX + viewBoxWidth > overviewWidth) {
|
||||
viewBoxX = overviewWidth - viewBoxWidth;
|
||||
viewBoxX = overviewWidth - viewBoxWidth
|
||||
}
|
||||
if (viewBoxY + viewBoxHeight > overviewHeight) {
|
||||
viewBoxY = overviewHeight - viewBoxHeight;
|
||||
viewBoxY = overviewHeight - viewBoxHeight
|
||||
}
|
||||
$id("overview_window_view_box").style.top = viewBoxY + 'px';
|
||||
$id("overview_window_view_box").style.left = viewBoxX + 'px';
|
||||
updateViewPortFromViewBox();
|
||||
});
|
||||
$id('overview_window_view_box').style.top = viewBoxY + 'px'
|
||||
$id('overview_window_view_box').style.left = viewBoxX + 'px'
|
||||
updateViewPortFromViewBox()
|
||||
})
|
||||
|
||||
return {
|
||||
name: 'overview window',
|
||||
canvasUpdated: updateViewDimensions,
|
||||
workareaResized: updateViewBox
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,71 +10,69 @@
|
||||
This is a very basic SVG-Edit extension to let tablet/mobile devices pan without problem
|
||||
*/
|
||||
|
||||
const name = "panning";
|
||||
const name = 'panning'
|
||||
|
||||
const loadExtensionTranslation = async function (svgEditor) {
|
||||
let translationModule;
|
||||
const lang = svgEditor.configObj.pref('lang');
|
||||
let translationModule
|
||||
const lang = svgEditor.configObj.pref('lang')
|
||||
try {
|
||||
// eslint-disable-next-line no-unsanitized/method
|
||||
translationModule = await import(`./locale/${lang}.js`);
|
||||
translationModule = await import(`./locale/${lang}.js`)
|
||||
} catch (_error) {
|
||||
console.warn(`Missing translation (${lang}) for ${name} - using 'en'`);
|
||||
translationModule = await import(`./locale/en.js`);
|
||||
console.warn(`Missing translation (${lang}) for ${name} - using 'en'`)
|
||||
translationModule = await import('./locale/en.js')
|
||||
}
|
||||
svgEditor.i18next.addResourceBundle(lang, name, translationModule.default);
|
||||
};
|
||||
svgEditor.i18next.addResourceBundle(lang, name, translationModule.default)
|
||||
}
|
||||
|
||||
export default {
|
||||
name,
|
||||
async init() {
|
||||
const svgEditor = this;
|
||||
await loadExtensionTranslation(svgEditor);
|
||||
async init () {
|
||||
const svgEditor = this
|
||||
await loadExtensionTranslation(svgEditor)
|
||||
const {
|
||||
svgCanvas
|
||||
} = svgEditor;
|
||||
} = svgEditor
|
||||
const {
|
||||
$id
|
||||
} = svgCanvas;
|
||||
} = svgCanvas
|
||||
const insertAfter = (referenceNode, newNode) => {
|
||||
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
|
||||
};
|
||||
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling)
|
||||
}
|
||||
return {
|
||||
name: svgEditor.i18next.t(`${name}:name`),
|
||||
callback() {
|
||||
const btitle = `${name}:buttons.0.title`;
|
||||
callback () {
|
||||
const btitle = `${name}:buttons.0.title`
|
||||
// Add the button and its handler(s)
|
||||
const buttonTemplate = document.createElement("template");
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
const buttonTemplate = document.createElement('template')
|
||||
buttonTemplate.innerHTML = `
|
||||
<se-button id="ext-panning" title="${btitle}" src="panning.svg"></se-button>
|
||||
`;
|
||||
insertAfter($id('tool_zoom'), buttonTemplate.content.cloneNode(true));
|
||||
$id('ext-panning').addEventListener("click", () => {
|
||||
if (this.leftPanel.updateLeftPanel("ext-panning")) {
|
||||
svgCanvas.setMode('ext-panning');
|
||||
`
|
||||
insertAfter($id('tool_zoom'), buttonTemplate.content.cloneNode(true))
|
||||
$id('ext-panning').addEventListener('click', () => {
|
||||
if (this.leftPanel.updateLeftPanel('ext-panning')) {
|
||||
svgCanvas.setMode('ext-panning')
|
||||
}
|
||||
});
|
||||
})
|
||||
},
|
||||
mouseDown() {
|
||||
mouseDown () {
|
||||
if (svgCanvas.getMode() === 'ext-panning') {
|
||||
svgEditor.setPanning(true);
|
||||
svgEditor.setPanning(true)
|
||||
return {
|
||||
started: true
|
||||
};
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
return undefined
|
||||
},
|
||||
mouseUp() {
|
||||
mouseUp () {
|
||||
if (svgCanvas.getMode() === 'ext-panning') {
|
||||
svgEditor.setPanning(false);
|
||||
svgEditor.setPanning(false)
|
||||
return {
|
||||
keep: false,
|
||||
element: null
|
||||
};
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
return undefined
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,4 +5,4 @@ export default {
|
||||
title: 'Panning'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,4 +5,4 @@ export default {
|
||||
title: '移动'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,33 +8,32 @@
|
||||
*
|
||||
*/
|
||||
|
||||
const name = "polystar";
|
||||
const name = 'polystar'
|
||||
|
||||
const loadExtensionTranslation = async function (svgEditor) {
|
||||
let translationModule;
|
||||
const lang = svgEditor.configObj.pref('lang');
|
||||
let translationModule
|
||||
const lang = svgEditor.configObj.pref('lang')
|
||||
try {
|
||||
// eslint-disable-next-line no-unsanitized/method
|
||||
translationModule = await import(`./locale/${lang}.js`);
|
||||
translationModule = await import(`./locale/${lang}.js`)
|
||||
} catch (_error) {
|
||||
console.warn(`Missing translation (${lang}) for ${name} - using 'en'`);
|
||||
translationModule = await import(`./locale/en.js`);
|
||||
console.warn(`Missing translation (${lang}) for ${name} - using 'en'`)
|
||||
translationModule = await import('./locale/en.js')
|
||||
}
|
||||
svgEditor.i18next.addResourceBundle(lang, name, translationModule.default);
|
||||
};
|
||||
svgEditor.i18next.addResourceBundle(lang, name, translationModule.default)
|
||||
}
|
||||
|
||||
export default {
|
||||
name,
|
||||
async init() {
|
||||
const svgEditor = this;
|
||||
const { svgCanvas } = svgEditor;
|
||||
const { ChangeElementCommand } = svgCanvas.history;
|
||||
const addToHistory = function (cmd) { svgCanvas.undoMgr.addCommandToHistory(cmd); };
|
||||
const { $id } = svgCanvas;
|
||||
let selElems;
|
||||
let started;
|
||||
let newFO;
|
||||
await loadExtensionTranslation(svgEditor);
|
||||
async init () {
|
||||
const svgEditor = this
|
||||
const { svgCanvas } = svgEditor
|
||||
const { ChangeElementCommand } = svgCanvas.history
|
||||
const addToHistory = function (cmd) { svgCanvas.undoMgr.addCommandToHistory(cmd) }
|
||||
const { $id } = svgCanvas
|
||||
let selElems
|
||||
let started
|
||||
let newFO
|
||||
await loadExtensionTranslation(svgEditor)
|
||||
|
||||
/**
|
||||
* @param {boolean} on true=display
|
||||
@@ -43,11 +42,11 @@ export default {
|
||||
*/
|
||||
const showPanel = (on, tool) => {
|
||||
if (on) {
|
||||
$id(`${tool}_panel`).style.removeProperty('display');
|
||||
$id(`${tool}_panel`).style.removeProperty('display')
|
||||
} else {
|
||||
$id(`${tool}_panel`).style.display = 'none';
|
||||
$id(`${tool}_panel`).style.display = 'none'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -56,66 +55,65 @@ export default {
|
||||
* @returns {void}
|
||||
*/
|
||||
const setAttr = (attr, val) => {
|
||||
svgCanvas.changeSelectedAttribute(attr, val);
|
||||
svgCanvas.call("changed", selElems);
|
||||
};
|
||||
svgCanvas.changeSelectedAttribute(attr, val)
|
||||
svgCanvas.call('changed', selElems)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Float} n angle
|
||||
* @return {Float} cotangeante
|
||||
*/
|
||||
const cot = (n) => 1 / Math.tan(n);
|
||||
const cot = (n) => 1 / Math.tan(n)
|
||||
|
||||
/**
|
||||
* @param {Float} n angle
|
||||
* @returns {Float} sec
|
||||
*/
|
||||
const sec = (n) => 1 / Math.cos(n);
|
||||
const sec = (n) => 1 / Math.cos(n)
|
||||
|
||||
return {
|
||||
name: svgEditor.i18next.t(`${name}:name`),
|
||||
// The callback should be used to load the DOM with the appropriate UI items
|
||||
callback() {
|
||||
callback () {
|
||||
// Add the button and its handler(s)
|
||||
// Note: the star extension needs to be loaded before the polygon extension
|
||||
const fbtitle = `${name}:title`;
|
||||
const title_star = `${name}:buttons.0.title`;
|
||||
const title_polygon = `${name}:buttons.1.title`;
|
||||
const fbtitle = `${name}:title`
|
||||
const titleStar = `${name}:buttons.0.title`
|
||||
const titlePolygon = `${name}:buttons.1.title`
|
||||
const buttonTemplate = `
|
||||
<se-flyingbutton id="tools_polygon" title="${fbtitle}">
|
||||
<se-button id="tool_star" title="${title_star}" src="star.svg">
|
||||
<se-button id="tool_star" title="${titleStar}" src="star.svg">
|
||||
</se-button>
|
||||
<se-button id="tool_polygon" title="${title_polygon}" src="polygon.svg">
|
||||
<se-button id="tool_polygon" title="${titlePolygon}" src="polygon.svg">
|
||||
</se-button>
|
||||
</se-flyingbutton>
|
||||
`;
|
||||
svgCanvas.insertChildAtIndex($id('tools_left'), buttonTemplate, 10);
|
||||
`
|
||||
svgCanvas.insertChildAtIndex($id('tools_left'), buttonTemplate, 10)
|
||||
// handler
|
||||
$id("tool_star").addEventListener("click", () => {
|
||||
if (this.leftPanel.updateLeftPanel("tool_star")) {
|
||||
svgCanvas.setMode("star");
|
||||
showPanel(true, "star");
|
||||
showPanel(false, "polygon");
|
||||
$id('tool_star').addEventListener('click', () => {
|
||||
if (this.leftPanel.updateLeftPanel('tool_star')) {
|
||||
svgCanvas.setMode('star')
|
||||
showPanel(true, 'star')
|
||||
showPanel(false, 'polygon')
|
||||
}
|
||||
});
|
||||
$id("tool_polygon").addEventListener("click", () => {
|
||||
if (this.leftPanel.updateLeftPanel("tool_polygon")) {
|
||||
svgCanvas.setMode("polygon");
|
||||
showPanel(true, "polygon");
|
||||
showPanel(false, "star");
|
||||
})
|
||||
$id('tool_polygon').addEventListener('click', () => {
|
||||
if (this.leftPanel.updateLeftPanel('tool_polygon')) {
|
||||
svgCanvas.setMode('polygon')
|
||||
showPanel(true, 'polygon')
|
||||
showPanel(false, 'star')
|
||||
}
|
||||
});
|
||||
const label0 = `${name}:contextTools.0.label`;
|
||||
const title0 = `${name}:contextTools.0.title`;
|
||||
const label1 = `${name}:contextTools.1.label`;
|
||||
const title1 = `${name}:contextTools.1.title`;
|
||||
const label2 = `${name}:contextTools.2.label`;
|
||||
const title2 = `${name}:contextTools.2.title`;
|
||||
const label3 = `${name}:contextTools.3.label`;
|
||||
const title3 = `${name}:contextTools.3.title`;
|
||||
})
|
||||
const label0 = `${name}:contextTools.0.label`
|
||||
const title0 = `${name}:contextTools.0.title`
|
||||
const label1 = `${name}:contextTools.1.label`
|
||||
const title1 = `${name}:contextTools.1.title`
|
||||
const label2 = `${name}:contextTools.2.label`
|
||||
const title2 = `${name}:contextTools.2.title`
|
||||
const label3 = `${name}:contextTools.3.label`
|
||||
const title3 = `${name}:contextTools.3.title`
|
||||
// Add the context panel and its handler(s)
|
||||
const panelTemplate = document.createElement("template");
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
const panelTemplate = document.createElement('template')
|
||||
panelTemplate.innerHTML = `
|
||||
<div id="star_panel">
|
||||
<se-spin-input id="starNumPoints" label="${label0}" min=1 step=1 value=5 title="${title0}">
|
||||
@@ -129,324 +127,324 @@ export default {
|
||||
<se-spin-input size="3" id="polySides" min=1 step=1 value=5 label="${label3}" title="${title3}">
|
||||
</se-spin-input>
|
||||
</div>
|
||||
`;
|
||||
//add handlers for the panel
|
||||
$id("tools_top").appendChild(panelTemplate.content.cloneNode(true));
|
||||
`
|
||||
// add handlers for the panel
|
||||
$id('tools_top').appendChild(panelTemplate.content.cloneNode(true))
|
||||
// don't display the panels on start
|
||||
showPanel(false, "star");
|
||||
showPanel(false, "polygon");
|
||||
$id("starNumPoints").addEventListener("change", (event) => {
|
||||
setAttr("point", event.target.value);
|
||||
const orient = 'point';
|
||||
const point = event.target.value;
|
||||
let i = selElems.length;
|
||||
showPanel(false, 'star')
|
||||
showPanel(false, 'polygon')
|
||||
$id('starNumPoints').addEventListener('change', (event) => {
|
||||
setAttr('point', event.target.value)
|
||||
const orient = 'point'
|
||||
const point = event.target.value
|
||||
let i = selElems.length
|
||||
while (i--) {
|
||||
const elem = selElems[i];
|
||||
const elem = selElems[i]
|
||||
if (elem.hasAttribute('r')) {
|
||||
const oldPoint = elem.getAttribute('point');
|
||||
const oldPoints = elem.getAttribute('points');
|
||||
const radialshift = elem.getAttribute('radialshift');
|
||||
let xpos = 0;
|
||||
let ypos = 0;
|
||||
const oldPoint = elem.getAttribute('point')
|
||||
const oldPoints = elem.getAttribute('points')
|
||||
const radialshift = elem.getAttribute('radialshift')
|
||||
let xpos = 0
|
||||
let ypos = 0
|
||||
if (elem.points) {
|
||||
const list = elem.points;
|
||||
const len = list.numberOfItems;
|
||||
const list = elem.points
|
||||
const len = list.numberOfItems
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const pt = list.getItem(i);
|
||||
xpos += parseFloat(pt.x);
|
||||
ypos += parseFloat(pt.y);
|
||||
const pt = list.getItem(i)
|
||||
xpos += parseFloat(pt.x)
|
||||
ypos += parseFloat(pt.y)
|
||||
}
|
||||
const cx = xpos / len;
|
||||
const cy = ypos / len;
|
||||
const circumradius = Number(elem.getAttribute('r'));
|
||||
const inradius = circumradius / elem.getAttribute('starRadiusMultiplier');
|
||||
const cx = xpos / len
|
||||
const cy = ypos / len
|
||||
const circumradius = Number(elem.getAttribute('r'))
|
||||
const inradius = circumradius / elem.getAttribute('starRadiusMultiplier')
|
||||
|
||||
let polyPoints = "";
|
||||
let polyPoints = ''
|
||||
for (let s = 0; point >= s; s++) {
|
||||
let angle = 2.0 * Math.PI * (s / point);
|
||||
if (orient === "point") {
|
||||
angle -= Math.PI / 2;
|
||||
} else if (orient === "edge") {
|
||||
angle = angle + Math.PI / point - Math.PI / 2;
|
||||
let angle = 2.0 * Math.PI * (s / point)
|
||||
if (orient === 'point') {
|
||||
angle -= Math.PI / 2
|
||||
} else if (orient === 'edge') {
|
||||
angle = angle + Math.PI / point - Math.PI / 2
|
||||
}
|
||||
|
||||
let x = circumradius * Math.cos(angle) + cx;
|
||||
let y = circumradius * Math.sin(angle) + cy;
|
||||
let x = circumradius * Math.cos(angle) + cx
|
||||
let y = circumradius * Math.sin(angle) + cy
|
||||
|
||||
polyPoints += x + "," + y + " ";
|
||||
polyPoints += x + ',' + y + ' '
|
||||
|
||||
if (!isNaN(inradius)) {
|
||||
angle = 2.0 * Math.PI * (s / point) + Math.PI / point;
|
||||
if (orient === "point") {
|
||||
angle -= Math.PI / 2;
|
||||
} else if (orient === "edge") {
|
||||
angle = angle + Math.PI / point - Math.PI / 2;
|
||||
angle = 2.0 * Math.PI * (s / point) + Math.PI / point
|
||||
if (orient === 'point') {
|
||||
angle -= Math.PI / 2
|
||||
} else if (orient === 'edge') {
|
||||
angle = angle + Math.PI / point - Math.PI / 2
|
||||
}
|
||||
angle += radialshift;
|
||||
angle += radialshift
|
||||
|
||||
x = inradius * Math.cos(angle) + cx;
|
||||
y = inradius * Math.sin(angle) + cy;
|
||||
x = inradius * Math.cos(angle) + cx
|
||||
y = inradius * Math.sin(angle) + cy
|
||||
|
||||
polyPoints += x + "," + y + " ";
|
||||
polyPoints += x + ',' + y + ' '
|
||||
}
|
||||
}
|
||||
elem.setAttribute("points", polyPoints);
|
||||
addToHistory(new ChangeElementCommand(elem, { 'point': oldPoint, 'points': oldPoints }));
|
||||
elem.setAttribute('points', polyPoints)
|
||||
addToHistory(new ChangeElementCommand(elem, { point: oldPoint, points: oldPoints }))
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
$id("RadiusMultiplier").addEventListener("change", (event) => {
|
||||
setAttr("starRadiusMultiplier", event.target.value);
|
||||
});
|
||||
$id("radialShift").addEventListener("change", (event) => {
|
||||
setAttr("radialshift", event.target.value);
|
||||
});
|
||||
$id("polySides").addEventListener("change", (event) => {
|
||||
setAttr("sides", event.target.value);
|
||||
const sides = event.target.value;
|
||||
let i = selElems.length;
|
||||
})
|
||||
$id('RadiusMultiplier').addEventListener('change', (event) => {
|
||||
setAttr('starRadiusMultiplier', event.target.value)
|
||||
})
|
||||
$id('radialShift').addEventListener('change', (event) => {
|
||||
setAttr('radialshift', event.target.value)
|
||||
})
|
||||
$id('polySides').addEventListener('change', (event) => {
|
||||
setAttr('sides', event.target.value)
|
||||
const sides = event.target.value
|
||||
let i = selElems.length
|
||||
while (i--) {
|
||||
const elem = selElems[i];
|
||||
const elem = selElems[i]
|
||||
if (elem.hasAttribute('edge')) {
|
||||
const oldSides = elem.getAttribute('sides');
|
||||
const oldPoints = elem.getAttribute('points');
|
||||
let xpos = 0;
|
||||
let ypos = 0;
|
||||
const oldSides = elem.getAttribute('sides')
|
||||
const oldPoints = elem.getAttribute('points')
|
||||
let xpos = 0
|
||||
let ypos = 0
|
||||
if (elem.points) {
|
||||
const list = elem.points;
|
||||
const len = list.numberOfItems;
|
||||
const list = elem.points
|
||||
const len = list.numberOfItems
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const pt = list.getItem(i);
|
||||
xpos += parseFloat(pt.x);
|
||||
ypos += parseFloat(pt.y);
|
||||
const pt = list.getItem(i)
|
||||
xpos += parseFloat(pt.x)
|
||||
ypos += parseFloat(pt.y)
|
||||
}
|
||||
const cx = xpos / len;
|
||||
const cy = ypos / len;
|
||||
const edg = elem.getAttribute('edge');
|
||||
const inradius = (edg / 2) * cot(Math.PI / sides);
|
||||
const circumradius = inradius * sec(Math.PI / sides);
|
||||
let points = "";
|
||||
const cx = xpos / len
|
||||
const cy = ypos / len
|
||||
const edg = elem.getAttribute('edge')
|
||||
const inradius = (edg / 2) * cot(Math.PI / sides)
|
||||
const circumradius = inradius * sec(Math.PI / sides)
|
||||
let points = ''
|
||||
for (let s = 0; sides >= s; s++) {
|
||||
const angle = (2.0 * Math.PI * s) / sides;
|
||||
const x = circumradius * Math.cos(angle) + cx;
|
||||
const y = circumradius * Math.sin(angle) + cy;
|
||||
points += x + "," + y + " ";
|
||||
const angle = (2.0 * Math.PI * s) / sides
|
||||
const x = circumradius * Math.cos(angle) + cx
|
||||
const y = circumradius * Math.sin(angle) + cy
|
||||
points += x + ',' + y + ' '
|
||||
}
|
||||
elem.setAttribute("points", points);
|
||||
addToHistory(new ChangeElementCommand(elem, { 'sides': oldSides, 'points': oldPoints }));
|
||||
elem.setAttribute('points', points)
|
||||
addToHistory(new ChangeElementCommand(elem, { sides: oldSides, points: oldPoints }))
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
},
|
||||
mouseDown(opts) {
|
||||
if (svgCanvas.getMode() === "star") {
|
||||
const rgb = svgCanvas.getColor("fill");
|
||||
const sRgb = svgCanvas.getColor("stroke");
|
||||
const sWidth = svgCanvas.getStrokeWidth();
|
||||
started = true;
|
||||
mouseDown (opts) {
|
||||
if (svgCanvas.getMode() === 'star') {
|
||||
const rgb = svgCanvas.getColor('fill')
|
||||
const sRgb = svgCanvas.getColor('stroke')
|
||||
const sWidth = svgCanvas.getStrokeWidth()
|
||||
started = true
|
||||
newFO = svgCanvas.addSVGElemensFromJson({
|
||||
element: "polygon",
|
||||
element: 'polygon',
|
||||
attr: {
|
||||
cx: opts.start_x,
|
||||
cy: opts.start_y,
|
||||
id: svgCanvas.getNextId(),
|
||||
shape: "star",
|
||||
point: $id("starNumPoints").value,
|
||||
shape: 'star',
|
||||
point: $id('starNumPoints').value,
|
||||
r: 0,
|
||||
radialshift: $id("radialShift").value,
|
||||
radialshift: $id('radialShift').value,
|
||||
r2: 0,
|
||||
orient: "point",
|
||||
orient: 'point',
|
||||
fill: rgb,
|
||||
strokecolor: sRgb,
|
||||
strokeWidth: sWidth
|
||||
}
|
||||
});
|
||||
})
|
||||
return {
|
||||
started: true
|
||||
};
|
||||
}
|
||||
}
|
||||
if (svgCanvas.getMode() === "polygon") {
|
||||
if (svgCanvas.getMode() === 'polygon') {
|
||||
// const e = opts.event;
|
||||
const rgb = svgCanvas.getColor("fill");
|
||||
const rgb = svgCanvas.getColor('fill')
|
||||
// const ccRgbEl = rgb.substring(1, rgb.length);
|
||||
const sRgb = svgCanvas.getColor("stroke");
|
||||
const sRgb = svgCanvas.getColor('stroke')
|
||||
// ccSRgbEl = sRgb.substring(1, rgb.length);
|
||||
const sWidth = svgCanvas.getStrokeWidth();
|
||||
started = true;
|
||||
const sWidth = svgCanvas.getStrokeWidth()
|
||||
started = true
|
||||
newFO = svgCanvas.addSVGElemensFromJson({
|
||||
element: "polygon",
|
||||
element: 'polygon',
|
||||
attr: {
|
||||
cx: opts.start_x,
|
||||
cy: opts.start_y,
|
||||
id: svgCanvas.getNextId(),
|
||||
shape: "regularPoly",
|
||||
sides: $id("polySides").value,
|
||||
orient: "x",
|
||||
shape: 'regularPoly',
|
||||
sides: $id('polySides').value,
|
||||
orient: 'x',
|
||||
edge: 0,
|
||||
fill: rgb,
|
||||
strokecolor: sRgb,
|
||||
strokeWidth: sWidth
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
return {
|
||||
started: true
|
||||
};
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
return undefined
|
||||
},
|
||||
mouseMove(opts) {
|
||||
mouseMove (opts) {
|
||||
if (!started) {
|
||||
return undefined;
|
||||
return undefined
|
||||
}
|
||||
if (svgCanvas.getMode() === "star") {
|
||||
const cx = Number(newFO.getAttribute("cx"));
|
||||
const cy = Number(newFO.getAttribute("cy"));
|
||||
const point = Number(newFO.getAttribute("point"));
|
||||
const orient = newFO.getAttribute("orient");
|
||||
const fill = newFO.getAttribute("fill");
|
||||
const strokecolor = newFO.getAttribute("strokecolor");
|
||||
const strokeWidth = Number(newFO.getAttribute("strokeWidth"));
|
||||
const radialshift = Number(newFO.getAttribute("radialshift"));
|
||||
if (svgCanvas.getMode() === 'star') {
|
||||
const cx = Number(newFO.getAttribute('cx'))
|
||||
const cy = Number(newFO.getAttribute('cy'))
|
||||
const point = Number(newFO.getAttribute('point'))
|
||||
const orient = newFO.getAttribute('orient')
|
||||
const fill = newFO.getAttribute('fill')
|
||||
const strokecolor = newFO.getAttribute('strokecolor')
|
||||
const strokeWidth = Number(newFO.getAttribute('strokeWidth'))
|
||||
const radialshift = Number(newFO.getAttribute('radialshift'))
|
||||
|
||||
let x = opts.mouse_x;
|
||||
let y = opts.mouse_y;
|
||||
let x = opts.mouse_x
|
||||
let y = opts.mouse_y
|
||||
|
||||
const circumradius =
|
||||
Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy)) / 1.5;
|
||||
const RadiusMultiplier = document.getElementById("RadiusMultiplier").value;
|
||||
Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy)) / 1.5
|
||||
const RadiusMultiplier = document.getElementById('RadiusMultiplier').value
|
||||
const inradius =
|
||||
circumradius / RadiusMultiplier;
|
||||
newFO.setAttribute("r", circumradius);
|
||||
newFO.setAttribute("r2", inradius);
|
||||
newFO.setAttribute('starRadiusMultiplier', RadiusMultiplier);
|
||||
circumradius / RadiusMultiplier
|
||||
newFO.setAttribute('r', circumradius)
|
||||
newFO.setAttribute('r2', inradius)
|
||||
newFO.setAttribute('starRadiusMultiplier', RadiusMultiplier)
|
||||
|
||||
let polyPoints = "";
|
||||
let polyPoints = ''
|
||||
for (let s = 0; point >= s; s++) {
|
||||
let angle = 2.0 * Math.PI * (s / point);
|
||||
if (orient === "point") {
|
||||
angle -= Math.PI / 2;
|
||||
} else if (orient === "edge") {
|
||||
angle = angle + Math.PI / point - Math.PI / 2;
|
||||
let angle = 2.0 * Math.PI * (s / point)
|
||||
if (orient === 'point') {
|
||||
angle -= Math.PI / 2
|
||||
} else if (orient === 'edge') {
|
||||
angle = angle + Math.PI / point - Math.PI / 2
|
||||
}
|
||||
|
||||
x = circumradius * Math.cos(angle) + cx;
|
||||
y = circumradius * Math.sin(angle) + cy;
|
||||
x = circumradius * Math.cos(angle) + cx
|
||||
y = circumradius * Math.sin(angle) + cy
|
||||
|
||||
polyPoints += x + "," + y + " ";
|
||||
polyPoints += x + ',' + y + ' '
|
||||
|
||||
if (!isNaN(inradius)) {
|
||||
angle = 2.0 * Math.PI * (s / point) + Math.PI / point;
|
||||
if (orient === "point") {
|
||||
angle -= Math.PI / 2;
|
||||
} else if (orient === "edge") {
|
||||
angle = angle + Math.PI / point - Math.PI / 2;
|
||||
angle = 2.0 * Math.PI * (s / point) + Math.PI / point
|
||||
if (orient === 'point') {
|
||||
angle -= Math.PI / 2
|
||||
} else if (orient === 'edge') {
|
||||
angle = angle + Math.PI / point - Math.PI / 2
|
||||
}
|
||||
angle += radialshift;
|
||||
angle += radialshift
|
||||
|
||||
x = inradius * Math.cos(angle) + cx;
|
||||
y = inradius * Math.sin(angle) + cy;
|
||||
x = inradius * Math.cos(angle) + cx
|
||||
y = inradius * Math.sin(angle) + cy
|
||||
|
||||
polyPoints += x + "," + y + " ";
|
||||
polyPoints += x + ',' + y + ' '
|
||||
}
|
||||
}
|
||||
newFO.setAttribute("points", polyPoints);
|
||||
newFO.setAttribute("fill", fill);
|
||||
newFO.setAttribute("stroke", strokecolor);
|
||||
newFO.setAttribute("stroke-width", strokeWidth);
|
||||
/* const shape = */ newFO.getAttribute("shape");
|
||||
newFO.setAttribute('points', polyPoints)
|
||||
newFO.setAttribute('fill', fill)
|
||||
newFO.setAttribute('stroke', strokecolor)
|
||||
newFO.setAttribute('stroke-width', strokeWidth)
|
||||
/* const shape = */ newFO.getAttribute('shape')
|
||||
|
||||
return {
|
||||
started: true
|
||||
};
|
||||
}
|
||||
}
|
||||
if (svgCanvas.getMode() === "polygon") {
|
||||
const cx = Number(newFO.getAttribute("cx"));
|
||||
const cy = Number(newFO.getAttribute("cy"));
|
||||
const sides = Number(newFO.getAttribute("sides"));
|
||||
if (svgCanvas.getMode() === 'polygon') {
|
||||
const cx = Number(newFO.getAttribute('cx'))
|
||||
const cy = Number(newFO.getAttribute('cy'))
|
||||
const sides = Number(newFO.getAttribute('sides'))
|
||||
// const orient = newFO.getAttribute('orient');
|
||||
const fill = newFO.getAttribute("fill");
|
||||
const strokecolor = newFO.getAttribute("strokecolor");
|
||||
const strokeWidth = Number(newFO.getAttribute("strokeWidth"));
|
||||
const fill = newFO.getAttribute('fill')
|
||||
const strokecolor = newFO.getAttribute('strokecolor')
|
||||
const strokeWidth = Number(newFO.getAttribute('strokeWidth'))
|
||||
|
||||
let x = opts.mouse_x;
|
||||
let y = opts.mouse_y;
|
||||
let x = opts.mouse_x
|
||||
let y = opts.mouse_y
|
||||
|
||||
const edg =
|
||||
Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy)) / 1.5;
|
||||
newFO.setAttribute("edge", edg);
|
||||
Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy)) / 1.5
|
||||
newFO.setAttribute('edge', edg)
|
||||
|
||||
const inradius = (edg / 2) * cot(Math.PI / sides);
|
||||
const circumradius = inradius * sec(Math.PI / sides);
|
||||
let points = "";
|
||||
const inradius = (edg / 2) * cot(Math.PI / sides)
|
||||
const circumradius = inradius * sec(Math.PI / sides)
|
||||
let points = ''
|
||||
for (let s = 0; sides >= s; s++) {
|
||||
const angle = (2.0 * Math.PI * s) / sides;
|
||||
x = circumradius * Math.cos(angle) + cx;
|
||||
y = circumradius * Math.sin(angle) + cy;
|
||||
const angle = (2.0 * Math.PI * s) / sides
|
||||
x = circumradius * Math.cos(angle) + cx
|
||||
y = circumradius * Math.sin(angle) + cy
|
||||
|
||||
points += x + "," + y + " ";
|
||||
points += x + ',' + y + ' '
|
||||
}
|
||||
|
||||
// const poly = newFO.createElementNS(NS.SVG, 'polygon');
|
||||
newFO.setAttribute("points", points);
|
||||
newFO.setAttribute("fill", fill);
|
||||
newFO.setAttribute("stroke", strokecolor);
|
||||
newFO.setAttribute("stroke-width", strokeWidth);
|
||||
newFO.setAttribute('points', points)
|
||||
newFO.setAttribute('fill', fill)
|
||||
newFO.setAttribute('stroke', strokecolor)
|
||||
newFO.setAttribute('stroke-width', strokeWidth)
|
||||
return {
|
||||
started: true
|
||||
};
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
return undefined
|
||||
},
|
||||
mouseUp() {
|
||||
if (svgCanvas.getMode() === "star") {
|
||||
const r = newFO.getAttribute("r");
|
||||
mouseUp () {
|
||||
if (svgCanvas.getMode() === 'star') {
|
||||
const r = newFO.getAttribute('r')
|
||||
return {
|
||||
keep: r !== "0",
|
||||
keep: r !== '0',
|
||||
element: newFO
|
||||
};
|
||||
}
|
||||
}
|
||||
if (svgCanvas.getMode() === "polygon") {
|
||||
const edge = newFO.getAttribute("edge");
|
||||
const keep = edge !== "0";
|
||||
if (svgCanvas.getMode() === 'polygon') {
|
||||
const edge = newFO.getAttribute('edge')
|
||||
const keep = edge !== '0'
|
||||
// svgCanvas.addToSelection([newFO], true);
|
||||
return {
|
||||
keep,
|
||||
element: newFO
|
||||
};
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
return undefined
|
||||
},
|
||||
selectedChanged(opts) {
|
||||
selectedChanged (opts) {
|
||||
// Use this to update the current selected elements
|
||||
selElems = opts.elems;
|
||||
selElems = opts.elems
|
||||
|
||||
let i = selElems.length;
|
||||
let i = selElems.length
|
||||
while (i--) {
|
||||
const elem = selElems[i];
|
||||
if (elem && elem.getAttribute("shape") === "star") {
|
||||
const elem = selElems[i]
|
||||
if (elem && elem.getAttribute('shape') === 'star') {
|
||||
if (opts.selectedElement && !opts.multiselected) {
|
||||
$id("starNumPoints").value = elem.getAttribute("point");
|
||||
$id("radialShift").value = elem.getAttribute("radialshift");
|
||||
showPanel(true, "star");
|
||||
$id('starNumPoints').value = elem.getAttribute('point')
|
||||
$id('radialShift').value = elem.getAttribute('radialshift')
|
||||
showPanel(true, 'star')
|
||||
} else {
|
||||
showPanel(false, "star");
|
||||
showPanel(false, 'star')
|
||||
}
|
||||
} else if (elem && elem.getAttribute("shape") === "regularPoly") {
|
||||
} else if (elem && elem.getAttribute('shape') === 'regularPoly') {
|
||||
if (opts.selectedElement && !opts.multiselected) {
|
||||
$id("polySides").value = elem.getAttribute("sides");
|
||||
showPanel(true, "polygon");
|
||||
$id('polySides').value = elem.getAttribute('sides')
|
||||
showPanel(true, 'polygon')
|
||||
} else {
|
||||
showPanel(false, "polygon");
|
||||
showPanel(false, 'polygon')
|
||||
}
|
||||
} else {
|
||||
showPanel(false, "star");
|
||||
showPanel(false, "polygon");
|
||||
showPanel(false, 'star')
|
||||
showPanel(false, 'polygon')
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -27,4 +27,4 @@ export default {
|
||||
label: 'sides'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -27,4 +27,4 @@ export default {
|
||||
label: 'côtés'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -27,4 +27,4 @@ export default {
|
||||
label: '边数'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,37 +6,36 @@
|
||||
* @copyright 2010 Christian Tzurcanu, 2010 Alexis Deveria
|
||||
*
|
||||
*/
|
||||
const name = "shapes";
|
||||
const name = 'shapes'
|
||||
|
||||
const loadExtensionTranslation = async function (svgEditor) {
|
||||
let translationModule;
|
||||
const lang = svgEditor.configObj.pref('lang');
|
||||
let translationModule
|
||||
const lang = svgEditor.configObj.pref('lang')
|
||||
try {
|
||||
// eslint-disable-next-line no-unsanitized/method
|
||||
translationModule = await import(`./locale/${lang}.js`);
|
||||
translationModule = await import(`./locale/${lang}.js`)
|
||||
} catch (_error) {
|
||||
console.warn(`Missing translation (${lang}) for ${name} - using 'en'`);
|
||||
translationModule = await import(`./locale/en.js`);
|
||||
console.warn(`Missing translation (${lang}) for ${name} - using 'en'`)
|
||||
translationModule = await import('./locale/en.js')
|
||||
}
|
||||
svgEditor.i18next.addResourceBundle(lang, name, translationModule.default);
|
||||
};
|
||||
svgEditor.i18next.addResourceBundle(lang, name, translationModule.default)
|
||||
}
|
||||
|
||||
export default {
|
||||
name,
|
||||
async init () {
|
||||
const svgEditor = this;
|
||||
const canv = svgEditor.svgCanvas;
|
||||
const { $id } = canv;
|
||||
const svgroot = canv.getSvgRoot();
|
||||
let lastBBox = {};
|
||||
await loadExtensionTranslation(svgEditor);
|
||||
const svgEditor = this
|
||||
const canv = svgEditor.svgCanvas
|
||||
const { $id } = canv
|
||||
const svgroot = canv.getSvgRoot()
|
||||
let lastBBox = {}
|
||||
await loadExtensionTranslation(svgEditor)
|
||||
|
||||
const modeId = 'shapelib';
|
||||
const startClientPos = {};
|
||||
const modeId = 'shapelib'
|
||||
const startClientPos = {}
|
||||
|
||||
let curShape;
|
||||
let startX;
|
||||
let startY;
|
||||
let curShape
|
||||
let startX
|
||||
let startY
|
||||
|
||||
return {
|
||||
callback () {
|
||||
@@ -44,28 +43,28 @@ export default {
|
||||
const buttonTemplate = `
|
||||
<se-explorerbutton id="tool_shapelib" title="${svgEditor.i18next.t(`${name}:buttons.0.title`)}" lib="./extensions/ext-shapes/shapelib/"
|
||||
src="shapelib.svg"></se-explorerbutton>
|
||||
`;
|
||||
canv.insertChildAtIndex($id('tools_left'), buttonTemplate, 9);
|
||||
$id('tool_shapelib').addEventListener("click", () => {
|
||||
if (this.leftPanel.updateLeftPanel("tool_shapelib")) {
|
||||
canv.setMode(modeId);
|
||||
`
|
||||
canv.insertChildAtIndex($id('tools_left'), buttonTemplate, 9)
|
||||
$id('tool_shapelib').addEventListener('click', () => {
|
||||
if (this.leftPanel.updateLeftPanel('tool_shapelib')) {
|
||||
canv.setMode(modeId)
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
},
|
||||
mouseDown (opts) {
|
||||
const mode = canv.getMode();
|
||||
if (mode !== modeId) { return undefined; }
|
||||
const mode = canv.getMode()
|
||||
if (mode !== modeId) { return undefined }
|
||||
|
||||
const currentD = document.getElementById('tool_shapelib').dataset.draw;
|
||||
startX = opts.start_x;
|
||||
const x = startX;
|
||||
startY = opts.start_y;
|
||||
const y = startY;
|
||||
const curStyle = canv.getStyle();
|
||||
const currentD = document.getElementById('tool_shapelib').dataset.draw
|
||||
startX = opts.start_x
|
||||
const x = startX
|
||||
startY = opts.start_y
|
||||
const y = startY
|
||||
const curStyle = canv.getStyle()
|
||||
|
||||
startClientPos.x = opts.event.clientX;
|
||||
startClientPos.y = opts.event.clientY;
|
||||
startClientPos.x = opts.event.clientX
|
||||
startClientPos.y = opts.event.clientY
|
||||
|
||||
curShape = canv.addSVGElemensFromJson({
|
||||
element: 'path',
|
||||
@@ -76,87 +75,87 @@ export default {
|
||||
opacity: curStyle.opacity / 2,
|
||||
style: 'pointer-events:none'
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
curShape.setAttribute('transform', 'translate(' + x + ',' + y + ') scale(0.005) translate(' + -x + ',' + -y + ')');
|
||||
curShape.setAttribute('transform', 'translate(' + x + ',' + y + ') scale(0.005) translate(' + -x + ',' + -y + ')')
|
||||
|
||||
canv.recalculateDimensions(curShape);
|
||||
canv.recalculateDimensions(curShape)
|
||||
|
||||
lastBBox = curShape.getBBox();
|
||||
lastBBox = curShape.getBBox()
|
||||
|
||||
return {
|
||||
started: true
|
||||
};
|
||||
}
|
||||
},
|
||||
mouseMove (opts) {
|
||||
const mode = canv.getMode();
|
||||
if (mode !== modeId) { return; }
|
||||
const mode = canv.getMode()
|
||||
if (mode !== modeId) { return }
|
||||
|
||||
const zoom = canv.getZoom();
|
||||
const evt = opts.event;
|
||||
const zoom = canv.getZoom()
|
||||
const evt = opts.event
|
||||
|
||||
const x = opts.mouse_x / zoom;
|
||||
const y = opts.mouse_y / zoom;
|
||||
const x = opts.mouse_x / zoom
|
||||
const y = opts.mouse_y / zoom
|
||||
|
||||
const tlist = curShape.transform.baseVal;
|
||||
const box = curShape.getBBox();
|
||||
const left = box.x; const top = box.y;
|
||||
const tlist = curShape.transform.baseVal
|
||||
const box = curShape.getBBox()
|
||||
const left = box.x; const top = box.y
|
||||
|
||||
const newbox = {
|
||||
x: Math.min(startX, x),
|
||||
y: Math.min(startY, y),
|
||||
width: Math.abs(x - startX),
|
||||
height: Math.abs(y - startY)
|
||||
};
|
||||
}
|
||||
|
||||
let sx = (newbox.width / lastBBox.width) || 1;
|
||||
let sy = (newbox.height / lastBBox.height) || 1;
|
||||
let sx = (newbox.width / lastBBox.width) || 1
|
||||
let sy = (newbox.height / lastBBox.height) || 1
|
||||
|
||||
// Not perfect, but mostly works...
|
||||
let tx = 0;
|
||||
let tx = 0
|
||||
if (x < startX) {
|
||||
tx = lastBBox.width;
|
||||
tx = lastBBox.width
|
||||
}
|
||||
let ty = 0;
|
||||
let ty = 0
|
||||
if (y < startY) {
|
||||
ty = lastBBox.height;
|
||||
ty = lastBBox.height
|
||||
}
|
||||
|
||||
// update the transform list with translate,scale,translate
|
||||
const translateOrigin = svgroot.createSVGTransform();
|
||||
const scale = svgroot.createSVGTransform();
|
||||
const translateBack = svgroot.createSVGTransform();
|
||||
const translateOrigin = svgroot.createSVGTransform()
|
||||
const scale = svgroot.createSVGTransform()
|
||||
const translateBack = svgroot.createSVGTransform()
|
||||
|
||||
translateOrigin.setTranslate(-(left + tx), -(top + ty));
|
||||
translateOrigin.setTranslate(-(left + tx), -(top + ty))
|
||||
if (!evt.shiftKey) {
|
||||
const max = Math.min(Math.abs(sx), Math.abs(sy));
|
||||
const max = Math.min(Math.abs(sx), Math.abs(sy))
|
||||
|
||||
sx = max * (sx < 0 ? -1 : 1);
|
||||
sy = max * (sy < 0 ? -1 : 1);
|
||||
sx = max * (sx < 0 ? -1 : 1)
|
||||
sy = max * (sy < 0 ? -1 : 1)
|
||||
}
|
||||
scale.setScale(sx, sy);
|
||||
scale.setScale(sx, sy)
|
||||
|
||||
translateBack.setTranslate(left + tx, top + ty);
|
||||
tlist.appendItem(translateBack);
|
||||
tlist.appendItem(scale);
|
||||
tlist.appendItem(translateOrigin);
|
||||
translateBack.setTranslate(left + tx, top + ty)
|
||||
tlist.appendItem(translateBack)
|
||||
tlist.appendItem(scale)
|
||||
tlist.appendItem(translateOrigin)
|
||||
|
||||
canv.recalculateDimensions(curShape);
|
||||
canv.recalculateDimensions(curShape)
|
||||
|
||||
lastBBox = curShape.getBBox();
|
||||
lastBBox = curShape.getBBox()
|
||||
},
|
||||
mouseUp (opts) {
|
||||
const mode = canv.getMode();
|
||||
if (mode !== modeId) { return undefined; }
|
||||
const mode = canv.getMode()
|
||||
if (mode !== modeId) { return undefined }
|
||||
|
||||
const keepObject = (opts.event.clientX !== startClientPos.x && opts.event.clientY !== startClientPos.y);
|
||||
const keepObject = (opts.event.clientX !== startClientPos.x && opts.event.clientY !== startClientPos.y)
|
||||
|
||||
return {
|
||||
keep: keepObject,
|
||||
element: curShape,
|
||||
started: false
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -21,4 +21,4 @@ export default {
|
||||
title: 'Shape library'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -21,4 +21,4 @@ export default {
|
||||
title: "Bibliothèque d'images"
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -21,4 +21,4 @@ export default {
|
||||
title: '图元库'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -18,23 +18,23 @@
|
||||
* @todo We might provide control of storage settings through the UI besides the
|
||||
* initial (or URL-forced) dialog. *
|
||||
*/
|
||||
import './storageDialog.js';
|
||||
import './storageDialog.js'
|
||||
|
||||
/**
|
||||
* Expire the storage cookie.
|
||||
* @returns {void}
|
||||
*/
|
||||
const removeStoragePrefCookie = () => {
|
||||
expireCookie('svgeditstore');
|
||||
};
|
||||
expireCookie('svgeditstore')
|
||||
}
|
||||
/**
|
||||
* Set the cookie to expire.
|
||||
* @param {string} cookie
|
||||
* @returns {void}
|
||||
*/
|
||||
const expireCookie = (cookie) => {
|
||||
document.cookie = encodeURIComponent(cookie) + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT';
|
||||
};
|
||||
document.cookie = encodeURIComponent(cookie) + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT'
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace `storagePrompt` parameter within URL.
|
||||
@@ -43,22 +43,22 @@ const expireCookie = (cookie) => {
|
||||
* @todo Replace the string manipulation with `searchParams.set`
|
||||
*/
|
||||
const replaceStoragePrompt = (val) => {
|
||||
val = val ? 'storagePrompt=' + val : '';
|
||||
const loc = top.location; // Allow this to work with the embedded editor as well
|
||||
val = val ? 'storagePrompt=' + val : ''
|
||||
const loc = top.location // Allow this to work with the embedded editor as well
|
||||
if (loc.href.includes('storagePrompt=')) {
|
||||
loc.href = loc.href.replace(/([&?])storagePrompt=[^&]*(&?)/, function (n0, n1, amp) {
|
||||
return (val ? n1 : '') + val + (!val && amp ? n1 : (amp || ''));
|
||||
});
|
||||
return (val ? n1 : '') + val + (!val && amp ? n1 : (amp || ''))
|
||||
})
|
||||
} else {
|
||||
loc.href += (loc.href.includes('?') ? '&' : '?') + val;
|
||||
loc.href += (loc.href.includes('?') ? '&' : '?') + val
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'storage',
|
||||
init () {
|
||||
const svgEditor = this;
|
||||
const { svgCanvas, storage } = svgEditor;
|
||||
const svgEditor = this
|
||||
const { svgCanvas, storage } = svgEditor
|
||||
|
||||
// We could empty any already-set data for users when they decline storage,
|
||||
// but it would be a risk for users who wanted to store but accidentally
|
||||
@@ -77,50 +77,50 @@ export default {
|
||||
// the "noStorageOnLoad" config setting to true in svgedit-config-*.js.
|
||||
noStorageOnLoad,
|
||||
forceStorage
|
||||
} = svgEditor.configObj.curConfig;
|
||||
} = svgEditor.configObj.curConfig
|
||||
|
||||
// storageDialog added to DOM
|
||||
const storageBox = document.createElement('se-storage-dialog');
|
||||
storageBox.setAttribute('id', 'se-storage-dialog');
|
||||
svgEditor.$container.append(storageBox);
|
||||
storageBox.init(svgEditor.i18next);
|
||||
const storageBox = document.createElement('se-storage-dialog')
|
||||
storageBox.setAttribute('id', 'se-storage-dialog')
|
||||
svgEditor.$container.append(storageBox)
|
||||
storageBox.init(svgEditor.i18next)
|
||||
|
||||
// manage the change in the storageDialog
|
||||
|
||||
storageBox.addEventListener('change', (e) => {
|
||||
storageBox.setAttribute('dialog', 'close');
|
||||
storageBox.setAttribute('dialog', 'close')
|
||||
if (e?.detail?.trigger === 'ok') {
|
||||
if (e?.detail?.select !== 'noPrefsOrContent') {
|
||||
const storagePrompt = new URL(top.location).searchParams.get('storagePrompt');
|
||||
document.cookie = 'svgeditstore=' + encodeURIComponent(e.detail.select) + '; expires=Fri, 31 Dec 9999 23:59:59 GMT';
|
||||
const storagePrompt = new URL(top.location).searchParams.get('storagePrompt')
|
||||
document.cookie = 'svgeditstore=' + encodeURIComponent(e.detail.select) + '; expires=Fri, 31 Dec 9999 23:59:59 GMT'
|
||||
if (storagePrompt === 'true' && e?.detail?.checkbox) {
|
||||
replaceStoragePrompt();
|
||||
return;
|
||||
replaceStoragePrompt()
|
||||
return
|
||||
}
|
||||
} else {
|
||||
removeStoragePrefCookie();
|
||||
removeStoragePrefCookie()
|
||||
if (svgEditor.configObj.curConfig.emptyStorageOnDecline && e?.detail?.checkbox) {
|
||||
this.setSvgContentStorage('');
|
||||
this.setSvgContentStorage('')
|
||||
Object.keys(svgEditor.curPrefs).forEach((name) => {
|
||||
name = 'svg-edit-' + name;
|
||||
name = 'svg-edit-' + name
|
||||
if (svgEditor.storage) {
|
||||
svgEditor.storage.removeItem(name);
|
||||
svgEditor.storage.removeItem(name)
|
||||
}
|
||||
expireCookie(name);
|
||||
});
|
||||
expireCookie(name)
|
||||
})
|
||||
}
|
||||
if (e?.detail?.select && e?.detail?.checkbox) {
|
||||
replaceStoragePrompt('false');
|
||||
return;
|
||||
replaceStoragePrompt('false')
|
||||
return
|
||||
}
|
||||
}
|
||||
} else if (e?.detail?.trigger === 'cancel') {
|
||||
removeStoragePrefCookie();
|
||||
removeStoragePrefCookie()
|
||||
}
|
||||
setupBeforeUnloadListener();
|
||||
svgEditor.storagePromptState = 'closed';
|
||||
svgEditor.updateCanvas(true);
|
||||
});
|
||||
setupBeforeUnloadListener()
|
||||
svgEditor.storagePromptState = 'closed'
|
||||
svgEditor.updateCanvas(true)
|
||||
})
|
||||
|
||||
/**
|
||||
* Sets SVG content as a string with "svgedit-" and the current
|
||||
@@ -130,11 +130,11 @@ export default {
|
||||
*/
|
||||
function setSvgContentStorage (val) {
|
||||
if (storage) {
|
||||
const name = 'svgedit-' + svgEditor.configObj.curConfig.canvasName;
|
||||
const name = 'svgedit-' + svgEditor.configObj.curConfig.canvasName
|
||||
if (!val) {
|
||||
storage.removeItem(name);
|
||||
storage.removeItem(name)
|
||||
} else {
|
||||
storage.setItem(name, val);
|
||||
storage.setItem(name, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,46 +152,46 @@ export default {
|
||||
window.addEventListener('beforeunload', function () {
|
||||
// Don't save anything unless the user opted in to storage
|
||||
if (!(/(?:^|;\s*)svgeditstore=(?:prefsAndContent|prefsOnly)/).test(document.cookie)) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
if ((/(?:^|;\s*)svgeditstore=prefsAndContent/).test(document.cookie)) {
|
||||
setSvgContentStorage(svgCanvas.getSvgString());
|
||||
setSvgContentStorage(svgCanvas.getSvgString())
|
||||
}
|
||||
|
||||
svgEditor.setConfig({ no_save_warning: true }); // No need for explicit saving at all once storage is on
|
||||
svgEditor.setConfig({ no_save_warning: true }) // No need for explicit saving at all once storage is on
|
||||
// svgEditor.showSaveWarning = false;
|
||||
|
||||
const { curPrefs } = svgEditor.configObj;
|
||||
const { curPrefs } = svgEditor.configObj
|
||||
|
||||
Object.entries(curPrefs).forEach(([ key, val ]) => {
|
||||
const store = (val !== undefined);
|
||||
key = 'svg-edit-' + key;
|
||||
Object.entries(curPrefs).forEach(([key, val]) => {
|
||||
const store = (val !== undefined)
|
||||
key = 'svg-edit-' + key
|
||||
if (!store) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
if (storage) {
|
||||
storage.setItem(key, val);
|
||||
storage.setItem(key, val)
|
||||
} else if (window.widget) {
|
||||
window.widget.setPreferenceForKey(val, key);
|
||||
window.widget.setPreferenceForKey(val, key)
|
||||
} else {
|
||||
val = encodeURIComponent(val);
|
||||
document.cookie = encodeURIComponent(key) + '=' + val + '; expires=Fri, 31 Dec 9999 23:59:59 GMT';
|
||||
val = encodeURIComponent(val)
|
||||
document.cookie = encodeURIComponent(key) + '=' + val + '; expires=Fri, 31 Dec 9999 23:59:59 GMT'
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
let loaded = false;
|
||||
let loaded = false
|
||||
return {
|
||||
name: 'storage',
|
||||
callback () {
|
||||
const storagePrompt = new URL(top.location).searchParams.get('storagePrompt');
|
||||
const storagePrompt = new URL(top.location).searchParams.get('storagePrompt')
|
||||
// No need to run this one-time dialog again just because the user
|
||||
// changes the language
|
||||
if (loaded) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
loaded = true;
|
||||
loaded = true
|
||||
|
||||
// Note that the following can load even if "noStorageOnLoad" is
|
||||
// set to false; to avoid any chance of storage, avoid this
|
||||
@@ -213,17 +213,17 @@ export default {
|
||||
)
|
||||
// ...then show the storage prompt.
|
||||
)) {
|
||||
const options = Boolean(storage);
|
||||
const options = Boolean(storage)
|
||||
// Open select-with-checkbox dialog
|
||||
// From svg-editor.js
|
||||
svgEditor.storagePromptState = 'waiting';
|
||||
const $storageDialog = document.getElementById('se-storage-dialog');
|
||||
$storageDialog.setAttribute('dialog', 'open');
|
||||
$storageDialog.setAttribute('storage', options);
|
||||
svgEditor.storagePromptState = 'waiting'
|
||||
const $storageDialog = document.getElementById('se-storage-dialog')
|
||||
$storageDialog.setAttribute('dialog', 'open')
|
||||
$storageDialog.setAttribute('storage', options)
|
||||
} else if (!noStorageOnLoad || forceStorage) {
|
||||
setupBeforeUnloadListener();
|
||||
setupBeforeUnloadListener()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,4 +11,4 @@ export default {
|
||||
storageNoPrefs: 'Do not store my preferences locally',
|
||||
rememberLabel: 'Remember this choice?',
|
||||
rememberTooltip: 'If you choose to opt out of storage while remembering this choice, the URL will change so as to avoid asking again.'
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,4 +11,4 @@ export default {
|
||||
storageNoPrefs: 'Do not store my preferences locally',
|
||||
rememberLabel: 'Remember this choice?',
|
||||
rememberTooltip: 'If you choose to opt out of storage while remembering this choice, the URL will change so as to avoid asking again.'
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,4 +11,4 @@ export default {
|
||||
storageNoPrefs: 'Do not store my preferences locally',
|
||||
rememberLabel: 'Remember this choice?',
|
||||
rememberTooltip: "Si vous choisissez de désactiver le stockage en mémorisant le choix, l'URL va changer afin que la question ne vous soit plus reposée."
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,4 +8,4 @@ export default {
|
||||
storageNoPrefs: '本地不保存配置参数',
|
||||
rememberLabel: '记住选择?',
|
||||
rememberTooltip: '如果您勾选记住选择,将不再弹出本窗口.'
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import storageDialogHTML from './storageDialog.html';
|
||||
import storageDialogHTML from './storageDialog.html'
|
||||
|
||||
const template = document.createElement('template');
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
template.innerHTML = storageDialogHTML;
|
||||
const template = document.createElement('template')
|
||||
template.innerHTML = storageDialogHTML
|
||||
/**
|
||||
* @class SeStorageDialog
|
||||
*/
|
||||
@@ -11,39 +10,42 @@ export class SeStorageDialog 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('#dialog_box');
|
||||
this.$storage = this._shadowRoot.querySelector('#js-storage');
|
||||
this.$okBtn = this._shadowRoot.querySelector('#storage_ok');
|
||||
this.$cancelBtn = this._shadowRoot.querySelector('#storage_cancel');
|
||||
this.$storageInput = this._shadowRoot.querySelector('#se-storage-pref');
|
||||
this.$rememberInput = this._shadowRoot.querySelector('#se-remember');
|
||||
this._shadowRoot = this.attachShadow({ mode: 'open' })
|
||||
this._shadowRoot.append(template.content.cloneNode(true))
|
||||
this.$dialog = this._shadowRoot.querySelector('#dialog_box')
|
||||
this.$storage = this._shadowRoot.querySelector('#js-storage')
|
||||
this.$okBtn = this._shadowRoot.querySelector('#storage_ok')
|
||||
this.$cancelBtn = this._shadowRoot.querySelector('#storage_cancel')
|
||||
this.$storageInput = this._shadowRoot.querySelector('#se-storage-pref')
|
||||
this.$rememberInput = this._shadowRoot.querySelector('#se-remember')
|
||||
}
|
||||
|
||||
/**
|
||||
* @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('notify-editor_pref_msg', i18next.t('notification.editorPreferencesMsg'));
|
||||
this.setAttribute('properties-prefs_and_content', i18next.t('properties.prefs_and_content'));
|
||||
this.setAttribute('properties-prefs_only', i18next.t('properties.prefs_only'));
|
||||
this.setAttribute('properties-no_prefs_or_content', i18next.t('properties.no_prefs_or_content'));
|
||||
this.setAttribute('tools-remember_this_choice', i18next.t('tools.remember_this_choice'));
|
||||
this.setAttribute('tools-remember_this_choice_title', i18next.t('tools.remember_this_choice_title'));
|
||||
this.setAttribute('common-ok', i18next.t('common.ok'))
|
||||
this.setAttribute('common-cancel', i18next.t('common.cancel'))
|
||||
this.setAttribute('notify-editor_pref_msg', i18next.t('notification.editorPreferencesMsg'))
|
||||
this.setAttribute('properties-prefs_and_content', i18next.t('properties.prefs_and_content'))
|
||||
this.setAttribute('properties-prefs_only', i18next.t('properties.prefs_only'))
|
||||
this.setAttribute('properties-no_prefs_or_content', i18next.t('properties.no_prefs_or_content'))
|
||||
this.setAttribute('tools-remember_this_choice', i18next.t('tools.remember_this_choice'))
|
||||
this.setAttribute('tools-remember_this_choice_title', i18next.t('tools.remember_this_choice_title'))
|
||||
}
|
||||
|
||||
/**
|
||||
* @function observedAttributes
|
||||
* @returns {any} observed
|
||||
*/
|
||||
static get observedAttributes () {
|
||||
return [ 'dialog', 'storage', 'common-ok', 'common-cancel', 'notify-editor_pref_msg', 'properties-prefs_and_content', 'tools-remember_this_choice', 'tools-remember_this_choice_title', 'properties-prefs_only', 'properties-no_prefs_or_content' ];
|
||||
return ['dialog', 'storage', 'common-ok', 'common-cancel', 'notify-editor_pref_msg', 'properties-prefs_and_content', 'tools-remember_this_choice', 'tools-remember_this_choice_title', 'properties-prefs_only', 'properties-no_prefs_or_content']
|
||||
}
|
||||
|
||||
/**
|
||||
* @function attributeChangedCallback
|
||||
* @param {string} name
|
||||
@@ -52,87 +54,93 @@ export class SeStorageDialog 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 'storage':
|
||||
if (newValue === 'true') {
|
||||
this.$storageInput.options[0].disabled = false;
|
||||
} else {
|
||||
this.$storageInput.options[0].disabled = true;
|
||||
}
|
||||
break;
|
||||
case 'common-ok':
|
||||
this.$okBtn.textContent = newValue;
|
||||
break;
|
||||
case 'common-cancel':
|
||||
this.$cancelBtn.textContent = newValue;
|
||||
break;
|
||||
case 'notify-editor_pref_msg':
|
||||
node = this._shadowRoot.querySelector('#notificationNote');
|
||||
node.textContent = newValue;
|
||||
break;
|
||||
case 'properties-prefs_and_content':
|
||||
node = this._shadowRoot.querySelector('#prefsAndContent');
|
||||
node.textContent = newValue;
|
||||
break;
|
||||
case 'properties-prefs_only':
|
||||
node = this._shadowRoot.querySelector('#prefsOnly');
|
||||
node.textContent = newValue;
|
||||
break;
|
||||
case 'properties-no_prefs_or_content':
|
||||
node = this._shadowRoot.querySelector('#noPrefsOrContent');
|
||||
node.textContent = newValue;
|
||||
break;
|
||||
case 'tools-remember_this_choice':
|
||||
node = this._shadowRoot.querySelector('#se-remember-title');
|
||||
node.prepend(newValue);
|
||||
break;
|
||||
case 'tools-remember_this_choice_title':
|
||||
node = this._shadowRoot.querySelector('#se-remember-title');
|
||||
node.setAttribute('title', newValue);
|
||||
break;
|
||||
default:
|
||||
case 'dialog':
|
||||
if (newValue === 'open') {
|
||||
this.$dialog.open()
|
||||
} else {
|
||||
this.$dialog.close()
|
||||
}
|
||||
break
|
||||
case 'storage':
|
||||
if (newValue === 'true') {
|
||||
this.$storageInput.options[0].disabled = false
|
||||
} else {
|
||||
this.$storageInput.options[0].disabled = true
|
||||
}
|
||||
break
|
||||
case 'common-ok':
|
||||
this.$okBtn.textContent = newValue
|
||||
break
|
||||
case 'common-cancel':
|
||||
this.$cancelBtn.textContent = newValue
|
||||
break
|
||||
case 'notify-editor_pref_msg':
|
||||
node = this._shadowRoot.querySelector('#notificationNote')
|
||||
node.textContent = newValue
|
||||
break
|
||||
case 'properties-prefs_and_content':
|
||||
node = this._shadowRoot.querySelector('#prefsAndContent')
|
||||
node.textContent = newValue
|
||||
break
|
||||
case 'properties-prefs_only':
|
||||
node = this._shadowRoot.querySelector('#prefsOnly')
|
||||
node.textContent = newValue
|
||||
break
|
||||
case 'properties-no_prefs_or_content':
|
||||
node = this._shadowRoot.querySelector('#noPrefsOrContent')
|
||||
node.textContent = newValue
|
||||
break
|
||||
case 'tools-remember_this_choice':
|
||||
node = this._shadowRoot.querySelector('#se-remember-title')
|
||||
node.prepend(newValue)
|
||||
break
|
||||
case 'tools-remember_this_choice_title':
|
||||
node = this._shadowRoot.querySelector('#se-remember-title')
|
||||
node.setAttribute('title', 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 () {
|
||||
const onSubmitHandler = (e, action) => {
|
||||
const triggerEvent = new CustomEvent('change', { detail: {
|
||||
trigger: action,
|
||||
select: this.$storageInput.value,
|
||||
checkbox: this.$rememberInput.checked
|
||||
} });
|
||||
this.dispatchEvent(triggerEvent);
|
||||
};
|
||||
this.$okBtn.addEventListener('click', (evt) => onSubmitHandler(evt, 'ok'));
|
||||
this.$cancelBtn.addEventListener('click', (evt) => onSubmitHandler(evt, 'cancel'));
|
||||
const triggerEvent = new CustomEvent('change', {
|
||||
detail: {
|
||||
trigger: action,
|
||||
select: this.$storageInput.value,
|
||||
checkbox: this.$rememberInput.checked
|
||||
}
|
||||
})
|
||||
this.dispatchEvent(triggerEvent)
|
||||
}
|
||||
this.$okBtn.addEventListener('click', (evt) => onSubmitHandler(evt, 'ok'))
|
||||
this.$cancelBtn.addEventListener('click', (evt) => onSubmitHandler(evt, 'cancel'))
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets SVG content as a string with "svgedit-" and the current
|
||||
* canvas name as namespace.
|
||||
@@ -141,15 +149,15 @@ export class SeStorageDialog extends HTMLElement {
|
||||
*/
|
||||
setSvgContentStorage (val) {
|
||||
if (this.storage) {
|
||||
const name = 'svgedit-' + this.configObj.curConfig.canvasName;
|
||||
const name = 'svgedit-' + this.configObj.curConfig.canvasName
|
||||
if (!val) {
|
||||
this.storage.removeItem(name);
|
||||
this.storage.removeItem(name)
|
||||
} else {
|
||||
this.storage.setItem(name, val);
|
||||
this.storage.setItem(name, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Register
|
||||
customElements.define('se-storage-dialog', SeStorageDialog);
|
||||
customElements.define('se-storage-dialog', SeStorageDialog)
|
||||
|
||||
@@ -30,26 +30,26 @@
|
||||
<!-- If you do not wish to add extensions by URL, you can add calls
|
||||
within the following file to svgEditor.setConfig -->
|
||||
<script type="module">
|
||||
import Editor from './Editor.js';
|
||||
/* for available options see the file `docs/tutorials/ConfigOptions.md */
|
||||
const svgEditor = new Editor(document.getElementById('container'));
|
||||
svgEditor.init();
|
||||
svgEditor.setConfig({
|
||||
import Editor from './Editor.js'
|
||||
/* for available options see the file `docs/tutorials/ConfigOptions.md */
|
||||
const svgEditor = new Editor(document.getElementById('container'))
|
||||
svgEditor.init()
|
||||
svgEditor.setConfig({
|
||||
allowInitialUserOverride: true,
|
||||
extensions: [],
|
||||
noDefaultExtensions: false,
|
||||
userExtensions: [/* '../ext-helloworld/ext-helloworld.js' */]
|
||||
});
|
||||
// Variable XDOMAIN below is created by Rollup for the Xdomain build (see rollup.config.js)
|
||||
/* globals XDOMAIN */
|
||||
try { // try clause to avoid js to complain if XDOMAIN undefined
|
||||
})
|
||||
// Variable XDOMAIN below is created by Rollup for the Xdomain build (see rollup.config.js)
|
||||
/* globals XDOMAIN */
|
||||
try { // try clause to avoid js to complain if XDOMAIN undefined
|
||||
if (XDOMAIN) {
|
||||
svgEditor.setConfig({
|
||||
canvasName: 'xdomain', // Namespace this
|
||||
allowedOrigins: [ '*' ]
|
||||
});
|
||||
console.info('xdomain config activated');
|
||||
}
|
||||
} catch (error) {/* empty fn */ }
|
||||
})
|
||||
console.info('xdomain config activated')
|
||||
}
|
||||
} catch (error) { /* empty fn */ }
|
||||
</script>
|
||||
</html>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user