|
@@ -2478,64 +2478,58 @@
|
|
|
*/
|
|
|
EditorUi.prototype.saveLocalFile = function(data, filename, mimeType, base64Encoded)
|
|
|
{
|
|
|
- if (this.isOfflineApp() || this.isOffline())
|
|
|
- {
|
|
|
- this.doSaveLocalFile(data, filename, mimeType, base64Encoded);
|
|
|
- }
|
|
|
- else
|
|
|
+ var allowTab = !mxClient.IS_IOS || !navigator.standalone;
|
|
|
+ var backends = !this.isOfflineApp() && !this.isOffline() &&
|
|
|
+ (typeof window.DriveClient === 'function' ||
|
|
|
+ typeof window.DropboxClient === 'function' ||
|
|
|
+ typeof window.OneDriveClient === 'function');
|
|
|
+
|
|
|
+ var dlg = new CreateDialog(this, filename, mxUtils.bind(this, function(newTitle, mode)
|
|
|
{
|
|
|
- var allowTab = !mxClient.IS_IOS || !navigator.standalone;
|
|
|
- var backends = typeof window.DriveClient === 'function' ||
|
|
|
- typeof window.DropboxClient === 'function' ||
|
|
|
- typeof window.OneDriveClient === 'function';
|
|
|
-
|
|
|
- var dlg = new CreateDialog(this, filename, mxUtils.bind(this, function(newTitle, mode)
|
|
|
+ try
|
|
|
{
|
|
|
- try
|
|
|
+ // Opens a new window
|
|
|
+ if (mode == '_blank')
|
|
|
{
|
|
|
- // Opens a new window
|
|
|
- if (mode == '_blank')
|
|
|
+ // Workaround for "Access denied" after URL.createObjectURL
|
|
|
+ // and blank window for window.open with data URI in MS Edge
|
|
|
+ // and empty window for IE 11 and 10
|
|
|
+ if (mxClient.IS_EDGE || document.documentMode == 11 || document.documentMode == 10)
|
|
|
{
|
|
|
- // Workaround for "Access denied" after URL.createObjectURL
|
|
|
- // and blank window for window.open with data URI in MS Edge
|
|
|
- // and empty window for IE 11 and 10
|
|
|
- if (mxClient.IS_EDGE || document.documentMode == 11 || document.documentMode == 10)
|
|
|
- {
|
|
|
- var param = (typeof(pako) === 'undefined') ? '&xml=' + encodeURIComponent(data) :
|
|
|
- '&data=' + encodeURIComponent(this.editor.graph.compress(data));
|
|
|
-
|
|
|
- new mxXmlRequest(SAVE_URL, 'mime=' + mimeType + param).simulate(document, '_blank');
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // Cannot use URL.createObjectURL since it kills gradients in FF
|
|
|
- window.open('data:' + mimeType + ((base64Encoded) ? ';base64,' +
|
|
|
- data : ';charset=utf8,' + encodeURIComponent(data)));
|
|
|
- }
|
|
|
+ var param = (typeof(pako) === 'undefined') ? '&xml=' + encodeURIComponent(data) :
|
|
|
+ '&data=' + encodeURIComponent(this.editor.graph.compress(data));
|
|
|
+
|
|
|
+ new mxXmlRequest(SAVE_URL, 'mime=' + mimeType + param).simulate(document, '_blank');
|
|
|
}
|
|
|
- else if (mode == App.MODE_DEVICE)
|
|
|
- {
|
|
|
- this.doSaveLocalFile(data, newTitle, mimeType, base64Encoded);
|
|
|
- }
|
|
|
- else if (newTitle != null && newTitle.length > 0)
|
|
|
+ else
|
|
|
{
|
|
|
- this.pickFolder(mode, mxUtils.bind(this, function(folderId)
|
|
|
- {
|
|
|
- this.exportFile(data, newTitle, mimeType, base64Encoded, mode, folderId);
|
|
|
- }));
|
|
|
+ // Cannot use URL.createObjectURL since it kills gradients in FF
|
|
|
+ window.open('data:' + mimeType + ((base64Encoded) ? ';base64,' +
|
|
|
+ data : ';charset=utf8,' + encodeURIComponent(data)));
|
|
|
}
|
|
|
}
|
|
|
- catch (e)
|
|
|
+ else if (mode == App.MODE_DEVICE)
|
|
|
{
|
|
|
- this.handleError(e);
|
|
|
+ this.doSaveLocalFile(data, newTitle, mimeType, base64Encoded);
|
|
|
+ }
|
|
|
+ else if (newTitle != null && newTitle.length > 0)
|
|
|
+ {
|
|
|
+ this.pickFolder(mode, mxUtils.bind(this, function(folderId)
|
|
|
+ {
|
|
|
+ this.exportFile(data, newTitle, mimeType, base64Encoded, mode, folderId);
|
|
|
+ }));
|
|
|
}
|
|
|
- }), mxUtils.bind(this, function()
|
|
|
+ }
|
|
|
+ catch (e)
|
|
|
{
|
|
|
- this.hideDialog();
|
|
|
- }), mxResources.get('saveAs'), mxResources.get('download'), false, false, allowTab);
|
|
|
- this.showDialog(dlg.container, 380, (backends) ? 280 : 160, true, true);
|
|
|
- dlg.init();
|
|
|
- }
|
|
|
+ this.handleError(e);
|
|
|
+ }
|
|
|
+ }), mxUtils.bind(this, function()
|
|
|
+ {
|
|
|
+ this.hideDialog();
|
|
|
+ }), mxResources.get('saveAs'), mxResources.get('download'), false, false, allowTab);
|
|
|
+ this.showDialog(dlg.container, 380, (backends) ? 280 : 160, true, true);
|
|
|
+ dlg.init();
|
|
|
};
|
|
|
|
|
|
/**
|
|
@@ -3890,6 +3884,47 @@
|
|
|
return cells;
|
|
|
};
|
|
|
|
|
|
+ /**
|
|
|
+ * Automatic loading for lucidchart import.
|
|
|
+ */
|
|
|
+ EditorUi.prototype.insertLucidChart = function(g, dx, dy, crop)
|
|
|
+ {
|
|
|
+ var delayed = mxUtils.bind(this, function()
|
|
|
+ {
|
|
|
+ // Checks for signature method
|
|
|
+ if (this.pasteLucidChart)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ this.pasteLucidChart(g, dx, dy, crop);
|
|
|
+ }
|
|
|
+ catch (e)
|
|
|
+ {
|
|
|
+ // ignore
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (!this.pasteLucidChart && !this.loadingExtensions && !this.isOffline())
|
|
|
+ {
|
|
|
+ this.loadingExtensions = true;
|
|
|
+
|
|
|
+ if (urlParams['dev'] == '1')
|
|
|
+ {
|
|
|
+ mxscript('/js/diagramly/Extensions.js', delayed);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ mxscript('/js/extensions.min.js', delayed);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Must be async for cell selection
|
|
|
+ window.setTimeout(delayed, 0);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
/**
|
|
|
* Imports the given XML into the existing diagram.
|
|
|
* TODO: Make this function asynchronous
|
|
@@ -3916,7 +3951,7 @@
|
|
|
return [];
|
|
|
}
|
|
|
// Handles special case of data URI which requires async loading for finding size
|
|
|
- else if (!this.isOffline() && (asImage || text.substring(0, 5) == 'data:' || (/\.(gif|jpg|jpeg|tiff|png|svg)$/i).test(text)))
|
|
|
+ else if (text.substring(0, 5) == 'data:' || (!this.isOffline() && (asImage || (/\.(gif|jpg|jpeg|tiff|png|svg)$/i).test(text))))
|
|
|
{
|
|
|
var graph = this.editor.graph;
|
|
|
|
|
@@ -4016,40 +4051,47 @@
|
|
|
}
|
|
|
else if (text.length > 0)
|
|
|
{
|
|
|
- var graph = this.editor.graph;
|
|
|
- var cell = null;
|
|
|
-
|
|
|
- graph.getModel().beginUpdate();
|
|
|
- try
|
|
|
- {
|
|
|
- // Fires cellsInserted to apply the current style to the inserted text.
|
|
|
- // This requires the value to be empty when the event is fired.
|
|
|
- cell = graph.insertVertex(graph.getDefaultParent(), null, '',
|
|
|
- graph.snap(dx), graph.snap(dy), 1, 1, 'text;' + ((html) ? 'html=1;' : ''));
|
|
|
- graph.fireEvent(new mxEventObject('textInserted', 'cells', [cell]));
|
|
|
-
|
|
|
- // Apply value and updates the cell size to fit the text block
|
|
|
- cell.value = text;
|
|
|
- graph.updateCellSize(cell);
|
|
|
-
|
|
|
- // See http://stackoverflow.com/questions/6927719/url-regex-does-not-work-in-javascript
|
|
|
- var regexp = /\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/i;
|
|
|
+ if (text.substring(0, 26) == '{"state":"{\\"Properties\\":')
|
|
|
+ {
|
|
|
+ this.insertLucidChart(JSON.parse(JSON.parse(text).state)['Pages']['0_0'], dx, dy, crop);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ var graph = this.editor.graph;
|
|
|
+ var cell = null;
|
|
|
|
|
|
- if (regexp.test(cell.value))
|
|
|
- {
|
|
|
- graph.setLinkForCell(cell, cell.value);
|
|
|
- }
|
|
|
+ graph.getModel().beginUpdate();
|
|
|
+ try
|
|
|
+ {
|
|
|
+ // Fires cellsInserted to apply the current style to the inserted text.
|
|
|
+ // This requires the value to be empty when the event is fired.
|
|
|
+ cell = graph.insertVertex(graph.getDefaultParent(), null, '',
|
|
|
+ graph.snap(dx), graph.snap(dy), 1, 1, 'text;' + ((html) ? 'html=1;' : ''));
|
|
|
+ graph.fireEvent(new mxEventObject('textInserted', 'cells', [cell]));
|
|
|
+
|
|
|
+ // Apply value and updates the cell size to fit the text block
|
|
|
+ cell.value = text;
|
|
|
+ graph.updateCellSize(cell);
|
|
|
+
|
|
|
+ // See http://stackoverflow.com/questions/6927719/url-regex-does-not-work-in-javascript
|
|
|
+ var regexp = /\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/i;
|
|
|
+
|
|
|
+ if (regexp.test(cell.value))
|
|
|
+ {
|
|
|
+ graph.setLinkForCell(cell, cell.value);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Adds spacing
|
|
|
+ cell.geometry.width += graph.gridSize;
|
|
|
+ cell.geometry.height += graph.gridSize;
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ graph.getModel().endUpdate();
|
|
|
+ }
|
|
|
|
|
|
- // Adds spacing
|
|
|
- cell.geometry.width += graph.gridSize;
|
|
|
- cell.geometry.height += graph.gridSize;
|
|
|
- }
|
|
|
- finally
|
|
|
- {
|
|
|
- graph.getModel().endUpdate();
|
|
|
- }
|
|
|
-
|
|
|
- return [cell];
|
|
|
+ return [cell];
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -4176,25 +4218,7 @@
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- if (/(\.vsdx)($|\?)/i.test(filename))
|
|
|
- {
|
|
|
- var vsdxModel = new mxVsdxModel();
|
|
|
- vsdxModel.decode(file);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- cells = this.insertTextAt(this.validateFileData(data), dx, dy, true);
|
|
|
- }
|
|
|
-// else if (String.prototype.trim)
|
|
|
-// {
|
|
|
-// var trimmed = data.trim();
|
|
|
-//
|
|
|
-// if (trimmed.substring(0, 6) == 'strict ' || trimmed.substring(0, 5) == 'graph' || trimmed.substring(0, 7) == 'digraph')
|
|
|
-// {
|
|
|
-// // GraphViz dot format http://www.graphviz.org/content/dot-language
|
|
|
-// //var digraph = graphlibDot.read("digraph { 1; 2; 1 -> 2 [label=\"label\"] }");
|
|
|
-// }
|
|
|
-// }
|
|
|
+ cells = this.insertTextAt(this.validateFileData(data), dx, dy, true, null, crop);
|
|
|
}
|
|
|
|
|
|
if (!async && done != null)
|
|
@@ -4541,10 +4565,6 @@
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
/**
|
|
|
* Parses the file using XHR2 via the server. File can be a blob or file object.
|
|
|
* Filename is an optional parameter for blobs (that do not have a filename).
|
|
@@ -5553,97 +5573,113 @@
|
|
|
{
|
|
|
if (!mxEvent.isConsumed(evt))
|
|
|
{
|
|
|
- var graph = this.editor.graph;
|
|
|
- var xml = mxUtils.trim((mxClient.IS_QUIRKS || document.documentMode == 8) ?
|
|
|
- mxUtils.getTextContent(elt) : elt.textContent);
|
|
|
- var compat = false;
|
|
|
-
|
|
|
- // Workaround for junk after XML in VM
|
|
|
- try
|
|
|
+ var spans = elt.getElementsByTagName('span');
|
|
|
+
|
|
|
+ if (spans != null && spans.length > 0 && spans[0].getAttribute('data-lucid-type') ===
|
|
|
+ 'application/vnd.lucid.chart.objects')
|
|
|
{
|
|
|
- var idx = xml.lastIndexOf('%3E');
|
|
|
+ var content = spans[0].getAttribute('data-lucid-content');
|
|
|
|
|
|
- if (idx >= 0 && idx < xml.length - 3)
|
|
|
+ if (content != null && content.length > 0)
|
|
|
{
|
|
|
- xml = xml.substring(0, idx + 3);
|
|
|
+ this.insertLucidChart(JSON.parse(content));
|
|
|
+ mxEvent.consume(evt);
|
|
|
}
|
|
|
}
|
|
|
- catch (e)
|
|
|
- {
|
|
|
- // ignore
|
|
|
- }
|
|
|
-
|
|
|
- // Checks for embedded XML content
|
|
|
- try
|
|
|
+ else
|
|
|
{
|
|
|
- var spans = elt.getElementsByTagName('span');
|
|
|
- var tmp = (spans != null && spans.length > 0) ?
|
|
|
- mxUtils.trim(decodeURIComponent(spans[0].textContent)) :
|
|
|
- decodeURIComponent(xml);
|
|
|
-
|
|
|
- if (this.isCompatibleString(tmp))
|
|
|
+ var graph = this.editor.graph;
|
|
|
+ var xml = mxUtils.trim((mxClient.IS_QUIRKS || document.documentMode == 8) ?
|
|
|
+ mxUtils.getTextContent(elt) : elt.textContent);
|
|
|
+ var compat = false;
|
|
|
+
|
|
|
+ // Workaround for junk after XML in VM
|
|
|
+ try
|
|
|
{
|
|
|
- compat = true;
|
|
|
- xml = tmp;
|
|
|
+ var idx = xml.lastIndexOf('%3E');
|
|
|
+
|
|
|
+ if (idx >= 0 && idx < xml.length - 3)
|
|
|
+ {
|
|
|
+ xml = xml.substring(0, idx + 3);
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- catch (e)
|
|
|
- {
|
|
|
- // ignore
|
|
|
- }
|
|
|
-
|
|
|
- if (graph.lastPasteXml == xml)
|
|
|
- {
|
|
|
- graph.pasteCounter++;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- graph.lastPasteXml = xml;
|
|
|
- graph.pasteCounter = 0;
|
|
|
- }
|
|
|
-
|
|
|
- var dx = graph.pasteCounter * graph.gridSize;
|
|
|
-
|
|
|
- if (xml != null && xml.length > 0)
|
|
|
- {
|
|
|
- if (compat || this.isCompatibleString(xml))
|
|
|
+ catch (e)
|
|
|
{
|
|
|
- graph.setSelectionCells(this.importXml(xml, dx, dx));
|
|
|
+ // ignore
|
|
|
}
|
|
|
- else
|
|
|
+
|
|
|
+ // Checks for embedded XML content
|
|
|
+ try
|
|
|
{
|
|
|
- var pt = graph.getInsertPoint();
|
|
|
-
|
|
|
- if (graph.isMouseInsertPoint())
|
|
|
+ var spans = elt.getElementsByTagName('span');
|
|
|
+ var tmp = (spans != null && spans.length > 0) ?
|
|
|
+ mxUtils.trim(decodeURIComponent(spans[0].textContent)) :
|
|
|
+ decodeURIComponent(xml);
|
|
|
+
|
|
|
+ if (this.isCompatibleString(tmp))
|
|
|
{
|
|
|
- dx = 0;
|
|
|
-
|
|
|
- // No offset for insert at mouse position
|
|
|
- if (graph.lastPasteXml == xml && graph.pasteCounter > 0)
|
|
|
- {
|
|
|
- graph.pasteCounter--;
|
|
|
- }
|
|
|
+ compat = true;
|
|
|
+ xml = tmp;
|
|
|
}
|
|
|
-
|
|
|
- graph.setSelectionCells(this.insertTextAt(xml, pt.x + dx, pt.y + dx, true));
|
|
|
+ }
|
|
|
+ catch (e)
|
|
|
+ {
|
|
|
+ // ignore
|
|
|
}
|
|
|
|
|
|
- if (!graph.isSelectionEmpty())
|
|
|
+ if (graph.lastPasteXml == xml)
|
|
|
+ {
|
|
|
+ graph.pasteCounter++;
|
|
|
+ }
|
|
|
+ else
|
|
|
{
|
|
|
- graph.scrollCellToVisible(graph.getSelectionCell());
|
|
|
+ graph.lastPasteXml = xml;
|
|
|
+ graph.pasteCounter = 0;
|
|
|
+ }
|
|
|
|
|
|
- if (this.hoverIcons != null)
|
|
|
+ var dx = graph.pasteCounter * graph.gridSize;
|
|
|
+
|
|
|
+ if (xml != null && xml.length > 0)
|
|
|
+ {
|
|
|
+ if (compat || this.isCompatibleString(xml))
|
|
|
{
|
|
|
- this.hoverIcons.update(graph.view.getState(graph.getSelectionCell()));
|
|
|
+ graph.setSelectionCells(this.importXml(xml, dx, dx));
|
|
|
}
|
|
|
-
|
|
|
- try
|
|
|
+ else
|
|
|
{
|
|
|
- mxEvent.consume(evt);
|
|
|
+ var pt = graph.getInsertPoint();
|
|
|
+
|
|
|
+ if (graph.isMouseInsertPoint())
|
|
|
+ {
|
|
|
+ dx = 0;
|
|
|
+
|
|
|
+ // No offset for insert at mouse position
|
|
|
+ if (graph.lastPasteXml == xml && graph.pasteCounter > 0)
|
|
|
+ {
|
|
|
+ graph.pasteCounter--;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ graph.setSelectionCells(this.insertTextAt(xml, pt.x + dx, pt.y + dx, true));
|
|
|
}
|
|
|
- catch (e)
|
|
|
+
|
|
|
+ if (!graph.isSelectionEmpty())
|
|
|
{
|
|
|
- // ignore event no longer exists in async handler in IE8-
|
|
|
+ graph.scrollCellToVisible(graph.getSelectionCell());
|
|
|
+
|
|
|
+ if (this.hoverIcons != null)
|
|
|
+ {
|
|
|
+ this.hoverIcons.update(graph.view.getState(graph.getSelectionCell()));
|
|
|
+ }
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ mxEvent.consume(evt);
|
|
|
+ }
|
|
|
+ catch (e)
|
|
|
+ {
|
|
|
+ // ignore event no longer exists in async handler in IE8-
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|