David Benson [draw.io] 4 лет назад
Родитель
Сommit
e0c5fd31df
77 измененных файлов с 5048 добавлено и 4368 удалено
  1. 13 0
      ChangeLog
  2. 1 1
      VERSION
  3. 3 3
      src/main/webapp/electron.js
  4. 1834 1819
      src/main/webapp/js/app.min.js
  5. 389 109
      src/main/webapp/js/diagramly/Dialogs.js
  6. 256 11
      src/main/webapp/js/diagramly/Editor.js
  7. 115 10
      src/main/webapp/js/diagramly/GraphViewer.js
  8. 5 3
      src/main/webapp/js/diagramly/Menus.js
  9. 2 1
      src/main/webapp/js/diagramly/Minimal.js
  10. 58 29
      src/main/webapp/js/diagramly/Pages.js
  11. 12 12
      src/main/webapp/js/grapheditor/Editor.js
  12. 78 52
      src/main/webapp/js/grapheditor/EditorUi.js
  13. 49 15
      src/main/webapp/js/grapheditor/Graph.js
  14. 1082 1071
      src/main/webapp/js/viewer-static.min.js
  15. 1082 1071
      src/main/webapp/js/viewer.min.js
  16. 1 1
      src/main/webapp/mxgraph/mxClient.js
  17. 8 158
      src/main/webapp/plugins/tags.js
  18. 1 0
      src/main/webapp/resources/dia.txt
  19. 1 0
      src/main/webapp/resources/dia_am.txt
  20. 1 0
      src/main/webapp/resources/dia_ar.txt
  21. 1 0
      src/main/webapp/resources/dia_bg.txt
  22. 1 0
      src/main/webapp/resources/dia_bn.txt
  23. 1 0
      src/main/webapp/resources/dia_bs.txt
  24. 1 0
      src/main/webapp/resources/dia_ca.txt
  25. 1 0
      src/main/webapp/resources/dia_cs.txt
  26. 1 0
      src/main/webapp/resources/dia_da.txt
  27. 1 0
      src/main/webapp/resources/dia_de.txt
  28. 1 0
      src/main/webapp/resources/dia_el.txt
  29. 1 0
      src/main/webapp/resources/dia_eo.txt
  30. 1 0
      src/main/webapp/resources/dia_es.txt
  31. 1 0
      src/main/webapp/resources/dia_et.txt
  32. 1 0
      src/main/webapp/resources/dia_eu.txt
  33. 1 0
      src/main/webapp/resources/dia_fa.txt
  34. 1 0
      src/main/webapp/resources/dia_fi.txt
  35. 1 0
      src/main/webapp/resources/dia_fil.txt
  36. 1 0
      src/main/webapp/resources/dia_fr.txt
  37. 1 0
      src/main/webapp/resources/dia_gl.txt
  38. 1 0
      src/main/webapp/resources/dia_gu.txt
  39. 1 0
      src/main/webapp/resources/dia_he.txt
  40. 1 0
      src/main/webapp/resources/dia_hi.txt
  41. 1 0
      src/main/webapp/resources/dia_hr.txt
  42. 1 0
      src/main/webapp/resources/dia_hu.txt
  43. 1 0
      src/main/webapp/resources/dia_i18n.txt
  44. 1 0
      src/main/webapp/resources/dia_id.txt
  45. 1 0
      src/main/webapp/resources/dia_it.txt
  46. 1 0
      src/main/webapp/resources/dia_ja.txt
  47. 1 0
      src/main/webapp/resources/dia_kn.txt
  48. 1 0
      src/main/webapp/resources/dia_ko.txt
  49. 1 0
      src/main/webapp/resources/dia_lt.txt
  50. 1 0
      src/main/webapp/resources/dia_lv.txt
  51. 1 0
      src/main/webapp/resources/dia_ml.txt
  52. 1 0
      src/main/webapp/resources/dia_mr.txt
  53. 1 0
      src/main/webapp/resources/dia_ms.txt
  54. 1 0
      src/main/webapp/resources/dia_my.txt
  55. 1 0
      src/main/webapp/resources/dia_nl.txt
  56. 1 0
      src/main/webapp/resources/dia_no.txt
  57. 1 0
      src/main/webapp/resources/dia_pl.txt
  58. 1 0
      src/main/webapp/resources/dia_pt-br.txt
  59. 1 0
      src/main/webapp/resources/dia_pt.txt
  60. 1 0
      src/main/webapp/resources/dia_ro.txt
  61. 1 0
      src/main/webapp/resources/dia_ru.txt
  62. 1 0
      src/main/webapp/resources/dia_si.txt
  63. 1 0
      src/main/webapp/resources/dia_sk.txt
  64. 1 0
      src/main/webapp/resources/dia_sl.txt
  65. 1 0
      src/main/webapp/resources/dia_sr.txt
  66. 1 0
      src/main/webapp/resources/dia_sv.txt
  67. 1 0
      src/main/webapp/resources/dia_sw.txt
  68. 1 0
      src/main/webapp/resources/dia_ta.txt
  69. 1 0
      src/main/webapp/resources/dia_te.txt
  70. 1 0
      src/main/webapp/resources/dia_th.txt
  71. 1 0
      src/main/webapp/resources/dia_tr.txt
  72. 1 0
      src/main/webapp/resources/dia_uk.txt
  73. 1 0
      src/main/webapp/resources/dia_vi.txt
  74. 1 0
      src/main/webapp/resources/dia_zh-tw.txt
  75. 1 0
      src/main/webapp/resources/dia_zh.txt
  76. 1 1
      src/main/webapp/service-worker.js
  77. 1 1
      src/main/webapp/service-worker.js.map

+ 13 - 0
ChangeLog

@@ -1,3 +1,16 @@
+06-SEP-2021: 15.1.0
+
+- Fixes link handling in viewer https://github.com/jgraph/drawio/issues/2220
+- Improvements to tags dialog https://github.com/jgraph/drawio/issues/2208
+- Fixes missing background page dropdown
+- Removes link if graph disabled or no cells selected
+- Highlights selection cells in disabled graphs
+- Fixes placeholders in PDF export
+- Fixes background pages and clipping https://github.com/jgraph/drawio/issues/2223
+- Adds tags custom action
+- Adds checks for valid tags
+- Fixes ignored background image bounds in lightbox
+
 02-SEP-2021: 15.0.6
 
 - Fixes NPE for PDF export with single page https://github.com/jgraph/drawio/issues/2221

+ 1 - 1
VERSION

@@ -1 +1 @@
-15.0.6
+15.1.0

+ 3 - 3
src/main/webapp/electron.js

@@ -325,10 +325,10 @@ app.on('ready', e =>
 			{
 	    		from = options.pageIndex;
 			}
-	    	else if (options.pageRage && options.pageRage.length == 2)
+	    	else if (options.pageRange && options.pageRange.length == 2)
 			{
-	    		from = options.pageRage[0] >= 0 ? options.pageRage[0] : null;
-	    		to = options.pageRage[1] >= 0 ? options.pageRage[1] : null;
+	    		from = options.pageRange[0] >= 0 ? options.pageRange[0] : null;
+	    		to = options.pageRange[1] >= 0 ? options.pageRange[1] : null;
 			}
 
 			var expArgs = {

Разница между файлами не показана из-за своего большого размера
+ 1834 - 1819
src/main/webapp/js/app.min.js


+ 389 - 109
src/main/webapp/js/diagramly/Dialogs.js

@@ -1570,7 +1570,7 @@ var BackgroundImageDialog = function(editorUi, applyFn, img)
 		}
 	}
 
