commit ba4eea92a00a4204d8da1c1c0dae4d324b779e66
Author: Pavel Fidranský <fidransky@outlook.com>
Date:   Sat Oct 20 21:15:18 2018 +0200

    reusing Vertex archetype icons in order to decrease number of DOM nodes

diff --git a/sources/src/main/webapp/js/components/group.js b/sources/src/main/webapp/js/components/group.js
index 2f1daf2..ffce79c 100644
--- a/sources/src/main/webapp/js/components/group.js
+++ b/sources/src/main/webapp/js/components/group.js
@@ -609,12 +609,12 @@ function Group(props) {
 			relatedArchetype.appendChild(relatedArchetypeCounter);
 
 			// icon
-			var relatedArchetypeIcon = app.dom.createSvgElement('g', {
+			var relatedArchetypeIcon = app.dom.createSvgElement('use', {
+				'href': '#vertexArchetypeIcon-' + app.archetype.vertex[archetypeIndex].name,
 				'class': 'archetype-icon',
 				'transform': `translate(15, -10)`,
 			});
 			relatedArchetypeIcon.addEventListener('click', relatedArchetypeClick.bind(this, parseInt(archetypeIndex))); // TODO when icon == null can not click on item
-			relatedArchetypeIcon.innerHTML = app.archetype.vertex[archetypeIndex].icon;
 			relatedArchetype.appendChild(relatedArchetypeIcon);
 
 			// line
diff --git a/sources/src/main/webapp/js/components/vertex.js b/sources/src/main/webapp/js/components/vertex.js
index a48c34b..9e08a5f 100644
--- a/sources/src/main/webapp/js/components/vertex.js
+++ b/sources/src/main/webapp/js/components/vertex.js
@@ -521,14 +521,13 @@ function Vertex(props) {
 		}));
 
 		// archetype icon
-		var archetypeIcon = app.dom.createSvgElement('g', {
+		var archetypeIcon = app.dom.createSvgElement('use', {
+			'href': '#vertexArchetypeIcon-' + app.archetype.vertex[this.archetype].name,
 			'class': 'archetype-icon',
 			'transform': 'translate(8, 8)',
 		});
 		archetypeIcon.addEventListener('click', archetypeClick.bind(this)); // TODO when icon == null can not click on item
 
-		archetypeIcon.innerHTML = app.archetype.vertex[this.archetype].icon;
-
 		rootElement.appendChild(archetypeIcon);
 
 		// name
@@ -548,15 +547,14 @@ function Vertex(props) {
 
 		var archetypeIconOrder = 0;
 		for (var archetypeIndex in relatedArchetypeMap) {
-			var relatedArchetype = app.utils.createSvgElement('g', {
+			var relatedArchetypeIcon = app.utils.createSvgElement('use', {
+				'href': '#vertexArchetypeIcon-' + app.archetype.vertex[archetypeIndex].name,
 				'class': 'archetype-icon',
 				'transform': `translate(${archetypeIconOrder * relatedArchetypeIconWidth}, 8)`,
 			});
-			relatedArchetype.addEventListener('click', relatedArchetypeClick.bind(this, parseInt(archetypeIndex))); // TODO when icon == null can not click on item
-
-			relatedArchetype.innerHTML = app.archetype.vertex[archetypeIndex].icon;
+			relatedArchetypeIcon.addEventListener('click', relatedArchetypeClick.bind(this, parseInt(archetypeIndex))); // TODO when icon == null can not click on item
 
-			relatedArchetypeListContainer.appendChild(relatedArchetype);
+			relatedArchetypeListContainer.appendChild(relatedArchetypeIcon);
 
 			archetypeIconOrder++;
 		}
@@ -608,12 +606,12 @@ function Vertex(props) {
 			relatedArchetype.appendChild(relatedArchetypeCounter);
 
 			// icon
-			var relatedArchetypeIcon = app.dom.createSvgElement('g', {
+			var relatedArchetypeIcon = app.dom.createSvgElement('use', {
+				'href': '#vertexArchetypeIcon-' + app.archetype.vertex[archetypeIndex].name,
 				'class': 'archetype-icon',
 				'transform': `translate(15, -10)`,
 			});
 			relatedArchetypeIcon.addEventListener('click', relatedArchetypeClick.bind(this, parseInt(archetypeIndex))); // TODO when icon == null can not click on item
-			relatedArchetypeIcon.innerHTML = app.archetype.vertex[archetypeIndex].icon;
 			relatedArchetype.appendChild(relatedArchetypeIcon);
 
 			// line
diff --git a/sources/src/main/webapp/js/components/viewport.js b/sources/src/main/webapp/js/components/viewport.js
index 50722ee..83e3a9a 100644
--- a/sources/src/main/webapp/js/components/viewport.js
+++ b/sources/src/main/webapp/js/components/viewport.js
@@ -17,6 +17,7 @@ function Viewport() {
 	var edgesContainer;
 	var verticesContainer;
 	var groupsContainer;
+	var definitions;
 
 	var pan = false;
 
@@ -94,6 +95,14 @@ function Viewport() {
 		return groupList;
 	};
 
+	this.addSvgDefinition = function(id, svgString) {
+		var g = app.dom.createSvgElement('g', {
+			'id': id,
+		});
+		g.innerHTML = svgString;
+		definitions.appendChild(g);
+	};
+
 	this.getSize = function() {
 		return {
 			'width': rootElement.offsetWidth,
@@ -173,8 +182,8 @@ function Viewport() {
 		groupsContainer.setAttribute('data-id', 'groups');
 		graph.appendChild(groupsContainer);
 
-		var defs = app.utils.createSvgElement('defs', {});
-		mainSvg.appendChild(defs);
+		definitions = app.utils.createSvgElement('defs', {});
+		mainSvg.appendChild(definitions);
 
 		var linearGradient = app.utils.createSvgElement('linearGradient', {
 			'id': 'node--highlighted-required-provided',
@@ -187,7 +196,7 @@ function Viewport() {
 			'offset': '100%',
 			'stop-color': '#5896ff',
 		}));
-		defs.appendChild(linearGradient);
+		definitions.appendChild(linearGradient);
 
 		this.contextMenuComponent = new VertexContextMenuList;
 		rootElement.appendChild(this.contextMenuComponent.render());
diff --git a/sources/src/main/webapp/js/graphLoader.js b/sources/src/main/webapp/js/graphLoader.js
index 6cd93cb..2695483 100644
--- a/sources/src/main/webapp/js/graphLoader.js
+++ b/sources/src/main/webapp/js/graphLoader.js
@@ -22,6 +22,12 @@ function GraphLoader() {
 		app.attributeTypeList = data.attributeTypes;
 		app.possibleEnumValues = data.possibleEnumValues;
 
+		app.archetype.vertex.filter(function(vertexArchetype) {
+			return app.utils.isDefined(vertexArchetype.icon);
+		}).forEach(function(vertexArchetype) {
+			app.viewportComponent.addSvgDefinition('vertexArchetypeIcon-' + vertexArchetype.name, vertexArchetype.icon);
+		});
+
         var highlightedNodeId;
         var highlightedNodeType;
         if (app.utils.isDefined(data.highlightedVertex) && data.highlightedVertex.length > 0) {
