Przeglądaj źródła

5.7.0.7 release

Former-commit-id: 8ad8f2779982c8375b47cf37daba4edf08479701
David Benson 8 lat temu
rodzic
commit
bfd6398fee

+ 12 - 0
ChangeLog

@@ -1,3 +1,15 @@
+27-SEP-2016: 5.7.0.7
+
+- Adds filename for editors in Atlassian cloud plugins
+- Fixes encoding of filenames in Atlassian cloud plugins
+- Adds optional title parameter to load message
+- Uses mxGraph 3.7.0.0 beta 5
+- Fixes possible empty pages in PDF export
+
+27-SEP-2016: 5.7.0.6
+
+- Fixes redirect error in IE
+
 26-SEP-2016: 5.7.0.5
 
 - Adds publish to Facebook, Twitter

+ 1 - 1
VERSION

@@ -1 +1 @@
-5.7.0.5
+5.7.0.7

Plik diff jest za duży
+ 4 - 4
etc/mxgraph/mxClient.js


+ 83 - 11
src/com/mxgraph/online/LogServlet.java

@@ -2,6 +2,9 @@ package com.mxgraph.online;
 
 import java.io.OutputStream;
 import java.net.URLDecoder;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -24,6 +27,39 @@ public class LogServlet extends HttpServlet {
 	
 	static byte[] singleByteGif = { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x1, 0x0, 0x1, 0x0, (byte) 0x80, 0x0, 0x0, (byte)  0xff, (byte)  0xff,  (byte) 0xff, 0x0, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x2, 0x2, 0x44, 0x1, 0x0, 0x3b };
 
+	/**
+	 * The start string of error message we want to ignore
+	 */
+	static String[] configArray;
+	
+	static Set<String> ignoreFilters;
+
+	/**
+	 * The start string of error message we want to reduce to a warning
+	 */
+	static String[] warningArray;
+		
+	static Set<String> warningFilters;
+
+	static
+	{
+		configArray = new String[]
+	    {
+	    	"Uncaught TypeError: frames.ezLinkPreviewIFRAME.postMessage is not a function", // third party Chrome plugin
+	    	"Uncaught TypeError: Cannot set property 'tgt' of null" // Tampermonkey extension, https://github.com/kogg/InstantLogoSearch/issues/199
+	    };
+		
+		ignoreFilters = new HashSet<String>(Arrays.asList(configArray));
+		
+		warningArray = new String[]
+	    {
+	    	"Uncaught Error: Client got in an error state. Call reset() to reuse it!", // dropbox auth failing
+	    	"Error: Client got in an error state. Call reset() to reuse it!"
+	    };
+		
+		warningFilters = new HashSet<String>(Arrays.asList(warningArray));
+	}
+
 	public void doGet(HttpServletRequest request, HttpServletResponse response)
 	{
 		doPost(request, response);
@@ -38,15 +74,7 @@ public class LogServlet extends HttpServlet {
 			String version = request.getParameter("v");
 			String stack = request.getParameter("stack");
 			
-			if (version != null)
-			{
-				message += "\nVERSION=" + version;
-			}
-			
-			if (stack != null)
-			{
-				message += "\n" + stack;
-			}
+			String userAgent = request.getHeader("User-Agent");
 
 			if (message != null)
 			{
@@ -57,12 +85,19 @@ public class LogServlet extends HttpServlet {
 					severityLevel = Level.parse(severity);
 				}
 				
-				if (severityLevel.intValue() >= 900)
+				if (severityLevel.intValue() >= 1000)
 				{
-					// Tidy up warnings and severes
+					// Tidy up severes
 					message = message == null ? message : URLDecoder.decode(message, "UTF-8");
+					version = version == null ? version : URLDecoder.decode(version, "UTF-8");
+					stack = stack == null ? stack : URLDecoder.decode(stack, "UTF-8");
+					
+					severityLevel = filterClientErrors(message, userAgent);
 				}
 
+				message = version != null ? message + "\nVERSION=" + version : message;		
+				message = stack != null ? message + "\n" + stack : message;
+
 				log.log(severityLevel, "CLIENT-LOG:" + message);
 			}
 
@@ -80,4 +115,41 @@ public class LogServlet extends HttpServlet {
 			e.printStackTrace();
 		}
 	}
+	
+	/**
+	 * Filter out known red herring client errors by reducing their severity
+	 * @param message the message thrown on the client
+	 * @param userAgent the user agent string 
+	 * @return the severity to treat the message with
+	 */
+	protected Level filterClientErrors(String message, String userAgent)
+	{
+		try
+		{
+			String result = message.substring(message.indexOf("clientError:") + 12, message.indexOf(":url:"));
+			
+			if (result != null)
+			{
+				if (ignoreFilters.contains(result))
+				{
+					return Level.CONFIG;
+				}
+				else if (warningFilters.contains(result))
+				{
+					return Level.WARNING;
+				}
+			}
+		}
+		catch (Exception e)
+		{
+			
+		}
+		
+		if (userAgent != null && userAgent.contains("compatible; MSIE 8.0;"))
+		{
+			return Level.WARNING;
+		}
+		
+		return Level.SEVERE;
+	}
 }

+ 1 - 1
war/WEB-INF/appengine-web.xml

@@ -2,7 +2,7 @@
 <appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
 	<application>drawdotio</application>
 	<!-- IMPORTANT! DO NOT CHANGE THIS VALUE IN SOURCE CONTROL! -->
-	<version>test</version>
+	<version>5-7-0-7</version>
 	
 	<!-- Configure java.util.logging -->
 	<system-properties>

+ 1 - 1
war/cache.manifest

@@ -1,7 +1,7 @@
 CACHE MANIFEST
 
 # THIS FILE WAS GENERATED. DO NOT MODIFY!
-# 09/26/2016 01:55 PM
+# 09/27/2016 11:52 AM
 
 /app.html
 /index.html?offline=1

+ 12 - 33
war/export2.html

@@ -285,55 +285,34 @@
 			if (graph.pdfPageVisible)
 			{
 				// Workaround to match available paper size
-				var printScale = 0.72;
-	
+				var printScale = 0.72
 				var pf = graph.pageFormat || mxConstants.PAGE_FORMAT_A4_PORTRAIT;
 				var scale = 1 / graph.pageScale;
-	
+				var autoOrigin = false;
+				var border = 0;
+
 				// Negative coordinates are cropped or shifted if page visible
 				var gb = graph.getGraphBounds();
-				var autoOrigin = false;
 				var border = 0;
 				var x0 = 0;
 				var y0 = 0;
-				
-				// Computes unscaled, untranslated graph bounds
-				var x = (gb.width > 0) ? Math.ceil(gb.x / graph.view.scale - graph.view.translate.x) : 0;
-				var y = (gb.height > 0) ? Math.ceil(gb.y / graph.view.scale - graph.view.translate.y) : 0;
-	
-				if (x < 0 || y < 0)
-				{
-					autoOrigin = true;
-					
-					var ps = graph.pageScale;
-					var pw = pf.width * ps;
-					var ph = pf.height * ps;
-	
-					// FIXME: Offset for page layout with x/y != 0
-					x0 = (x > 0) ? x : pf.width * -Math.floor(Math.min(0, x) / pw) + Math.min(0, x) / graph.pageScale;
-					y0 = (y > 0) ? y : pf.height * -Math.floor(Math.min(0, y) / ph) + Math.min(0, y) / graph.pageScale;
-				}
-	
+		
 				// Applies print scale
 				pf = mxRectangle.fromRectangle(pf);
-				pf.width = Math.round(pf.width * printScale);
-				pf.height = Math.round(pf.height * printScale);
+				pf.width = Math.ceil(pf.width * printScale);
+				pf.height = Math.ceil(pf.height * printScale);
 				scale *= printScale;
 				
 				// Starts at first visible page
-				if (graph.pageVisible)
-				{
-					var layout = graph.getPageLayout();
-					
-					x0 -= Math.max(layout.x, 0) * pf.width;
-					y0 -= Math.max(layout.y, 0) * pf.height;
-				}
-	
+				var layout = graph.getPageLayout();
+				x0 -= layout.x * pf.width;
+				y0 -= layout.y * pf.height;
+				
 				var preview = new mxPrintPreview(graph, scale, pf, border, x0, y0);
 				preview.printBackgroundImage = true;
 				preview.autoOrigin = autoOrigin;
 				preview.backgroundColor = bg;
-				
+
 				// Renders print output into this document and removes the graph container
 				preview.open(null, window);
 				graph.container.parentNode.removeChild(graph.container);

+ 1 - 1
war/index.html

@@ -66,7 +66,7 @@
 				var proto = window.location.protocol;
 				
 				// Electron protocol is file:
-				if (!proto.startsWith('file:'))
+				if (proto != 'file:')
 				{
 					var host = window.location.host;
 		

Plik diff jest za duży
+ 703 - 701
war/js/app.min.js


Plik diff jest za duży
+ 45 - 44
war/js/atlas-viewer.min.js


Plik diff jest za duży
+ 335 - 334
war/js/atlas.min.js


+ 17 - 17
war/js/diagramly/App.js

@@ -379,7 +379,7 @@ App.main = function(callback)
 				var img = new Image();
 				var severity = (message.indexOf('NetworkError') >= 0 || message.indexOf('SecurityError') >= 0 ||
 					message.indexOf('NS_ERROR_FAILURE') >= 0 || message.indexOf('out of memory') >= 0) ?
-					'CONFIG' : 'WARNING';
+					'CONFIG' : 'SEVERE';
 	    		img.src = 'log?severity=' + severity + '&v=' + encodeURIComponent(EditorUi.VERSION) +
 	    			'&msg=clientError:' + encodeURIComponent(message) + ':url:' + encodeURIComponent(window.location.href) +
 	    			':lnum:' + encodeURIComponent(linenumber) + 
@@ -4156,22 +4156,22 @@ App.prototype.fileLoaded = function(file)
 			
 			this.editor.fireEvent(new mxEventObject('fileLoaded'));
 			
-			if (this.enableLogging)
-			{
-	        	try
-	        	{
-		        	if (!this.isOffline())
-		        	{
-	        			var img = new Image();
-	        			img.src = 'log?msg=storageMode:' + encodeURIComponent(file.getMode()) +
-        				'&v=' + encodeURIComponent(EditorUi.VERSION);
-		        	}
-	        	}
-	        	catch (e)
-	        	{
-	        		// ignore
-	        	}
-			}
+//			if (this.enableLogging)
+//			{
+//	        	try
+//	        	{
+//		        	if (!this.isOffline())
+//		        	{
+//	        			var img = new Image();
+//	        			img.src = 'log?msg=storageMode:' + encodeURIComponent(file.getMode()) +
+//        				'&v=' + encodeURIComponent(EditorUi.VERSION);
+//		        	}
+//	        	}
+//	        	catch (e)
+//	        	{
+//	        		// ignore
+//	        	}
+//			}
 			
 			if (this.mode == file.getMode() && file.getMode() != App.MODE_DEVICE)
 			{

+ 37 - 7
war/js/diagramly/Dialogs.js

@@ -5195,6 +5195,27 @@ var RevisionDialog = function(editorUi, revs)
 	graph.maxFitScale = null;
 	graph.centerZoom = true;
 	
+	// Handles placeholders for pages
+	var currentPage = 0;
+	var diagrams = null;
+	var realPage = 0;
+	
+	var graphGetGlobalVariable = graph.getGlobalVariable;
+	
+	graph.getGlobalVariable = function(name)
+	{
+		if (name == 'page' && diagrams != null && diagrams[realPage] != null)
+		{
+			return diagrams[currentPage].getAttribute('name');
+		}
+		else if (name == 'pagenumber')
+		{
+			return realPage + 1;
+		}
+		
+		return graphGetGlobalVariable.apply(this, arguments);
+	};
+	
 	// Disables hyperlinks
 	graph.getLinkForCell = function()
 	{
@@ -5447,10 +5468,8 @@ var RevisionDialog = function(editorUi, revs)
 			table.style.borderSpacing = '0px';
 			table.style.width = '100%';
 			var tbody = document.createElement('tbody');
-			
 			var today = new Date().toDateString();
-			var currentPage = 0;
-			
+
 			if (editorUi.currentPage != null && editorUi.pages != null)
 			{
 				currentPage = mxUtils.indexOf(editorUi.pages, editorUi.currentPage);
@@ -5514,6 +5533,8 @@ var RevisionDialog = function(editorUi, revs)
 								currentDoc = doc;
 								currentXml = xml;
 								parseSelectFunction = null;
+								diagrams = null;
+								realPage = 0;
 								
 								function parseGraphModel(dataNode)
 								{
@@ -5545,11 +5566,19 @@ var RevisionDialog = function(editorUi, revs)
 									
 									return diagramNode;
 								}
-								
+
 								if (node.nodeName == 'mxfile')
 								{
-									var diagrams = node.getElementsByTagName('diagram');
-									var realPage = Math.min(currentPage, diagrams.length - 1); 
+									// Workaround for "invalid calling object" error in IE
+									var tmp = node.getElementsByTagName('diagram');
+									diagrams = [];
+									
+									for (var i = 0; i < tmp.length; i++)
+									{
+										diagrams.push(tmp[i]);	
+									}
+									
+									realPage = Math.min(currentPage, diagrams.length - 1);
 									
 									if (diagrams.length > 0)
 									{
@@ -5579,7 +5608,8 @@ var RevisionDialog = function(editorUi, revs)
 									
 									pageSelectFunction = function()
 									{
-										currentPage = pageSelect.value;
+										currentPage = parseInt(pageSelect.value);
+										realPage = currentPage;
 										parseDiagram(diagrams[currentPage]);
 									}
 								}

+ 7 - 1
war/js/diagramly/DriveRealtime.js

@@ -886,7 +886,13 @@ DriveRealtime.prototype.installPageSelectListener = function()
 					
 					if (index != null)
 					{
-						this.ui.removePage(this.ui.pages[index]);
+						var page = this.ui.pages[index];
+						
+						if (page != null)
+						{
+							this.ui.removePage(page);
+							page.mapping.destroy();
+						}
 					}
 				}
 				

+ 154 - 126
war/js/diagramly/EditorUi.js

@@ -2413,7 +2413,11 @@
 							}
 							
 							var bounds = graph.getBoundingBoxFromGeometry(cells, true);
-							graph.moveCells(cells, dx - bounds.x, dy - bounds.y);
+							
+							if (bounds != null)
+							{
+								graph.moveCells(cells, dx - bounds.x, dy - bounds.y);
+							}
 						}
 					}
 					finally
@@ -2445,157 +2449,162 @@
 		crop = (crop != null) ? crop : true;
 		
 		// Handles special case for Gliffy data which requires async server-side for parsing
-		if (Graph.fileSupport && !this.isOffline() && new XMLHttpRequest().upload && this.isRemoteFileFormat(text))
+		if (text != null)
 		{
-			// Fixes possible parsing problems with ASCII 160 (non-breaking space)
-			this.parseFile(new Blob([text.replace(/\s+/g,' ')], {type: 'application/octet-stream'}), mxUtils.bind(this, function(xhr)
+			if (Graph.fileSupport && !this.isOffline() && new XMLHttpRequest().upload && this.isRemoteFileFormat(text))
 			{
-				if (xhr.readyState == 4 && xhr.status == 200)
+				// Fixes possible parsing problems with ASCII 160 (non-breaking space)
+				this.parseFile(new Blob([text.replace(/\s+/g,' ')], {type: 'application/octet-stream'}), mxUtils.bind(this, function(xhr)
 				{
-					this.editor.graph.setSelectionCells(this.insertTextAt(xhr.responseText, dx, dy, true));
-				}
-			}));
-			
-			// Returns empty cells array as it is aysynchronous
-			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)))
-		{
-			var graph = this.editor.graph;
-			
-			// Checks for embedded XML in PNG
-			if (text.substring(0, 22) == 'data:image/png;base64,')
-			{
-				var xml = this.extractGraphModelFromPng(text);
-				var result = this.importXml(xml, dx, dy, crop, true); 
+					if (xhr.readyState == 4 && xhr.status == 200)
+					{
+						this.editor.graph.setSelectionCells(this.insertTextAt(xhr.responseText, dx, dy, true));
+					}
+				}));
 				
-				if (result.length > 0)
-				{
-					return result;
-				}
+				// Returns empty cells array as it is aysynchronous
+				return [];
 			}
-			
-			// Tries to extract embedded XML from SVG data URI
-			if (text.substring(0, 19) == 'data:image/svg+xml;')
+			// 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)))
 			{
-				try
+				var graph = this.editor.graph;
+				
+				// Checks for embedded XML in PNG
+				if (text.substring(0, 22) == 'data:image/png;base64,')
 				{
-					var xml = null;
-					
-					if (text.substring(0, 26) == 'data:image/svg+xml;base64,')
-					{
-						xml = text.substring(text.indexOf(',') + 1);
-						xml = (window.atob && !mxClient.IS_SF) ? atob(xml) : Base64.decode(xml, true);
-					}
-					else
-					{
-						xml = decodeURIComponent(text.substring(text.indexOf(',') + 1));
-					}
-					
+					var xml = this.extractGraphModelFromPng(text);
 					var result = this.importXml(xml, dx, dy, crop, true); 
-
+					
 					if (result.length > 0)
 					{
 						return result;
 					}
 				}
-				catch (e)
+				
+				// Tries to extract embedded XML from SVG data URI
+				if (text.substring(0, 19) == 'data:image/svg+xml;')
 				{
-					// Ignore
+					try
+					{
+						var xml = null;
+						
+						if (text.substring(0, 26) == 'data:image/svg+xml;base64,')
+						{
+							xml = text.substring(text.indexOf(',') + 1);
+							xml = (window.atob && !mxClient.IS_SF) ? atob(xml) : Base64.decode(xml, true);
+						}
+						else
+						{
+							xml = decodeURIComponent(text.substring(text.indexOf(',') + 1));
+						}
+						
+						var result = this.importXml(xml, dx, dy, crop, true); 
+	
+						if (result.length > 0)
+						{
+							return result;
+						}
+					}
+					catch (e)
+					{
+						// Ignore
+					}
 				}
-			}
-			
-			this.loadImage(text, mxUtils.bind(this, function(img)
-			{
-				if (text.substring(0, 5) == 'data:')
+				
+				this.loadImage(text, mxUtils.bind(this, function(img)
 				{
-					this.resizeImage(img, text, mxUtils.bind(this, function(data2, w2, h2)
-    				{
+					if (text.substring(0, 5) == 'data:')
+					{
+						this.resizeImage(img, text, mxUtils.bind(this, function(data2, w2, h2)
+	    				{
+							graph.setSelectionCell(graph.insertVertex(null, null, '', graph.snap(dx), graph.snap(dy),
+									w2, h2, 'shape=image;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;' +
+									'verticalAlign=top;aspect=fixed;image=' + this.convertDataUri(data2) + ';'));
+	    				}), true, this.maxImageSize);
+					}
+					else
+					{
+						var s = Math.min(1, Math.min(this.maxImageSize / img.width, this.maxImageSize / img.height));
+						var w = Math.round(img.width * s);
+						var h = Math.round(img.height * s);
+						
 						graph.setSelectionCell(graph.insertVertex(null, null, '', graph.snap(dx), graph.snap(dy),
-								w2, h2, 'shape=image;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;' +
-								'verticalAlign=top;aspect=fixed;image=' + this.convertDataUri(data2) + ';'));
-    				}), true, this.maxImageSize);
-				}
-				else
+								w, h, 'shape=image;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;' +
+								'verticalAlign=top;aspect=fixed;image=' + text + ';'));
+					}
+				}), mxUtils.bind(this, function()
 				{
-					var s = Math.min(1, Math.min(this.maxImageSize / img.width, this.maxImageSize / img.height));
-					var w = Math.round(img.width * s);
-					var h = Math.round(img.height * s);
+					var cell = null;
 					
-					graph.setSelectionCell(graph.insertVertex(null, null, '', graph.snap(dx), graph.snap(dy),
-							w, h, 'shape=image;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;' +
-							'verticalAlign=top;aspect=fixed;image=' + text + ';'));
-				}
-			}), mxUtils.bind(this, function()
-			{
-				var cell = null;
+					// Inserts invalid data URIs as text
+			    	graph.getModel().beginUpdate();
+			    	try
+			    	{
+						cell = graph.insertVertex(graph.getDefaultParent(), null, text,
+								graph.snap(dx), graph.snap(dy), 1, 1, 'text;' + ((html) ? 'html=1;' : ''));
+						graph.updateCellSize(cell);
+						graph.fireEvent(new mxEventObject('textInserted', 'cells', [cell]));
+			    	}
+			    	finally
+			    	{
+			    		graph.getModel().endUpdate();
+			    	}
+	
+					graph.setSelectionCell(cell);
+				}));
 				