-	if (isPageLink || editorUi.pages == null || editorUi.pages.length == 1)
+	if (!isPageLink && (editorUi.pages == null || editorUi.pages.length == 1))
 	{
 		urlRadio.style.display = 'none';
 		pageRadio.style.display = 'none';
@@ -7456,7 +7456,6 @@ var FindWindow = function(ui, x, y, w, h, withReplace)
 var FreehandWindow = function(editorUi, x, y, w, h)
 {
 	var graph = editorUi.editor.graph;
-	var propertyName = 'tags';
 
 	var div = document.createElement('div');
 	div.style.textAlign = 'center';
@@ -7551,7 +7550,7 @@ var FreehandWindow = function(editorUi, x, y, w, h)
 var TagsWindow = function(editorUi, x, y, w, h)
 {
 	var graph = editorUi.editor.graph;
-	var propertyName = 'tags';
+	var allTags = [];
 
 	var div = document.createElement('div');
 	div.style.userSelect = 'none';
@@ -7559,151 +7558,432 @@ var TagsWindow = function(editorUi, x, y, w, h)
 	div.style.padding = '10px';
 	div.style.height = '100%';
 	
-	var searchInput = document.createElement('input');
-	searchInput.setAttribute('placeholder', mxResources.get('allTags'));
-	searchInput.setAttribute('type', 'text');
-	searchInput.style.marginTop = '4px';
-	searchInput.style.width = '260px';
-	searchInput.style.fontSize = '12px';
-	searchInput.style.borderRadius = '4px';
-	searchInput.style.padding = '6px';
-	div.appendChild(searchInput);
-	
-	if (!editorUi.isOffline() || mxClient.IS_CHROMEAPP)
-	{
-		searchInput.style.width = '240px';
-		var elt = editorUi.menus.createHelpLink('https://www.diagrams.net/doc/faq/tags');
-		elt.firstChild.style.marginBottom = '6px';
-		elt.style.marginLeft = '6px';
-		div.appendChild(elt);
-	}
-	
-	mxEvent.addListener(searchInput, 'dblclick', function()
+	var tagCloud = document.createElement('div');
+	tagCloud.style.border = '1px solid #808080';
+	tagCloud.style.boxSizing = 'border-box';
+	tagCloud.style.borderRadius = '4px';
+	tagCloud.style.userSelect = 'none';
+	tagCloud.style.overflowY = 'scroll';
+	tagCloud.style.position = 'absolute';
+	tagCloud.style.left = '10px';
+	tagCloud.style.right = '10px';
+	tagCloud.style.top = '10px';
+	tagCloud.style.bottom = '68px';
+
+	div.appendChild(tagCloud);
+	
+	var options = document.createElement('div');
+	options.style.position = 'absolute';
+	options.style.left = '10px';
+	options.style.right = '10px';
+	options.style.height = '10px';
+	options.style.bottom = '54px';
+
+	var removeCb = document.createElement('input');
+	removeCb.setAttribute('type', 'checkbox');
+	removeCb.setAttribute('id', 'geRemoveUnusedTags');
+	removeCb.style.marginRight = '8px';
+	options.appendChild(removeCb);
+
+	var span = document.createElement('label');
+	span.setAttribute('for', 'geRemoveUnusedTags');
+	mxUtils.write(span, mxResources.get('removeUnusedTags'));
+	span.style.textOverflow = 'ellipsis';
+	span.style.position = 'relative';
+	span.style.top = '-1px';
+	options.appendChild(span);
+	div.appendChild(options);
+
+	mxEvent.addListener(removeCb, 'change', function(evt)
+	{
+		refreshUi();
+		mxEvent.consume(evt);
+	});
+
+	var addBtn = mxUtils.button(mxResources.get('add') + '...', function()
 	{
-		var dlg = new FilenameDialog(editorUi, propertyName, mxResources.get('ok'), mxUtils.bind(this, function(name)
+		if (graph.isEnabled())
 		{
-			if (name != null && name.length > 0)
+			var dlg = new FilenameDialog(editorUi, '', mxResources.get('add'), function(newValue)
 			{
-				propertyName = name;
-			}
-		}), mxResources.get('enterPropertyName'));
-		editorUi.showDialog(dlg.container, 300, 80, true, true);
-		dlg.init();
+				editorUi.hideDialog();
+				
+				if (newValue != null && newValue.length > 0)
+				{
+					var temp = newValue.split(' ');
+					var tags = [];
+
+					for (var i = 0; i < temp.length; i++)
+					{
+						var tag = mxUtils.trim(temp[i]);
+
+						if (tag != '')
+						{
+							tags.push(tag);
+						}
+					}
+
+					if (tags.length > 0)
+					{
+						if (graph.isSelectionEmpty())
+						{
+							allTags = allTags.concat(tags);
+							refreshUi();
+						}
+						else
+						{
+							graph.addTagsForCells(graph.getSelectionCells(), tags);
+						}
+					}
+				}
+			}, mxResources.get('enterValue') + ' (' + mxResources.get('tags') + ')');
+
+			editorUi.showDialog(dlg.container, 300, 80, true, true);
+			dlg.init();
+		}
 	});
 	
-	searchInput.setAttribute('title', mxResources.get('doubleClickChangeProperty'));
+	addBtn.setAttribute('title', mxResources.get('add'));
+	addBtn.className = 'geBtn';
+	addBtn.marginTop = '4px';
 
-	function searchCells(cells)
+	graph.addListener(mxEvent.ROOT, function()
 	{
-		return graph.getCellsForTags(searchInput.value.split(' '), cells, propertyName, true);
-	};
+		allTags = [];
+	});
 
-	function setCellsVisible(cells, visible)
+	function refreshButtons()
 	{
-		graph.setCellsVisible(cells, visible);
+		if (graph.isSelectionEmpty() && removeCb.checked)
+		{
+			addBtn.setAttribute('disabled', 'disabled');
+		}
+		else
+		{
+			addBtn.removeAttribute('disabled');
+		}
 	};
-	
-	mxUtils.br(div);
 
-	var hideBtn = mxUtils.button(mxResources.get('hide'), function()
+	function refreshTags(tags, selected)
 	{
-		setCellsVisible(searchCells(), false);
-	});
-	
-	hideBtn.setAttribute('title', mxResources.get('hide'));
-	hideBtn.style.marginTop = '8px';
-	hideBtn.style.marginRight = '4px';
-	hideBtn.className = 'geBtn';
-	
-	div.appendChild(hideBtn);
+		tagCloud.innerHTML = '';
 
-	var showBtn = mxUtils.button(mxResources.get('show'), function()
-	{
-		var cells = searchCells();
-		setCellsVisible(cells, true);
-		
-		if (graph.isEnabled())
+		if (tags.length > 0)
 		{
-			// Ignores layers for selection
-			var temp = [];
-			
-			for (var i = 0; i < cells.length; i++)
+			var table = document.createElement('table');
+			table.setAttribute('cellpadding', '2');
+			table.style.boxSizing = 'border-box';
+			table.style.width = '100%';
+
+			var tbody = document.createElement('tbody');
+
+			var row = document.createElement('tr');
+			var td = document.createElement('td');
+			var a = document.createElement('a');
+			a.style.fontSize = '10px';
+			a.style.cursor = 'pointer';
+			a.setAttribute('title', mxResources.get(
+				(graph.hiddenTags.length == 0) ?
+				'selectNone' : 'selectAll'));
+			mxUtils.write(a, mxResources.get('show'));
+			td.appendChild(a);
+			row.appendChild(td);
+
+			mxEvent.addListener(a, 'click', function(evt)
+			{
+				if (graph.hiddenTags.length == 0)
+				{
+					graph.hiddenTags = allTags.slice();
+				}
+				else
+				{
+					graph.hiddenTags = [];
+				}
+
+				graph.clearSelection();
+				graph.refresh();
+
+				mxEvent.consume(evt);
+			});
+
+			if (graph.isEnabled())
 			{
-				if (!graph.isCellLocked(cells[i]) &&
-					(graph.model.isVertex(cells[i]) ||
-					graph.model.isEdge(cells[i])))
+				td = document.createElement('td');
+				a = document.createElement('a');
+				a.style.fontSize = '10px';
+				mxUtils.write(a, mxResources.get('tags'));
+				td.appendChild(a);
+
+				if (graph.isEnabled() && !graph.isSelectionEmpty())
 				{
-					temp.push(cells[i]);
+					a.setAttribute('title', mxResources.get('selectAll'));
+					a.style.cursor = 'pointer';
+
+					mxEvent.addListener(a, 'click', function(evt)
+					{
+						graph.addTagsForCells(graph.getSelectionCells(), allTags);
+						graph.refresh();
+
+						mxEvent.consume(evt);
+					});
 				}
+
+				row.appendChild(td);
 			}
+
+			td = document.createElement('td');
+
+			a = document.createElement('a');
+			a.style.fontSize = '10px';
+			a.style.cursor = 'pointer';
+			a.setAttribute('title', mxResources.get('selectAll') +
+				' (' + mxResources.get('allTags') + ')');
+			mxUtils.write(a, mxResources.get('select'));
+
+			mxEvent.addListener(a, 'click', function(evt)
+			{
+				var cells = graph.getCellsForTags([]);
+
+				if (graph.isEnabled())
+				{
+					graph.setSelectionCells(cells, null, null, true);
+				}
+				else
+				{
+					graph.highlightCells(cells);
+				}
+
+				refreshUi();
+				mxEvent.consume(evt);
+			});
+
+			td.appendChild(a);
+
+			td.style.width = '100%';
+			row.appendChild(td);
+			tbody.appendChild(row);
+
+			var td2 = document.createElement('td');
+
+			if (tags != null && tags.length > 0)
+			{
+				for (var i = 0; i < tags.length; i++)
+				{
+					(function(tag)
+					{
+						var row = document.createElement('tr');
+						var td = document.createElement('td');
+						td.style.textAlign = 'center';
+
+						var cb = document.createElement('input');
+						cb.setAttribute('type', 'checkbox');
+						cb.style.marginRight = '4px';
+
+						cb.defaultChecked = mxUtils.indexOf(graph.hiddenTags, tag) < 0;
+						cb.checked = cb.defaultChecked;
+						cb.setAttribute('title', mxResources.get(
+							cb.defaultChecked ? 'hide' : 'show'));
+
+						mxEvent.addListener(cb, 'change', function(evt)
+						{
+							var idx = mxUtils.indexOf(graph.hiddenTags, tag)
+
+							if (idx < 0 && !cb.checked)
+							{
+								graph.hiddenTags.push(tag);
+							}
+							else if (idx >= 0 && cb.checked)
+							{
+								graph.hiddenTags.splice(idx, 1);
+							}
+
+							graph.clearSelection();
+							graph.refresh();
+
+							mxEvent.consume(evt);
+						});
+
+						td.appendChild(cb);
+						row.appendChild(td);
 			
-			graph.setSelectionCells(temp);
+						if (graph.isEnabled())
+						{
+							td = document.createElement('td');
+							td.style.textAlign = 'center';
+
+							var cb2 = document.createElement('input');
+							cb2.setAttribute('type', 'checkbox');
+							cb2.style.marginRight = '8px';
+
+							cb2.defaultChecked = (selected != null && mxUtils.indexOf(selected, tag) >= 0);
+							cb2.checked = cb2.defaultChecked;
+							cb2.setAttribute('title', mxResources.get(
+								cb2.defaultChecked ? 'removeIt' : 'add',
+								['']));
+
+							if (selected == null)
+							{
+								cb2.setAttribute('disabled', 'disabled');
+							}
+							else
+							{
+								mxEvent.addListener(cb2, 'change', function(evt)
+								{
+									if (cb2.checked)
+									{
+										graph.addTagsForCells(graph.getSelectionCells(), [tag]);
+									}
+									else
+									{
+										graph.removeTagsForCells(graph.getSelectionCells(), [tag]);
+									}
+								
+									mxEvent.consume(evt);
+								});
+							}
+
+							td.appendChild(cb2);
+							row.appendChild(td);
+						}
+
+						td = document.createElement('td');
+
+						a = document.createElement('a');
+						mxUtils.write(a, tag);
+						a.setAttribute('title', mxResources.get('selectAll') +
+							' (' + tag + ')');
+						a.style.textOverflow = 'ellipsis';
+						a.style.position = 'relative';
+						a.style.cursor = 'pointer';
+						a.style.top = '-1px';
+						td.appendChild(a);
+
+						mxEvent.addListener(a, 'click', (function()
+						{
+							return function(evt)
+							{
+								if (!cb.checked)
+								{
+									cb.click();
+								}
+
+								var cells = graph.getCellsForTags(
+									[tag], null, null, true);
+
+								if (graph.isEnabled())
+								{
+									graph.setSelectionCells(cells);
+								}
+								else
+								{
+									graph.highlightCells(cells);
+								}
+
+								mxEvent.consume(evt);
+							};
+						})());
+						
+						row.appendChild(td);
+						tbody.appendChild(row);
+					})(tags[i]);
+				}
+			}
+
+			table.appendChild(tbody);
+			tagCloud.appendChild(table);
 		}
-		else
+		
+		refreshButtons();
+	};
+
+	var refreshUi = mxUtils.bind(this, function()
+	{
+		if (this.window.isVisible())
 		{
-			for (var i = 0; i < cells.length; i++)
+			var tags = graph.getAllTags();
+
+			if (removeCb.checked)
+			{
+				allTags = tags;
+			}
+			else
+			{
+				for (var i = 0; i < tags.length; i++)
+				{
+					if (mxUtils.indexOf(allTags, tags[i]) < 0)
+					{
+						allTags.push(tags[i]);
+					}
+				}
+			}
+
+			allTags.sort();
+
+			if (graph.isSelectionEmpty())
 			{
-				graph.highlightCell(cells[i]);
+				refreshTags(allTags);
+			}
+			else
+			{
+				refreshTags(allTags, graph.getCommonTagsForCells(
+					graph.getSelectionCells()));
 			}
 		}
 	});
-	
-	showBtn.setAttribute('title', mxResources.get('show'));
-	showBtn.style.marginTop = '8px';
-	showBtn.style.marginRight = '4px';
-	showBtn.className = 'geBtn';
-	
-	div.appendChild(showBtn);
-	
-	var action = editorUi.actions.get('tags');
 
-	var btn = mxUtils.button(mxResources.get('close'), function()
+	graph.selectionModel.addListener(mxEvent.EVENT_CHANGE, refreshUi);
+	graph.model.addListener(mxEvent.EVENT_CHANGE, refreshUi);
+	graph.addListener(mxEvent.REFRESH, refreshUi);
+
+	var footer = document.createElement('div');
+	footer.style.boxSizing = 'border-box';
+	footer.style.position = 'absolute';
+	footer.style.userSelect = 'none';
+	footer.style.bottom = '0px';
+	footer.style.height = '42px';
+	footer.style.right = '10px';
+	footer.style.left = '10px';
+
+	// TODO: Write help topic and add link
+	/*
+	var helpBtn = mxUtils.button(mxResources.get('help'), function()
 	{
-		action.funct();
+		editorUi.openLink('');
 	});
+
+	helpBtn.className = 'geBtn';
+	helpBtn.style.marginRight = '4px';
 	
-	btn.setAttribute('title', mxResources.get('close') + ' (Enter/Esc)');
-	btn.style.marginTop = '8px';
-	btn.className = 'geBtn gePrimaryBtn';
+	if (editorUi.isOffline() && !mxClient.IS_CHROMEAPP)
+	{
+		helpBtn.style.display = 'none';
+	}
 	
-	div.appendChild(btn);
-		
-	mxEvent.addListener(searchInput, 'keyup', function(evt)
+	footer.appendChild(helpBtn);*/
+
+	if (graph.isEnabled())
 	{
-		// Ctrl or Cmd keys
-		if (evt.keyCode == 13 || evt.keyCode == 27)
-		{
-			action.funct();
-		}
-	});
+		footer.appendChild(addBtn);
+	}
+
+	div.appendChild(footer);
 
 	this.window = new mxWindow(mxResources.get('tags'), div, x, y, w, h, true, true);
 	this.window.destroyOnClose = false;
 	this.window.setMaximizable(false);
-	this.window.setResizable(false);
+	this.window.setResizable(true);
 	this.window.setClosable(true);
-	
+
+	this.window.contentWrapper.style.height = '100%';
+	this.window.table.style.minHeight = '40px';
+	this.window.table.style.minWidth = '200px';
+	this.window.div.style.minHeight = this.window.table.style.minHeight;
+	this.window.div.style.minWidth = this.window.table.style.minWidth;
+
 	this.window.addListener('show', mxUtils.bind(this, function()
 	{
+		refreshUi();
 		this.window.fit();
-		
-		if (this.window.isVisible())
-		{
-			searchInput.focus();
-			
-			if (mxClient.IS_GC || mxClient.IS_FF || document.documentMode >= 5)
-			{
-				searchInput.select();
-			}
-			else
-			{
-				document.execCommand('selectAll', false, null);
-			}
-		}
-		else
-		{
-			graph.container.focus();
-		}
 	}));
 	
 	this.window.setLocation = function(x, y)

Разница между файлами не показана из-за своего большого размера
+ 256 - 11
src/main/webapp/js/diagramly/Editor.js


+ 115 - 10
src/main/webapp/js/diagramly/GraphViewer.js

@@ -319,16 +319,12 @@ GraphViewer.prototype.init = function(container, xmlNode, graphConfig)
 				
 				this.selectPageById = function(id)
 				{
-					var found = false;
-					
-					for (var i = 0; i < this.diagrams.length; i++)
+					var index = this.getIndexById(id);
+					var found = index >= 0;
+
+					if (found)
 					{
-						if (this.diagrams[i].getAttribute('id') == id)
-						{
-							this.selectPage(i);
-							found = true;
-							break;
-						}
+						this.selectPage(index);
 					}
 					
 					return found;
@@ -346,7 +342,57 @@ GraphViewer.prototype.init = function(container, xmlNode, graphConfig)
 						lastXmlNode = this.xmlNode;
 					}
 				});
-				
+
+				// Replaces background page reference with SVG
+				var graphSetBackgroundImage = this.graph.setBackgroundImage;
+		
+				this.graph.setBackgroundImage = function(img)
+				{
+					if (img != null && Graph.isPageLink(img.src))
+					{
+						var src = img.src;
+						var comma = src.indexOf(',');
+							
+						if (comma > 0)
+						{
+							var index = self.getIndexById(src.substring(comma + 1));
+					
+							if (index >= 0)
+							{
+								img = self.getImageForGraphModel(
+									Editor.parseDiagramNode(
+									self.diagrams[index]));
+								img.originalSrc = src;
+							}
+						}
+					}
+
+					graphSetBackgroundImage.apply(this, arguments);
+				};
+
+				// Overrides graph bounds to include background pages
+				var graphGetGraphBounds = this.graph.getGraphBounds;
+		
+				this.graph.getGraphBounds = function(img)
+				{
+					var bounds = graphGetGraphBounds.apply(this, arguments);
+					var img = this.backgroundImage;
+
+					// Check img.originalSrc to ignore background
+					// images but not background pages
+					if (img != null)
+					{
+						var t = this.view.translate;
+						var s = this.view.scale;
+		
+						bounds.add(new mxRectangle(
+							(t.x + img.x) * s, (t.y + img.y) * s,
+							img.width * s, img.height * s));
+					}
+
+					return bounds;
+				};
+
 				// LATER: Add event for setGraphXml
 				this.addListener('xmlNodeChanged', update);
 				update();
@@ -521,6 +567,65 @@ GraphViewer.prototype.getImageUrl = function(url)
 	return url;
 };
 
+/**
+ * 
+ */
+GraphViewer.prototype.getImageForGraphModel = function(node)
+{
+	var graphGetGlobalVariable = this.graph.getGlobalVariable;
+	var graph = Graph.createOffscreenGraph(this.graph.getStylesheet());
+	// var index = this.getPageIndex((sourcePage != null) ?
+	// 	sourcePage : this.currentPage);
+
+	graph.getGlobalVariable = function(name)
+	{
+		// if (name == 'pagenumber')
+		// {
+		// 	return index + 1;
+		// }
+		// else if (name == 'page' && sourcePage != null)
+		// {
+		// 	return sourcePage.getName();
+		// }
+		// else
+		{
+			return graphGetGlobalVariable.apply(this, arguments);
+		}
+	};
+
+	document.body.appendChild(graph.container);
+
+	var codec = new mxCodec(node.ownerDocument);
+	var root = codec.decode(node).root;
+	graph.model.setRoot(root);
+	
+	var svgRoot = graph.getSvg();
+	var bounds = graph.getGraphBounds();
+	document.body.removeChild(graph.container);
+
+	return new mxImage(Editor.createSvgDataUri(mxUtils.getXml(svgRoot)),
+		bounds.width, bounds.height, bounds.x, bounds.y);
+};
+
+/**
+ * 
+ */
+GraphViewer.prototype.getIndexById = function(id)
+{
+	if (this.diagrams != null)
+	{
+		for (var i = 0; i < this.diagrams.length; i++)
+		{
+			if (this.diagrams[i].getAttribute('id') == id)
+			{
+				return i;
+			}
+		}
+	}
+
+	return -1;
+};
+
 /**
  * 
  */

+ 5 - 3
src/main/webapp/js/diagramly/Menus.js

@@ -897,11 +897,11 @@
 			editorUi.openLink('https://get.diagrams.net/');
 		});
 		
-		action = editorUi.actions.addAction('tags...', mxUtils.bind(this, function()
+		action = editorUi.actions.addAction('tags', mxUtils.bind(this, function()
 		{
 			if (this.tagsWindow == null)
 			{
-				this.tagsWindow = new TagsWindow(editorUi, document.body.offsetWidth - 380, 230, 300, 120);
+				this.tagsWindow = new TagsWindow(editorUi, document.body.offsetWidth - 400, 60, 240, 270);
 				this.tagsWindow.window.addListener('show', function()
 				{
 					editorUi.fireEvent(new mxEventObject('tags'));
@@ -3525,6 +3525,8 @@
 		viewPanelsMenu.funct = function(menu, parent)
 		{
 			viewPanelsFunct.apply(this, arguments);
+
+			editorUi.menus.addMenuItems(menu, ['tags'], parent);
 			
 			if (editorUi.commentsSupported())
 			{
@@ -3613,7 +3615,7 @@
 				this.addMenuItem(menu, 'plugins', parent);
 			}
 
-			this.addMenuItems(menu, ['tags', '-', 'editDiagram'], parent);
+			this.addMenuItems(menu, ['-', 'editDiagram'], parent);
 	
 			if (Graph.translateDiagram)
 			{

+ 2 - 1
src/main/webapp/js/diagramly/Minimal.js

@@ -907,6 +907,7 @@ EditorUi.initMinimalTheme = function()
         ui.actions.get('createShape').label = mxResources.get('shape') + '...';
         ui.actions.get('outline').label = mxResources.get('outline') + '...';
         ui.actions.get('layers').label = mxResources.get('layers') + '...';
+        ui.actions.get('tags').label = mxResources.get('tags') + '...';
 		ui.actions.get('forkme').visible = urlParams['sketch'] != '1';
 		ui.actions.get('downloadDesktop').visible = urlParams['sketch'] != '1';
 
@@ -1332,7 +1333,7 @@ EditorUi.initMinimalTheme = function()
 			}
 			else
 			{
-				ui.menus.addMenuItems(menu, ['pageSetup', '-', 'layers'], parent);
+				ui.menus.addMenuItems(menu, ['pageSetup', '-', 'layers', 'tags'], parent);
 			}
         })));
 	};

+ 58 - 29
src/main/webapp/js/diagramly/Pages.js

@@ -277,24 +277,32 @@ EditorUi.prototype.tabContainerHeight = 38;
  */
 EditorUi.prototype.getSelectedPageIndex = function()
 {
-	var result = null;
-	
-	if (this.pages != null && this.currentPage != null)
-	{
-		for (var i = 0; i < this.pages.length; i++)
-		{
-			if (this.pages[i] == this.currentPage)
-			{
-				result = i;
-				
-				break;
-			}
-		}
-	}
-	
-	return result;
+	return this.getPageIndex(this.currentPage);
 };
 
+/**
+ * Returns the index of the given page.
+ */
+ EditorUi.prototype.getPageIndex = function(page)
+ {
+	 var result = null;
+	 
+	 if (this.pages != null && page != null)
+	 {
+		 for (var i = 0; i < this.pages.length; i++)
+		 {
+			 if (this.pages[i] == page)
+			 {
+				 result = i;
+				 
+				 break;
+			 }
+		 }
+	 }
+	 
+	 return result;
+ };
+ 
 /**
  * Returns true if the given string contains an mxfile.
  */
@@ -328,7 +336,7 @@ EditorUi.prototype.createImageForPageLink = function(src, sourcePage)
 
 		if (page != null && page != sourcePage)
 		{
-			result = this.getImageForPage(page);
+			result = this.getImageForPage(page, sourcePage);
 			result.originalSrc = src;
 		}
 	}
@@ -344,14 +352,27 @@ EditorUi.prototype.createImageForPageLink = function(src, sourcePage)
 /**
  * Returns true if the given string contains an mxfile.
  */
-EditorUi.prototype.getImageForPage = function(page)
+EditorUi.prototype.getImageForPage = function(page, sourcePage)
 {
 	var graphGetGlobalVariable = this.editor.graph.getGlobalVariable;
 	var graph = this.createTemporaryGraph(this.editor.graph.getStylesheet());
+	var index = this.getPageIndex((sourcePage != null) ?
+		sourcePage : this.currentPage);
 
 	graph.getGlobalVariable = function(name)
 	{
-		return graphGetGlobalVariable.apply(this, arguments);
+		if (name == 'pagenumber')
+		{
+			return index + 1;
+		}
+		else if (name == 'page' && sourcePage != null)
+		{
+			return sourcePage.getName();
+		}
+		else
+		{
+			return graphGetGlobalVariable.apply(this, arguments);
+		}
 	};
 
 	document.body.appendChild(graph.container);
@@ -365,7 +386,7 @@ EditorUi.prototype.getImageForPage = function(page)
 	return new mxImage(Editor.createSvgDataUri(mxUtils.getXml(svgRoot)),
 		bounds.width, bounds.height, bounds.x, bounds.y);
 };
- 
+
 /**
  * Returns true if the given string contains an mxfile.
  */
@@ -591,6 +612,7 @@ Graph.prototype.createViewState = function(node)
 		defaultParent: null,
 		scrollbars: this.defaultScrollbars,
 		scale: 1,
+		hiddenTags: [],
 		extFonts: extFonts || []
 	};
 };
@@ -615,7 +637,8 @@ Graph.prototype.saveViewState = function(vs, node, ignoreTransient, resolveRefer
 		node.setAttribute('fold', (vs == null || vs.foldingEnabled) ? '1' : '0');
 	}
 
-	node.setAttribute('pageScale', (vs != null && vs.pageScale != null) ? vs.pageScale : mxGraph.prototype.pageScale);
+	node.setAttribute('pageScale', (vs != null && vs.pageScale != null) ?
+		vs.pageScale : mxGraph.prototype.pageScale);
 	
 	var pf = (vs != null) ? vs.pageFormat : (typeof mxSettings === 'undefined' ||
 		this.defaultPageFormat != null) ? mxGraph.prototype.pageFormat :
@@ -626,17 +649,20 @@ Graph.prototype.saveViewState = function(vs, node, ignoreTransient, resolveRefer
 		node.setAttribute('pageWidth', pf.width);
 		node.setAttribute('pageHeight', pf.height);
 	}
-	
-	if (vs != null && vs.background != null)
+
+	if (vs != null)
 	{
-		node.setAttribute('background', vs.background);
-	}
+		if (vs.background != null)
+		{
+			node.setAttribute('background', vs.background);
+		}
 
-	var bgImg = this.getBackgroundImageObject(vs.backgroundImage, resolveReferences);
+		var bgImg = this.getBackgroundImageObject(vs.backgroundImage, resolveReferences);
 
-	if (bgImg != null)
-	{
-		node.setAttribute('backgroundImage', JSON.stringify(bgImg));
+		if (bgImg != null)
+		{
+			node.setAttribute('backgroundImage', JSON.stringify(bgImg));
+		}
 	}
 
 	node.setAttribute('math', (vs != null && vs.mathEnabled) ? '1' : '0');
@@ -681,6 +707,7 @@ Graph.prototype.getViewState = function()
 		lastPasteXml: this.lastPasteXml,
 		pasteCounter: this.pasteCounter,
 		mathEnabled: this.mathEnabled,
+		hiddenTags: this.hiddenTags,
 		extFonts: this.extFonts
 	};
 };
@@ -712,6 +739,7 @@ Graph.prototype.setViewState = function(state, removeOldExtFonts)
 		this.setTooltips(state.tooltips);
 		this.setConnectable(state.connect);
 		this.setBackgroundImage(state.backgroundImage);
+		this.hiddenTags = state.hiddenTags;
 
 		var oldExtFonts = this.extFonts;
 		this.extFonts = state.extFonts || [];
@@ -787,6 +815,7 @@ Graph.prototype.setViewState = function(state, removeOldExtFonts)
 		this.pasteCounter = 0;
 		this.mathEnabled = false;
 		this.connectionArrowsEnabled = true;
+		this.hiddenTags = [];
 		this.extFonts = [];
 	}
 	

Разница между файлами не показана из-за своего большого размера
+ 12 - 12
src/main/webapp/js/grapheditor/Editor.js


+ 78 - 52
src/main/webapp/js/grapheditor/EditorUi.js

@@ -17,6 +17,31 @@ EditorUi = function(editor, container, lightbox)
 	this.initialDefaultVertexStyle = mxUtils.clone(graph.defaultVertexStyle);
 	this.initialDefaultEdgeStyle = mxUtils.clone(graph.defaultEdgeStyle);
 
+	if (lightbox)
+	{
+		// Overrides graph bounds to include background pages
+		var graphGetGraphBounds = graph.getGraphBounds;
+
+		graph.getGraphBounds = function(img)
+		{
+			var bounds = graphGetGraphBounds.apply(this, arguments);
+			var img = this.backgroundImage;
+
+			if (img != null)
+			{
+				var t = this.view.translate;
+				var s = this.view.scale;
+
+				bounds.add(new mxRectangle(
+					(t.x + img.x) * s, (t.y + img.y) * s,
+					img.width * s, img.height * s));
+			}
+	
+			return bounds;
+		};
+	}
+
+
 	// Faster scrollwheel zoom is possible with CSS transforms
 	if (graph.useCssTransforms)
 	{
@@ -1281,50 +1306,68 @@ EditorUi.prototype.installShapePicker = function()
 			}
 		};
 
