Allow dropping SVGs into editor [#45]
This commit is contained in:
parent
262ac71844
commit
703129d3d0
|
@ -9394,6 +9394,15 @@ define('sequence/SequenceDiagram',[
|
|||
themes.push(theme);
|
||||
}
|
||||
|
||||
function extractCodeFromSVG(svg) {
|
||||
const dom = new DOMParser().parseFromString(svg, 'image/svg+xml');
|
||||
const meta = dom.querySelector('metadata');
|
||||
if(!meta) {
|
||||
return '';
|
||||
}
|
||||
return meta.textContent;
|
||||
}
|
||||
|
||||
class SequenceDiagram extends EventObject {
|
||||
constructor(code = null, options = {}) {
|
||||
super();
|
||||
|
@ -9538,20 +9547,15 @@ define('sequence/SequenceDiagram',[
|
|||
}
|
||||
}
|
||||
|
||||
extractCodeFromSVG(svg) {
|
||||
return extractCodeFromSVG(svg);
|
||||
}
|
||||
|
||||
dom() {
|
||||
return this.renderer.svg();
|
||||
}
|
||||
}
|
||||
|
||||
function extractCodeFromSVG(svg) {
|
||||
const dom = new DOMParser().parseFromString(svg, 'image/svg+xml');
|
||||
const meta = dom.querySelector('metadata');
|
||||
if(!meta) {
|
||||
return '';
|
||||
}
|
||||
return meta.textContent;
|
||||
}
|
||||
|
||||
function convert(element, code = null, options = {}) {
|
||||
if(element.tagName === 'svg') {
|
||||
return null;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -101,6 +101,39 @@ define(['require'], (require) => {
|
|||
});
|
||||
}
|
||||
|
||||
function hasDroppedFile(event, mime) {
|
||||
if(!event.dataTransfer.items && event.dataTransfer.files.length === 0) {
|
||||
// Work around Safari not supporting dataTransfer.items
|
||||
return [...event.dataTransfer.types].includes('Files');
|
||||
}
|
||||
|
||||
const items = (event.dataTransfer.items || event.dataTransfer.files);
|
||||
return (items.length === 1 && items[0].type === mime);
|
||||
}
|
||||
|
||||
function getDroppedFile(event, mime) {
|
||||
const items = (event.dataTransfer.items || event.dataTransfer.files);
|
||||
if(items.length !== 1 || items[0].type !== mime) {
|
||||
return null;
|
||||
}
|
||||
const item = items[0];
|
||||
if(item.getAsFile) {
|
||||
return item.getAsFile();
|
||||
} else {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
function getFileContent(file) {
|
||||
return new Promise((resolve) => {
|
||||
const reader = new FileReader();
|
||||
reader.addEventListener('loadend', () => {
|
||||
resolve(reader.result);
|
||||
}, {once: true});
|
||||
reader.readAsText(file);
|
||||
});
|
||||
}
|
||||
|
||||
return class Interface {
|
||||
constructor({
|
||||
sequenceDiagram,
|
||||
|
@ -127,6 +160,8 @@ define(['require'], (require) => {
|
|||
this._downloadSVGClick = this._downloadSVGClick.bind(this);
|
||||
this._downloadPNGClick = this._downloadPNGClick.bind(this);
|
||||
this._downloadPNGFocus = this._downloadPNGFocus.bind(this);
|
||||
this._showDropStyle = this._showDropStyle.bind(this);
|
||||
this._hideDropStyle = this._hideDropStyle.bind(this);
|
||||
|
||||
this._enhanceEditor();
|
||||
}
|
||||
|
@ -221,6 +256,28 @@ define(['require'], (require) => {
|
|||
this.code.focus();
|
||||
}
|
||||
});
|
||||
|
||||
this.container.addEventListener('dragover', (event) => {
|
||||
event.preventDefault();
|
||||
if(hasDroppedFile(event, 'image/svg+xml')) {
|
||||
event.dataTransfer.dropEffect = 'copy';
|
||||
this._showDropStyle();
|
||||
} else {
|
||||
event.dataTransfer.dropEffect = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
this.container.addEventListener('dragleave', this._hideDropStyle);
|
||||
this.container.addEventListener('dragend', this._hideDropStyle);
|
||||
|
||||
this.container.addEventListener('drop', (event) => {
|
||||
event.preventDefault();
|
||||
this._hideDropStyle();
|
||||
const file = getDroppedFile(event, 'image/svg+xml');
|
||||
if(file) {
|
||||
this.loadFile(file);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
buildLibrary(container) {
|
||||
|
@ -303,6 +360,7 @@ define(['require'], (require) => {
|
|||
}
|
||||
|
||||
build(container) {
|
||||
this.container = container;
|
||||
const hold = makeNode('div', {'class': 'pane-hold'});
|
||||
const lPane = makeNode('div', {'class': 'pane-side'});
|
||||
hold.appendChild(lPane);
|
||||
|
@ -421,6 +479,27 @@ define(['require'], (require) => {
|
|||
}
|
||||
}
|
||||
|
||||
setValue(code) {
|
||||
if(this.code.getDoc) {
|
||||
const doc = this.code.getDoc();
|
||||
doc.setValue(code);
|
||||
doc.clearHistory();
|
||||
} else {
|
||||
this.code.value = code;
|
||||
}
|
||||
this.update(true);
|
||||
this.diagram.setHighlight(null);
|
||||
}
|
||||
|
||||
loadFile(file) {
|
||||
return getFileContent(file).then((svg) => {
|
||||
const code = this.diagram.extractCodeFromSVG(svg);
|
||||
if(code) {
|
||||
this.setValue(code);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
update(immediate = true) {
|
||||
const src = this.value();
|
||||
this.saveCode(src);
|
||||
|
@ -476,6 +555,14 @@ define(['require'], (require) => {
|
|||
return true;
|
||||
}
|
||||
|
||||
_showDropStyle() {
|
||||
this.container.setAttribute('class', 'drop-target');
|
||||
}
|
||||
|
||||
_hideDropStyle() {
|
||||
this.container.setAttribute('class', '');
|
||||
}
|
||||
|
||||
_downloadPNGFocus() {
|
||||
this.updatePNGLink();
|
||||
}
|
||||
|
|
|
@ -28,7 +28,10 @@ defineDescribe('Interface', ['./Interface'], (Interface) => {
|
|||
});
|
||||
sequenceDiagram.getSize.and.returnValue({width: 10, height: 20});
|
||||
sequenceDiagram.dom.and.returnValue(document.createElement('svg'));
|
||||
container = jasmine.createSpyObj('container', ['appendChild']);
|
||||
container = jasmine.createSpyObj('container', [
|
||||
'appendChild',
|
||||
'addEventListener',
|
||||
]);
|
||||
|
||||
ui = new Interface({
|
||||
sequenceDiagram,
|
||||
|
|
|
@ -51,6 +51,15 @@ define([
|
|||
themes.push(theme);
|
||||
}
|
||||
|
||||
function extractCodeFromSVG(svg) {
|
||||
const dom = new DOMParser().parseFromString(svg, 'image/svg+xml');
|
||||
const meta = dom.querySelector('metadata');
|
||||
if(!meta) {
|
||||
return '';
|
||||
}
|
||||
return meta.textContent;
|
||||
}
|
||||
|
||||
class SequenceDiagram extends EventObject {
|
||||
constructor(code = null, options = {}) {
|
||||
super();
|
||||
|
@ -195,20 +204,15 @@ define([
|
|||
}
|
||||
}
|
||||
|
||||
extractCodeFromSVG(svg) {
|
||||
return extractCodeFromSVG(svg);
|
||||
}
|
||||
|
||||
dom() {
|
||||
return this.renderer.svg();
|
||||
}
|
||||
}
|
||||
|
||||
function extractCodeFromSVG(svg) {
|
||||
const dom = new DOMParser().parseFromString(svg, 'image/svg+xml');
|
||||
const meta = dom.querySelector('metadata');
|
||||
if(!meta) {
|
||||
return '';
|
||||
}
|
||||
return meta.textContent;
|
||||
}
|
||||
|
||||
function convert(element, code = null, options = {}) {
|
||||
if(element.tagName === 'svg') {
|
||||
return null;
|
||||
|
|
|
@ -36,6 +36,24 @@ html, body {
|
|||
margin: 0 10px 10px;
|
||||
}
|
||||
|
||||
.drop-target:after {
|
||||
content: 'Drop SVG to Load Code';
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
background: rgba(255, 255, 255, 0.6);
|
||||
text-shadow: 0 0 3px #FFFFFF;
|
||||
font-size: 3em;
|
||||
padding-top: 100px;
|
||||
text-align: center;
|
||||
border: 5px solid #88CC66;
|
||||
border-radius: 20px;
|
||||
pointer-events: none;
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
.pane-hold {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
|
|
Loading…
Reference in New Issue