-				// Inserts invalid data URIs as text
-		    	graph.getModel().beginUpdate();
-		    	try
-		    	{
-					cell = graph.insertVertex(graph.getDefaultParent(), null, text,
-							graph.snap(dx), graph.snap(dy), 1, 1, 'text;' + ((html) ? 'html=1;' : ''));
-					graph.updateCellSize(cell);
-					graph.fireEvent(new mxEventObject('textInserted', 'cells', [cell]));
-		    	}
-		    	finally
-		    	{
-		    		graph.getModel().endUpdate();
-		    	}
-
-				graph.setSelectionCell(cell);
-			}));
-			
-			return [];
-		}
-		else
-		{
-			text = this.editor.graph.zapGremlins(mxUtils.trim(text));
-		
-			if (this.isCompatibleString(text))
-			{
-				return this.importXml(text, dx, dy, crop);
+				return [];
 			}
-			else if (text.length > 0)
+			else
 			{
-				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;
+				text = this.editor.graph.zapGremlins(mxUtils.trim(text));
+			
+				if (this.isCompatibleString(text))
+				{
+					return this.importXml(text, dx, dy, crop);
+				}
+				else if (text.length > 0)
+				{
+					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];
+				}
 			}
 		}
+		
+		return [];
 	};
 
 	/**
@@ -5229,6 +5238,25 @@
 						urlParams['saveAndExit'] = data.saveAndExit;
 					}
 					
+					if (data.title != null && this.buttonContainer != null)
+					{
+						var tmp = document.createElement('span');
+						mxUtils.write(tmp, data.title);
+						
+						if (uiTheme == 'atlas')
+						{
+							this.buttonContainer.style.paddingRight = '12px';
+							this.buttonContainer.style.paddingTop = '12px';
+						}
+						else
+						{
+							this.buttonContainer.style.paddingRight = '38px';
+							this.buttonContainer.style.paddingTop = '6px';
+						}
+						
+						this.buttonContainer.appendChild(tmp);
+					}
+					
 					if (data.xmlpng != null)
 					{
 						data = this.extractGraphModelFromPng(data.xmlpng);

+ 5 - 5
war/js/diagramly/Pages.js

@@ -685,12 +685,12 @@ EditorUi.prototype.renamePage = function(page)
 	if (graph.isEnabled())
 	{
 		var dlg = new FilenameDialog(this, page.getName(), mxResources.get('rename'), mxUtils.bind(this, function(name)
-	{
-		if (name != null && name.length > 0)
 		{
-			this.editor.graph.model.execute(new RenamePage(this, page, name));
-		}
-	}), mxResources.get('rename'));
+			if (name != null && name.length > 0)
+			{
+				this.editor.graph.model.execute(new RenamePage(this, page, name));
+			}
+		}), mxResources.get('rename'));
 		this.showDialog(dlg.container, 300, 80, true, true);
 		dlg.init();
 	}

+ 53 - 2
war/js/diagramly/RealtimeMapping.js

@@ -212,8 +212,16 @@ RealtimeMapping.prototype.initGraph = function()
 	}
 	
 	var rtRoot = this.diagramMap.get(this.driveRealtime.rootKey);
-	this.createCell(rtRoot);
-	this.restoreCell(rtRoot);
+	
+	if (rtRoot.cell == null)
+	{
+		this.createCell(rtRoot);
+		this.restoreCell(rtRoot);
+	}
+	else
+	{
+		this.installAllRealtimeCellListeners(rtRoot);	
+	}
 	
 	// Stores root in current model and local model
 	var gm = this.getGraphModel();
@@ -596,6 +604,22 @@ RealtimeMapping.prototype.beginUpdate = function()
 	return graphModel;
 };
 
+/**
+ * Syncs initial state from collab model to graph model.
+ */
+RealtimeMapping.prototype.installAllRealtimeCellListeners = function(rtCell)
+{
+	if (rtCell != null)
+	{
+		this.installRealtimeCellListeners(rtCell);
+		
+		for (var i = 0; i < rtCell.children.length; i++)
+		{
+			this.installAllRealtimeCellListeners(rtCell.children.get(i));
+		}
+	}
+};
+
 /**
  * Adds the listener for added and removed cells in the collab model and maps
  * them to the graph model.
@@ -962,3 +986,30 @@ RealtimeMapping.prototype.realtimeMathEnabledChanged = function(value, quiet)
 		this.driveRealtime.ignoreMathEnabledChanged = false;
 	}
 };
+
+/**
+ * Syncs initial state from collab model to graph model.
+ */
+RealtimeMapping.prototype.removeAllRealtimeCellListeners = function(rtCell)
+{
+	if (rtCell != null)
+	{
+		rtCell.removeAllEventListeners();
+		rtCell.children.removeAllEventListeners();
+		
+		for (var i = 0; i < rtCell.children.length; i++)
+		{
+			this.removeAllRealtimeCellListeners(rtCell.children.get(i));
+		}
+	}
+};
+
+/**
+ * Syncs initial state from collab model to graph model.
+ */
+RealtimeMapping.prototype.destroy = function()
+{
+	this.diagramMap.removeAllEventListeners();
+	this.selectionMap.removeAllEventListeners();
+	this.removeAllRealtimeCellListeners(this.diagramMap.get(this.driveRealtime.rootKey));
+};

