diff --git a/frontend-js/src/main/js/Admin.js b/frontend-js/src/main/js/Admin.js
index 376df411df584851aad80a2fa4e09f04b30b67c1..ad8a602d79cbe9eb8d7655984fdc4271bd92fffa 100644
--- a/frontend-js/src/main/js/Admin.js
+++ b/frontend-js/src/main/js/Admin.js
@@ -1,185 +1,173 @@
-"use strict";
-
-/* exported logger */
-
-var Promise = require("bluebird");
-
-var CustomMapOptions = require('./map/CustomMapOptions');
-var GuiUtils = require('./gui/leftPanel/GuiUtils');
-var ObjectWithListeners = require('./ObjectWithListeners');
-
-var ConfigurationAdminPanel = require('./gui/admin/ConfigurationAdminPanel');
-var GenomeAdminPanel = require('./gui/admin/GenomeAdminPanel');
-var MapsAdminPanel = require('./gui/admin/MapsAdminPanel');
-var UsersAdminPanel = require('./gui/admin/UsersAdminPanel');
-
-// noinspection JSUnusedLocalSymbols
-var logger = require('./logger');
-var Functions = require('./Functions');
-
-/**
- * Default constructor.
- *
- * @param {CustomMapOptions} options
- *           object representing all parameters needed for map creation
- */
-function Admin(options) {
-  var self = this;
-  self._panels = [];
-  self._tabIdCount = 0;
-  if (!(options instanceof CustomMapOptions)) {
-    options = new CustomMapOptions(options);
-  }
-  self.setElement(options.getElement());
-
-  self.setConfiguration(options.getConfiguration());
-  self.setServerConnector(options.getServerConnector());
-  self.setGuiUtils(new GuiUtils());
-  self._createGui();
-}
-
-Admin.prototype = Object.create(ObjectWithListeners.prototype);
-Admin.prototype.constructor = ObjectWithListeners;
-
-Admin.prototype._createGui = function () {
-  var self = this;
-  self.getElement().innerHTML = "";
-
-  var panels = [{
-    name: "PROJECTS",
-    panelClass: MapsAdminPanel
-  }, {
-    name: "USERS",
-    panelClass: UsersAdminPanel
-  }, {
-    name: "CONFIGURATION",
-    panelClass: ConfigurationAdminPanel
-  }, {
-    name: "GENOMES",
-    panelClass: GenomeAdminPanel
-  }];
-
-  var tabDiv = Functions.createElement({
-    type: "div",
-    name: "tabView",
-    className: "tabbable boxed parentTabs"
-  });
-  self.getElement().appendChild(tabDiv);
-
-  var tabMenuDiv = Functions.createElement({
-    type: "ul",
-    className: "nav nav-tabs"
-  });
-  tabDiv.appendChild(tabMenuDiv);
-
-  var tabContentDiv = Functions.createElement({
-    type: "div",
-    className: "tab-content"
-  });
-  tabDiv.appendChild(tabContentDiv);
-
-  for (var i = 0; i < panels.length; i++) {
-    self.addTab(panels[i], tabMenuDiv, tabContentDiv);
-  }
-  self.addLogoutButton(tabMenuDiv);
-};
-
-Admin.prototype.addLogoutButton = function (navElement) {
-  var self = this;
-  var logoutLink = self.getGuiUtils().createLogoutLink();
-
-  var navLi = document.createElement("li");
-  navLi.appendChild(logoutLink);
-  navLi.style.cssFloat = "right";
-
-  navElement.appendChild(navLi);
-};
-
-Admin.prototype.addTab = function (params, navElement, contentElement) {
-  var self = this;
-
-  var tabId = "admin_panel_tab_" + this._tabIdCount;
-  self._tabIdCount++;
-
-  var navLi = self.getGuiUtils().createTabMenuObject({
-    id: tabId,
-    name: params.name,
-    navigationBar: navElement
-  });
-  navElement.appendChild(navLi);
-
-  var contentDiv = self.getGuiUtils().createTabContentObject({
-    id: tabId,
-    navigationObject: navLi
-  });
-
-  contentElement.appendChild(contentDiv);
-
-  this._panels.push(new params.panelClass({
-    element: contentDiv,
-    name: params.name,
-    configuration: self.getConfiguration(),
-    serverConnector: self.getServerConnector()
-  }));
-};
-
-Admin.prototype.setElement = function (element) {
-  this._element = element;
-};
-Admin.prototype.getElement = function () {
-  return this._element;
-};
-
-Admin.prototype.init = function () {
-  var promises = [];
-  for (var i = 0; i < this._panels.length; i++) {
-    promises.push(this._panels[i].init());
-  }
-  return Promise.all(promises).then(function () {
-    $(window).trigger('resize');
-  });
-};
-
-Admin.prototype.setConfiguration = function (configuration) {
-  this._configuration = configuration;
-};
-
-Admin.prototype.getConfiguration = function () {
-  return this._configuration;
-};
-
-Admin.prototype.setGuiUtils = function (guiUtils) {
-  this._guiUtils = guiUtils;
-};
-
-Admin.prototype.getGuiUtils = function () {
-  return this._guiUtils;
-};
-
-Admin.prototype.destroy = function () {
-  var self = this;
-  var promises = [];
-  for (var i = 0; i < self._panels.length; i++) {
-    promises.push(self._panels[i].destroy());
-  }
-  return Promise.all(promises);
-};
-
-/**
- *
- * @param {ServerConnector} serverConnector
- */
-Admin.prototype.setServerConnector = function (serverConnector) {
-  this._serverConnector = serverConnector;
-};
-
-/**
- *
- * @returns {ServerConnector}
- */
-Admin.prototype.getServerConnector = function () {
-  return this._serverConnector;
-};
-
-
-module.exports = Admin;
+"use strict";
+
+/* exported logger */
+
+var Promise = require("bluebird");
+
+var CustomMapOptions = require('./map/CustomMapOptions');
+var AbstractGuiElement = require('./gui/AbstractGuiElement');
+
+var ConfigurationAdminPanel = require('./gui/admin/ConfigurationAdminPanel');
+var GenomeAdminPanel = require('./gui/admin/GenomeAdminPanel');
+var MapsAdminPanel = require('./gui/admin/MapsAdminPanel');
+var UsersAdminPanel = require('./gui/admin/UsersAdminPanel');
+
+// noinspection JSUnusedLocalSymbols
+var logger = require('./logger');
+var GuiUtils = require('./gui/leftPanel/GuiUtils');
+
+/**
+ * Default constructor.
+ *
+ * @param {CustomMapOptions} options
+ *           object representing all parameters needed for map creation
+ * @constructor
+ */
+function Admin(options) {
+  var self = this;
+  if (!(options instanceof CustomMapOptions)) {
+    options = new CustomMapOptions(options);
+  }
+
+  self.setElement(options.getElement());
+  self.setConfiguration(options.getConfiguration());
+  self.setServerConnector(options.getServerConnector());
+
+  self._createGui();
+}
+
+Admin.prototype = Object.create(AbstractGuiElement.prototype);
+Admin.prototype.constructor = AbstractGuiElement;
+
+/**
+ *
+ * @private
+ */
+Admin.prototype._createGui = function () {
+  var self = this;
+  self.getElement().innerHTML = "";
+  self.getGuiUtils().initTabContent(self);
+
+  var panels = [{
+    name: "PROJECTS",
+    panelClass: MapsAdminPanel
+  }, {
+    name: "USERS",
+    panelClass: UsersAdminPanel
+  }, {
+    name: "CONFIGURATION",
+    panelClass: ConfigurationAdminPanel
+  }, {
+    name: "GENOMES",
+    panelClass: GenomeAdminPanel
+  }];
+
+  for (var i = 0; i < panels.length; i++) {
+    self.getGuiUtils().addTab(self, panels[i]);
+  }
+  self.addLogoutButton($(this.getElement()).find("> .parentTabs > .nav-tabs")[0]);
+};
+
+/**
+ *
+ * @param navElement
+ */
+Admin.prototype.addLogoutButton = function (navElement) {
+  var self = this;
+  var logoutLink = self.getGuiUtils().createLogoutLink();
+
+  var navLi = document.createElement("li");
+  navLi.appendChild(logoutLink);
+  navLi.style.cssFloat = "right";
+
+  navElement.appendChild(navLi);
+};
+
+/**
+ *
+ * @param {HTMLElement} element
+ */
+Admin.prototype.setElement = function (element) {
+  this._element = element;
+};
+/**
+ *
+ * @returns {HTMLElement}
+ */
+Admin.prototype.getElement = function () {
+  return this._element;
+};
+
+/**
+ *
+ * @returns {Promise}
+ */
+Admin.prototype.init = function () {
+  var promises = [];
+  for (var i = 0; i < this._panels.length; i++) {
+    promises.push(this._panels[i].init());
+  }
+  return Promise.all(promises).then(function () {
+    $(window).trigger('resize');
+  });
+};
+
+/**
+ *
+ * @param {Configuration} configuration
+ */
+Admin.prototype.setConfiguration = function (configuration) {
+  this._configuration = configuration;
+};
+
+/**
+ *
+ * @returns {Configuration}
+ */
+Admin.prototype.getConfiguration = function () {
+  return this._configuration;
+};
+
+/**
+ *
+ * @returns {Promise}
+ */
+Admin.prototype.destroy = function () {
+  var self = this;
+  var promises = [];
+  for (var i = 0; i < self._panels.length; i++) {
+    promises.push(self._panels[i].destroy());
+  }
+  return Promise.all(promises);
+};
+
+/**
+ *
+ * @param {ServerConnector} serverConnector
+ */
+Admin.prototype.setServerConnector = function (serverConnector) {
+  this._serverConnector = serverConnector;
+};
+
+/**
+ *
+ * @returns {ServerConnector}
+ */
+Admin.prototype.getServerConnector = function () {
+  return this._serverConnector;
+};
+
+/**
+ *
+ * @returns {GuiUtils}
+ */
+Admin.prototype.getGuiUtils = function () {
+  var self = this;
+  if (self._guiUtils === undefined) {
+    self._guiUtils = new GuiUtils(self.getConfiguration());
+  }
+  return this._guiUtils;
+};
+
+
+module.exports = Admin;
diff --git a/frontend-js/src/main/js/gui/AbstractGuiElement.js b/frontend-js/src/main/js/gui/AbstractGuiElement.js
index b859caede9c7adb19bd2abff6323d3f55b38429f..6183c5953282cb47688ef0caac0f67ace4e61bae 100644
--- a/frontend-js/src/main/js/gui/AbstractGuiElement.js
+++ b/frontend-js/src/main/js/gui/AbstractGuiElement.js
@@ -7,6 +7,7 @@ var PanelControlElementType = require('./PanelControlElementType');
 
 // noinspection JSUnusedLocalSymbols
 var logger = require('../logger');
+var Functions = require('../Functions');
 
 /**
  *
@@ -221,5 +222,4 @@ AbstractGuiElement.prototype.askConfirmRemoval = function (params) {
   })
 };
 
-
 module.exports = AbstractGuiElement;
diff --git a/frontend-js/src/main/js/gui/Panel.js b/frontend-js/src/main/js/gui/Panel.js
index 75ebb3459b1ea5d8f6aa595dc1caf6b2f584d5bd..ae0f4900331f9769f5c8d93ec74ac02b5512d7af 100644
--- a/frontend-js/src/main/js/gui/Panel.js
+++ b/frontend-js/src/main/js/gui/Panel.js
@@ -16,7 +16,7 @@ var xss = require('xss');
  * @param {Configuration} [params.configuration]
  * @param {HTMLElement} params.element
  * @param {Project} params.project
- * @param {CustomMap} params.customMap
+ * @param {CustomMap} [params.customMap]
  * @param {string} params.panelName
  * @param {boolean} params.scrollable
  * @param {string} [params.helpTip]
diff --git a/frontend-js/src/main/js/gui/leftPanel/GuiUtils.js b/frontend-js/src/main/js/gui/leftPanel/GuiUtils.js
index 37c7cb0f4c0e25753841dfdb4462072ee0cd6b74..87cf701f2818916178676825f3f045fad5710767 100644
--- a/frontend-js/src/main/js/gui/leftPanel/GuiUtils.js
+++ b/frontend-js/src/main/js/gui/leftPanel/GuiUtils.js
@@ -1,950 +1,1015 @@
-"use strict";
-
-/* exported logger */
-
-var Alias = require('../../map/data/Alias');
-var ConfigurationType = require('../../ConfigurationType');
-var IdentifiedElement = require('../../map/data/IdentifiedElement');
-var SearchBioEntityGroup = require('../../map/data/SearchBioEntityGroup');
-
-
-var GuiConnector = require('../../GuiConnector');
-var AbstractGuiElement = require('../AbstractGuiElement');
-var Functions = require('../../Functions');
-
-var logger = require('../../logger');
-var xss = require('xss');
-
-var Promise = require('bluebird');
-
-var tabIdCounter = 0;
-
-/**
- *
- * @param {Configuration} configuration
- * @constructor
- */
-function GuiUtils(configuration) {
-  var self = this;
-  self.setConfiguration(configuration);
-}
-
-GuiUtils.prototype = Object.create(AbstractGuiElement.prototype);
-GuiUtils.prototype.constructor = GuiUtils;
-
-/**
- *
- * @param {Configuration} configuration
- */
-GuiUtils.prototype.setConfiguration = function (configuration) {
-  this._configuration = configuration;
-};
-
-/**
- *
- * @returns {Configuration}
- */
-GuiUtils.prototype.getConfiguration = function () {
-  return this._configuration;
-};
-
-/**
- *
- * @param {string} value
- * @returns {HTMLSpanElement}
- */
-GuiUtils.prototype.createLabel = function (value) {
-  var result = document.createElement("span");
-  result.innerHTML = value;
-  result.className = "minerva-label";
-  return result;
-};
-
-/**
- *
- * @param {Object} modification
- * @param {string} [modification.name]
- * @param {string} modification.type
- * @param {string} [modification.state]
- *
- * @returns {HTMLElement| null}
- */
-GuiUtils.prototype.createModificationRow = function (modification) {
-  var self = this;
-  var row = null;
-  var name = modification.name;
-  var desc = undefined;
-  if (modification.state !== undefined && modification.state !== null) {
-    var modificationStateType = self.getConfiguration().getModificationStateTypeByName(modification.state);
-    var state = modificationStateType.getCommonName();
-
-    if (name !== null && name !== undefined && name !== "") {
-      desc = state + " at position " + name + ", ";
-    } else {
-      desc = state + ",";
-    }
-  } else if (name !== null && name !== undefined && name !== "" &&
-    (modification.type === "BINDING_REGION" ||
-      modification.type === "CODING_REGION" ||
-      modification.type === "PROTEIN_BINDING_DOMAIN" ||
-      modification.type === "TRANSCRIPTION_SITE_LEFT" ||
-      modification.type === "TRANSCRIPTION_SITE_RIGHT" ||
-      modification.type === "REGULATORY_REGION"
-    )) {
-    desc = name + ",";
-  }
-
-  if (desc !== undefined) {
-    row = Functions.createElement({
-      type: "li"
-    });
-    row.appendChild(self.createLabelText(desc));
-  }
-  return row;
-};
-
-/**
- *
- * @param {string} label
- * @param {Object[]} value
- * @returns {HTMLDivElement}
- */
-GuiUtils.prototype.createPostTranslationalModifications = function (label, value) {
-  var result = document.createElement("div");
-  var count = 0;
-  if (value !== undefined && value.length > 0) {
-    var self = this;
-    var userFriendlyLabel = label + ": ";
-    if (label === "RESIDUE") {
-      userFriendlyLabel = "Posttranslational modifications: "
-    } else if (label === "BINDING_REGION") {
-      userFriendlyLabel = "Binding regions: "
-    } else if (label === "CODING_REGION") {
-      userFriendlyLabel = "Coding regions: "
-    } else if (label === "PROTEIN_BINDING_DOMAIN") {
-      userFriendlyLabel = "Protein binding domains: "
-    } else if (label === "TRANSCRIPTION_SITE_LEFT") {
-      userFriendlyLabel = "Transcription sites (left): "
-    } else if (label === "TRANSCRIPTION_SITE_RIGHT") {
-      userFriendlyLabel = "Transcription sites (right): "
-    } else if (label === "TRANSCRIPTION_SITE") {
-      userFriendlyLabel = "Transcription sites: "
-    } else if (label === "MODIFICATION_SITE") {
-      userFriendlyLabel = "Modification sites: "
-    }
-    result.appendChild(self.createLabel(userFriendlyLabel));
-    result.appendChild(self.createNewLine());
-    var list = Functions.createElement({
-      type: "ul"
-    });
-    for (var i = 0; i < value.length; i++) {
-      var modification = value[i];
-      var row = self.createModificationRow(modification, self);
-      if (row !== null) {
-        list.appendChild(row);
-        count++;
-      }
-    }
-    result.appendChild(list);
-  }
-  if (count > 0) {
-    return result;
-  } else {
-    return document.createElement("div");
-  }
-};
-
-/**
- *
- * @returns {HTMLHRElement}
- */
-GuiUtils.prototype.createSeparator = function () {
-  return document.createElement("hr");
-};
-
-/**
- *
- * @param {number} [count]
- * @returns {HTMLParagraphElement}
- */
-GuiUtils.prototype.createNewLine = function (count) {
-  if (count === undefined) {
-    count = 0;
-  }
-  var result = document.createElement("p");
-  if (count > 0) {
-    result.style.height = ((count - 1) * 10) + "px";
-  }
-  return result;
-};
-
-/**
- *
- * @param {string} [url]
- * @param {string} name
- * @returns {HTMLElement}
- */
-GuiUtils.prototype.createLink = function (url, name) {
-  if (url === null || url === undefined) {
-    logger.warn("URL not defined for: \"" + name + "\" link");
-    return Functions.createElement({type: "span", content: name});
-  }
-  var link = document.createElement("a");
-  link.href = url;
-  link.innerHTML = name;
-  link.target = "_blank";
-  link.style.textDecoration = "underline";
-  return link;
-};
-
-/**
- *
- * @param {Annotation} annotation
- * @param {boolean} [showType=false]
- * @returns {HTMLElement}
- */
-GuiUtils.prototype.createAnnotationLink = function (annotation, showType) {
-  var self = this;
-  var name, type, hint;
-  var article = annotation.getArticle();
-  if (article !== undefined) {
-
-    hint = article.getTitle() + " " + article.getAuthors().join(", ") + ", " + article.getYear() + ", "
-      + article.getJournal();
-    type = "PUBMED";
-    name = article.getId();
-  } else {
-    //replace encoded parts of uri (like %2F - > "/")
-    name = decodeURIComponent(annotation.getResource());
-    var miriamType = self.getConfiguration().getMiriamTypeByName(annotation.getType());
-    if (miriamType === null) {
-      logger.warn("Unknown miriam type: " + annotation.getType());
-      type = annotation.getType();
-    } else {
-      type = miriamType.getCommonName();
-    }
-  }
-  var link;
-  if (showType) {
-    link = self.createLink(annotation.getLink(), type + " (" + name + ")");
-  } else {
-    link = self.createLink(annotation.getLink(), name);
-  }
-  if (hint !== undefined) {
-    var div = document.createElement("div");
-    div.title = hint;
-    div.appendChild(link);
-    return div;
-  } else {
-    return link;
-  }
-};
-
-/**
- *
- * @param {string} label
- * @param {Annotation[]} [value]
- * @param {Object} [options]
- * @param {boolean} [options.inline]
- *
- * @returns {HTMLDivElement}
- */
-GuiUtils.prototype.createAnnotations = function (label, value, options) {
-  var self = this;
-
-  var inline = false;
-  if (options !== undefined) {
-    if (options.inline !== undefined) {
-      inline = options.inline;
-    }
-  }
-  var result = document.createElement("div");
-  result.appendChild(self.createLabel(label));
-  if (value !== undefined && value.length > 0) {
-    if (!inline) {
-      result.appendChild(self.createNewLine());
-    }
-    result.appendChild(self.createAnnotationList(value, options));
-  } else {
-    result.appendChild(self.createLabelText("No annotations"));
-  }
-  return result;
-};
-
-/**
- *
- * @param {boolean} inline
- * @param {string} annotatorClass
- * @param {Object.<string, Annotator>} annotatorsClassMapping
- * @param {boolean} groupAnnotations
- * @returns {HTMLElement}
- */
-function createGroupContainer(inline, annotatorClass, annotatorsClassMapping, groupAnnotations) {
-  var automaticallyAnnotated = !(annotatorClass === undefined || annotatorClass === "undefined" || annotatorClass === null || annotatorClass === "");
-  var groupContainer = (inline ? document.createElement("span") : document.createElement("div"));
-  var descContainer = (inline ? document.createElement("span") : document.createElement("div"));
-
-  if (groupAnnotations) {
-    var annotatorName = automaticallyAnnotated ? annotatorsClassMapping[annotatorClass].getName() : "Annotated by curator";
-    if (inline) {
-      descContainer.innerHTML = 'Source: ' + annotatorName + ': ';
-    } else {
-      descContainer.innerHTML = 'Source: ' + annotatorName;
-
-      if (automaticallyAnnotated) {
-        var annotatorDescription = annotatorsClassMapping[annotatorClass].getDescription();
-        if (annotatorDescription) {
-          var tooltipContainer = Functions.createElement({
-            type: "span"
-          });
-          tooltipContainer.appendChild(Functions.createElement({
-            type: "span",
-            className: "glyphicon glyphicon-question-sign tooltip-icon"
-          }));
-          tooltipContainer.appendChild(Functions.createElement({
-            type: "span",
-            className: "annotator-tooltip",
-            content: annotatorsClassMapping[annotatorClass].getDescription()
-          }));
-
-          descContainer.appendChild(tooltipContainer);
-        }
-      }
-    }
-    descContainer.className = "minerva-annotation-group-header";
-    if (!inline) groupContainer.className = "minerva-annotation-group";
-    groupContainer.appendChild(descContainer);
-  }
-  return groupContainer;
-}
-
-/**
- *
- * @param {Annotation[]} annotations
- * @param {Object} [options]
- * @param {boolean} [options.showType = true]
- * @param {boolean} [options.inline = false]
- * @param {boolean} [options.groupAnnotations = true]
- * @returns {HTMLDivElement}
- */
-GuiUtils.prototype.createAnnotationList = function (annotations, options) {
-  var showType = true;
-  var inline = false;
-  var groupAnnotations = true;
-  if (options !== undefined) {
-    if (options.showType !== undefined) {
-      showType = options.showType;
-    }
-    if (options.inline !== undefined) {
-      inline = options.inline;
-    }
-    if (options.groupAnnotations !== undefined) {
-      groupAnnotations = options.groupAnnotations;
-    }
-  }
-
-  var self = this;
-  var result = document.createElement("div");
-
-  var annotators = this.getConfiguration().getAnnotators();
-  var annotatorsClassMapping = {};
-  var grouppedAnnotations = {};
-  var i;
-  if (groupAnnotations) {
-    for (i = 0; i < annotators.length; i++) {
-      annotatorsClassMapping[annotators[i].getClassName()] = annotators[i];
-    }
-
-    for (i = 0; i < annotations.length; i++) {
-      var clazz = annotations[i].getAnnotatorClassName();
-      if (!(clazz in grouppedAnnotations)) grouppedAnnotations[clazz] = [];
-      grouppedAnnotations[clazz].push(annotations[i])
-    }
-  } else {
-    annotatorsClassMapping["undefined"] = {
-      getName: function () {
-        return ""
-      }
-    };
-    grouppedAnnotations["undefined"] = annotations;
-  }
-
-  // = annotatorClasName ? annotatorsClassMapping[annotatorClasName].getName() : "Annotated by curator";
-
-  var cntAnnotations = 0;
-
-  Object.keys(grouppedAnnotations).sort().forEach(function (annotatorClass) {
-    var groupContainer = createGroupContainer(inline, annotatorClass, annotatorsClassMapping, groupAnnotations);
-
-    var par;
-    if (inline) {
-      par = document.createElement("span");
-      par.innerHTML = "(";
-      groupContainer.appendChild(par);
-    }
-
-    grouppedAnnotations[annotatorClass] = grouppedAnnotations[annotatorClass].sort(function (a, b) {
-      var aType = a.getType().toUpperCase();
-      var bType = b.getType().toUpperCase();
-      if (aType < bType) return -1;
-      else if (aType > bType) return 1;
-      else return 0;
-    });
-
-    for (var j = 0; j < grouppedAnnotations[annotatorClass].length; j++) {
-
-      cntAnnotations += 1;
-
-      var element = grouppedAnnotations[annotatorClass][j];
-      var link = self.createAnnotationLink(element, showType);
-      if (inline) {
-        if (j > 0) {
-          var coma = document.createElement("span");
-          coma.innerHTML = ", ";
-          groupContainer.appendChild(coma);
-        }
-        groupContainer.appendChild(link);
-      } else {
-
-        var row = document.createElement("div");
-        row.style.height = "26px";
-        if (j % 2 === 0) {
-          row.className = "minerva-annotation-row-odd";
-        } else {
-          row.className = "minerva-annotation-row-even";
-        }
-
-        var header = document.createElement("div");
-        header.style.width = "28px";
-        header.style.float = "left";
-        header.innerHTML = "[" + cntAnnotations + "]";
-        row.appendChild(header);
-
-        var body = document.createElement("div");
-        body.style.float = "left";
-        body.appendChild(link);
-        row.appendChild(body);
-        groupContainer.appendChild(row);
-      }
-    }
-
-    if (inline) {
-      par = document.createElement("span");
-      par.innerHTML = ")";
-      groupContainer.appendChild(par);
-    }
-
-    result.appendChild(groupContainer);
-  });
-
-  return result;
-};
-
-/**
- *
- * @param {string} [value]
- * @returns {HTMLSpanElement}
- */
-GuiUtils.prototype.createLabelText = function (value) {
-  var result = document.createElement("span");
-  if (value !== undefined) {
-    result.innerHTML = value;
-  }
-  return result;
-};
-
-/**
- *
- * @param {string} [value]
- * @returns {HTMLInputElement}
- */
-GuiUtils.prototype.createInputText = function (value) {
-  var result = document.createElement("input");
-  result.setAttribute('type', 'text');
-
-  if (value !== undefined) {
-    result.setAttribute('value', value);
-  }
-  return result;
-};
-
-/**
- *
- * @param {string} [value]
- * @returns {HTMLTextAreaElement}
- */
-GuiUtils.prototype.createTextArea = function (value) {
-  var result = document.createElement("textarea");
-
-  if (value !== undefined) {
-    result.setAttribute('value', value);
-    result.innerHTML = value;
-  }
-  return result;
-};
-
-/**
- *
- * @param {string} label
- * @param {string|number} [value]
- * @returns {HTMLDivElement}
- */
-GuiUtils.prototype.createParamLine = function (label, value) {
-  var result = document.createElement("div");
-  if (value !== undefined && value !== null && value !== "") {
-    var self = this;
-    result.appendChild(self.createLabel(label));
-    result.appendChild(self.createLabelText(value));
-  }
-  return result;
-};
-
-/**
- *
- * @param {string} [icon]
- * @param {function} [onclickFunction]
- * @returns {HTMLDivElement}
- */
-GuiUtils.prototype.createIcon = function (icon, onclickFunction) {
-  var result = document.createElement("div");
-  if (icon !== undefined && icon !== null) {
-    var img = document.createElement("img");
-    img.src = GuiConnector.getImgPrefix() + icon;
-    img.style.float = "left";
-    img.hspace = 5;
-    if (onclickFunction !== undefined) {
-      img.onclick = onclickFunction;
-    }
-    result.appendChild(img);
-  }
-  return result;
-};
-
-/**
- *
- * @param {string} label
- * @param {string[]} [value]
- *
- * @returns {HTMLDivElement}
- */
-GuiUtils.prototype.createArrayParamLine = function (label, value) {
-  var result = document.createElement("div");
-  if (value !== undefined && value.length > 0) {
-    var self = this;
-    result.appendChild(self.createLabel(label));
-    result.appendChild(self.createLabelText(value.join(", ")));
-  }
-  return result;
-};
-
-/**
- *
- * @param {string} label
- * @param {number} [modelId]
- * @returns {HTMLDivElement}
- */
-GuiUtils.prototype.createSubMapLink = function (label, modelId) {
-  var self = this;
-  var result = document.createElement("div");
-  if (modelId !== undefined) {
-    var button = document.createElement("button");
-    var model = self.getMap().getSubmapById(modelId).getModel();
-
-    button.innerHTML = model.getName();
-    button.onclick = function () {
-      return self.getMap().openSubmap(modelId);
-    };
-    result.appendChild(this.createLabel(label));
-    result.appendChild(button);
-  }
-  return result;
-};
-
-/**
- *
- * @param {Array<string|HTMLElement>} elements
- * @returns {HTMLElement}
- */
-GuiUtils.prototype.createTableRow = function (elements) {
-  var row = Functions.createElement({
-    type: "div",
-    style: "display: table-row;"
-  });
-
-  for (var i = 0; i < elements.length; i++) {
-    var cell = Functions.createElement({
-      type: "div",
-      style: "display: table-cell;"
-    });
-    if (Functions.isDomElement(elements[i])) {
-      cell.appendChild(elements[i]);
-    } else {
-      cell.innerHTML = elements[i];
-    }
-    row.appendChild(cell);
-  }
-  return row;
-};
-
-/**
- *
- * @param {Reaction|SearchBioEntityGroup} params.reaction
- * @param {string} [params.icon]
- * @param {boolean} [params.showTitle]
- *
- * @returns {Promise<HTMLDivElement>}
- */
-GuiUtils.prototype.createReactionElement = function (params) {
-  var reaction = params.reaction;
-  var showTitle = ((params.showTitle === undefined) || params.showTitle);
-  var self = this;
-  var div = document.createElement("div");
-
-  if (showTitle) {
-    div.appendChild(self.createLabel("Reaction: " + reaction.getReactionId()));
-    if (reaction.getModelId() !== self.getMap().getId()) {
-      div.appendChild(self.createSubMapLink("In submap: ", reaction.getModelId()));
-    }
-  }
-
-  if (reaction.getLinkedSubmodelId() !== null && reaction.getLinkedSubmodelId() !== undefined) {
-    div.appendChild(self.createSubMapLink("Associated submap: ", reaction.getLinkedSubmodelId()));
-  }
-  if (showTitle) {
-    div.appendChild(self.createNewLine());
-  }
-
-  if (self.getConfiguration().getOption(ConfigurationType.SHOW_REACTION_TYPE).getValue().toLowerCase() === "true") {
-    div.appendChild(self.createParamLine("Type: ", reaction.getType()));
-  }
-  div.appendChild(self.createParamLine("Symbol: ", reaction.getSymbol()));
-  div.appendChild(self.createParamLine("Abbreviation: ", reaction.getAbbreviation()));
-  div.appendChild(self.createParamLine("Formula: ", reaction.getFormula()));
-  div.appendChild(self.createParamLine("Mechanical Confidence Score: ", reaction.getMechanicalConfidenceScore()));
-  div.appendChild(self.createParamLine("Lower Bound: ", reaction.getLowerBound()));
-  div.appendChild(self.createParamLine("Upper Bound: ", reaction.getUpperBound()));
-  div.appendChild(self.createParamLine("Gene Protein Reaction: ", reaction.getGeneProteinReaction()));
-  div.appendChild(self.createParamLine("Subsystem: ", reaction.getSubsystem()));
-  div.appendChild(self.createArrayParamLine("Synonyms: ", reaction.getSynonyms()));
-  div.appendChild(self.createParamLine("Description: ", reaction.getDescription()));
-  div.appendChild(self.createAnnotations("Annotations: ", reaction.getReferences()));
-  return Promise.resolve(div);
-};
-
-/**
- *
- * @param {Object[]} modifications
- *
- * @returns {HTMLDivElement}
- */
-GuiUtils.prototype.createModifications = function (modifications) {
-  var self = this;
-  var result = document.createElement("div");
-  var modificationsByType = [];
-  if (modifications !== undefined) {
-    for (var i = 0; i < modifications.length; i++) {
-      var modification = modifications[i];
-      if (modificationsByType[modification.type] === undefined) {
-        modificationsByType[modification.type] = [];
-      }
-      modificationsByType[modification.type].push(modification);
-    }
-    for (var key in modificationsByType) {
-      if (modificationsByType.hasOwnProperty(key)) {
-        result.appendChild(self.createPostTranslationalModifications(key, modificationsByType[key]));
-      }
-    }
-  }
-  return result;
-};
-
-/**
- *
- * @param {Alias|SearchBioEntityGroup} params.alias
- * @param {string} [params.icon]
- * @param {boolean} [params.showTitle]
- *
- * @returns {Promise<HTMLDivElement>}
- */
-GuiUtils.prototype.createAliasElement = function (params) {
-  var alias = params.alias;
-  var icon = params.icon;
-  var showTitle = ((params.showTitle === undefined) || params.showTitle);
-  var self = this;
-  var div = document.createElement("div");
-
-  if (showTitle) {
-    if (icon !== undefined) {
-      div.appendChild(this.createIcon(icon, function () {
-        return self.getMap().openSubmap(alias.getModelId()).then(function () {
-          if (alias instanceof Alias) {
-            return self.getMap().getSubmapById(alias.getModelId()).fitBounds([alias]);
-          } else {
-            return self.getMap().getSubmapById(alias.getModelId()).fitBounds(alias.getBioEntities());
-          }
-        });
-      }));
-    }
-
-    div.appendChild(this.createParamLine(alias.getType() + ": ", alias.getName()));
-    if (alias.getModelId() !== self.getMap().getId()) {
-      div.appendChild(self.createSubMapLink("In submap: ", alias.getModelId()));
-    }
-  }
-  if (alias.getLinkedSubmodelId() !== undefined) {
-    div.appendChild(self.createSubMapLink("Associated submap: ", alias.getLinkedSubmodelId()));
-  }
-  if (alias instanceof SearchBioEntityGroup && alias.getBioEntities().length > 1) {
-    div.appendChild(self.createLabelText("Group of " + alias.getBioEntities().length + " elements."));
-  }
-  if (showTitle) {
-    div.appendChild(self.createNewLine(3));
-  }
-
-  var promise = Promise.resolve();
-  if (alias.getCompartmentId() !== undefined) {
-    promise = self.getMap().getModel().getByIdentifiedElement(new IdentifiedElement({
-      type: "ALIAS",
-      id: alias.getCompartmentId(),
-      modelId: alias.getModelId()
-    }), true).then(function (compartment) {
-      div.appendChild(self.createParamLine("Compartment: ", compartment.getName()));
-    })
-  }
-
-  return promise.then(function () {
-
-    div.appendChild(self.createParamLine("Full name: ", alias.getFullName()));
-    div.appendChild(self.createParamLine("Symbol: ", alias.getSymbol()));
-    div.appendChild(self.createParamLine("Abbreviation: ", alias.getAbbreviation()));
-    div.appendChild(self.createParamLine("Formula: ", alias.getFormula()));
-    div.appendChild(self.createArrayParamLine("Former symbols: ", alias.getFormerSymbols()));
-    div.appendChild(self.createModifications(alias.getOther('modifications')));
-    div.appendChild(self.createParamLine("Charge: ", alias.getCharge()));
-    div.appendChild(self.createArrayParamLine("Synonyms: ", alias.getSynonyms()));
-    div.appendChild(self.createLabelText(alias.getDescription()));
-    div.appendChild(self.createAnnotations("Annotations: ", alias.getReferences()));
-
-    return div;
-  })
-};
-
-/**
- *
- * @param {SearchBioEntityGroup} group
- * @returns {Promise<HTMLDivElement>}
- */
-GuiUtils.prototype.createSearchBioEntityGroupElement = function (group) {
-  if (group.getBioEntities()[0] instanceof Alias) {
-    return this.createAliasElement({alias: group, icon: group.getIcon()});
-  } else {
-    return this.createReactionElement({reaction: group, icon: group.getIcon()});
-  }
-};
-
-/**
- *
- * @returns {HTMLAnchorElement}
- */
-GuiUtils.prototype.createLogoutLink = function () {
-  var logoutLink = document.createElement("a");
-  logoutLink.href = "#";
-  logoutLink.innerHTML = "LOGOUT";
-  logoutLink.id = "logoutLink";
-  logoutLink.onclick = function () {
-    return ServerConnector.logout();
-  };
-  return logoutLink;
-};
-
-/**
- *
- * @param {string} params.name
- * @param {string} params.id
- * @param {HTMLElement} params.navigationBar
- *
- * @returns {HTMLLIElement}
- */
-GuiUtils.prototype.createTabMenuObject = function (params) {
-  var name = params.name;
-  var id = params.id;
-  var navigationBar = params.navigationBar;
-
-  var navClass = '';
-  if (navigationBar.children.length === 0) {
-    navClass = "active";
-  }
-
-  var navLi = document.createElement("li");
-  navLi.className = navClass;
-
-  var navLink = document.createElement("a");
-  navLink.href = "#" + id;
-  if (name !== undefined) {
-    navLink.innerHTML = name;
-  }
-  navLink.onclick = function () {
-    $(this).tab('show');
-  };
-  navLi.appendChild(navLink);
-  if (name !== undefined) {
-    navLink.innerHTML = name;
-  }
-  return navLi;
-};
-
-/**
- *
- * @param {string} params.id
- * @param {HTMLElement} params.navigationObject
- *
- * @returns {HTMLDivElement}
- */
-GuiUtils.prototype.createTabContentObject = function (params) {
-  var navigationObject = params.navigationObject;
-  var tabId = params.id;
-  var result = document.createElement("div");
-  result.style.height = "100%";
-
-  var contentClass = 'tab-pane';
-  if (navigationObject.className === "active") {
-    contentClass = "tab-pane active";
-  }
-
-  result.className = contentClass;
-  result.id = tabId;
-  return result;
-};
-
-/**
- *
- * @param {HTMLElement} [params.element]
- * @param {string} params.id
- *
- * @returns {{element: HTMLElement, menu: HTMLElement, content: HTMLElement, tabId: *}}
- */
-GuiUtils.prototype.createTabDiv = function (params) {
-  var tabDiv = Functions.createElement({
-    type: "div",
-    name: "tabView",
-    className: "tabbable boxed parentTabs"
-  });
-
-  var tabMenuDiv = Functions.createElement({
-    type: "ul",
-    className: "nav nav-tabs"
-  });
-  tabDiv.appendChild(tabMenuDiv);
-
-  var tabContentDiv = Functions.createElement({
-    type: "div",
-    className: "tab-content"
-  });
-  tabDiv.appendChild(tabContentDiv);
-
-  if (params.element !== undefined) {
-    params.element.appendChild(tabDiv);
-  }
-
-  return {
-    element: tabDiv,
-    menu: tabMenuDiv,
-    content: tabContentDiv,
-    tabId: params.id
-  }
-};
-
-GuiUtils.prototype.createTab = function (params) {
-  var tabData = params.tabData;
-
-  var tabId = tabData.tabId + "_tab_" + tabIdCounter;
-  tabIdCounter++;
-
-  var navClass = '';
-  var contentClass = 'tab-pane';
-  if (tabData.menu.children.length === 0) {
-    navClass = "active";
-    contentClass = "tab-pane active";
-  }
-
-  var navLi = document.createElement("li");
-  navLi.className = navClass;
-
-  var navLink = document.createElement("a");
-  navLink.href = "#" + tabId;
-
-  navLink.innerHTML = params.title;
-
-  navLink.onclick = function () {
-    $(this).tab('show');
-  };
-  navLi.appendChild(navLink);
-  tabData.menu.appendChild(navLi);
-
-  var contentDiv = document.createElement("div");
-  contentDiv.style.height = "100%";
-  contentDiv.className = contentClass;
-  contentDiv.id = tabId;
-
-  if (Functions.isDomElement(params.content)) {
-    contentDiv.appendChild(params.content);
-  } else {
-    contentDiv.innerHTML = params.content;
-  }
-  tabData.content.appendChild(contentDiv);
-
-  $(contentDiv).css("overflow", "auto");
-  $(contentDiv).css("height", "calc(100vh - " + $(contentDiv).offset().top + "px)");
-
-  return {
-    title: navLink,
-    content: contentDiv
-  }
-};
-
-/**
- *
- * @param {string} toolTip
- * @param {boolean} [useXss=false]
- * @returns {HTMLElement}
- */
-GuiUtils.prototype.createHelpButton = function (toolTip, useXss) {
-  var helpContent;
-  if (useXss) {
-    helpContent = xss(toolTip);
-  } else {
-    helpContent = toolTip;
-  }
-
-  var helpTipButton = Functions.createElement({
-    type: "button",
-    className: "minerva-help-button",
-    content: '<span class="ui-icon ui-icon-help" style="margin-left: -0.5em;"/>',
-    xss: false
-  });
-  var helpDialogDiv = undefined;
-  helpTipButton.onclick = function () {
-    if (helpDialogDiv === undefined) {
-      helpDialogDiv = Functions.createElement({
-        type: "div",
-        content: helpContent,
-        xss: false
-      });
-      $(helpDialogDiv).dialog({
-        close: function () {
-          $(this).dialog('destroy').remove();
-          helpDialogDiv = undefined;
-        },
-        position: {
-          my: "left top",
-          at: "left bottom",
-          of: helpTipButton
-        }
-      });
-      $('.ui-dialog').find("a").blur();
-    }
-  };
-  return helpTipButton;
-};
-
-module.exports = GuiUtils;
+"use strict";
+
+/* exported logger */
+
+var Alias = require('../../map/data/Alias');
+var ConfigurationType = require('../../ConfigurationType');
+var IdentifiedElement = require('../../map/data/IdentifiedElement');
+var SearchBioEntityGroup = require('../../map/data/SearchBioEntityGroup');
+
+
+var GuiConnector = require('../../GuiConnector');
+var AbstractGuiElement = require('../AbstractGuiElement');
+var Functions = require('../../Functions');
+
+var logger = require('../../logger');
+var xss = require('xss');
+
+var Promise = require('bluebird');
+
+var tabIdCounter = 0;
+
+/**
+ *
+ * @param {Configuration} configuration
+ * @constructor
+ */
+function GuiUtils(configuration) {
+  var self = this;
+  self.setConfiguration(configuration);
+}
+
+GuiUtils.prototype = Object.create(AbstractGuiElement.prototype);
+GuiUtils.prototype.constructor = GuiUtils;
+
+/**
+ *
+ * @param {Configuration} configuration
+ */
+GuiUtils.prototype.setConfiguration = function (configuration) {
+  this._configuration = configuration;
+};
+
+/**
+ *
+ * @returns {Configuration}
+ */
+GuiUtils.prototype.getConfiguration = function () {
+  return this._configuration;
+};
+
+/**
+ *
+ * @param {string} value
+ * @returns {HTMLSpanElement}
+ */
+GuiUtils.prototype.createLabel = function (value) {
+  var result = document.createElement("span");
+  result.innerHTML = value;
+  result.className = "minerva-label";
+  return result;
+};
+
+/**
+ *
+ * @param {Object} modification
+ * @param {string} [modification.name]
+ * @param {string} modification.type
+ * @param {string} [modification.state]
+ *
+ * @returns {HTMLElement| null}
+ */
+GuiUtils.prototype.createModificationRow = function (modification) {
+  var self = this;
+  var row = null;
+  var name = modification.name;
+  var desc = undefined;
+  if (modification.state !== undefined && modification.state !== null) {
+    var modificationStateType = self.getConfiguration().getModificationStateTypeByName(modification.state);
+    var state = modificationStateType.getCommonName();
+
+    if (name !== null && name !== undefined && name !== "") {
+      desc = state + " at position " + name + ", ";
+    } else {
+      desc = state + ",";
+    }
+  } else if (name !== null && name !== undefined && name !== "" &&
+    (modification.type === "BINDING_REGION" ||
+      modification.type === "CODING_REGION" ||
+      modification.type === "PROTEIN_BINDING_DOMAIN" ||
+      modification.type === "TRANSCRIPTION_SITE_LEFT" ||
+      modification.type === "TRANSCRIPTION_SITE_RIGHT" ||
+      modification.type === "REGULATORY_REGION"
+    )) {
+    desc = name + ",";
+  }
+
+  if (desc !== undefined) {
+    row = Functions.createElement({
+      type: "li"
+    });
+    row.appendChild(self.createLabelText(desc));
+  }
+  return row;
+};
+
+/**
+ *
+ * @param {string} label
+ * @param {Object[]} value
+ * @returns {HTMLDivElement}
+ */
+GuiUtils.prototype.createPostTranslationalModifications = function (label, value) {
+  var result = document.createElement("div");
+  var count = 0;
+  if (value !== undefined && value.length > 0) {
+    var self = this;
+    var userFriendlyLabel = label + ": ";
+    if (label === "RESIDUE") {
+      userFriendlyLabel = "Posttranslational modifications: "
+    } else if (label === "BINDING_REGION") {
+      userFriendlyLabel = "Binding regions: "
+    } else if (label === "CODING_REGION") {
+      userFriendlyLabel = "Coding regions: "
+    } else if (label === "PROTEIN_BINDING_DOMAIN") {
+      userFriendlyLabel = "Protein binding domains: "
+    } else if (label === "TRANSCRIPTION_SITE_LEFT") {
+      userFriendlyLabel = "Transcription sites (left): "
+    } else if (label === "TRANSCRIPTION_SITE_RIGHT") {
+      userFriendlyLabel = "Transcription sites (right): "
+    } else if (label === "TRANSCRIPTION_SITE") {
+      userFriendlyLabel = "Transcription sites: "
+    } else if (label === "MODIFICATION_SITE") {
+      userFriendlyLabel = "Modification sites: "
+    }
+    result.appendChild(self.createLabel(userFriendlyLabel));
+    result.appendChild(self.createNewLine());
+    var list = Functions.createElement({
+      type: "ul"
+    });
+    for (var i = 0; i < value.length; i++) {
+      var modification = value[i];
+      var row = self.createModificationRow(modification, self);
+      if (row !== null) {
+        list.appendChild(row);
+        count++;
+      }
+    }
+    result.appendChild(list);
+  }
+  if (count > 0) {
+    return result;
+  } else {
+    return document.createElement("div");
+  }
+};
+
+/**
+ *
+ * @returns {HTMLHRElement}
+ */
+GuiUtils.prototype.createSeparator = function () {
+  return document.createElement("hr");
+};
+
+/**
+ *
+ * @param {number} [count]
+ * @returns {HTMLParagraphElement}
+ */
+GuiUtils.prototype.createNewLine = function (count) {
+  if (count === undefined) {
+    count = 0;
+  }
+  var result = document.createElement("p");
+  if (count > 0) {
+    result.style.height = ((count - 1) * 10) + "px";
+  }
+  return result;
+};
+
+/**
+ *
+ * @param {string} [url]
+ * @param {string} name
+ * @returns {HTMLElement}
+ */
+GuiUtils.prototype.createLink = function (url, name) {
+  if (url === null || url === undefined) {
+    logger.warn("URL not defined for: \"" + name + "\" link");
+    return Functions.createElement({type: "span", content: name});
+  }
+  var link = document.createElement("a");
+  link.href = url;
+  link.innerHTML = name;
+  link.target = "_blank";
+  link.style.textDecoration = "underline";
+  return link;
+};
+
+/**
+ *
+ * @param {Annotation} annotation
+ * @param {boolean} [showType=false]
+ * @returns {HTMLElement}
+ */
+GuiUtils.prototype.createAnnotationLink = function (annotation, showType) {
+  var self = this;
+  var name, type, hint;
+  var article = annotation.getArticle();
+  if (article !== undefined) {
+
+    hint = article.getTitle() + " " + article.getAuthors().join(", ") + ", " + article.getYear() + ", "
+      + article.getJournal();
+    type = "PUBMED";
+    name = article.getId();
+  } else {
+    //replace encoded parts of uri (like %2F - > "/")
+    name = decodeURIComponent(annotation.getResource());
+    var miriamType = self.getConfiguration().getMiriamTypeByName(annotation.getType());
+    if (miriamType === null) {
+      logger.warn("Unknown miriam type: " + annotation.getType());
+      type = annotation.getType();
+    } else {
+      type = miriamType.getCommonName();
+    }
+  }
+  var link;
+  if (showType) {
+    link = self.createLink(annotation.getLink(), type + " (" + name + ")");
+  } else {
+    link = self.createLink(annotation.getLink(), name);
+  }
+  if (hint !== undefined) {
+    var div = document.createElement("div");
+    div.title = hint;
+    div.appendChild(link);
+    return div;
+  } else {
+    return link;
+  }
+};
+
+/**
+ *
+ * @param {string} label
+ * @param {Annotation[]} [value]
+ * @param {Object} [options]
+ * @param {boolean} [options.inline]
+ *
+ * @returns {HTMLDivElement}
+ */
+GuiUtils.prototype.createAnnotations = function (label, value, options) {
+  var self = this;
+
+  var inline = false;
+  if (options !== undefined) {
+    if (options.inline !== undefined) {
+      inline = options.inline;
+    }
+  }
+  var result = document.createElement("div");
+  result.appendChild(self.createLabel(label));
+  if (value !== undefined && value.length > 0) {
+    if (!inline) {
+      result.appendChild(self.createNewLine());
+    }
+    result.appendChild(self.createAnnotationList(value, options));
+  } else {
+    result.appendChild(self.createLabelText("No annotations"));
+  }
+  return result;
+};
+
+/**
+ *
+ * @param {boolean} inline
+ * @param {string} annotatorClass
+ * @param {Object.<string, Annotator>} annotatorsClassMapping
+ * @param {boolean} groupAnnotations
+ * @returns {HTMLElement}
+ */
+function createGroupContainer(inline, annotatorClass, annotatorsClassMapping, groupAnnotations) {
+  var automaticallyAnnotated = !(annotatorClass === undefined || annotatorClass === "undefined" || annotatorClass === null || annotatorClass === "");
+  var groupContainer = (inline ? document.createElement("span") : document.createElement("div"));
+  var descContainer = (inline ? document.createElement("span") : document.createElement("div"));
+
+  if (groupAnnotations) {
+    var annotatorName = automaticallyAnnotated ? annotatorsClassMapping[annotatorClass].getName() : "Annotated by curator";
+    if (inline) {
+      descContainer.innerHTML = 'Source: ' + annotatorName + ': ';
+    } else {
+      descContainer.innerHTML = 'Source: ' + annotatorName;
+
+      if (automaticallyAnnotated) {
+        var annotatorDescription = annotatorsClassMapping[annotatorClass].getDescription();
+        if (annotatorDescription) {
+          var tooltipContainer = Functions.createElement({
+            type: "span"
+          });
+          tooltipContainer.appendChild(Functions.createElement({
+            type: "span",
+            className: "glyphicon glyphicon-question-sign tooltip-icon"
+          }));
+          tooltipContainer.appendChild(Functions.createElement({
+            type: "span",
+            className: "annotator-tooltip",
+            content: annotatorsClassMapping[annotatorClass].getDescription()
+          }));
+
+          descContainer.appendChild(tooltipContainer);
+        }
+      }
+    }
+    descContainer.className = "minerva-annotation-group-header";
+    if (!inline) groupContainer.className = "minerva-annotation-group";
+    groupContainer.appendChild(descContainer);
+  }
+  return groupContainer;
+}
+
+/**
+ *
+ * @param {Annotation[]} annotations
+ * @param {Object} [options]
+ * @param {boolean} [options.showType = true]
+ * @param {boolean} [options.inline = false]
+ * @param {boolean} [options.groupAnnotations = true]
+ * @returns {HTMLDivElement}
+ */
+GuiUtils.prototype.createAnnotationList = function (annotations, options) {
+  var showType = true;
+  var inline = false;
+  var groupAnnotations = true;
+  if (options !== undefined) {
+    if (options.showType !== undefined) {
+      showType = options.showType;
+    }
+    if (options.inline !== undefined) {
+      inline = options.inline;
+    }
+    if (options.groupAnnotations !== undefined) {
+      groupAnnotations = options.groupAnnotations;
+    }
+  }
+
+  var self = this;
+  var result = document.createElement("div");
+
+  var annotators = this.getConfiguration().getAnnotators();
+  var annotatorsClassMapping = {};
+  var grouppedAnnotations = {};
+  var i;
+  if (groupAnnotations) {
+    for (i = 0; i < annotators.length; i++) {
+      annotatorsClassMapping[annotators[i].getClassName()] = annotators[i];
+    }
+
+    for (i = 0; i < annotations.length; i++) {
+      var clazz = annotations[i].getAnnotatorClassName();
+      if (!(clazz in grouppedAnnotations)) grouppedAnnotations[clazz] = [];
+      grouppedAnnotations[clazz].push(annotations[i])
+    }
+  } else {
+    annotatorsClassMapping["undefined"] = {
+      getName: function () {
+        return ""
+      }
+    };
+    grouppedAnnotations["undefined"] = annotations;
+  }
+
+  // = annotatorClasName ? annotatorsClassMapping[annotatorClasName].getName() : "Annotated by curator";
+
+  var cntAnnotations = 0;
+
+  Object.keys(grouppedAnnotations).sort().forEach(function (annotatorClass) {
+    var groupContainer = createGroupContainer(inline, annotatorClass, annotatorsClassMapping, groupAnnotations);
+
+    var par;
+    if (inline) {
+      par = document.createElement("span");
+      par.innerHTML = "(";
+      groupContainer.appendChild(par);
+    }
+
+    grouppedAnnotations[annotatorClass] = grouppedAnnotations[annotatorClass].sort(function (a, b) {
+      var aType = a.getType().toUpperCase();
+      var bType = b.getType().toUpperCase();
+      if (aType < bType) return -1;
+      else if (aType > bType) return 1;
+      else return 0;
+    });
+
+    for (var j = 0; j < grouppedAnnotations[annotatorClass].length; j++) {
+
+      cntAnnotations += 1;
+
+      var element = grouppedAnnotations[annotatorClass][j];
+      var link = self.createAnnotationLink(element, showType);
+      if (inline) {
+        if (j > 0) {
+          var coma = document.createElement("span");
+          coma.innerHTML = ", ";
+          groupContainer.appendChild(coma);
+        }
+        groupContainer.appendChild(link);
+      } else {
+
+        var row = document.createElement("div");
+        row.style.height = "26px";
+        if (j % 2 === 0) {
+          row.className = "minerva-annotation-row-odd";
+        } else {
+          row.className = "minerva-annotation-row-even";
+        }
+
+        var header = document.createElement("div");
+        header.style.width = "28px";
+        header.style.float = "left";
+        header.innerHTML = "[" + cntAnnotations + "]";
+        row.appendChild(header);
+
+        var body = document.createElement("div");
+        body.style.float = "left";
+        body.appendChild(link);
+        row.appendChild(body);
+        groupContainer.appendChild(row);
+      }
+    }
+
+    if (inline) {
+      par = document.createElement("span");
+      par.innerHTML = ")";
+      groupContainer.appendChild(par);
+    }
+
+    result.appendChild(groupContainer);
+  });
+
+  return result;
+};
+
+/**
+ *
+ * @param {string} [value]
+ * @returns {HTMLSpanElement}
+ */
+GuiUtils.prototype.createLabelText = function (value) {
+  var result = document.createElement("span");
+  if (value !== undefined) {
+    result.innerHTML = value;
+  }
+  return result;
+};
+
+/**
+ *
+ * @param {string} [value]
+ * @returns {HTMLInputElement}
+ */
+GuiUtils.prototype.createInputText = function (value) {
+  var result = document.createElement("input");
+  result.setAttribute('type', 'text');
+
+  if (value !== undefined) {
+    result.setAttribute('value', value);
+  }
+  return result;
+};
+
+/**
+ *
+ * @param {string} [value]
+ * @returns {HTMLTextAreaElement}
+ */
+GuiUtils.prototype.createTextArea = function (value) {
+  var result = document.createElement("textarea");
+
+  if (value !== undefined) {
+    result.setAttribute('value', value);
+    result.innerHTML = value;
+  }
+  return result;
+};
+
+/**
+ *
+ * @param {string} label
+ * @param {string|number} [value]
+ * @returns {HTMLDivElement}
+ */
+GuiUtils.prototype.createParamLine = function (label, value) {
+  var result = document.createElement("div");
+  if (value !== undefined && value !== null && value !== "") {
+    var self = this;
+    result.appendChild(self.createLabel(label));
+    result.appendChild(self.createLabelText(value));
+  }
+  return result;
+};
+
+/**
+ *
+ * @param {string} [icon]
+ * @param {function} [onclickFunction]
+ * @returns {HTMLDivElement}
+ */
+GuiUtils.prototype.createIcon = function (icon, onclickFunction) {
+  var result = document.createElement("div");
+  if (icon !== undefined && icon !== null) {
+    var img = document.createElement("img");
+    img.src = GuiConnector.getImgPrefix() + icon;
+    img.style.float = "left";
+    img.hspace = 5;
+    if (onclickFunction !== undefined) {
+      img.onclick = onclickFunction;
+    }
+    result.appendChild(img);
+  }
+  return result;
+};
+
+/**
+ *
+ * @param {string} label
+ * @param {string[]} [value]
+ *
+ * @returns {HTMLDivElement}
+ */
+GuiUtils.prototype.createArrayParamLine = function (label, value) {
+  var result = document.createElement("div");
+  if (value !== undefined && value.length > 0) {
+    var self = this;
+    result.appendChild(self.createLabel(label));
+    result.appendChild(self.createLabelText(value.join(", ")));
+  }
+  return result;
+};
+
+/**
+ *
+ * @param {string} label
+ * @param {number} [modelId]
+ * @returns {HTMLDivElement}
+ */
+GuiUtils.prototype.createSubMapLink = function (label, modelId) {
+  var self = this;
+  var result = document.createElement("div");
+  if (modelId !== undefined) {
+    var button = document.createElement("button");
+    var model = self.getMap().getSubmapById(modelId).getModel();
+
+    button.innerHTML = model.getName();
+    button.onclick = function () {
+      return self.getMap().openSubmap(modelId);
+    };
+    result.appendChild(this.createLabel(label));
+    result.appendChild(button);
+  }
+  return result;
+};
+
+/**
+ *
+ * @param {Array<string|HTMLElement>} elements
+ * @returns {HTMLElement}
+ */
+GuiUtils.prototype.createTableRow = function (elements) {
+  var row = Functions.createElement({
+    type: "div",
+    style: "display: table-row;"
+  });
+
+  for (var i = 0; i < elements.length; i++) {
+    var cell = Functions.createElement({
+      type: "div",
+      style: "display: table-cell;"
+    });
+    if (Functions.isDomElement(elements[i])) {
+      cell.appendChild(elements[i]);
+    } else {
+      cell.innerHTML = elements[i];
+    }
+    row.appendChild(cell);
+  }
+  return row;
+};
+
+/**
+ *
+ * @param {Reaction|SearchBioEntityGroup} params.reaction
+ * @param {string} [params.icon]
+ * @param {boolean} [params.showTitle]
+ *
+ * @returns {Promise<HTMLDivElement>}
+ */
+GuiUtils.prototype.createReactionElement = function (params) {
+  var reaction = params.reaction;
+  var showTitle = ((params.showTitle === undefined) || params.showTitle);
+  var self = this;
+  var div = document.createElement("div");
+
+  if (showTitle) {
+    div.appendChild(self.createLabel("Reaction: " + reaction.getReactionId()));
+    if (reaction.getModelId() !== self.getMap().getId()) {
+      div.appendChild(self.createSubMapLink("In submap: ", reaction.getModelId()));
+    }
+  }
+
+  if (reaction.getLinkedSubmodelId() !== null && reaction.getLinkedSubmodelId() !== undefined) {
+    div.appendChild(self.createSubMapLink("Associated submap: ", reaction.getLinkedSubmodelId()));
+  }
+  if (showTitle) {
+    div.appendChild(self.createNewLine());
+  }
+
+  if (self.getConfiguration().getOption(ConfigurationType.SHOW_REACTION_TYPE).getValue().toLowerCase() === "true") {
+    div.appendChild(self.createParamLine("Type: ", reaction.getType()));
+  }
+  div.appendChild(self.createParamLine("Symbol: ", reaction.getSymbol()));
+  div.appendChild(self.createParamLine("Abbreviation: ", reaction.getAbbreviation()));
+  div.appendChild(self.createParamLine("Formula: ", reaction.getFormula()));
+  div.appendChild(self.createParamLine("Mechanical Confidence Score: ", reaction.getMechanicalConfidenceScore()));
+  div.appendChild(self.createParamLine("Lower Bound: ", reaction.getLowerBound()));
+  div.appendChild(self.createParamLine("Upper Bound: ", reaction.getUpperBound()));
+  div.appendChild(self.createParamLine("Gene Protein Reaction: ", reaction.getGeneProteinReaction()));
+  div.appendChild(self.createParamLine("Subsystem: ", reaction.getSubsystem()));
+  div.appendChild(self.createArrayParamLine("Synonyms: ", reaction.getSynonyms()));
+  div.appendChild(self.createParamLine("Description: ", reaction.getDescription()));
+  div.appendChild(self.createAnnotations("Annotations: ", reaction.getReferences()));
+  return Promise.resolve(div);
+};
+
+/**
+ *
+ * @param {Object[]} modifications
+ *
+ * @returns {HTMLDivElement}
+ */
+GuiUtils.prototype.createModifications = function (modifications) {
+  var self = this;
+  var result = document.createElement("div");
+  var modificationsByType = [];
+  if (modifications !== undefined) {
+    for (var i = 0; i < modifications.length; i++) {
+      var modification = modifications[i];
+      if (modificationsByType[modification.type] === undefined) {
+        modificationsByType[modification.type] = [];
+      }
+      modificationsByType[modification.type].push(modification);
+    }
+    for (var key in modificationsByType) {
+      if (modificationsByType.hasOwnProperty(key)) {
+        result.appendChild(self.createPostTranslationalModifications(key, modificationsByType[key]));
+      }
+    }
+  }
+  return result;
+};
+
+/**
+ *
+ * @param {Alias|SearchBioEntityGroup} params.alias
+ * @param {string} [params.icon]
+ * @param {boolean} [params.showTitle]
+ *
+ * @returns {Promise<HTMLDivElement>}
+ */
+GuiUtils.prototype.createAliasElement = function (params) {
+  var alias = params.alias;
+  var icon = params.icon;
+  var showTitle = ((params.showTitle === undefined) || params.showTitle);
+  var self = this;
+  var div = document.createElement("div");
+
+  if (showTitle) {
+    if (icon !== undefined) {
+      div.appendChild(this.createIcon(icon, function () {
+        return self.getMap().openSubmap(alias.getModelId()).then(function () {
+          if (alias instanceof Alias) {
+            return self.getMap().getSubmapById(alias.getModelId()).fitBounds([alias]);
+          } else {
+            return self.getMap().getSubmapById(alias.getModelId()).fitBounds(alias.getBioEntities());
+          }
+        });
+      }));
+    }
+
+    div.appendChild(this.createParamLine(alias.getType() + ": ", alias.getName()));
+    if (alias.getModelId() !== self.getMap().getId()) {
+      div.appendChild(self.createSubMapLink("In submap: ", alias.getModelId()));
+    }
+  }
+  if (alias.getLinkedSubmodelId() !== undefined) {
+    div.appendChild(self.createSubMapLink("Associated submap: ", alias.getLinkedSubmodelId()));
+  }
+  if (alias instanceof SearchBioEntityGroup && alias.getBioEntities().length > 1) {
+    div.appendChild(self.createLabelText("Group of " + alias.getBioEntities().length + " elements."));
+  }
+  if (showTitle) {
+    div.appendChild(self.createNewLine(3));
+  }
+
+  var promise = Promise.resolve();
+  if (alias.getCompartmentId() !== undefined) {
+    promise = self.getMap().getModel().getByIdentifiedElement(new IdentifiedElement({
+      type: "ALIAS",
+      id: alias.getCompartmentId(),
+      modelId: alias.getModelId()
+    }), true).then(function (compartment) {
+      div.appendChild(self.createParamLine("Compartment: ", compartment.getName()));
+    })
+  }
+
+  return promise.then(function () {
+
+    div.appendChild(self.createParamLine("Full name: ", alias.getFullName()));
+    div.appendChild(self.createParamLine("Symbol: ", alias.getSymbol()));
+    div.appendChild(self.createParamLine("Abbreviation: ", alias.getAbbreviation()));
+    div.appendChild(self.createParamLine("Formula: ", alias.getFormula()));
+    div.appendChild(self.createArrayParamLine("Former symbols: ", alias.getFormerSymbols()));
+    div.appendChild(self.createModifications(alias.getOther('modifications')));
+    div.appendChild(self.createParamLine("Charge: ", alias.getCharge()));
+    div.appendChild(self.createArrayParamLine("Synonyms: ", alias.getSynonyms()));
+    div.appendChild(self.createLabelText(alias.getDescription()));
+    div.appendChild(self.createAnnotations("Annotations: ", alias.getReferences()));
+
+    return div;
+  })
+};
+
+/**
+ *
+ * @param {SearchBioEntityGroup} group
+ * @returns {Promise<HTMLDivElement>}
+ */
+GuiUtils.prototype.createSearchBioEntityGroupElement = function (group) {
+  if (group.getBioEntities()[0] instanceof Alias) {
+    return this.createAliasElement({alias: group, icon: group.getIcon()});
+  } else {
+    return this.createReactionElement({reaction: group, icon: group.getIcon()});
+  }
+};
+
+/**
+ *
+ * @returns {HTMLAnchorElement}
+ */
+GuiUtils.prototype.createLogoutLink = function () {
+  var logoutLink = document.createElement("a");
+  logoutLink.href = "#";
+  logoutLink.innerHTML = "LOGOUT";
+  logoutLink.id = "logoutLink";
+  logoutLink.onclick = function () {
+    return ServerConnector.logout();
+  };
+  return logoutLink;
+};
+
+/**
+ *
+ * @param {string} params.name
+ * @param {string} params.id
+ * @param {HTMLElement} params.navigationBar
+ *
+ * @returns {HTMLLIElement}
+ */
+GuiUtils.prototype.createTabMenuObject = function (params) {
+  var name = params.name;
+  var id = params.id;
+  var navigationBar = params.navigationBar;
+
+  var navClass = '';
+  if (navigationBar.children.length === 0) {
+    navClass = "active";
+  }
+
+  var navLi = document.createElement("li");
+  navLi.className = navClass;
+
+  var navLink = document.createElement("a");
+  navLink.href = "#" + id;
+  if (name !== undefined) {
+    navLink.innerHTML = name;
+  }
+  navLink.onclick = function () {
+    $(this).tab('show');
+  };
+  navLi.appendChild(navLink);
+  if (name !== undefined) {
+    navLink.innerHTML = name;
+  }
+  return navLi;
+};
+
+/**
+ *
+ * @param {string} params.id
+ * @param {HTMLElement} params.navigationObject
+ *
+ * @returns {HTMLDivElement}
+ */
+GuiUtils.prototype.createTabContentObject = function (params) {
+  var navigationObject = params.navigationObject;
+  var tabId = params.id;
+  var result = document.createElement("div");
+  result.style.height = "100%";
+
+  var contentClass = 'tab-pane';
+  if (navigationObject.className === "active") {
+    contentClass = "tab-pane active";
+  }
+
+  result.className = contentClass;
+  result.id = tabId;
+  return result;
+};
+
+/**
+ *
+ * @param {HTMLElement} [params.element]
+ * @param {string} params.id
+ *
+ * @returns {{element: HTMLElement, menu: HTMLElement, content: HTMLElement, tabId: *}}
+ */
+GuiUtils.prototype.createTabDiv = function (params) {
+  var tabDiv = Functions.createElement({
+    type: "div",
+    name: "tabView",
+    className: "tabbable boxed parentTabs"
+  });
+
+  var tabMenuDiv = Functions.createElement({
+    type: "ul",
+    className: "nav nav-tabs"
+  });
+  tabDiv.appendChild(tabMenuDiv);
+
+  var tabContentDiv = Functions.createElement({
+    type: "div",
+    className: "tab-content"
+  });
+  tabDiv.appendChild(tabContentDiv);
+
+  if (params.element !== undefined) {
+    params.element.appendChild(tabDiv);
+  }
+
+  return {
+    element: tabDiv,
+    menu: tabMenuDiv,
+    content: tabContentDiv,
+    tabId: params.id
+  }
+};
+
+GuiUtils.prototype.createTab = function (params) {
+  var tabData = params.tabData;
+
+  var tabId = tabData.tabId + "_tab_" + tabIdCounter;
+  tabIdCounter++;
+
+  var navClass = '';
+  var contentClass = 'tab-pane';
+  if (tabData.menu.children.length === 0) {
+    navClass = "active";
+    contentClass = "tab-pane active";
+  }
+
+  var navLi = document.createElement("li");
+  navLi.className = navClass;
+
+  var navLink = document.createElement("a");
+  navLink.href = "#" + tabId;
+
+  navLink.innerHTML = params.title;
+
+  navLink.onclick = function () {
+    $(this).tab('show');
+  };
+  navLi.appendChild(navLink);
+  tabData.menu.appendChild(navLi);
+
+  var contentDiv = document.createElement("div");
+  contentDiv.style.height = "100%";
+  contentDiv.className = contentClass;
+  contentDiv.id = tabId;
+
+  if (Functions.isDomElement(params.content)) {
+    contentDiv.appendChild(params.content);
+  } else {
+    contentDiv.innerHTML = params.content;
+  }
+  tabData.content.appendChild(contentDiv);
+
+  $(contentDiv).css("overflow", "auto");
+  $(contentDiv).css("height", "calc(100vh - " + $(contentDiv).offset().top + "px)");
+
+  return {
+    title: navLink,
+    content: contentDiv
+  }
+};
+
+/**
+ *
+ * @param {string} toolTip
+ * @param {boolean} [useXss=false]
+ * @returns {HTMLElement}
+ */
+GuiUtils.prototype.createHelpButton = function (toolTip, useXss) {
+  var helpContent;
+  if (useXss) {
+    helpContent = xss(toolTip);
+  } else {
+    helpContent = toolTip;
+  }
+
+  var helpTipButton = Functions.createElement({
+    type: "button",
+    className: "minerva-help-button",
+    content: '<span class="ui-icon ui-icon-help" style="margin-left: -0.5em;"/>',
+    xss: false
+  });
+  var helpDialogDiv = undefined;
+  helpTipButton.onclick = function () {
+    if (helpDialogDiv === undefined) {
+      helpDialogDiv = Functions.createElement({
+        type: "div",
+        content: helpContent,
+        xss: false
+      });
+      $(helpDialogDiv).dialog({
+        close: function () {
+          $(this).dialog('destroy').remove();
+          helpDialogDiv = undefined;
+        },
+        position: {
+          my: "left top",
+          at: "left bottom",
+          of: helpTipButton
+        }
+      });
+      $('.ui-dialog').find("a").blur();
+    }
+  };
+  return helpTipButton;
+};
+
+/**
+ * @param {AbstractGuiElement} abstractGuiElement
+ */
+GuiUtils.prototype.initTabContent = function (abstractGuiElement) {
+  if (abstractGuiElement._panels !== undefined) {
+    throw new Error("Tabs were already initialized");
+  }
+
+  abstractGuiElement._panels = [];
+  abstractGuiElement._tabIdCount = 0;
+
+  var tabDiv = Functions.createElement({
+    type: "div",
+    name: "tabView",
+    className: "tabbable boxed parentTabs"
+  });
+  abstractGuiElement.getElement().appendChild(tabDiv);
+
+  tabDiv.appendChild(Functions.createElement({
+    type: "ul",
+    className: "nav nav-tabs"
+  }));
+
+  tabDiv.appendChild(Functions.createElement({
+    type: "div",
+    className: "tab-content"
+  }));
+};
+
+/**
+ *
+ * @param {AbstractGuiElement} abstractGuiElement
+ * @param {Object} params
+ * @param {string} params.name
+ * @param {function} params.panelClass
+ */
+GuiUtils.prototype.addTab = function (abstractGuiElement, params) {
+  var tabId = "admin_panel_tab_" + abstractGuiElement._tabIdCount;
+  abstractGuiElement._tabIdCount++;
+
+  var navElement = $(abstractGuiElement.getElement()).find("> .parentTabs > .nav-tabs")[0];
+  var contentElement = $(abstractGuiElement.getElement()).find("> .parentTabs > .tab-content")[0];
+
+  var navLi = this.createTabMenuObject({
+    id: tabId,
+    name: params.name,
+    navigationBar: navElement
+  });
+  navElement.appendChild(navLi);
+
+  var contentDiv = this.createTabContentObject({
+    id: tabId,
+    navigationObject: navLi
+  });
+
+  contentElement.appendChild(contentDiv);
+
+  abstractGuiElement._panels.push(new params.panelClass({
+    element: contentDiv,
+    name: params.name,
+    configuration: this.getConfiguration(),
+    serverConnector: abstractGuiElement.getServerConnector()
+  }));
+};
+
+module.exports = GuiUtils;