+		var thread = null;
+
 		this.hoverIcons.addListener('focus', mxUtils.bind(this, function(sender, evt)
 		{
-			var arrow = evt.getProperty('arrow');
-			var dir = evt.getProperty('direction');
-			var mouseEvent = evt.getProperty('event');
-
-			var rect = arrow.getBoundingClientRect();
-			var offset = mxUtils.getOffset(graph.container);
-			var x = graph.container.scrollLeft + rect.x - offset.x;
-			var y = graph.container.scrollTop + rect.y - offset.y;
+			if (thread != null)
+			{
+				window.clearTimeout(thread);
+			}
 
-			var temp = graph.getCompositeParent((this.hoverIcons.currentState != null) ?
-				this.hoverIcons.currentState.cell : null);
-			var div = ui.showShapePicker(x, y, temp, mxUtils.bind(this, function(cell)
+			thread = window.setTimeout(mxUtils.bind(this, function()
 			{
-				if (cell != null)
+				var arrow = evt.getProperty('arrow');
+				var dir = evt.getProperty('direction');
+				var mouseEvent = evt.getProperty('event');
+
+				var rect = arrow.getBoundingClientRect();
+				var offset = mxUtils.getOffset(graph.container);
+				var x = graph.container.scrollLeft + rect.x - offset.x;
+				var y = graph.container.scrollTop + rect.y - offset.y;
+
+				var temp = graph.getCompositeParent((this.hoverIcons.currentState != null) ?
+					this.hoverIcons.currentState.cell : null);
+				var div = ui.showShapePicker(x, y, temp, mxUtils.bind(this, function(cell)
 				{
-					graph.connectVertex(temp, dir, graph.defaultEdgeLength, mouseEvent, true, true, function(x, y, execute)
+					if (cell != null)
 					{
-						execute(cell);
-							
-						if (ui.hoverIcons != null)
+						graph.connectVertex(temp, dir, graph.defaultEdgeLength, mouseEvent, true, true, function(x, y, execute)
 						{
-							ui.hoverIcons.update(graph.view.getState(cell));
-						}
-					}, function(cells)
-					{
-						graph.selectCellsForConnectVertex(cells);
-					}, mouseEvent, this.hoverIcons);
-				}
-			}), dir, true);
+							execute(cell);
+								
+							if (ui.hoverIcons != null)
+							{
+								ui.hoverIcons.update(graph.view.getState(cell));
+							}
+						}, function(cells)
+						{
+							graph.selectCellsForConnectVertex(cells);
+						}, mouseEvent, this.hoverIcons);
+					}
+				}), dir, true);
 
-			this.centerShapePicker(div, rect, x, y, dir);
-			mxUtils.setOpacity(div, 30);
+				this.centerShapePicker(div, rect, x, y, dir);
+				mxUtils.setOpacity(div, 30);
 
-			mxEvent.addListener(div, 'mouseenter', function()
-			{
-				mxUtils.setOpacity(div, 100);
-			});
+				mxEvent.addListener(div, 'mouseenter', function()
+				{
+					mxUtils.setOpacity(div, 100);
+				});
+
+				mxEvent.addListener(div, 'mouseleave', function()
+				{
+					ui.hideShapePicker();
+				});
+			}), 500);
+		}));
 
-			mxEvent.addListener(div, 'mouseleave', function()
+		this.hoverIcons.addListener('blur', mxUtils.bind(this, function(sender, evt)
+		{
+			if (thread != null)
 			{
-				ui.hideShapePicker();
-			});
+				window.clearTimeout(thread);
+			}
 		}));
 	}
 };
@@ -2151,7 +2194,7 @@ EditorUi.prototype.initCanvas = function()
 				pageInfo.style.display = 'inline-block';
 				pageInfo.style.verticalAlign = 'top';
 				pageInfo.style.fontFamily = 'Helvetica,Arial';
-				pageInfo.style.marginTop = '8px';
+				pageInfo.style.marginTop = '10px';
 				pageInfo.style.fontSize = '14px';
 				pageInfo.style.color = '#ffffff';
 				this.chromelessToolbar.appendChild(pageInfo);
@@ -2407,7 +2450,6 @@ EditorUi.prototype.initCanvas = function()
 			
 			if ((toolbarConfig.closeBtn && window.self === window.top) ||
 				(graph.lightbox && (urlParams['close'] == '1' || this.container != document.body)))
-			
 			{
 				addButton(mxUtils.bind(this, function(evt)
 				{
@@ -2934,23 +2976,7 @@ EditorUi.prototype.isPagesEnabled = function()
  */
 EditorUi.prototype.createTemporaryGraph = function(stylesheet)
 {
-	var graph = new Graph(document.createElement('div'));
-	graph.stylesheet.styles = mxUtils.clone(stylesheet.styles);
-	graph.resetViewOnRootChange = false;
-	graph.setConnectable(false);
-	graph.gridEnabled = false;
-	graph.autoScroll = false;
-	graph.setTooltips(false);
-	graph.setEnabled(false);
-
-	// Container must be in the DOM for correct HTML rendering
-	graph.container.style.visibility = 'hidden';
-	graph.container.style.position = 'absolute';
-	graph.container.style.overflow = 'hidden';
-	graph.container.style.height = '1px';
-	graph.container.style.width = '1px';
-	
-	return graph;
+	return Graph.createOffscreenGraph(stylesheet);
 };
 
 /**

+ 49 - 15
src/main/webapp/js/grapheditor/Graph.js

@@ -1309,6 +1309,30 @@ Graph.pasteStyles = ['rounded', 'shadow', 'dashed', 'dashPattern', 'fontFamily',
 					'arcSize', 'comic', 'sketch', 'fillWeight', 'hachureGap', 'hachureAngle', 'jiggle', 'disableMultiStroke',
 					'disableMultiStrokeFill', 'fillStyle', 'curveFitting', 'simplification', 'comicStyle'];
 
+/**
+ * Creates a temporary graph instance for rendering off-screen content.
+ */
+Graph.createOffscreenGraph = function(stylesheet)
+{
+	var graph = new Graph(document.createElement('div'));
+	graph.stylesheet.styles = mxUtils.clone(stylesheet.styles);
+	graph.resetViewOnRootChange = false;
+	graph.setConnectable(false);
+	graph.gridEnabled = false;
+	graph.autoScroll = false;
+	graph.setTooltips(false);
+	graph.setEnabled(false);
+
+	// Container must be in the DOM for correct HTML rendering
+	graph.container.style.visibility = 'hidden';
+	graph.container.style.position = 'absolute';
+	graph.container.style.overflow = 'hidden';
+	graph.container.style.height = '1px';
+	graph.container.style.width = '1px';
+
+	return graph;
+};
+ 
 /**
  * Helper function for creating SVG data URI.
  */
@@ -1738,6 +1762,25 @@ Graph.stripQuotes = function(text)
 	return text;
 };
 
+/**
+ * Create remove icon. 
+ */
+Graph.createRemoveIcon = function(title, onclick)
+{
+	var removeLink = document.createElement('img');
+	removeLink.setAttribute('src', Dialog.prototype.clearImage);
+	removeLink.setAttribute('title', title);
+	removeLink.setAttribute('width', '13');
+	removeLink.setAttribute('height', '10');
+	removeLink.style.marginLeft = '4px';
+	removeLink.style.marginBottom = '-1px';
+	removeLink.style.cursor = 'pointer';
+
+	mxEvent.addListener(removeLink, 'click', onclick);
+
+	return removeLink;
+};
+
 /**
  * Returns true if the given string is a page link.
  */
@@ -8835,7 +8878,7 @@ if (typeof mxVertexHandler != 'undefined')
 			    {
 			    	var tmp = me.sourceState;
 			    	
-			    	// Gets topmost intersecting cell with link
+			    	// Gets first intersecting ancestor with link
 			    	if (tmp == null || graph.getLinkForCell(tmp.cell) == null)
 			    	{
 			    		var cell = graph.getCellAt(me.getGraphX(), me.getGraphY(), null, null, null, function(state, x, y)
@@ -8843,9 +8886,9 @@ if (typeof mxVertexHandler != 'undefined')
 			    			return graph.getLinkForCell(state.cell) == null;
 	    				});
 			    		
-			    		tmp = graph.view.getState(cell);
+			    		tmp = (tmp != null && !graph.model.isAncestor(cell, tmp.cell)) ? null : graph.view.getState(cell);
 			    	}
-			    	
+
 			      	if (tmp != this.currentState)
 			      	{
 			        	if (this.currentState != null)
@@ -11881,7 +11924,7 @@ if (typeof mxVertexHandler != 'undefined')
 					var s = this.state.view.scale;
 					var unit = this.state.view.unit;
 					this.hint.innerHTML = formatHintText(this.roundLength(this.bounds.width / s), unit) + ' x ' + 
-											formatHintText(this.roundLength(this.bounds.height / s), unit);
+						formatHintText(this.roundLength(this.bounds.height / s), unit);
 				}
 				
 				var rot = (this.currentAlpha != null) ? this.currentAlpha : this.state.style[mxConstants.STYLE_ROTATION] || '0';
@@ -12726,17 +12769,8 @@ if (typeof mxVertexHandler != 'undefined')
 								mxEvent.consume(evt);
 							}));
 							
-							var removeLink = document.createElement('img');
-							removeLink.setAttribute('src', Dialog.prototype.clearImage);
-							removeLink.setAttribute('title', mxResources.get('removeIt', [mxResources.get('link')]));
-							removeLink.setAttribute('width', '13');
-							removeLink.setAttribute('height', '10');
-							removeLink.style.marginLeft = '4px';
-							removeLink.style.marginBottom = '-1px';
-							removeLink.style.cursor = 'pointer';
-							this.linkHint.appendChild(removeLink);
-							
-							mxEvent.addListener(removeLink, 'click', mxUtils.bind(this, function(evt)
+							this.linkHint.appendChildGraph.createRemoveIcon(mxResources.get('removeIt',
+								[mxResources.get('link')]), mxUtils.bind(this, function(evt)
 							{
 								this.graph.setLinkForCell(this.state.cell, null);
 								mxEvent.consume(evt);

Разница между файлами не показана из-за своего большого размера
+ 1082 - 1071
src/main/webapp/js/viewer-static.min.js


Разница между файлами не показана из-за своего большого размера
+ 1082 - 1071
src/main/webapp/js/viewer.min.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
src/main/webapp/mxgraph/mxClient.js


+ 8 - 158
src/main/webapp/plugins/tags.js

@@ -54,7 +54,6 @@ Draw.loadPlugin(function(editorUi)
 	var HiddenTagsWindow = function(editorUi, x, y, w, h)
 	{
 		var graph = editorUi.editor.graph;
-		var propertyName = 'tags';
 
 		var div = document.createElement('div');
 		div.style.overflow = 'hidden';
@@ -85,75 +84,6 @@ Draw.loadPlugin(function(editorUi)
 		var graph = editorUi.editor.graph;
 		var lastValue = null;
 		
-		function getTagsForCell(cell)
-		{
-			return graph.getAttributeForCell(cell, propertyName, '');
-		};
-
-		function getAllTagsForCells(cells)
-		{
-			var tokens = [];
-			var temp = {};
-			
-			for (var i = 0; i < cells.length; i++)
-			{
-				var tags = getTagsForCell(cells[i]);
-
-				if (tags.length > 0)
-				{
-					var t = tags.toLowerCase().split(' ');
-					
-					for (var j = 0; j < t.length; j++)
-					{
-						if (temp[t[j]] == null)
-						{
-							temp[t[j]] = true;
-							tokens.push(t[j]);
-						}
-					}
-				}
-			}
-			
-			tokens.sort();
-			
-			return tokens;
-		};
-		
-		function getCommonTagsForCells(cells)
-		{
-			var commonTokens = null;
-			var validTags = [];
-			
-			for (var i = 0; i < cells.length; i++)
-			{
-				var tags = getTagsForCell(cells[i]);
-				validTags = [];
-
-				if (tags.length > 0)
-				{
-					var tokens = tags.toLowerCase().split(' ');
-					var temp = {};
-					
-					for (var j = 0; j < tokens.length; j++)
-					{
-						if (commonTokens == null || commonTokens[tokens[j]] != null)
-						{
-							temp[tokens[j]] = true;
-							validTags.push(tokens[j]);
-						}
-					}
-					
-					commonTokens = temp;
-				}
-				else
-				{
-					return [];
-				}
-			}
-		
-			return validTags;
-		};
-		
 		function getLookup(tagList)
 		{
 			var lookup = {};
@@ -168,7 +98,7 @@ Draw.loadPlugin(function(editorUi)
 		
 		function getAllTags()
 		{
-			return getAllTagsForCells(graph.model.getDescendants(
+			return graph.getTagsForCells(graph.model.getDescendants(
 				graph.model.getRoot()));
 		};
 
@@ -212,12 +142,12 @@ Draw.loadPlugin(function(editorUi)
 		{
 			return graphIsCellVisible.apply(this, arguments) &&
 				(hiddenTagCount == 0 ||
-				!matchTags(getTagsForCell(cell), hiddenTags, hiddenTagCount));
+				!matchTags(graph.getTagsForCell(cell), hiddenTags, hiddenTagCount));
 		};
 		
 		function setCellsVisibleForTag(tag, visible)
 		{
-			var cells = graph.getCellsForTags([tag], null, propertyName, true);
+			var cells = graph.getCellsForTags([tag], null, true);
 			
 			// Ignores layers for selection
 			var temp = [];
@@ -268,7 +198,7 @@ Draw.loadPlugin(function(editorUi)
 					}
 					else
 					{
-						span.style.background = (uiTheme == 'dark') ? 'transparent' : '#ffffff';
+						span.style.background = (Editor.isDarkMode()) ? 'transparent' : '#ffffff';
 					}
 					
 					mxEvent.addListener(span, 'click', (function(tag)
@@ -279,7 +209,7 @@ Draw.loadPlugin(function(editorUi)
 							{
 								if (!graph.isSelectionEmpty())
 								{
-									addTagsToCells(graph.getSelectionCells(), [tag])
+									graph.addTagsForCells(graph.getSelectionCells(), [tag])
 								}
 								else
 								{
@@ -297,7 +227,7 @@ Draw.loadPlugin(function(editorUi)
 							{
 								if (!graph.isSelectionEmpty())
 								{
-									removeTagsFromCells(graph.getSelectionCells(), [tag])
+									graph.removeTagsForCells(graph.getSelectionCells(), [tag])
 								}
 								else
 								{
@@ -341,94 +271,14 @@ Draw.loadPlugin(function(editorUi)
 			}
 			else
 			{
-				updateSelectedTags(getAllTags(), getLookup(getCommonTagsForCells(graph.getSelectionCells())), '#2873e1');
+				updateSelectedTags(getAllTags(), getLookup(graph.getCommonTagsForCells(graph.getSelectionCells())), '#2873e1');
 				searchInput.style.display = '';
 				filterInput.style.display = 'none';
 			}
 		}
 		
 		refreshUi();
-		
-		function addTagsToCells(cells, tagList)
-		{
-			if (cells.length > 0 && tagList.length > 0)
-			{
-				graph.model.beginUpdate();
-				
-				try
-				{
-					for (var i = 0; i < cells.length; i++)
-					{
-						var temp = getTagsForCell(cells[i]);
-						var tags = temp.toLowerCase().split(' ');
-						
-						for (var j = 0; j < tagList.length; j++)
-						{
-							var tag = tagList[j];
-							var changed = false;
-		
-							if (tags.length == 0 || mxUtils.indexOf(tags, tag) < 0)
-							{
-								temp = (temp.length > 0) ? temp + ' ' + tag : tag;
-								changed = true;
-							}
-						}
-						
-						if (changed)
-						{
-							graph.setAttributeForCell(cells[i], 'tags', temp);
-						}
-					}
-				}
-				finally
-				{
-					graph.model.endUpdate();
-				}
-			}
-		};
-
-		function removeTagsFromCells(cells, tagList)
-		{
-			if (cells.length > 0 && tagList.length > 0)
-			{
-				graph.model.beginUpdate();
-				
-				try
-				{
-					for (var i = 0; i < cells.length; i++)
-					{
-						var tags = getTagsForCell(cells[i]);
-						
-						if (tags.length > 0)
-						{
-							var tokens = tags.split(' ');
-							var changed = false;
-							
-							for (var j = 0; j < tagList.length; j++)
-							{
-								var idx = mxUtils.indexOf(tokens, tagList[j]);
-								
-								if (idx >= 0)
-								{
-									tokens.splice(idx, 1);
-									changed = true;
-								}
-							}
 
-							if (changed)
-							{
-								graph.setAttributeForCell(cells[i], 'tags', tokens.join(' '));
-							}
-						}
-					}
-				}
-				finally
-				{
-					graph.model.endUpdate();
-				}
-			}
-		};
-		
 		graph.selectionModel.addListener(mxEvent.EVENT_CHANGE, function(sender, evt)
 		{
 			refreshUi();
@@ -449,7 +299,7 @@ Draw.loadPlugin(function(editorUi)
 			// Ctrl or Cmd keys
 			if (evt.keyCode == 13)
 			{
-				addTagsToCells(graph.getSelectionCells(), searchInput.value.toLowerCase().split(' '));
+				graph.addTagsForCells(graph.getSelectionCells(), searchInput.value.toLowerCase().split(' '));
 				searchInput.value = '';
 			}
 		});

+ 1 - 0
src/main/webapp/resources/dia.txt

@@ -617,6 +617,7 @@ removeFormat=Clear Formatting
 removeFromGroup=Remove from Group
 removeIt=Remove {1}
 removeWaypoint=Remove Waypoint
+removeUnusedTags=Remove unused tags
 rename=Rename
 renamed=Renamed
 renameIt=Rename {1}

+ 1 - 0
src/main/webapp/resources/dia_am.txt

@@ -617,6 +617,7 @@ removeFormat=Clear Formatting
 removeFromGroup=Remove from Group
 removeIt=Remove {1}
 removeWaypoint=Remove Waypoint
+removeUnusedTags=Remove unused tags
 rename=Rename
 renamed=Renamed
 renameIt=Rename {1}

+ 1 - 0
src/main/webapp/resources/dia_ar.txt

@@ -617,6 +617,7 @@ removeFormat=‫إزالة التنسيق‬
 removeFromGroup=‫إزالة من مجموعة‬
 removeIt=‫إزالة {1}‬
 removeWaypoint=‫إزالة نقطة المسار‬
+removeUnusedTags=Remove unused tags
 rename=‫إعادة تسمية‬
 renamed=‫تمت إعادة التسمية‬
 renameIt=‫إعادة تسمية {1}‬

+ 1 - 0
src/main/webapp/resources/dia_bg.txt

@@ -617,6 +617,7 @@ removeFormat=Изчистване на форматирането
 removeFromGroup=Премахване от групата
 removeIt=Премахване на {1}
 removeWaypoint=Премахване на ориентир
+removeUnusedTags=Remove unused tags
 rename=Преименуване
 renamed=Преименувано
 renameIt=Преименувай {1}

+ 1 - 0
src/main/webapp/resources/dia_bn.txt

@@ -617,6 +617,7 @@ removeFormat=Clear Formatting
 removeFromGroup=Remove from Group
 removeIt=Remove {1}
 removeWaypoint=Remove Waypoint
+removeUnusedTags=Remove unused tags
 rename=Rename
 renamed=Renamed
 renameIt=Rename {1}

+ 1 - 0
src/main/webapp/resources/dia_bs.txt

@@ -617,6 +617,7 @@ removeFormat=Očisti formatiranje
 removeFromGroup=Ukloni iz grupe
 removeIt=Ukoni {1}
 removeWaypoint=Ukloni međutačku
+removeUnusedTags=Remove unused tags
 rename=Preimenuj
 renamed=Preimenovano
 renameIt=Preimenuj {1}

+ 1 - 0
src/main/webapp/resources/dia_ca.txt

@@ -617,6 +617,7 @@ removeFormat=Esborra el format
 removeFromGroup=Suprimeix del grup
 removeIt=Suprimeix {1}
 removeWaypoint=Suprimeix la coordenada
+removeUnusedTags=Remove unused tags
 rename=Canvia el nom
 renamed=Nom canviat
 renameIt=Canvia el nom a {1}

+ 1 - 0
src/main/webapp/resources/dia_cs.txt

@@ -617,6 +617,7 @@ removeFormat=Vymazat formátování
 removeFromGroup=Odstranit ze skupiny
 removeIt=Odstranit {1}
 removeWaypoint=Odebrat průchozí bod
+removeUnusedTags=Remove unused tags
 rename=Přejmenovat
 renamed=Přejmenováno
 renameIt=Přejmenovat {1}

+ 1 - 0
src/main/webapp/resources/dia_da.txt

@@ -617,6 +617,7 @@ removeFormat=Ryd formatering
 removeFromGroup=Fjern fra gruppe
 removeIt=Fjern {1}
 removeWaypoint=Fjern støttepunkt
+removeUnusedTags=Remove unused tags
 rename=Omdøb
 renamed=Omdøbt
 renameIt=Omdøb {1}

+ 1 - 0
src/main/webapp/resources/dia_de.txt

@@ -617,6 +617,7 @@ removeFormat=Formatierung entfernen
 removeFromGroup=Aus Gruppe entfernen
 removeIt={1} entfernen
 removeWaypoint=Wegpunkt entfernen
+removeUnusedTags=Ungenutzte Tags entfernen
 rename=Umbenennen
 renamed=Umbenannt
 renameIt={1} umbenennen

+ 1 - 0
src/main/webapp/resources/dia_el.txt

@@ -617,6 +617,7 @@ removeFormat=Καθαρισμός μορφοποίησης
 removeFromGroup=Αφαίρεση από ομάδα
 removeIt=Αφαίρεση {1}
 removeWaypoint=Αφαίρεση σημείου αναφοράς
+removeUnusedTags=Remove unused tags
 rename=Μετονομασία
 renamed=Μετονομάσθηκε
 renameIt=Μετονομασία {1}

+ 1 - 0
src/main/webapp/resources/dia_eo.txt

@@ -617,6 +617,7 @@ removeFormat=Clear Formatting
 removeFromGroup=Remove from Group
 removeIt=Remove {1}
 removeWaypoint=Remove Waypoint
+removeUnusedTags=Remove unused tags
 rename=Rename
 renamed=Renamed
 renameIt=Rename {1}

+ 1 - 0
src/main/webapp/resources/dia_es.txt

@@ -617,6 +617,7 @@ removeFormat=Borrar formato
 removeFromGroup=Eliminar del grupo
 removeIt=Eliminar {1}
 removeWaypoint=Eliminar punto de referencia
+removeUnusedTags=Remove unused tags
 rename=Renombrar
 renamed=Renombrado
 renameIt=Renombrar {1}

+ 1 - 0
src/main/webapp/resources/dia_et.txt

@@ -617,6 +617,7 @@ removeFormat=Tühjenda formaat
 removeFromGroup=Eemalda rühmast
 removeIt=Eemalda {1}
 removeWaypoint=Eemalda kontrollpunkt
+removeUnusedTags=Remove unused tags
 rename=Muuda nime
 renamed=Nimi muudetud
 renameIt=Muuda nime {1}

+ 1 - 0
src/main/webapp/resources/dia_eu.txt

@@ -617,6 +617,7 @@ removeFormat=Garbitu formatua
 removeFromGroup=Taldetik kendu
 removeIt={1} kendu
 removeWaypoint=Kendu koordenatua
+removeUnusedTags=Remove unused tags
 rename=Aldatu izena
 renamed=Izena aldatuta
 renameIt=Izena aldatu {1}-ri

+ 1 - 0
src/main/webapp/resources/dia_fa.txt

@@ -617,6 +617,7 @@ removeFormat=‫قالب بندی را پاک کن‬
 removeFromGroup=‫حذف از گروه‬
 removeIt=‫حذف {1}‬
 removeWaypoint=‫نقطه مسیر را پاک کن‬
+removeUnusedTags=Remove unused tags
 rename=‫تغییر نام‬
 renamed=‫نام تغییر یافت‬
 renameIt=‫تغییر نام {1}‬

+ 1 - 0
src/main/webapp/resources/dia_fi.txt

@@ -617,6 +617,7 @@ removeFormat=Poista muotoilu
 removeFromGroup=Poista ryhmityksestä
 removeIt=Poista {1}
 removeWaypoint=Poista reittipiste
+removeUnusedTags=Remove unused tags
 rename=Nimeä uudelleen
 renamed=Nimetty uudelleen
 renameIt=Nimeä uudelleen {1}

+ 1 - 0
src/main/webapp/resources/dia_fil.txt

@@ -617,6 +617,7 @@ removeFormat=Alisin ang pagkaka-ayos
 removeFromGroup=Tanggalin mula sa grupo
 removeIt=Tanggalin {1}
 removeWaypoint=Tanggalin ang Waypoint
+removeUnusedTags=Remove unused tags
 rename=Palitan ang Pangalan
 renamed=Napalitan ang Pangalan
 renameIt=Palitan ang Pangalan {1}

+ 1 - 0
src/main/webapp/resources/dia_fr.txt

@@ -617,6 +617,7 @@ removeFormat=Effacer la mise en forme
 removeFromGroup=Retirer du groupe
 removeIt=Retirer {1}
 removeWaypoint=Effacer le repère
+removeUnusedTags=Remove unused tags
 rename=Renommer
 renamed=Renommé
 renameIt=Renommer {1}

+ 1 - 0
src/main/webapp/resources/dia_gl.txt

@@ -617,6 +617,7 @@ removeFormat=Limpar Formatación
 removeFromGroup=Eliminar do Grupo
 removeIt=Eliminar {1}
 removeWaypoint=Eliminar Etapa
+removeUnusedTags=Remove unused tags
 rename=Renomear
 renamed=Renomeado
 renameIt=Renomear {1}

+ 1 - 0
src/main/webapp/resources/dia_gu.txt

@@ -617,6 +617,7 @@ removeFormat=Clear Formatting
 removeFromGroup=Remove from Group
 removeIt=Remove {1}
 removeWaypoint=Remove Waypoint
+removeUnusedTags=Remove unused tags
 rename=Rename
 renamed=Renamed
 renameIt=Rename {1}

+ 1 - 0
src/main/webapp/resources/dia_he.txt

@@ -617,6 +617,7 @@ removeFormat=‫נקה עיצוב ‬
 removeFromGroup=‫הסר מקבוצה‬
 removeIt=‫הסר {1}‬
 removeWaypoint=‫הסר נקודת ציון‬
+removeUnusedTags=Remove unused tags
 rename=‫שנה שם‬
 renamed=‫השם שונה‬
 renameIt=‫שנה שם {1}‬

+ 1 - 0
src/main/webapp/resources/dia_hi.txt

@@ -617,6 +617,7 @@ removeFormat=Clear Formatting
 removeFromGroup=Remove from Group
 removeIt=Remove {1}
 removeWaypoint=Remove Waypoint
+removeUnusedTags=Remove unused tags
 rename=Rename
 renamed=Renamed
 renameIt=Rename {1}

+ 1 - 0
src/main/webapp/resources/dia_hr.txt

@@ -617,6 +617,7 @@ removeFormat=Clear Formatting
 removeFromGroup=Remove from Group
 removeIt=Remove {1}
 removeWaypoint=Remove Waypoint
+removeUnusedTags=Remove unused tags
 rename=Rename
 renamed=Renamed
 renameIt=Rename {1}

+ 1 - 0
src/main/webapp/resources/dia_hu.txt

@@ -617,6 +617,7 @@ removeFormat=Formázás törlése
 removeFromGroup=Eltávolítás a csoportból
 removeIt={1}-t eltávolít
 removeWaypoint=Útpontot eltávolít
+removeUnusedTags=Remove unused tags
 rename=Átnevez
 renamed=Átnevezve
 renameIt={1}-t átnevez

+ 1 - 0
src/main/webapp/resources/dia_i18n.txt

@@ -617,6 +617,7 @@ removeFormat=removeFormat
 removeFromGroup=removeFromGroup
 removeIt=removeIt
 removeWaypoint=removeWaypoint
+removeUnusedTags=removeUnusedTags
 rename=rename
 renamed=renamed
 renameIt=renameIt

+ 1 - 0
src/main/webapp/resources/dia_id.txt

@@ -617,6 +617,7 @@ removeFormat=Hapus Format
 removeFromGroup=Hapus dari Grup
 removeIt=Hapus {1}
 removeWaypoint=Hapus Waypoint
+removeUnusedTags=Remove unused tags
 rename=Namai Ulang
 renamed=Dinamai Ulang
 renameIt=Namai Ulang {1}

+ 1 - 0
src/main/webapp/resources/dia_it.txt

@@ -617,6 +617,7 @@ removeFormat=Cancella la formattazione
 removeFromGroup=Rimuovi dal gruppo
 removeIt=Rimuovi {1}
 removeWaypoint=Rimuovi punto di passaggio
+removeUnusedTags=Remove unused tags
 rename=Rinomina
 renamed=Rinominato
 renameIt=Rinomina {1}

+ 1 - 0
src/main/webapp/resources/dia_ja.txt

@@ -617,6 +617,7 @@ removeFormat=書式をクリア
 removeFromGroup=グループから削除
 removeIt={1}  を削除。
 removeWaypoint=途中点を削除
+removeUnusedTags=Remove unused tags
 rename=名前を変更
 renamed=名前が変更されました
 renameIt={1}  の名前を変更する。

+ 1 - 0
src/main/webapp/resources/dia_kn.txt

@@ -617,6 +617,7 @@ removeFormat=Clear Formatting
 removeFromGroup=Remove from Group
 removeIt=Remove {1}
 removeWaypoint=Remove Waypoint
+removeUnusedTags=Remove unused tags
 rename=Rename
 renamed=Renamed
 renameIt=Rename {1}

+ 1 - 0
src/main/webapp/resources/dia_ko.txt

@@ -617,6 +617,7 @@ removeFormat=서식 제거
 removeFromGroup=그룹에서 제거
 removeIt={1} 제거
 removeWaypoint=중간점 제거
+removeUnusedTags=Remove unused tags
 rename=이름 바꾸기
 renamed=이름 변경됨
 renameIt={1} 이름 바꾸기

+ 1 - 0
src/main/webapp/resources/dia_lt.txt

@@ -617,6 +617,7 @@ removeFormat=Clear Formatting
 removeFromGroup=Remove from Group
 removeIt=Remove {1}
 removeWaypoint=Remove Waypoint
+removeUnusedTags=Remove unused tags
 rename=Rename
 renamed=Renamed
 renameIt=Rename {1}

+ 1 - 0
src/main/webapp/resources/dia_lv.txt

@@ -617,6 +617,7 @@ removeFormat=Clear Formatting
 removeFromGroup=Remove from Group
 removeIt=Remove {1}
 removeWaypoint=Remove Waypoint
+removeUnusedTags=Remove unused tags
 rename=Rename
 renamed=Renamed
 renameIt=Rename {1}

+ 1 - 0
src/main/webapp/resources/dia_ml.txt

@@ -617,6 +617,7 @@ removeFormat=Clear Formatting
 removeFromGroup=Remove from Group
 removeIt=Remove {1}
 removeWaypoint=Remove Waypoint
+removeUnusedTags=Remove unused tags
 rename=Rename
 renamed=Renamed
 renameIt=Rename {1}

+ 1 - 0
src/main/webapp/resources/dia_mr.txt

@@ -617,6 +617,7 @@ removeFormat=Clear Formatting
 removeFromGroup=Remove from Group
 removeIt=Remove {1}
 removeWaypoint=Remove Waypoint
+removeUnusedTags=Remove unused tags
 rename=Rename
 renamed=Renamed
 renameIt=Rename {1}

+ 1 - 0
src/main/webapp/resources/dia_ms.txt

@@ -617,6 +617,7 @@ removeFormat=Kosongkan Format
 removeFromGroup=Buang daripada Kumpulan
 removeIt=Buang {1}
 removeWaypoint=Buang Titik Arah
+removeUnusedTags=Remove unused tags
 rename=Namakan semula
 renamed=Telah dinamakan semula
 renameIt=Namakan semula {1}

+ 1 - 0
src/main/webapp/resources/dia_my.txt

@@ -617,6 +617,7 @@ removeFormat=Clear Formatting
 removeFromGroup=Remove from Group
 removeIt=Remove {1}
 removeWaypoint=Remove Waypoint
+removeUnusedTags=Remove unused tags
 rename=Rename
 renamed=Renamed
 renameIt=Rename {1}

+ 1 - 0
src/main/webapp/resources/dia_nl.txt

@@ -617,6 +617,7 @@ removeFormat=Opmaak wissen
 removeFromGroup=Uit groep verwijderen
 removeIt={1} verwijderen
 removeWaypoint=Tussenpunt verwijderen
+removeUnusedTags=Remove unused tags
 rename=Hernoemen
 renamed=Hernoemd
 renameIt={1} hernoemen

+ 1 - 0
src/main/webapp/resources/dia_no.txt

@@ -617,6 +617,7 @@ removeFormat=Fjern formatering
 removeFromGroup=Fjern fra gruppe
 removeIt=Fjern {1}
 removeWaypoint=Fjern støttepunkt
+removeUnusedTags=Remove unused tags
 rename=Endre navn
 renamed=Endret navn
 renameIt=Endre navn {1}

+ 1 - 0
src/main/webapp/resources/dia_pl.txt

@@ -617,6 +617,7 @@ removeFormat=Wyczyść formatowanie
 removeFromGroup=Usuń z grupy
 removeIt=Usuń {1}
 removeWaypoint=Usuń punkt trasy
+removeUnusedTags=Remove unused tags
 rename=Zmień nazwę 
 renamed=Nazwa zmieniona 
 renameIt=Zmień nazwę {1}

+ 1 - 0
src/main/webapp/resources/dia_pt-br.txt

@@ -617,6 +617,7 @@ removeFormat=Limpar formatação
 removeFromGroup=Remover do Grupo 
 removeIt=Remover {1}
 removeWaypoint=Remover ponto de notificação
+removeUnusedTags=Remove unused tags
 rename=Renomear
 renamed=Renomeado
 renameIt=Renomear {1}

+ 1 - 0
src/main/webapp/resources/dia_pt.txt

@@ -617,6 +617,7 @@ removeFormat=Limpar formatação
 removeFromGroup=Remover do grupo 
 removeIt=Remover {1}
 removeWaypoint=Remover ponto de notificação
+removeUnusedTags=Remove unused tags
 rename=Renomear
 renamed=Renomeado
 renameIt=Renomear {1}

+ 1 - 0
src/main/webapp/resources/dia_ro.txt

@@ -617,6 +617,7 @@ removeFormat=Anulează formatarea
 removeFromGroup=Șterge din grup
 removeIt=Șterge {1}
 removeWaypoint=Șterge reper
+removeUnusedTags=Remove unused tags
 rename=Redenumeşte
 renamed=Redenumit
 renameIt=Redenumeşte {1}

+ 1 - 0
src/main/webapp/resources/dia_ru.txt

@@ -617,6 +617,7 @@ removeFormat=Очистить форматирование
 removeFromGroup=Удалить из группы
 removeIt=Удалить {1}
 removeWaypoint=Удалить опорную точку
+removeUnusedTags=Remove unused tags
 rename=Переименовать
 renamed=Переименовано
 renameIt=Переименовать {1}

+ 1 - 0
src/main/webapp/resources/dia_si.txt

@@ -617,6 +617,7 @@ removeFormat=Clear Formatting
 removeFromGroup=Remove from Group
 removeIt=Remove {1}
 removeWaypoint=Remove Waypoint
+removeUnusedTags=Remove unused tags
 rename=Rename
 renamed=Renamed
 renameIt=Rename {1}

+ 1 - 0
src/main/webapp/resources/dia_sk.txt

@@ -617,6 +617,7 @@ removeFormat=Clear Formatting
 removeFromGroup=Remove from Group
 removeIt=Remove {1}
 removeWaypoint=Remove Waypoint
+removeUnusedTags=Remove unused tags
 rename=Rename
 renamed=Renamed
 renameIt=Rename {1}

+ 1 - 0
src/main/webapp/resources/dia_sl.txt

@@ -617,6 +617,7 @@ removeFormat=Clear Formatting
 removeFromGroup=Remove from Group
 removeIt=Remove {1}
 removeWaypoint=Remove Waypoint
+removeUnusedTags=Remove unused tags
 rename=Rename
 renamed=Renamed
 renameIt=Rename {1}

+ 1 - 0
src/main/webapp/resources/dia_sr.txt

@@ -617,6 +617,7 @@ removeFormat=Obriši formatiranje
 removeFromGroup=Ukloni iz grupe
 removeIt=Ukloni {1}
 removeWaypoint=Ukloni waypoint
+removeUnusedTags=Remove unused tags
 rename=Preimenuj
 renamed=Preimenovano
 renameIt=Preimenuj {1}

+ 1 - 0
src/main/webapp/resources/dia_sv.txt

@@ -617,6 +617,7 @@ removeFormat=Rensa formatering
 removeFromGroup=Ta bort från grupp
 removeIt=Ta bort {1}
 removeWaypoint=Ta bort brytpunkt
+removeUnusedTags=Remove unused tags
 rename=Byt namn
 renamed=Namnändrad
 renameIt=Byt namn {1}

+ 1 - 0
src/main/webapp/resources/dia_sw.txt

@@ -617,6 +617,7 @@ removeFormat=Clear Formatting
 removeFromGroup=Remove from Group
 removeIt=Remove {1}
 removeWaypoint=Remove Waypoint
+removeUnusedTags=Remove unused tags
 rename=Rename
 renamed=Renamed
 renameIt=Rename {1}

+ 1 - 0
src/main/webapp/resources/dia_ta.txt

@@ -617,6 +617,7 @@ removeFormat=Clear Formatting
 removeFromGroup=Remove from Group
 removeIt=Remove {1}
 removeWaypoint=Remove Waypoint
+removeUnusedTags=Remove unused tags
 rename=Rename
 renamed=Renamed
 renameIt=Rename {1}

+ 1 - 0
src/main/webapp/resources/dia_te.txt

@@ -617,6 +617,7 @@ removeFormat=Clear Formatting
 removeFromGroup=Remove from Group
 removeIt=Remove {1}
 removeWaypoint=Remove Waypoint
+removeUnusedTags=Remove unused tags
 rename=Rename
 renamed=Renamed
 renameIt=Rename {1}

+ 1 - 0
src/main/webapp/resources/dia_th.txt

@@ -617,6 +617,7 @@ removeFormat=ล้างรูปแบบ
 removeFromGroup=ลบออกจากกลุ่ม
 removeIt=ลบ{1}
 removeWaypoint=ลบการกำหนดเส้นทาง
+removeUnusedTags=Remove unused tags
 rename=เปลี่ยนชื่อใหม่
 renamed=ได้เปลี่ยนชื่อแล้ว
 renameIt=เปลี่ยนชื่อ{1}

+ 1 - 0
src/main/webapp/resources/dia_tr.txt

@@ -617,6 +617,7 @@ removeFormat=Biçimi temizle
 removeFromGroup=Gruptan çıkart
 removeIt={1} Sil
 removeWaypoint=Ara noktayı sil
+removeUnusedTags=Remove unused tags
 rename=Yeniden isimlendir
 renamed=Yeniden isimlendirildi
 renameIt={1} Yeniden isimlendir

+ 1 - 0
src/main/webapp/resources/dia_uk.txt

@@ -617,6 +617,7 @@ removeFormat=Очистити форматування
 removeFromGroup=Прибрати з гурту
 removeIt=Прибрати {1}
 removeWaypoint=Знищити точку шляху
+removeUnusedTags=Remove unused tags
 rename=Змінити назву
 renamed=Перейменований
 renameIt=Змінити назву {1}

+ 1 - 0
src/main/webapp/resources/dia_vi.txt

@@ -617,6 +617,7 @@ removeFormat=Xóa định dạng
 removeFromGroup=Loại bỏ khỏi nhóm
 removeIt=Loại bỏ {1}
 removeWaypoint=Loại bỏ điểm tham chiếu
+removeUnusedTags=Remove unused tags
 rename=Đổi tên
 renamed=Đã đổi tên
 renameIt=Đổi tên {1}

+ 1 - 0
src/main/webapp/resources/dia_zh-tw.txt

@@ -617,6 +617,7 @@ removeFormat=清除格式
 removeFromGroup=移出組
 removeIt=刪除{1}
 removeWaypoint=刪除航點
+removeUnusedTags=Remove unused tags
 rename=重新命名
 renamed=已重新命名
 renameIt=重新命名 {1}

+ 1 - 0
src/main/webapp/resources/dia_zh.txt

@@ -617,6 +617,7 @@ removeFormat=清除格式
 removeFromGroup=移出组合
 removeIt=删除 {1}
 removeWaypoint=删除航点
+removeUnusedTags=Remove unused tags
 rename=重命名
 renamed=已重命名
 renameIt=重命名 {1}

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
src/main/webapp/service-worker.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
src/main/webapp/service-worker.js.map