Plik diff jest za duży
+ 11 - 11
war/js/embed-static.min.js


+ 1 - 1
war/js/mxgraph/Format.js

@@ -2658,7 +2658,7 @@ TextFormatPanel.prototype.addFont = function(container)
 				node = node.parentNode;
 			}
 			
-			if (node == graph.cellEditor.textarea && graph.cellEditor.textarea.firstChild != null)
+			if (node != null && node == graph.cellEditor.textarea && graph.cellEditor.textarea.firstChild != null)
 			{
 				if (graph.cellEditor.textarea.firstChild.nodeName != 'FONT')
 				{

+ 3 - 2
war/js/mxgraph/Graph.js

@@ -1406,8 +1406,9 @@ Graph.prototype.selectCellsForConnectVertex = function(cells, evt, hoverIcons)
  */
 Graph.prototype.connectVertex = function(source, direction, length, evt, forceClone)
 {
-	var pt = (source.geometry.relative) ? new mxPoint(source.parent.geometry.width * source.geometry.x,
-			source.parent.geometry.height * source.geometry.y) : new mxPoint(source.geometry.x, source.geometry.y);
+	var pt = (source.geometry.relative && source.parent.geometry != null) ?
+			new mxPoint(source.parent.geometry.width * source.geometry.x, source.parent.geometry.height * source.geometry.y) :
+			new mxPoint(source.geometry.x, source.geometry.y);
 		
 	if (direction == mxConstants.DIRECTION_NORTH)
 	{

Plik diff jest za duży
+ 11 - 11
war/js/reader.min.js


Plik diff jest za duży
+ 45 - 44
war/js/viewer.min.js


+ 1 - 1
war/package.json

@@ -27,6 +27,6 @@
 	"homepage": "https://github.com/jgraph/draw.io",
 	"devDependencies":
 	{
-    	"electron": "^1.3.4"
+    	"electron": "^1.4.1"
 	}
 }