Add support for working with online rendering service when available
This commit is contained in:
parent
eaef4a3f47
commit
78cec2be8c
|
@ -39,7 +39,7 @@ function readEncoded(str, encoding) {
|
||||||
.from(decodeURIComponent(str), 'base64')
|
.from(decodeURIComponent(str), 'base64')
|
||||||
.toString('utf8');
|
.toString('utf8');
|
||||||
case 'uri':
|
case 'uri':
|
||||||
return str.split('/').map((ln) => decodeURIComponent(ln)).join('\n');
|
return str.split('/').map(decodeURIComponent).join('\n');
|
||||||
default:
|
default:
|
||||||
throw new HttpError(400, 'Unknown encoding');
|
throw new HttpError(400, 'Unknown encoding');
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
https://cdnjs.cloudflare.com
|
https://cdnjs.cloudflare.com
|
||||||
'sha256-s7UPtBgvov5WNF9C1DlTZDpqwLgEmfiWha5a5p/Zn7E='
|
'sha256-s7UPtBgvov5WNF9C1DlTZDpqwLgEmfiWha5a5p/Zn7E='
|
||||||
;
|
;
|
||||||
|
connect-src 'self';
|
||||||
font-src 'self' data:;
|
font-src 'self' data:;
|
||||||
img-src 'self' blob:;
|
img-src 'self' blob:;
|
||||||
form-action 'none';
|
form-action 'none';
|
||||||
|
|
|
@ -10065,6 +10065,7 @@
|
||||||
this.parentNode = null;
|
this.parentNode = null;
|
||||||
this.childNodes = [];
|
this.childNodes = [];
|
||||||
this.attributes = new Map();
|
this.attributes = new Map();
|
||||||
|
this.style = {};
|
||||||
this.listeners = new Map();
|
this.listeners = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@ class ElementNode {
|
||||||
this.parentNode = null;
|
this.parentNode = null;
|
||||||
this.childNodes = [];
|
this.childNodes = [];
|
||||||
this.attributes = new Map();
|
this.attributes = new Map();
|
||||||
|
this.style = {};
|
||||||
this.listeners = new Map();
|
this.listeners = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -265,7 +265,6 @@ html, body {
|
||||||
.options {
|
.options {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: #FFFFFF;
|
background: #FFFFFF;
|
||||||
overflow: hidden;
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
z-index: 30;
|
z-index: 30;
|
||||||
}
|
}
|
||||||
|
@ -284,6 +283,8 @@ html, body {
|
||||||
border-top-left-radius: 5px;
|
border-top-left-radius: 5px;
|
||||||
border-top: 1px solid #EEEEEE;
|
border-top: 1px solid #EEEEEE;
|
||||||
border-left: 1px solid #EEEEEE;
|
border-left: 1px solid #EEEEEE;
|
||||||
|
transition: 0.2s ease;
|
||||||
|
transition-property: box-shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
.options a {
|
.options a {
|
||||||
|
@ -305,3 +306,85 @@ html, body {
|
||||||
background: #EEEEEE;
|
background: #EEEEEE;
|
||||||
color: #6666CC;
|
color: #6666CC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.urlbuilder {
|
||||||
|
border-top: 1px solid #EEEEEE;
|
||||||
|
overflow: auto;
|
||||||
|
box-sizing: border-box;
|
||||||
|
transition: 0.2s ease;
|
||||||
|
transition-property: height, width, padding;
|
||||||
|
font-size: 0.8em;
|
||||||
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.urlbuilder .message {
|
||||||
|
color: #666666;
|
||||||
|
font-size: 1.5em;
|
||||||
|
padding-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.urlbuilder .config {
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.urlbuilder input[type=number] {
|
||||||
|
width: 60px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.urlbuilder .or {
|
||||||
|
display: block;
|
||||||
|
margin: 10px 0;
|
||||||
|
color: #333333;
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.urlbuilder .output {
|
||||||
|
display: block;
|
||||||
|
padding: 6px;
|
||||||
|
height: 30px;
|
||||||
|
border: 1px solid #999999;
|
||||||
|
border-right: none;
|
||||||
|
font-size: 1em;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10px;
|
||||||
|
left: 10px;
|
||||||
|
width: calc(100% - 50px);
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.urlbuilder .copy {
|
||||||
|
display: block;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
line-height: 28px;
|
||||||
|
padding-top: 1px;
|
||||||
|
border: 1px solid #999999;
|
||||||
|
background: #FFFFFF;
|
||||||
|
font-size: 1em;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10px;
|
||||||
|
right: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.urlbuilder .copy:active {
|
||||||
|
background: #EEEEEE;
|
||||||
|
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||||
|
padding-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.urlbuilder .copied {
|
||||||
|
display: none;
|
||||||
|
height: 30px;
|
||||||
|
border: 1px solid #999999;
|
||||||
|
font-size: 1em;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10px;
|
||||||
|
left: 10px;
|
||||||
|
width: calc(100% - 20px);
|
||||||
|
line-height: 28px;
|
||||||
|
background: #99EE99;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* eslint-disable max-lines */
|
||||||
|
|
||||||
import DOMWrapper from '../../scripts/core/DOMWrapper.mjs';
|
import DOMWrapper from '../../scripts/core/DOMWrapper.mjs';
|
||||||
|
|
||||||
const DELAY_AGENTCHANGE = 500;
|
const DELAY_AGENTCHANGE = 500;
|
||||||
|
@ -36,6 +38,54 @@ function simplifyPreview(code) {
|
||||||
.replace(/[{}]/g, '');
|
.replace(/[{}]/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toCappedFixed(v, cap) {
|
||||||
|
const s = v.toString();
|
||||||
|
const p = s.indexOf('.');
|
||||||
|
if(p === -1 || s.length - p - 1 <= cap) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
return v.toFixed(cap);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchResource(path) {
|
||||||
|
if(typeof fetch === 'undefined') {
|
||||||
|
return Promise.reject(new Error());
|
||||||
|
}
|
||||||
|
return fetch(path)
|
||||||
|
.then((response) => {
|
||||||
|
if(!response.ok) {
|
||||||
|
throw new Error(response.statusText);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eslint-disable complexity */
|
||||||
|
function makeURL(code, {height, width, zoom}) {
|
||||||
|
/* eslint-enable complexity */
|
||||||
|
const uri = code
|
||||||
|
.split('\n')
|
||||||
|
.map(encodeURIComponent)
|
||||||
|
.filter((ln) => ln !== '')
|
||||||
|
.join('/');
|
||||||
|
|
||||||
|
let opts = '';
|
||||||
|
if(!Number.isNaN(width) || !Number.isNaN(height)) {
|
||||||
|
if(!Number.isNaN(width)) {
|
||||||
|
opts += 'w' + toCappedFixed(Math.max(width, 0), 4);
|
||||||
|
}
|
||||||
|
if(!Number.isNaN(height)) {
|
||||||
|
opts += 'h' + toCappedFixed(Math.max(height, 0), 4);
|
||||||
|
}
|
||||||
|
opts += '/';
|
||||||
|
} else if(!Number.isNaN(zoom) && zoom !== 1) {
|
||||||
|
opts += 'z' + toCappedFixed(Math.max(zoom, 0), 4);
|
||||||
|
opts += '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
return opts + uri + '.svg';
|
||||||
|
}
|
||||||
|
|
||||||
function makeSplit(require, nodes, options) {
|
function makeSplit(require, nodes, options) {
|
||||||
// Load on demand for progressive enhancement
|
// Load on demand for progressive enhancement
|
||||||
// (failure to load external module will not block functionality)
|
// (failure to load external module will not block functionality)
|
||||||
|
@ -142,6 +192,7 @@ export default class Interface {
|
||||||
this._downloadSVGClick = this._downloadSVGClick.bind(this);
|
this._downloadSVGClick = this._downloadSVGClick.bind(this);
|
||||||
this._downloadPNGClick = this._downloadPNGClick.bind(this);
|
this._downloadPNGClick = this._downloadPNGClick.bind(this);
|
||||||
this._downloadPNGFocus = this._downloadPNGFocus.bind(this);
|
this._downloadPNGFocus = this._downloadPNGFocus.bind(this);
|
||||||
|
this._downloadURLClick = this._downloadURLClick.bind(this);
|
||||||
this._showDropStyle = this._showDropStyle.bind(this);
|
this._showDropStyle = this._showDropStyle.bind(this);
|
||||||
this._hideDropStyle = this._hideDropStyle.bind(this);
|
this._hideDropStyle = this._hideDropStyle.bind(this);
|
||||||
|
|
||||||
|
@ -189,12 +240,169 @@ export default class Interface {
|
||||||
);
|
);
|
||||||
this.code.focus();
|
this.code.focus();
|
||||||
}
|
}
|
||||||
|
this._hideURLBuilder();
|
||||||
})
|
})
|
||||||
.on('dblclick', (element) => {
|
.on('dblclick', (element) => {
|
||||||
this.diagram.toggleCollapsed(element.ln);
|
this.diagram.toggleCollapsed(element.ln);
|
||||||
|
this._hideURLBuilder();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildURLBuilder() {
|
||||||
|
const copied = this.dom.el('div').setClass('copied')
|
||||||
|
.add('Copied to Clipboard');
|
||||||
|
this.urlOutput = this.dom.el('input').setClass('output')
|
||||||
|
.attr('readonly', 'readonly')
|
||||||
|
.on('focus', () => {
|
||||||
|
this.urlOutput.select(0, this.urlOutput.element.value.length);
|
||||||
|
});
|
||||||
|
|
||||||
|
const copy = this.dom.el('button').setClass('copy')
|
||||||
|
.add('\uD83D\uDCCB')
|
||||||
|
.attr('title', 'Copy to clipboard')
|
||||||
|
.on('click', () => {
|
||||||
|
this.urlOutput
|
||||||
|
.focus()
|
||||||
|
.select(0, this.urlOutput.element.value.length)
|
||||||
|
.element.ownerDocument.execCommand('copy');
|
||||||
|
copy.focus();
|
||||||
|
copied.styles({
|
||||||
|
'display': 'block',
|
||||||
|
'opacity': 1,
|
||||||
|
'transition': 'none',
|
||||||
|
});
|
||||||
|
setTimeout(() => copied.styles({
|
||||||
|
'opacity': 0,
|
||||||
|
'transition': 'opacity 0.5s linear',
|
||||||
|
}), 1000);
|
||||||
|
setTimeout(() => copied.styles({'display': 'none'}), 1500);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.urlWidth = this.dom.el('input').attrs({
|
||||||
|
'min': 0,
|
||||||
|
'placeholder': 'auto',
|
||||||
|
'step': 'any',
|
||||||
|
'type': 'number',
|
||||||
|
}).on('input', () => {
|
||||||
|
this.urlZoom.val('1');
|
||||||
|
this._refreshURL();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.urlHeight = this.dom.el('input').attrs({
|
||||||
|
'min': 0,
|
||||||
|
'placeholder': 'auto',
|
||||||
|
'step': 'any',
|
||||||
|
'type': 'number',
|
||||||
|
}).on('input', () => {
|
||||||
|
this.urlZoom.val('1');
|
||||||
|
this._refreshURL();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.urlZoom = this.dom.el('input').attrs({
|
||||||
|
'min': 0,
|
||||||
|
'step': 'any',
|
||||||
|
'type': 'number',
|
||||||
|
'value': 1,
|
||||||
|
}).on('input', () => {
|
||||||
|
this.urlWidth.val('');
|
||||||
|
this.urlHeight.val('');
|
||||||
|
this._refreshURL();
|
||||||
|
});
|
||||||
|
|
||||||
|
const urlOpts = this.dom.el('div').setClass('config').add(
|
||||||
|
this.dom.el('label').add('width ', this.urlWidth),
|
||||||
|
', ',
|
||||||
|
this.dom.el('label').add('height ', this.urlHeight),
|
||||||
|
this.dom.el('span').setClass('or').add('or'),
|
||||||
|
this.dom.el('label').add('zoom ', this.urlZoom),
|
||||||
|
this.urlOutput,
|
||||||
|
copy,
|
||||||
|
copied
|
||||||
|
);
|
||||||
|
|
||||||
|
this.urlBuilder = this.dom.el('div').setClass('urlbuilder')
|
||||||
|
.styles({'display': 'none'})
|
||||||
|
.add(
|
||||||
|
this.dom.el('div').setClass('message')
|
||||||
|
.add('Loading\u2026')
|
||||||
|
);
|
||||||
|
|
||||||
|
this.renderService = '';
|
||||||
|
const relativePath = 'render/';
|
||||||
|
fetchResource(relativePath)
|
||||||
|
.then((response) => response.text())
|
||||||
|
.then((content) => {
|
||||||
|
let path = content.trim();
|
||||||
|
if(!path || path.startsWith('<svg')) {
|
||||||
|
path = relativePath;
|
||||||
|
}
|
||||||
|
this.renderService = new URL(path, window.location.href).href;
|
||||||
|
this.urlBuilder.empty().add(urlOpts);
|
||||||
|
this._refreshURL();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.urlBuilder.empty().add(
|
||||||
|
this.dom.el('div').setClass('message')
|
||||||
|
.add('No online rendering service available.')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.urlBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
_refreshURL() {
|
||||||
|
this.urlOutput.val(this.renderService + makeURL(this.value(), {
|
||||||
|
height: Number.parseFloat(this.urlHeight.element.value),
|
||||||
|
width: Number.parseFloat(this.urlWidth.element.value),
|
||||||
|
zoom: Number.parseFloat(this.urlZoom.element.value || '1'),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
_showURLBuilder() {
|
||||||
|
if(this.builderVisible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.builderVisible = true;
|
||||||
|
this.urlBuilder.styles({
|
||||||
|
'display': 'block',
|
||||||
|
'height': '0px',
|
||||||
|
'padding': '0px',
|
||||||
|
'width': this.optsHold.element.clientWidth + 'px',
|
||||||
|
});
|
||||||
|
clearTimeout(this.builderTm);
|
||||||
|
this.builderTm = setTimeout(() => {
|
||||||
|
this.urlBuilder.styles({
|
||||||
|
'height': '150px',
|
||||||
|
'padding': '10px',
|
||||||
|
'width': '400px',
|
||||||
|
});
|
||||||
|
this.optsHold.styles({
|
||||||
|
'box-shadow': '10px 10px 25px 12px rgba(0,0,0,0.3)',
|
||||||
|
});
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
this._refreshURL();
|
||||||
|
}
|
||||||
|
|
||||||
|
_hideURLBuilder() {
|
||||||
|
if(!this.builderVisible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.builderVisible = false;
|
||||||
|
this.urlBuilder.styles({
|
||||||
|
'height': '0px',
|
||||||
|
'padding': '0px',
|
||||||
|
'width': '0px',
|
||||||
|
});
|
||||||
|
this.optsHold.styles({
|
||||||
|
'box-shadow': 'none',
|
||||||
|
});
|
||||||
|
clearTimeout(this.builderTm);
|
||||||
|
this.builderTm = setTimeout(() => {
|
||||||
|
this.urlBuilder.styles({'display': 'none'});
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
|
||||||
buildOptionsDownloads() {
|
buildOptionsDownloads() {
|
||||||
this.downloadPNG = this.dom.el('a')
|
this.downloadPNG = this.dom.el('a')
|
||||||
.text('Download PNG')
|
.text('Download PNG')
|
||||||
|
@ -213,8 +421,19 @@ export default class Interface {
|
||||||
})
|
})
|
||||||
.on('click', this._downloadSVGClick);
|
.on('click', this._downloadSVGClick);
|
||||||
|
|
||||||
return this.dom.el('div').setClass('options downloads')
|
this.downloadURL = this.dom.el('a')
|
||||||
.add(this.downloadPNG, this.downloadSVG);
|
.text('URL')
|
||||||
|
.attrs({'href': '#'})
|
||||||
|
.on('click', this._downloadURLClick);
|
||||||
|
|
||||||
|
this.optsHold = this.dom.el('div').setClass('options downloads').add(
|
||||||
|
this.downloadPNG,
|
||||||
|
this.downloadSVG,
|
||||||
|
this.downloadURL,
|
||||||
|
this.buildURLBuilder()
|
||||||
|
);
|
||||||
|
|
||||||
|
return this.optsHold;
|
||||||
}
|
}
|
||||||
|
|
||||||
buildLibrary(container) {
|
buildLibrary(container) {
|
||||||
|
@ -250,7 +469,8 @@ export default class Interface {
|
||||||
|
|
||||||
buildViewPane() {
|
buildViewPane() {
|
||||||
this.viewPaneInner = this.dom.el('div').setClass('pane-view-inner')
|
this.viewPaneInner = this.dom.el('div').setClass('pane-view-inner')
|
||||||
.add(this.diagram.dom());
|
.add(this.diagram.dom())
|
||||||
|
.on('click', () => this._hideURLBuilder());
|
||||||
|
|
||||||
this.errorMsg = this.dom.el('div').setClass('msg-error');
|
this.errorMsg = this.dom.el('div').setClass('msg-error');
|
||||||
|
|
||||||
|
@ -336,6 +556,14 @@ export default class Interface {
|
||||||
snapOffset: 70,
|
snapOffset: 70,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(typeof window !== 'undefined') {
|
||||||
|
window.addEventListener('keydown', (e) => {
|
||||||
|
if(e.keyCode === 27) {
|
||||||
|
this._hideURLBuilder();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Delay first update 1 frame to ensure render target is ready
|
// Delay first update 1 frame to ensure render target is ready
|
||||||
// (prevents initial incorrect font calculations for custom fonts)
|
// (prevents initial incorrect font calculations for custom fonts)
|
||||||
setTimeout(this.update.bind(this), 0);
|
setTimeout(this.update.bind(this), 0);
|
||||||
|
@ -463,6 +691,7 @@ export default class Interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
update(immediate = true) {
|
update(immediate = true) {
|
||||||
|
this._hideURLBuilder();
|
||||||
const src = this.value();
|
const src = this.value();
|
||||||
this.saveCode(src);
|
this.saveCode(src);
|
||||||
let sequence = null;
|
let sequence = null;
|
||||||
|
@ -529,12 +758,24 @@ export default class Interface {
|
||||||
} else if(this.updatePNGLink()) {
|
} else if(this.updatePNGLink()) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
this._hideURLBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
_downloadSVGClick() {
|
_downloadSVGClick() {
|
||||||
this.forceRender();
|
this.forceRender();
|
||||||
const url = this.diagram.getSVGSynchronous();
|
const url = this.diagram.getSVGSynchronous();
|
||||||
this.downloadSVG.attr('href', url);
|
this.downloadSVG.attr('href', url);
|
||||||
|
this._hideURLBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
_downloadURLClick(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if(this.builderVisible) {
|
||||||
|
this._hideURLBuilder();
|
||||||
|
} else {
|
||||||
|
this._showURLBuilder();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_enhanceEditor() {
|
_enhanceEditor() {
|
||||||
|
|
247
weblib/editor.js
247
weblib/editor.js
|
@ -504,6 +504,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* eslint-disable max-lines */
|
||||||
|
|
||||||
const DELAY_AGENTCHANGE = 500;
|
const DELAY_AGENTCHANGE = 500;
|
||||||
const DELAY_STAGECHANGE = 250;
|
const DELAY_STAGECHANGE = 250;
|
||||||
const PNG_RESOLUTION = 4;
|
const PNG_RESOLUTION = 4;
|
||||||
|
@ -540,6 +542,54 @@
|
||||||
.replace(/[{}]/g, '');
|
.replace(/[{}]/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toCappedFixed(v, cap) {
|
||||||
|
const s = v.toString();
|
||||||
|
const p = s.indexOf('.');
|
||||||
|
if(p === -1 || s.length - p - 1 <= cap) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
return v.toFixed(cap);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchResource(path) {
|
||||||
|
if(typeof fetch === 'undefined') {
|
||||||
|
return Promise.reject(new Error());
|
||||||
|
}
|
||||||
|
return fetch(path)
|
||||||
|
.then((response) => {
|
||||||
|
if(!response.ok) {
|
||||||
|
throw new Error(response.statusText);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eslint-disable complexity */
|
||||||
|
function makeURL(code, {height, width, zoom}) {
|
||||||
|
/* eslint-enable complexity */
|
||||||
|
const uri = code
|
||||||
|
.split('\n')
|
||||||
|
.map(encodeURIComponent)
|
||||||
|
.filter((ln) => ln !== '')
|
||||||
|
.join('/');
|
||||||
|
|
||||||
|
let opts = '';
|
||||||
|
if(!Number.isNaN(width) || !Number.isNaN(height)) {
|
||||||
|
if(!Number.isNaN(width)) {
|
||||||
|
opts += 'w' + toCappedFixed(Math.max(width, 0), 4);
|
||||||
|
}
|
||||||
|
if(!Number.isNaN(height)) {
|
||||||
|
opts += 'h' + toCappedFixed(Math.max(height, 0), 4);
|
||||||
|
}
|
||||||
|
opts += '/';
|
||||||
|
} else if(!Number.isNaN(zoom) && zoom !== 1) {
|
||||||
|
opts += 'z' + toCappedFixed(Math.max(zoom, 0), 4);
|
||||||
|
opts += '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
return opts + uri + '.svg';
|
||||||
|
}
|
||||||
|
|
||||||
function makeSplit(require, nodes, options) {
|
function makeSplit(require, nodes, options) {
|
||||||
// Load on demand for progressive enhancement
|
// Load on demand for progressive enhancement
|
||||||
// (failure to load external module will not block functionality)
|
// (failure to load external module will not block functionality)
|
||||||
|
@ -646,6 +696,7 @@
|
||||||
this._downloadSVGClick = this._downloadSVGClick.bind(this);
|
this._downloadSVGClick = this._downloadSVGClick.bind(this);
|
||||||
this._downloadPNGClick = this._downloadPNGClick.bind(this);
|
this._downloadPNGClick = this._downloadPNGClick.bind(this);
|
||||||
this._downloadPNGFocus = this._downloadPNGFocus.bind(this);
|
this._downloadPNGFocus = this._downloadPNGFocus.bind(this);
|
||||||
|
this._downloadURLClick = this._downloadURLClick.bind(this);
|
||||||
this._showDropStyle = this._showDropStyle.bind(this);
|
this._showDropStyle = this._showDropStyle.bind(this);
|
||||||
this._hideDropStyle = this._hideDropStyle.bind(this);
|
this._hideDropStyle = this._hideDropStyle.bind(this);
|
||||||
|
|
||||||
|
@ -693,12 +744,169 @@
|
||||||
);
|
);
|
||||||
this.code.focus();
|
this.code.focus();
|
||||||
}
|
}
|
||||||
|
this._hideURLBuilder();
|
||||||
})
|
})
|
||||||
.on('dblclick', (element) => {
|
.on('dblclick', (element) => {
|
||||||
this.diagram.toggleCollapsed(element.ln);
|
this.diagram.toggleCollapsed(element.ln);
|
||||||
|
this._hideURLBuilder();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildURLBuilder() {
|
||||||
|
const copied = this.dom.el('div').setClass('copied')
|
||||||
|
.add('Copied to Clipboard');
|
||||||
|
this.urlOutput = this.dom.el('input').setClass('output')
|
||||||
|
.attr('readonly', 'readonly')
|
||||||
|
.on('focus', () => {
|
||||||
|
this.urlOutput.select(0, this.urlOutput.element.value.length);
|
||||||
|
});
|
||||||
|
|
||||||
|
const copy = this.dom.el('button').setClass('copy')
|
||||||
|
.add('\uD83D\uDCCB')
|
||||||
|
.attr('title', 'Copy to clipboard')
|
||||||
|
.on('click', () => {
|
||||||
|
this.urlOutput
|
||||||
|
.focus()
|
||||||
|
.select(0, this.urlOutput.element.value.length)
|
||||||
|
.element.ownerDocument.execCommand('copy');
|
||||||
|
copy.focus();
|
||||||
|
copied.styles({
|
||||||
|
'display': 'block',
|
||||||
|
'opacity': 1,
|
||||||
|
'transition': 'none',
|
||||||
|
});
|
||||||
|
setTimeout(() => copied.styles({
|
||||||
|
'opacity': 0,
|
||||||
|
'transition': 'opacity 0.5s linear',
|
||||||
|
}), 1000);
|
||||||
|
setTimeout(() => copied.styles({'display': 'none'}), 1500);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.urlWidth = this.dom.el('input').attrs({
|
||||||
|
'min': 0,
|
||||||
|
'placeholder': 'auto',
|
||||||
|
'step': 'any',
|
||||||
|
'type': 'number',
|
||||||
|
}).on('input', () => {
|
||||||
|
this.urlZoom.val('1');
|
||||||
|
this._refreshURL();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.urlHeight = this.dom.el('input').attrs({
|
||||||
|
'min': 0,
|
||||||
|
'placeholder': 'auto',
|
||||||
|
'step': 'any',
|
||||||
|
'type': 'number',
|
||||||
|
}).on('input', () => {
|
||||||
|
this.urlZoom.val('1');
|
||||||
|
this._refreshURL();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.urlZoom = this.dom.el('input').attrs({
|
||||||
|
'min': 0,
|
||||||
|
'step': 'any',
|
||||||
|
'type': 'number',
|
||||||
|
'value': 1,
|
||||||
|
}).on('input', () => {
|
||||||
|
this.urlWidth.val('');
|
||||||
|
this.urlHeight.val('');
|
||||||
|
this._refreshURL();
|
||||||
|
});
|
||||||
|
|
||||||
|
const urlOpts = this.dom.el('div').setClass('config').add(
|
||||||
|
this.dom.el('label').add('width ', this.urlWidth),
|
||||||
|
', ',
|
||||||
|
this.dom.el('label').add('height ', this.urlHeight),
|
||||||
|
this.dom.el('span').setClass('or').add('or'),
|
||||||
|
this.dom.el('label').add('zoom ', this.urlZoom),
|
||||||
|
this.urlOutput,
|
||||||
|
copy,
|
||||||
|
copied
|
||||||
|
);
|
||||||
|
|
||||||
|
this.urlBuilder = this.dom.el('div').setClass('urlbuilder')
|
||||||
|
.styles({'display': 'none'})
|
||||||
|
.add(
|
||||||
|
this.dom.el('div').setClass('message')
|
||||||
|
.add('Loading\u2026')
|
||||||
|
);
|
||||||
|
|
||||||
|
this.renderService = '';
|
||||||
|
const relativePath = 'render/';
|
||||||
|
fetchResource(relativePath)
|
||||||
|
.then((response) => response.text())
|
||||||
|
.then((content) => {
|
||||||
|
let path = content.trim();
|
||||||
|
if(!path || path.startsWith('<svg')) {
|
||||||
|
path = relativePath;
|
||||||
|
}
|
||||||
|
this.renderService = new URL(path, window.location.href).href;
|
||||||
|
this.urlBuilder.empty().add(urlOpts);
|
||||||
|
this._refreshURL();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.urlBuilder.empty().add(
|
||||||
|
this.dom.el('div').setClass('message')
|
||||||
|
.add('No online rendering service available.')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.urlBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
_refreshURL() {
|
||||||
|
this.urlOutput.val(this.renderService + makeURL(this.value(), {
|
||||||
|
height: Number.parseFloat(this.urlHeight.element.value),
|
||||||
|
width: Number.parseFloat(this.urlWidth.element.value),
|
||||||
|
zoom: Number.parseFloat(this.urlZoom.element.value || '1'),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
_showURLBuilder() {
|
||||||
|
if(this.builderVisible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.builderVisible = true;
|
||||||
|
this.urlBuilder.styles({
|
||||||
|
'display': 'block',
|
||||||
|
'height': '0px',
|
||||||
|
'padding': '0px',
|
||||||
|
'width': this.optsHold.element.clientWidth + 'px',
|
||||||
|
});
|
||||||
|
clearTimeout(this.builderTm);
|
||||||
|
this.builderTm = setTimeout(() => {
|
||||||
|
this.urlBuilder.styles({
|
||||||
|
'height': '150px',
|
||||||
|
'padding': '10px',
|
||||||
|
'width': '400px',
|
||||||
|
});
|
||||||
|
this.optsHold.styles({
|
||||||
|
'box-shadow': '10px 10px 25px 12px rgba(0,0,0,0.3)',
|
||||||
|
});
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
this._refreshURL();
|
||||||
|
}
|
||||||
|
|
||||||
|
_hideURLBuilder() {
|
||||||
|
if(!this.builderVisible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.builderVisible = false;
|
||||||
|
this.urlBuilder.styles({
|
||||||
|
'height': '0px',
|
||||||
|
'padding': '0px',
|
||||||
|
'width': '0px',
|
||||||
|
});
|
||||||
|
this.optsHold.styles({
|
||||||
|
'box-shadow': 'none',
|
||||||
|
});
|
||||||
|
clearTimeout(this.builderTm);
|
||||||
|
this.builderTm = setTimeout(() => {
|
||||||
|
this.urlBuilder.styles({'display': 'none'});
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
|
||||||
buildOptionsDownloads() {
|
buildOptionsDownloads() {
|
||||||
this.downloadPNG = this.dom.el('a')
|
this.downloadPNG = this.dom.el('a')
|
||||||
.text('Download PNG')
|
.text('Download PNG')
|
||||||
|
@ -717,8 +925,19 @@
|
||||||
})
|
})
|
||||||
.on('click', this._downloadSVGClick);
|
.on('click', this._downloadSVGClick);
|
||||||
|
|
||||||
return this.dom.el('div').setClass('options downloads')
|
this.downloadURL = this.dom.el('a')
|
||||||
.add(this.downloadPNG, this.downloadSVG);
|
.text('URL')
|
||||||
|
.attrs({'href': '#'})
|
||||||
|
.on('click', this._downloadURLClick);
|
||||||
|
|
||||||
|
this.optsHold = this.dom.el('div').setClass('options downloads').add(
|
||||||
|
this.downloadPNG,
|
||||||
|
this.downloadSVG,
|
||||||
|
this.downloadURL,
|
||||||
|
this.buildURLBuilder()
|
||||||
|
);
|
||||||
|
|
||||||
|
return this.optsHold;
|
||||||
}
|
}
|
||||||
|
|
||||||
buildLibrary(container) {
|
buildLibrary(container) {
|
||||||
|
@ -754,7 +973,8 @@
|
||||||
|
|
||||||
buildViewPane() {
|
buildViewPane() {
|
||||||
this.viewPaneInner = this.dom.el('div').setClass('pane-view-inner')
|
this.viewPaneInner = this.dom.el('div').setClass('pane-view-inner')
|
||||||
.add(this.diagram.dom());
|
.add(this.diagram.dom())
|
||||||
|
.on('click', () => this._hideURLBuilder());
|
||||||
|
|
||||||
this.errorMsg = this.dom.el('div').setClass('msg-error');
|
this.errorMsg = this.dom.el('div').setClass('msg-error');
|
||||||
|
|
||||||
|
@ -840,6 +1060,14 @@
|
||||||
snapOffset: 70,
|
snapOffset: 70,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(typeof window !== 'undefined') {
|
||||||
|
window.addEventListener('keydown', (e) => {
|
||||||
|
if(e.keyCode === 27) {
|
||||||
|
this._hideURLBuilder();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Delay first update 1 frame to ensure render target is ready
|
// Delay first update 1 frame to ensure render target is ready
|
||||||
// (prevents initial incorrect font calculations for custom fonts)
|
// (prevents initial incorrect font calculations for custom fonts)
|
||||||
setTimeout(this.update.bind(this), 0);
|
setTimeout(this.update.bind(this), 0);
|
||||||
|
@ -967,6 +1195,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
update(immediate = true) {
|
update(immediate = true) {
|
||||||
|
this._hideURLBuilder();
|
||||||
const src = this.value();
|
const src = this.value();
|
||||||
this.saveCode(src);
|
this.saveCode(src);
|
||||||
let sequence = null;
|
let sequence = null;
|
||||||
|
@ -1033,12 +1262,24 @@
|
||||||
} else if(this.updatePNGLink()) {
|
} else if(this.updatePNGLink()) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
this._hideURLBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
_downloadSVGClick() {
|
_downloadSVGClick() {
|
||||||
this.forceRender();
|
this.forceRender();
|
||||||
const url = this.diagram.getSVGSynchronous();
|
const url = this.diagram.getSVGSynchronous();
|
||||||
this.downloadSVG.attr('href', url);
|
this.downloadSVG.attr('href', url);
|
||||||
|
this._hideURLBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
_downloadURLClick(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if(this.builderVisible) {
|
||||||
|
this._hideURLBuilder();
|
||||||
|
} else {
|
||||||
|
this._showURLBuilder();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_enhanceEditor() {
|
_enhanceEditor() {
|
||||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue