From 318b396affcf5dbdc0ebb4282ce203c840fe3a45 Mon Sep 17 00:00:00 2001
From: Iker Hurtado <iker@ikerhurtado.com>
Date: Sun, 11 Nov 2018 20:03:58 +0100
Subject: [PATCH] Search by Material name last improvements

---
 client/bundle.js                      | 18204 ++++++++++++------------
 client/src/search-mod/NewSearchMod.js |    62 +-
 2 files changed, 9167 insertions(+), 9099 deletions(-)

diff --git a/client/bundle.js b/client/bundle.js
index 44b65420..9c7c32e5 100644
--- a/client/bundle.js
+++ b/client/bundle.js
@@ -1,9917 +1,9977 @@
 /******/ (function(modules) { // webpackBootstrap
 /******/ 	// The module cache
 /******/ 	var installedModules = {};
-
+/******/
 /******/ 	// The require function
 /******/ 	function __webpack_require__(moduleId) {
-
+/******/
 /******/ 		// Check if module is in cache
-/******/ 		if(installedModules[moduleId])
+/******/ 		if(installedModules[moduleId]) {
 /******/ 			return installedModules[moduleId].exports;
-
+/******/ 		}
 /******/ 		// Create a new module (and put it into the cache)
 /******/ 		var module = installedModules[moduleId] = {
-/******/ 			exports: {},
-/******/ 			id: moduleId,
-/******/ 			loaded: false
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
 /******/ 		};
-
+/******/
 /******/ 		// Execute the module function
 /******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
-
+/******/
 /******/ 		// Flag the module as loaded
-/******/ 		module.loaded = true;
-
+/******/ 		module.l = true;
+/******/
 /******/ 		// Return the exports of the module
 /******/ 		return module.exports;
 /******/ 	}
-
-
+/******/
+/******/
 /******/ 	// expose the modules object (__webpack_modules__)
 /******/ 	__webpack_require__.m = modules;
-
+/******/
 /******/ 	// expose the module cache
 /******/ 	__webpack_require__.c = installedModules;
-
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, {
+/******/ 				configurable: false,
+/******/ 				enumerable: true,
+/******/ 				get: getter
+/******/ 			});
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
 /******/ 	// __webpack_public_path__
 /******/ 	__webpack_require__.p = "";
-
+/******/
 /******/ 	// Load entry module and return exports
-/******/ 	return __webpack_require__(0);
+/******/ 	return __webpack_require__(__webpack_require__.s = 16);
 /******/ })
 /************************************************************************/
 /******/ ([
 /* 0 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-	   This file is the application entry point.
-	   It defines some app level components (Breadcrumb) and
-	   initializes several more (app level events, app routing, authentication)
-	 */
-
-
-	"use strict";
-
-	let util = __webpack_require__(1);
-	let LoadingPopup = __webpack_require__(4);
-	let FlaggingFormPopup = __webpack_require__(5);
-	let PubSub = __webpack_require__(6);
-	let Router = __webpack_require__(7);
-	let MaterialMod = __webpack_require__(8);
-	let SearchModule = __webpack_require__(32);
-	let UserGuidance = __webpack_require__(33);
-	let DataStore = __webpack_require__(2);
-
-
-	// main DOM elements
-	let contentElement = document.getElementById('content');
-	let titleElement = document.querySelector('title');
-
-
-	/********* User flagging side tab ****************/
-
-	/* This side vertical tab is hidden initially
-	   but it has to be set up when the app starts */
-
-	let flaggingTab = document.getElementById('calc-flagging-tab');
-	flaggingTab.style.top = (window.innerHeight/2)+'px';
-
-	flaggingTab.addEventListener('click',e => {
-	  FlaggingFormPopup.show(MaterialModule.getCurrentPageStatus());
-	});
-
-
-
-	/*********** App Breadcrumb component definition ***************/
-
-	class Breadcrumb {
-
-	  constructor() {
-
-	    this.element = document.querySelector('#breadcrumb-placeholder');
-	    this.element.innerHTML = `
-	      <span class="goto-page Search">Search</span>
-	      <span class="goto-page Overview">&nbsp; > &nbsp; <span>Overview</span></span>
-	      <span class="Details">
-	        &nbsp; > &nbsp;
-	        <select class="details-dropdown" >
-	          <option value="structure">Structure</option>
-	          <option value="electronicstruct">Electronic structure</option>
-	          <option value="methodology">Methodology</option>
-	          <option value="thermalprops">Thermal Properties</option>
-	          <!-- elasticconst-->
-	        </select>
-	      </span>
-	    `;
-	    this.overviewSel = this.element.querySelector('.Overview');
-	    this.detailsSel = this.element.querySelector('.Details');
-	    this.detailsDropDown = this.element.querySelector('.details-dropdown');
-
-	    // Events
-	    this.element.querySelector('.Search').addEventListener( "click", e => {
-	      util.setBrowserHashPath('search');
-	    });
-
-	    this.overviewSel.addEventListener('click', () => {
-	      util.setBrowserHashPath('material', util.materialId);
-	    });
-
-	    this.detailsDropDown.addEventListener('change', e => {
-	      util.setBrowserHashPath('material',
-	        DataStore.getMaterialData().id+'/'+e.target.value);
-	    });
-
-	    let self = this;
-	    function adjustDropdownOptions() {
-	      let esOption = self.detailsDropDown.querySelector('option[value="electronicstruct"]');
-	      if (!DataStore.hasElecStructureData) self.detailsDropDown.removeChild(esOption);
-
-	      let thOption = self.detailsDropDown.querySelector('option[value="thermalprops"]');
-	      if (!DataStore.hasThermalData) self.detailsDropDown.removeChild(thOption);
-	      // Remove because we want it's executed once
-	      self.detailsDropDown.removeEventListener('focus', adjustDropdownOptions);
-	    }
-
-	    this.detailsDropDown.addEventListener('focus', adjustDropdownOptions);
-	  }
-
-
-	  setState(appModule, param){
-	    let overviewSelLabel = this.overviewSel.querySelector('span');
-	    overviewSelLabel.style.fontWeight = 'normal';
-
-	    if (appModule === 'search'){
-	      this.overviewSel.style.display = 'none';
-	      this.detailsSel.style.display = 'none';
-
-	      /*
-	      if (param === 'results'){
-	        this.resultsSel.style.display = 'inline';
-	        this.resultsSel.querySelector('span').style.fontWeight = 'bold';
-	        this.element.style.visibility = 'visible';
-	      }else   this.element.style.visibility = 'hidden';
-	      */
-	      this.element.style.visibility = 'hidden';
-
-	    }else if (appModule === 'material'){
-	      this.element.style.visibility = 'visible';
-	      this.overviewSel.style.display = 'inline';
-
-	      if (param === undefined){ // Overview page
-	        this.detailsSel.style.display = 'none';
-	        overviewSelLabel.style.fontWeight = 'bold';
-	      }else{ // Details page
-	        this.detailsSel.style.display = 'inline';
-	        this.detailsDropDown.value = param;
-	      }
-	    }
-	  } // setState
-
-	} // class Breadcrumb
-
-
-	/***************************
-	         App setup
-	***************************/
-
-	let breadcrumb = new Breadcrumb();
-
-	let searchMod;
-	let MaterialModule;
-	let materialModDOM;
-	let currentModule; // current module DOM being shown
-
+/***/ (function(module, exports, __webpack_require__) {
 
-	function showModuleDOM(module){
-	  if (currentModule) contentElement.removeChild(currentModule);
-	  currentModule= module;
-	  contentElement.appendChild(currentModule);
-	}
-
-
-	/******  App level events setup ********/
-
-	PubSub.subscribe('show-material', data => {
-	  console.log('Handling event show-material: '+data.id+' view: '+data.view);
+"use strict";
 
-	  //titleElement.innerHTML = 'NOMAD Encyclopedia - Material '+data.id;
-	  breadcrumb.setState('material',data.view);
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
 
-	  if (typeof materialModDOM === 'undefined'){
-	    MaterialModule = new MaterialMod();
-	    materialModDOM= MaterialModule.element;
-	  }
-	  MaterialModule.setMaterialView(data);
-	  showModuleDOM(materialModDOM);
-
-	  // In case the app comes from the search module through the url (back button)
-	  UserGuidance.show(false);
 
-	  //console.log('User data:',util.getUserData());
-	  if (util.getUserData() !== null) flaggingTab.style.visibility = 'visible';
-	});
+ /*
+   This is an app-level utility JavaScript file. It holds:
 
+      - Environments conf (API URL and user cookie domain configuration)
+        * Maybe this conf info can be removed from here to a better place
+      - global state variables and app-level constants
+      - miscellaneous app-level function
+      - local vars
+      - app-level util functions
 
-	PubSub.subscribe('show-search', search => {
-	  console.log('Handling event show-search: '+search);
+   * Maybe this file should be rethought
+ */
 
-	  titleElement.innerHTML = 'NOMAD Encyclopedia - Search';
-	  breadcrumb.setState('search',search);
 
-	  if (search === undefined){
-	    searchMod.showSearchPage();
-	    LoadingPopup.hide();  // In case it comes from the result page
 
-	  }//else if (search === 'results')  searchMod.showSearchResults();
 
-	  showModuleDOM(searchMod.element);
+let DataStore = __webpack_require__(1);
+let Conf = __webpack_require__(17);
 
-	  if (flaggingTab.style.visibility !== 'hidden')
-	    flaggingTab.style.visibility = 'hidden';
-	});
 
+// global state vars
+let materialId = null;
 
 
-	/******  App routing config  ******/
+// app-level constants
 
-	Router.add('search', search => PubSub.publish('show-search', search));
-	Router.add('material', (matId, view) => PubSub.publish('show-material', {'id': matId, 'view': view}));
+const IMAGE_DIR = 'img/';
 
+const AUTH_REQUEST_HEADER_GUEST_USER = 'Basic '+ btoa(Conf.GuestUserToken+':');
 
+const MAT_VIEW = {
+  'structure' : 'structure',
+  'electronicstruct': 'electronicstruct',
+  'methodology': 'methodology',
+  'thermalprops': 'thermalprops',
+  'elasticconst': 'elasticconst'
+};
 
-	/****** init ******/
+let ELEMENTS = [
+  'H', 'He', 'Li', 'Be', 'B', 'C', 'N', 'O', 'F', 'Ne', 'Na', 'Mg', 'Al', 'Si',  // Si = 14
+  'P', 'S', 'Cl', 'Ar', 'K', 'Ca', 'Sc', 'Ti', 'V', 'Cr', 'Mn', 'Fe', 'Co', 'Ni', // Nin = 28
+  'Cu', 'Zn', 'Ga', 'Ge', 'As', 'Se', 'Br', 'Kr', 'Rb', 'Sr', 'Y', 'Zr', 'Nb',  // Nb = 41
+  'Mo', 'Tc', 'Ru', 'Rh', 'Pd', 'Ag', 'Cd', 'In', 'Sn', 'Sb', 'Te', 'I', 'Xe',  // Xe = 54
+  'Cs', 'Ba', 'La', 'Ce', 'Pr', 'Nd', 'Pm', 'Sm', 'Eu', 'Gd', 'Tb', 'Dy', 'Ho', // Ho= 67
+  'Er', 'Tm', 'Yb', 'Lu', 'Hf', 'Ta', 'W', 'Re', 'Os', 'Ir', 'Pt', 'Au', 'Hg',  // Hg = 80
+  'Tl', 'Pb', 'Bi', 'Po', 'At', 'Rn', 'Fr', 'Ra', 'Ac', 'Th', 'Pa', 'U', 'Np',  // Np = 93
+  'Pu', 'Am', 'Cm', 'Bk', 'Cf', 'Es', 'Fm', 'Md', 'No', 'Lr', 'Rf', 'Ha', 'Sg', // sg = 106
+  'Ns', 'Hs', 'Mt', 'Ds', 'Rg', 'Cn', 'Nh', 'Fl', 'Mc', 'Lv', 'Ts', 'Og' // Mt = 109
+];
 
-	searchMod = new SearchModule();
 
-	//console.log('document.location: '+document.location.hash);
-	if (document.location.hash === '') document.location += "#/search";
-	Router.route();
+// API URL and user cookie domain configuration
 
+// Case 1: my local dev environment
+let  API_HOST= 'http://enc-staging-nomad.esc.rzg.mpg.de/';
+let USER_COOKIE_DOMAIN = 'localhost';
+let path = 'current/v1.0/'; // current development version of the API
+// let path = 'v1.0/'; // stable staging
 
-	/********* User authentication ***********/
+// Case 2: production environment
+if (document.location.href.indexOf('nomad-coe.eu') > 0){//
+  API_HOST='https://encyclopedia.nomad-coe.eu/';
+  USER_COOKIE_DOMAIN = '.nomad-coe.eu';
+  path = 'api/v1.0/';
+}
+ // Case 3: testing-staging environment and local installations (docker containers) of full Encyclopedia stack
+else if (document.location.href.indexOf('gui') > 0){
+  API_HOST= '/'; //  USER_COOKIE_DOMAIN = 'localhost' and path = 'v1.0/';
+  if (document.location.href.indexOf('staging') > 0) // testing-staging server
+    USER_COOKIE_DOMAIN = '.mpg.de';
+}
 
-	let userNameElement = document.querySelector('#user-name');
-	let logoutButton = document.querySelector('#logout-button');
+let API_BASE_URL = API_HOST + path;
+//console.log('API host: ',API_HOST,'  USER_COOKIE_DOMAIN: ',USER_COOKIE_DOMAIN);
 
-	function setAppAuthenticated(data){
-	  if (data.status === 'Authenticated'){
-	    userNameElement.innerHTML = data.user.username;
-	    document.querySelector('#guest-user').style.display = 'none';
-	    document.querySelector('#auth-user').style.display = 'inline';
-	    util.setAuthRequestHeader(data.user, data.token.data);
-	    if (currentModule === materialModDOM) flaggingTab.style.visibility = 'visible';
-	  }
-	}
+document.querySelector('#guest-user a').href = API_BASE_URL+'saml/?sso2';
 
 
-	function setAppLoggedOut(){
-	  userNameElement.innerHTML = '';
-	  document.querySelector('#guest-user').style.display = 'inline';
-	  document.querySelector('#auth-user').style.display = 'none';
-	  util.setAuthRequestHeader();
+// Mockup URLs
+//const FERMI_SURFACE_URL= HOST+'files/fermi/'+
+//'fed3fa9fbc68aa6c5e51845396889666ca37bb2e626e1da53.x3d';
 
-	  if (flaggingTab.style.visibility !== 'hidden')
-	    flaggingTab.style.visibility = 'hidden';
-	}
 
 
-	function getCookie(name) {
-	  let value = "; " + document.cookie;
-	  let parts = value.split("; " + name + "=");
-	  if (parts.length === 2) return parts.pop().split(";").shift();
-	}
+// Local variables
 
+let authRequestHeaderValue = AUTH_REQUEST_HEADER_GUEST_USER;
+//console.log('user: ANONYMOUS  authRequestHeader: ',authRequestHeaderValue);
+let userData = null;
 
-	function parseCookie(userData) {
-	  return userData.substring(1, userData.length-1).replace(/\\054/g,',').replace(/\\/g,'');
-	}
 
+// app-level util functions
 
-	let userInfoCookie = getCookie('user_info');
-	//console.log('Cookies: ', document.cookie, userInfoCookie);
+function getUserData(){
+  return userData;
+}
 
-	if (userInfoCookie !== undefined){
-	  let userInfoData = JSON.parse(parseCookie(userInfoCookie));
-	  //console.log('userInfoData: ', userInfoData);
-	  setAppAuthenticated(userInfoData);
-	}
 
+function getServerLocation(){
+  return document.location.hostname;
+}
 
-	// Logout
-	logoutButton.addEventListener( "click", e => {
 
-	  document.cookie='user_info=; expires=Thu, 01 Jan 1970 00:00:00 GMT; domain='+
-	    util.USER_COOKIE_DOMAIN+'; path=/';
-	  //console.log('Logging out document.cookie ',document.cookie);
+function authServerReq(url, callback){
+  var oReq = new XMLHttpRequest();
+  oReq.addEventListener("load", callback);
+  console.log('util.authServerReq: ', API_BASE_URL+url);
+  oReq.open("GET", API_BASE_URL+url);
+  //console.log('util.authServerReq oReq: ', oReq);
+  oReq.send();
+  return oReq;
+}
 
-	  setAppLoggedOut();
-	  //console.log('Logging out ',userNameElement.innerHTML);
-	});
 
+function setAuthRequestHeader(userDataP, value){
 
-/***/ },
+  if (value === undefined){// default value
+    authRequestHeaderValue = AUTH_REQUEST_HEADER_GUEST_USER;
+    userData = null;
+    //console.log('user: ANONYMOUS  authRequestHeader: ',authRequestHeaderValue);
+  } else{
+    authRequestHeaderValue = 'Basic '+ btoa(value+':');
+    userData = userDataP;
+    //console.log('user',user,'authRequestHeader: ',authRequestHeaderValue);
+  }
+}
+
+
+function serverReq(url, callback){
+  var oReq = new XMLHttpRequest();
+  oReq.addEventListener("load", callback);
+  oReq.open("GET", url);
+  //console.log('authRequestHeaderValue: ',authRequestHeaderValue);
+  oReq.setRequestHeader('Authorization', authRequestHeaderValue);
+  oReq.send();
+  return oReq;
+}
+
+
+function serverReqPOST(url, data, callback){
+  var oReq = new XMLHttpRequest();
+  oReq.addEventListener('load', callback);
+  oReq.open('POST', url);
+  oReq.setRequestHeader('Content-Type', 'application/json');
+  //console.log('authRequestHeaderValue: ',authRequestHeaderValue);
+  oReq.setRequestHeader('Authorization', authRequestHeaderValue);
+  oReq.send(data);
+  return oReq;
+}
+
+
+function getSubscriptedFormula(formula){
+  let finalFormula= '';  // 'elementCode' :  number
+  for (let i = 0; i < formula.length; i++){
+    if (formula.charCodeAt(i) >= 47 && formula.charCodeAt(i) < 58 )
+      finalFormula += '<sub>'+formula[i]+'</sub>';
+    else finalFormula += formula[i];
+    //console.log(formula.charCodeAt(i) + " "+finalFormula);
+  }
+  return finalFormula;
+}
+
+
+function getSearchURL(){
+  return API_BASE_URL+'esmaterials';
+}
+
+function getSuggestionURL(quantity){
+  return API_BASE_URL+'suggestions?property='+quantity;
+}
+
+function getMaterialURL(matId){
+  return API_BASE_URL+'materials/'+matId;//'/materials/matid'; //
+}
+
+function getMaterialCalcURL(matId, calcId, property = ''){
+  let propertyString = (property === '' ? '' : '?property='+property);
+  return API_BASE_URL+'materials/'+matId+'/calculations/'+calcId+propertyString;
+}
+
+function getMaterialXsURL(what, matId){
+  return API_BASE_URL+'materials/'+matId+'/'+what+'?pagination=off';//page=1&per_page=5000';//'/materials/calculations';//
+}
+
+function getCalcEnergiesURL(matId,calcId){
+  return API_BASE_URL+'materials/'+matId+'/calculations/'+calcId+'/energies';//'/materials/calculations';//
+}
+
+function getFlaggingURL(){
+  return API_BASE_URL+'flagme';
+}
+
+
+// Launch an app event
+function setBrowserHashPath(modulePath, finalPath){
+  if (typeof finalPath === 'undefined') document.location= '#/'+modulePath;
+  else document.location= '#/'+modulePath+'/'+finalPath;
+}
+
+function loadLib(url){
+  let script = document.createElement('script');
+  script.setAttribute('type', 'text/javascript');
+  script.setAttribute('src', url);
+  document.getElementsByTagName('head')[0].appendChild(script);
+}
+
+function getNumberArray(string){
+  let sArray= string.substring(1,string.length-1).split(',');
+  let fArray= [];
+  for (var i = 0; i < sArray.length; i++) {
+    fArray.push(parseFloat(sArray[i]));
+  }
+  //console.log('getNumberArray.SPLIT: '+fArray);
+  return fArray;
+}
+
+function getCellDataForViewer(matData){
+  let cellData= {};
+  cellData.normalizedCell= [
+    getNumberArray(matData.cell.a),
+    getNumberArray(matData.cell.b),
+    getNumberArray(matData.cell.c)
+  ];
+
+  cellData.periodicity = JSON.parse(matData.periodicity);
+
+  cellData.labels= [];
+  cellData.positions= [];
+
+  for (var i = 0; i < matData.elements.length; i++) {
+    cellData.labels.push(matData.elements[i].label);
+    cellData.positions.push(getNumberArray(matData.elements[i].position));
+  }
+  return cellData;
+}
+
+
+function J2eV(energy, decimals){
+  let result= energy/1.602176565e-19;
+  if (decimals === undefined){
+    if (result < 0.01) return result.toFixed(6);
+    else  return result.toFixed(3);
+  }else{
+    return result.toFixed(decimals);
+  }
+}
+
+function eV2J(energy){
+  return energy*1.602176565e-19;
+}
+
+
+/*
+function getBandGapStatsValue(calcs){
+  let bandGapSum= 0;
+  let bandArray= [];
+  let bandGapDirect= calcs[0].band_gap_direct;
+  let bandGapType= (bandGapDirect ? "direct" : "indirect");
+
+  for (var i = 0; i < calcs.length; i++) {
+    //if (calcs[i].band_gap > 0){
+      bandGapSum+= calcs[i].band_gap;
+      bandArray.push(calcs[i].band_gap);
+      if (calcs[i].band_gap_direct !== bandGapDirect)
+        bandGapType= 'various results';
+    //}
+    //console.log(bandGapSum+'  '+calcs[i].band_gap+' '+bandArray.length);
+  }
+
+  let html= '';//let html= ((bandGapSum / bandArray.length)/1.602176565e-19).toFixed(3)+' eV ('+bandGapType+')';;
+  let min= (Math.min.apply(null, bandArray)/1.602176565e-19).toFixed(3);
+  let max= (Math.max.apply(null, bandArray)/1.602176565e-19).toFixed(3);
+    html+= '&nbsp;('+min+' ... '+max+' eV)';
+   //html+= '&nbsp;&nbsp;&nbsp;['+bandArray.length+' / '+calcs.length+']';
+
+  return html;
+}*/
+
+function m2Angstrom(dist){
+  return (dist/1e-10).toFixed(3)+' &#197;';
+}
+
+
+function getLatticeAnglesValues(calcs, twoD, bulk){
+  let lattParams= [0.0, 0.0, 0.0];
+  calcs.forEach( (calc) => {
+    if (calc.lattice_parameters !== undefined && calc.lattice_parameters !== null){
+      let tempLattParams= getNumberArray(calc.lattice_parameters);
+      lattParams[0] += tempLattParams[3];
+      lattParams[1] += tempLattParams[4];
+      lattParams[2] += tempLattParams[5];
+    }
+  });
+
+  if (bulk)
+    return `<div>&alpha; = ${rad2degree(lattParams[0] / calcs.size)}</div>
+    <div>&beta; = ${rad2degree(lattParams[1] / calcs.size)}</div>
+    <div>&gamma; = ${rad2degree(lattParams[2] / calcs.size)}</div>`;
+  else if (twoD)
+    return `<div>&alpha; = ${rad2degree(lattParams[0] / calcs.size)}</div>`;
+  else return ''; // 1D
+}
+
+
+function rad2degree(angle){
+  return (angle * (180 / Math.PI)).toFixed(0)+'&deg;';
+}
+
+function m3ToAngstrom3(vol){
+  return (vol/1e-30).toFixed(3)+' &#197;<sup>3</sup>';
+}
+
+
+function getAverage(array){
+  let sum = 0;
+  for (var i = 0; i < array.length; i++) sum += array[i];
+  return sum/array.length;
+}
+
+
+function getQuantityStatsMap(calcs){
+
+  let quantities = ['volume', 'atomic_density', 'mass_density', 'lattice_a', 'lattice_b', 'lattice_c'];
+  let labels = ['Volume (ų)', 'Atomic density (Å⁻³)', 'Mass density (kg/m³)', 'a (Å)', 'b (Å)', 'c (Å)'];
+  let quantitiesMap = new Map();
+
+  if (calcs.values().next().value.cell_volume === null){ // not bulk type volume of a calc null
+    quantities = ['lattice_a', 'lattice_b', 'lattice_c'];
+    labels = ['a (Å)', 'b (Å)', 'c (Å)'];
+  }
+
+  quantities.forEach( (quantity, index) => {
+    let array= [];
+    calcs.forEach( calc => {
+      let value;
+      if (quantity === 'volume') value = calc.cell_volume/1e-30;
+      else if (quantity === 'atomic_density') value = calc.atomic_density*1e-30;
+      else if (quantity === 'mass_density') value = calc.mass_density;
+      else if (quantity.indexOf('lattice') >= 0){
+        let tempLattParams= getNumberArray(calc.lattice_parameters);
+        if (quantity === 'lattice_a') value = tempLattParams[0]/1e-10;
+        else if (quantity === 'lattice_b') value = tempLattParams[1]/1e-10;
+        else if (quantity === 'lattice_c') value = tempLattParams[2]/1e-10;
+      }
+      array.push(value);
+    });
+    let stats = {};
+    stats.data = array;
+    stats.min = Math.min.apply(null, array);
+    stats.max = Math.max.apply(null, array);
+    stats.equal = (stats.min === stats.max);
+    let lls = labels[index].split(':');
+    stats.label = lls[0];
+    if (lls.length === 2)  stats.units = lls[1];
+    else stats.units = '';
+
+    let decimals = 3;
+    if (quantity === 'mass_density') decimals = 1;
+    stats.html = getAverage(stats.data).toFixed(decimals)+
+      ' &nbsp; <span style="font-size: 0.9em">['+stats.min.toFixed(decimals)
+      +' , '+stats.max.toFixed(decimals)+']</span>';
+
+    quantitiesMap.set(quantity, stats);
+  });
+  return quantitiesMap;
+}
+
+
+function toAngstromMinus3(density){
+  return (density*1e-30).toFixed(3)+' &#197;<sup>-3</sup>';
+}
+
+
+function getMaterialTitle(data, html){
+  let title;
+  title = getSubscriptedFormula(data.formula_reduced);
+  if (html !== undefined && html ===false)   title = data.formula_reduced;
+
+  if (data.space_group_number !== null)
+    title += ' - space group '+data.space_group_number;
+  //return '<span style="font-size: 0.9em">'+title+' </span>';
+  return title;
+}
+
+function getMinMaxHTML(calcs,prop){
+  let propArray= [];
+
+  calcs.forEach( (calc) => {
+    propArray.push(calc[prop]);
+  });
+
+  return '('+Math.min.apply(null, propArray)+' ... '+Math.max.apply(null, propArray)+')';
+}
+
+
+function generateDiagramSteps(maxVal){
+
+  let d = 4; // generates 0 and 4 more points
+  let exp = -Math.floor(Math.log(maxVal/d) * Math.LOG10E);
+
+  let factor = Math.pow(10,exp);//100;
+  //console.log('util.generateDiagramSteps  ',exp, maxVal/d, factor);
+  let ceil = Math.ceil(maxVal*factor/d);
+  let stepArray = [];
+  for (var i = 0; i <= d; i++) {
+    stepArray[i] = ceil*i/factor;
+  }
+  //console.log('stepArray '+stepArray);
+  exp = (exp < 0 ? 0 : exp);
+  return [stepArray, exp];
+}
+
+
+
+/*
+function addBandGapData(calcJson, bsData){
+  if (calcJson.band_gap > 0) {
+    bsData.bandGapData = {};
+    bsData.bandGapData.cbmEnergy = calcJson.band_gap_lower_energy;
+    bsData.bandGapData.cbmKpt = getNumberArray(calcJson.band_gap_lower_kpt);
+    bsData.bandGapData.vbmEnergy = calcJson.band_gap_upper_energy;
+    bsData.bandGapData.vbmKpt = getNumberArray(calcJson.band_gap_upper_kpt);
+  }
+}*/
+
+/*
+function is2DSystem_temporary_patch(){
+
+//console.log('TEMPORARY PATCH is2DSystem:', DataStore.getMaterialData());
+  return DataStore.getMaterialData().system_type === '2D';
+}
+*/
+
+
+module.exports = {
+  materialId,
+  MAT_VIEW: MAT_VIEW,
+  IMAGE_DIR: IMAGE_DIR,
+  USER_COOKIE_DOMAIN,
+  ELEMENTS: ELEMENTS,
+  setAuthRequestHeader,
+  getUserData,
+  getServerLocation,
+  authServerReq,
+  serverReq,
+  serverReqPOST,
+  getSearchURL: getSearchURL,
+  getSuggestionURL,
+  getMaterialURL: getMaterialURL,
+  getMaterialCalcURL: getMaterialCalcURL,
+  getMaterialXsURL: getMaterialXsURL,
+  getCalcEnergiesURL: getCalcEnergiesURL,
+  getFlaggingURL,
+  setBrowserHashPath: setBrowserHashPath,
+  loadLib: loadLib,
+  getNumberArray: getNumberArray,
+  getCellDataForViewer: getCellDataForViewer,
+  //FERMI_SURFACE_URL: FERMI_SURFACE_URL,
+  J2eV: J2eV,
+  eV2J,
+  //getBandGapStatsValue: getBandGapStatsValue,
+  m2Angstrom: m2Angstrom,
+  getLatticeAnglesValues: getLatticeAnglesValues,
+  rad2degree: rad2degree,
+  m3ToAngstrom3: m3ToAngstrom3,
+  getQuantityStatsMap: getQuantityStatsMap,
+  toAngstromMinus3,
+  getMaterialTitle,
+  getMinMaxHTML: getMinMaxHTML,
+  getSubscriptedFormula: getSubscriptedFormula,
+  getAverage,
+  generateDiagramSteps,
+  //is2DSystem_temporary_patch
+  //addBandGapData
+}
+
+
+/***/ }),
 /* 1 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-	   This is an app-level utility JavaScript file. It holds:
-
-	      - Environments conf (API URL and user cookie domain configuration)
-	        * Maybe this conf info can be removed from here to a better place
-	      - global state variables and app-level constants
-	      - miscellaneous app-level function
-	      - local vars
-	      - app-level util functions
-
-	   * Maybe this file should be rethought
-	 */
-
-
-	"use strict";
-
-	let DataStore = __webpack_require__(2);
-	let Conf = __webpack_require__(3);
-
-
-	// global state vars
-	let materialId = null;
-
-
-	// app-level constants
-
-	const IMAGE_DIR = 'img/';
-
-	const AUTH_REQUEST_HEADER_GUEST_USER = 'Basic '+ btoa(Conf.GuestUserToken+':');
-
-	const MAT_VIEW = {
-	  'structure' : 'structure',
-	  'electronicstruct': 'electronicstruct',
-	  'methodology': 'methodology',
-	  'thermalprops': 'thermalprops',
-	  'elasticconst': 'elasticconst'
-	};
-
-	let ELEMENTS = [
-	  'H', 'He', 'Li', 'Be', 'B', 'C', 'N', 'O', 'F', 'Ne', 'Na', 'Mg', 'Al', 'Si',  // Si = 14
-	  'P', 'S', 'Cl', 'Ar', 'K', 'Ca', 'Sc', 'Ti', 'V', 'Cr', 'Mn', 'Fe', 'Co', 'Ni', // Nin = 28
-	  'Cu', 'Zn', 'Ga', 'Ge', 'As', 'Se', 'Br', 'Kr', 'Rb', 'Sr', 'Y', 'Zr', 'Nb',  // Nb = 41
-	  'Mo', 'Tc', 'Ru', 'Rh', 'Pd', 'Ag', 'Cd', 'In', 'Sn', 'Sb', 'Te', 'I', 'Xe',  // Xe = 54
-	  'Cs', 'Ba', 'La', 'Ce', 'Pr', 'Nd', 'Pm', 'Sm', 'Eu', 'Gd', 'Tb', 'Dy', 'Ho', // Ho= 67
-	  'Er', 'Tm', 'Yb', 'Lu', 'Hf', 'Ta', 'W', 'Re', 'Os', 'Ir', 'Pt', 'Au', 'Hg',  // Hg = 80
-	  'Tl', 'Pb', 'Bi', 'Po', 'At', 'Rn', 'Fr', 'Ra', 'Ac', 'Th', 'Pa', 'U', 'Np',  // Np = 93
-	  'Pu', 'Am', 'Cm', 'Bk', 'Cf', 'Es', 'Fm', 'Md', 'No', 'Lr', 'Rf', 'Ha', 'Sg', // sg = 106
-	  'Ns', 'Hs', 'Mt', 'Ds', 'Rg', 'Cn', 'Nh', 'Fl', 'Mc', 'Lv', 'Ts', 'Og' // Mt = 109
-	];
-
-
-	// API URL and user cookie domain configuration
-
-	// Case 1: my local dev environment
-	let  API_HOST= 'http://enc-staging-nomad.esc.rzg.mpg.de/';
-	let USER_COOKIE_DOMAIN = 'localhost';
-	let path = 'current/v1.0/'; // current development version of the API
-	// let path = 'v1.0/'; // stable staging
-
-	// Case 2: production environment
-	if (document.location.href.indexOf('nomad-coe.eu') > 0){//
-	  API_HOST='https://encyclopedia.nomad-coe.eu/';
-	  USER_COOKIE_DOMAIN = '.nomad-coe.eu';
-	  path = 'api/v1.0/';
-	}
-	 // Case 3: testing-staging environment and local installations (docker containers) of full Encyclopedia stack
-	else if (document.location.href.indexOf('gui') > 0){
-	  API_HOST= '/'; //  USER_COOKIE_DOMAIN = 'localhost' and path = 'v1.0/';
-	  if (document.location.href.indexOf('staging') > 0) // testing-staging server
-	    USER_COOKIE_DOMAIN = '.mpg.de';
-	}
-
-	let API_BASE_URL = API_HOST + path;
-	//console.log('API host: ',API_HOST,'  USER_COOKIE_DOMAIN: ',USER_COOKIE_DOMAIN);
-
-	document.querySelector('#guest-user a').href = API_BASE_URL+'saml/?sso2';
-
-
-	// Mockup URLs
-	//const FERMI_SURFACE_URL= HOST+'files/fermi/'+
-	//'fed3fa9fbc68aa6c5e51845396889666ca37bb2e626e1da53.x3d';
-
-
-
-	// Local variables
-
-	let authRequestHeaderValue = AUTH_REQUEST_HEADER_GUEST_USER;
-	//console.log('user: ANONYMOUS  authRequestHeader: ',authRequestHeaderValue);
-	let userData = null;
-
-
-	// app-level util functions
-
-	function getUserData(){
-	  return userData;
-	}
-
+/***/ (function(module, exports) {
+
+
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+ /*
+  This file create and holds the application data models.
+  It stores the data loaded from the backend (immutable).
+  In addition it creates app life-time entities for convenience
+ */
+
+
+let materialData;
+
+function setMaterialData(dataFromAPI){
+  materialData = dataFromAPI;
+}
+
+function getMaterialData(){
+  return materialData;
+}
+
+
+let calcs;
+let calcMap = new Map();
+
+function setCalculations(calcsFromAPI){
+  calcs = calcsFromAPI;
+  for (let i = 0; i < calcs.length; i++)
+    calcMap.set(calcs[i].id, calcs[i]);
+}
+
+function getCalculations(){
+  return calcs;
+}
+
+function getCalc(calcId){
+  return calcMap.get(calcId);
+}
+
+
+
+let groups;
+
+function processCalcGroups(groupsFromAPI){
+
+  let methodCalcsMap = new Map();
+  groupsFromAPI.forEach( (group, i) => {
+    if (group.group_type !== 'method'){
+      let calcsMins;
+      if (methodCalcsMap.has(group.method_hash) ){
+        calcsMins = methodCalcsMap.get(group.method_hash);
+      }else{
+        calcsMins = {'ids': [], 'minEnergies': []};
+        methodCalcsMap.set(group.method_hash, calcsMins);
+      }
+      calcsMins.ids.push(group.representative_calculation_id);
+      calcsMins.minEnergies.push(group.energy_minimum);
+    }
+  });
+
+  let methodRepresentativeMap = new Map();
+  methodCalcsMap.forEach( (calcsData, methodHash) => {
+    let minVal = Math.min.apply(null, calcsData.minEnergies);
+    let index = calcsData.minEnergies.indexOf(minVal);
+    methodRepresentativeMap.set(methodHash, calcsData.ids[index]);
+  });
+
+  let calcsInGroups = new Map();
+  groupsFromAPI.forEach( (group, i) => {
+    if (group.group_type !== 'method'){
+      let groupData = {
+        'calcs': new Set(),
+        'method_representative': methodRepresentativeMap.get(group.method_hash)
+      };
+      calcsInGroups.set(
+        getGroupTypeCode(group)+group.representative_calculation_id, groupData);
+      //let calcSet = new Set(); // The representative is (not?) in the set
+      group.calculations_list.forEach( calcId => groupData.calcs.add(calcId) );
+    }
+  });
+  return calcsInGroups;
+}
+
+function setGroups(groupsFromAPI){
+  groups = processCalcGroups(groupsFromAPI);
+}
+
+function getGroups(){
+  return groups;
+}
+
+function getGroupTypeCode(group){
+  if (group.group_type === 'equation of state') return 'eos';
+  else if (group.group_type === 'convergence') return 'par';
+}
+
+function getGroupType(leafId){
+  let code = leafId.substring(0,3);
+  if (code === 'eos') return 'equation of state';
+  else if (code === 'par') return 'convergence';
+  else return null;
+}
+
+function isGroup(leafId){//*** ********** REFACTOR
+  return (leafId.substring(0,3) === 'eos' || leafId.substring(0,3) === 'par');
+}
+
+function getCalcReprIntId(leafId){
+  if (isGroup(leafId)) return parseInt(leafId.substring(3));
+  else return parseInt(leafId);
+}
+
+function isInAnyGroup(calcId){
+  let thereIs = false;
+  groups.forEach( (groupData, groupId) => {
+    //console.log('isInAnyGroup', calcId, groupData.calcs);
+    if (groupData.calcs.has(calcId)) thereIs = true;//return true;
+  });
+  return thereIs;
+}
+
+function isInAnyNotDisabledGroup(calcId){
+  let thereIs = false;
+
+  groups.forEach( (groupData, groupId) => {
+    let representative = getCalc(getCalcReprIntId(groupId));
+    //let codeNameTrimed= representative.code_name.trim();
+    //console.log('isInAnyGroup', calcId, groupData.calcs);
+
+    /***** Exception: disable grouping for some codes
+    if (codeNameTrimed !== 'VASP' && codeNameTrimed !== 'FHI-aims'
+      && groupData.calcs.has(calcId)) thereIs = true; */
+    if (groupData.calcs.has(calcId)) thereIs = true;
+  });
+  return thereIs;
+}
+
+function getGroupLeafId(calcId){
+  let leafId = null;
+  groups.forEach( (groupData, groupId) => {
+    //console.log('isInAnyGroup', calcId, groupData.calcs);
+    if (groupData.calcs.has(calcId)) leafId = groupId;//return true;
+  });
+  //console.log('getGroupLeafId', leafId);
+  return leafId;
+}
+
+
+let hasThermalData, hasElecStructureData;
+
+/*
+function hasThermalData(bool){
+  hasThermalData = bool;
+}
+
+function setHasThermalData(bool){
+  hasThermalData = bool;
+}
+
+function hasElecStructureData(bool){
+  hasThermalData = bool;
+}
+
+function setHasElecStructureData(bool){
+  hasElecStructureData = bool;
+}*/
+
+
+
+// EXPORTS
+module.exports = { setMaterialData, getMaterialData, getCalculations, getCalc,
+  setCalculations, getGroups, setGroups, isGroup, getGroupType,
+  getCalcReprIntId, isInAnyGroup, isInAnyNotDisabledGroup, getGroupLeafId,
+ hasThermalData, hasElecStructureData};
+
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+ /*
+   SVG drawing util library
+ */
+
+
+
+
+const xmlns="http://www.w3.org/2000/svg";
+const xlink="http://www.w3.org/1999/xlink";
+
+
+function addPoint(parent, x, y, r, className) {
+  let e = document.createElementNS(xmlns, "circle");
+  e.setAttribute("r", r); // e.setAttributeNS(null, "r", 5);
+  e.setAttribute("cx", x);
+  e.setAttribute("cy", y);
+  if (className !== undefined) e.setAttribute("class", className);
+  parent.appendChild(e);
+  return e;
+}
+
+function addCircle(parent, x, y, r, fillColor, strokeColor, strokeWidth) {
+  let e = document.createElementNS(xmlns, "circle");
+  e.setAttribute("r", r); // e.setAttributeNS(null, "r", 5);
+  e.setAttribute("cx", x);
+  e.setAttribute("cy", y);
+  e.setAttribute("fill", fillColor);
+  e.setAttribute("stroke", strokeColor);
+  e.setAttribute("stroke-width", strokeWidth);
+  parent.appendChild(e);
+  return e;
+}
+
+
+function addLine(parent, x1, y1, x2, y2, className) {
+  let e = document.createElementNS(xmlns, "line");
+  e.setAttribute("x1", x1);
+  e.setAttribute("y1", y1);
+  e.setAttribute("x2", x2);
+  e.setAttribute("y2", y2);
+  if (className !== undefined)  e.setAttribute("class", className);
+  //e.setAttribute("stroke-width", stroke);
+  parent.appendChild(e);
+  return e;
+}
+
+
+function addRect(parent, x, y, w, h) {
+  let e = document.createElementNS(xmlns, "rect");
+  e.setAttribute("x", x);
+  e.setAttribute("y", y);
+  e.setAttribute("width", w);
+  e.setAttribute("height", h);
+  parent.appendChild(e);
+  return e;
+}
+
+
+
+function addText(parent, x, y, text, textAnchor = 'start', className) {
+  let e = document.createElementNS(xmlns, "text");
+  e.setAttribute("x", x);
+  e.setAttribute("y", y);
+  e.textContent= text;
+  //e.setAttribute("stroke", 'black');
+  e.setAttribute("text-anchor", textAnchor);
+  if (className !== undefined)  e.setAttribute("class", className);
+  parent.appendChild(e);
+  return e;
+}
+
+
+function addPolyline(parent, points, className) {
+  let e = document.createElementNS(xmlns, "polyline");
+  e.setAttribute("points", points);
+  if (className !== undefined)  e.setAttribute("class", className);
+  //e.setAttribute("stroke-width", stroke);
+  parent.appendChild(e);
+}
+
+
+function removeElement(element){
+  element.parentElement.removeChild(element);
+}
+
+
+
+// EXPORTS
+module.exports = {
+  addPoint: addPoint,
+  addCircle,
+  addLine: addLine,
+  addRect: addRect,
+  addText: addText,
+  addPolyline: addPolyline,
+  removeElement: removeElement
+};
 
-	function getServerLocation(){
-	  return document.location.hostname;
-	}
 
+/***/ }),
+/* 3 */
+/***/ (function(module, exports, __webpack_require__) {
 
-	function authServerReq(url, callback){
-	  var oReq = new XMLHttpRequest();
-	  oReq.addEventListener("load", callback);
-	  console.log('util.authServerReq: ', API_BASE_URL+url);
-	  oReq.open("GET", API_BASE_URL+url);
-	  //console.log('util.authServerReq oReq: ', oReq);
-	  oReq.send();
-	  return oReq;
-	}
+"use strict";
 
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+ /*
+   This file implements an information system for the user that provides info
+   related to the concepts or quantities shown on the UI
+   The literals are read form the file infosys.json
+ */
 
-	function setAuthRequestHeader(userDataP, value){
 
-	  if (value === undefined){// default value
-	    authRequestHeaderValue = AUTH_REQUEST_HEADER_GUEST_USER;
-	    userData = null;
-	    //console.log('user: ANONYMOUS  authRequestHeader: ',authRequestHeaderValue);
-	  } else{
-	    authRequestHeaderValue = 'Basic '+ btoa(value+':');
-	    userData = userDataP;
-	    //console.log('user',user,'authRequestHeader: ',authRequestHeaderValue);
-	  }
-	}
 
+let util = __webpack_require__(0);
+let SwitchComponent = __webpack_require__(10);
+
+const INFOSYS_FILE_PATH = 'infosys.json';
+
+let tooltip = document.querySelector('#info-tooltip');
+let tooltipContent = document.querySelector('#tooltip-content');
+
+let elements = [];
+let timerSet = null;
+let on = false;
+let data = null;
+
+function clearCurrentTimeoutAnSetANew(){
+  if (timerSet !== null)  window.clearTimeout(timerSet);
+  timerSet = window.setTimeout(t => tooltip.style.display = 'none', 1000);
+}
+
+
+let switchComponent = new SwitchComponent(util.IMAGE_DIR+'switch');
+document.querySelector('#info-sys-switch-box').appendChild(switchComponent.element);
+
+switchComponent.setListener( off => {
+  on = !off;
+  if (off) {
+    elements.forEach( element => {
+      element.removeEventListener('mouseover', mouseOver);
+      element.className = '';
+    });
+  }else{
+    if (data === null)
+      util.serverReq(INFOSYS_FILE_PATH, e => data = JSON.parse(e.target.response));
+
+    elements.forEach(enableTooltip);
+  }
+
+
+  tooltip.addEventListener('mouseover', e => {
+    window.clearTimeout(timerSet);
+  });
+
+  tooltip.addEventListener('mouseout', e => {
+    clearCurrentTimeoutAnSetANew();
+  });
+
+});
+
+
+function addToInfoSystem(baseElement){
+  let infosysLabels = baseElement.querySelectorAll('span[info-sys-data]');
+
+  for (let i = 0; i < infosysLabels.length; ++i)
+    elements.push(infosysLabels[i]);
+
+  //if (on)  infosysLabels.forEach(enableTooltip);
+  if (on)
+    for (let i = 0; i < infosysLabels.length; ++i)
+      enableTooltip(infosysLabels[i]);
+}
+
+
+function addElementToInfoSystem(element, value){
+  elements.push(element);
+  element.setAttribute('info-sys-data',value);
+
+  if (on) enableTooltip(element);
+}
+
+
+function enableTooltip(element){
+  element.addEventListener('mouseover', mouseOver);
+  element.addEventListener('mouseout', e => {
+    clearCurrentTimeoutAnSetANew();
+    element.style.cursor = 'inherit';
+  });
+  element.className = 'info-sys-label';
+}
+
+
+function mouseOver(e){
+  let r = e.target.getBoundingClientRect();
+  let quantity =  e.target.getAttribute('info-sys-data');
+
+  let index = quantity.indexOf('.value');
+  if (index > 0){ // quantity value
+    let quantityObject = data[quantity.split('-').join(' ').substring(0, index)];
+    //console.log('VALUE', quantityObject);
+    if (quantityObject.value_template === undefined){ //direct value
+      let valueObj = quantityObject.values[quantity.split(':')[1]];
+      tooltipContent.innerHTML = getHTML(valueObj);
+    }else{ // value template
+      let object = quantityObject.value_template;
+      object.text = templating(object.text, quantity.split(':')[1]);
+      object.link = templating(object.link, quantity.split(':')[1]);
+      tooltipContent.innerHTML = getHTML(object);
+      //console.log('VALUE TEMPLATE: ', object);
+    }
+  }else // quantity name
+    tooltipContent.innerHTML = getHTML(data[quantity.split('-').join(' ')]);
+
+  tooltip.style.visibility = 'hidden';
+  tooltip.style.display = 'block';
+  let ttRect = tooltip.getBoundingClientRect();
+  let leftOffset = ttRect.width - r.width;
+  let leftPos = r.left -leftOffset/2;
+  if (leftPos + ttRect.width > window.innerWidth)
+    leftPos = window.innerWidth -ttRect.width;
+  //let topOffset = ttRect.height + 20 - window.pageYOffset;
+  let topOffset =  - window.pageYOffset;
+  tooltip.style.left = (leftPos < 0 ? 5 : leftPos)+'px';
+  tooltip.style.top = (r.top + r.height -topOffset)+'px';
+  tooltip.style.visibility = 'visible';
+  window.clearTimeout(timerSet);
+  e.target.style.cursor = 'help';
+}
+
+
+function templating(s, param) {
+  let initIndex = s.indexOf('${');
+  let finalIndex = s.indexOf('}');
+  if (initIndex >= 0 && finalIndex >= 0 && finalIndex > initIndex){
+    return s.substring(0,initIndex)+param+s.substring(finalIndex+1);
+  }else return s;
+}
+
+function getHTML(object) {
+  let html = '';
+  if (object.text === undefined){
+    //html = 'NO TEXT!! Comment: '+object.comment;
+  }else{ // there is text attr
+    html += object.text;
+  }
+  if (object.link !== undefined){
+    if (object.text !== undefined)   html += '<br>';
+    html += '<a href="'+object.link+'" target="_blank">More information</a>';
+  }
+
+  return html;
+}
+
+
+// EXPORTS
+module.exports = { addToInfoSystem, addElementToInfoSystem };
+
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports, __webpack_require__) {
 
-	function serverReq(url, callback){
-	  var oReq = new XMLHttpRequest();
-	  oReq.addEventListener("load", callback);
-	  oReq.open("GET", url);
-	  //console.log('authRequestHeaderValue: ',authRequestHeaderValue);
-	  oReq.setRequestHeader('Authorization', authRequestHeaderValue);
-	  oReq.send();
-	  return oReq;
-	}
+"use strict";
 
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
 
-	function serverReqPOST(url, data, callback){
-	  var oReq = new XMLHttpRequest();
-	  oReq.addEventListener('load', callback);
-	  oReq.open('POST', url);
-	  oReq.setRequestHeader('Content-Type', 'application/json');
-	  //console.log('authRequestHeaderValue: ',authRequestHeaderValue);
-	  oReq.setRequestHeader('Authorization', authRequestHeaderValue);
-	  oReq.send(data);
-	  return oReq;
-	}
 
+ /*
+   This component is the loading popup window 
+ */
 
-	function getSubscriptedFormula(formula){
-	  let finalFormula= '';  // 'elementCode' :  number
-	  for (let i = 0; i < formula.length; i++){
-	    if (formula.charCodeAt(i) >= 47 && formula.charCodeAt(i) < 58 )
-	      finalFormula += '<sub>'+formula[i]+'</sub>';
-	    else finalFormula += formula[i];
-	    //console.log(formula.charCodeAt(i) + " "+finalFormula);
-	  }
-	  return finalFormula;
-	}
 
 
-	function getSearchURL(){
-	  return API_BASE_URL+'esmaterials';
-	}
 
-	function getSuggestionURL(quantity){
-	  return API_BASE_URL+'suggestions?property='+quantity;
-	}
+let util = __webpack_require__(0);
 
-	function getMaterialURL(matId){
-	  return API_BASE_URL+'materials/'+matId;//'/materials/matid'; //
-	}
+let loadingPopup = document.querySelector('#loading-popup');
 
-	function getMaterialCalcURL(matId, calcId, property = ''){
-	  let propertyString = (property === '' ? '' : '?property='+property);
-	  return API_BASE_URL+'materials/'+matId+'/calculations/'+calcId+propertyString;
-	}
+function show(){
+  let ttRect = loadingPopup.getBoundingClientRect();
+  let leftPos =  (window.innerWidth - ttRect.width)/2;
+  let topPos = (window.innerHeight -ttRect.height)/2;
+  loadingPopup.style.left = leftPos+'px';
+  loadingPopup.style.top = (topPos-100)+'px';
+  loadingPopup.style.visibility = 'visible';
+}
 
-	function getMaterialXsURL(what, matId){
-	  return API_BASE_URL+'materials/'+matId+'/'+what+'?pagination=off';//page=1&per_page=5000';//'/materials/calculations';//
-	}
+function hide(){
+  loadingPopup.style.visibility = 'hidden';
+}
 
-	function getCalcEnergiesURL(matId,calcId){
-	  return API_BASE_URL+'materials/'+matId+'/calculations/'+calcId+'/energies';//'/materials/calculations';//
-	}
+// EXPORTS
+module.exports = { show, hide };
 
-	function getFlaggingURL(){
-	  return API_BASE_URL+'flagme';
-	}
 
+/***/ }),
+/* 5 */
+/***/ (function(module, exports, __webpack_require__) {
 
-	// Launch an app event
-	function setBrowserHashPath(modulePath, finalPath){
-	  if (typeof finalPath === 'undefined') document.location= '#/'+modulePath;
-	  else document.location= '#/'+modulePath+'/'+finalPath;
-	}
+"use strict";
+
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+ /*
+  This is the base class that models a regular plotter.
+  It is inherited by several classes implementing specifc plotters
+ */
+
+
+
+
+let svg = __webpack_require__(2);
+
+const xmlns="http://www.w3.org/2000/svg";
+const xlink="http://www.w3.org/1999/xlink";
+
+
+class PlotterBase{
+
+  constructor(margins = {left: 20, right: 0, top: 10, bottom: 20}) {
+    this.svg = document.createElementNS(xmlns, "svg");
+    this.plotArea = document.createElementNS(xmlns, "g");
+    this.svg.appendChild(this.plotArea);
+
+    this.margins= margins;
+    this.parentElement= null;
+    this.yLabelText = null;
+    this.noDataGroup = null;
+  }
+
+
+  attach(element, width, height){
+    this.parentElement= element;
+    this.parentElement.appendChild(this.svg);
+    this.width = (width !== undefined ? width : this.parentElement.clientWidth);
+    this.height = (height !== undefined ? height : this.svg.width);
+    this.svg.setAttribute("width", this.width);
+    this.svg.setAttribute("height", this.height);
+    this.plotRangeX = this.width - this.margins.left - this.margins.right;
+    this.plotRangeY = this.height - this.margins.top - this.margins.bottom;
+  }
+
+
+  isAttached(){
+    return this.parentElement !== null;
+  }
+
+
+  setRangeAndLabels(xLabel, xMin, xMax, yLabel, yMin, yMax){
+    this.xLabel= xLabel;
+    this.xMin = xMin;
+    this.xMax = xMax;
+    this.yLabel= yLabel;
+    this.yMin= yMin;
+    this.yMax= yMax;
+
+    this.xRel= this.plotRangeX/(this.xMax-this.xMin);
+    this.yRel= this.plotRangeY/(this.yMax-this.yMin);
+  }
+
+
+  drawAxis(xSteps = 0, ySteps = 0, decimals = 2){
+
+	  this.plotArea.setAttribute("transform", 'matrix(1 0 0 1 '+
+      this.margins.left+' '+(this.height  - this.margins.bottom)+')');
+
+    this.yLabelText = svg.addText(this.svg, 0, 0, this.yLabel, 'middle', 'axis-steps-big');
+    this.yLabelText.setAttribute('transform','translate(13,'
+      +(this.plotRangeY/2+this.margins.top)+') rotate(-90)');
+	  svg.addText(this.plotArea, this.plotRangeX/2, this.margins.bottom-1,
+      this.xLabel, 'middle', 'axis-steps-big');
+
+    if (xSteps !== null){
+      let xStep= this.plotRangeX/ xSteps;
+      for (let i = 0; i <= xSteps; i++) {
+        svg.addLine(this.plotArea, xStep*i, 0, xStep*i, 4, 1);
+        svg.addText(this.plotArea, xStep*i, 14,
+          +((xStep*i/this.xRel)+this.xMin).toFixed(decimals), 'middle', 'statisticsviewersteps');
+      }
+    }
+
+    if (ySteps === null && this.yMax > 0 && this.yMin < 0){
+      let i = 1;
+      while(this.yMax*i > this.yMin) {
+        svg.addLine(this.plotArea, 0, this.transformY(this.yMax*i), -3, this.transformY(this.yMax*i), 1);
+        let numberText = (Math.abs(this.yMax*i) >= 10000 ? (this.yMax*i).toExponential() : this.yMax*i );
+        svg.addText(this.plotArea,-5, this.transformY(this.yMax*i)+3, numberText,
+          'end', 'statisticsviewersteps');
+        i--;
+      }
+    }
+
+    if (ySteps !== null){
+        let yStep= this.plotRangeY/ ySteps;
+        for (let i = 0; i <= ySteps; i++) {
+          svg.addLine(this.plotArea, 0, -yStep*i, -3, -yStep*i, 1);
+          let numberToPaint= (yStep*i/this.yRel) + this.yMin;
+          // Fix to prevent the the -0 printing
+          if (Math.abs(numberToPaint) < 0.01) numberToPaint = 0;
+          //console.log('drawAxis', yStep, i, this.yRel, this.yMin, numberToPaint);
+          svg.addText(this.plotArea,-5, -(yStep*i-3), numberToPaint.toFixed(decimals), 'end', 'statisticsviewersteps');
+        }
+    }
+
+	  svg.addLine(this.plotArea, 0, 0, this.plotRangeX+1 ,0 ,'main-axis');
+	  svg.addLine(this.plotArea, 0,0,0,-(this.plotRangeY+1) ,'main-axis');
+    svg.addLine(this.plotArea, this.plotRangeX, 0, this.plotRangeX, -this.plotRangeY ,'main-axis');
+  	svg.addLine(this.plotArea, 0,-this.plotRangeY, this.plotRangeX, -this.plotRangeY,'main-axis');
+  }
+
+
+  clear(){
+    this.svg.removeChild(this.plotArea);
+    this.plotArea = document.createElementNS(xmlns, "g");
+    this.svg.appendChild(this.plotArea);
+    this.plotArea.setAttribute("transform", 'matrix(1 0 0 1 '+
+        this.margins.left+' '+(this.height  - this.margins.bottom)+')');
+
+    if (this.yLabelText !== null){
+      this.svg.removeChild(this.yLabelText);
+      this.yLabelText = null;
+    }
+    if (this.noDataGroup !== null){
+      this.svg.removeChild(this.noDataGroup);
+      this.noDataGroup = null;
+    }
+  }
+
+
+  setNoData(){
+    this.clear();
+    if (this.noDataGroup === null){
+      this.noDataGroup = document.createElementNS(xmlns, 'g');
+      this.svg.appendChild(this.noDataGroup);
+      svg.addRect(this.noDataGroup, 0, 0, this.width, this.height);
+      this.noDataGroup.setAttribute('fill', '#EEE');
+      svg.addText(this.noDataGroup, this.width/2, this.height/2+10,
+        'NO DATA', 'middle', 'nodata');
+    }
+
+  }
+
+
+  // Transform from y-axis units to  y-axis pixels (svg-coordinates)
+  transformY(y){
+    return -this.yRel*(y - this.yMin);
+  }
+
+}
+
+
+// EXPORTS
+module.exports = PlotterBase;
+
+
+/***/ }),
+/* 6 */
+/***/ (function(module, exports, __webpack_require__) {
 
-	function loadLib(url){
-	  let script = document.createElement('script');
-	  script.setAttribute('type', 'text/javascript');
-	  script.setAttribute('src', url);
-	  document.getElementsByTagName('head')[0].appendChild(script);
-	}
+"use strict";
 
-	function getNumberArray(string){
-	  let sArray= string.substring(1,string.length-1).split(',');
-	  let fArray= [];
-	  for (var i = 0; i < sArray.length; i++) {
-	    fArray.push(parseFloat(sArray[i]));
-	  }
-	  //console.log('getNumberArray.SPLIT: '+fArray);
-	  return fArray;
-	}
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
 
-	function getCellDataForViewer(matData){
-	  let cellData= {};
-	  cellData.normalizedCell= [
-	    getNumberArray(matData.cell.a),
-	    getNumberArray(matData.cell.b),
-	    getNumberArray(matData.cell.c)
-	  ];
+ /*
+  Base class from which other main 'Details' view containers inherit.
+  Every of these containers shows all the material info related to a type of info:
+  Structure, Electronic Structure, etc
+ */
 
-	  cellData.periodicity = JSON.parse(matData.periodicity);
 
-	  cellData.labels= [];
-	  cellData.positions= [];
 
-	  for (var i = 0; i < matData.elements.length; i++) {
-	    cellData.labels.push(matData.elements[i].label);
-	    cellData.positions.push(getNumberArray(matData.elements[i].position));
-	  }
-	  return cellData;
-	}
+let util = __webpack_require__(0);
+let DataStore = __webpack_require__(1);
 
 
-	function J2eV(energy, decimals){
-	  let result= energy/1.602176565e-19;
-	  if (decimals === undefined){
-	    if (result < 0.01) return result.toFixed(6);
-	    else  return result.toFixed(3);
-	  }else{
-	    return result.toFixed(decimals);
-	  }
-	}
+class DetailsViewBase {
 
-	function eV2J(energy){
-	  return energy*1.602176565e-19;
-	}
+  constructor(domId) {
+    this.element = document.createElement('div');
+    this.element.setAttribute('id',domId);
+    this.gotoResultsListener= null;
+    this.gotoOverviewListener= null;
+    this.element.innerHTML= '<div class="material-title"></div>';
+    this.element.style.display= 'none';
+  }
 
 
-	/*
-	function getBandGapStatsValue(calcs){
-	  let bandGapSum= 0;
-	  let bandArray= [];
-	  let bandGapDirect= calcs[0].band_gap_direct;
-	  let bandGapType= (bandGapDirect ? "direct" : "indirect");
-
-	  for (var i = 0; i < calcs.length; i++) {
-	    //if (calcs[i].band_gap > 0){
-	      bandGapSum+= calcs[i].band_gap;
-	      bandArray.push(calcs[i].band_gap);
-	      if (calcs[i].band_gap_direct !== bandGapDirect)
-	        bandGapType= 'various results';
-	    //}
-	    //console.log(bandGapSum+'  '+calcs[i].band_gap+' '+bandArray.length);
-	  }
+  attachAndSetEvents(element){
+    element.appendChild(this.element);
+    this.materialTitle= this.element.querySelector('.material-title');
+  }
 
-	  let html= '';//let html= ((bandGapSum / bandArray.length)/1.602176565e-19).toFixed(3)+' eV ('+bandGapType+')';;
-	  let min= (Math.min.apply(null, bandArray)/1.602176565e-19).toFixed(3);
-	  let max= (Math.max.apply(null, bandArray)/1.602176565e-19).toFixed(3);
-	    html+= '&nbsp;('+min+' ... '+max+' eV)';
-	   //html+= '&nbsp;&nbsp;&nbsp;['+bandArray.length+' / '+calcs.length+']';
 
-	  return html;
-	}*/
+  attachNavTree(navTree){
+    navTree.attach(this.navTreeWrapper);
+  }
 
-	function m2Angstrom(dist){
-	  return (dist/1e-10).toFixed(3)+' &#197;';
-	}
 
+  setVisible(){
+    this.element.style.display= 'block';
+  }
 
-	function getLatticeAnglesValues(calcs, twoD, bulk){
-	  let lattParams= [0.0, 0.0, 0.0];
-	  calcs.forEach( (calc) => {
-	    if (calc.lattice_parameters !== undefined && calc.lattice_parameters !== null){
-	      let tempLattParams= getNumberArray(calc.lattice_parameters);
-	      lattParams[0] += tempLattParams[3];
-	      lattParams[1] += tempLattParams[4];
-	      lattParams[2] += tempLattParams[5];
-	    }
-	  });
 
-	  if (bulk)
-	    return `<div>&alpha; = ${rad2degree(lattParams[0] / calcs.size)}</div>
-	    <div>&beta; = ${rad2degree(lattParams[1] / calcs.size)}</div>
-	    <div>&gamma; = ${rad2degree(lattParams[2] / calcs.size)}</div>`;
-	  else if (twoD)
-	    return `<div>&alpha; = ${rad2degree(lattParams[0] / calcs.size)}</div>`;
-	  else return ''; // 1D
-	}
+  setMaterialData() {
+    this.materialTitle.innerHTML= util.getMaterialTitle(DataStore.getMaterialData());
+  }
 
 
-	function rad2degree(angle){
-	  return (angle * (180 / Math.PI)).toFixed(0)+'&deg;';
-	}
+  updateCalcs(calcs){
+  }
 
-	function m3ToAngstrom3(vol){
-	  return (vol/1e-30).toFixed(3)+' &#197;<sup>3</sup>';
-	}
 
+  updateMarkedCalc(calc){
+  }
 
-	function getAverage(array){
-	  let sum = 0;
-	  for (var i = 0; i < array.length; i++) sum += array[i];
-	  return sum/array.length;
-	}
+}
 
+// EXPORTS
+module.exports = DetailsViewBase;
 
-	function getQuantityStatsMap(calcs){
 
-	  let quantities = ['volume', 'atomic_density', 'mass_density', 'lattice_a', 'lattice_b', 'lattice_c'];
-	  let labels = ['Volume (ų)', 'Atomic density (Å⁻³)', 'Mass density (kg/m³)', 'a (Å)', 'b (Å)', 'c (Å)'];
-	  let quantitiesMap = new Map();
+/***/ }),
+/* 7 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+ /*
+  Implements the Band Structure plotter.
+  It's used to show either the regular Band Structure data or
+  the Phonon Dispersion.
+ */
+
+
+
+
+let InteractivePlotterBase = __webpack_require__(8);
+let svg = __webpack_require__(2);
+let util = __webpack_require__(0);
+
+const MULTIPLO1 = 1.602176565e-19;
+const MULTIPLO2 = 1/5.034117012222e22;
+
+
+class BSPlotter extends InteractivePlotterBase{
+
+  constructor() {
+    super({left: 55, right: 5, top: 0, bottom: 30});
+    this.phononMode = false;
+    this.factor = MULTIPLO1;
+  }
+
+
+  setPhononMode(){
+    this.phononMode = true;
+    this.factor = MULTIPLO2;
+    this.outOfRangeColorActivated = false;
+  }
+
+
+  // detach if necessary and attach
+  attach(element, width, height){
+    super.attach(element, width, height);
+  }
+
+
+  getTopAndLowestPoints(bandStructData){
+    let bandMax = -10000;
+    let bandMin = 10000;
+    for (let i = 0; i < bandStructData.length; i++) { // Per segment
+      // spin1 - per band energy loop
+      for (let j = 0; j < bandStructData[i].band_energies[0].length; j++) {
+        let tempValue= Math.max.apply(null, bandStructData[i].band_energies[0]/*spin1*/[j]/*first_band*/);
+        if (tempValue > bandMax) bandMax= tempValue;
+        tempValue= Math.min.apply(null, bandStructData[i].band_energies[0]/*spin1*/[j]/*first_band*/);
+        if (tempValue < bandMin) bandMin= tempValue;
+      }
+
+      if (bandStructData[i].band_energies.length === 2)
+        // spin2 - per band energy loop
+        for (let j = 0; j < bandStructData[i].band_energies[1].length; j++) { // Per segment
+          let tempValue= Math.max.apply(null, bandStructData[i].band_energies[1]/*spin1*/[j]/*first_band*/);
+          if (tempValue > bandMax) bandMax= tempValue;
+          tempValue= Math.min.apply(null, bandStructData[i].band_energies[1]/*spin1*/[j]/*first_band*/);
+          if (tempValue < bandMin) bandMin= tempValue;
+        }
+    }
+    return [bandMin/this.factor, bandMax/this.factor];
+  }
+
+
+  drawKPointLabel(x, label){
+    svg.addText(this.axisGroup, x*this.xRel, 16, label, 'middle', 'steps');
+  }
+
+
+  setBandStructureData(data){
+
+    let bandStructData;
+    if (data.segments !== undefined)  bandStructData = data.segments;
+    else bandStructData = data;
+
+    this.bandGapData = undefined;
+    if (data.band_gap !== undefined && data.band_gap.position !== undefined){
+      this.bandGapData = data.band_gap.position;
+      this.bandGapData.cbmDistances = [];
+      this.bandGapData.vbmDistances = [];
+    }
+
+    // Gather all the points per band (divided by spin) crossing the segments
+    this.bandsDataSpin1= [];  // [segment][band][kpoint]
+    this.bandsDataSpin2= [];
+    this.segmentLimitsX = [];
+    this._reset();
+
+    let topAndLowestPoints = this.getTopAndLowestPoints(bandStructData);
+    let minEnergyVal = topAndLowestPoints[0];
+    let maxEnergyVal = topAndLowestPoints[1];
+
+    if (this.phononMode){
+      this.setAxisRangeAndLabels('',0,1,'Frequency (cm⁻¹)',-50, 320,
+        minEnergyVal, maxEnergyVal, 100);
+    }else
+      this.setAxisRangeAndLabels('',0,1,'Energy (eV)' ,-6 ,11 , minEnergyVal,
+        maxEnergyVal, 5 );
+
+    // Calculates de distance
+    let totalDistance= 0;
+    for (let k = 0; k < bandStructData.length; k++) {
+      let kPoints= bandStructData[k].band_k_points;
+      totalDistance+= kPointDistance(kPoints,kPoints.length-1);
+    }
+    let currentDistance= 0;
+    let prevLastLabel = null;
+    let dataOverflow = false;
+
+    for (let k = 0; k < bandStructData.length; k++) { // For every  segment
+
+      let segment= bandStructData[k];
+      let kPoints= segment.band_k_points;
+      let labels= segment.band_segm_labels;
+
+      let energiesSpin1= segment.band_energies[0];
+      let energiesSpin2= segment.band_energies[1];
+      this.bandsDataSpin1.push([]);  // Add a new array per segment
+      this.bandsDataSpin2.push([]);
+
+      let segmentDistance= kPointDistance(kPoints,kPoints.length-1);
+
+      // keeping the segment limits (x coordenate) for after painting
+      this.segmentLimitsX.push(currentDistance/totalDistance);
+
+      if (labels !== null){
+        // Set k-points labels
+        if (prevLastLabel !== null && prevLastLabel !== labels[0])
+          this.drawKPointLabel(currentDistance/totalDistance,
+            getSymbol(prevLastLabel)+'|'+getSymbol(labels[0]));
+        else
+          this.drawKPointLabel(currentDistance/totalDistance,getSymbol(labels[0]));
+        // The last label
+        if (k === bandStructData.length -1)
+          this.drawKPointLabel(1, getSymbol(labels[1]));
+
+        prevLastLabel = labels[1];
+      }
+
+      for (let i = 0; i < kPoints.length; i++) { // For every  k-point
+
+        let tempDistance= (currentDistance + kPointDistance(kPoints, i))/totalDistance;
+
+        if (this.bandGapData !== undefined){
+
+          if (this.bandGapData.lower !== undefined){
+            let kpt = this.bandGapData.lower.kpt;
+            if (kPoints[i][0] === kpt[0] && kPoints[i][1] === kpt[1]
+              && kPoints[i][2] === kpt[2]){
+                this.bandGapData.cbmDistances.push(tempDistance);
+            }
+          }
+
+          if (this.bandGapData.upper !== undefined){
+            let kpt = this.bandGapData.upper.kpt;
+            if (kPoints[i][0] === kpt[0] && kPoints[i][1] === kpt[1]
+              && kPoints[i][2] === kpt[2]){
+                this.bandGapData.vbmDistances.push(tempDistance);
+            }
+          }
+
+          /*
+          let kpt = this.bandGapData.cbmKpt;
+          if (kPoints[i][0] === kpt[0] && kPoints[i][1] === kpt[1]
+            && kPoints[i][2] === kpt[2]){
+              //console.log("kpoints: ", kPoints[i], kpt, tempDistance);
+              this.bandGapData.cbmX = tempDistance;
+          }
+          kpt = this.bandGapData.vbmKpt;
+          if (kPoints[i][0] === kpt[0] && kPoints[i][1] === kpt[1]
+            && kPoints[i][2] === kpt[2]){
+              //console.log("kpoints: ", kPoints[i], kpt, tempDistance);
+              this.bandGapData.vbmX = tempDistance;
+          }
+          */
+        }
+
+
+        // All bands spin1
+        for (let j = 0; j < energiesSpin1[i].length; j++) {
+          if (i === 0) this.bandsDataSpin1[k][j] = [];//if (k === 0 && i === 0) this.bandsDataSpin1[j] = [];
+          let currentY = energiesSpin1[i][j]/this.factor;
+          this.bandsDataSpin1[k][j].push({x: tempDistance, y: currentY});
+          if (!dataOverflow && currentY > 10000)  dataOverflow = true;
+        }
+        // All bands spin2
+        if (energiesSpin2 !== undefined)
+          for (let j = 0; j < energiesSpin2[i].length; j++) {
+            if (i === 0) this.bandsDataSpin2[k][j] = [];
+            let currentY = energiesSpin2[i][j]/this.factor;
+            this.bandsDataSpin2[k][j].push({x: tempDistance, y: currentY});
+            if (!dataOverflow && currentY > 10000)  dataOverflow = true;
+          }
+        //console.log("K PPPPPP Ponint: "+i+' DIS: '+tempDistance, this.bandsDataSpin1[k]);
+      }
+
+      currentDistance+= segmentDistance;
+    }
+
+    if (dataOverflow) throw 'Plotter Data Overflow: Probably the energy data is not in correct units'; //console.log('BSPlotter data overflow');
+    else this.repaint();
+  }
+
+
+  repaintData(yMin, yMax){
+
+    this.segmentLimitsX.forEach(x => {
+      let yMinPx = this.transformY(yMin);
+      let yMaxPx = this.transformY(yMax);
+      if (this.phononMode) { yMinPx += 200; yMaxPx -= 200; }
+      svg.addLine(this.plotContent, x*this.xRel, yMinPx,
+        x*this.xRel, yMaxPx, 'segment');
+    });
+
+    // Drawing lines
+    let polylinePoints;
+    for (var i = 0; i < this.bandsDataSpin1.length; i++) // loop the segments
+
+      for (var j = 0; j < this.bandsDataSpin1[i].length; j++) { // loop the bands
+        polylinePoints = '';
+        for (var k = 0; k < this.bandsDataSpin1[i][j].length; k++) { // loop the kpoints
+          polylinePoints+= ' '+this.xRel*this.bandsDataSpin1[i][j][k].x+
+            ' '+this.transformY(this.bandsDataSpin1[i][j][k].y);
+        }
+        svg.addPolyline(this.plotContent, polylinePoints, 'plotSpin1');
+      }
+
+    if (this.bandsDataSpin2.length > 0){
+      for (var i = 0; i < this.bandsDataSpin2.length; i++) // loop the segments
+
+        for (var j = 0; j < this.bandsDataSpin2[i].length; j++) { // loop the kpoints
+          polylinePoints = '';
+          for (var k = 0; k < this.bandsDataSpin2[i][j].length; k++) { // loop the bands
+            polylinePoints+= ' '+this.xRel*this.bandsDataSpin2[i][j][k].x+
+              ' '+this.transformY(this.bandsDataSpin2[i][j][k].y);
+          }
+          svg.addPolyline(this.plotContent, polylinePoints, 'plotSpin2');
+        }
+    }
+
+
+    // Paint CBM and VBM
+    // console.log("Paint CBM and VBM: ", this.vbm); this.vbm.y = -1.01577992001999e-20/this.factor;
+    if (this.bandGapData !== undefined
+      // If there are two spins related data the CBM and VBM points aren't shown
+    /*&& this.bandsDataSpin2.length === 0*/)
+       {
+
+         this.bandGapData.cbmDistances.forEach( distance => {
+           let x = this.xRel * distance;
+           let y = this.transformY(this.bandGapData.lower.energy/this.factor);
+           //console.log("hhhhhhhhh: ", x, y);
+           svg.addPoint(this.plotContent, x, y , 3, 'cbm-vbm-points');
+           svg.addText(this.plotContent, x+4, y-6, 'CBM');
+         });
+
+
+         this.bandGapData.vbmDistances.forEach( distance => {
+           let x = this.xRel*distance;
+           let y = this.transformY(this.bandGapData.upper.energy/this.factor);
+           svg.addPoint(this.plotContent, x, y, 3, 'cbm-vbm-points');
+           svg.addText(this.plotContent, x+4, y+14, 'VBM');
+          });
+
+        /*
+
+      let x = this.xRel*this.bandGapData.cbmDistance;
+      let y = this.transformY(this.bandGapData.lower.energy/this.factor);
+      //console.log("hhhhhhhhh: ", x, y);
+      svg.addPoint(this.plotContent, x, y , 3, 'cbm-vbm-points');
+      svg.addText(this.plotContent, x+4, y-6, 'CBM');
+
+      x = this.xRel*this.bandGapData.vbmDistance;
+      y = this.transformY(this.bandGapData.upper.energy/this.factor);
+      svg.addPoint(this.plotContent, x, y, 3, 'cbm-vbm-points');
+      svg.addText(this.plotContent, x+4, y+14, 'VBM');
+      */
+    }
+
+  }
+
+
+}
+
+
+function kPointDistance(kPoints, position){
+  let p0= kPoints[0];
+  let p1= kPoints[position];
+  let deltaX= p1[0] - p0[0];
+  let deltaY= p1[1] - p0[1];
+  let deltaZ= p1[2] - p0[2];
+  return Math.sqrt(deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ);
+}
+
+function getSymbol(label){
+  if (label === 'Gamma' || label === 'G') return 'Γ';
+  else return label;
+}
+
+// EXPORTS
+module.exports = BSPlotter;
+
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports, __webpack_require__) {
 
-	  if (calcs.values().next().value.cell_volume === null){ // not bulk type volume of a calc null
-	    quantities = ['lattice_a', 'lattice_b', 'lattice_c'];
-	    labels = ['a (Å)', 'b (Å)', 'c (Å)'];
-	  }
+"use strict";
+
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+ /*
+  This is the base class that models a highly interactive plotter.
+  It is inherited by several classes implementing specifc plotters.
+  This plotter implements zoom and y-axis offset
+ */
+
+
+
+
+
+let svg = __webpack_require__(2);
+
+const xmlns="http://www.w3.org/2000/svg";
+const xlink="http://www.w3.org/1999/xlink";
+
+
+class InteractivePlotterBase{
+
+  constructor(margins = {left: 20, right: 0, top: 0, bottom: 20}) {
+    this.margins= margins;
+    this.svg = document.createElementNS(xmlns, "svg");
+
+    this.parentElement= null;
+    this.plotContent = null;
+    this.axisGroup = null;
+    this.yAxisLabelsGroup = null;
+    this.yLabelText = null; // If null, y axis label and numbers are not painted
+    this.noDataGroup = null;
+
+    this.yZoom = 1;  // Initial zoom
+    this.yOffset = 0; // Initial y offset = 0
+    this.repaintListener = null;
+    this.nodataLabel = null;
+
+    this.outOfRangeColorActivated = true;
+  }
+
+
+  attach(element, width, height){
+    this.parentElement= element;
+    this.parentElement.appendChild(this.svg);
+    this.width = (width !== undefined ? width : this.parentElement.clientWidth);
+    this.height = (height !== undefined ? height : this.svg.width);
+    this.svg.setAttribute("width", this.width);
+    this.svg.setAttribute("height", this.height);
+    this.plotRangeX = this.width - this.margins.left - this.margins.right;
+    this.plotRangeY = this.height - this.margins.top - this.margins.bottom;
+
+    // y axis area (zoomable)
+    this.yAxisArea = document.createElementNS(xmlns, "svg");
+    this.svg.appendChild(this.yAxisArea);
+    let yAxisAreaWidth = this.margins.left;
+    this.plotAreaHeight = this.height - this.margins.bottom - this.margins.top;
+    this.yAxisArea.setAttribute("width", yAxisAreaWidth);
+    this.yAxisArea.setAttribute("height", this.plotAreaHeight);//-OVERLAP_CORRECTOR);
+    this.yAxisArea.setAttribute("x", 0);
+    this.yAxisArea.setAttribute("y", 0);//OVERLAP_CORRECTOR);
+
+    // SVG plot area window
+    this.plotArea = document.createElementNS(xmlns, "svg");
+    this.svg.appendChild(this.plotArea);
+    this.plotAreaWidth = this.width - this.margins.left - this.margins.right;
+    this.plotArea.setAttribute("width", this.plotAreaWidth);
+    this.plotArea.setAttribute("height", this.plotAreaHeight);
+    this.plotArea.setAttribute("x", this.margins.left);
+    this.plotArea.setAttribute("y", this.margins.top);
+
+    // Rect filling plot area in order to support styles and events
+    this.plotAreaBg  = svg.addRect(this.plotArea, 0, 0, this.plotAreaWidth, this.plotAreaHeight);
+    this.plotAreaBg.setAttribute('class', 'moveable-plot');
+    this.plotAreaBg.setAttribute('opacity', 0.0);
+
+    this. _events();
+  }
+
+
+  isAttached(){
+    return this.parentElement !== null;
+  }
+
+
+  setAxisRangeAndLabels(xLabel, xMin, xMax, yLabel, yMinInit, yMaxInit,
+    yMin, yMax, yLabelGap, decimals = 2){
+    this.xLabel= xLabel;
+    this.xMin = xMin;
+    this.xMax = xMax;
+    this.yMinInit= yMinInit;
+    this.yMaxInit= yMaxInit;
+    this.yMin= yMin;
+    this.yMax= yMax;
+    this.yLabelGapInit = yLabelGap;
+    this.xRel= this.plotRangeX/(this.xMax-this.xMin);
+    this.yRel= this.plotRangeY/(this.yMaxInit-this.yMinInit);
+
+    this._resetAxisGroup();
+
+    // Draw axes
+    svg.addLine(this.axisGroup, 0,0,this.plotRangeX,0,  'main-axis');
+  	svg.addLine(this.axisGroup, 0,0,0,-this.plotRangeY ,'main-axis');
+    svg.addLine(this.axisGroup, this.plotRangeX, 0, this.plotRangeX, -this.plotRangeY, 'main-axis');
+  	svg.addLine(this.axisGroup, 0,-this.plotRangeY, this.plotRangeX, -this.plotRangeY, 'main-axis');
+
+    // Paint x and y axes labels
+    if (yLabel !== null){
+      this.yLabelText = svg.addText(this.svg, 0, 0, yLabel, 'middle', 'axis-steps-big');
+      this.yLabelText.setAttribute('transform','translate(15,'+(this.plotRangeY/2+this.margins.top)+') rotate(-90)');
+    }
+    if (xLabel !== null)
+      svg.addText(this.axisGroup, this.plotRangeX/2, this.margins.bottom-12, this.xLabel, 'middle', 'axis-steps-big');
+
+    // initialize y axis steps (dynamic construction) container
+    this._resetYAxisLabelGroup();
+
+    // transformY precalcultation 1
+    this.precalculation_1 = this.plotAreaHeight  + this.yMinInit*this.yRel;
+    this.precalculation_2 = this.precalculation_1;//- this.yOffset // when this quantity changes
+  }
+
+
+  _events(){
+
+    this.plotArea.addEventListener('wheel', (e) => {
+      e.preventDefault();
+      if (e.deltaY > 0 && this.yZoom > 0.5 ) this.yZoom -= 0.2;
+      else if (e.deltaY < 0 && this.yZoom < 2) this.yZoom += 0.2;
+      this.repaint();
+      if (this.repaintListener !== null)
+        this.repaintListener(this.yZoom, this.yOffset);
+    });
+
+    let initPosY;
+    this.plotArea.addEventListener('mousedown', (e) => {
+      e.preventDefault();
+      initPosY = e.clientY + this.yOffset;
+      //console.log('mousedown: e.clientY + this.yOffset', e.clientY, this.yOffset);
+      this.plotArea.addEventListener('mousemove', moveListener);
+
+      this.plotArea.addEventListener('mouseup', (e) => {
+        this.plotArea.removeEventListener('mousemove', moveListener);
+      });
+      this.plotArea.addEventListener('mouseout', (e) => {
+        this.plotArea.removeEventListener('mousemove', moveListener);
+      });
+    });
+
+    let self = this;
+    function moveListener(e) {
+      //console.log('Y offset:', e.clientY - initPosY);
+      // Bad if (initPosY - e.clientY > this.yMax || initPosY - e.clientY < this.yMin)
+      self.yOffset = initPosY - e.clientY ;
+      self.precalculation_2 = self.precalculation_1 - self.yOffset;
+      self.repaint();
+      if (self.repaintListener !== null)
+        self.repaintListener(self.yZoom, self.yOffset);
+    }
+  }
+
+
+  setYZoomAndOffset(yZoom, yOffset){
+    this.yZoom = yZoom;
+    this.yOffset = yOffset;
+    this.precalculation_2 = this.precalculation_1 - this.yOffset;
+  }
+
+
+  setExternalYAxisMax(externalYAxisMax){
+    this.externalYAxisMax = externalYAxisMax;
+  }
+
+
+  getYAxisMax(){
+    return this.yAxisMax;
+  }
+
+
+  repaint(){
+    // repaint Y axis
+    this._resetYAxisLabelGroup();
+
+    let yLabelGap;
+    if (this.yZoom > 1) yLabelGap = this.yLabelGapInit/5;
+    else yLabelGap = this.yLabelGapInit;
+
+    let min = Math.floor(this.yMin/yLabelGap)*yLabelGap;
+    let max = Math.ceil(this.yMax/yLabelGap)*yLabelGap;
+    this.yAxisMax = max;
+    if (this.externalYAxisMax !== undefined) max = this.externalYAxisMax;
+
+    if (this.yLabelText !== null) {
+      for (let i = min; i < max+1; i = i + yLabelGap) {
+        svg.addLine(this.yAxisLabelsGroup, this.margins.left,
+          this.transformY(i), this.margins.left-3, this.transformY(i));
+        svg.addText(this.yAxisLabelsGroup, this.margins.left-5,
+          this.transformY(i)+5, i, 'end', 'axis-steps');
+      }
+    }
+
+    // repaint plot content
+    this._resetPlotContent();
+
+    // Out of range areas
+    if (this.outOfRangeColorActivated){
+      let area = svg.addRect(this.plotContent, 0, this.transformY(this.yMax)-2*this.plotAreaHeight, this.plotAreaWidth, 2*this.plotAreaHeight);
+      area.setAttribute('class', 'out-of-range');
+      let area1 = svg.addRect(this.plotContent, 0, this.transformY(this.yMin), this.plotAreaWidth, 2*this.plotAreaHeight);
+      area1.setAttribute('class', 'out-of-range');
+    }
+
+    // Zero line
+    svg.addLine(this.plotContent, 0, this.transformY(0), this.plotRangeX,
+      this.transformY(0), 'zeroline');
+
+    // repaint data lines
+    this.repaintData(min, max);
+
+    // Add the top layer: rect for events
+    this.plotArea.removeChild(this.plotAreaBg);
+    this.plotArea.appendChild(this.plotAreaBg);
+  }
+
+
+  setRepaintListener(listener) {
+    this.repaintListener = listener;
+  }
+
+
+  transformY(y){
+    // Precalculation usage
+    // this.plotAreaHeight -y*this.yZoom*this.yRel + this.yMinInit*this.yRel - this.yOffset
+    // -y*this.yZoom*this.yRel (calculated here)  this.plotAreaHeight  + this.yMinInit*this.yRel - this.yOffset
+    let result = -y*this.yZoom*this.yRel + this.precalculation_2;
+    if (result > 10000) throw 'Y coordinate too large';
+    return result;
+  }
+
+
+  _resetPlotContent(){
+    // TRy to delete with textContent property
+    if (this.plotContent !== null)
+      this.plotArea.removeChild(this.plotContent);
+    this.plotContent = document.createElementNS(xmlns, "g");
+    this.plotArea.appendChild(this.plotContent);
+  }
 
-	  quantities.forEach( (quantity, index) => {
-	    let array= [];
-	    calcs.forEach( calc => {
-	      let value;
-	      if (quantity === 'volume') value = calc.cell_volume/1e-30;
-	      else if (quantity === 'atomic_density') value = calc.atomic_density*1e-30;
-	      else if (quantity === 'mass_density') value = calc.mass_density;
-	      else if (quantity.indexOf('lattice') >= 0){
-	        let tempLattParams= getNumberArray(calc.lattice_parameters);
-	        if (quantity === 'lattice_a') value = tempLattParams[0]/1e-10;
-	        else if (quantity === 'lattice_b') value = tempLattParams[1]/1e-10;
-	        else if (quantity === 'lattice_c') value = tempLattParams[2]/1e-10;
-	      }
-	      array.push(value);
-	    });
-	    let stats = {};
-	    stats.data = array;
-	    stats.min = Math.min.apply(null, array);
-	    stats.max = Math.max.apply(null, array);
-	    stats.equal = (stats.min === stats.max);
-	    let lls = labels[index].split(':');
-	    stats.label = lls[0];
-	    if (lls.length === 2)  stats.units = lls[1];
-	    else stats.units = '';
-
-	    let decimals = 3;
-	    if (quantity === 'mass_density') decimals = 1;
-	    stats.html = getAverage(stats.data).toFixed(decimals)+
-	      ' &nbsp; <span style="font-size: 0.9em">['+stats.min.toFixed(decimals)
-	      +' , '+stats.max.toFixed(decimals)+']</span>';
-
-	    quantitiesMap.set(quantity, stats);
-	  });
-	  return quantitiesMap;
-	}
 
+  _resetAxisGroup(){
+    if (this.axisGroup !== null)
+      this.svg.removeChild(this.axisGroup);
+    this.axisGroup = document.createElementNS(xmlns, 'g');
+    this.svg.appendChild(this.axisGroup);
 
-	function toAngstromMinus3(density){
-	  return (density*1e-30).toFixed(3)+' &#197;<sup>-3</sup>';
-	}
+    // The y axis is inverted so the y coordinate has to be multiplied by -1
+    this.axisGroup.setAttribute("transform", 'matrix(1 0 0 1 '+
+      this.margins.left+' '+(this.height - this.margins.bottom)+')');
+  }
 
 
-	function getMaterialTitle(data, html){
-	  let title;
-	  title = getSubscriptedFormula(data.formula_reduced);
-	  if (html !== undefined && html ===false)   title = data.formula_reduced;
+  _resetYAxisLabelGroup(){
+    if (this.yLabelText === null) return;
 
-	  if (data.space_group_number !== null)
-	    title += ' - space group '+data.space_group_number;
-	  //return '<span style="font-size: 0.9em">'+title+' </span>';
-	  return title;
-	}
+    if (this.yAxisLabelsGroup !== null)
+      this.yAxisArea.removeChild(this.yAxisLabelsGroup);
+    this.yAxisLabelsGroup = document.createElementNS(xmlns, 'g');
+    this.yAxisArea.appendChild(this.yAxisLabelsGroup);
+    //this.yAxisLabelsGroup.setAttribute("transform", 'matrix(1 0 0 1 0 -'+OVERLAP_CORRECTOR+')');
+  }
 
-	function getMinMaxHTML(calcs,prop){
-	  let propArray= [];
 
-	  calcs.forEach( (calc) => {
-	    propArray.push(calc[prop]);
-	  });
+  _reset(){
+    this.yZoom = 1;  // Initial zoom
+    this.yOffset = 0; // Initial y offset = 0
 
-	  return '('+Math.min.apply(null, propArray)+' ... '+Math.max.apply(null, propArray)+')';
-	}
+    // initialize plot content (dynamic construction) container
+    this._resetPlotContent();
+
+    if (this.yLabelText !== null){
+      this.svg.removeChild(this.yLabelText);
+      this.yLabelText = null;
+    }
+
+    if (this.noDataGroup !== null){
+      this.svg.removeChild(this.noDataGroup);
+      this.noDataGroup = null;
+    }
+  }
 
 
-	function generateDiagramSteps(maxVal){
+  setNoData(){
+    this._resetYAxisLabelGroup();
+    this._resetPlotContent();
+    this._resetAxisGroup();
+    if (this.noDataGroup === null){
+      this.noDataGroup = document.createElementNS(xmlns, 'g');
+      this.svg.appendChild(this.noDataGroup);
+      svg.addRect(this.noDataGroup, 0, 0, this.width, this.height);
+      this.noDataGroup.setAttribute('fill', '#EEE');
+      svg.addText(this.noDataGroup, this.width/2, this.height/2+10,
+        'NO DATA', 'middle', 'nodata');
+    }
 
-	  let d = 4; // generates 0 and 4 more points
-	  let exp = -Math.floor(Math.log(maxVal/d) * Math.LOG10E);
+  }
 
-	  let factor = Math.pow(10,exp);//100;
-	  //console.log('util.generateDiagramSteps  ',exp, maxVal/d, factor);
-	  let ceil = Math.ceil(maxVal*factor/d);
-	  let stepArray = [];
-	  for (var i = 0; i <= d; i++) {
-	    stepArray[i] = ceil*i/factor;
-	  }
-	  //console.log('stepArray '+stepArray);
-	  exp = (exp < 0 ? 0 : exp);
-	  return [stepArray, exp];
-	}
+}
 
+// EXPORTS
+module.exports = InteractivePlotterBase;
 
 
-	/*
-	function addBandGapData(calcJson, bsData){
-	  if (calcJson.band_gap > 0) {
-	    bsData.bandGapData = {};
-	    bsData.bandGapData.cbmEnergy = calcJson.band_gap_lower_energy;
-	    bsData.bandGapData.cbmKpt = getNumberArray(calcJson.band_gap_lower_kpt);
-	    bsData.bandGapData.vbmEnergy = calcJson.band_gap_upper_energy;
-	    bsData.bandGapData.vbmKpt = getNumberArray(calcJson.band_gap_upper_kpt);
-	  }
-	}*/
+/***/ }),
+/* 9 */
+/***/ (function(module, exports, __webpack_require__) {
 
-	/*
-	function is2DSystem_temporary_patch(){
 
-	//console.log('TEMPORARY PATCH is2DSystem:', DataStore.getMaterialData());
-	  return DataStore.getMaterialData().system_type === '2D';
-	}
-	*/
-
-
-	module.exports = {
-	  materialId,
-	  MAT_VIEW: MAT_VIEW,
-	  IMAGE_DIR: IMAGE_DIR,
-	  USER_COOKIE_DOMAIN,
-	  ELEMENTS: ELEMENTS,
-	  setAuthRequestHeader,
-	  getUserData,
-	  getServerLocation,
-	  authServerReq,
-	  serverReq,
-	  serverReqPOST,
-	  getSearchURL: getSearchURL,
-	  getSuggestionURL,
-	  getMaterialURL: getMaterialURL,
-	  getMaterialCalcURL: getMaterialCalcURL,
-	  getMaterialXsURL: getMaterialXsURL,
-	  getCalcEnergiesURL: getCalcEnergiesURL,
-	  getFlaggingURL,
-	  setBrowserHashPath: setBrowserHashPath,
-	  loadLib: loadLib,
-	  getNumberArray: getNumberArray,
-	  getCellDataForViewer: getCellDataForViewer,
-	  //FERMI_SURFACE_URL: FERMI_SURFACE_URL,
-	  J2eV: J2eV,
-	  eV2J,
-	  //getBandGapStatsValue: getBandGapStatsValue,
-	  m2Angstrom: m2Angstrom,
-	  getLatticeAnglesValues: getLatticeAnglesValues,
-	  rad2degree: rad2degree,
-	  m3ToAngstrom3: m3ToAngstrom3,
-	  getQuantityStatsMap: getQuantityStatsMap,
-	  toAngstromMinus3,
-	  getMaterialTitle,
-	  getMinMaxHTML: getMinMaxHTML,
-	  getSubscriptedFormula: getSubscriptedFormula,
-	  getAverage,
-	  generateDiagramSteps,
-	  //is2DSystem_temporary_patch
-	  //addBandGapData
-	}
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
 
 
-/***/ },
-/* 2 */
-/***/ function(module, exports) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-	 /*
-	  This file create and holds the application data models.
-	  It stores the data loaded from the backend (immutable).
-	  In addition it creates app life-time entities for convenience
-	 */
-
-
-	let materialData;
-
-	function setMaterialData(dataFromAPI){
-	  materialData = dataFromAPI;
-	}
+ /*
+  This file implements the Material Module of the application.
+  It's a UI component container that displays the selected material information.
+  It's complex because of the amount and diversity of material info available.
 
-	function getMaterialData(){
-	  return materialData;
-	}
+  In this file other two inner components of the module are implemented
+  (by convenience):
+  StructureViewerWrapper and DropDown (used exclusively in StructureViewerWrapper)
+ */
 
 
-	let calcs;
-	let calcMap = new Map();
+let svg = __webpack_require__(2);
+let util = __webpack_require__(0);
+let NavTree = __webpack_require__(21);
+let Overview = __webpack_require__(22);
+let StructureDetails = __webpack_require__(23);
+let ElectronicStructDetails = __webpack_require__(25);
+let MethodologyDetails = __webpack_require__(27);
+let ThermalPropsDetails = __webpack_require__(29);
+let ElasticConstDetails = __webpack_require__(32);
+let DataStore = __webpack_require__(1);
+let LoadingPopup = __webpack_require__(4);
+
+
+// Store material data at this level (material model) ?
+let materialData = null, materialCalcsData = null;
+
+// Store the default marked tree leafs
+let markedTreeLeafs = { eStruct: null, thermalProps: null };
+
+
+class MaterialMod{
+
+  constructor(){
+    this.element = document.createElement('div');
+    this.element.setAttribute("id",'material-module');
+
+    this.overview = new Overview();
+    this.overview.attachAndSetEvents(this.element);
+
+    this.navTree= new NavTree();
+
+    this.structureViewer = null;
+
+    // They are created hidden
+    // Structure detail section init
+    this.structureDetails = new StructureDetails();
+    this.structureDetails.attachAndSetEvents(this.element);
+
+    // Electronic structure detail section init
+    this.electronicStructDetails = new ElectronicStructDetails();
+    this.electronicStructDetails.attachAndSetEvents(this.element);
+
+    // Methodology detail section init
+    this.methodologyDetails = new MethodologyDetails();
+    this.methodologyDetails.attachAndSetEvents(this.element);
+
+    this.thermalDetails = new ThermalPropsDetails();
+    this.thermalDetails.attachAndSetEvents(this.element);
+
+    this.elasticDetails = new ElasticConstDetails();
+    this.elasticDetails.attachAndSetEvents(this.element);
+
+    this.currentDetailView= null;
+  }
+
+
+  setMaterialView(data){
+    if (materialData === null || materialData.id !== parseInt(data.id) ){
+      this._loadMaterial(data.id, data.view);
+      // Reset the checkboxes to the initial checked value (new material)
+      if (this.structureViewer !== null){
+        this.structureViewer.axisCheckbox.checked = true;
+        this.structureViewer.bondsCheckbox.checked = true;
+      }
+
+    }else{
+      this._setView(data.view);
+      document.querySelector('title').innerHTML = 'NOMAD Encyclopedia - '+
+        util.getMaterialTitle(DataStore.getMaterialData(), false);
+    }
+  }
+
+
+  getCurrentPageStatus(){
+
+    let tempeStructCalcs = null;
+    if (this.currentDetailView === null){
+      tempeStructCalcs = this.overview.getEStructChosenCalcs();
+    }
+
+    return {
+      pageId: this.currentDetailViewId,
+      markedLeaf: this.navTree.getMarkedLeaf(),
+      eStructCalcs: tempeStructCalcs
+    };
+  }
+
 
-	function setCalculations(calcsFromAPI){
-	  calcs = calcsFromAPI;
-	  for (let i = 0; i < calcs.length; i++)
-	    calcMap.set(calcs[i].id, calcs[i]);
-	}
+  _setView(view){
+    //console.log('FFFFF setMaterialView: '+view);
+    // Hide the current view
+    if (this.currentDetailView === null)
+      this.overview.element.style.display= 'none';
+    else
+      this.currentDetailView.element.style.display= 'none';
 
-	function getCalculations(){
-	  return calcs;
-	}
+    if (typeof view === 'undefined'){ // Overview view
+      this.currentDetailView = null;
+      this.currentDetailViewId = null;
+      this.overview.setVisible();//this.overview.element.style.display= 'block';
+      this.navTree.setLeafMarkedListener(undefined);
+      this._setCellViewer(this.overview.vizBox);
+    }else{
+      this.currentDetailViewId = view;
+      this._setDetailView(util.MAT_VIEW[view]);
+    }
+  }
+
+
+  _setCellViewer(hostElement){
+    //console.log('_setCellViewer', this.structureViewer,materialData);
+    if (this.structureViewer === null){
+      this.structureViewer = new StructureViewerWrapper(hostElement);//CellViewer(hostElement);//
+      if (materialData !== null){ // Case: landing at e. structure details page
+        this.structureViewer.load(util.getCellDataForViewer(materialData));
+        this.structureViewer.setMaterialId(materialData.id);
+      }
+    }else
+      this.structureViewer.changeHostElement(hostElement);
+  }
+
+
+  _setDetailView(view) {
+//    console.log('FFFFF _setDetailView: '+view);
+
+    if (view === util.MAT_VIEW.structure){
+      this.currentDetailView= this.structureDetails;
+      this.navTree.showCalcsGraphDataAvalability(false);
+      this.navTree.setHeight(250);
+      this.navTree.setMarkedLeafIfNoneMarked(null); // Set the first leaf marked
+
+    }else if (view === util.MAT_VIEW.electronicstruct){
+      this.currentDetailView= this.electronicStructDetails;
+      this.navTree.showCalcsGraphDataAvalability(true);
+      this.navTree.setHeight(400);
+      this.navTree.setMarkedLeafIfNoneMarked(markedTreeLeafs.eStruct);
+
+    }else if (view === util.MAT_VIEW.methodology){ // Methodology
+      this.currentDetailView = this.methodologyDetails;
+
+    }else  if (view === util.MAT_VIEW.thermalprops){ // Thermal properties
+      this.currentDetailView= this.thermalDetails;
+      this.navTree.showCalcsGraphDataAvalability(true);
+      this.navTree.setHeight(600);
+      this.navTree.setMarkedLeafIfNoneMarked(markedTreeLeafs.thermalProps);
+    }
+
+    /* To be implemented
+    else{ // Elastic constants
+      this.currentDetailView = this.elasticDetails;
+      this.navTree.showCalcsGraphDataAvalability(false);
+      this.navTree.setHeight(600);
+      this.navTree.setMarkedLeafIfNoneMarked(null);
+    }*/
+
+    this.currentDetailView.setVisible();//this.currentDetailView.element.style.display= 'block';
+
+    if (view === util.MAT_VIEW.structure)
+      this._setCellViewer(this.structureDetails.vizBox);
+
+    //this.currentDetailView.setMaterialData(materialData); //// WHY DOES  It do always?
+    if (view !== util.MAT_VIEW.methodology)
+      this.currentDetailView.attachNavTree(this.navTree);
+
+    this.currentDetailView.updateSelection(this.navTree.getTreeSelectedCalcs());
+
+    this.currentDetailView.updateMarkedLeaf(this.navTree.getMarkedLeaf());
+
+    this.navTree.setTreeSelectionListener( leafIds => {
+      this.currentDetailView.updateSelection(leafIds);
+    });
+    this.navTree.setLeafMarkedListener( leafId => {
+      this.currentDetailView.updateMarkedLeaf(leafId);
+    });
+  }
+
+
+  _loadMaterial(matId,view){
+
+    this.overview.element.style.visibility= 'hidden';
+    LoadingPopup.show();
+    util.serverReq(util.getMaterialURL(matId), e1 => {
+
+      materialData= JSON.parse(e1.target.response);
+      util.materialId = materialData.id;
+
+      if (e1.target.status === 200){
+
+        util.serverReq(util.getMaterialXsURL('elements',matId), e2 => {
+          materialData.elements= JSON.parse(e2.target.response).results;
+
+          util.serverReq(util.getMaterialXsURL('cells',matId), e3 => {
+            let cells= JSON.parse(e3.target.response).results;
+            if (!cells[0].is_primitive) materialData.cell= cells[0];
+            else materialData.cell= cells[1];
+
+            DataStore.setMaterialData(materialData);
+            //console.log("CELLS: "+JSON.stringify(materialData.cell));
+            document.querySelector('title').innerHTML =
+              'NOMAD Encyclopedia - '+util.getMaterialTitle(materialData, false);
+            this.overview.setMaterialData();
+            this.structureDetails.setMaterialData();
+            this.electronicStructDetails.setMaterialData();
+            this.methodologyDetails.setMaterialData();
+            this.thermalDetails.setMaterialData();
+            this.elasticDetails.setMaterialData();
+            //console.log("MATDATA LOADED: ");
+            if (this.structureViewer !== null)
+              this.structureViewer.load(util.getCellDataForViewer(materialData));
+
+            util.serverReq(util.getMaterialXsURL('calculations',matId), e4 => {
+              DataStore.setCalculations(JSON.parse(e4.target.response).results);
+
+              util.serverReq(util.getMaterialXsURL('groups', matId), e5 => {
+                DataStore.setGroups(JSON.parse(e5.target.response).groups);
+
+                let name = (materialData.material_name === null ?
+                  materialData.formula : materialData.material_name);
+                this.navTree.build(name);
+                this.overview.setCalcsData(markedTreeLeafs);
+                this.navTree.selectAll();
+                //console.log('MaterialMod - thermalPropsDetailsTreeLeaf: ', markedTreeLeafs.thermalProps);
+
+                this._setView(view);
+                this.overview.element.style.visibility= 'visible';
+                LoadingPopup.hide();
+              });
+            });
+          });
+        });
+
+      }else{ // Error - First request
+         }
+
+    });
+  }
+} // class MaterialMod
+
+
+// Wrapper the structure viewer to be properly integrated
+// on the UI components showing it
+class StructureViewerWrapper{
+
+  constructor(hostElement){
+    this.hostElement = hostElement;
+
+    this.viewer = new StructureViewer(hostElement);
+    //Get the focus -> this.viewer.renderer.domElement.setAttribute('tabindex', '0');
+
+    this.legendElement = document.createElement('div');
+    this.legendElement.setAttribute('class', 'element-labels');
+    this.legendElement.setAttribute('style', 'position: absolute; bottom: 50px; right: 0');
+    this.hostElement.appendChild(this.legendElement);
+
+    this.footerElement = document.createElement('div');
+    this.footerElement.setAttribute('class', 'structure-viewer-legend');
+    this.hostElement.appendChild(this.footerElement);
+    this.footerElement.innerHTML = `
+
+    <div style="float: left; padding-right: 12px" >
+      <input type="checkbox" class="show-axis" checked> Show axis
+    </div>
+
+    <div style="float: left; padding-right: 18px" >
+      <input type="checkbox" class="show-bonds" checked> Show bonds
+    </div>
+
+    <div style="float: left; position:relative;" >
+      <img class="view-reset" style="cursor: pointer;" height="18px"
+        src="${util.IMAGE_DIR}reset.svg" />
+      <div class="view-reset-tooltip" > Set original view </div>
+    </div>
+
+    <!--
+    <div class="view-reset-tooltip" style="float: left; display: none; font-size: 0.8em;" >
+      Set original <br> &nbsp; view
+    </div>
+    -->
+
+    <div class="vr-download" style="float: right"> </div>
+
+    <div style="clear: both;"></div>
+    `;
+
+    this.axisCheckbox = this.footerElement.querySelector('.show-axis');
+    this.axisCheckbox.addEventListener('click', e => {
+      this.viewer.toggleLatticeParameters(this.axisCheckbox.checked);
+    });
+
+    this.bondsCheckbox = this.footerElement.querySelector('.show-bonds');
+    this.bondsCheckbox.addEventListener('click', e => {
+      this.viewer.toggleBonds(this.bondsCheckbox.checked);
+    });
+
+    this.labelsContainer = this.hostElement.querySelector('.element-labels');
+
+    this.vrLinksContainer = this.footerElement.querySelector('.vr-download');
+    this.vrDropDown = new DropDown();
+    this.vrLinksContainer.appendChild(this.vrDropDown.element);
+
+    let resetButton = this.hostElement.querySelector('.view-reset');
+    resetButton.addEventListener('click', e =>  this.viewer.reset() );
+
+    resetButton.addEventListener('mouseover', e => {
+      this.hostElement.querySelector('.view-reset-tooltip').style.display = 'block';
+    });
+    resetButton.addEventListener('mouseout', e => {
+      this.hostElement.querySelector('.view-reset-tooltip').style.display = 'none';
+    });
+  }
+
+  load(data){
+    this.viewer.load(data);
+    this.createElementLegend();
+  }
+
+  setMaterialId(id){
+    this.vrDropDown.setMaterialId(id);
+  }
+
+  changeHostElement(hostElement){
+    if (this.hostElement !== hostElement){
+      this.hostElement.removeChild(this.legendElement);
+      this.hostElement.removeChild(this.footerElement);
+      this.hostElement = hostElement;
+      this.viewer.changeHostElement(hostElement);
+      this.hostElement.appendChild(this.legendElement);
+      this.hostElement.appendChild(this.footerElement);
+    }
+  }
+
+
+  createElementLegend() {
+    // Empty the old legend
+    this.labelsContainer.innerHTML = '';
+
+    let elements = this.viewer.elements;
+    // Create a list of elements
+    let elementArray = [];
+    for (let property in elements) {
+      if (elements.hasOwnProperty(property))
+        elementArray.push([property, elements[property][0], elements[property][1]]);
+    }
+
+    // Sort by name
+    elementArray.sort(function (a, b) {
+      if (a[0] < b[0]) return -1;
+      if (a[0] > b[0]) return 1;
+      return 0;
+    });
+
+    let svgElement = document.createElementNS("http://www.w3.org/2000/svg", "svg");
+    svgElement.setAttribute("width", 50);
+    svgElement.setAttribute("height", elementArray.length*25);
+
+    this.labelsContainer.appendChild(svgElement);
+
+    for (let i = 0; i < elementArray.length; ++i) {
+      let elementName = elementArray[i][0];
+      //let elementColor = "#" + elementArray[i][1].toString(16); Lauri's bugfixing feb-2017
+      let elementColor = elementArray[i][1].toString(16);
+      let nZeros = 6 - elementColor.length;
+      let prefix = "#" + Array(nZeros + 1).join("0");
+      elementColor = prefix + elementColor;
+
+      //let elementRadius = 25 * elementArray[i][2];
+      //elementRadius = Math.min(100, elementRadius);
+      //elementRadius = Math.max(30, elementRadius);
+      svg.addCircle(svgElement, 10, 25*i+12, 8,  elementColor, "#777", 1);
+      svg.addText(svgElement,  24, 25*i+18, elementName, 'start', 'structure-viewer-legend-labels');
+    }
+  }
+} // class StructureViewerWrapper
+
+
+// used exclusively in StructureViewerWrapper
+class DropDown{
+
+  constructor(materialId){
+    this.folded = true;
+    this.element = document.createElement('div');
+    //this.element.className = className;
+
+    this.element.innerHTML+=`
+      <div >
+        <span style=" vertical-align: 30%; ">Virtual Reality files</span>
+        <img style="cursor: pointer" src="${util.IMAGE_DIR}folded.png" />
+      </div>
+
+      <div class="vr-download-panel" style="position: relative; display: none">
+
+      </div>
+    `;
+
+    // Focus related properties (in order to hide the box when the user click out)
+    this.element.tabIndex = '0'; // enabled the support of focusing
+    this.element.style.outline = 'none'; // The outline is not shown when it gains the focus
+
+    this.foldingPanel = this.element.querySelector('.vr-download-panel');
+    this.foldBtn = this.element.querySelector('img');
+
+    this.foldBtn.addEventListener('click', e => {
+      this.folded = !this.folded;
+      this.foldBtn.src = (this.folded ? util.IMAGE_DIR+'folded.png' :
+        util.IMAGE_DIR+'unfolded.png');
+      //this.foldBtn.className = (this.folded ? 'on' : 'off');
+      this.foldingPanel.style.display = (this.folded ? 'none' : 'block');
+    });
+
+    this.element.addEventListener('blur' , e => {
+      this.folded = true;
+      this.foldBtn.src = util.IMAGE_DIR+'folded.png';
+      this.foldingPanel.style.display = 'none';
+    });
+
+      //this.cellViewer.toggleLatticeParameters(false);
+  }
+
+  setMaterialId(id){
+    this.foldingPanel.innerHTML = `
+    <div class="vr-download-panel-unfolded" style="width: 210px;">
+      <div style="padding: 5px; ">
+        <a href="http://nomad.srv.lrz.de/cgi-bin/NOMAD/material?${id}">Get VR file</a>
+      </div>
+      <br>
+      <div style="padding-bottom: 5px; ">Visualization tools for specific devices:</div>
+
+      <div style="padding: 5px; ">
+        <a href="http://nomad.srv.lrz.de/NOMAD/NOMADViveT-Setup.exe">HTC Vive</a>
+      </div>
+      <!--
+      <div style="padding: 5px; ">
+        <a href="http://nomad.srv.lrz.de/NOMAD/NOMADGearvrT.apk">Samsung GearVR</a>
+      </div>
+      -->
+      <div style="padding: 5px; ">
+        <a target="_blank" href="https://play.google.com/store/apps/details?id=com.lrz.nomadvr">Google Cardboard</a>
+      </div>
+
+    </div>
+    `
+  }
+
+} // class DropDown
+
+
+// EXPORTS
+module.exports = MaterialMod;
+
+
+/***/ }),
+/* 10 */
+/***/ (function(module, exports, __webpack_require__) {
 
-	function getCalc(calcId){
-	  return calcMap.get(calcId);
-	}
 
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
 
 
-	let groups;
+ /*
+    This component implements a generic switch/toggle button
+ */
 
-	function processCalcGroups(groupsFromAPI){
 
-	  let methodCalcsMap = new Map();
-	  groupsFromAPI.forEach( (group, i) => {
-	    if (group.group_type !== 'method'){
-	      let calcsMins;
-	      if (methodCalcsMap.has(group.method_hash) ){
-	        calcsMins = methodCalcsMap.get(group.method_hash);
-	      }else{
-	        calcsMins = {'ids': [], 'minEnergies': []};
-	        methodCalcsMap.set(group.method_hash, calcsMins);
-	      }
-	      calcsMins.ids.push(group.representative_calculation_id);
-	      calcsMins.minEnergies.push(group.energy_minimum);
-	    }
-	  });
+let util = __webpack_require__(0);
 
-	  let methodRepresentativeMap = new Map();
-	  methodCalcsMap.forEach( (calcsData, methodHash) => {
-	    let minVal = Math.min.apply(null, calcsData.minEnergies);
-	    let index = calcsData.minEnergies.indexOf(minVal);
-	    methodRepresentativeMap.set(methodHash, calcsData.ids[index]);
-	  });
+class SwitchComponent {
 
-	  let calcsInGroups = new Map();
-	  groupsFromAPI.forEach( (group, i) => {
-	    if (group.group_type !== 'method'){
-	      let groupData = {
-	        'calcs': new Set(),
-	        'method_representative': methodRepresentativeMap.get(group.method_hash)
-	      };
-	      calcsInGroups.set(
-	        getGroupTypeCode(group)+group.representative_calculation_id, groupData);
-	      //let calcSet = new Set(); // The representative is (not?) in the set
-	      group.calculations_list.forEach( calcId => groupData.calcs.add(calcId) );
-	    }
-	  });
-	  return calcsInGroups;
-	}
+  constructor(imageBasePath) {
 
-	function setGroups(groupsFromAPI){
-	  groups = processCalcGroups(groupsFromAPI);
-	}
+    this.off = true;
 
-	function getGroups(){
-	  return groups;
-	}
+    this.element = document.createElement('span');
+    this.element.innerHTML+=`
+       <img src="${imageBasePath}_off.png" width="24px"
+        style="margin-bottom: -1px; cursor: pointer"/>
+    `;
+    this.image = this.element.querySelector('img');
 
-	function getGroupTypeCode(group){
-	  if (group.group_type === 'equation of state') return 'eos';
-	  else if (group.group_type === 'convergence') return 'par';
-	}
+    this.element.addEventListener('click', e => {
+      this.off = !this.off;
+      let imagePath = (this.off ? imageBasePath+'_off' : imageBasePath);
+      this.image.setAttribute('src',imagePath+'.png');
+      this.listener(this.off);
+    });
+  }
 
-	function getGroupType(leafId){
-	  let code = leafId.substring(0,3);
-	  if (code === 'eos') return 'equation of state';
-	  else if (code === 'par') return 'convergence';
-	  else return null;
-	}
 
-	function isGroup(leafId){//*** ********** REFACTOR
-	  return (leafId.substring(0,3) === 'eos' || leafId.substring(0,3) === 'par');
-	}
+  setListener(listener){
+    this.listener = listener;
+  }
+}
 
-	function getCalcReprIntId(leafId){
-	  if (isGroup(leafId)) return parseInt(leafId.substring(3));
-	  else return parseInt(leafId);
-	}
+// EXPORTS
+module.exports = SwitchComponent;
 
-	function isInAnyGroup(calcId){
-	  let thereIs = false;
-	  groups.forEach( (groupData, groupId) => {
-	    //console.log('isInAnyGroup', calcId, groupData.calcs);
-	    if (groupData.calcs.has(calcId)) thereIs = true;//return true;
-	  });
-	  return thereIs;
-	}
 
-	function isInAnyNotDisabledGroup(calcId){
-	  let thereIs = false;
+/***/ }),
+/* 11 */
+/***/ (function(module, exports, __webpack_require__) {
 
-	  groups.forEach( (groupData, groupId) => {
-	    let representative = getCalc(getCalcReprIntId(groupId));
-	    //let codeNameTrimed= representative.code_name.trim();
-	    //console.log('isInAnyGroup', calcId, groupData.calcs);
+"use strict";
+
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+ /*
+  Implements the DOS plotter.
+ */
 
-	    /***** Exception: disable grouping for some codes
-	    if (codeNameTrimed !== 'VASP' && codeNameTrimed !== 'FHI-aims'
-	      && groupData.calcs.has(calcId)) thereIs = true; */
-	    if (groupData.calcs.has(calcId)) thereIs = true;
-	  });
-	  return thereIs;
-	}
 
-	function getGroupLeafId(calcId){
-	  let leafId = null;
-	  groups.forEach( (groupData, groupId) => {
-	    //console.log('isInAnyGroup', calcId, groupData.calcs);
-	    if (groupData.calcs.has(calcId)) leafId = groupId;//return true;
-	  });
-	  //console.log('getGroupLeafId', leafId);
-	  return leafId;
-	}
 
 
-	let hasThermalData, hasElecStructureData;
+let InteractivePlotterBase = __webpack_require__(8);
+let svg = __webpack_require__(2);
+let util = __webpack_require__(0);
+
 
-	/*
-	function hasThermalData(bool){
-	  hasThermalData = bool;
-	}
+const E_MIN = -6;
+const E_MAX = 11;
+const E_FACTOR = 1.602176565e-19;
+//const DOSVALUE_FACTOR = 1.602176565e-49;
 
-	function setHasThermalData(bool){
-	  hasThermalData = bool;
-	}
 
-	function hasElecStructureData(bool){
-	  hasThermalData = bool;
-	}
+class DOSPlotter extends InteractivePlotterBase{
 
-	function setHasElecStructureData(bool){
-	  hasElecStructureData = bool;
-	}*/
+  constructor(margins) {
+    super(margins);
+  }
 
+  // detach if necessary and attach
+  attach(element, width, height){
+    super.attach(element, width, height);
+  }
 
 
-	// EXPORTS
-	module.exports = { setMaterialData, getMaterialData, getCalculations, getCalc,
-	  setCalculations, getGroups, setGroups, isGroup, getGroupType,
-	  getCalcReprIntId, isInAnyGroup, isInAnyNotDisabledGroup, getGroupLeafId,
-	 hasThermalData, hasElecStructureData};
+  setPoints(points, codeName){
 
+    let dosValueDivisor =  E_FACTOR;
+    //if (codeName === 'VASP') dosValueDivisor =  1e-10*(E_FACTOR*E_FACTOR);
 
-/***/ },
-/* 3 */
-/***/ function(module, exports) {
+    this.pointsSpin1 = [];
+    this.pointsSpin2 = [];
+    this._reset();
 
-	
-	const Conf = {};
+    let pSpin1= points.dos_values[0];
+    let pSpin2 = null;
+    if (points.dos_values.length === 2)  pSpin2 = points.dos_values[1];
+    let pointsY= points.dos_energies;
+    let pointsXInPlotRange = [];
+    let pointsYInPlotRange = [];
 
-	Conf.GuestUserToken =
-	  'eyJhbGciOiJIUzI1NiIsImlhdCI6MTUyMzg4MDE1OSwiZXhwIjoxNjgxNTYwMTU5fQ.ey'+
-	  'JpZCI6ImVuY2d1aSJ9.MsMWQa3IklH7cQTxRaIRSF9q8D_2LD5Fs2-irpWPTp4';
+    for (var i = 0; i < pointsY.length; i++) {
+      let energy = pointsY[i]/E_FACTOR;
+      let dos_value_spin1 = pSpin1[i]/dosValueDivisor;
+      pointsXInPlotRange.push(dos_value_spin1);
+      if (pSpin2 !== null) pointsXInPlotRange.push(pSpin2[i]);
+      pointsYInPlotRange.push(energy);
+      //console.log('POINTS : ',pointsX[i], energy);
+      this.pointsSpin1.push({x: dos_value_spin1, y: energy});
+      if (pSpin2 !== null)
+        this.pointsSpin2.push({x: pSpin2[i]/dosValueDivisor, y: energy});
+    }
 
+    let maxDosVal = Math.max.apply(null, pointsXInPlotRange);
+    let maxEnergyVal = Math.max.apply(null, pointsYInPlotRange);
+    let minEnergyVal = Math.min.apply(null, pointsYInPlotRange);
 
-	// EXPORTS
-	module.exports = Conf;
+    // x axis steps generation
+    let t = util.generateDiagramSteps(maxDosVal);
+    let xSteps = t[0], exp = t[1];
 
+    this.setAxisRangeAndLabels(null, 0, xSteps[xSteps.length-1], 'Energy (eV)',
+      E_MIN, E_MAX, minEnergyVal, maxEnergyVal, 5);
 
-/***/ },
-/* 4 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-	   This component is the loading popup window 
-	 */
-
-
-	"use strict";
-
-	let util = __webpack_require__(1);
-
-	let loadingPopup = document.querySelector('#loading-popup');
-
-	function show(){
-	  let ttRect = loadingPopup.getBoundingClientRect();
-	  let leftPos =  (window.innerWidth - ttRect.width)/2;
-	  let topPos = (window.innerHeight -ttRect.height)/2;
-	  loadingPopup.style.left = leftPos+'px';
-	  loadingPopup.style.top = (topPos-100)+'px';
-	  loadingPopup.style.visibility = 'visible';
-	}
+    svg.addText(this.axisGroup, this.plotRangeX/2, this.margins.bottom,
+      'DOS (states/eV/cell)', 'middle', 'axis-steps-big');
 
-	function hide(){
-	  loadingPopup.style.visibility = 'hidden';
-	}
+    // draw x axis steps
+    for (let i = 0; i < xSteps.length; i++) {
+      let stepX = (this.plotRangeX*xSteps[i])/xSteps[xSteps.length-1];
+      svg.addLine(this.axisGroup, stepX, 0, stepX, 3, 1);
+      //console.log('step ',xSteps[i], stepX);
+      svg.addText(this.axisGroup, stepX, 13,
+        (i === 0 ? '0' : xSteps[i].toFixed(exp)),'middle', 'axis-steps-smaller');
+    }
 
-	// EXPORTS
-	module.exports = { show, hide };
+    this.repaint();
+  }
 
 
-/***/ },
-/* 5 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-	   This component is the popup window (and the darkened background) with a form
-	   inside used for users to report (flagging) errors on the calculations
-	 */
-
-	"use strict";
-
-	let util = __webpack_require__(1);
-	let DataStore = __webpack_require__(2);
-
-	// main DOM elements
-	let flaggingPopupBackground = document.querySelector('#flagging-form-popup-bg');
-	let flaggingFormPopup = document.querySelector('#flagging-form-popup');
-	flaggingFormPopup.innerHTML =`
-
-	<div> <img src="img/cross.svg"  height="12px"
-	  style="float: right; cursor: pointer" />
-	</div>
-
-	<div class="form-wrapper">
-	  <div class="popup-title"> Error reporting</div>
-	  <select id="flagging-category" name="category">
-	    <option value="">Select a category *</option>
-	    <option value="structure">Structure</option>
-	    <option value="electronicstruct">Electronic structure</option>
-	    <option value="methodology">Methodology</option>
-	    <option value="thermalprops">Thermal properties</option>
-	  </select>
-
-	  <select id="flagging-subcategory" name="subcategory">
-
-	  </select>
-
-	  <textarea id="subject" name="subject" style="height:200px"
-	  placeholder="Write a short explanation about the error detected" ></textarea>
-
-	  <div id="form-validation-msg"> </div>
-
-	  <div style="display: flex; justify-content: space-evenly;">
-	    <button style="display: block">Send</button>
-	  </div>
-
-
-	</div>
-	`;
-
-	// Form elements
-	let categoryField = flaggingFormPopup.querySelector('#flagging-category');
-	let eStructOption = categoryField.querySelector('option[value="electronicstruct"]');
-	let thermalOption = categoryField.querySelector('option[value="thermalprops"]');
-	let subcategoryField = flaggingFormPopup.querySelector('#flagging-subcategory');
-	let closeButton= flaggingFormPopup.querySelector('img');
-	let validationMsg = flaggingFormPopup.querySelector('#form-validation-msg');
-	let sendButton= flaggingFormPopup.querySelector('button');
-
-	let treeLeaf = null;
-	let overviewEStructCalcs = null;
-
-
-	function _setCurrentPage(pageId){
-
-	  subcategoryField.innerHTML = '';
-
-	  if (pageId === null){
-	    categoryField.disabled = false;
-	    subcategoryField.style.display = 'none';
-
-	  }else{
-	    categoryField.disabled = true;
-	    subcategoryField.style.display = 'block';
-	    subcategoryField.appendChild(createOption('Choose the subcategory *', ''));
-
-	    switch (pageId) {
-
-	      case util.MAT_VIEW.structure:
-	        categoryField.selectedIndex = 1;
-	        subcategoryField.appendChild(createOption('Structure representation'));
-	        subcategoryField.appendChild(createOption('Calculation tree'));
-	        subcategoryField.appendChild(createOption('Summary'));
-	        subcategoryField.appendChild(createOption('Specific calculation'));
-	        break;
-
-	      case util.MAT_VIEW.electronicstruct:
-	        categoryField.selectedIndex = 2;
-	        subcategoryField.appendChild(createOption('Calculation tree'));
-	        subcategoryField.appendChild(createOption('Summary'));
-	        subcategoryField.appendChild(createOption('Band structure'));
-	        subcategoryField.appendChild(createOption('DOS'));
-	        subcategoryField.appendChild(createOption('Brillouin zone'));
-	        break;
-
-	      case util.MAT_VIEW.methodology:
-	        categoryField.selectedIndex = 3;
-	        subcategoryField.style.display = 'none';
-	        break;
-
-	      case util.MAT_VIEW.thermalprops:
-	        categoryField.selectedIndex = 4;
-	        subcategoryField.appendChild(createOption('Calculation tree'));
-	        subcategoryField.appendChild(createOption('Phonon dispersion'));
-	        subcategoryField.appendChild(createOption('Phonon DOS'));
-	        subcategoryField.appendChild(createOption('Specific heat'));
-	        subcategoryField.appendChild(createOption('Helmholtz free energy'));
-	        break;
-	    }
-	  }
+  repaintData(){
 
-	} // function _setCurrentPage
+    let polylinePoints = '';
+    for (var i = 0; i < this.pointsSpin1.length; i++) {
+      polylinePoints+= ' '+this.xRel*this.pointsSpin1[i].x+
+        ' '+this.transformY(this.pointsSpin1[i].y);
+    }
+    svg.addPolyline(this.plotContent, polylinePoints, 'plotSpin1');
 
+    polylinePoints = '';
+    for (var i = 0; i < this.pointsSpin2.length; i++) {
+      polylinePoints+= ' '+this.xRel*this.pointsSpin2[i].x+
+        ' '+this.transformY(this.pointsSpin2[i].y);
+    }
+    svg.addPolyline(this.plotContent, polylinePoints, 'plotSpin2');
+  }
 
-	function show(pageStatus){
-	  //console.log('pageStatus : ',pageStatus);
-	  treeLeaf = pageStatus.markedLeaf;
-	  overviewEStructCalcs = pageStatus.eStructCalcs;
 
-	  // Show/hide some dropdown list options
-	  eStructOption.style.display = (DataStore.hasElecStructureData ? 'block' : 'none');
-	  thermalOption.style.display = (DataStore.hasThermalData ? 'block' : 'none');
+  setYAxisLabelsVisibility(value){
+    if (this.yAxisLabelsGroup !== null)
+      this.yAxisLabelsGroup.style.visibility = (value ? 'visible' : 'hidden');
+  }
 
-	  _setCurrentPage(pageStatus.pageId);
+}
 
-	  let ttRect = flaggingFormPopup.getBoundingClientRect();
-	  let leftPos =  (window.innerWidth - ttRect.width)/2;
-	  let topPos = (window.innerHeight -ttRect.height)/2;
-	  flaggingFormPopup.style.left = leftPos+'px';
-	  flaggingFormPopup.style.top = (topPos-20)+'px';
 
-	  flaggingFormPopup.style.visibility = 'visible';
-	  flaggingPopupBackground.style.visibility = 'visible';
-	}
+// EXPORTS
+module.exports = DOSPlotter;
 
 
-	function hide(){
-	  flaggingPopupBackground.style.visibility = 'hidden';
-	  flaggingFormPopup.style.visibility = 'hidden';
-	  // reset UI
-	  categoryField.selectedIndex = 0;
-	  subcategoryField.selectedIndex = 0;
-	  flaggingFormPopup.querySelector('textarea').value = '';
-	  validationMsg.innerHTML = '';
-	}
+/***/ }),
+/* 12 */
+/***/ (function(module, exports, __webpack_require__) {
 
+"use strict";
 
-	function createOption(text, value){
-	  let opt = document.createElement('option');
-	  opt.value = (value === undefined ? text : value);
-	  opt.innerHTML = text;
-	  return opt;
-	}
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
 
 
-	closeButton.addEventListener('click', e => {
-	  hide();
-	});
+ /*
+  Specific Heat plotter implementation
+ */
 
 
-	sendButton.addEventListener('click', e => {
 
-	  let categoryChosen = categoryField.options[categoryField.selectedIndex];
 
-	  if (!categoryField.disabled && categoryChosen.value === ''){ // Overview case
-	    validationMsg.innerHTML = 'The category fields must be set';
+let svg = __webpack_require__(2);
+let PlotterBase = __webpack_require__(5);
 
-	  }else if (categoryField.disabled && subcategoryField.value === '' // Detaisl pages case
-	            && categoryChosen.value !== util.MAT_VIEW.methodology){
-	    validationMsg.innerHTML = 'The subcategory fields must be set';
 
-	  }else{
-	    validationMsg.innerHTML = 'Sending report...';
-	    let textareaText = flaggingFormPopup.querySelector('textarea').value;
-	    let materialId = DataStore.getMaterialData().id;
-	    let userdata = util.getUserData();
+class HeatCapPlotter extends PlotterBase{
 
+  constructor() {
+    super({left: 50, right: 16, top: 10, bottom: 32});
+    this.tooltip;
+  }
 
-	    let titleText = 'User issue | Material '+materialId;
-	    let descriptionText = '**Server:** '+util.getServerLocation()+
-	      '\\n\\n**User:** '+userdata.username+', '+userdata.email;
 
-	    // Overview page
-	    if ( !categoryField.disabled){
-	      descriptionText += '\\n\\n**Category:** Overview / '+categoryChosen.text;
+  setData(data){
+    //console.log(JSON.stringify(data));//
+    this.clear();
+    // up to 600K data is taken
+    let indexOf600K = data.temperature.indexOf(600)+1;
+    let values = data.value.slice(0, indexOf600K);
+    let temperatures = data.temperature.slice(0, indexOf600K);
 
-	      if (categoryChosen.value === util.MAT_VIEW.electronicstruct
-	          && overviewEStructCalcs !== null)
-	        descriptionText += '\\n\\n**Chosen calculations:** '+
-	          (overviewEStructCalcs.bs === null ? '' : 'BS calculation '+overviewEStructCalcs.bs)+
-	          (overviewEStructCalcs.dos === null ? '' : ' DOS calculation '+overviewEStructCalcs.dos);
+    let yMaxValue = Math.max.apply(null, values);
+    //console.log('maxValue: ',maxValue);//
+    this.setRangeAndLabels('T (K)', 0, 600, 'Cv (J/K/kg)', 0, Math.ceil(yMaxValue/200)*200);
+    this.drawAxis(4, 4, 0);
 
-	    }else{ // Details pages
-	      descriptionText += '\\n\\n**Category:** '+categoryChosen.text;
+    let polylinePoints = '';
+    temperatures.forEach( (t, i) => {
+        let y = values[i];///1e-25;
+        polylinePoints+= ' '+this.xRel*t+' -'+this.yRel*(y - this.yMin);
+    });
+    svg.addPolyline(this.plotArea, polylinePoints, 'plotSpin1');
+  }
 
-	      if (categoryChosen.value !== util.MAT_VIEW.methodology){
-	        descriptionText += '\\n\\n**Subcategory:** '+
-	          subcategoryField.options[subcategoryField.selectedIndex].text+
-	          '\\n\\n**Calculation/group marked on the tree:** '+treeLeaf;
-	      }
-	    }
+}
 
-	    descriptionText += '\\n\\n**User text:** '+textareaText;
 
-	    let queryJson =`{
-	      "title": "${titleText}",
-	      "description": "${descriptionText}"}`;
-	    console.log('Flagging POST request Json: ',queryJson);//, util.getFlaggingURL());
+// EXPORTS
+module.exports = HeatCapPlotter;
 
 
-	    util.serverReqPOST(util.getFlaggingURL(), queryJson, e => {
-	      console.log('response',e);
-	      if (e.target.status === 200) hide();
+/***/ }),
+/* 13 */
+/***/ (function(module, exports) {
+
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+ /*
+  This class implements the bar to select calculations on a material
+ */
+
+
+class CalcSelectorBar{
+
+  constructor(className, width){
+    this.first = true;
+    this.last = false;
+    this.element = document.createElement('div');
+    this.element.className = className;
+    if (width !== undefined) this.element.style.width = width;
+    this.element.innerHTML = `
+      <div class="prev-sel-btn" style="float: left; width: 20%;">
+        <div style="padding-left: 10%;">
+          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10.069 11.872" width="20px">
+            <path transform="scale(0.7) translate(-346.291 -664.481)"
+              d="M356.36,666.024l-1.544-1.544-8.525,8.513,8.493,8.447,1.544-1.544-6.8-6.9Z" />
+          </svg>
+        </div>
+      </div>
+      <div class="calc-sel-text" style="float: left; width: 60%;">
+       NOT Calculation
+      </div>
+      <div class="next-sel-btn" style="float: right; width: 20%;">
+        <div style="padding-right: 10%;">
+          <svg xmlns="http://www.w3.org/2000/svg" viewBox="-10.069 -11.872 10.069 11.872" width="20px">
+            <g transform="rotate(180) scale(0.7)">
+              <path d="M10.069,1.544,8.525,0,0,8.513,8.493,16.96l1.544-1.544-6.8-6.9Z"/>
+            </g>
+          </svg>
+        </div>
+      </div>
+      <div style="clear: both;"></div>
+    `;
+
+    this.prevBtn = this.element.querySelector('.prev-sel-btn');
+    this.prevIcon = this.element.querySelector('.prev-sel-btn path');
+    this.calcSelectorTxt = this.element.querySelector('.calc-sel-text');
+    this.nextBtn = this.element.querySelector('.next-sel-btn');
+    this.nextIcon = this.element.querySelector('.next-sel-btn path');
+    this._styleButtons();
+    this._events();
+  }
+
+
+  _events() {
+    this.prevBtn.addEventListener( "click", e => {
+      e.preventDefault();
+      if (this.first) return;
+      /*** repensar esto es problematico porque necesita poder ser configurado desde fuera **/
+      //if (this.last)  this.last = false;
+      this.first = this.prevListener();
+      this.last = false;
+      this._styleButtons();
+    });
+
+    this.nextBtn.addEventListener( "click", e => {
+      e.preventDefault();
+      if (this.last) return;
+      //if (this.first)  this.first = false;
+    //  this.last = this.nextListener();
+      this.first = false;
+      this.last = this.nextListener();
+      this._styleButtons();
+    });
+  }
+
+
+  _styleButtons(){
+    this.prevIcon.setAttribute("class",
+      'calc-selector-icon'+(this.first ? '-disabled' : ''));
+    this.nextIcon.setAttribute("class",
+      'calc-selector-icon'+(this.last ? '-disabled' : ''));
+  }
+
+
+  setPrevListener(listener){
+    this.prevListener = listener;
+  }
+
+
+  setNextListener(listener){
+    this.nextListener = listener;
+  }
+
+
+  setState(text, first, last){
+    this.calcSelectorTxt.innerHTML = text;
+    this.first = first;
+    this.last = last;
+    this._styleButtons();
+  }
+
+}
+
+
+// EXPORTS
+module.exports = CalcSelectorBar;
+
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+ /*
+  The StatsViewer class implements a graphical UI component composed of
+  a points plotter and a frecuency graph.
+  (classes defined in this file MainGraph and FrequencyGraph)
+ */
+
+
+
+
+let svg = __webpack_require__(2);
+let PlotterBase = __webpack_require__(5);
+
+
+class MainGraph extends PlotterBase{
+
+  constructor() {
+    super({left: 54, right: 20, top: 20, bottom: 30});
+    this.tooltip;
+  }
+
+
+  drawPoints(points){
+    for (let i = 0; i < points.length; i++) {
+      //console.log('drawPoint '+this.xRel, i, this.yRel, points[i]);
+	    let pointElement = svg.addPoint(this.plotArea,
+        this.xRel*i, -this.yRel*(points[i] - this.yMin), 2, 'stats-viewer-point');
+
+	    pointElement.addEventListener('mouseover', (e) => {
+		    this.tooltip = svg.addText(this.plotArea, e.target.getBBox().x+6,
+          e.target.getBBox().y-4, (points[i]).toFixed(2), 'start', 'tooltip');
+        /*getBBox() Rect data (x, y, w, h) of the element were the event happendd,
+          coordenate system: the parent element coordinate system */
+      });
+	    pointElement.addEventListener('mouseout', (e) => {
+		    svg.removeElement(this.tooltip);
 	    });
-
-	  }
-
-	});
-
-
-
-	// EXPORTS
-	module.exports = { show, hide };
-
-
-/***/ },
-/* 6 */
-/***/ function(module, exports) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-	   This file implements the design pattern pub/sub, which allows one module
-		 to broadcast messages to other modules.
-	 */
-
-	"use strict";
-
-	var messages = new Map();
-	var lastUid = -1;
-
-	  /**
-	   *	subscribe( message, func ) -> String
-	   *	- message (String): The message to subscribe to
-	   *	- func (Function): The function to call when a new message is published
-	   *	Subscribes the passed function to the passed message. Every returned token
-	   *	is unique and should be stored if you need to unsubscribe
-	  **/
-	function subscribe( message, func ){
-	  //console.log('SUBSCRIBING Message '+message);
-		if ( typeof func !== 'function'){
-			return false;
-		}
-		// message is not registered yet
-		if ( !messages.has( message ) ){
-			messages.set( message, new Map());
-		}
-		// forcing token as String, to allow for future expansions without breaking usage
-		// and allow for easy use as key names for the 'messages' object
-		var token = 'uid_' + String(++lastUid);
-		messages.get(message).set(token, func); //messages[message][token] = func;
-	  //print();
-		// return token for unsubscribing
-		return token;
-	}
-
-
-	function publish( message, data){
-
-	  var hasSubscribers = messages.has( message )
-	                       && (messages.get( message ).size > 0);
-
-		if ( !hasSubscribers ){
-			return false;
 	  }
+  }
 
-	  var deliver = function (){
-	    //deliverMessage(message, data);
-	    var subscribers = messages.get(message);
-	    //console.log('DELIVERING Message '+message);
-	    subscribers.forEach(function(func, token) {
-	      func(data);
-	      //console.log('EXE funct   '+ func);
-	    });
-	  };
+}
 
-	  setTimeout( deliver, 0 );  // async
-		return true;
-	}
 
+class FrequencyGraph extends PlotterBase{
 
-	function print(){
-	  console.log('PubSub data: ');
-	  messages.forEach(function(functions, msg) {
-	    console.log(msg + ': ');
+  constructor() {
+    super({left: 4, right: 10, top: 20, bottom: 30});
+  }
 
-	    functions.forEach(function(func, token) {
-	      console.log('    '+token + ': ' + func);
-	    });
+  drawBars(points, yMin, yRange){
+	  let ranges = [0,0,0,0,0,0,0,0,0,0];
+	  points.forEach(point => {
+	    let rangeIndex = Math.floor(((point-yMin)/yRange)*10);
+      if (rangeIndex > 9) rangeIndex = 9;
+	    ranges[rangeIndex] += 1;
 	  });
-	}
-
-	// EXPORTS
-	module.exports = { subscribe: subscribe, publish: publish };
-
-
-/***/ },
-/* 7 */
-/***/ function(module, exports) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-	   This file implements the app Routing system: the feature that allows
-	   the page navigation in a single-page environment.
-	 */
-
-
-	"use strict";
-
-	let routes = new Map();
-
-
-	function add(route, func){
-	  routes.set(route, func);
-	}
-
-
-	window.addEventListener("hashchange", route);
-
-	function route(){
-	  let hashPath= document.location.hash.substring(2);
-	  let command, param, subparam;
-
-	  // remove the ending /
-	  if (hashPath.lastIndexOf('/') === (hashPath.length-1))
-	    hashPath = hashPath.substring(0,hashPath.length-1);
-
-	  if (hashPath.indexOf('/') >0){
-	    let a= hashPath.split('/');
-	    command= a[0];
-	    param= a[1];
-	    subparam= a[2];
-	  }
-	  else command= hashPath;
-
-	  //console.log("hashPath: " + hashPath+' command: '+command+' param: '+param+' subparam: '+subparam);
-
-	  if (routes.has(command)) {
-	    routes.get(command)(param, subparam);
-	  }
-	};
-
-
-	function print(){
-	  console.log('Router data: ');
-	  routes.forEach(function(func, url) {
-	    console.log(url + ': ' + func);
+	  ranges.forEach((value, index) => {
+	    let yBar= (index + 0.5)*this.yRel;
+	    svg.addLine(this.plotArea, 0, -yBar, value*this.xRel, -yBar, 'bar');
 	  });
-	}
-
-
-	// EXPORTS
-	module.exports = { add: add, route: route };
-
-
-/***/ },
-/* 8 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-	  This file implements the Material Module of the application.
-	  It's a UI component container that displays the selected material information.
-	  It's complex because of the amount and diversity of material info available.
-
-	  In this file other two inner components of the module are implemented
-	  (by convenience):
-	  StructureViewerWrapper and DropDown (used exclusively in StructureViewerWrapper)
-	 */
-
-
-	let svg = __webpack_require__(9);
-	let util = __webpack_require__(1);
-	let NavTree = __webpack_require__(10);
-	let Overview = __webpack_require__(11);
-	let StructureDetails = __webpack_require__(19);
-	let ElectronicStructDetails = __webpack_require__(24);
-	let MethodologyDetails = __webpack_require__(26);
-	let ThermalPropsDetails = __webpack_require__(28);
-	let ElasticConstDetails = __webpack_require__(31);
-	let DataStore = __webpack_require__(2);
-	let LoadingPopup = __webpack_require__(4);
-
-
-	// Store material data at this level (material model) ?
-	let materialData = null, materialCalcsData = null;
-
-	// Store the default marked tree leafs
-	let markedTreeLeafs = { eStruct: null, thermalProps: null };
-
-
-	class MaterialMod{
-
-	  constructor(){
-	    this.element = document.createElement('div');
-	    this.element.setAttribute("id",'material-module');
-
-	    this.overview = new Overview();
-	    this.overview.attachAndSetEvents(this.element);
-
-	    this.navTree= new NavTree();
-
-	    this.structureViewer = null;
-
-	    // They are created hidden
-	    // Structure detail section init
-	    this.structureDetails = new StructureDetails();
-	    this.structureDetails.attachAndSetEvents(this.element);
-
-	    // Electronic structure detail section init
-	    this.electronicStructDetails = new ElectronicStructDetails();
-	    this.electronicStructDetails.attachAndSetEvents(this.element);
-
-	    // Methodology detail section init
-	    this.methodologyDetails = new MethodologyDetails();
-	    this.methodologyDetails.attachAndSetEvents(this.element);
-
-	    this.thermalDetails = new ThermalPropsDetails();
-	    this.thermalDetails.attachAndSetEvents(this.element);
-
-	    this.elasticDetails = new ElasticConstDetails();
-	    this.elasticDetails.attachAndSetEvents(this.element);
-
-	    this.currentDetailView= null;
-	  }
-
-
-	  setMaterialView(data){
-	    if (materialData === null || materialData.id !== parseInt(data.id) ){
-	      this._loadMaterial(data.id, data.view);
-	      // Reset the checkboxes to the initial checked value (new material)
-	      if (this.structureViewer !== null){
-	        this.structureViewer.axisCheckbox.checked = true;
-	        this.structureViewer.bondsCheckbox.checked = true;
-	      }
-
-	    }else{
-	      this._setView(data.view);
-	      document.querySelector('title').innerHTML = 'NOMAD Encyclopedia - '+
-	        util.getMaterialTitle(DataStore.getMaterialData(), false);
-	    }
-	  }
-
-
-	  getCurrentPageStatus(){
-
-	    let tempeStructCalcs = null;
-	    if (this.currentDetailView === null){
-	      tempeStructCalcs = this.overview.getEStructChosenCalcs();
-	    }
-
-	    return {
-	      pageId: this.currentDetailViewId,
-	      markedLeaf: this.navTree.getMarkedLeaf(),
-	      eStructCalcs: tempeStructCalcs
-	    };
-	  }
-
-
-	  _setView(view){
-	    //console.log('FFFFF setMaterialView: '+view);
-	    // Hide the current view
-	    if (this.currentDetailView === null)
-	      this.overview.element.style.display= 'none';
-	    else
-	      this.currentDetailView.element.style.display= 'none';
-
-	    if (typeof view === 'undefined'){ // Overview view
-	      this.currentDetailView = null;
-	      this.currentDetailViewId = null;
-	      this.overview.setVisible();//this.overview.element.style.display= 'block';
-	      this.navTree.setLeafMarkedListener(undefined);
-	      this._setCellViewer(this.overview.vizBox);
-	    }else{
-	      this.currentDetailViewId = view;
-	      this._setDetailView(util.MAT_VIEW[view]);
-	    }
-	  }
-
-
-	  _setCellViewer(hostElement){
-	    //console.log('_setCellViewer', this.structureViewer,materialData);
-	    if (this.structureViewer === null){
-	      this.structureViewer = new StructureViewerWrapper(hostElement);//CellViewer(hostElement);//
-	      if (materialData !== null){ // Case: landing at e. structure details page
-	        this.structureViewer.load(util.getCellDataForViewer(materialData));
-	        this.structureViewer.setMaterialId(materialData.id);
-	      }
-	    }else
-	      this.structureViewer.changeHostElement(hostElement);
-	  }
-
-
-	  _setDetailView(view) {
-	//    console.log('FFFFF _setDetailView: '+view);
-
-	    if (view === util.MAT_VIEW.structure){
-	      this.currentDetailView= this.structureDetails;
-	      this.navTree.showCalcsGraphDataAvalability(false);
-	      this.navTree.setHeight(250);
-	      this.navTree.setMarkedLeafIfNoneMarked(null); // Set the first leaf marked
-
-	    }else if (view === util.MAT_VIEW.electronicstruct){
-	      this.currentDetailView= this.electronicStructDetails;
-	      this.navTree.showCalcsGraphDataAvalability(true);
-	      this.navTree.setHeight(400);
-	      this.navTree.setMarkedLeafIfNoneMarked(markedTreeLeafs.eStruct);
-
-	    }else if (view === util.MAT_VIEW.methodology){ // Methodology
-	      this.currentDetailView = this.methodologyDetails;
-
-	    }else  if (view === util.MAT_VIEW.thermalprops){ // Thermal properties
-	      this.currentDetailView= this.thermalDetails;
-	      this.navTree.showCalcsGraphDataAvalability(true);
-	      this.navTree.setHeight(600);
-	      this.navTree.setMarkedLeafIfNoneMarked(markedTreeLeafs.thermalProps);
-	    }
-
-	    /* To be implemented
-	    else{ // Elastic constants
-	      this.currentDetailView = this.elasticDetails;
-	      this.navTree.showCalcsGraphDataAvalability(false);
-	      this.navTree.setHeight(600);
-	      this.navTree.setMarkedLeafIfNoneMarked(null);
-	    }*/
-
-	    this.currentDetailView.setVisible();//this.currentDetailView.element.style.display= 'block';
-
-	    if (view === util.MAT_VIEW.structure)
-	      this._setCellViewer(this.structureDetails.vizBox);
-
-	    //this.currentDetailView.setMaterialData(materialData); //// WHY DOES  It do always?
-	    if (view !== util.MAT_VIEW.methodology)
-	      this.currentDetailView.attachNavTree(this.navTree);
-
-	    this.currentDetailView.updateSelection(this.navTree.getTreeSelectedCalcs());
-
-	    this.currentDetailView.updateMarkedLeaf(this.navTree.getMarkedLeaf());
-
-	    this.navTree.setTreeSelectionListener( leafIds => {
-	      this.currentDetailView.updateSelection(leafIds);
-	    });
-	    this.navTree.setLeafMarkedListener( leafId => {
-	      this.currentDetailView.updateMarkedLeaf(leafId);
-	    });
-	  }
-
-
-	  _loadMaterial(matId,view){
-
-	    this.overview.element.style.visibility= 'hidden';
-	    LoadingPopup.show();
-	    util.serverReq(util.getMaterialURL(matId), e1 => {
-
-	      materialData= JSON.parse(e1.target.response);
-	      util.materialId = materialData.id;
-
-	      if (e1.target.status === 200){
-
-	        util.serverReq(util.getMaterialXsURL('elements',matId), e2 => {
-	          materialData.elements= JSON.parse(e2.target.response).results;
+  }
+}
 
-	          util.serverReq(util.getMaterialXsURL('cells',matId), e3 => {
-	            let cells= JSON.parse(e3.target.response).results;
-	            if (!cells[0].is_primitive) materialData.cell= cells[0];
-	            else materialData.cell= cells[1];
 
-	            DataStore.setMaterialData(materialData);
-	            //console.log("CELLS: "+JSON.stringify(materialData.cell));
-	            document.querySelector('title').innerHTML =
-	              'NOMAD Encyclopedia - '+util.getMaterialTitle(materialData, false);
-	            this.overview.setMaterialData();
-	            this.structureDetails.setMaterialData();
-	            this.electronicStructDetails.setMaterialData();
-	            this.methodologyDetails.setMaterialData();
-	            this.thermalDetails.setMaterialData();
-	            this.elasticDetails.setMaterialData();
-	            //console.log("MATDATA LOADED: ");
-	            if (this.structureViewer !== null)
-	              this.structureViewer.load(util.getCellDataForViewer(materialData));
-
-	            util.serverReq(util.getMaterialXsURL('calculations',matId), e4 => {
-	              DataStore.setCalculations(JSON.parse(e4.target.response).results);
-
-	              util.serverReq(util.getMaterialXsURL('groups', matId), e5 => {
-	                DataStore.setGroups(JSON.parse(e5.target.response).groups);
-
-	                let name = (materialData.material_name === null ?
-	                  materialData.formula : materialData.material_name);
-	                this.navTree.build(name);
-	                this.overview.setCalcsData(markedTreeLeafs);
-	                this.navTree.selectAll();
-	                //console.log('MaterialMod - thermalPropsDetailsTreeLeaf: ', markedTreeLeafs.thermalProps);
-
-	                this._setView(view);
-	                this.overview.element.style.visibility= 'visible';
-	                LoadingPopup.hide();
-	              });
-	            });
-	          });
-	        });
-
-	      }else{ // Error - First request
-	         }
-
-	    });
-	  }
-	} // class MaterialMod
-
-
-	// Wrapper the structure viewer to be properly integrated
-	// on the UI components showing it
-	class StructureViewerWrapper{
-
-	  constructor(hostElement){
-	    this.hostElement = hostElement;
-
-	    this.viewer = new StructureViewer(hostElement);
-	    //Get the focus -> this.viewer.renderer.domElement.setAttribute('tabindex', '0');
-
-	    this.legendElement = document.createElement('div');
-	    this.legendElement.setAttribute('class', 'element-labels');
-	    this.legendElement.setAttribute('style', 'position: absolute; bottom: 50px; right: 0');
-	    this.hostElement.appendChild(this.legendElement);
-
-	    this.footerElement = document.createElement('div');
-	    this.footerElement.setAttribute('class', 'structure-viewer-legend');
-	    this.hostElement.appendChild(this.footerElement);
-	    this.footerElement.innerHTML = `
-
-	    <div style="float: left; padding-right: 12px" >
-	      <input type="checkbox" class="show-axis" checked> Show axis
-	    </div>
-
-	    <div style="float: left; padding-right: 18px" >
-	      <input type="checkbox" class="show-bonds" checked> Show bonds
-	    </div>
-
-	    <div style="float: left; position:relative;" >
-	      <img class="view-reset" style="cursor: pointer;" height="18px"
-	        src="${util.IMAGE_DIR}reset.svg" />
-	      <div class="view-reset-tooltip" > Set original view </div>
-	    </div>
-
-	    <!--
-	    <div class="view-reset-tooltip" style="float: left; display: none; font-size: 0.8em;" >
-	      Set original <br> &nbsp; view
-	    </div>
-	    -->
-
-	    <div class="vr-download" style="float: right"> </div>
-
-	    <div style="clear: both;"></div>
-	    `;
-
-	    this.axisCheckbox = this.footerElement.querySelector('.show-axis');
-	    this.axisCheckbox.addEventListener('click', e => {
-	      this.viewer.toggleLatticeParameters(this.axisCheckbox.checked);
-	    });
-
-	    this.bondsCheckbox = this.footerElement.querySelector('.show-bonds');
-	    this.bondsCheckbox.addEventListener('click', e => {
-	      this.viewer.toggleBonds(this.bondsCheckbox.checked);
-	    });
-
-	    this.labelsContainer = this.hostElement.querySelector('.element-labels');
-
-	    this.vrLinksContainer = this.footerElement.querySelector('.vr-download');
-	    this.vrDropDown = new DropDown();
-	    this.vrLinksContainer.appendChild(this.vrDropDown.element);
-
-	    let resetButton = this.hostElement.querySelector('.view-reset');
-	    resetButton.addEventListener('click', e =>  this.viewer.reset() );
-
-	    resetButton.addEventListener('mouseover', e => {
-	      this.hostElement.querySelector('.view-reset-tooltip').style.display = 'block';
-	    });
-	    resetButton.addEventListener('mouseout', e => {
-	      this.hostElement.querySelector('.view-reset-tooltip').style.display = 'none';
-	    });
-	  }
-
-	  load(data){
-	    this.viewer.load(data);
-	    this.createElementLegend();
-	  }
-
-	  setMaterialId(id){
-	    this.vrDropDown.setMaterialId(id);
-	  }
-
-	  changeHostElement(hostElement){
-	    if (this.hostElement !== hostElement){
-	      this.hostElement.removeChild(this.legendElement);
-	      this.hostElement.removeChild(this.footerElement);
-	      this.hostElement = hostElement;
-	      this.viewer.changeHostElement(hostElement);
-	      this.hostElement.appendChild(this.legendElement);
-	      this.hostElement.appendChild(this.footerElement);
-	    }
-	  }
-
-
-	  createElementLegend() {
-	    // Empty the old legend
-	    this.labelsContainer.innerHTML = '';
-
-	    let elements = this.viewer.elements;
-	    // Create a list of elements
-	    let elementArray = [];
-	    for (let property in elements) {
-	      if (elements.hasOwnProperty(property))
-	        elementArray.push([property, elements[property][0], elements[property][1]]);
-	    }
-
-	    // Sort by name
-	    elementArray.sort(function (a, b) {
-	      if (a[0] < b[0]) return -1;
-	      if (a[0] > b[0]) return 1;
-	      return 0;
-	    });
-
-	    let svgElement = document.createElementNS("http://www.w3.org/2000/svg", "svg");
-	    svgElement.setAttribute("width", 50);
-	    svgElement.setAttribute("height", elementArray.length*25);
-
-	    this.labelsContainer.appendChild(svgElement);
-
-	    for (let i = 0; i < elementArray.length; ++i) {
-	      let elementName = elementArray[i][0];
-	      //let elementColor = "#" + elementArray[i][1].toString(16); Lauri's bugfixing feb-2017
-	      let elementColor = elementArray[i][1].toString(16);
-	      let nZeros = 6 - elementColor.length;
-	      let prefix = "#" + Array(nZeros + 1).join("0");
-	      elementColor = prefix + elementColor;
-
-	      //let elementRadius = 25 * elementArray[i][2];
-	      //elementRadius = Math.min(100, elementRadius);
-	      //elementRadius = Math.max(30, elementRadius);
-	      svg.addCircle(svgElement, 10, 25*i+12, 8,  elementColor, "#777", 1);
-	      svg.addText(svgElement,  24, 25*i+18, elementName, 'start', 'structure-viewer-legend-labels');
-	    }
-	  }
-	} // class StructureViewerWrapper
-
-
-	// used exclusively in StructureViewerWrapper
-	class DropDown{
-
-	  constructor(materialId){
-	    this.folded = true;
-	    this.element = document.createElement('div');
-	    //this.element.className = className;
-
-	    this.element.innerHTML+=`
-	      <div >
-	        <span style=" vertical-align: 30%; ">Virtual Reality files</span>
-	        <img style="cursor: pointer" src="${util.IMAGE_DIR}folded.png" />
-	      </div>
-
-	      <div class="vr-download-panel" style="position: relative; display: none">
-
-	      </div>
-	    `;
-
-	    // Focus related properties (in order to hide the box when the user click out)
-	    this.element.tabIndex = '0'; // enabled the support of focusing
-	    this.element.style.outline = 'none'; // The outline is not shown when it gains the focus
-
-	    this.foldingPanel = this.element.querySelector('.vr-download-panel');
-	    this.foldBtn = this.element.querySelector('img');
-
-	    this.foldBtn.addEventListener('click', e => {
-	      this.folded = !this.folded;
-	      this.foldBtn.src = (this.folded ? util.IMAGE_DIR+'folded.png' :
-	        util.IMAGE_DIR+'unfolded.png');
-	      //this.foldBtn.className = (this.folded ? 'on' : 'off');
-	      this.foldingPanel.style.display = (this.folded ? 'none' : 'block');
-	    });
-
-	    this.element.addEventListener('blur' , e => {
-	      this.folded = true;
-	      this.foldBtn.src = util.IMAGE_DIR+'folded.png';
-	      this.foldingPanel.style.display = 'none';
-	    });
-
-	      //this.cellViewer.toggleLatticeParameters(false);
-	  }
-
-	  setMaterialId(id){
-	    this.foldingPanel.innerHTML = `
-	    <div class="vr-download-panel-unfolded" style="width: 210px;">
-	      <div style="padding: 5px; ">
-	        <a href="http://nomad.srv.lrz.de/cgi-bin/NOMAD/material?${id}">Get VR file</a>
-	      </div>
-	      <br>
-	      <div style="padding-bottom: 5px; ">Visualization tools for specific devices:</div>
-
-	      <div style="padding: 5px; ">
-	        <a href="http://nomad.srv.lrz.de/NOMAD/NOMADViveT-Setup.exe">HTC Vive</a>
-	      </div>
-	      <!--
-	      <div style="padding: 5px; ">
-	        <a href="http://nomad.srv.lrz.de/NOMAD/NOMADGearvrT.apk">Samsung GearVR</a>
-	      </div>
-	      -->
-	      <div style="padding: 5px; ">
-	        <a target="_blank" href="https://play.google.com/store/apps/details?id=com.lrz.nomadvr">Google Cardboard</a>
-	      </div>
-
-	    </div>
-	    `
-	  }
-
-	} // class DropDown
-
-
-	// EXPORTS
-	module.exports = MaterialMod;
-
-
-/***/ },
-/* 9 */
-/***/ function(module, exports) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-	   SVG drawing util library
-	 */
-
-
-	"use strict";
-
-	const xmlns="http://www.w3.org/2000/svg";
-	const xlink="http://www.w3.org/1999/xlink";
-
-
-	function addPoint(parent, x, y, r, className) {
-	  let e = document.createElementNS(xmlns, "circle");
-	  e.setAttribute("r", r); // e.setAttributeNS(null, "r", 5);
-	  e.setAttribute("cx", x);
-	  e.setAttribute("cy", y);
-	  if (className !== undefined) e.setAttribute("class", className);
-	  parent.appendChild(e);
-	  return e;
-	}
-
-	function addCircle(parent, x, y, r, fillColor, strokeColor, strokeWidth) {
-	  let e = document.createElementNS(xmlns, "circle");
-	  e.setAttribute("r", r); // e.setAttributeNS(null, "r", 5);
-	  e.setAttribute("cx", x);
-	  e.setAttribute("cy", y);
-	  e.setAttribute("fill", fillColor);
-	  e.setAttribute("stroke", strokeColor);
-	  e.setAttribute("stroke-width", strokeWidth);
-	  parent.appendChild(e);
-	  return e;
-	}
-
-
-	function addLine(parent, x1, y1, x2, y2, className) {
-	  let e = document.createElementNS(xmlns, "line");
-	  e.setAttribute("x1", x1);
-	  e.setAttribute("y1", y1);
-	  e.setAttribute("x2", x2);
-	  e.setAttribute("y2", y2);
-	  if (className !== undefined)  e.setAttribute("class", className);
-	  //e.setAttribute("stroke-width", stroke);
-	  parent.appendChild(e);
-	  return e;
-	}
-
-
-	function addRect(parent, x, y, w, h) {
-	  let e = document.createElementNS(xmlns, "rect");
-	  e.setAttribute("x", x);
-	  e.setAttribute("y", y);
-	  e.setAttribute("width", w);
-	  e.setAttribute("height", h);
-	  parent.appendChild(e);
-	  return e;
-	}
-
-
-
-	function addText(parent, x, y, text, textAnchor = 'start', className) {
-	  let e = document.createElementNS(xmlns, "text");
-	  e.setAttribute("x", x);
-	  e.setAttribute("y", y);
-	  e.textContent= text;
-	  //e.setAttribute("stroke", 'black');
-	  e.setAttribute("text-anchor", textAnchor);
-	  if (className !== undefined)  e.setAttribute("class", className);
-	  parent.appendChild(e);
-	  return e;
-	}
-
-
-	function addPolyline(parent, points, className) {
-	  let e = document.createElementNS(xmlns, "polyline");
-	  e.setAttribute("points", points);
-	  if (className !== undefined)  e.setAttribute("class", className);
-	  //e.setAttribute("stroke-width", stroke);
-	  parent.appendChild(e);
-	}
-
-
-	function removeElement(element){
-	  element.parentElement.removeChild(element);
-	}
-
-
-
-	// EXPORTS
-	module.exports = {
-	  addPoint: addPoint,
-	  addCircle,
-	  addLine: addLine,
-	  addRect: addRect,
-	  addText: addText,
-	  addPolyline: addPolyline,
-	  removeElement: removeElement
-	};
-
-
-/***/ },
-/* 10 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-	 /*
-	  The NavTree class define the UI tree component showing the material calculations.
-	  There is only one instance that is shared by several 'Details' views.
-	 */
-
-	"use strict";
-
-	let util = __webpack_require__(1);
-	let DataStore = __webpack_require__(2);
-
-
-
-	function buildCalcTree(calcs, calcsInGroups){
-
-	  let calcTree = new Map();
-	  calcsInGroups.forEach( (groupData, groupId) => {
-
-	    let representative = DataStore.getCalc(DataStore.getCalcReprIntId(groupId));
-	    let codeNameTrimed= representative.code_name.trim();
-	    let functionalType = representative.functional_type;
-
-	    /***** Exception: disable grouping for some codes
-	    if (codeNameTrimed !== 'VASP' && codeNameTrimed !== 'FHI-aims') */
-	      if (calcTree.has(functionalType)){
-	        let functionalMap= calcTree.get(functionalType);
-
-	        if (functionalMap.has(codeNameTrimed)){
-	          // Get an array and push a new calc
-	          functionalMap.get(codeNameTrimed).push(groupId);
-	        }else // New code name
-	          functionalMap.set(codeNameTrimed,[groupId]);
-
-	      }else{ // New functional
-	        let newFunctionalMap= new Map();
-	        newFunctionalMap.set(codeNameTrimed,[groupId]);
-	        calcTree.set(functionalType,newFunctionalMap);
-	      }
-	  });
-
-	  // Simple calcs are added to the tree
-	  calcs.forEach( calc => {
-	    //if (!DataStore.isInAnyGroup(calc.id)) addToCalcTree(calc, calc.id+'');
-	    //****** Exception: disable grouping for some codes
-	    if (!DataStore.isInAnyNotDisabledGroup(calc.id))
-	      addToCalcTree(calc, calc.id+'');
-	  });
-
-
-	  return calcTree;
-
-	  function addToCalcTree(calc, id){
-	    let codeNameTrimed= calc.code_name.trim();
-	    let functionalType = calc.functional_type;
-	    if (calcTree.has(functionalType)){
-	      let functionalMap= calcTree.get(functionalType);
-
-	      if (functionalMap.has(codeNameTrimed)){
-	        // Get an array and push a new calc
-	        functionalMap.get(codeNameTrimed).push(id);
-	      }else // New code name
-	        functionalMap.set(codeNameTrimed,[id]);
-
-	    }else{ // New functional
-	      let newFunctionalMap= new Map();
-	      newFunctionalMap.set(codeNameTrimed,[id]);
-	      calcTree.set(functionalType,newFunctionalMap);
-	    }
-	  }
-	}
-
-
-	/* Maybe these functions (getNextNode, getPreviousNode) can be removed
-	searching by node class calc-l and node-selected. Think about this */
-
-	function getNextNode(nodeBox){
-	  let nextCalcNodeBox= nodeBox.nextElementSibling.nextElementSibling;
-	  // console.log("nextCALC.getNextNode " +nextCalcNodeBox);
-	  if (nextCalcNodeBox === null){
-
-	    if (nodeBox.parentElement.nextElementSibling !== null)
-	      nextCalcNodeBox= nodeBox.parentElement.nextElementSibling/*nextCodeNodeBox*/
-	          .nextElementSibling/*nextCodeBox*/.children[0]/*nextCalc*/;
-
-	    else if (nodeBox.parentElement.parentElement.nextElementSibling !== null)
-	      nextCalcNodeBox= nodeBox.parentElement.parentElement/*FunctionalBox*/
-	          .nextElementSibling.nextElementSibling/*nextFunctionalBox*/
-	          .children[1]/*nextCodeBox*/.children[0]/*nextCalc*/;
-	    else //reaching the final node
-	      nextCalcNodeBox= null;
-	  }
-	  return nextCalcNodeBox;
-	}
-
-
-	function getPreviousNode(nodeBox){
-	  let prevCalcNodeBox;
-	  if (nodeBox.previousElementSibling !== null)
-	    prevCalcNodeBox= nodeBox.previousElementSibling.previousElementSibling;
-	  // console.log("nextCALC.getNextNode " +nextCalcNodeBox);
-	  else{
-
-	    if (nodeBox.parentElement.previousElementSibling.previousElementSibling !== null)
-	      prevCalcNodeBox= nodeBox.parentElement.previousElementSibling/*prevCodeNodeBox*/
-	          .previousElementSibling/*prevCodeBox*/.children[0]/*prevCalc*/;
-	    else if (nodeBox.parentElement.parentElement.previousElementSibling.previousElementSibling !== null)
-	      prevCalcNodeBox= nodeBox.parentElement.parentElement/*FunctionalBox*/
-	          .previousElementSibling.previousElementSibling/*prevFunctionalBox*/
-	          .lastElementChild/*prevCodeBox*/.lastElementChild.previousElementSibling/*prevCalc*/;
-	    else //reaching the final node
-	      prevCalcNodeBox= null;
-	  }
-	  return prevCalcNodeBox;
-	}
-
-
-
-	class NavTree {
-
-	  constructor() {
-	    this.selectedCalcs= new Set();
-
-	    this.element = document.createElement('div');
-	    this.element.setAttribute('id','navigation-tree');
-	    this.parentElement= null;
-	    this.markedNode = null;
-	    this._events();
-	  }
-
-	  // detach if necessary and attach
-	  attach(element){
-	    if (this.parentElement !== null)
-	      this.parentElement.removeChild(this.element);
-	    this.parentElement= element;
-	    this.parentElement.appendChild(this.element);
-	  }
-
-
-	  build(materialName){
-	    // Reset
-	    this.selectedCalcs.clear();
-	    this.markedNode = null;
-	    this.element.innerHTML= '';
-	    this.calcsInGroups = DataStore.getGroups();
-
-
-	    function getNodeHTML(level, label, unfolded, counter = 0){
-	      let foldingValue= 'node-'+(unfolded ? 'unfolded' : 'folded');
-	      let counterTag= (counter === 0 ? '' :
-	        '<span class="node-counter">('+counter+')</span>');
-	      return `
-	        <div class="${level}">
-	          <span class="${foldingValue}"></span>
-	          <span class="node-checkbox"></span>
-	          <span class="node-label" >${label}</span>
-	          ${counterTag}
-	        </div>
-	      `;
-	    }
-
-	    function getCalcGraphInfoAvalabilityHTML(calc){
-	      let html= '';
-	      if (calc.has_band_structure) html += '<span class="tooltip">B<span class="tooltiptext">Band structure</span></span> ';
-	      if (calc.has_dos) html += '<span class="tooltip">D<span class="tooltiptext">Density of states</span></span> ';
-	      if (calc.has_fermi_surface) html += '<span class="tooltip">F<span class="tooltiptext">Fermi surface</span></span>';
-	      if (calc.has_thermal_properties) html += '<span class="tooltip">T<span class="tooltiptext">Phonons</span></span>';
-
-	      return '&nbsp; <span class="calc-graph-aval">'+html+'</span>';
-	    }
-
-	    // Init map to store calculations data
-	    let calcs = DataStore.getCalculations();
-
-	    let tree= buildCalcTree(calcs, this.calcsInGroups);
-	    let rootElement= document.createElement('div');
-	    this.element.appendChild(rootElement);
-	    rootElement.innerHTML= getNodeHTML('material-l',materialName,true);
-
-	    let functionalLevelBox= document.createElement('div');
-	    rootElement.appendChild(functionalLevelBox);
-
-	    tree.forEach((codeMap, functionalName) => {
-	      //console.log(codeMap + " " + value);
-	      functionalLevelBox.innerHTML+= getNodeHTML('functional-l',functionalName,true);
-
-	      let codeLevelBox= document.createElement('div');
-	      functionalLevelBox.appendChild(codeLevelBox);
-
-	      codeMap.forEach( (calcArray, codeName) => {
-	        codeLevelBox.innerHTML+= getNodeHTML('code-l', codeName, false, calcArray.length);
-
-	        let calcLevelBox= document.createElement('div');
-	        codeLevelBox.appendChild(calcLevelBox);
-	        calcLevelBox.style.display= 'none';
-
-	        for (var i = 0; i < calcArray.length; i++) {
-	          let graphInfoAvalabilityHTML = getCalcGraphInfoAvalabilityHTML(
-	            DataStore.getCalc(DataStore.getCalcReprIntId(calcArray[i])));
-
-	          let calcIcon = '', calcNumber = '';
-	          if (DataStore.isGroup(calcArray[i])){
-	            calcIcon = '<img class="folder-icon" src="'+util.IMAGE_DIR+'folder.png" />'
-	            calcNumber = '('+this.calcsInGroups.get(calcArray[i]).calcs.size+')';
-	          }
-
-
-	          calcLevelBox.innerHTML += `
-	            <div class="calc-l" data-calc-id="${calcArray[i]}" >
-	              <span></span>
-	              <span class="node-checkbox"></span>
-
-	              <span class="node-label" >
-	                ${calcIcon} ${calcArray[i]} ${calcNumber} ${graphInfoAvalabilityHTML}
-	              </span>
-
-	              <div style="float: right; padding: 1px 10px 0 0;  display: none;">
-	                <img  src="${util.IMAGE_DIR}next.png" />
-	              </div>
-
-	            </div>
-	            <div> </div>`;
-	        }
-	      });
-	    });
-	  } // build method
-
-
-	  selectAll(initMarkedLeafId){
-	    let materialNodeBox= this.element.children[0].children[0];
-	    this._recursiveNodeSelection(materialNodeBox, true);
-	    keepTreeIntegrity(materialNodeBox, true);
-	    // No calc marked
-	  }
-
-
-	  getMarkedLeaf(){
-	    if (this.markedNode === null)  return null;
-	    else return this.markedNode.getAttribute('data-calc-id');
-	  }
-
-
-	  setMarkedLeafIfNoneMarked(leafId){ // If leafId === null first node selected
-	    if (this.getMarkedLeaf() === null){ // If none marked
-	      if (leafId === null) this._markFirstSelectedNode();
-	      else{
-	        let nodeBox = this.element.querySelector('div[data-calc-id="'+leafId+'"]');
-	        this._setMarkedCalc(nodeBox);
-	      }
-	    }
-	  }
-
-
-
-	  _events() {
-	    this.element.addEventListener('click',(e) => {
-	      let classString = e.target.className;
-
-	      // drop down/up event
-	      if (classString.indexOf('folded')  >= 0){
-	        this._foldTreeNode(e.target);
-
-	        // descendant selection/deselection event
-	      }else if ((classString.indexOf('node-checkbox')  >= 0)){
-
-	        let selectMode= (e.target.parentElement.className.indexOf('selected') < 0);
-	        this._recursiveNodeSelection(e.target.parentElement, selectMode);
-	        keepTreeIntegrity(e.target.parentElement, selectMode);
-	        this.treeSelectionListener(this.selectedCalcs);
-	        this._keepCalcMarked(selectMode); //if (this.calcMarked)
-
-	      }else if (/*this.calcMarked && */(classString.indexOf('node-label')  >= 0 )
-	        && (e.target.parentElement.className === 'calc-l node-selected')){
-	        this._setMarkedCalc(e.target.parentElement/*nodeBox*/);
-	      }
-	    });
-
-	  }
-
-
-	  _foldTreeNode(dropDowmElement){
-	    let siblingElement= dropDowmElement.parentElement.nextElementSibling;
-	    let classString = dropDowmElement.className;
-
-	    if (classString.indexOf('-folded')  >= 0) {
-	      dropDowmElement.className= dropDowmElement.className.replace('folded','unfolded');
-	      siblingElement.style.display= 'block';
-	    }else {
-	      dropDowmElement.className= dropDowmElement.className.replace('unfolded','folded');
-	      siblingElement.style.display= 'none';
-	    }
-	  }
-
-
-	  _recursiveNodeSelection(nodeBox, select){
-
-	    let nodeCheckBox= nodeBox.children[1];
-	    if (select){
-	        nodeBox.className += ' node-selected';
-	    }else{ // deselect
-	        let index= nodeBox.className.indexOf(' node-selected');
-	        nodeBox.className= nodeBox.className.substring(0,index);
-	    }
-
-	    if (nodeBox.className.indexOf('calc-l')  >= 0)  { // leaf node
-	      let id= nodeBox.getAttribute('data-calc-id');//let id= parseInt(nodeBox.getAttribute('data-calc-id'));
-	      if (select)  this.selectedCalcs.add(id);
-	      else this.selectedCalcs.delete(id);
-
-	    }else { // Not leaf node
-
-	      let nextLevelBox = nodeBox.nextElementSibling;  // next levelBox
-	      // Two children per banch: the first one is the node label box
-	      // and the second one the next level with the descendants
-	      for (let i = 0; i < nextLevelBox.children.length; i++ ) {
-	        this._recursiveNodeSelection(nextLevelBox.children[i++], select);
-	      }
-	    }
-	  }
-
-
-
-	  setTreeSelectionListener(listener){
-	    this.treeSelectionListener= listener;
-	  }
-
-
-	  setLeafMarkedListener(listener){
-	    this.leafMarkedListener = listener;
-	  }
-
-
-	  getTreeSelectedCalcs(){
-	    return this.selectedCalcs;
-	  }
-
-
-	  _keepCalcMarked(select){
-
-	    if (select && (this.markedNode === null)){
-	      this._markFirstSelectedNode();
-
-	    }else if (!select){
-	      let id= parseInt(this.markedNode.getAttribute('data-calc-id'));
-	      if (this.selectedCalcs.size === 0){
-	        this.markedNode.className= this.markedNode.className.replace('-marked','');
-	        this.markedNode= null;
-	        this.leafMarkedListener(null);
-	      }else  if (!this.selectedCalcs.has(id)){
-	        this._markFirstSelectedNode();
-	      }
-	    }
-	  } // _keepCalcMarked
-
-
-	  _markFirstSelectedNode(){
-	    let calcNodeBoxes = this.element.getElementsByClassName('calc-l');
-	    for (var i = 0; i < calcNodeBoxes.length; i++)
-	      if (calcNodeBoxes[i].className.indexOf('node-selected') >= 0){
-	        this._setMarkedCalc(calcNodeBoxes[i]);
-	        return;
-	      }
-	  }
-
-
-	  _setMarkedCalc(nodeBox){
-	    if (this.markedNode !== null){
-	      this.markedNode.className= this.markedNode.className.replace('-marked','');
-	      this.markedNode.querySelector('div').style.display = 'none';
-	      let folderIcon = this.markedNode.querySelector('.folder-icon');
-	      if (folderIcon !== null ) folderIcon.src = util.IMAGE_DIR+'folder.png';
-	    }
-
-	    nodeBox.className += '-marked';
-	    let folderIcon = nodeBox.querySelector('.folder-icon');
-	    if (folderIcon !== null ) folderIcon.src = util.IMAGE_DIR+'folder-sel.png';
-	    nodeBox.querySelector('div').style.display = 'block';
-	    this.markedNode= nodeBox;
-
-	    // The parent tree node is unfolded in order to show the leaf selected
-	    let foldingElement = nodeBox.parentElement.previousElementSibling.firstElementChild;
-	    if (foldingElement.className === 'node-folded'){
-	      foldingElement.className = 'node-unfolded';
-	      foldingElement.parentElement.nextElementSibling.style.display= 'block';
-	    }
-
-	    if (this.leafMarkedListener !== undefined)
-	      this.leafMarkedListener(nodeBox.getAttribute('data-calc-id'));
-	  }
-
-	  showCalcsGraphDataAvalability(bool){
-	    let elements= this.element.getElementsByClassName('calc-graph-aval');
-	    for (var i = 0; i < elements.length; i++)
-	      elements[i].style.display= (bool ? 'inline' : 'none');
-	  }
-
-	  setHeight(heightPx){
-	    this.element.style.height = heightPx+'px';
-	  }
-
-	} // class NavTree
-
-
-
-	function keepTreeIntegrity(nodeBox, select){
-
-	  if (nodeBox.className.indexOf('material-l') >= 0) return;
-	  let levelBox= nodeBox.parentElement;
-
-	  for (let i = 0; i < levelBox.children.length; i++ ) {
-	    let siblingNodeBox = levelBox.children[i++];
-	    if (siblingNodeBox !== nodeBox &&
-	          siblingNodeBox/*.children[1]*/.className.indexOf('selected') < 0)
-	      return;
-	  }
-	  let parentNodeBox= levelBox.previousElementSibling;
-	  if (select){
-	    parentNodeBox.className += ' node-selected';
-	  }else{
-	    let index= parentNodeBox.className.indexOf(' node-selected');
-	    parentNodeBox.className= parentNodeBox.className.substring(0,index);
-	  }
-	  keepTreeIntegrity(parentNodeBox, select);
-	}
-
-
-
-
-	// EXPORTS
-	module.exports = NavTree;
-
-
-/***/ },
-/* 11 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-	  This file implements the Overview view component in the  Material Module.
-	 */
-
-
-	"use strict";
-
-	let util = __webpack_require__(1);
-	let InfoSys = __webpack_require__(12);
-	let LoadingPopup = __webpack_require__(4);
-
-	let BSPlotter = __webpack_require__(14);
-	let DOSPlotter = __webpack_require__(16);
-	let HeatCapPlotter = __webpack_require__(17);
-	let MaterialMod = __webpack_require__(8);
-	let DataStore = __webpack_require__(2);
-
-	const ELEMENT_INCLUDED_MSG = 'ELEMENT ALREADY INCLUDED';
-
-
-	class Overview {
-
-	  constructor() {
-
-	    this.element = document.createElement('div');
-	    this.element.setAttribute('id','overview');
-	    this.materialId;
-	    this.element.innerHTML=`
-
-	    <div class="material-title">
-	    </div>
-
-	    <div style="float: left; width: 40%;">
-
-	      <div id="structure-ov" class="view-box">
-	        <div class="title">Structure
-	          <img style="float: right" class="to-detail" src="img/more.svg" />
-	          <div style="clear: both;"></div>
-	        </div>
-
-	        <div class="viz-box" style="height: 260px; position: relative"></div>
-
-	        <div class="footer">
-	          <div ><b><span>System type</span></b>:
-	            <span class="system-type-field" ></span>
-	          </div>
-	          <div class="space-group-field" style="display: none">
-	            <b><span info-sys-data="space-group">Space group</span></b>:
-	            <span class="space-group-value" ></span>
-	          </div>
-	          <div class="structure-type-field" style="display: none">
-	            <b><span info-sys-data="structure-type">Structure type</span></b>:
-	            <span class="structure-type-value" ></span>
-	          </div>
-	        </div>
-	      </div>
-
-
-	<!-- ***** Elastic Constants Box
-
-	      <div id="elastic-ov" class="view-box">
-	        <div class="title">Elastic constants
-	          <img style="float: right" class="to-detail" src="img/more.svg" />
-	          <div style="clear: both;"></div>
-	        </div>
-
-	        <div class="info-fields">
-	          Not analyzed yet
-	        </div>
-
-	      </div>
-	-->
-
-
-	      <div id="methodology-ov" class="view-box">
-	        <div class="title">Methodology
-	          <img style="float: right" class="to-detail" src="img/more.svg" />
-	          <div style="clear: both;"></div>
-	        </div>
-
-	        <div class="info-fields">
-
-	          <div class="info-fields-label" > Available calculations </div>
-
-	          <div style="float: left; width: 45%" >
-	            <b><span info-sys-data="functional-type">Functional</span></b>
-	            <div class="functional-field" > </div>
-	          </div>
-	          <div style="float: right; width: 45%" >
-	            <b><span info-sys-data="code-name">Code</span></b>
-	            <div class="code-field"> </div>
-	           </div>
-	           <div style="clear: both;"></div>
-	        </div>
-
-	      </div>
-
-	    </div>
-
-	    <div style="float: right; width: 60%;">
-
-	      <div id="e-structure-ov"  class="view-box" > <!--style="height: 610px; "-->
-	        <div class="title">Electronic structure
-	          <img style="float: right" class="to-detail" src="img/more.svg" />
-	          <div style="clear: both;"></div>
-	        </div>
-
-	        <div > <!-- style="margin: 12% 0; " -->
-
-	        <div style="float: left; width: 60%;  ">
-	        <div style="padding: 20px 0 20px 30px">
-	          <div  class="info-fields-label">
-	            <span info-sys-data="band-structure">Band structure</span>
-	          </div>
-	          <div>
-	              <div id="band-plotter" >  </div>
-	          </div>
-
-	          <div class="footer-bs-calc"></div>
-	        </div>
-	        </div>
-
-	        <div style="float: left; width: 40%;  ">
-	          <div style="padding: 20px 30px 20px 60px">
-	            <div class="info-fields-label">
-	              <span info-sys-data="DOS">DOS</span>
-	            </div>
-
-	            <div>
-	                <div id="dos-plotter" >  </div>
-	            </div>
-	            <div class="footer-dos-calc"></div>
-	          </div>
-	        </div>
-
-
-	        <div style="clear: both;"></div>
-
-	        <div class="spin-legend" style="font-size: 0.9em; padding: 6px 30px 10px; display: none">
-	          <svg width="15px" height="10px"> <polyline points="0,5 15,5" class="plotSpin1"/></svg>
-	          Spin <span style='font-size: 1.1em'>⇧</span>  &nbsp;&nbsp;&nbsp;
-
-	          <svg width="15px" height="10px"> <polyline points="0,5 15,5" class="plotSpin2"/></svg>
-	          Spin <span style='font-size: 1.1em'>⇩</span>
-	        </div>
-
-	        </div>
-
-	        <!--
-	        <div class="footer">
-	          <b>Band gap</b>: <span class="e-struct-field" ></span>
-	        </div>
-	        -->
-	      </div>
-
-	      <div id="thermal-props-ov"  class="view-box" >
-	        <div class="title">Vibrational and thermal properties
-	          <img style="float: right" class="to-detail thermal-props" src="img/more.svg" />
-	          <div style="clear: both;"></div>
-	        </div>
-
-	        <div style="padding: 36px; ">
-	          <div class="info-fields-label">
-	            <span info-sys-data="heat-capacity-cv">Specific heat</span>
-	          </div>
-
-
-	          <div>
-	              <div id="heat-plotter" >  </div>
-	          </div>
-	          <div class="footer-heat-calc" style="text-align: center"></div>
-	        </div>
-
-	      </div>
-
-	    </div>
-
-	    <div style="clear: both;"></div>
-	    `;
-
-	    this.materialTitle= this.element.getElementsByClassName('material-title')[0];
-
-	    this.systemType= this.element.querySelector('.system-type-field');
-	    this.spaceGroupField = this.element.querySelector('.space-group-field');
-	    this.spaceGroupValue = this.element.querySelector('.space-group-value');
-	    this.structTypeField= this.element.querySelector('.structure-type-field');
-	    this.structTypeValue= this.element.querySelector('.structure-type-value');
-	    //this.band_gap = this.element.getElementsByClassName('e-struct-field')[0];
-
-	    //fields= this.element.getElementsByClassName('method-field');
-	    this.functional= this.element.querySelector('.functional-field');//fields[0];
-	    this.code= this.element.querySelector('.code-field');//fields[1];
-
-	    let fields= this.element.getElementsByClassName('to-detail');
-	    this.structureDetailBtn= fields[0];
-	    this.electronicStructDetailBtn= fields[2];
-	    this.methodologyDetailBtn= fields[1];
-	    this.thermalDetailBtn= fields[3];
-	/*
-	    this.elasticDetailBtn= fields[1];
-	    this.methodologyDetailBtn= fields[2];
-	    this.electronicStructDetailBtn= fields[3];
-	    this.thermalDetailBtn= fields[4];
-	    */
-
-	    this.vizBox = this.element.getElementsByClassName('viz-box')[0];
-	    //this.cellViewer= null;
-
-	    this.bandPlotter= null;
-	    this.bsCalcIdBox = this.element.getElementsByClassName('footer-bs-calc')[0];
-	    this.dosPlotter= null;
-	    this.dosCalcIdBox = this.element.getElementsByClassName('footer-dos-calc')[0];
-	    this.heatPlotter= null;
-	    this.heatCalcIdBox = this.element.querySelector('.footer-heat-calc');
-
-	    this.spinLegend = this.element.querySelector('.spin-legend');
-
-	    // For static ones
-	    InfoSys.addToInfoSystem(this.element);
-
-	    // Store the state of the calcs chosen on the Elec. Structure box
-	    this.eStructCalcs = { bs: null, dos: null};
-	  }
-
-
-	  attachAndSetEvents(element){
-	    element.appendChild(this.element);
-	    this._events();
-	  }
-
-
-	  _events() {
-
-	    this.structureDetailBtn.addEventListener( "click", (e) => {
-	      util.setBrowserHashPath('material', this.materialId+'/'+util.MAT_VIEW.structure);
-	    });
-
-	    this.electronicStructDetailBtn.addEventListener( "click", (e) => {
-	      util.setBrowserHashPath('material', this.materialId+'/'+util.MAT_VIEW.electronicstruct);
-	    });
-
-	    this.methodologyDetailBtn.addEventListener( "click", (e) => {
-	      util.setBrowserHashPath('material', this.materialId+'/'+util.MAT_VIEW.methodology);
-	    });
-
-	    this.thermalDetailBtn.addEventListener( "click", (e) => {
-	      util.setBrowserHashPath('material', this.materialId+'/'+util.MAT_VIEW.thermalprops);
-	    });
-
-	/*
-	    this.elasticDetailBtn.addEventListener( "click", (e) => {
-	      util.setBrowserHashPath('material', this.materialId+'/'+util.MAT_VIEW.elasticconst);
-	    });
-	*/
-
-
-	    //******* Optimize, genralize:
-	    //this.element.querySelectorAll('.to-detail+.'+detailsId).addEventListener( "click", (e) => {
-	    // util.setBrowserHashPath('material', this.materialId+'/'+detailsId);
-	  }
-
-
-	  getEStructChosenCalcs(){
-	    return this.eStructCalcs;
-	  }
-
-
-	  setDetailViewsListener(listener){
-	    this.detailViewsListener= listener;
-	  }
-
-	  setVisible(){
-	    this.element.style.display= 'block';
-	  }
-
-
-	  setMaterialData() {
-
-	    let data = DataStore.getMaterialData();
-	    this.materialTitle.innerHTML= util.getMaterialTitle(data);
-	    this.materialId = data.id;
-
-	    let isBulk = (data.system_type === 'bulk');
-	    this.systemType.textContent= data.system_type;
-	    this.structTypeField.style.display =
-	      (isBulk && data.structure_type !== null ? 'block' : 'none');
-	    this.spaceGroupField.style.display = (isBulk ? 'block' : 'none');
-
-	    if (isBulk){
-	      this.structTypeValue.textContent= data.structure_type;
-	      this.spaceGroupValue.textContent = data.space_group_number+
-	        ' ('+data.space_group_international_short_symbol+')';
-	      InfoSys.addElementToInfoSystem(this.spaceGroupValue,
-	        'space-group.value:'+data.space_group_number);
-	    }
-
-	  }
-
-
-	  _evaluateCalc(calc){
-	    let value = 0;
-	    if (calc.functional_type === 'GGA') value += 100;
-	    if (calc.has_band_structure && calc.has_dos) value += 10;
-	    switch (calc.code_name.trim()) {
-	      case 'FHI-aims': value += 3;  break;
-	      case 'VASP': value += 2;  break;
-	      case 'Quantum Espresso': value += 1;  break;
-	    }
-	    return value;
-	  }
-
-
-	  setCalcsData(markedTreeLeafs) {
-	    //console.log('setCalcsData: '+JSON.stringify(data));
-	    let calcs = DataStore.getCalculations();
-
-	    let functionalMap = new Map();
-	    let codeMap = new Map();
-	    let calcWithBS = null, calcWithDOS = null, calcWithHeat = null;
-	    let calcBSEvaluation = -1, calcDOSEvaluation = -1;
-
-	    for (let i = 0; i < calcs.length; i++) {
-
-	      if (functionalMap.has(calcs[i].functional_type)){
-	        let num= functionalMap.get(calcs[i].functional_type);
-	        // Because it's a number we can't use the returned value as a reference
-	        functionalMap.set(calcs[i].functional_type,++num);
-	      }else
-	        functionalMap.set(calcs[i].functional_type,1);
-
-	      let codeNameTrimed= calcs[i].code_name.trim();
-	      if (codeMap.has(codeNameTrimed)){
-	        let num= codeMap.get(codeNameTrimed);
-	        // Because it's a number we can't use the returned value as a reference
-	        codeMap.set(codeNameTrimed,++num);
-	      }else
-	        codeMap.set(codeNameTrimed,1);
-
-	      let calcEvaluation = this._evaluateCalc(calcs[i]);
-	      //console.log('calcEvaluation',calcEvaluation);
-
-	      if (calcs[i].has_band_structure && calcEvaluation > calcBSEvaluation){
-	        calcBSEvaluation = calcEvaluation;
-	        calcWithBS = calcs[i];
-	      }
-
-	      if (calcs[i].has_dos && calcEvaluation > calcDOSEvaluation){
-	        calcDOSEvaluation = calcEvaluation;
-	        calcWithDOS = calcs[i];
-	      }
-	      //console.log('BS DOS Evaluation',calcBSEvaluation, calcDOSEvaluation);
-
-	      if (calcWithHeat === null && calcs[i].has_thermal_properties)
-	        calcWithHeat = calcs[i];
-	    }
-
-	    if (calcWithBS !== null)  this.eStructCalcs.bs = calcWithBS.id;
-	    if (calcWithDOS !== null)  this.eStructCalcs.dos = calcWithDOS.id;
-
-	    let tempCalcId = null;
-	    if (calcWithBS !== null)  tempCalcId = calcWithBS.id;
-	    else if (calcWithDOS !== null)  tempCalcId = calcWithDOS.id;
-
-	    if (tempCalcId === null) markedTreeLeafs.eStruct = null; // no graph data
-	    else if (DataStore.isInAnyNotDisabledGroup(tempCalcId)){
-	      markedTreeLeafs.eStruct = DataStore.getGroupLeafId(tempCalcId);
-	    }else
-	      markedTreeLeafs.eStruct = +tempCalcId;
-
-	    if (calcWithHeat === null) markedTreeLeafs.thermalProps = null;
-	    else if (DataStore.isInAnyNotDisabledGroup(calcWithHeat.id)){
-	      markedTreeLeafs.thermalProps = DataStore.getGroupLeafId(calcWithHeat.id);
-	    }else
-	      markedTreeLeafs.thermalProps = +calcWithHeat.id;
-	    //console.log('Overview - thermalPropsDetailsTreeLeaf: ', markedTreeLeafs.thermalProps);
-
-	    //this.band_gap.innerHTML= util.getBandGapStatsValue(calcs);
-
-	    let functionalHTML= '';
-	    functionalMap.forEach((number,functional) => {
-	      functionalHTML+= '<span info-sys-data="functional-type.value:'+functional+
-	        '">'+number+' '+functional+'</span> <br> ';
-	    });
-
-	    this.functional.innerHTML= functionalHTML;
-	    InfoSys.addToInfoSystem(this.functional);
-
-	    let codeHTML= '';
-	    codeMap.forEach((number,codeName) => {
-	      codeHTML+= '<span info-sys-data="code-name.value:'+codeName+
-	        '">'+number+' '+codeName+'</span> <br> ';
-	      //codeHTML+= number+' '+codeName+' <br> ';
-	    });
-	    this.code.innerHTML= codeHTML;
-	    InfoSys.addToInfoSystem(this.code);
-
-
-	    if (calcWithBS === null && calcWithDOS === null){
-	      document.getElementById('e-structure-ov').style.display = 'none';
-	      DataStore.hasElecStructureData = false;
-	    }else{
-	      document.getElementById('e-structure-ov').style.display = 'block';
-	      DataStore.hasElecStructureData = true;
-
-	      if (this.bandPlotter === null){
-	        this.bandPlotter= new BSPlotter();
-	        this.bandPlotter.attach(document.getElementById('band-plotter'),undefined,316);
-	      }
-	      if (this.dosPlotter === null){
-	        this.dosPlotter= new DOSPlotter({left: 40, right: 16, top: 0, bottom: 30});
-	        this.dosPlotter.attach(document.getElementById('dos-plotter'),undefined,317);
-	      }
-
-	      if (calcWithBS === null){
-	        this.bandPlotter.setNoData();
-	        this.bsCalcIdBox.innerHTML = '';
-	      }else{
-	        let url = util.getMaterialCalcURL(calcWithBS.material,calcWithBS.id,
-	            'band_structure');
-	        LoadingPopup.show();
-	        util.serverReq(url, e => {
-	          if (e.target.status === 200){
-	            let bandStructData= JSON.parse(e.target.response).band_structure;
-	            this.bandPlotter.setBandStructureData(bandStructData);
-	            this.bsCalcIdBox.innerHTML = 'From calculation <b>'+calcWithBS.id+
-	              '</b><br><span style="font-size: 0.8em">('+calcWithBS.functional_type+' - '+calcWithBS.code_name+')</span>';
-	            if (bandStructData.segments[0].band_energies.length === 2)
-	              this.spinLegend.style.display = 'block';
-	          }
-	          LoadingPopup.hide();
-	        });
-	      }
-
-	      if (calcWithDOS === null){
-	        this.dosPlotter.setNoData();
-	        this.dosCalcIdBox.innerHTML = '';
-	      }else{
-	        let url = util.getMaterialCalcURL(calcWithDOS.material,calcWithDOS.id,
-	            'dos');
-	        LoadingPopup.show();
-	        util.serverReq(url, e => {
-	          if (e.target.status === 200){
-	            let dosData= JSON.parse(e.target.response).dos;
-
-	            this.dosPlotter.setPoints(dosData);//paintPointsLine(dosData);
-	            this.dosCalcIdBox.innerHTML = 'From calculation <b>'+calcWithDOS.id+
-	            '</b><br><span style="font-size: 0.8em">('+calcWithDOS.functional_type+' - '+calcWithDOS.code_name+')</span>';
-	            if (dosData.dos_values.length === 2)
-	              this.spinLegend.style.display = 'block';
-	          }
-	          LoadingPopup.hide();
-	        });
-	      }
-	    }
-
-	    if (calcWithHeat === null){
-	      document.getElementById('thermal-props-ov').style.display = 'none';
-	      DataStore.hasThermalData = false;
-	    }else{
-	      document.getElementById('thermal-props-ov').style.display = 'block';
-	      DataStore.hasThermalData = true;
-
-	      if (this.heatPlotter === null){
-	        this.heatPlotter= new HeatCapPlotter();
-	        this.heatPlotter.attach(document.getElementById('heat-plotter'),undefined,317);
-	      }
-
-	      if (calcWithHeat === null){
-	        this.heatPlotter.setNoData();
-	        this.heatCalcIdBox.innerHTML = '';
-	      }else{
-	        let url = util.getMaterialCalcURL(calcWithHeat.material, calcWithHeat.id,
-	            'specific_heat_cv');
-	        LoadingPopup.show();
-	        util.serverReq(url, e => {
-	          if (e.target.status === 200){
-	            let heatData= JSON.parse(e.target.response).specific_heat_cv;
-	            //console.log(heatData);
-	            this.heatPlotter.setData(heatData);
-	            this.heatCalcIdBox.innerHTML = 'From calculation <b>'+calcWithHeat.id+'</b>'+
-	            '</b> <span style="font-size: 0.8em">('+calcWithHeat.functional_type+' - '+calcWithHeat.code_name+')</span>';
-	          }
-	          LoadingPopup.hide();
-	        });
-	      }
-	    }
-
-	  } // setCalcsData function
-
-	}
-
-	// EXPORTS
-	module.exports = Overview;
-
-
-/***/ },
-/* 12 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-	   This file implements an information system for the user that provides info
-	   related to the concepts or quantities shown on the UI
-	   The literals are read form the file infosys.json
-	 */
-
-	"use strict";
-
-	let util = __webpack_require__(1);
-	let SwitchComponent = __webpack_require__(13);
-
-	const INFOSYS_FILE_PATH = 'infosys.json';
-
-	let tooltip = document.querySelector('#info-tooltip');
-	let tooltipContent = document.querySelector('#tooltip-content');
-
-	let elements = [];
-	let timerSet = null;
-	let on = false;
-	let data = null;
-
-	function clearCurrentTimeoutAnSetANew(){
-	  if (timerSet !== null)  window.clearTimeout(timerSet);
-	  timerSet = window.setTimeout(t => tooltip.style.display = 'none', 1000);
-	}
-
-
-	let switchComponent = new SwitchComponent(util.IMAGE_DIR+'switch');
-	document.querySelector('#info-sys-switch-box').appendChild(switchComponent.element);
-
-	switchComponent.setListener( off => {
-	  on = !off;
-	  if (off) {
-	    elements.forEach( element => {
-	      element.removeEventListener('mouseover', mouseOver);
-	      element.className = '';
-	    });
-	  }else{
-	    if (data === null)
-	      util.serverReq(INFOSYS_FILE_PATH, e => data = JSON.parse(e.target.response));
-
-	    elements.forEach(enableTooltip);
-	  }
-
-
-	  tooltip.addEventListener('mouseover', e => {
-	    window.clearTimeout(timerSet);
-	  });
-
-	  tooltip.addEventListener('mouseout', e => {
-	    clearCurrentTimeoutAnSetANew();
-	  });
-
-	});
-
-
-	function addToInfoSystem(baseElement){
-	  let infosysLabels = baseElement.querySelectorAll('span[info-sys-data]');
-
-	  for (let i = 0; i < infosysLabels.length; ++i)
-	    elements.push(infosysLabels[i]);
-
-	  //if (on)  infosysLabels.forEach(enableTooltip);
-	  if (on)
-	    for (let i = 0; i < infosysLabels.length; ++i)
-	      enableTooltip(infosysLabels[i]);
-	}
-
-
-	function addElementToInfoSystem(element, value){
-	  elements.push(element);
-	  element.setAttribute('info-sys-data',value);
-
-	  if (on) enableTooltip(element);
-	}
-
-
-	function enableTooltip(element){
-	  element.addEventListener('mouseover', mouseOver);
-	  element.addEventListener('mouseout', e => {
-	    clearCurrentTimeoutAnSetANew();
-	    element.style.cursor = 'inherit';
-	  });
-	  element.className = 'info-sys-label';
-	}
-
-
-	function mouseOver(e){
-	  let r = e.target.getBoundingClientRect();
-	  let quantity =  e.target.getAttribute('info-sys-data');
-
-	  let index = quantity.indexOf('.value');
-	  if (index > 0){ // quantity value
-	    let quantityObject = data[quantity.split('-').join(' ').substring(0, index)];
-	    //console.log('VALUE', quantityObject);
-	    if (quantityObject.value_template === undefined){ //direct value
-	      let valueObj = quantityObject.values[quantity.split(':')[1]];
-	      tooltipContent.innerHTML = getHTML(valueObj);
-	    }else{ // value template
-	      let object = quantityObject.value_template;
-	      object.text = templating(object.text, quantity.split(':')[1]);
-	      object.link = templating(object.link, quantity.split(':')[1]);
-	      tooltipContent.innerHTML = getHTML(object);
-	      //console.log('VALUE TEMPLATE: ', object);
-	    }
-	  }else // quantity name
-	    tooltipContent.innerHTML = getHTML(data[quantity.split('-').join(' ')]);
-
-	  tooltip.style.visibility = 'hidden';
-	  tooltip.style.display = 'block';
-	  let ttRect = tooltip.getBoundingClientRect();
-	  let leftOffset = ttRect.width - r.width;
-	  let leftPos = r.left -leftOffset/2;
-	  if (leftPos + ttRect.width > window.innerWidth)
-	    leftPos = window.innerWidth -ttRect.width;
-	  //let topOffset = ttRect.height + 20 - window.pageYOffset;
-	  let topOffset =  - window.pageYOffset;
-	  tooltip.style.left = (leftPos < 0 ? 5 : leftPos)+'px';
-	  tooltip.style.top = (r.top + r.height -topOffset)+'px';
-	  tooltip.style.visibility = 'visible';
-	  window.clearTimeout(timerSet);
-	  e.target.style.cursor = 'help';
-	}
-
-
-	function templating(s, param) {
-	  let initIndex = s.indexOf('${');
-	  let finalIndex = s.indexOf('}');
-	  if (initIndex >= 0 && finalIndex >= 0 && finalIndex > initIndex){
-	    return s.substring(0,initIndex)+param+s.substring(finalIndex+1);
-	  }else return s;
-	}
-
-	function getHTML(object) {
-	  let html = '';
-	  if (object.text === undefined){
-	    //html = 'NO TEXT!! Comment: '+object.comment;
-	  }else{ // there is text attr
-	    html += object.text;
-	  }
-	  if (object.link !== undefined){
-	    if (object.text !== undefined)   html += '<br>';
-	    html += '<a href="'+object.link+'" target="_blank">More information</a>';
-	  }
-
-	  return html;
-	}
-
-
-	// EXPORTS
-	module.exports = { addToInfoSystem, addElementToInfoSystem };
-
-
-/***/ },
-/* 13 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-	    This component implements a generic switch/toggle button
-	 */
-
-
-	let util = __webpack_require__(1);
-
-	class SwitchComponent {
-
-	  constructor(imageBasePath) {
-
-	    this.off = true;
-
-	    this.element = document.createElement('span');
-	    this.element.innerHTML+=`
-	       <img src="${imageBasePath}_off.png" width="24px"
-	        style="margin-bottom: -1px; cursor: pointer"/>
-	    `;
-	    this.image = this.element.querySelector('img');
-
-	    this.element.addEventListener('click', e => {
-	      this.off = !this.off;
-	      let imagePath = (this.off ? imageBasePath+'_off' : imageBasePath);
-	      this.image.setAttribute('src',imagePath+'.png');
-	      this.listener(this.off);
-	    });
-	  }
-
-
-	  setListener(listener){
-	    this.listener = listener;
-	  }
-	}
-
-	// EXPORTS
-	module.exports = SwitchComponent;
-
-
-/***/ },
-/* 14 */
-/***/ function(module, exports, __webpack_require__) {
-
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-	 /*
-	  Implements the Band Structure plotter.
-	  It's used to show either the regular Band Structure data or
-	  the Phonon Dispersion.
-	 */
-
-
-	"use strict";
-
-	let InteractivePlotterBase = __webpack_require__(15);
-	let svg = __webpack_require__(9);
-	let util = __webpack_require__(1);
-
-	const MULTIPLO1 = 1.602176565e-19;
-	const MULTIPLO2 = 1/5.034117012222e22;
-
-
-	class BSPlotter extends InteractivePlotterBase{
-
-	  constructor() {
-	    super({left: 55, right: 5, top: 0, bottom: 30});
-	    this.phononMode = false;
-	    this.factor = MULTIPLO1;
-	  }
-
-
-	  setPhononMode(){
-	    this.phononMode = true;
-	    this.factor = MULTIPLO2;
-	    this.outOfRangeColorActivated = false;
-	  }
-
-
-	  // detach if necessary and attach
-	  attach(element, width, height){
-	    super.attach(element, width, height);
-	  }
-
-
-	  getTopAndLowestPoints(bandStructData){
-	    let bandMax = -10000;
-	    let bandMin = 10000;
-	    for (let i = 0; i < bandStructData.length; i++) { // Per segment
-	      // spin1 - per band energy loop
-	      for (let j = 0; j < bandStructData[i].band_energies[0].length; j++) {
-	        let tempValue= Math.max.apply(null, bandStructData[i].band_energies[0]/*spin1*/[j]/*first_band*/);
-	        if (tempValue > bandMax) bandMax= tempValue;
-	        tempValue= Math.min.apply(null, bandStructData[i].band_energies[0]/*spin1*/[j]/*first_band*/);
-	        if (tempValue < bandMin) bandMin= tempValue;
-	      }
-
-	      if (bandStructData[i].band_energies.length === 2)
-	        // spin2 - per band energy loop
-	        for (let j = 0; j < bandStructData[i].band_energies[1].length; j++) { // Per segment
-	          let tempValue= Math.max.apply(null, bandStructData[i].band_energies[1]/*spin1*/[j]/*first_band*/);
-	          if (tempValue > bandMax) bandMax= tempValue;
-	          tempValue= Math.min.apply(null, bandStructData[i].band_energies[1]/*spin1*/[j]/*first_band*/);
-	          if (tempValue < bandMin) bandMin= tempValue;
-	        }
-	    }
-	    return [bandMin/this.factor, bandMax/this.factor];
-	  }
-
-
-	  drawKPointLabel(x, label){
-	    svg.addText(this.axisGroup, x*this.xRel, 16, label, 'middle', 'steps');
-	  }
-
-
-	  setBandStructureData(data){
-
-	    let bandStructData;
-	    if (data.segments !== undefined)  bandStructData = data.segments;
-	    else bandStructData = data;
-
-	    this.bandGapData = undefined;
-	    if (data.band_gap !== undefined && data.band_gap.position !== undefined){
-	      this.bandGapData = data.band_gap.position;
-	      this.bandGapData.cbmDistances = [];
-	      this.bandGapData.vbmDistances = [];
-	    }
-
-	    // Gather all the points per band (divided by spin) crossing the segments
-	    this.bandsDataSpin1= [];  // [segment][band][kpoint]
-	    this.bandsDataSpin2= [];
-	    this.segmentLimitsX = [];
-	    this._reset();
-
-	    let topAndLowestPoints = this.getTopAndLowestPoints(bandStructData);
-	    let minEnergyVal = topAndLowestPoints[0];
-	    let maxEnergyVal = topAndLowestPoints[1];
-
-	    if (this.phononMode){
-	      this.setAxisRangeAndLabels('',0,1,'Frequency (cm⁻¹)',-50, 320,
-	        minEnergyVal, maxEnergyVal, 100);
-	    }else
-	      this.setAxisRangeAndLabels('',0,1,'Energy (eV)' ,-6 ,11 , minEnergyVal,
-	        maxEnergyVal, 5 );
-
-	    // Calculates de distance
-	    let totalDistance= 0;
-	    for (let k = 0; k < bandStructData.length; k++) {
-	      let kPoints= bandStructData[k].band_k_points;
-	      totalDistance+= kPointDistance(kPoints,kPoints.length-1);
-	    }
-	    let currentDistance= 0;
-	    let prevLastLabel = null;
-	    let dataOverflow = false;
-
-	    for (let k = 0; k < bandStructData.length; k++) { // For every  segment
-
-	      let segment= bandStructData[k];
-	      let kPoints= segment.band_k_points;
-	      let labels= segment.band_segm_labels;
-
-	      let energiesSpin1= segment.band_energies[0];
-	      let energiesSpin2= segment.band_energies[1];
-	      this.bandsDataSpin1.push([]);  // Add a new array per segment
-	      this.bandsDataSpin2.push([]);
-
-	      let segmentDistance= kPointDistance(kPoints,kPoints.length-1);
-
-	      // keeping the segment limits (x coordenate) for after painting
-	      this.segmentLimitsX.push(currentDistance/totalDistance);
-
-	      if (labels !== null){
-	        // Set k-points labels
-	        if (prevLastLabel !== null && prevLastLabel !== labels[0])
-	          this.drawKPointLabel(currentDistance/totalDistance,
-	            getSymbol(prevLastLabel)+'|'+getSymbol(labels[0]));
-	        else
-	          this.drawKPointLabel(currentDistance/totalDistance,getSymbol(labels[0]));
-	        // The last label
-	        if (k === bandStructData.length -1)
-	          this.drawKPointLabel(1, getSymbol(labels[1]));
-
-	        prevLastLabel = labels[1];
-	      }
-
-	      for (let i = 0; i < kPoints.length; i++) { // For every  k-point
-
-	        let tempDistance= (currentDistance + kPointDistance(kPoints, i))/totalDistance;
-
-	        if (this.bandGapData !== undefined){
-
-	          if (this.bandGapData.lower !== undefined){
-	            let kpt = this.bandGapData.lower.kpt;
-	            if (kPoints[i][0] === kpt[0] && kPoints[i][1] === kpt[1]
-	              && kPoints[i][2] === kpt[2]){
-	                this.bandGapData.cbmDistances.push(tempDistance);
-	            }
-	          }
-
-	          if (this.bandGapData.upper !== undefined){
-	            let kpt = this.bandGapData.upper.kpt;
-	            if (kPoints[i][0] === kpt[0] && kPoints[i][1] === kpt[1]
-	              && kPoints[i][2] === kpt[2]){
-	                this.bandGapData.vbmDistances.push(tempDistance);
-	            }
-	          }
-
-	          /*
-	          let kpt = this.bandGapData.cbmKpt;
-	          if (kPoints[i][0] === kpt[0] && kPoints[i][1] === kpt[1]
-	            && kPoints[i][2] === kpt[2]){
-	              //console.log("kpoints: ", kPoints[i], kpt, tempDistance);
-	              this.bandGapData.cbmX = tempDistance;
-	          }
-	          kpt = this.bandGapData.vbmKpt;
-	          if (kPoints[i][0] === kpt[0] && kPoints[i][1] === kpt[1]
-	            && kPoints[i][2] === kpt[2]){
-	              //console.log("kpoints: ", kPoints[i], kpt, tempDistance);
-	              this.bandGapData.vbmX = tempDistance;
-	          }
-	          */
-	        }
-
-
-	        // All bands spin1
-	        for (let j = 0; j < energiesSpin1[i].length; j++) {
-	          if (i === 0) this.bandsDataSpin1[k][j] = [];//if (k === 0 && i === 0) this.bandsDataSpin1[j] = [];
-	          let currentY = energiesSpin1[i][j]/this.factor;
-	          this.bandsDataSpin1[k][j].push({x: tempDistance, y: currentY});
-	          if (!dataOverflow && currentY > 10000)  dataOverflow = true;
-	        }
-	        // All bands spin2
-	        if (energiesSpin2 !== undefined)
-	          for (let j = 0; j < energiesSpin2[i].length; j++) {
-	            if (i === 0) this.bandsDataSpin2[k][j] = [];
-	            let currentY = energiesSpin2[i][j]/this.factor;
-	            this.bandsDataSpin2[k][j].push({x: tempDistance, y: currentY});
-	            if (!dataOverflow && currentY > 10000)  dataOverflow = true;
-	          }
-	        //console.log("K PPPPPP Ponint: "+i+' DIS: '+tempDistance, this.bandsDataSpin1[k]);
-	      }
-
-	      currentDistance+= segmentDistance;
-	    }
-
-	    if (dataOverflow) throw 'Plotter Data Overflow: Probably the energy data is not in correct units'; //console.log('BSPlotter data overflow');
-	    else this.repaint();
-	  }
-
-
-	  repaintData(yMin, yMax){
-
-	    this.segmentLimitsX.forEach(x => {
-	      let yMinPx = this.transformY(yMin);
-	      let yMaxPx = this.transformY(yMax);
-	      if (this.phononMode) { yMinPx += 200; yMaxPx -= 200; }
-	      svg.addLine(this.plotContent, x*this.xRel, yMinPx,
-	        x*this.xRel, yMaxPx, 'segment');
-	    });
-
-	    // Drawing lines
-	    let polylinePoints;
-	    for (var i = 0; i < this.bandsDataSpin1.length; i++) // loop the segments
-
-	      for (var j = 0; j < this.bandsDataSpin1[i].length; j++) { // loop the bands
-	        polylinePoints = '';
-	        for (var k = 0; k < this.bandsDataSpin1[i][j].length; k++) { // loop the kpoints
-	          polylinePoints+= ' '+this.xRel*this.bandsDataSpin1[i][j][k].x+
-	            ' '+this.transformY(this.bandsDataSpin1[i][j][k].y);
-	        }
-	        svg.addPolyline(this.plotContent, polylinePoints, 'plotSpin1');
-	      }
-
-	    if (this.bandsDataSpin2.length > 0){
-	      for (var i = 0; i < this.bandsDataSpin2.length; i++) // loop the segments
-
-	        for (var j = 0; j < this.bandsDataSpin2[i].length; j++) { // loop the kpoints
-	          polylinePoints = '';
-	          for (var k = 0; k < this.bandsDataSpin2[i][j].length; k++) { // loop the bands
-	            polylinePoints+= ' '+this.xRel*this.bandsDataSpin2[i][j][k].x+
-	              ' '+this.transformY(this.bandsDataSpin2[i][j][k].y);
-	          }
-	          svg.addPolyline(this.plotContent, polylinePoints, 'plotSpin2');
-	        }
-	    }
-
-
-	    // Paint CBM and VBM
-	    // console.log("Paint CBM and VBM: ", this.vbm); this.vbm.y = -1.01577992001999e-20/this.factor;
-	    if (this.bandGapData !== undefined
-	      // If there are two spins related data the CBM and VBM points aren't shown
-	    /*&& this.bandsDataSpin2.length === 0*/)
-	       {
-
-	         this.bandGapData.cbmDistances.forEach( distance => {
-	           let x = this.xRel * distance;
-	           let y = this.transformY(this.bandGapData.lower.energy/this.factor);
-	           //console.log("hhhhhhhhh: ", x, y);
-	           svg.addPoint(this.plotContent, x, y , 3, 'cbm-vbm-points');
-	           svg.addText(this.plotContent, x+4, y-6, 'CBM');
-	         });
-
-
-	         this.bandGapData.vbmDistances.forEach( distance => {
-	           let x = this.xRel*distance;
-	           let y = this.transformY(this.bandGapData.upper.energy/this.factor);
-	           svg.addPoint(this.plotContent, x, y, 3, 'cbm-vbm-points');
-	           svg.addText(this.plotContent, x+4, y+14, 'VBM');
-	          });
-
-	        /*
-
-	      let x = this.xRel*this.bandGapData.cbmDistance;
-	      let y = this.transformY(this.bandGapData.lower.energy/this.factor);
-	      //console.log("hhhhhhhhh: ", x, y);
-	      svg.addPoint(this.plotContent, x, y , 3, 'cbm-vbm-points');
-	      svg.addText(this.plotContent, x+4, y-6, 'CBM');
-
-	      x = this.xRel*this.bandGapData.vbmDistance;
-	      y = this.transformY(this.bandGapData.upper.energy/this.factor);
-	      svg.addPoint(this.plotContent, x, y, 3, 'cbm-vbm-points');
-	      svg.addText(this.plotContent, x+4, y+14, 'VBM');
-	      */
-	    }
-
-	  }
-
-
-	}
-
-
-	function kPointDistance(kPoints, position){
-	  let p0= kPoints[0];
-	  let p1= kPoints[position];
-	  let deltaX= p1[0] - p0[0];
-	  let deltaY= p1[1] - p0[1];
-	  let deltaZ= p1[2] - p0[2];
-	  return Math.sqrt(deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ);
-	}
-
-	function getSymbol(label){
-	  if (label === 'Gamma' || label === 'G') return 'Γ';
-	  else return label;
-	}
-
-	// EXPORTS
-	module.exports = BSPlotter;
-
-
-/***/ },
-/* 15 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-	 /*
-	  This is the base class that models a highly interactive plotter.
-	  It is inherited by several classes implementing specifc plotters.
-	  This plotter implements zoom and y-axis offset
-	 */
-
-
-	"use strict";
-
-
-	let svg = __webpack_require__(9);
-
-	const xmlns="http://www.w3.org/2000/svg";
-	const xlink="http://www.w3.org/1999/xlink";
-
-
-	class InteractivePlotterBase{
-
-	  constructor(margins = {left: 20, right: 0, top: 0, bottom: 20}) {
-	    this.margins= margins;
-	    this.svg = document.createElementNS(xmlns, "svg");
-
-	    this.parentElement= null;
-	    this.plotContent = null;
-	    this.axisGroup = null;
-	    this.yAxisLabelsGroup = null;
-	    this.yLabelText = null; // If null, y axis label and numbers are not painted
-	    this.noDataGroup = null;
-
-	    this.yZoom = 1;  // Initial zoom
-	    this.yOffset = 0; // Initial y offset = 0
-	    this.repaintListener = null;
-	    this.nodataLabel = null;
-
-	    this.outOfRangeColorActivated = true;
-	  }
-
-
-	  attach(element, width, height){
-	    this.parentElement= element;
-	    this.parentElement.appendChild(this.svg);
-	    this.width = (width !== undefined ? width : this.parentElement.clientWidth);
-	    this.height = (height !== undefined ? height : this.svg.width);
-	    this.svg.setAttribute("width", this.width);
-	    this.svg.setAttribute("height", this.height);
-	    this.plotRangeX = this.width - this.margins.left - this.margins.right;
-	    this.plotRangeY = this.height - this.margins.top - this.margins.bottom;
-
-	    // y axis area (zoomable)
-	    this.yAxisArea = document.createElementNS(xmlns, "svg");
-	    this.svg.appendChild(this.yAxisArea);
-	    let yAxisAreaWidth = this.margins.left;
-	    this.plotAreaHeight = this.height - this.margins.bottom - this.margins.top;
-	    this.yAxisArea.setAttribute("width", yAxisAreaWidth);
-	    this.yAxisArea.setAttribute("height", this.plotAreaHeight);//-OVERLAP_CORRECTOR);
-	    this.yAxisArea.setAttribute("x", 0);
-	    this.yAxisArea.setAttribute("y", 0);//OVERLAP_CORRECTOR);
-
-	    // SVG plot area window
-	    this.plotArea = document.createElementNS(xmlns, "svg");
-	    this.svg.appendChild(this.plotArea);
-	    this.plotAreaWidth = this.width - this.margins.left - this.margins.right;
-	    this.plotArea.setAttribute("width", this.plotAreaWidth);
-	    this.plotArea.setAttribute("height", this.plotAreaHeight);
-	    this.plotArea.setAttribute("x", this.margins.left);
-	    this.plotArea.setAttribute("y", this.margins.top);
-
-	    // Rect filling plot area in order to support styles and events
-	    this.plotAreaBg  = svg.addRect(this.plotArea, 0, 0, this.plotAreaWidth, this.plotAreaHeight);
-	    this.plotAreaBg.setAttribute('class', 'moveable-plot');
-	    this.plotAreaBg.setAttribute('opacity', 0.0);
-
-	    this. _events();
-	  }
-
-
-	  isAttached(){
-	    return this.parentElement !== null;
-	  }
-
-
-	  setAxisRangeAndLabels(xLabel, xMin, xMax, yLabel, yMinInit, yMaxInit,
-	    yMin, yMax, yLabelGap, decimals = 2){
-	    this.xLabel= xLabel;
-	    this.xMin = xMin;
-	    this.xMax = xMax;
-	    this.yMinInit= yMinInit;
-	    this.yMaxInit= yMaxInit;
-	    this.yMin= yMin;
-	    this.yMax= yMax;
-	    this.yLabelGapInit = yLabelGap;
-	    this.xRel= this.plotRangeX/(this.xMax-this.xMin);
-	    this.yRel= this.plotRangeY/(this.yMaxInit-this.yMinInit);
-
-	    this._resetAxisGroup();
-
-	    // Draw axes
-	    svg.addLine(this.axisGroup, 0,0,this.plotRangeX,0,  'main-axis');
-	  	svg.addLine(this.axisGroup, 0,0,0,-this.plotRangeY ,'main-axis');
-	    svg.addLine(this.axisGroup, this.plotRangeX, 0, this.plotRangeX, -this.plotRangeY, 'main-axis');
-	  	svg.addLine(this.axisGroup, 0,-this.plotRangeY, this.plotRangeX, -this.plotRangeY, 'main-axis');
-
-	    // Paint x and y axes labels
-	    if (yLabel !== null){
-	      this.yLabelText = svg.addText(this.svg, 0, 0, yLabel, 'middle', 'axis-steps-big');
-	      this.yLabelText.setAttribute('transform','translate(15,'+(this.plotRangeY/2+this.margins.top)+') rotate(-90)');
-	    }
-	    if (xLabel !== null)
-	      svg.addText(this.axisGroup, this.plotRangeX/2, this.margins.bottom-12, this.xLabel, 'middle', 'axis-steps-big');
-
-	    // initialize y axis steps (dynamic construction) container
-	    this._resetYAxisLabelGroup();
-
-	    // transformY precalcultation 1
-	    this.precalculation_1 = this.plotAreaHeight  + this.yMinInit*this.yRel;
-	    this.precalculation_2 = this.precalculation_1;//- this.yOffset // when this quantity changes
-	  }
-
-
-	  _events(){
-
-	    this.plotArea.addEventListener('wheel', (e) => {
-	      e.preventDefault();
-	      if (e.deltaY > 0 && this.yZoom > 0.5 ) this.yZoom -= 0.2;
-	      else if (e.deltaY < 0 && this.yZoom < 2) this.yZoom += 0.2;
-	      this.repaint();
-	      if (this.repaintListener !== null)
-	        this.repaintListener(this.yZoom, this.yOffset);
-	    });
-
-	    let initPosY;
-	    this.plotArea.addEventListener('mousedown', (e) => {
-	      e.preventDefault();
-	      initPosY = e.clientY + this.yOffset;
-	      //console.log('mousedown: e.clientY + this.yOffset', e.clientY, this.yOffset);
-	      this.plotArea.addEventListener('mousemove', moveListener);
-
-	      this.plotArea.addEventListener('mouseup', (e) => {
-	        this.plotArea.removeEventListener('mousemove', moveListener);
-	      });
-	      this.plotArea.addEventListener('mouseout', (e) => {
-	        this.plotArea.removeEventListener('mousemove', moveListener);
-	      });
-	    });
-
-	    let self = this;
-	    function moveListener(e) {
-	      //console.log('Y offset:', e.clientY - initPosY);
-	      // Bad if (initPosY - e.clientY > this.yMax || initPosY - e.clientY < this.yMin)
-	      self.yOffset = initPosY - e.clientY ;
-	      self.precalculation_2 = self.precalculation_1 - self.yOffset;
-	      self.repaint();
-	      if (self.repaintListener !== null)
-	        self.repaintListener(self.yZoom, self.yOffset);
-	    }
-	  }
-
-
-	  setYZoomAndOffset(yZoom, yOffset){
-	    this.yZoom = yZoom;
-	    this.yOffset = yOffset;
-	    this.precalculation_2 = this.precalculation_1 - this.yOffset;
-	  }
-
-
-	  setExternalYAxisMax(externalYAxisMax){
-	    this.externalYAxisMax = externalYAxisMax;
-	  }
-
-
-	  getYAxisMax(){
-	    return this.yAxisMax;
-	  }
-
-
-	  repaint(){
-	    // repaint Y axis
-	    this._resetYAxisLabelGroup();
-
-	    let yLabelGap;
-	    if (this.yZoom > 1) yLabelGap = this.yLabelGapInit/5;
-	    else yLabelGap = this.yLabelGapInit;
-
-	    let min = Math.floor(this.yMin/yLabelGap)*yLabelGap;
-	    let max = Math.ceil(this.yMax/yLabelGap)*yLabelGap;
-	    this.yAxisMax = max;
-	    if (this.externalYAxisMax !== undefined) max = this.externalYAxisMax;
-
-	    if (this.yLabelText !== null) {
-	      for (let i = min; i < max+1; i = i + yLabelGap) {
-	        svg.addLine(this.yAxisLabelsGroup, this.margins.left,
-	          this.transformY(i), this.margins.left-3, this.transformY(i));
-	        svg.addText(this.yAxisLabelsGroup, this.margins.left-5,
-	          this.transformY(i)+5, i, 'end', 'axis-steps');
-	      }
-	    }
-
-	    // repaint plot content
-	    this._resetPlotContent();
-
-	    // Out of range areas
-	    if (this.outOfRangeColorActivated){
-	      let area = svg.addRect(this.plotContent, 0, this.transformY(this.yMax)-2*this.plotAreaHeight, this.plotAreaWidth, 2*this.plotAreaHeight);
-	      area.setAttribute('class', 'out-of-range');
-	      let area1 = svg.addRect(this.plotContent, 0, this.transformY(this.yMin), this.plotAreaWidth, 2*this.plotAreaHeight);
-	      area1.setAttribute('class', 'out-of-range');
-	    }
-
-	    // Zero line
-	    svg.addLine(this.plotContent, 0, this.transformY(0), this.plotRangeX,
-	      this.transformY(0), 'zeroline');
-
-	    // repaint data lines
-	    this.repaintData(min, max);
-
-	    // Add the top layer: rect for events
-	    this.plotArea.removeChild(this.plotAreaBg);
-	    this.plotArea.appendChild(this.plotAreaBg);
-	  }
-
-
-	  setRepaintListener(listener) {
-	    this.repaintListener = listener;
-	  }
-
-
-	  transformY(y){
-	    // Precalculation usage
-	    // this.plotAreaHeight -y*this.yZoom*this.yRel + this.yMinInit*this.yRel - this.yOffset
-	    // -y*this.yZoom*this.yRel (calculated here)  this.plotAreaHeight  + this.yMinInit*this.yRel - this.yOffset
-	    let result = -y*this.yZoom*this.yRel + this.precalculation_2;
-	    if (result > 10000) throw 'Y coordinate too large';
-	    return result;
-	  }
-
-
-	  _resetPlotContent(){
-	    // TRy to delete with textContent property
-	    if (this.plotContent !== null)
-	      this.plotArea.removeChild(this.plotContent);
-	    this.plotContent = document.createElementNS(xmlns, "g");
-	    this.plotArea.appendChild(this.plotContent);
-	  }
-
-
-	  _resetAxisGroup(){
-	    if (this.axisGroup !== null)
-	      this.svg.removeChild(this.axisGroup);
-	    this.axisGroup = document.createElementNS(xmlns, 'g');
-	    this.svg.appendChild(this.axisGroup);
-
-	    // The y axis is inverted so the y coordinate has to be multiplied by -1
-	    this.axisGroup.setAttribute("transform", 'matrix(1 0 0 1 '+
-	      this.margins.left+' '+(this.height - this.margins.bottom)+')');
-	  }
-
-
-	  _resetYAxisLabelGroup(){
-	    if (this.yLabelText === null) return;
-
-	    if (this.yAxisLabelsGroup !== null)
-	      this.yAxisArea.removeChild(this.yAxisLabelsGroup);
-	    this.yAxisLabelsGroup = document.createElementNS(xmlns, 'g');
-	    this.yAxisArea.appendChild(this.yAxisLabelsGroup);
-	    //this.yAxisLabelsGroup.setAttribute("transform", 'matrix(1 0 0 1 0 -'+OVERLAP_CORRECTOR+')');
-	  }
-
-
-	  _reset(){
-	    this.yZoom = 1;  // Initial zoom
-	    this.yOffset = 0; // Initial y offset = 0
-
-	    // initialize plot content (dynamic construction) container
-	    this._resetPlotContent();
-
-	    if (this.yLabelText !== null){
-	      this.svg.removeChild(this.yLabelText);
-	      this.yLabelText = null;
-	    }
-
-	    if (this.noDataGroup !== null){
-	      this.svg.removeChild(this.noDataGroup);
-	      this.noDataGroup = null;
-	    }
-	  }
-
-
-	  setNoData(){
-	    this._resetYAxisLabelGroup();
-	    this._resetPlotContent();
-	    this._resetAxisGroup();
-	    if (this.noDataGroup === null){
-	      this.noDataGroup = document.createElementNS(xmlns, 'g');
-	      this.svg.appendChild(this.noDataGroup);
-	      svg.addRect(this.noDataGroup, 0, 0, this.width, this.height);
-	      this.noDataGroup.setAttribute('fill', '#EEE');
-	      svg.addText(this.noDataGroup, this.width/2, this.height/2+10,
-	        'NO DATA', 'middle', 'nodata');
-	    }
-
-	  }
-
-	}
-
-	// EXPORTS
-	module.exports = InteractivePlotterBase;
-
-
-/***/ },
-/* 16 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-	 /*
-	  Implements the DOS plotter.
-	 */
-
-
-	"use strict";
-
-	let InteractivePlotterBase = __webpack_require__(15);
-	let svg = __webpack_require__(9);
-	let util = __webpack_require__(1);
-
-
-	const E_MIN = -6;
-	const E_MAX = 11;
-	const E_FACTOR = 1.602176565e-19;
-	//const DOSVALUE_FACTOR = 1.602176565e-49;
-
-
-	class DOSPlotter extends InteractivePlotterBase{
-
-	  constructor(margins) {
-	    super(margins);
-	  }
-
-	  // detach if necessary and attach
-	  attach(element, width, height){
-	    super.attach(element, width, height);
-	  }
-
-
-	  setPoints(points, codeName){
-
-	    let dosValueDivisor =  E_FACTOR;
-	    //if (codeName === 'VASP') dosValueDivisor =  1e-10*(E_FACTOR*E_FACTOR);
-
-	    this.pointsSpin1 = [];
-	    this.pointsSpin2 = [];
-	    this._reset();
-
-	    let pSpin1= points.dos_values[0];
-	    let pSpin2 = null;
-	    if (points.dos_values.length === 2)  pSpin2 = points.dos_values[1];
-	    let pointsY= points.dos_energies;
-	    let pointsXInPlotRange = [];
-	    let pointsYInPlotRange = [];
-
-	    for (var i = 0; i < pointsY.length; i++) {
-	      let energy = pointsY[i]/E_FACTOR;
-	      let dos_value_spin1 = pSpin1[i]/dosValueDivisor;
-	      pointsXInPlotRange.push(dos_value_spin1);
-	      if (pSpin2 !== null) pointsXInPlotRange.push(pSpin2[i]);
-	      pointsYInPlotRange.push(energy);
-	      //console.log('POINTS : ',pointsX[i], energy);
-	      this.pointsSpin1.push({x: dos_value_spin1, y: energy});
-	      if (pSpin2 !== null)
-	        this.pointsSpin2.push({x: pSpin2[i]/dosValueDivisor, y: energy});
-	    }
-
-	    let maxDosVal = Math.max.apply(null, pointsXInPlotRange);
-	    let maxEnergyVal = Math.max.apply(null, pointsYInPlotRange);
-	    let minEnergyVal = Math.min.apply(null, pointsYInPlotRange);
-
-	    // x axis steps generation
-	    let t = util.generateDiagramSteps(maxDosVal);
-	    let xSteps = t[0], exp = t[1];
-
-	    this.setAxisRangeAndLabels(null, 0, xSteps[xSteps.length-1], 'Energy (eV)',
-	      E_MIN, E_MAX, minEnergyVal, maxEnergyVal, 5);
-
-	    svg.addText(this.axisGroup, this.plotRangeX/2, this.margins.bottom,
-	      'DOS (states/eV/cell)', 'middle', 'axis-steps-big');
-
-	    // draw x axis steps
-	    for (let i = 0; i < xSteps.length; i++) {
-	      let stepX = (this.plotRangeX*xSteps[i])/xSteps[xSteps.length-1];
-	      svg.addLine(this.axisGroup, stepX, 0, stepX, 3, 1);
-	      //console.log('step ',xSteps[i], stepX);
-	      svg.addText(this.axisGroup, stepX, 13,
-	        (i === 0 ? '0' : xSteps[i].toFixed(exp)),'middle', 'axis-steps-smaller');
-	    }
-
-	    this.repaint();
-	  }
-
-
-	  repaintData(){
-
-	    let polylinePoints = '';
-	    for (var i = 0; i < this.pointsSpin1.length; i++) {
-	      polylinePoints+= ' '+this.xRel*this.pointsSpin1[i].x+
-	        ' '+this.transformY(this.pointsSpin1[i].y);
-	    }
-	    svg.addPolyline(this.plotContent, polylinePoints, 'plotSpin1');
-
-	    polylinePoints = '';
-	    for (var i = 0; i < this.pointsSpin2.length; i++) {
-	      polylinePoints+= ' '+this.xRel*this.pointsSpin2[i].x+
-	        ' '+this.transformY(this.pointsSpin2[i].y);
-	    }
-	    svg.addPolyline(this.plotContent, polylinePoints, 'plotSpin2');
-	  }
-
-
-	  setYAxisLabelsVisibility(value){
-	    if (this.yAxisLabelsGroup !== null)
-	      this.yAxisLabelsGroup.style.visibility = (value ? 'visible' : 'hidden');
-	  }
-
-	}
-
-
-	// EXPORTS
-	module.exports = DOSPlotter;
-
-
-/***/ },
-/* 17 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-	  Specific Heat plotter implementation
-	 */
-
-
-	"use strict";
-
-	let svg = __webpack_require__(9);
-	let PlotterBase = __webpack_require__(18);
-
-
-	class HeatCapPlotter extends PlotterBase{
-
-	  constructor() {
-	    super({left: 50, right: 16, top: 10, bottom: 32});
-	    this.tooltip;
-	  }
-
-
-	  setData(data){
-	    //console.log(JSON.stringify(data));//
-	    this.clear();
-	    // up to 600K data is taken
-	    let indexOf600K = data.temperature.indexOf(600)+1;
-	    let values = data.value.slice(0, indexOf600K);
-	    let temperatures = data.temperature.slice(0, indexOf600K);
-
-	    let yMaxValue = Math.max.apply(null, values);
-	    //console.log('maxValue: ',maxValue);//
-	    this.setRangeAndLabels('T (K)', 0, 600, 'Cv (J/K/kg)', 0, Math.ceil(yMaxValue/200)*200);
-	    this.drawAxis(4, 4, 0);
-
-	    let polylinePoints = '';
-	    temperatures.forEach( (t, i) => {
-	        let y = values[i];///1e-25;
-	        polylinePoints+= ' '+this.xRel*t+' -'+this.yRel*(y - this.yMin);
-	    });
-	    svg.addPolyline(this.plotArea, polylinePoints, 'plotSpin1');
-	  }
-
-	}
-
-
-	// EXPORTS
-	module.exports = HeatCapPlotter;
-
-
-/***/ },
-/* 18 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-	 /*
-	  This is the base class that models a regular plotter.
-	  It is inherited by several classes implementing specifc plotters
-	 */
-
-	"use strict";
-
-
-	let svg = __webpack_require__(9);
-
-	const xmlns="http://www.w3.org/2000/svg";
-	const xlink="http://www.w3.org/1999/xlink";
-
-
-	class PlotterBase{
-
-	  constructor(margins = {left: 20, right: 0, top: 10, bottom: 20}) {
-	    this.svg = document.createElementNS(xmlns, "svg");
-	    this.plotArea = document.createElementNS(xmlns, "g");
-	    this.svg.appendChild(this.plotArea);
-
-	    this.margins= margins;
-	    this.parentElement= null;
-	    this.yLabelText = null;
-	    this.noDataGroup = null;
-	  }
-
-
-	  attach(element, width, height){
-	    this.parentElement= element;
-	    this.parentElement.appendChild(this.svg);
-	    this.width = (width !== undefined ? width : this.parentElement.clientWidth);
-	    this.height = (height !== undefined ? height : this.svg.width);
-	    this.svg.setAttribute("width", this.width);
-	    this.svg.setAttribute("height", this.height);
-	    this.plotRangeX = this.width - this.margins.left - this.margins.right;
-	    this.plotRangeY = this.height - this.margins.top - this.margins.bottom;
-	  }
-
-
-	  isAttached(){
-	    return this.parentElement !== null;
-	  }
-
-
-	  setRangeAndLabels(xLabel, xMin, xMax, yLabel, yMin, yMax){
-	    this.xLabel= xLabel;
-	    this.xMin = xMin;
-	    this.xMax = xMax;
-	    this.yLabel= yLabel;
-	    this.yMin= yMin;
-	    this.yMax= yMax;
-
-	    this.xRel= this.plotRangeX/(this.xMax-this.xMin);
-	    this.yRel= this.plotRangeY/(this.yMax-this.yMin);
-	  }
-
-
-	  drawAxis(xSteps = 0, ySteps = 0, decimals = 2){
-
-		  this.plotArea.setAttribute("transform", 'matrix(1 0 0 1 '+
-	      this.margins.left+' '+(this.height  - this.margins.bottom)+')');
-
-	    this.yLabelText = svg.addText(this.svg, 0, 0, this.yLabel, 'middle', 'axis-steps-big');
-	    this.yLabelText.setAttribute('transform','translate(13,'
-	      +(this.plotRangeY/2+this.margins.top)+') rotate(-90)');
-		  svg.addText(this.plotArea, this.plotRangeX/2, this.margins.bottom-1,
-	      this.xLabel, 'middle', 'axis-steps-big');
-
-	    if (xSteps !== null){
-	      let xStep= this.plotRangeX/ xSteps;
-	      for (let i = 0; i <= xSteps; i++) {
-	        svg.addLine(this.plotArea, xStep*i, 0, xStep*i, 4, 1);
-	        svg.addText(this.plotArea, xStep*i, 14,
-	          +((xStep*i/this.xRel)+this.xMin).toFixed(decimals), 'middle', 'statisticsviewersteps');
-	      }
-	    }
-
-	    if (ySteps === null && this.yMax > 0 && this.yMin < 0){
-	      let i = 1;
-	      while(this.yMax*i > this.yMin) {
-	        svg.addLine(this.plotArea, 0, this.transformY(this.yMax*i), -3, this.transformY(this.yMax*i), 1);
-	        let numberText = (Math.abs(this.yMax*i) >= 10000 ? (this.yMax*i).toExponential() : this.yMax*i );
-	        svg.addText(this.plotArea,-5, this.transformY(this.yMax*i)+3, numberText,
-	          'end', 'statisticsviewersteps');
-	        i--;
-	      }
-	    }
-
-	    if (ySteps !== null){
-	        let yStep= this.plotRangeY/ ySteps;
-	        for (let i = 0; i <= ySteps; i++) {
-	          svg.addLine(this.plotArea, 0, -yStep*i, -3, -yStep*i, 1);
-	          let numberToPaint= (yStep*i/this.yRel) + this.yMin;
-	          // Fix to prevent the the -0 printing
-	          if (Math.abs(numberToPaint) < 0.01) numberToPaint = 0;
-	          //console.log('drawAxis', yStep, i, this.yRel, this.yMin, numberToPaint);
-	          svg.addText(this.plotArea,-5, -(yStep*i-3), numberToPaint.toFixed(decimals), 'end', 'statisticsviewersteps');
-	        }
-	    }
-
-		  svg.addLine(this.plotArea, 0, 0, this.plotRangeX+1 ,0 ,'main-axis');
-		  svg.addLine(this.plotArea, 0,0,0,-(this.plotRangeY+1) ,'main-axis');
-	    svg.addLine(this.plotArea, this.plotRangeX, 0, this.plotRangeX, -this.plotRangeY ,'main-axis');
-	  	svg.addLine(this.plotArea, 0,-this.plotRangeY, this.plotRangeX, -this.plotRangeY,'main-axis');
-	  }
-
-
-	  clear(){
-	    this.svg.removeChild(this.plotArea);
-	    this.plotArea = document.createElementNS(xmlns, "g");
-	    this.svg.appendChild(this.plotArea);
-	    this.plotArea.setAttribute("transform", 'matrix(1 0 0 1 '+
-	        this.margins.left+' '+(this.height  - this.margins.bottom)+')');
-
-	    if (this.yLabelText !== null){
-	      this.svg.removeChild(this.yLabelText);
-	      this.yLabelText = null;
-	    }
-	    if (this.noDataGroup !== null){
-	      this.svg.removeChild(this.noDataGroup);
-	      this.noDataGroup = null;
-	    }
-	  }
-
-
-	  setNoData(){
-	    this.clear();
-	    if (this.noDataGroup === null){
-	      this.noDataGroup = document.createElementNS(xmlns, 'g');
-	      this.svg.appendChild(this.noDataGroup);
-	      svg.addRect(this.noDataGroup, 0, 0, this.width, this.height);
-	      this.noDataGroup.setAttribute('fill', '#EEE');
-	      svg.addText(this.noDataGroup, this.width/2, this.height/2+10,
-	        'NO DATA', 'middle', 'nodata');
-	    }
-
-	  }
-
-
-	  // Transform from y-axis units to  y-axis pixels (svg-coordinates)
-	  transformY(y){
-	    return -this.yRel*(y - this.yMin);
-	  }
-
-	}
-
-
-	// EXPORTS
-	module.exports = PlotterBase;
-
-
-/***/ },
-/* 19 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-	 /*
-	  'Details' view container that shows all the material info related to
-	  its structure.
-
-	  This container is extremely complex.
-
-	  In the file there are two defined (classes) components used in the container:
-	  - TreeLeafViewer: The panel on the right showing the data of the tree leaf marked
-	  - SummaryByFunctionalsComponent: the component (central panel, below part)
-	  showing a summary for the selected item on the tree (by functional)
-	 */
-
-	"use strict";
-
-	let DetailsViewBase = __webpack_require__(20);
-	let util = __webpack_require__(1);
-	let InfoSys = __webpack_require__(12);
-	let CalcSelectorBar = __webpack_require__(21);
-	let StatsViewer = __webpack_require__(22);
-	let EquationOfStateViewer = __webpack_require__(23);
-	let DataStore = __webpack_require__(2);
-	let LoadingPopup = __webpack_require__(4);
-
-
-
-	class StructureDetails extends DetailsViewBase {
-
-	  constructor() {
-	    super('Structure');
-	    this.groupsData; // the calcs groups data is necesary to be shown
-
-	    this.firstId;
-	    this.lastId;
-
-	    this.element.innerHTML+=`
-
-	      <div style="float: left; width: 36%;">
-	        <div class="view-box">
-	          <div class="title">Structure </div>
-	          <div class="viz-box" style="height: 400px; position: relative"></div>
-
-	          <div class="footer-flex-wrapper">
-
-	            <div class="fields-container">
-	              <div><b><span>System type</span></b>:
-	                <span class="struct-field" ></span>
-	              </div>
-	              <div class="structure-type-field" style="display: none">
-	                <b><span info-sys-data="structure-type">Structure type</span></b>:
-	                <span class="structure-type-value" ></span>
-	              </div>
-	              <div class="structure-prototype-field" style="display: none">
-	                <b><span info-sys-data="structure-prototype">Structure prototype</span></b>:
-	                <span class="structure-prototype-value" ></span>
-	              </div>
-	              <div class="strukturbericht-field" style="display: none">
-	                <b><span info-sys-data="strukturbericht">Strukturbericht designation</span></b>:
-	                <span class="strukturbericht-value" ></span>
-	              </div>
-	            </div>
-
-	            <div class="footer-flex" style="display: none">
-
-	              <div class="fields-container"
-	                style="flex-basis: 70%; border-right: 1px solid #E4E4E4; ">
-
-	                <div>
-	                  <b><span info-sys-data="crystal-system">Lattice</span></b>:
-	                  <span class="lattice-value" ></span>
-	                </div>
-	                <div>
-	                  <b><span info-sys-data="space-group">Space group</span></b>:
-	                  <span class="space-group-value" ></span>
-	                </div>
-	                <div>
-	                  <b><span info-sys-data="point-group">Point group</span></b>:
-	                  <span class="point-group-value" ></span>
-	                </div>
-	              </div>
-
-	              <div style="flex-basis: 30%; margin-left: 30px;">
-	                <div class="fields-container">
-	                  <div><b><span info-sys-data="wyckoff-position-population">Wyckoff sites</span></b></div>
-	                  <div class="wyckoff-sites-value"> </div>
-	                </div>
-	              </div>
-
-	            </div>
-
-	          </div>
-
-	        </div>
-	      </div>
-
-	      <div style="float: left; width: 36%;">
-	        <div class="view-box">
-	          <div class="title">Calculations</div>
-	          <div class="navTreeWrapper"></div>
-
-	          <div class="summary-title">Summary  </div>
-	          <div style="font-size: 0.85em; text-align: center; padding: 4px;">Based on the calculations selected above</div>
-
-	          <div class="info-fields summary-box">
-	          <!-- Lattice constants Cell volume, Density panel dynamically generated
-	            -->
-	          </div>
-	        </div>
-	      </div>
-
-	      <div style="float: right; width: 28%;">
-	        <div class="calc-specifics-box">
-
-	          <div style="padding-top: 10px; " >
-	            <div class="tree-leaf-title"></div>
-	          </div>
-
-	          <div class="tree-leaf-viewer-host"></div>
-
-	          </div>
-	        </div>
-
-	      </div>
-	    </div>
-	    `;
-
-	    this.navTreeWrapper =
-	        this.element.getElementsByClassName("navTreeWrapper")[0];
-
-	    let fields= this.element.getElementsByClassName('struct-field');
-	    this.systemTypeField= fields[0];
-	    this.structTypeField= this.element.querySelector('.structure-type-field');
-	    this.structTypeValue= this.element.querySelector('.structure-type-value');
-	    this.structPrototypeField= this.element.querySelector('.structure-prototype-field');
-	    this.structPrototypeValue= this.element.querySelector('.structure-prototype-value');
-	    this.strukturberichtField= this.element.querySelector('.strukturbericht-field');
-	    this.strukturberichtValue= this.element.querySelector('.strukturbericht-value');
-
-	    this.lowerBox = this.element.querySelector('.footer-flex');
-	    this.latticeValue= this.element.querySelector('.lattice-value');
-	    this.spaceGroupValue= this.element.querySelector('.space-group-value');
-	    this.pointGroupValue= this.element.querySelector('.point-group-value');
-	    this.wyckoffValue= this.element.querySelector('.wyckoff-sites-value');
-
-	    this.summaryByFunctionals = null;
-
-	    this.leafTitle = this.element.querySelector('.tree-leaf-title');
-
-	    this.summaryBox = this.element.querySelector('.summary-box');
-
-	    this.calcSpecificsBox = this.element.querySelector('.calc-specifics-box');
-
-	    this.treeLeafViewer = new TreeLeafViewer();
-	    this.element.querySelector('.tree-leaf-viewer-host').
-	      appendChild(this.treeLeafViewer.element);
-
-	    this.vizBox = this.element.querySelector('.viz-box');
-
-	    // For static ones
-	    InfoSys.addToInfoSystem(this.element);
-	  }
-
-
-	  setMaterialData() {
-	    let data = DataStore.getMaterialData();
-	    super.setMaterialData(data);
-	    this.isBulk = (data.system_type === 'bulk');
-
-	    this.systemTypeField.textContent= data.system_type;
-	    this.structTypeField.style.display =
-	      (this.isBulk && data.structure_type !== null ? 'block' : 'none');
-	    this.structPrototypeField.style.display =
-	      (this.isBulk && data.structure_prototype !== null ? 'block' : 'none');
-	    this.strukturberichtField.style.display =
-	      (this.isBulk && data.strukturbericht_designation !== null ? 'block' : 'none');
-
-	    this.lowerBox.style.display = (this.isBulk ? 'flex' : 'none');
-
-	    if (this.isBulk){
-	      this.structTypeValue.textContent= data.structure_type;
-	      this.structPrototypeValue.textContent= data.structure_prototype;
-	      this.strukturberichtValue.textContent= data.strukturbericht_designation;
-	      this.spaceGroupValue.textContent = data.space_group_number
-	        +' ('+data.space_group_international_short_symbol+')';
-	      this.pointGroupValue.textContent = data.point_group;
-	      this.latticeValue.textContent = data.crystal_system;
-
-	      // wyckoff processing
-	      let wyckoffMap = new Map();
-	      let valueSet= new Set();
-
-	      for (var i = 0; i < data.elements.length; i++) {
-	        let element = util.ELEMENTS[data.elements[i].label-1];
-	        if (wyckoffMap.has(element)){
-	          wyckoffMap.get(element).add(data.elements[i].wyckoff);
-	        }else {
-	          let newSet = new Set();
-	          newSet.add(data.elements[i].wyckoff);
-	          wyckoffMap.set(element, newSet);
-	        }
-	      }
-	      let wyckoffHTML= '';
-	      wyckoffMap.forEach((posSet, element) => {
-	        let firstPos = true;
-	        wyckoffHTML += '<tr> <td>'+element+': </td>';
-	        posSet.forEach( pos => {
-	          if (firstPos){
-	            firstPos = false;
-	            wyckoffHTML += '<td>'+pos+'</td></tr>';
-	          }else
-	            wyckoffHTML += '<tr><td> </td><td>'+pos+'</td></tr>';
-	        });
-	      });
-
-	      this.wyckoffValue.innerHTML = '<table>' + wyckoffHTML+'</table>';
-	    }
-
-	    InfoSys.addElementToInfoSystem(this.spaceGroupValue,
-	      'space-group.value:'+data.space_group_number);
-	    InfoSys.addElementToInfoSystem(this.latticeValue,
-	      'crystal-system.value:'+data.crystal_system);
-	    InfoSys.addElementToInfoSystem(this.pointGroupValue,
-	      'point-group.value:'+data.point_group);
-	    //InfoSys.addElementToInfoSystem(this.wyckoffValue, 'wyckoff-position-population.value:'+);
-	  }
-
-
-	  updateSelection(leafIds /*Set*/) {
-	    //console.log('StructureDetails.updateSelection: ', leafIds);
-	    if (leafIds.size > 0){
-	      this.summaryBox.style.visibility = 'visible';
-
-	      let summaryCalcSet = new Set();
-	      leafIds.forEach( leafId => {
-	        let calc;
-	        if (DataStore.getGroups().has(leafId)){
-	          calc = DataStore.getCalc(DataStore.getGroups().get(leafId).method_representative);
-	        }else
-	          calc = DataStore.getCalc(parseInt(leafId));
-	        summaryCalcSet.add(calc);
-	      });
-
-	      let calcMapByFunctional = getCalcMapByFunctional(summaryCalcSet);
-	      if (this.summaryByFunctionals === null)
-	        this.summaryByFunctionals =
-	          new SummaryByFunctionalsComponent(calcMapByFunctional, this.summaryBox);
-	      else
-	        this.summaryByFunctionals.build(calcMapByFunctional);
-
-	      let counter= 0;
-	      leafIds.forEach( calcId => {
-	        counter++;
-	        if (counter === 1) this.firstId = calcId;
-	        else if (counter === leafIds.size) this.lastId = calcId;
-	      });
-
-	    }else{
-	      this.summaryBox.style.visibility = 'hidden';
-	    }
-
-	    function getCalcMapByFunctional(summaryCalcSet){
-
-	      let functCalcMap = new Map();
-	      summaryCalcSet.forEach( calc => {
-	        if (functCalcMap.has(calc.functional_type)){
-	          functCalcMap.get(calc.functional_type).add(calc);
-
-	        }else{ // New functional
-	          let newFunctionalArray = new Set();
-	          newFunctionalArray.add(calc);
-	          functCalcMap.set(calc.functional_type, newFunctionalArray);
-	        }
-	      });
-	      //console.log('functCalcMap: ',functCalcMap);
-	      return functCalcMap;
-	    }
-	  }
-
-
-	  updateMarkedLeaf(leafId){
-
-	    if (leafId !== null){
-	      this.calcSpecificsBox.style.visibility = 'visible';
-	      //this.calcSpecificsBox.style.backgroundColor= '#FFF7EB';
-
-	      if (DataStore.getGroups().has(leafId)){
-	        this.leafTitle.innerHTML = leafId+
-	          ' ('+DataStore.getGroups().get(leafId).calcs.size+')';
-	      }else
-	        this.leafTitle.innerHTML = leafId;
-
-	    }else
-	      this.calcSpecificsBox.style.visibility = 'hidden';
-	      //this.calcSpecificsBox.style.backgroundColor= 'white';
-	      //this.leafTitle.innerHTML = 'NO SELECTION';
-
-	    this.treeLeafViewer.update(leafId, DataStore.getGroups().get(leafId));
-	  }
-
-	}
-
-
-	class TreeLeafViewer{
-
-	  constructor(hostClass){
-	    this.groupCalcs = null;
-	    this.element = document.createElement('div');
-	    this.element.innerHTML = `
-	    <div>
-
-	      <div class="group-components" style="display: none">
-	        <div style="padding: 10px 0 30px 10px; " class="eos-host">
-	        </div>
-
-	        <div style="padding-top: 10px; " class="calc-selector-host">
-	        </div>
-	      </div>
-
-	      <div class="info-fields">
-	        <div><b>Lattice constants</b></div>
-	        <div class="latt-constants"></div>
-	        <div class="volume-field"><b><span info-sys-data="cell-volume">Volume</span></b>:
-	          <span class="volume-value" ></span>
-	        </div>
-	        <!-- <div><b>Pressure</b>: <span class="" ></span>  </div>-->
-	        <div class="density-field"><b>Density</b>:
-	            <div class="stats-fields" >
-	              <span info-sys-data="mass-density">Mass density</span> =
-	              <span class="mass-density-value" ></span>
-	            </div>
-	            <div class="stats-fields" >
-	              <span info-sys-data="atomic-density">Atomic density</span> =
-	              <span class="atomic-density-value" ></span>
-	            </div>
-	        </div>
-
-	        <div class="energy-field"><b><span info-sys-data="energies">Energies</span></b> (code-specific)</div>
-	        <div class="energy-descomp"> </div>
-
-	        <div class="wyckoff-pos-calc-field" >
-	          <b><span info-sys-data="free-wyckoff-parameters">Wyckoff sites</span></b>
-	          (fractional coordinates)
-	          <div class="wyckoff-pos-calc-table"> </div>
-	        </div>
-
-	      </div>
-
-	    </div>
-	    `;
-
-	    this.groupComponents = this.element.querySelector('.group-components');
-
-	    this.calcSelector = new CalcSelectorBar('calc-selector-bar','60%');
-	    this.element.querySelector('.calc-selector-host').
-	      appendChild(this.calcSelector.element);
-
-	    this.lattConstantsField = this.element.querySelector('.latt-constants');
-	    this.volumeField = this.element.querySelector('.volume-field');
-	    this.volumeValue = this.element.querySelector('.volume-value');
-	    this.densityField = this.element.querySelector('.density-field');
-	    this.massDensityValue = this.element.querySelector('.mass-density-value');
-	    this.atomicDensityValue = this.element.querySelector('.atomic-density-value');
-
-	    this.energyField= this.element.querySelector('.energy-field');
-	    this.energyDescompValue= this.element.querySelector('.energy-descomp');
-
-	    this.wyckoffPosField = this.element.querySelector('.wyckoff-pos-calc-field');
-	    this.wyckoffPosTable = this.element.querySelector('.wyckoff-pos-calc-table');
-
-	    this.eosViewer = new EquationOfStateViewer();
-	    this.eosViewer.attach(this.element.querySelector('.eos-host'),320, 280);
-
-	     this.eosViewer.setClickPointListener( calc => {
-	      this.groupCalcUpdate(calc+'');
-	    });
-
-	    InfoSys.addToInfoSystem(this.element);
-
-	    this._events();
-	  }
-
-
-	  _events() {
-
-	    this.calcSelector.setPrevListener(e => {
-	      //console.log('calcSelectorPrevBtn');
-	      if (this.groupIndex > 0){
-	        this.groupCalcUpdate(this.groupCalcs[--this.groupIndex]+'');
-	        return this.groupIndex === 0; // the first
-	      }
-	    });
-
-	    this.calcSelector.setNextListener( e => {
-	      //console.log('calcSelectorNextBtn');
-	      if (this.groupIndex < this.groupCalcs.length-1){
-	        this.groupCalcUpdate(this.groupCalcs[++this.groupIndex]+'');
-	        return this.groupIndex === this.groupCalcs.length-1; // the last
-	      }
-	    });
-
-	  }
-
-
-	  update(leafId, groupData){
-
-	    this.representative = leafId;
-	    this.isGroup = false;
-	    //console.log('SET: ',groupData);
-	    if (groupData !== undefined){
-
-	      this.groupCalcs = Array.from(groupData.calcs);
-	      this.groupIndex = this.groupCalcs.indexOf(
-	        DataStore.getCalcReprIntId(this.representative));
-
-	      this.isGroup = true;
-	      this.groupComponents.style.display = 'block';
-
-	      this.eosViewer.clear();
-	      let pointsX = [], pointsY = [];//, calcIds = [];
-
-	      this.groupCalcs.forEach( calcId => {
-	        //calcIds.push(calcId);
-	        let calc = DataStore.getCalc(calcId);
-	        //console.log('CALC: ', calcId, calc);
-	        pointsX.push(calc.cell_volume/1e-30);
-	        let yVal = 555; // Trick: signal value
-	        calc.energy.forEach( e => {
-	          if (e.e_kind === 'Total E'){
-	            yVal = e.e_val/1.602176565e-19;
-	          }
-	        });
-	        pointsY.push(yVal);
-	      });
-
-	      // Method re
-	      let mReprCalc = DataStore.getCalc(groupData.method_representative);
-	      //console.log('mReprCalc: ', mReprCalc);
-	      let eZero;
-	      mReprCalc.energy.forEach( e => {
-	        if (e.e_kind === 'Total E')
-	          eZero = e.e_val/1.602176565e-19;
-	      });
-	      //console.log('CALC: ', pointsX, pointsY, groupCalcsForChart);
-	      this.eosViewer.draw(pointsX, pointsY, this.groupCalcs, eZero);
-
-	    }else{
-	      this.groupComponents.style.display = 'none';
-	    }
-	    this.groupCalcUpdate(leafId);
-	  }
-
-
-	  groupCalcUpdate(leafId){
-
-	    if (leafId !== null){
-
-	      let calcId = DataStore.getCalcReprIntId(leafId);
-	      if (this.groupCalcs !== null){
-	        this.groupIndex = this.groupCalcs.indexOf(calcId);
-	        if (this.groupIndex >= 0){
-	          let t = calcId+' ('+(this.groupIndex+1)+'/'+this.groupCalcs.length+')';
-	          this.calcSelector.setState(t, this.groupIndex === 0,
-	            this.groupIndex === this.groupCalcs.length-1);
-
-	          this.eosViewer.selectCalc(calcId);
-	        }
-	      }
-
-	      //console.log('LEAF UPDATE', calc.id, this.groupIndex);
-	      let is2Dsystem = (DataStore.getMaterialData().system_type === '2D');
-	      let isBulk = (DataStore.getMaterialData().system_type === 'bulk');
-	      let calc = DataStore.getCalc(calcId);
-	      let lattParams= util.getNumberArray(calc.lattice_parameters);
-
-	      let lattCFieldHTML = ((is2Dsystem  || isBulk) ?
-	        `<div>b = ${util.m2Angstrom(lattParams[1])}</div>` : '');
-	      lattCFieldHTML += (isBulk ?
-	        `<div>c = ${util.m2Angstrom(lattParams[2])}</div>` : '');
-
-	      let lattBetaGammaFieldHTML = ((is2Dsystem  || isBulk) ?
-	          `<div>&alpha; = ${util.rad2degree(lattParams[3])}</div>` : '');
-
-	      lattBetaGammaFieldHTML += (isBulk ?
-	          `<div>&beta; = ${util.rad2degree(lattParams[4])}</div>
-	          <div>&gamma; = ${util.rad2degree(lattParams[5])}</div>` : '');
-
-	      this.lattConstantsField.innerHTML= `
-	        <div style="float: left; ">
-	          <div>a = ${util.m2Angstrom(lattParams[0])}</div>
-	          ${lattCFieldHTML}
-	        </div>
-	        <div style="float: left; padding-left: 40px;">
-	          ${lattBetaGammaFieldHTML}
-	        </div>
-	        <div style="clear: both;padding: 0"></div>
-	      `;
-
-	      this.densityField.style.display = (isBulk ? 'block' : 'none');
-	      this.volumeField.style.display = (isBulk ? 'block' : 'none');
-	      if (isBulk){ // bulk type
-	        this.volumeValue.innerHTML= util.m3ToAngstrom3(calc.cell_volume);
-	      //this.pressureCalcField.textContent= calc.pressure;
-	        this.atomicDensityValue.innerHTML= util.toAngstromMinus3(calc.atomic_density);
-	        this.massDensityValue.innerHTML= calc.mass_density.toFixed(1)+' kg/m<sup>3</sup>';
-	      }
-
-	      let r= util.serverReq(util.getCalcEnergiesURL(DataStore.getMaterialData().id, calc.id), () => {
-	        let value = false;
-	        if (r.status === 200){
-	          let energies= JSON.parse(r.response).results;
-	          for (var i = 0; i < energies.length; i++)
-	            if (energies[i].e_kind === 'Total E'){
-	              value = true;
-	              this.energyDescompValue.innerHTML =
-	                '<div>Total E = &nbsp; '+util.J2eV(energies[i].e_val)+' eV</div>';
-	            }
-	        }
-	        this.energyField.style.display = (value ? 'block' : 'none');
-	        this.energyDescompValue.style.display = (value ? 'block' : 'none');
-	      });
-
-	      let thereIsWyckoffData =
-	        (DataStore.getMaterialData().has_free_wyckoff_parameters
-	          && calc.wyckoff_groups_json.length > 0);
-
-	      this.wyckoffPosField.style.display = (thereIsWyckoffData ? 'block' : 'none');
-
-	      if (thereIsWyckoffData){
-	        let wyckoffMap = new Map(); // Map(element, Array of pairArray[w-pos, coor])
-	        calc.wyckoff_groups_json.forEach( d => {
-	          // Only entries having items in .variables are included
-	          if (  Object.keys(d.variables).length !== 0 ){
-
-	            let varsHtml = '';
-	            //d.variables.forEach( v => { varsHtml += '<p>'+v+'</p>'; } );
-	            for (let v in d.variables) {
-	              varsHtml += ''+v+' = '+d.variables[v].toFixed(2)+'<br>';
-	            }
-
-	            let wyckoffVarsPair = [];
-	            wyckoffVarsPair.push(d.wyckoff_letter);
-	            wyckoffVarsPair.push(varsHtml);
-
-	            if (wyckoffMap.has(d.element)){
-	              wyckoffMap.get(d.element).push(wyckoffVarsPair);
-	            }else {
-	              wyckoffMap.set(d.element, [wyckoffVarsPair]);
-	            }
-	          }
-
-	        });
-	        //console.log('wyckoffMap', wyckoffMap);
-
-	        let wyckoffHTML= '';
-	        wyckoffMap.forEach((posSet, element) => {
-
-	          posSet.sort( (a, b) => {
-	            return (a[0] > b[0] ? 1 : -1);
-	          });
-
-	          let firstPos = true;
-	          wyckoffHTML += '<tr > <td style="width: 30%;">'+element+' </td>';
-	          posSet.forEach( pos => {
-	            if (firstPos){
-	              firstPos = false;
-	              wyckoffHTML += '<td style="width: 30%; ">'+pos[0]+'</td><td style="width: 40%;">'+pos[1]+'</td></tr>';
-	            }else
-	              wyckoffHTML += '<tr><td> </td><td>'+pos[0]+'</td><td>'+pos[1]+'</td></tr>';
-	          });
-	        });
-
-	        this.wyckoffPosTable.innerHTML = '<table id="calc-wyckoff">' + wyckoffHTML+'</table>';
-
-	/*
-	        for (var i = 0; i < data.elements.length; i++) {
-	          let element = util.ELEMENTS[data.elements[i].label-1];
-	          if (wyckoffMap.has(element)){
-	            wyckoffMap.get(element).add(data.elements[i].wyckoff);
-	          }else {
-	            let newSet = new Set();
-	            newSet.add(data.elements[i].wyckoff);
-	            wyckoffMap.set(element, newSet);
-	          }
-	        }
-	        */
-
-	      }
-
-
-	    }else{
-	      console.log('THIS dOESNT BE REACHED');
-	    }
-	  }
-
-	}
-
-
-	class SummaryByFunctionalsComponent{
-
-	  constructor(calcMapByFunctional, hostElement){
-	    this.calcMapByFunctional = calcMapByFunctional;
-	    this.hostElement = hostElement;
-	    this.graphTrigger = null;
-	    this.viewType = 'text';
-	    this.functional = null;
-	    this.hostElement.innerHTML+=`
-	      <div style="float: left" >
-	        <svg xmlns="http://www.w3.org/2000/svg" class="chart-tab"
-	          viewBox="0 0 15 15" width="15" height="15" style="fill: #c7c7c7;">
-	            <rect x="0" y="0"  width="2" height="15" />
-	            <rect   x="3" y="5"  width="1.8" height="7"  />
-	            <rect  x="6" y="3"  width="1.8" height="9"  />
-	            <rect   x="9" y="6"  width="1.8" height="6"  />
-	            <rect  x="12" y="2"  width="1.8" height="10"  />
-	            <rect x="2" y="13"   width="13" height="2" />
-	        </svg>
-	        <svg xmlns="http://www.w3.org/2000/svg" class="text-tab"
-	          viewBox="0 0 15 15" width="15" height="15" style="fill: #777;">
-	            <rect x="0" y="1"   width="15" height="2.5" />
-	            <rect   x="0" y="6"  width="15" height="2.5"  />
-	            <rect  x="0" y="11"  width="15" height="2.5"  />
-	        </svg>
-	      </div>
-
-	      <div class="functional-tabs" style="float: right">
-	      </div>
-
-	      <div style="clear: both;"></div>
-
-	      <div class="content-placeholder" >
-
-	        <div style="display: block" class="text-panel" >
-	          <div><b>Lattice constants</b>:
-	            <div class="stats-fields latt-constants-field" >
-	            </div>
-	          </div>
-	          <div class="volume-field"><b><span info-sys-data="cell-volume">Volume</span></b> (&#197;<sup>3</sup>):
-	            <div class="stats-fields volume-value" > </div>
-	          </div>
-	          <div class="density-field"><b>Density</b> :
-	            <div >
-	              <div class="stats-fields" >
-	                <span info-sys-data="mass-density">Mass density</span> (kg/m<sup>3</sup>) =
-	                <span class="mass-density-value" ></span>
-	              </div>
-	              <div class="stats-fields" >
-	                <span info-sys-data="atomic-density">Atomic density</span> (&#197;<sup>-3</sup>) =
-	                <span class="atomic-density-value" ></span>
-	              </div>
-	            </div>
-	          </div>
-	        </div>
-
-	        <div style="display:none" class="chart-panel" >
-	          <div class="charts-placeholder" > </div>
-	          <div class="charts-selector" >
-
-	          </div>
-	        </div>
-
-	      </div>
-	    `;
-	    this.chartTab = this.hostElement.querySelector('.chart-tab');
-	    this.textTab = this.hostElement.querySelector('.text-tab');
-	    this.functionalTabs = this.hostElement.querySelector('.functional-tabs');
-	    this.chartPanel = this.hostElement.querySelector('.chart-panel');
-	    this.textPanel = this.hostElement.querySelector('.text-panel');
-	    this.lattConstantsField = this.hostElement.querySelector('.latt-constants-field');
-	    this.volumeField = this.hostElement.querySelector('.volume-field');
-	    this.volumeFieldValue = this.hostElement.querySelector('.volume-value');
-	    this.densityField = this.hostElement.querySelector('.density-field');
-	    this.massDensityValue = this.hostElement.querySelector('.mass-density-value');
-	    this.atomicDensityValue = this.hostElement.querySelector('.atomic-density-value');
-
-
-	    this.calcMapByFunctional.forEach( (calcs, functionalName) =>{
-	      this.functionalTabs.innerHTML +=
-	        '<span class="tab" data-tab="'+functionalName+'">'+functionalName+'</span>';
-	    });
-
-
-	    this.statsViewer = new StatsViewer();
-	    let chartsPlaceholder = this.hostElement.querySelector('.charts-placeholder');
-	    this.statsViewer.attach(chartsPlaceholder, 350, 200);
-
-	    this.chartsSelector = this.hostElement.querySelector('.charts-selector');
-
-	    this.build(calcMapByFunctional);
-
-	    this.chartTab.addEventListener( "click", e => {
-	      this.chartTab.style.fill = '#777';
-	      this.viewType = 'chart';
-	      this.textTab.style.fill = '#c7c7c7';
-	      this.chartPanel.style.display = 'block';
-	      this.textPanel.style.display = 'none';
-	    });
-
-	    this.textTab.addEventListener( "click", e => {
-	      this.textTab.style.fill = '#777';
-	      this.viewType = 'text';
-	      this.chartTab.style.fill = '#c7c7c7';
-	      this.textPanel.style.display = 'block';
-	      this.chartPanel.style.display = 'none';
-	    });
-
-	    this.functionalTabs.addEventListener( "click", e => {
-	      if (e.target.className === 'tab'){
-	        this.statsViewer.clear();
-	        this.functionalTabs.querySelector('[data-tab="'+this.functional+'"]')
-	          .className = 'tab';
-	        this.functional = e.target.getAttribute('data-tab');
-	        this.functionalTabs.querySelector('[data-tab="'+this.functional+'"]')
-	          .className = 'tab-selected';
-	        this._setData();
-	      }
-	    });
-
-	    this.chartsSelector.addEventListener( "click", e => {
-	      if (e.target.className.indexOf('quantity') === 0){
-	        this.statsViewer.clear();
-	        let quantity = e.target.getAttribute('data-quantity');
-	        let stats = this.functionalQuantityMap.get(this.functional).get(quantity);
-	        this.statsViewer.drawPoints(stats.data, stats.label, stats.min, stats.max);
-
-	        this.chartsSelector.querySelector('.quantity-selected').className = 'quantity';
-	        e.target.className = 'quantity-selected';
-	      }
-	    });
-
-	  }
-
-	  _setData(){
-	    let is2Dsystem = (DataStore.getMaterialData().system_type === '2D');
-	    let isBulk = (DataStore.getMaterialData().system_type === 'bulk');
-	    let statsMap = this.functionalQuantityMap.get(this.functional);
-
-	    let lattCFieldHTML = ((is2Dsystem || isBulk) ?
-	      `<div>b (&#197;) = ${statsMap.get('lattice_b').html}</div>` : '');
-
-	    lattCFieldHTML += (isBulk ?
-	      `<div>c (&#197;) = ${statsMap.get('lattice_c').html}</div>` : '');
-	    // Set text data
-	    this.lattConstantsField.innerHTML = `
-	      <div style="float: left; ">
-	        <div>a (&#197;) = ${statsMap.get('lattice_a').html}</div>
-	        ${lattCFieldHTML}
-	      </div>
-	      <div style="float: left; padding-left: 40px;">
-	        ${util.getLatticeAnglesValues(
-	          this.calcMapByFunctional.get(this.functional), is2Dsystem, isBulk)}
-	      </div>
-	      <div style="clear: both;padding: 0"></div>
-	      `;
-
-	    let chartSelectorHTML= `
-	    <span class="quantity-selected" data-quantity="lattice_a">a</span>
-	    `;
-
-	    if (is2Dsystem || isBulk)
-	      chartSelectorHTML += `<span class="quantity" data-quantity="lattice_b">b</span>`;
-
-	      //console.log('statsMap', statsMap, statsMap.get('volume'));
-	    this.densityField.style.display = (isBulk ? 'block' : 'none');
-	    this.volumeField.style.display = (isBulk ? 'block' : 'none');
-	    if (isBulk){ // bulk type
-	      this.volumeFieldValue.innerHTML = statsMap.get('volume').html;
-	      this.massDensityValue.innerHTML = statsMap.get('mass_density').html;
-	      this.atomicDensityValue.innerHTML = statsMap.get('atomic_density').html;
-	      chartSelectorHTML += `
-	        <span class="quantity" data-quantity="lattice_c">c</span>
-	        <span class="quantity" data-quantity="volume">volume</span>
-	        <span class="quantity" data-quantity="mass_density">mass density</span>
-	        <span class="quantity" data-quantity="atomic_density">atomic density</span>
-	      `;
-	    }
-
-	    this.chartsSelector.innerHTML = chartSelectorHTML;
-
-	    // Set Charts data
-	    let stats = statsMap.get('lattice_a');
-	    this.statsViewer.drawPoints(stats.data, stats.label, stats.min, stats.max);
-	  }
-
-
-
-	  build(calcMapByFunctional){
-	    this.calcMapByFunctional = calcMapByFunctional;
-	    this.graphTrigger = null;
-	    this.statsViewer.clear();
-	    //this.functional = null;
-	    //this.functionalTabs.innerHTML = '';
-	    this.unfoldedElement = null;
-	    this.functionalQuantityMap = new Map();
-
-	    // Hide and deselect all the tabs before knowing the active ones
-	    for (var i = 0; i < this.functionalTabs.children.length; i++) {
-	      //console.log('functionalTabs',this.functionalTabs.children[i]);
-	      this.functionalTabs.children[i].style.display = 'none';
-	      this.functionalTabs.children[i].className = 'tab';
-	    }
-
-	    // For each active functional
-	    this.calcMapByFunctional.forEach( (calcs, functionalName) =>{
-	      let statsMap = util.getQuantityStatsMap(calcs);
-	      this.functionalQuantityMap.set(functionalName, statsMap);
-	      //show the active ones
-	      this.functionalTabs.querySelector('[data-tab="'+functionalName+'"]')
-	          .style.display = 'inline';
-	    });
-
-	    // Select the selected functional
-	    let functionals = Array.from( this.calcMapByFunctional.keys() );
-	    // If there isn't selected functional or the current functional is not active
-	    if (this.functional === null || functionals.indexOf(this.functional) < 0)
-	      this.functional = functionals[0]; // the first one is selected
-	    this._setData();
-	    this.functionalTabs.querySelector('[data-tab="'+this.functional+'"]')
-	      .className = 'tab-selected';
-
-	    InfoSys.addToInfoSystem(this.hostElement);
-	  }
-
-	}
-
-
-	// EXPORTS
-	module.exports = StructureDetails;
-
-
-/***/ },
-/* 20 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-	 /*
-	  Base class from which other main 'Details' view containers inherit.
-	  Every of these containers shows all the material info related to a type of info:
-	  Structure, Electronic Structure, etc
-	 */
-
-	"use strict";
-
-	let util = __webpack_require__(1);
-	let DataStore = __webpack_require__(2);
-
-
-	class DetailsViewBase {
-
-	  constructor(domId) {
-	    this.element = document.createElement('div');
-	    this.element.setAttribute('id',domId);
-	    this.gotoResultsListener= null;
-	    this.gotoOverviewListener= null;
-	    this.element.innerHTML= '<div class="material-title"></div>';
-	    this.element.style.display= 'none';
-	  }
-
-
-	  attachAndSetEvents(element){
-	    element.appendChild(this.element);
-	    this.materialTitle= this.element.querySelector('.material-title');
-	  }
-
-
-	  attachNavTree(navTree){
-	    navTree.attach(this.navTreeWrapper);
-	  }
-
-
-	  setVisible(){
-	    this.element.style.display= 'block';
-	  }
-
-
-	  setMaterialData() {
-	    this.materialTitle.innerHTML= util.getMaterialTitle(DataStore.getMaterialData());
-	  }
-
-
-	  updateCalcs(calcs){
-	  }
-
-
-	  updateMarkedCalc(calc){
-	  }
-
-	}
-
-	// EXPORTS
-	module.exports = DetailsViewBase;
-
-
-/***/ },
-/* 21 */
-/***/ function(module, exports) {
-
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-	  This class implements the bar to select calculations on a material
-	 */
-
-
-	class CalcSelectorBar{
-
-	  constructor(className, width){
-	    this.first = true;
-	    this.last = false;
-	    this.element = document.createElement('div');
-	    this.element.className = className;
-	    if (width !== undefined) this.element.style.width = width;
-	    this.element.innerHTML = `
-	      <div class="prev-sel-btn" style="float: left; width: 20%;">
-	        <div style="padding-left: 10%;">
-	          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10.069 11.872" width="20px">
-	            <path transform="scale(0.7) translate(-346.291 -664.481)"
-	              d="M356.36,666.024l-1.544-1.544-8.525,8.513,8.493,8.447,1.544-1.544-6.8-6.9Z" />
-	          </svg>
-	        </div>
-	      </div>
-	      <div class="calc-sel-text" style="float: left; width: 60%;">
-	       NOT Calculation
-	      </div>
-	      <div class="next-sel-btn" style="float: right; width: 20%;">
-	        <div style="padding-right: 10%;">
-	          <svg xmlns="http://www.w3.org/2000/svg" viewBox="-10.069 -11.872 10.069 11.872" width="20px">
-	            <g transform="rotate(180) scale(0.7)">
-	              <path d="M10.069,1.544,8.525,0,0,8.513,8.493,16.96l1.544-1.544-6.8-6.9Z"/>
-	            </g>
-	          </svg>
-	        </div>
-	      </div>
-	      <div style="clear: both;"></div>
-	    `;
-
-	    this.prevBtn = this.element.querySelector('.prev-sel-btn');
-	    this.prevIcon = this.element.querySelector('.prev-sel-btn path');
-	    this.calcSelectorTxt = this.element.querySelector('.calc-sel-text');
-	    this.nextBtn = this.element.querySelector('.next-sel-btn');
-	    this.nextIcon = this.element.querySelector('.next-sel-btn path');
-	    this._styleButtons();
-	    this._events();
-	  }
-
-
-	  _events() {
-	    this.prevBtn.addEventListener( "click", e => {
-	      e.preventDefault();
-	      if (this.first) return;
-	      /*** repensar esto es problematico porque necesita poder ser configurado desde fuera **/
-	      //if (this.last)  this.last = false;
-	      this.first = this.prevListener();
-	      this.last = false;
-	      this._styleButtons();
-	    });
-
-	    this.nextBtn.addEventListener( "click", e => {
-	      e.preventDefault();
-	      if (this.last) return;
-	      //if (this.first)  this.first = false;
-	    //  this.last = this.nextListener();
-	      this.first = false;
-	      this.last = this.nextListener();
-	      this._styleButtons();
-	    });
-	  }
-
-
-	  _styleButtons(){
-	    this.prevIcon.setAttribute("class",
-	      'calc-selector-icon'+(this.first ? '-disabled' : ''));
-	    this.nextIcon.setAttribute("class",
-	      'calc-selector-icon'+(this.last ? '-disabled' : ''));
-	  }
-
-
-	  setPrevListener(listener){
-	    this.prevListener = listener;
-	  }
-
-
-	  setNextListener(listener){
-	    this.nextListener = listener;
-	  }
-
-
-	  setState(text, first, last){
-	    this.calcSelectorTxt.innerHTML = text;
-	    this.first = first;
-	    this.last = last;
-	    this._styleButtons();
-	  }
-
-	}
-
-
-	// EXPORTS
-	module.exports = CalcSelectorBar;
-
-
-/***/ },
-/* 22 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-	 /*
-	  The StatsViewer class implements a graphical UI component composed of
-	  a points plotter and a frecuency graph.
-	  (classes defined in this file MainGraph and FrequencyGraph)
-	 */
-
-
-	"use strict";
-
-	let svg = __webpack_require__(9);
-	let PlotterBase = __webpack_require__(18);
-
-
-	class MainGraph extends PlotterBase{
-
-	  constructor() {
-	    super({left: 54, right: 20, top: 20, bottom: 30});
-	    this.tooltip;
-	  }
-
-
-	  drawPoints(points){
-	    for (let i = 0; i < points.length; i++) {
-	      //console.log('drawPoint '+this.xRel, i, this.yRel, points[i]);
-		    let pointElement = svg.addPoint(this.plotArea,
-	        this.xRel*i, -this.yRel*(points[i] - this.yMin), 2, 'stats-viewer-point');
-
-		    pointElement.addEventListener('mouseover', (e) => {
-			    this.tooltip = svg.addText(this.plotArea, e.target.getBBox().x+6,
-	          e.target.getBBox().y-4, (points[i]).toFixed(2), 'start', 'tooltip');
-	        /*getBBox() Rect data (x, y, w, h) of the element were the event happendd,
-	          coordenate system: the parent element coordinate system */
-	      });
-		    pointElement.addEventListener('mouseout', (e) => {
-			    svg.removeElement(this.tooltip);
-		    });
-		  }
-	  }
-
-	}
-
-
-	class FrequencyGraph extends PlotterBase{
-
-	  constructor() {
-	    super({left: 4, right: 10, top: 20, bottom: 30});
-	  }
-
-	  drawBars(points, yMin, yRange){
-		  let ranges = [0,0,0,0,0,0,0,0,0,0];
-		  points.forEach(point => {
-		    let rangeIndex = Math.floor(((point-yMin)/yRange)*10);
-	      if (rangeIndex > 9) rangeIndex = 9;
-		    ranges[rangeIndex] += 1;
-		  });
-		  ranges.forEach((value, index) => {
-		    let yBar= (index + 0.5)*this.yRel;
-		    svg.addLine(this.plotArea, 0, -yBar, value*this.xRel, -yBar, 'bar');
-		  });
-	  }
-	}
-
-
-	class StatsViewer{
-
-	  constructor() {
-	    this.mainGraph = new MainGraph();
-	    this.freqGraph = new FrequencyGraph();
-	  }
-
-
-	  attach(element, width, height){
-	    this.mainGraph.attach(element, width/2 + 24, height);
-		  this.freqGraph.attach(element, width/2 - 24, height);
-	  }
-
-
-	  drawPoints(points, label, min, max){
-	    let defMin = min, defMax = max;
-	    if (max === min){  defMin = min-1;  defMax = max+1;  }
-
-	    this.mainGraph.setRangeAndLabels('Calculation', 0, points.length, label,
-	      defMin, defMax);
-		  this.mainGraph.drawAxis(null,(max === min ? 2: 4),(min > 1000 ? 0 : 2));
-	    this.mainGraph.drawPoints(points);
-
-	    let freqRange= (points.length < 10 ? 10 : Math.floor(points.length/10)*10);
-	    this.freqGraph.setRangeAndLabels('Occurrence', 0, freqRange, '', 0, 10);
-		  this.freqGraph.drawAxis(2, 1, 1);
-	    this.freqGraph.drawBars(points, this.mainGraph.yMin,
-	      this.mainGraph.yMax - this.mainGraph.yMin);
-	  }
+class StatsViewer{
 
+  constructor() {
+    this.mainGraph = new MainGraph();
+    this.freqGraph = new FrequencyGraph();
+  }
 
-	  clear(){
-	    this.mainGraph.clear();
-	    this.freqGraph.clear();
-	  }
 
-	}
+  attach(element, width, height){
+    this.mainGraph.attach(element, width/2 + 24, height);
+	  this.freqGraph.attach(element, width/2 - 24, height);
+  }
 
 
-	// EXPORTS
-	module.exports = StatsViewer;
+  drawPoints(points, label, min, max){
+    let defMin = min, defMax = max;
+    if (max === min){  defMin = min-1;  defMax = max+1;  }
 
+    this.mainGraph.setRangeAndLabels('Calculation', 0, points.length, label,
+      defMin, defMax);
+	  this.mainGraph.drawAxis(null,(max === min ? 2: 4),(min > 1000 ? 0 : 2));
+    this.mainGraph.drawPoints(points);
 
-/***/ },
-/* 23 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-	  Equation of State plotter implementation
-	 */
-
-	"use strict";
-
-	let svg = __webpack_require__(9);
-	let PlotterBase = __webpack_require__(18);
-
-
-	class EquationOfStateViewer extends PlotterBase{
-
-	  constructor() {
-	    super({left: 60, right: 20, top: 30, bottom: 40});
-	    this.tooltip;
-	    this.calcPointMap= new Map();
-	    this.pointSelected = null;
-	  }
+    let freqRange= (points.length < 10 ? 10 : Math.floor(points.length/10)*10);
+    this.freqGraph.setRangeAndLabels('Occurrence', 0, freqRange, '', 0, 10);
+	  this.freqGraph.drawAxis(2, 1, 1);
+    this.freqGraph.drawBars(points, this.mainGraph.yMin,
+      this.mainGraph.yMax - this.mainGraph.yMin);
+  }
 
 
-	  draw(pointsX, pointsY, calcIds, eZero){
-
-	    for (let i = 0; i < pointsY.length; i++) {
-	      if (pointsY[i] !== 555) pointsY[i] -= eZero;
-	    }
-
-	    function remove555(points){
-	      let goodPoints = [];
-	      points.forEach( p => {
-	        if (p !== 555) goodPoints.push(p);
-	      });
-	      return goodPoints;
-	    }
-	    let goodPointsY = remove555(pointsY);
-
-	    let xMin = Math.min.apply(null,pointsX);
-	    let xMax = Math.max.apply(null,pointsX);
-	    let yMin = 0;
-	    let yMax = Math.max.apply(null,goodPointsY);
-
-	    if (xMin === xMax) { xMin -= 1; xMax += 1; }
-	    else{
-	      let gap = xMax - xMin;
-	      xMin -= gap*0.1; xMax += gap*0.1;
-	    }
-	    if (yMin === yMax) { yMin -= 1; yMax += 1; }
-	    else{
-	      let gap = yMax - yMin;
-	      yMin -= gap*0.15; yMax += gap*0.1;
-	    }
-
-	    this.setRangeAndLabels('Volume (ų)', xMin, xMax,'E - Eₘᵢₙ (eV)', yMin, yMax);
-	    this.drawAxis(2, null);
-	    // Y axis labels drawing
-	    let self = this;
-	    function drawYAxisLabel(element, y){
-	      let pixelY = self.y(y);
-	      svg.addLine(element, 0, pixelY, -3, pixelY, 1);
-	      let numberToPaint= -(pixelY/self.yRel) + self.yMin;
-	      svg.addText(element,-5, pixelY+3, numberToPaint.toFixed(3), 'end', 'statisticsviewersteps');
-	    }
-	    drawYAxisLabel(this.plotArea, 0);
-	    drawYAxisLabel(this.plotArea, yMax/2);
-	    drawYAxisLabel(this.plotArea, yMax);
-
-	    // zero line drawing
-	    svg.addLine(this.plotArea, 0, this.y(0), this.plotRangeX, this.y(0), 'zeroline');
-
-	    svg.addText(this.plotArea, this.x(xMax),
-	      this.y(0)+12, 'Eₘᵢₙ: '+eZero.toFixed(3)+' eV', 'end', 'axis-steps');
-	    // points drawing
-	    for (let i = 0; i < pointsX.length; i++) {
-
-	      let styleClass = (i === 0 ? 'eos-viewer-sel' : 'eos-viewer');
-	      let r = (i === 0 ? 6 : 3);
-	      let yVal = (pointsY[i] === 555 ? 20 : this.y(pointsY[i])); // Trick
-		    let pointElement =
-	        svg.addPoint(this.plotArea,this.x(pointsX[i]), yVal, r
-	        , styleClass);
-	      if (i === 0) this.pointSelected = pointElement;
-
-		    pointElement.addEventListener('mouseover', e => {
-			    this.tooltip = svg.addText(this.plotArea, e.target.getBBox().x+10,
-	          e.target.getBBox().y-10, 'Calc '+calcIds[i], 'middle', 'tooltip');
-	      });
-		    pointElement.addEventListener('mouseout', e => {
-			    svg.removeElement(this.tooltip);
-		    });
-	      pointElement.addEventListener('click', e => {
-			    //console.log('ID',calcIds[i]);
-	        this.clickPointListener(calcIds[i]);
-		    });
-	      this.calcPointMap.set(calcIds[i], pointElement);
-		  }
-	  }
+  clear(){
+    this.mainGraph.clear();
+    this.freqGraph.clear();
+  }
 
+}
 
-	  selectCalc(calcId){
-	    this.pointSelected.setAttribute('class', 'eos-viewer');
-	    this.pointSelected.setAttribute('r', 3);
-	    this.pointSelected = this.calcPointMap.get(calcId);
-	    this.pointSelected.setAttribute('class', 'eos-viewer-sel');
-	    this.pointSelected.setAttribute('r', 6);
-	  }
 
+// EXPORTS
+module.exports = StatsViewer;
 
-	  setClickPointListener(listener){
-	    this.clickPointListener = listener;
-	  }
 
+/***/ }),
+/* 15 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+ /*
+    This file implements the user guidance system. This complex system for
+    showing tips to the user is specified in the project documentation 
+ */
+
+
+
+
+//let util = require('util.js');
+
+let body = document.querySelector('body');
+let tips = [];
+let tipData = [];
+let currentTip;// = 1;
+let independentTips = []; // if null => showing else if 'off' not showing
+let addBox, table, searchBox, propertiesTabs;
+let searchBarShowing = false;
+
+
+function createUserMsg(i, width){
+  let element= document.createElement('div');
+  element.setAttribute('class','user-guidance');
+  element.innerHTML = '<img src="img/tip'+i+'.png" width="'+width+'px" />';
+  element.style.position = 'absolute';
+  element.style.display = 'none';
+  body.appendChild(element);
+  return element;
+}
+
+
+function showTip(tipNumber){
+  if (tipNumber === 8 && !searchBarShowing) return; // Do nothing
+  if (tipNumber === 4 && !searchBarShowing) return; // Do nothing
+
+  let r = tipData[tipNumber].domTarget.getBoundingClientRect();
+//console.log("GGGGGGGGG: ",r);
+  tips[tipNumber].style.top = (r.top + tipData[tipNumber].top + window.pageYOffset)+'px';
+  tips[tipNumber].style.left = (r.left + tipData[tipNumber].left)+'px';
+  tips[tipNumber].style.display = 'block';
+}
+
+// Init per user session
+function init(addBoxP, tableP, searchBoxP, propertiesTabsP){
+  addBox = addBoxP;
+  table = tableP;
+  searchBox = searchBoxP;
+  propertiesTabs = propertiesTabsP;
+
+  independentTips[3] = localStorage.getItem('tip3');
+  independentTips[4] = localStorage.getItem('tip4');
+  independentTips[7] = localStorage.getItem('tip7');
+
+  createUserTips();
+  let currentTip = localStorage.getItem('currentTip');
+  if (currentTip === null){ // First time
+    updateCurrentTip(1);
+  }else{
+    currentTip = parseInt(currentTip);
+    if (currentTip < 10){ // regular case
+      updateCurrentTip(currentTip);
+    }//else {  currentTip === 10 the guidance has finished
+  }
+}
+
+
+function createUserTips(){
+
+  if (tips.length === 0){
+    tips[1] = createUserMsg(1, 220);
+    tipData[1] = {domTarget: addBox, top: -70, left: -240 };
+    tips[2] = createUserMsg(2, 280);
+    tipData[2] = {domTarget: addBox, top: -110, left: 80 };
+    tips[3] = createUserMsg(3, 180);
+    tipData[3] = {domTarget: table, top: 180, left: 720 };
+    tips[4] = createUserMsg(4, 240);
+    tipData[4] = {domTarget: searchBox, top: 45, left: -250 };
+    tips[5] = createUserMsg(5, 210);
+    tipData[5] = {domTarget: addBox, top: -130, left: 70};
+    tips[6] = createUserMsg(6, 240);
+    tipData[6] = {domTarget: addBox, top: -100, left: 370};
+    tips[7] = createUserMsg(7, 220);
+    tipData[7] = {domTarget: propertiesTabs, top: 160, left: -40};
+    tips[8] = createUserMsg(8, 240);
+    tipData[8] = {domTarget: searchBox, top: 30, left: 760};
+
+    // Event
+    tips[1].addEventListener( "click", closeAndShowNext);
+    tips[2].addEventListener( "click", closeAndShowNext);
+    tips[3].addEventListener( "click", e => { closeIndependentTip(3) });
+    tips[4].addEventListener( "click", e => { closeIndependentTip(4) });
+    tips[5].addEventListener( "click", closeAndShowNext);
+    tips[6].addEventListener( "click", closeAndShowNext);
+    tips[7].addEventListener( "click",  e => { closeIndependentTip(7) });
+    tips[8].addEventListener( "click", e => {
+      e.target.style.display = 'none';
+      updateCurrentTip(10);
+    });
+  }
+}
+
+
+function setFinal(){
+  searchBarShowing = true;
+  if (currentTip < 10){
+    tips[currentTip].style.display = 'none';
+    updateCurrentTip(8);//currentTip = 4;
+    showTip(currentTip);
+  }
+  showIndependentTip(4, true);
+}
+
+
+function closeIndependentTip( tipNumber){
+  //e.preventDefault();
+  tips[tipNumber].style.display = 'none';
+  localStorage.setItem('tip'+tipNumber, 'off');
+  independentTips[tipNumber] = 'off';
+}
+
+
+function closeAndShowNext(e){
+  e.preventDefault();
+  //console.log("closeAndShowNext",currentTip);
+  e.target.style.display = 'none';
+
+  switch (currentTip) {
+    case 2:  currentTip = 5;  break;
+
+    case 6:  currentTip = 8;  break;
+
+    default: // 1 , 5
+      currentTip++;
+  }
+  updateCurrentTip(currentTip);
+  showTip(currentTip);
+}
+
+
+function showIndependentTip(tipNumber, value){
+  //console.log("showIndependentTip",tipNumber);
+  if (independentTips[tipNumber] === null){ // Tip has not been removed (clicked)
+    if (value) showTip(tipNumber);
+    else tips[tipNumber].style.display = 'none';
+  }
+}
+
+
+
+
+function show(value, tip3, tip7){ // Global show - the UserGuidance is shown or hidden at all
+  if (currentTip < 10){ // sequential tips
+    if (value) showTip(currentTip);
+    else tips[currentTip].style.display = 'none';
+  }
+  // Independent tips
+  showIndependentTip(3, value && tip3);
+  showIndependentTip(4, value);
+  showIndependentTip(7, value && tip7);
+}
+
+
+function updateCurrentTip(value){
+  currentTip = value;
+  localStorage.setItem('currentTip', value);
+  //console.log('localStorage.currentTip:',localStorage.getItem('currentTip'));
+}
+
+
+
+
+// EXPORTS
+module.exports = {init, setFinal, show, showIndependentTip}
+
+
+/***/ }),
+/* 16 */
+/***/ (function(module, exports, __webpack_require__) {
 
-	  x(x){
-	    return this.xRel*(x - this.xMin);
-	  }
+"use strict";
+
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
 
 
-	  y(y){
-	    return -this.yRel*(y - this.yMin);
-	  }
+ /*
+   This file is the application entry point.
+   It defines some app level components (Breadcrumb) and
+   initializes several more (app level events, app routing, authentication)
+ */
+
+
+
+
+let util = __webpack_require__(0);
+let LoadingPopup = __webpack_require__(4);
+let FlaggingFormPopup = __webpack_require__(18);
+let PubSub = __webpack_require__(19);
+let Router = __webpack_require__(20);
+let MaterialMod = __webpack_require__(9);
+let SearchModule = __webpack_require__(33);
+let UserGuidance = __webpack_require__(15);
+let DataStore = __webpack_require__(1);
+
+
+// main DOM elements
+let contentElement = document.getElementById('content');
+let titleElement = document.querySelector('title');
+
+
+/********* User flagging side tab ****************/
+
+/* This side vertical tab is hidden initially
+   but it has to be set up when the app starts */
+
+let flaggingTab = document.getElementById('calc-flagging-tab');
+flaggingTab.style.top = (window.innerHeight/2)+'px';
+
+flaggingTab.addEventListener('click',e => {
+  FlaggingFormPopup.show(MaterialModule.getCurrentPageStatus());
+});
+
 
-	}
 
+/*********** App Breadcrumb component definition ***************/
 
+class Breadcrumb {
+
+  constructor() {
 
-	// EXPORTS
-	module.exports = EquationOfStateViewer;
+    this.element = document.querySelector('#breadcrumb-placeholder');
+    this.element.innerHTML = `
+      <span class="goto-page Search">Search</span>
+      <span class="goto-page Overview">&nbsp; > &nbsp; <span>Overview</span></span>
+      <span class="Details">
+        &nbsp; > &nbsp;
+        <select class="details-dropdown" >
+          <option value="structure">Structure</option>
+          <option value="electronicstruct">Electronic structure</option>
+          <option value="methodology">Methodology</option>
+          <option value="thermalprops">Thermal Properties</option>
+          <!-- elasticconst-->
+        </select>
+      </span>
+    `;
+    this.overviewSel = this.element.querySelector('.Overview');
+    this.detailsSel = this.element.querySelector('.Details');
+    this.detailsDropDown = this.element.querySelector('.details-dropdown');
 
+    // Events
+    this.element.querySelector('.Search').addEventListener( "click", e => {
+      util.setBrowserHashPath('search');
+    });
 
-/***/ },
-/* 24 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-	 /*
-	  'Details' view container that shows all the material info related to
-	  its electronic structure.
-
-	  This container is quite complex.
-
-	  In the file there are two defined (classes) components used in the container:
-	  - SummaryByFunctionalsComponent: the component (left panel, below part)
-	  showing a band gap summary info by functional.
-	  - BZViewerWrapper: This component is a wrapper for the Brillouin zone viewer
-	 */
-
-	"use strict";
-
-	let DetailsViewBase = __webpack_require__(20);
-	let util = __webpack_require__(1);
-	let InfoSys = __webpack_require__(12);
-	let CalcSelectorBar = __webpack_require__(21);
-	let StatsViewer = __webpack_require__(22);
-	let BSDOSPlotter = __webpack_require__(25);
-	let PlotterBase = __webpack_require__(18);
-	let plotter= new PlotterBase();
-	let DataStore = __webpack_require__(2);
-	let LoadingPopup = __webpack_require__(4);
-
-	function setFermiVizContent(fermiBox,url){
-	  let sceneContent;
-	  if (url === ''){
-	    fermiBox.innerHTML= '';//fermiBox.removeChild(plotter.canvas);
-	    plotter.attach(fermiBox,undefined,316);
-	    plotter.setNoData();
-	  }
-	  else{
-	    sceneContent= '<inline url="'+url+'"> </inline>';
-	    fermiBox.innerHTML=
-	      `<x3d id="x3dframe" width='290px' height='290px' >
-	        <scene>${sceneContent} </scene>
-	      </x3d>`;
-	    x3dom.reload();
-	  }
+    this.overviewSel.addEventListener('click', () => {
+      util.setBrowserHashPath('material', util.materialId);
+    });
 
-	}
+    this.detailsDropDown.addEventListener('change', e => {
+      util.setBrowserHashPath('material',
+        DataStore.getMaterialData().id+'/'+e.target.value);
+    });
 
-	class ElectronicStructDetails  extends DetailsViewBase{
+    let self = this;
+    function adjustDropdownOptions() {
+      let esOption = self.detailsDropDown.querySelector('option[value="electronicstruct"]');
+      if (!DataStore.hasElecStructureData) self.detailsDropDown.removeChild(esOption);
 
-	  constructor() {
-	    super('Electronic Structure');
-	    this.firstId;
-	    this.lastId;
-	    this.element.innerHTML+=`
-	      <div style="float: left; width: 30%;">
-	        <div class="view-box">
-	          <div class="title">Calculations </div>
-	          <div class="navTreeWrapper"></div>
+      let thOption = self.detailsDropDown.querySelector('option[value="thermalprops"]');
+      if (!DataStore.hasThermalData) self.detailsDropDown.removeChild(thOption);
+      // Remove because we want it's executed once
+      self.detailsDropDown.removeEventListener('focus', adjustDropdownOptions);
+    }
 
+    this.detailsDropDown.addEventListener('focus', adjustDropdownOptions);
+  }
 
-	          <div class="summary-title">Summary</div>
-	          <div class="footer summary-box" style="border-top: 0">
-	          </div>
-	        </div>
-	      </div>
 
-	      <div style="float: right; width: 70%;">
-	        <div class="view-box e-structure-box">
+  setState(appModule, param){
+    let overviewSelLabel = this.overviewSel.querySelector('span');
+    overviewSelLabel.style.fontWeight = 'normal';
 
-	          <div class="title">Electronic structure</div>
+    if (appModule === 'search'){
+      this.overviewSel.style.display = 'none';
+      this.detailsSel.style.display = 'none';
 
-	          <div style="padding-top: 10px;">
-	            <div class="calc-selector-host"></div>
-	          </div>
+      /*
+      if (param === 'results'){
+        this.resultsSel.style.display = 'inline';
+        this.resultsSel.querySelector('span').style.fontWeight = 'bold';
+        this.element.style.visibility = 'visible';
+      }else   this.element.style.visibility = 'hidden';
+      */
+      this.element.style.visibility = 'hidden';
 
+    }else if (appModule === 'material'){
+      this.element.style.visibility = 'visible';
+      this.overviewSel.style.display = 'inline';
 
-	          <div>
+      if (param === undefined){ // Overview page
+        this.detailsSel.style.display = 'none';
+        overviewSelLabel.style.fontWeight = 'bold';
+      }else{ // Details page
+        this.detailsSel.style.display = 'inline';
+        this.detailsDropDown.value = param;
+      }
+    }
+  } // setState
 
-	            <div  style="padding: 30px  100px 20px 100px; ">
-	              <div class="info-fields-label" style="float: left; width: 54%; ">
-	                <span info-sys-data="band-structure">Band structure</span>
-	              </div>
-	              <div class="info-fields-label" style="float: left;">
-	                <span info-sys-data="DOS">DOS</span>
-	              </div>
-	              <div style="clear: both;"></div>
+} // class Breadcrumb
 
-	              <div class="calc-bs-dos-plotter" >
-	              </div>
 
-	              <div>
-	              <div class="band-gap-field" style="float: left; width: 56%; text-align: right">
-	                <b><span info-sys-data="band-gap">Band gap</span></b>:
-	                <span class="band-gap-value" ></span>
-	              </div>
-	              <div style="clear: both;"></div>
+/***************************
+         App setup
+***************************/
 
-	              </div>
-	            </div>
+let breadcrumb = new Breadcrumb();
 
-	            <div class="spin-legend" style="font-size: 0.9em; padding: 0 30px 10px; display: none">
-	              <svg width="15px" height="10px"> <polyline points="0,5 15,5" class="plotSpin1"/></svg>
-	              Spin <span style='font-size: 1.1em'>⇧</span>  &nbsp;&nbsp;&nbsp;
-	              <svg width="15px" height="10px"> <polyline points="0,5 15,5" class="plotSpin2"/></svg>
-	              Spin <span style='font-size: 1.1em'>⇩</span>
-	            </div>
+let searchMod;
+let MaterialModule;
+let materialModDOM;
+let currentModule; // current module DOM being shown
 
-	          </div>
 
-	          <div class="footer lower-section">
+function showModuleDOM(module){
+  if (currentModule) contentElement.removeChild(currentModule);
+  currentModule= module;
+  contentElement.appendChild(currentModule);
+}
 
-	            <div  style="float: left">
-	              <div style="padding: 16px; ">
-	                <div class="info-fields-label" >
-	                  <span info-sys-data="brillouin-zone-viewer">Brillouin zone</span>
-	                </div>
-	                <div class="bz-viewer-wrapper" style="width: 400px; height: 400px">
-	                </div>
-	              </div>
-	            </div>
 
-	            <div class="band" style="float: right; width: 40%;">
-	              <div style="padding: 16px; ">
-	                <div class="info-fields-label" >
-	                  <!-- <span info-sys-data="fermi-surface">Fermi surface </span> -->
-	                </div>
-	                <div class="fermi-box" >      </div>
-	              </div>
-	            </div>
+/******  App level events setup ********/
 
-	            <div style="clear: both;"></div>
+PubSub.subscribe('show-material', data => {
+  console.log('Handling event show-material: '+data.id+' view: '+data.view);
 
-	          </div> <!-- footer -->
+  //titleElement.innerHTML = 'NOMAD Encyclopedia - Material '+data.id;
+  breadcrumb.setState('material',data.view);
 
-	        </div>
+  if (typeof materialModDOM === 'undefined'){
+    MaterialModule = new MaterialMod();
+    materialModDOM= MaterialModule.element;
+  }
+  MaterialModule.setMaterialView(data);
+  showModuleDOM(materialModDOM);
 
-	      </div> <!-- view-box -->
-	    `;
+  // In case the app comes from the search module through the url (back button)
+  UserGuidance.show(false);
 
-	    this.navTreeWrapper =
-	        this.element.getElementsByClassName("navTreeWrapper")[0];
+  //console.log('User data:',util.getUserData());
+  if (util.getUserData() !== null) flaggingTab.style.visibility = 'visible';
+});
 
-	    //this.leafTitle = this.element.querySelector('.tree-leaf-title');
-	    this.calcSelector = new CalcSelectorBar('calc-selector-bar','70%');
-	    this.element.querySelector('.calc-selector-host').
-	      appendChild(this.calcSelector.element);
 
-	    this.rightBox = this.element.querySelector('.e-structure-box');
+PubSub.subscribe('show-search', search => {
+  console.log('Handling event show-search: '+search);
 
-	    this.summaryByFunctionals = null;
+  titleElement.innerHTML = 'NOMAD Encyclopedia - Search';
+  breadcrumb.setState('search',search);
 
-	    this.bsDosPlotter = new BSDOSPlotter();
+  if (search === undefined){
+    searchMod.showSearchPage();
+    LoadingPopup.hide();  // In case it comes from the result page
 
-	    this.bandGapField = this.element.querySelector('.band-gap-field');
-	    this.bandGapValue = this.element.querySelector('.band-gap-value');
+  }//else if (search === 'results')  searchMod.showSearchResults();
 
-	    this.spinLegend = this.element.querySelector('.spin-legend');
+  showModuleDOM(searchMod.element);
 
-	    this.lowerSection = this.element.querySelector('.lower-section');
+  if (flaggingTab.style.visibility !== 'hidden')
+    flaggingTab.style.visibility = 'hidden';
+});
 
-	    this.fermiBox= this.element.getElementsByClassName('fermi-box')[0];
-	    // Load the x3dom library
-	    util.loadLib("lib/x3dom.js");
 
-	    this.bzViewerWrapper = this.element.querySelector('.bz-viewer-wrapper');
-	    this.bzViewerWrapper = new BZViewerWrapper(this.bzViewerWrapper);
 
-	    // For static ones
-	    InfoSys.addToInfoSystem(this.element);
+/******  App routing config  ******/
 
-	    this._events();
-	  }
+Router.add('search', search => PubSub.publish('show-search', search));
+Router.add('material', (matId, view) => PubSub.publish('show-material', {'id': matId, 'view': view}));
 
-	  _events() {
-	    //super._events();
 
-	    this.calcSelector.setPrevListener(e => {
-	      if (this.groupIndex > 0){
-	        let calcId = this.groupCalcs[--this.groupIndex];
-	        this._loadGraphData(calcId);
-	        this._updateSelectorState(calcId);
-	        return this.groupIndex === 0; // the first
-	      }
-	    });
 
-	    this.calcSelector.setNextListener( e => {
-	      if (this.groupIndex < this.groupCalcs.length-1){
-	        let calcId = this.groupCalcs[++this.groupIndex];
-	        this._loadGraphData(calcId);
-	        this._updateSelectorState(calcId);
-	        return this.groupIndex === this.groupCalcs.length-1; // the last
-	      }
-	    });
-	  }
+/****** init ******/
 
+searchMod = new SearchModule();
 
-	  updateSelection(leafIds/*Set*/){
-	    //console.log('E-StructureDetails UPDATING calcs: ',calcs.values().next().value);
-	    if (leafIds.size > 0){
-	      this.rightBox.style.visibility = 'visible';
-	      //console.log('E-StructureDetails UPDATING calcs:leafIds.size > 0 ',leafIds);
-	      let calcMapByFunctional = getCalcMapByFunctional(leafIds);
-	      if (this.summaryByFunctionals === null)
-	        this.summaryByFunctionals =
-	          new SummaryByFunctionalsComponent(calcMapByFunctional,
-	            this.element.querySelector('.summary-box'));
-	      else
-	        this.summaryByFunctionals.build(calcMapByFunctional);
-	      // let bandGapDirect= calcs.values().next().value.band_gap_direct;
-	      //let bandGapType= (bandGapDirect ? "direct" : "indirect");
-
-	      let counter= 0;
-	      leafIds.forEach( calcId => {
-	        counter++;
-	        if (counter === 1) this.firstId = calcId;
-	        if (counter === leafIds.size) this.lastId = calcId;
-	      });
-	    }else
-	      this.rightBox.style.visibility = 'hidden';
-
-	    function getCalcMapByFunctional(leafIds/*Set*/){
-	      let functCalcMap = new Map();
-	      leafIds.forEach( leafId => {
-	        let calc = DataStore.getCalc(DataStore.getCalcReprIntId(leafId));
-	        if (calc.has_band_structure){
-	          //console.log('CALC BS ',calc.band_gap,calc.band_gap_direct);
-	          if (functCalcMap.has(calc.functional_type)){
-	            functCalcMap.get(calc.functional_type).add(calc);
-	          }else{ // New functional
-	            let newFunctionalArray = new Set();
-	            newFunctionalArray.add(calc);
-	            functCalcMap.set(calc.functional_type, newFunctionalArray);
-	          }
-	        }
-	      });
-	      return functCalcMap;
-	    }
+//console.log('document.location: '+document.location.hash);
+if (document.location.hash === '') document.location += "#/search";
+Router.route();
 
-	  }
 
+/********* User authentication ***********/
 
+let userNameElement = document.querySelector('#user-name');
+let logoutButton = document.querySelector('#logout-button');
 
-	  updateMarkedLeaf(leafId){
-	    //console.log('updateMarkedCalc '+calc);
-	    this.groupCalcs = null; // if the leafId is not a group else this.groupCalcs is array
-	    if (leafId === null){
-	      //this.leafTitle.innerHTML = 'NO SELECTION';
-	      this.calcSelector.setState('NO SELECTION', true, true);
-	      return;
+function setAppAuthenticated(data){
+  if (data.status === 'Authenticated'){
+    userNameElement.innerHTML = data.user.username;
+    document.querySelector('#guest-user').style.display = 'none';
+    document.querySelector('#auth-user').style.display = 'inline';
+    util.setAuthRequestHeader(data.user, data.token.data);
+    if (currentModule === materialModDOM) flaggingTab.style.visibility = 'visible';
+  }
+}
 
-	    }else{
-	      if (DataStore.getGroups().has(leafId)){
-	        //this.leafTitle.innerHTML = leafId+' ('+DataStore.getGroups().get(leafId).calcs.size+')';
-	        this.groupCalcs =  Array.from(DataStore.getGroups().get(leafId).calcs);
-	        let calcId = DataStore.getCalcReprIntId(leafId);
-	        this.groupIndex = this.groupCalcs.indexOf(calcId);
-	        this._updateSelectorState(calcId);
-	      }else
-	        //this.leafTitle.innerHTML = leafId;
-	        this.calcSelector.setState(leafId, true, true);
-	    }
 
-	    this._loadGraphData(DataStore.getCalcReprIntId(leafId));
+function setAppLoggedOut(){
+  userNameElement.innerHTML = '';
+  document.querySelector('#guest-user').style.display = 'inline';
+  document.querySelector('#auth-user').style.display = 'none';
+  util.setAuthRequestHeader();
 
-	    // calc.fermi_surface
+  if (flaggingTab.style.visibility !== 'hidden')
+    flaggingTab.style.visibility = 'hidden';
+}
 
-	  }
 
+function getCookie(name) {
+  let value = "; " + document.cookie;
+  let parts = value.split("; " + name + "=");
+  if (parts.length === 2) return parts.pop().split(";").shift();
+}
 
-	  _updateSelectorState(leafId){
-	    let t = leafId+' ('+(this.groupIndex+1)+'/'+this.groupCalcs.length+')';
-	    this.calcSelector.setState(t, this.groupIndex === 0,
-	      this.groupIndex === this.groupCalcs.length-1);
-	  }
 
+function parseCookie(userData) {
+  return userData.substring(1, userData.length-1).replace(/\\054/g,',').replace(/\\/g,'');
+}
 
-	  _loadGraphData(calcId){
-
-	    let calc = DataStore.getCalc(calcId);
-
-	    if (!this.bsDosPlotter.isAttached())
-	      this.bsDosPlotter.attach(this.element.querySelector('.calc-bs-dos-plotter')
-	        ,undefined,360);
-
-	    if (calc === null || (!calc.has_band_structure && !calc.has_dos)){
-	      this.bsDosPlotter.setNoData();
-	      this.bzViewerWrapper.setNoData();
-	      this.bandGapField.style.display = 'none';
-	      this.lowerSection.style.display = 'none';
-
-	    }else{
-	      LoadingPopup.show();
-	      let matId = DataStore.getMaterialData().id;
-
-	      util.serverReq(util.getMaterialCalcURL(matId, calc.id, 'dos'), e1 => {
-	        let dosData = JSON.parse(e1.target.response).dos;
-
-	        util.serverReq(util.getMaterialCalcURL(matId, calc.id, 'band_structure'),
-	        e2 => {
-	          let bsData= JSON.parse(e2.target.response).band_structure;
-	          if (bothSpins(bsData, dosData))
-	            this.spinLegend.style.display = 'block';
-
-	          //***util.addBandGapData(calcData, bsData);
-	          //console.log('CODE NAME:', calc.code_name);
-	          this.bsDosPlotter.setUpAndData(bsData, dosData, calc.code_name );
-
-	          if (calc.has_band_structure){
-
-	            this.bandGapField.style.display = 'block';
-	            this.bandGapValue.textContent= util.J2eV(calc.band_gap, 2)+' eV ';
-	            // console.log('calc.brillouin_zone_json',calc.brillouin_zone_json);
-	            if (calc.brillouin_zone_json !== null){
-	              this.lowerSection.style.display = 'block';
-	              this.bzViewerWrapper.setCalcData(calc.brillouin_zone_json, bsData.segments);
-	            }else{
-	              this.lowerSection.style.display = 'none';
-	              this.bzViewerWrapper.setNoData();
-	            }
-
-	            //this.bzViewerWrapper.setCalcData(calc.brillouin_zone_json, bsData.segments);
-	            // if there bandstruc data && calc.band_gap === 0  => show FermiSurface
-	            //if (calc.band_gap === 0)
-	              //setFermiVizContent(this.fermiBox, (calc === null ? '' : util.FERMI_SURFACE_URL));
-	          }else{
-	            this.lowerSection.style.display = 'none';
-	            this.bandGapField.style.display = 'none';
-	            this.bzViewerWrapper.setNoData();
-	          }
-	          LoadingPopup.hide();
-	        });
-	      });
-
-	    }
-
-	    function bothSpins(bsData, dosData){
-	      if (bsData !== undefined){
-	        if (bsData.segments[0].band_energies.length === 2) return true;
-	      }
-	      if (dosData !== undefined){
-	        if (dosData.dos_values.length === 2) return true;
-	      }
-	      return false;
-	    }
-	  }
 
+let userInfoCookie = getCookie('user_info');
+//console.log('Cookies: ', document.cookie, userInfoCookie);
 
-	  setPrevCalcListener(listener){
-	    this.prevCalcListener= listener;
-	  }
+if (userInfoCookie !== undefined){
+  let userInfoData = JSON.parse(parseCookie(userInfoCookie));
+  //console.log('userInfoData: ', userInfoData);
+  setAppAuthenticated(userInfoData);
+}
 
 
-	  setNextCalcListener(listener){
-	    this.nextCalcListener= listener;
-	  }
+// Logout
+logoutButton.addEventListener( "click", e => {
 
-	}
+  document.cookie='user_info=; expires=Thu, 01 Jan 1970 00:00:00 GMT; domain='+
+    util.USER_COOKIE_DOMAIN+'; path=/';
+  //console.log('Logging out document.cookie ',document.cookie);
 
+  setAppLoggedOut();
+  //console.log('Logging out ',userNameElement.innerHTML);
+});
 
 
-	class SummaryByFunctionalsComponent{
-
-	  constructor(calcMapByFunctional, hostElement){
-	    this.calcMapByFunctional = calcMapByFunctional;
-	    this.hostElement = hostElement;
-	    this.viewType = 'text';
-	    this.functional = null;
-	    this.hostElement.innerHTML+=`
-	      <div style="float: left" >
-	        <svg xmlns="http://www.w3.org/2000/svg" class="chart-tab"
-	          viewBox="0 0 15 15" width="15" height="15" style="fill: #c7c7c7;">
-	            <rect x="0" y="0"  width="2" height="15" />
-	            <rect   x="3" y="5"  width="1.8" height="7"  />
-	            <rect  x="6" y="3"  width="1.8" height="9"  />
-	            <rect   x="9" y="6"  width="1.8" height="6"  />
-	            <rect  x="12" y="2"  width="1.8" height="10"  />
-	            <rect x="2" y="13"   width="13" height="2" />
-	        </svg>
-	        <svg xmlns="http://www.w3.org/2000/svg" class="text-tab"
-	          viewBox="0 0 15 15" width="15" height="15" style="fill: #777;">
-	            <rect x="0" y="1"   width="15" height="2.5" />
-	            <rect   x="0" y="6"  width="15" height="2.5"  />
-	            <rect  x="0" y="11"  width="15" height="2.5"  />
-	        </svg>
-	      </div>
-
-	      <div class="functional-tabs" style="float: right">
-	      </div>
-
-	      <div style="clear: both;"></div>
-
-	      <div class="content-placeholder" >
-
-	        <div style="display: block" class="text-panel" >
-
-	          <div><b><span info-sys-data="band gap">Band gap</span></b> (eV):
-	            <div class="stats-fields summary-bandgap-field" > </div>
-	          </div>
-	        </div>
-
-	        <div style="display:none" class="chart-panel" >
-	          <div class="charts-placeholder" > </div>
-	        </div>
-
-	      </div>
-	    `;
-	    this.chartTab = this.hostElement.querySelector('.chart-tab');
-	    this.textTab = this.hostElement.querySelector('.text-tab');
-	    this.functionalTabs = this.hostElement.querySelector('.functional-tabs');
-	    this.chartPanel = this.hostElement.querySelector('.chart-panel');
-	    this.textPanel = this.hostElement.querySelector('.text-panel');
-	    this.bandgapField = this.hostElement.querySelector('.summary-bandgap-field');
-
-	    this.statsViewer = new StatsViewer();
-	    let chartsPlaceholder = this.hostElement.querySelector('.charts-placeholder');
-	    this.statsViewer.attach(chartsPlaceholder, 250, 150);
-
-	    this.build(calcMapByFunctional);
-
-	    this.chartTab.addEventListener( "click", e => {
-	      this.chartTab.style.fill = '#777';
-	      this.viewType = 'chart';
-	      this.textTab.style.fill = '#c7c7c7';
-	      this.chartPanel.style.display = 'block';
-	      this.textPanel.style.display = 'none';
-	    });
+/***/ }),
+/* 17 */
+/***/ (function(module, exports) {
 
-	    this.textTab.addEventListener( "click", e => {
-	      this.textTab.style.fill = '#777';
-	      this.viewType = 'text';
-	      this.chartTab.style.fill = '#c7c7c7';
-	      this.textPanel.style.display = 'block';
-	      this.chartPanel.style.display = 'none';
-	    });
 
-	    this.functionalTabs.addEventListener( "click", e => {
-	      if (e.target.className === 'tab'){
-	        this.functionalTabs.querySelector('[data-tab="'+this.functional+'"]')
-	          .className = 'tab';
-	        this.functional = e.target.getAttribute('data-tab');
-	        this.functionalTabs.querySelector('[data-tab="'+this.functional+'"]')
-	          .className = 'tab-selected';
-	        this._setData();
-	      }
-	    });
+const Conf = {};
 
-	  }
+Conf.GuestUserToken =
+  'eyJhbGciOiJIUzI1NiIsImlhdCI6MTUyMzg4MDE1OSwiZXhwIjoxNjgxNTYwMTU5fQ.ey'+
+  'JpZCI6ImVuY2d1aSJ9.MsMWQa3IklH7cQTxRaIRSF9q8D_2LD5Fs2-irpWPTp4';
 
-	  _setData(){
-	    let stats = this.functionalBandGapMap.get(this.functional);
-	    // Set text data
 
-	    this.bandgapField.innerHTML = stats.html;
+// EXPORTS
+module.exports = Conf;
 
-	    // Set Charts data
-	    this.statsViewer.clear();
-	    this.statsViewer.drawPoints(stats.data, stats.label, stats.min, stats.max);
-	  }
 
+/***/ }),
+/* 18 */
+/***/ (function(module, exports, __webpack_require__) {
 
+"use strict";
 
-	  build(calcMapByFunctional){
-
-	    if (calcMapByFunctional.size === 0){
-	      this.hostElement.style.display = 'none';
-	      this.hostElement.previousElementSibling.style.display = 'none';
-	    }else{
-	      this.hostElement.style.display = 'block';
-	      this.hostElement.previousElementSibling.style.display = 'block';
-	    }
-
-	    this.unfoldedElement = null;
-	    this.functionalTabs.innerHTML = '';
-	    this.functionalBandGapMap = new Map();
-	    //console.log('calcMapByFunctional',calcMapByFunctional, this.hostElement);
-	    calcMapByFunctional.forEach( (calcs, functionalName) =>{
-	      //let statsMap = util.getQuantityStatsMap(calcs);
-	      let array= [];
-	      calcs.forEach( calc => {
-	        array.push(calc.band_gap/1.602176565e-19);
-	      });
-	      let stats = {};
-	      stats.data = array;
-	      stats.min = Math.min.apply(null, array);
-	      stats.max = Math.max.apply(null, array);
-	      stats.equal = (stats.min === stats.max);
-	      stats.label = 'band gap';
-	      stats.html = util.getAverage(stats.data).toFixed(2)+
-	        ' &nbsp; <span style="font-size: 0.9em">['+stats.min.toFixed(2)
-	        +' , '+stats.max.toFixed(2)+']</span>';
-
-	      this.functionalBandGapMap.set(functionalName, stats);
-
-	      let tabClass= 'tab';
-	      if (this.functional === null)     this.functional = functionalName;
-	      if (this.functional === functionalName){
-	        this._setData();
-	        tabClass= 'tab-selected';
-	      }
-
-	      this.functionalTabs.innerHTML +=
-	        '<span class="'+tabClass+'" data-tab="'+functionalName+'">'+functionalName+'</span>';
-	    });
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+ /*
+   This component is the popup window (and the darkened background) with a form
+   inside used for users to report (flagging) errors on the calculations
+ */
+
+
+
+let util = __webpack_require__(0);
+let DataStore = __webpack_require__(1);
+
+// main DOM elements
+let flaggingPopupBackground = document.querySelector('#flagging-form-popup-bg');
+let flaggingFormPopup = document.querySelector('#flagging-form-popup');
+flaggingFormPopup.innerHTML =`
+
+<div> <img src="img/cross.svg"  height="12px"
+  style="float: right; cursor: pointer" />
+</div>
+
+<div class="form-wrapper">
+  <div class="popup-title"> Error reporting</div>
+  <select id="flagging-category" name="category">
+    <option value="">Select a category *</option>
+    <option value="structure">Structure</option>
+    <option value="electronicstruct">Electronic structure</option>
+    <option value="methodology">Methodology</option>
+    <option value="thermalprops">Thermal properties</option>
+  </select>
+
+  <select id="flagging-subcategory" name="subcategory">
+
+  </select>
 
-	    InfoSys.addToInfoSystem(this.hostElement);
-	  }
+  <textarea id="subject" name="subject" style="height:200px"
+  placeholder="Write a short explanation about the error detected" ></textarea>
+
+  <div id="form-validation-msg"> </div>
+
+  <div style="display: flex; justify-content: space-evenly;">
+    <button style="display: block">Send</button>
+  </div>
+
+
+</div>
+`;
+
+// Form elements
+let categoryField = flaggingFormPopup.querySelector('#flagging-category');
+let eStructOption = categoryField.querySelector('option[value="electronicstruct"]');
+let thermalOption = categoryField.querySelector('option[value="thermalprops"]');
+let subcategoryField = flaggingFormPopup.querySelector('#flagging-subcategory');
+let closeButton= flaggingFormPopup.querySelector('img');
+let validationMsg = flaggingFormPopup.querySelector('#form-validation-msg');
+let sendButton= flaggingFormPopup.querySelector('button');
+
+let treeLeaf = null;
+let overviewEStructCalcs = null;
 
-	}
 
+function _setCurrentPage(pageId){
 
+  subcategoryField.innerHTML = '';
 
-	class BZViewerWrapper{
+  if (pageId === null){
+    categoryField.disabled = false;
+    subcategoryField.style.display = 'none';
 
-	  constructor(hostElement) {
-	    this.hostElement = hostElement;
-	    this.bzViewer = null;
-	  }
+  }else{
+    categoryField.disabled = true;
+    subcategoryField.style.display = 'block';
+    subcategoryField.appendChild(createOption('Choose the subcategory *', ''));
 
+    switch (pageId) {
 
-	  setCalcData(bzData, bsData){
-	    if (this.bzViewer === null)
-	      this.bzViewer = new BrillouinZoneViewer(this.hostElement);
-	    this.bzViewer.load(this._getBZDataForViewer(bzData,bsData));
-	    this.hostElement.style.visibility = 'visible';
-	  }
+      case util.MAT_VIEW.structure:
+        categoryField.selectedIndex = 1;
+        subcategoryField.appendChild(createOption('Structure representation'));
+        subcategoryField.appendChild(createOption('Calculation tree'));
+        subcategoryField.appendChild(createOption('Summary'));
+        subcategoryField.appendChild(createOption('Specific calculation'));
+        break;
 
+      case util.MAT_VIEW.electronicstruct:
+        categoryField.selectedIndex = 2;
+        subcategoryField.appendChild(createOption('Calculation tree'));
+        subcategoryField.appendChild(createOption('Summary'));
+        subcategoryField.appendChild(createOption('Band structure'));
+        subcategoryField.appendChild(createOption('DOS'));
+        subcategoryField.appendChild(createOption('Brillouin zone'));
+        break;
 
-	  setNoData(){
-	    this.hostElement.style.visibility = 'hidden';
-	  }
+      case util.MAT_VIEW.methodology:
+        categoryField.selectedIndex = 3;
+        subcategoryField.style.display = 'none';
+        break;
 
+      case util.MAT_VIEW.thermalprops:
+        categoryField.selectedIndex = 4;
+        subcategoryField.appendChild(createOption('Calculation tree'));
+        subcategoryField.appendChild(createOption('Phonon dispersion'));
+        subcategoryField.appendChild(createOption('Phonon DOS'));
+        subcategoryField.appendChild(createOption('Specific heat'));
+        subcategoryField.appendChild(createOption('Helmholtz free energy'));
+        break;
+    }
+  }
 
-	  _getBZDataForViewer(bz_json, bs_json){
-	    let labels = [];
-	    let kPoints = [];
-	    bs_json.forEach( segment => {
-	      labels.push(segment.band_segm_labels);
-	      kPoints.push(segment.band_k_points);
-	    });
+} // function _setCurrentPage
 
-	    let data = {
-	      vertices: bz_json.vertices,
-	      faces: bz_json.faces,
-	      basis: bz_json.basis,
-	      labels: labels,
-	      segments: kPoints
-	    }
-	    return data;
-	  }
 
-	}
+function show(pageStatus){
+  //console.log('pageStatus : ',pageStatus);
+  treeLeaf = pageStatus.markedLeaf;
+  overviewEStructCalcs = pageStatus.eStructCalcs;
 
+  // Show/hide some dropdown list options
+  eStructOption.style.display = (DataStore.hasElecStructureData ? 'block' : 'none');
+  thermalOption.style.display = (DataStore.hasThermalData ? 'block' : 'none');
 
-	// EXPORTS
-	module.exports = ElectronicStructDetails;
+  _setCurrentPage(pageStatus.pageId);
 
+  let ttRect = flaggingFormPopup.getBoundingClientRect();
+  let leftPos =  (window.innerWidth - ttRect.width)/2;
+  let topPos = (window.innerHeight -ttRect.height)/2;
+  flaggingFormPopup.style.left = leftPos+'px';
+  flaggingFormPopup.style.top = (topPos-20)+'px';
 
-/***/ },
-/* 25 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-	 /*
-	  Implements a graphical UI component composed of a DOS plotter and a
-	  Band Structure plotter
-	 */
-
-
-	let BSPlotter = __webpack_require__(14);
-	let DOSPlotter = __webpack_require__(16);
-	let svg = __webpack_require__(9);
-
-
-	class BSDOSPlotter{
-
-	  constructor() {
-	    this.element = document.createElement('div');
-	    this.element.setAttribute('style','margin: 0 auto');
-	    this.parentElement= null;
-	    this.bsPlotter= new BSPlotter();
-	    this.dosPlotter= new DOSPlotter({left: 4, right: 16, top: 0, bottom: 30});
-	    this.dosYAxisLabeled = false;
-	  }
+  flaggingFormPopup.style.visibility = 'visible';
+  flaggingPopupBackground.style.visibility = 'visible';
+}
 
 
-	  attach(element, width, height){
-	    element.appendChild(this.element);
-	    //this.bsPlotter.attach(this.element, element.clientWidth/2 + 200 -20/*padding*/, height);
-	    //this.dosPlotter.attach(this.element, element.clientWidth/2 - 200 -20/*padding*/, height);
-	    this.bsPlotter.attach(this.element, height, height);
-	    this.height = height;
-	    this.dosPlotter.attach(this.element, this.height/2+20, height);
-	    this.parentElement= element;
-	  }
+function hide(){
+  flaggingPopupBackground.style.visibility = 'hidden';
+  flaggingFormPopup.style.visibility = 'hidden';
+  // reset UI
+  categoryField.selectedIndex = 0;
+  subcategoryField.selectedIndex = 0;
+  flaggingFormPopup.querySelector('textarea').value = '';
+  validationMsg.innerHTML = '';
+}
 
 
-	  isAttached(){
-	    return this.parentElement !== null;
-	  }
+function createOption(text, value){
+  let opt = document.createElement('option');
+  opt.value = (value === undefined ? text : value);
+  opt.innerHTML = text;
+  return opt;
+}
 
 
-	  setUpAndData(dispData, dosData, codeName){
+closeButton.addEventListener('click', e => {
+  hide();
+});
 
-	    this.hasDispData = (dispData !== undefined && dispData !== null);
-	    this.hasDosData = (dosData !== undefined && dosData !== null);
 
-	    // Create a new DOS graph with/without left axis and labels
-	    let newDosYAxisLabeled;
-	    if (this.hasDosData && !this.hasDispData) newDosYAxisLabeled = true;
-	    else newDosYAxisLabeled = false;
+sendButton.addEventListener('click', e => {
 
-	    if (this.dosYAxisLabeled !== newDosYAxisLabeled){
-	      this.element.removeChild(this.dosPlotter.svg);
-	      let newLeftMargin = (newDosYAxisLabeled ? 40 : 4)
-	      this.dosPlotter= new DOSPlotter({left: newLeftMargin, right: 16, top: 0, bottom: 30});
-	      let width = this.height/2 + newLeftMargin;
-	      this.dosPlotter.attach(this.element, width, this.height);
-	    }
-	    this.dosYAxisLabeled = newDosYAxisLabeled;
+  let categoryChosen = categoryField.options[categoryField.selectedIndex];
 
-	    if (this.hasDispData){
-	      this.bsPlotter.setBandStructureData(dispData);
-	      if (this.hasDosData)
-	        this.bsPlotter.setRepaintListener( (yZoom, yOffset) => {
-	          this.dosPlotter.setYZoomAndOffset(yZoom, yOffset);
-	          this.dosPlotter.repaint();
-	        });
-	    }else
-	      this.bsPlotter.setNoData();
+  if (!categoryField.disabled && categoryChosen.value === ''){ // Overview case
+    validationMsg.innerHTML = 'The category fields must be set';
 
-	    if (this.hasDosData){
+  }else if (categoryField.disabled && subcategoryField.value === '' // Detaisl pages case
+            && categoryChosen.value !== util.MAT_VIEW.methodology){
+    validationMsg.innerHTML = 'The subcategory fields must be set';
 
-	      this.dosPlotter.setPoints(dosData, codeName);
+  }else{
+    validationMsg.innerHTML = 'Sending report...';
+    let textareaText = flaggingFormPopup.querySelector('textarea').value;
+    let materialId = DataStore.getMaterialData().id;
+    let userdata = util.getUserData();
 
-	      if (this.hasDispData){
-	        this.bsPlotter.setExternalYAxisMax(this.dosPlotter.getYAxisMax());
 
-	        this.dosPlotter.setRepaintListener( (yZoom, yOffset) => {
-	          this.bsPlotter.setYZoomAndOffset(yZoom, yOffset);
-	          this.bsPlotter.repaint();
-	        });
-	        // Remove y axis label
-	        this.dosPlotter.svg.removeChild(this.dosPlotter.yLabelText);
-	        this.dosPlotter.yLabelText = null;
-	      }
+    let titleText = 'User issue | Material '+materialId;
+    let descriptionText = '**Server:** '+util.getServerLocation()+
+      '\\n\\n**User:** '+userdata.username+', '+userdata.email;
 
-	    }else
-	      this.dosPlotter.setNoData();
+    // Overview page
+    if ( !categoryField.disabled){
+      descriptionText += '\\n\\n**Category:** Overview / '+categoryChosen.text;
 
-	    this.dosPlotter.setYAxisLabelsVisibility(newDosYAxisLabeled);
-	  }
+      if (categoryChosen.value === util.MAT_VIEW.electronicstruct
+          && overviewEStructCalcs !== null)
+        descriptionText += '\\n\\n**Chosen calculations:** '+
+          (overviewEStructCalcs.bs === null ? '' : 'BS calculation '+overviewEStructCalcs.bs)+
+          (overviewEStructCalcs.dos === null ? '' : ' DOS calculation '+overviewEStructCalcs.dos);
 
+    }else{ // Details pages
+      descriptionText += '\\n\\n**Category:** '+categoryChosen.text;
 
-	  setNoData(){
-	    this.bsPlotter.setNoData();
-	    this.dosPlotter.setNoData();
-	  }
+      if (categoryChosen.value !== util.MAT_VIEW.methodology){
+        descriptionText += '\\n\\n**Subcategory:** '+
+          subcategoryField.options[subcategoryField.selectedIndex].text+
+          '\\n\\n**Calculation/group marked on the tree:** '+treeLeaf;
+      }
+    }
 
-	}
+    descriptionText += '\\n\\n**User text:** '+textareaText;
 
+    let queryJson =`{
+      "title": "${titleText}",
+      "description": "${descriptionText}"}`;
+    console.log('Flagging POST request Json: ',queryJson);//, util.getFlaggingURL());
 
-	// EXPORTS
-	module.exports = BSDOSPlotter;
 
+    util.serverReqPOST(util.getFlaggingURL(), queryJson, e => {
+      console.log('response',e);
+      if (e.target.status === 200) hide();
+    });
 
-/***/ },
-/* 26 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-	  'Details' view container that shows a table with the methodology info used
-	  to get the material calculations.
-
-	  In the file there is a defined (class) component used as a filter widget for
-	  the table: FilterInGroupsComponent.
-	 */
-
-	"use strict";
-
-	let DetailsViewBase = __webpack_require__(20);
-	let util = __webpack_require__(1);
-	let InfoSys = __webpack_require__(12);
-	let DataStore = __webpack_require__(2);
-	let SortingButton = __webpack_require__(27);
-
-
-	const REPOSITORY_LINK =
-	  'https://repository.nomad-coe.eu/NomadRepository-1.1/views/calculation.zul?pid=';
-
-	const calcTypesMap = new Map([
-	  ['single point', 'Single point'],
-	  ['GW calculation', 'GW'],
-	  ['geometry optimization', 'Geometry optimization'],
-	  ['molecular dynamics', 'Molecular dynamics'],
-	  ['phonon calculation', 'Phonon'],
-	  ['equation of state', 'Equation of state'],
-	  ['parameter variation', 'Parameter variation'],//['Convergence', 'convergence'],
-	  ['QHA calculation', 'QHA']
-	]);
-
-	const densityFunctionalMap = new Map([
-	  ['LDA', 'LDA'],
-	  ['GGA', 'GGA'],
-	  ['meta-GGA', 'meta-GGA'],
-	  ['hybrid-GGA', 'hybrid-GGA'],
-	  ['meta-hybrid-GGA', 'meta-hybrid-GGA'],
-	  ['HF', 'HF']
-	]);
-
-	const codeMap = new Map([
-	  ['exciting', 'exciting'],
-	  ['VASP', 'VASP'],
-	  ['FHI-aims', 'FHI-aims']
-	]);
-
-	const potentialMap = new Map([
-	  ['full all electron', 'Full potential' ],
-	  ['pseudopotential', 'Pseudo potential' ]
-	]);
-
-	const basicSetMap = new Map([
-	  ['numeric AOs', 'Numeric AOs' ],
-	  ['gaussians', 'Gaussians' ],
-	  ['(L)APW+lo', '(L)APW+lo'],
-	  ['plane waves', 'Plane waves']
-	]);
-
-
-
-	class FilterInGroupsComponent {
-
-	  constructor(className) {
-	    this.element = document.createElement('div');
-	    this.element.className = className;
-	    this.filtersOn = [];
-	    this.folded = true;
-	    this.element.innerHTML+=`
-	      <div>
-	        <div style="display: flex; justify-content: flex-end;">
-	          <div class="filter-groups-c-folded" >
-	            <span style="vertical-align: top;">Filtering &nbsp;&nbsp;</span>
-	          </div>
-	          <div class="filter-c-btn" >
-	             <img src="${util.IMAGE_DIR}folded.png" />
-	            <!--<button class="on">filter</button> -->
-	          </div>
-	        </div>
-	        <div class="filter-groups-c-unfolded" style="display: none">
-	          <table style="width: 100%">
-	            <thead>
-	            <tr>
-	              <th style="width: 13%;"> </th>
-	              <th style="width: 17%;">
-	                <span>Type</span>
-	              </th>
-	              <th style="width: 19%;">
-	                <span info-sys-data="functional-type">Density functional</span>
-	              </th>
-	              <th style="width: 13%;">
-	                <span info-sys-data="code-name">Code</span>
-	              </th>
-	              <th style="width: 17%;">
-	                <span info-sys-data="pseudopotential-type">Potential</span>
-	              </th>
-	              <th style="width: 12%;">
-	                <span info-sys-data="basis-set-type">Basis set</span>
-	              </th>
-	              <th style="width: 9%;"> </th>
-	            </tr>
-	            </thead>
-	            <tbody>
-	              <tr id="filter-items-row"></tr>
-	            </tbody>
-	          </table>
-	        </div>
-	      </div>
-	    `;
-	    //this.foldedPanel = this.element.querySelector('.filter-groups-c-folded');
-	    this.unfoldedPanel = this.element.querySelector('.filter-groups-c-unfolded');
-	    this.filterItemsRow = this.element.querySelector('#filter-items-row');
-
-	    this.foldBtn = this.element.querySelector('img');
-
-	    this.foldBtn.addEventListener('click', e => {
-	      this.folded = !this.folded;
-	      this.foldBtn.src = (this.folded ? util.IMAGE_DIR+'folded.png' :
-	        util.IMAGE_DIR+'unfolded.png');
-	      //this.foldedPanel.style.display = (this.folded ? 'block' : 'none');
-	      this.unfoldedPanel.style.display = (this.folded ? 'none' : 'block');
-	    });
+  }
 
-	    // Add listener for checkboxes events
-	    this.element.addEventListener('click', (e) => {
+});
 
-	      if (e.target.tagName === 'INPUT'){
-	        let index = this.filtersOn.indexOf(e.target.value);
-	        if (index >= 0)  this.filtersOn.splice( index, 1 );
-	        else this.filtersOn.push(e.target.value);
-	        this.itemListener(this.filtersOn);
-	        //console.log('this.filtersOn',this.filtersOn);
-	      }
-	    });
-	  }
 
 
-	  addGroupsItems(calcs){
-	    let lCalcTypesMap = new Map();
-	    let lDensityFunctionalMap = new Map();
-	    let lCodeMap = new Map();
-	    let lPotentialMap = new Map();
-	    let lBasicSetMap = new Map();
-	    calcs.forEach( c => {
-	      if (!lCalcTypesMap.has(c.type))
-	        lCalcTypesMap.set(c.type, calcTypesMap.get(c.type));
-	      if (!lDensityFunctionalMap.has(c.functional))
-	        lDensityFunctionalMap.set(c.functional, densityFunctionalMap.get(c.functional));
-	      if (!lCodeMap.has(c.code))
-	        lCodeMap.set(c.code, codeMap.get(c.code));
-	      if (!lPotentialMap.has(c.potential))
-	        lPotentialMap.set(c.potential, potentialMap.get(c.potential));
-	      if (!lBasicSetMap.has(c.basisSet))
-	        lBasicSetMap.set(c.basisSet, basicSetMap.get(c.basisSet));
-	    });
-	    this.filterItemsRow.innerHTML = '<td></td>'; // calculation Id column
-	    this.filtersOn = [];
-	    this.addGroupItems(lCalcTypesMap);
-	    this.addGroupItems(lDensityFunctionalMap);
-	    this.addGroupItems(lCodeMap);
-	    this.addGroupItems(lPotentialMap);
-	    this.addGroupItems(lBasicSetMap);
-	    this.filterItemsRow.innerHTML += '<td></td>'; // link column
-	  }
+// EXPORTS
+module.exports = { show, hide };
 
 
-	  addGroupItems(groupItemsMap){
-	    let html = '<td>  ';
-	    groupItemsMap.forEach( (itemName, itemId) => {
-	      this.filtersOn.push(itemId);
-	      html += '<input type="checkbox" value="'+itemId+'" checked>'+
-	        '<span style="vertical-align: 20%">'+itemName+'</span> &nbsp;&nbsp; <br> ';
-	    });
-	    this.filterItemsRow.innerHTML += html+ '</td>';
-	  }
+/***/ }),
+/* 19 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+ /*
+   This file implements the design pattern pub/sub, which allows one module
+	 to broadcast messages to other modules.
+ */
+
+
+
+var messages = new Map();
+var lastUid = -1;
+
+  /**
+   *	subscribe( message, func ) -> String
+   *	- message (String): The message to subscribe to
+   *	- func (Function): The function to call when a new message is published
+   *	Subscribes the passed function to the passed message. Every returned token
+   *	is unique and should be stored if you need to unsubscribe
+  **/
+function subscribe( message, func ){
+  //console.log('SUBSCRIBING Message '+message);
+	if ( typeof func !== 'function'){
+		return false;
+	}
+	// message is not registered yet
+	if ( !messages.has( message ) ){
+		messages.set( message, new Map());
+	}
+	// forcing token as String, to allow for future expansions without breaking usage
+	// and allow for easy use as key names for the 'messages' object
+	var token = 'uid_' + String(++lastUid);
+	messages.get(message).set(token, func); //messages[message][token] = func;
+  //print();
+	// return token for unsubscribing
+	return token;
+}
+
+
+function publish( message, data){
+
+  var hasSubscribers = messages.has( message )
+                       && (messages.get( message ).size > 0);
+
+	if ( !hasSubscribers ){
+		return false;
+  }
+
+  var deliver = function (){
+    //deliverMessage(message, data);
+    var subscribers = messages.get(message);
+    //console.log('DELIVERING Message '+message);
+    subscribers.forEach(function(func, token) {
+      func(data);
+      //console.log('EXE funct   '+ func);
+    });
+  };
+
+  setTimeout( deliver, 0 );  // async
+	return true;
+}
+
+
+function print(){
+  console.log('PubSub data: ');
+  messages.forEach(function(functions, msg) {
+    console.log(msg + ': ');
+
+    functions.forEach(function(func, token) {
+      console.log('    '+token + ': ' + func);
+    });
+  });
+}
+
+// EXPORTS
+module.exports = { subscribe: subscribe, publish: publish };
+
+
+/***/ }),
+/* 20 */
+/***/ (function(module, exports, __webpack_require__) {
 
+"use strict";
 
-	  setItemListener(listener){
-	    this.itemListener = listener;
-	  }
-	}
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
 
 
+ /*
+   This file implements the app Routing system: the feature that allows
+   the page navigation in a single-page environment.
+ */
 
-	class MethodologyDetails extends DetailsViewBase {
-
-	  constructor() {
-	    super('Methodology');
-
-	    this.sortedCalcs = [];
-	    this.markedCalc = null;
-
-	    this.element.innerHTML+=`
-
-	      <div>
-	        <div class="view-box">
-	          <div class="title">Methodology</div>
-
-	          <div class="filter-placeholder"></div>
-
-	          <div class="dataTableWrapper"></div>
-	        </div>
-	      </div>
-	    `;
-
-	    // There is no this.navTreeWrapper = this.element.querySelector('.navTreeWrapper');
-
-	    this.dataTableWrapper =
-	        this.element.querySelector('.dataTableWrapper');
-
-	    this.dataTableWrapper.innerHTML+=`
-	      <table id="methodology-data">
-	        <thead>
-	        <tr>
-	          <th style="width: 13%;">
-	            <span>Calculation ID</span>
-	            <span class="sorting-button"></span>
-	          </th>
-	          <th style="width: 17%;">
-	            <span>Type</span>
-	            <span class="sorting-button"></span>
-	          </th>
-	          <th style="width: 19%;">
-	            <span info-sys-data="functional-type">Density functional</span>
-	            <span class="sorting-button"></span>
-	          </th>
-	          <th style="width: 13%;">
-	            <span info-sys-data="code-name">Code</span>
-	            <span class="sorting-button"></span>
-	          </th>
-	          <th style="width: 17%;">
-	            <span info-sys-data="pseudopotential-type">Potential</span>
-	            <span class="sorting-button"></span>
-	          </th>
-	          <th style="width: 12%;">
-	            <span info-sys-data="basis-set-type">Basis set</span>
-	            <span class="sorting-button"></span>
-	          </th>
-	          <th style="width: 9%;">
-	            <span info-sys-data="basis-set-type">Link</span>
-
-	          </th>
-	        </tr>
-	        </thead>
-	        <tbody>
-	        </tbody>
-	      </table>
-	    `;
-
-	    this.tbody = this.dataTableWrapper.querySelector("tbody");
-	    this.moreInfoRow = document.createElement('tr'); //
-	    this.moreInfoRow.className= 'moreinfo';
-	    this.moreInfoCalcId = null;
-
-	    // filtering feature initialitation
-	    this.filterComponent = new FilterInGroupsComponent('meth-filter-component');
-	    this.element.querySelector('.filter-placeholder').
-	      appendChild(this.filterComponent.element);
-
-	    this.filterComponent.setItemListener( propsSel/*ected*/ => {
-
-	      let rows = this.tbody.querySelectorAll('tr');
-	      for (let i = 0; i < rows.length; ++i){
-	        let calcProps = rows[i].getAttribute('data-calc-props').split(',');
-	        //console.log('FILTERING calcProps: ',calcProps);
-	        let propsPresent = true;
-	        calcProps.forEach( e => {
-	          if (propsSel.indexOf(e) < 0) propsPresent = false;
-	        });
-
-	        if (propsPresent) rows[i].style.display = 'table-row';
-	        else rows[i].style.display = 'none';
-	      }
-	    });
 
-	    // row sorting feature initialitation
-	    this.sortingButtonWrappers =
-	      this.dataTableWrapper.querySelectorAll('.sorting-button');
-
-	    this.sortingButtons = [];
-
-	    let sortingButtonsMap = new Map([
-	      [ 'id', undefined ],
-	      [ 'type', undefined ],
-	      [ 'functional', undefined ],
-	      [ 'code', undefined ],
-	      [ 'potential', undefined ],
-	      [ 'basisSet', undefined ] ]);
-
-	    let keysIter = sortingButtonsMap.keys();
-	    this.sortingButtonWrappers.forEach( e => {
-	      let field = keysIter.next().value;
-	      let component = new SortingButton(field);
-	      e.appendChild(component.element);
-	      this.sortingButtons.push(component);
-
-	      component.setListener( (descendingOrder, field) => {
-	        //console.log(descendingOrder, field);
-	        this.sortingButtons.forEach( el => {
-	          if (el !== component) el.init();
-	        });
-	        this._sortRowsCalcDataBy(descendingOrder, field);
-	        this._render();
-	      });
-	    });
 
-	    // For static ones
-	    InfoSys.addToInfoSystem(this.element);
 
-	    this._events();
-	  }
+let routes = new Map();
 
 
-	  _events() {
-	    //super._events();
+function add(route, func){
+  routes.set(route, func);
+}
 
-	    this.dataTableWrapper.addEventListener('click', (e) => {
 
-	      let rowElement = e.target.parentElement;
-	      if (rowElement.className.indexOf('data-row') < 0)
-	        rowElement = rowElement.parentElement;
+window.addEventListener("hashchange", route);
 
-	      if (rowElement.className.indexOf('data-row') >= 0){
-	        let id= rowElement.getAttribute('data-calc-id');
+function route(){
+  let hashPath= document.location.hash.substring(2);
+  let command, param, subparam;
 
-	        if (this.moreInfoCalcId !== null){ // If more-info panel unfolded
-	          this.moreInfoRow.parentElement.removeChild(this.moreInfoRow);
-	          if (this.moreInfoCalcId === id){
-	            this.moreInfoCalcId = null;
-	            return;
-	          }
-	        }
-	        this.moreInfoCalcId = id;
-	        let moreInfoCalc, calcGroupType;
-	        this.sortedCalcs.forEach( leafId => { //console.log(leafId, id);
-	          if (leafId === id){
-	            moreInfoCalc = DataStore.getCalc(DataStore.getCalcReprIntId(leafId));
-	            calcGroupType = DataStore.getGroupType(leafId);
+  // remove the ending /
+  if (hashPath.lastIndexOf('/') === (hashPath.length-1))
+    hashPath = hashPath.substring(0,hashPath.length-1);
 
-	          }
-	        });
-	        this.moreInfoRow.innerHTML= ' <td></td><td colspan="7"> '+
-	          getHTMLCalcType(calcGroupType, moreInfoCalc)+' </td>';
-	        rowElement.parentElement.insertBefore(this.moreInfoRow, rowElement.nextElementSibling);
-	      }
+  if (hashPath.indexOf('/') >0){
+    let a= hashPath.split('/');
+    command= a[0];
+    param= a[1];
+    subparam= a[2];
+  }
+  else command= hashPath;
 
-	    });
+  //console.log("hashPath: " + hashPath+' command: '+command+' param: '+param+' subparam: '+subparam);
 
+  if (routes.has(command)) {
+    routes.get(command)(param, subparam);
+  }
+};
 
-	    function getHTMLCalcType(calcGroupType, calc){
 
-	      let result = '';
-	      let calcType = calcGroupType;
-	      if (calcGroupType === null ) calcType = calc.run_type;
-	      //console.log('getHTMLCalcType',calcType);
-	      switch (calcType){
+function print(){
+  console.log('Router data: ');
+  routes.forEach(function(func, url) {
+    console.log(url + ': ' + func);
+  });
+}
 
-	        case calcTypesMap.get('Single point'):
 
-	        case calcTypesMap.get('Geometry optimization'):
-	          //console.log(calc.pseudopotential_type, calc.scf_threshold, calc.basis_set_short_name);
-	          result = getValueHTML('pseudopotential type',calc.pseudopotential_type) +
-	          getValueHTML('scf threshold',calc.scf_threshold) +
-	          getValueHTML('basis set short name',calc.basis_set_short_name) +
-	          getSmearingHTML(calc.smearing);
-	          break;
+// EXPORTS
+module.exports = { add: add, route: route };
 
-	        case calcTypesMap.get('GW'):
-	          result =  getValueHTML('gw starting point',calc.gw_starting_point) +
-	            getValueHTML('gw type',calc.gw_type);
-	          break;
 
-	        case calcTypesMap.get('Equation of state'):
-	          result =  getValueHTML('pseudopotential type',calc.pseudopotential_type) +
-	            getValueHTML('basis set short name',calc.basis_set_short_name) +
-	            getValueHTML('scf threshold',calc.scf_threshold) +
-	            getSmearingHTML(calc.smearing) +
-	            getValueHTML('k point grid description',calc.k_point_grid_description);
-	          break;
+/***/ }),
+/* 21 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+ /*
+  The NavTree class define the UI tree component showing the material calculations.
+  There is only one instance that is shared by several 'Details' views.
+ */
+
+
+
+let util = __webpack_require__(0);
+let DataStore = __webpack_require__(1);
+
+
+
+function buildCalcTree(calcs, calcsInGroups){
+
+  let calcTree = new Map();
+  calcsInGroups.forEach( (groupData, groupId) => {
+
+    let representative = DataStore.getCalc(DataStore.getCalcReprIntId(groupId));
+    let codeNameTrimed= representative.code_name.trim();
+    let functionalType = representative.functional_type;
+
+    /***** Exception: disable grouping for some codes
+    if (codeNameTrimed !== 'VASP' && codeNameTrimed !== 'FHI-aims') */
+      if (calcTree.has(functionalType)){
+        let functionalMap= calcTree.get(functionalType);
+
+        if (functionalMap.has(codeNameTrimed)){
+          // Get an array and push a new calc
+          functionalMap.get(codeNameTrimed).push(groupId);
+        }else // New code name
+          functionalMap.set(codeNameTrimed,[groupId]);
+
+      }else{ // New functional
+        let newFunctionalMap= new Map();
+        newFunctionalMap.set(codeNameTrimed,[groupId]);
+        calcTree.set(functionalType,newFunctionalMap);
+      }
+  });
+
+  // Simple calcs are added to the tree
+  calcs.forEach( calc => {
+    //if (!DataStore.isInAnyGroup(calc.id)) addToCalcTree(calc, calc.id+'');
+    //****** Exception: disable grouping for some codes
+    if (!DataStore.isInAnyNotDisabledGroup(calc.id))
+      addToCalcTree(calc, calc.id+'');
+  });
+
+
+  return calcTree;
+
+  function addToCalcTree(calc, id){
+    let codeNameTrimed= calc.code_name.trim();
+    let functionalType = calc.functional_type;
+    if (calcTree.has(functionalType)){
+      let functionalMap= calcTree.get(functionalType);
+
+      if (functionalMap.has(codeNameTrimed)){
+        // Get an array and push a new calc
+        functionalMap.get(codeNameTrimed).push(id);
+      }else // New code name
+        functionalMap.set(codeNameTrimed,[id]);
+
+    }else{ // New functional
+      let newFunctionalMap= new Map();
+      newFunctionalMap.set(codeNameTrimed,[id]);
+      calcTree.set(functionalType,newFunctionalMap);
+    }
+  }
+}
+
+
+/* Maybe these functions (getNextNode, getPreviousNode) can be removed
+searching by node class calc-l and node-selected. Think about this */
+
+function getNextNode(nodeBox){
+  let nextCalcNodeBox= nodeBox.nextElementSibling.nextElementSibling;
+  // console.log("nextCALC.getNextNode " +nextCalcNodeBox);
+  if (nextCalcNodeBox === null){
+
+    if (nodeBox.parentElement.nextElementSibling !== null)
+      nextCalcNodeBox= nodeBox.parentElement.nextElementSibling/*nextCodeNodeBox*/
+          .nextElementSibling/*nextCodeBox*/.children[0]/*nextCalc*/;
+
+    else if (nodeBox.parentElement.parentElement.nextElementSibling !== null)
+      nextCalcNodeBox= nodeBox.parentElement.parentElement/*FunctionalBox*/
+          .nextElementSibling.nextElementSibling/*nextFunctionalBox*/
+          .children[1]/*nextCodeBox*/.children[0]/*nextCalc*/;
+    else //reaching the final node
+      nextCalcNodeBox= null;
+  }
+  return nextCalcNodeBox;
+}
+
+
+function getPreviousNode(nodeBox){
+  let prevCalcNodeBox;
+  if (nodeBox.previousElementSibling !== null)
+    prevCalcNodeBox= nodeBox.previousElementSibling.previousElementSibling;
+  // console.log("nextCALC.getNextNode " +nextCalcNodeBox);
+  else{
+
+    if (nodeBox.parentElement.previousElementSibling.previousElementSibling !== null)
+      prevCalcNodeBox= nodeBox.parentElement.previousElementSibling/*prevCodeNodeBox*/
+          .previousElementSibling/*prevCodeBox*/.children[0]/*prevCalc*/;
+    else if (nodeBox.parentElement.parentElement.previousElementSibling.previousElementSibling !== null)
+      prevCalcNodeBox= nodeBox.parentElement.parentElement/*FunctionalBox*/
+          .previousElementSibling.previousElementSibling/*prevFunctionalBox*/
+          .lastElementChild/*prevCodeBox*/.lastElementChild.previousElementSibling/*prevCalc*/;
+    else //reaching the final node
+      prevCalcNodeBox= null;
+  }
+  return prevCalcNodeBox;
+}
+
+
+
+class NavTree {
+
+  constructor() {
+    this.selectedCalcs= new Set();
+
+    this.element = document.createElement('div');
+    this.element.setAttribute('id','navigation-tree');
+    this.parentElement= null;
+    this.markedNode = null;
+    this._events();
+  }
+
+  // detach if necessary and attach
+  attach(element){
+    if (this.parentElement !== null)
+      this.parentElement.removeChild(this.element);
+    this.parentElement= element;
+    this.parentElement.appendChild(this.element);
+  }
+
+
+  build(materialName){
+    // Reset
+    this.selectedCalcs.clear();
+    this.markedNode = null;
+    this.element.innerHTML= '';
+    this.calcsInGroups = DataStore.getGroups();
+
+
+    function getNodeHTML(level, label, unfolded, counter = 0){
+      let foldingValue= 'node-'+(unfolded ? 'unfolded' : 'folded');
+      let counterTag= (counter === 0 ? '' :
+        '<span class="node-counter">('+counter+')</span>');
+      return `
+        <div class="${level}">
+          <span class="${foldingValue}"></span>
+          <span class="node-checkbox"></span>
+          <span class="node-label" >${label}</span>
+          ${counterTag}
+        </div>
+      `;
+    }
+
+    function getCalcGraphInfoAvalabilityHTML(calc){
+      let html= '';
+      if (calc.has_band_structure) html += '<span class="tooltip">B<span class="tooltiptext">Band structure</span></span> ';
+      if (calc.has_dos) html += '<span class="tooltip">D<span class="tooltiptext">Density of states</span></span> ';
+      if (calc.has_fermi_surface) html += '<span class="tooltip">F<span class="tooltiptext">Fermi surface</span></span>';
+      if (calc.has_thermal_properties) html += '<span class="tooltip">T<span class="tooltiptext">Phonons</span></span>';
+
+      return '&nbsp; <span class="calc-graph-aval">'+html+'</span>';
+    }
+
+    // Init map to store calculations data
+    let calcs = DataStore.getCalculations();
+
+    let tree= buildCalcTree(calcs, this.calcsInGroups);
+    let rootElement= document.createElement('div');
+    this.element.appendChild(rootElement);
+    rootElement.innerHTML= getNodeHTML('material-l',materialName,true);
+
+    let functionalLevelBox= document.createElement('div');
+    rootElement.appendChild(functionalLevelBox);
+
+    tree.forEach((codeMap, functionalName) => {
+      //console.log(codeMap + " " + value);
+      functionalLevelBox.innerHTML+= getNodeHTML('functional-l',functionalName,true);
+
+      let codeLevelBox= document.createElement('div');
+      functionalLevelBox.appendChild(codeLevelBox);
+
+      codeMap.forEach( (calcArray, codeName) => {
+        codeLevelBox.innerHTML+= getNodeHTML('code-l', codeName, false, calcArray.length);
+
+        let calcLevelBox= document.createElement('div');
+        codeLevelBox.appendChild(calcLevelBox);
+        calcLevelBox.style.display= 'none';
+
+        for (var i = 0; i < calcArray.length; i++) {
+          let graphInfoAvalabilityHTML = getCalcGraphInfoAvalabilityHTML(
+            DataStore.getCalc(DataStore.getCalcReprIntId(calcArray[i])));
+
+          let calcIcon = '', calcNumber = '';
+          if (DataStore.isGroup(calcArray[i])){
+            calcIcon = '<img class="folder-icon" src="'+util.IMAGE_DIR+'folder.png" />'
+            calcNumber = '('+this.calcsInGroups.get(calcArray[i]).calcs.size+')';
+          }
+
+
+          calcLevelBox.innerHTML += `
+            <div class="calc-l" data-calc-id="${calcArray[i]}" >
+              <span></span>
+              <span class="node-checkbox"></span>
+
+              <span class="node-label" >
+                ${calcIcon} ${calcArray[i]} ${calcNumber} ${graphInfoAvalabilityHTML}
+              </span>
+
+              <div style="float: right; padding: 1px 10px 0 0;  display: none;">
+                <img  src="${util.IMAGE_DIR}next.png" />
+              </div>
+
+            </div>
+            <div> </div>`;
+        }
+      });
+    });
+  } // build method
+
+
+  selectAll(initMarkedLeafId){
+    let materialNodeBox= this.element.children[0].children[0];
+    this._recursiveNodeSelection(materialNodeBox, true);
+    keepTreeIntegrity(materialNodeBox, true);
+    // No calc marked
+  }
 
-	        case calcTypesMap.get('Parameter variation'):
-	          result =  getValueHTML('pseudopotential type',calc.pseudopotential_type) +
-	            getValueHTML('scf threshold',calc.scf_threshold);
-	          break;
 
-	        case calcTypesMap.get('Phonon'):
-	          result =  getValueHTML('type', 'finite differences');
-	          break;
+  getMarkedLeaf(){
+    if (this.markedNode === null)  return null;
+    else return this.markedNode.getAttribute('data-calc-id');
+  }
 
-	      }
-	      if (result.trim() === '') return 'NO ADDITIONAL DATA';
-	      else return result;
-	    }
 
-	  }
+  setMarkedLeafIfNoneMarked(leafId){ // If leafId === null first node selected
+    if (this.getMarkedLeaf() === null){ // If none marked
+      if (leafId === null) this._markFirstSelectedNode();
+      else{
+        let nodeBox = this.element.querySelector('div[data-calc-id="'+leafId+'"]');
+        this._setMarkedCalc(nodeBox);
+      }
+    }
+  }
 
 
-	  updateSelection( leafIds/* Not used */ ){
 
-	    this.sortedCalcs = [];
+  _events() {
+    this.element.addEventListener('click',(e) => {
+      let classString = e.target.className;
 
-	    DataStore.getCalculations().forEach( c => {
+      // drop down/up event
+      if (classString.indexOf('folded')  >= 0){
+        this._foldTreeNode(e.target);
 
-	      let calcType = c.run_type;
-	      if (DataStore.getGroups().has(c.id)){//leafId))
-	        calcType = DataStore.getGroupType(c.id);//leafId);
-	        if (calcType === 'convergence') calcType = 'parameter variation';
-	        //console.log('Group',DataStore.getGroupType(leafId));
-	      }
+        // descendant selection/deselection event
+      }else if ((classString.indexOf('node-checkbox')  >= 0)){
 
-	      this.sortedCalcs.push({
-	        id: c.id,
-	        type: calcType,
-	        functional: c.functional_type,
-	        code: c.code_name,
-	        potential: c.core_electron_treatment,
-	        basisSet: c.basis_set_type
-	      });
-	    });
+        let selectMode= (e.target.parentElement.className.indexOf('selected') < 0);
+        this._recursiveNodeSelection(e.target.parentElement, selectMode);
+        keepTreeIntegrity(e.target.parentElement, selectMode);
+        this.treeSelectionListener(this.selectedCalcs);
+        this._keepCalcMarked(selectMode); //if (this.calcMarked)
 
-	    this.filterComponent.addGroupsItems(this.sortedCalcs);
+      }else if (/*this.calcMarked && */(classString.indexOf('node-label')  >= 0 )
+        && (e.target.parentElement.className === 'calc-l node-selected')){
+        this._setMarkedCalc(e.target.parentElement/*nodeBox*/);
+      }
+    });
 
-	    this._sortRowsCalcDataBy(true, 'id');
-	    //console.log('sortedCalcs:', this.sortedCalcs);
+  }
 
-	    this._render();
-	  }
 
+  _foldTreeNode(dropDowmElement){
+    let siblingElement= dropDowmElement.parentElement.nextElementSibling;
+    let classString = dropDowmElement.className;
 
-	  _sortRowsCalcDataBy(descendingOrder, field){
+    if (classString.indexOf('-folded')  >= 0) {
+      dropDowmElement.className= dropDowmElement.className.replace('folded','unfolded');
+      siblingElement.style.display= 'block';
+    }else {
+      dropDowmElement.className= dropDowmElement.className.replace('unfolded','folded');
+      siblingElement.style.display= 'none';
+    }
+  }
+
+
+  _recursiveNodeSelection(nodeBox, select){
 
-	    this.sortedCalcs.sort( (a, b) => {
-	      if(a[field] < b[field]) return (descendingOrder ? -1 : 1);
-	      if(a[field] > b[field]) return (descendingOrder ? 1 : -1);
-	      return 0;
-	    });
-	  }
+    let nodeCheckBox= nodeBox.children[1];
+    if (select){
+        nodeBox.className += ' node-selected';
+    }else{ // deselect
+        let index= nodeBox.className.indexOf(' node-selected');
+        nodeBox.className= nodeBox.className.substring(0,index);
+    }
 
+    if (nodeBox.className.indexOf('calc-l')  >= 0)  { // leaf node
+      let id= nodeBox.getAttribute('data-calc-id');//let id= parseInt(nodeBox.getAttribute('data-calc-id'));
+      if (select)  this.selectedCalcs.add(id);
+      else this.selectedCalcs.delete(id);
 
-	  updateMarkedLeaf(leafId){  }
+    }else { // Not leaf node
 
+      let nextLevelBox = nodeBox.nextElementSibling;  // next levelBox
+      // Two children per banch: the first one is the node label box
+      // and the second one the next level with the descendants
+      for (let i = 0; i < nextLevelBox.children.length; i++ ) {
+        this._recursiveNodeSelection(nextLevelBox.children[i++], select);
+      }
+    }
+  }
 
-	  _render(){
 
-	    let html = '';
-	    this.sortedCalcs.forEach( rowCalcData => { //leafId => {
-	      //html+= getRowHtml(leafId, calc, calcType);
-	      html+= getRowHtml(rowCalcData);
-	    });
-	    this.tbody.innerHTML = html;
-
-	    InfoSys.addToInfoSystem(this.tbody);
-
-	    function getRowHtml(rowCalcData/*leafId, calc, calcType*/){
-
-	      let calc = DataStore.getCalc( /*DataStore.getCalcReprIntId(*/rowCalcData.id);
-	      let calcType = rowCalcData.type;
-	      let calcProps = calcType+','+calc.functional_type+','+calc.code_name+
-	        ','+calc.core_electron_treatment+','+calc.basis_set_type;
-
-	      let repositoryLinkHtml = '';
-	      if (calc.calculation_pid !== null && calc.calculation_pid !== undefined)
-	        repositoryLinkHtml =
-	          '<a href="'+REPOSITORY_LINK+calc.calculation_pid+'" target="blank"> '
-	          +'<img src="img/download.svg" height="20px" /> </a>';
-
-	      return  `
-	        <tr data-calc-id="${calc.id/*leafId*/}" data-calc-props="${calcProps}" class="data-row">
-	        <td>${calc.id/*leafId*/}</td>
-	        <td>
-	          <span info-sys-data="calculation-type.value:${calcType}">
-	          ${calcType}</span>
-	        </td>
-	        <td>
-	          <span info-sys-data="functional-type.value:${calc.functional_type}">
-	            ${calc.functional_type}</span>
-	          ${getOptValue(calc.functional_long_name)}
-	        </td>
-	        <td>
-	          <span info-sys-data="code-name.value:${calc.code_name}">
-	            ${calc.code_name}</span>
-	           ${getOptValue(calc.code_version)}
-	        </td>
-
-	        <td>
-	          <span info-sys-data="core-electron-treatment.value:${calc.core_electron_treatment}">
-	          ${getPotentialValue(calc.core_electron_treatment)}</span>
-	        </td>
-	        <td>
-	          <span info-sys-data="basis-set-type.value:${calc.basis_set_type}">
-	            ${calc.basis_set_type}</span>
-	           ${getOptValue(calc.basis_set_quality_quantifier)}
-	        </td>
-
-	        <td style="padding-top: 8px;padding-bottom: 4px;">${repositoryLinkHtml}
-	        </td>
-
-	        </tr>`;
-	    }
-
-	    function getOptValue(value){
-	      if (value === undefined || value === null)  return '';
-	      else return '('+value+')';
-	    }
-
-	    function getPotentialValue(value){
-	      if (value === 'pseudopotential')  return 'pseudopotential';
-	      else if (value === 'full all electron')  return 'full potential';
-	      else return value;
-	    }
-	  }
 
-	}
+  setTreeSelectionListener(listener){
+    this.treeSelectionListener= listener;
+  }
+
+
+  setLeafMarkedListener(listener){
+    this.leafMarkedListener = listener;
+  }
 
-	function getValueHTML(text,value){
-	  if (value === undefined || value === null)  return '';
-	  else return '<b>'+text+'</b>: '+value+'<br>';
-	}
 
+  getTreeSelectedCalcs(){
+    return this.selectedCalcs;
+  }
 
-	function getSmearingHTML(value){
-	  let values = value.substring(1,value.length-1).split(',');
-	  return (values[0] === 'none' ? '' : '<b>smearing kind</b>: '+values[0]+' , ')+
-	         (values[1] === '0' ? '' : '<b>smearing width</b>: '+values[1]);
-	}
 
+  _keepCalcMarked(select){
 
+    if (select && (this.markedNode === null)){
+      this._markFirstSelectedNode();
 
-	// EXPORTS
-	module.exports = MethodologyDetails;
+    }else if (!select){
+      let id= parseInt(this.markedNode.getAttribute('data-calc-id'));
+      if (this.selectedCalcs.size === 0){
+        this.markedNode.className= this.markedNode.className.replace('-marked','');
+        this.markedNode= null;
+        this.leafMarkedListener(null);
+      }else  if (!this.selectedCalcs.has(id)){
+        this._markFirstSelectedNode();
+      }
+    }
+  } // _keepCalcMarked
 
 
-/***/ },
-/* 27 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-	 /*
-	  Sorting button component implementation
-	 */
-
-
-	let util = __webpack_require__(1);
-
-	class SortingButton {
-
-	  constructor(id) {
-
-	    this.id = id;
-	    this.ascending = true;
-
-	    this.element = document.createElement('span');
-	    this.element.innerHTML+=`
-	       <img src="img/sorting_init.png" width="12px"
-	        style="margin-bottom: -1px; cursor: pointer"/>
-	    `;
-	    this.image = this.element.querySelector('img');
-
-	    if (id === 'id')
-	      this.image.setAttribute('src','img/sorting_ascending.png');
-
-	    this.element.addEventListener('click', e => {
-	      this.ascending = !this.ascending;
-	      this.image.setAttribute('src',
-	        'img/sorting_'+(this.ascending ? 'ascending' : 'descending')+'.png');
-	      this.listener(this.ascending, this.id);
-	    });
-	  }
+  _markFirstSelectedNode(){
+    let calcNodeBoxes = this.element.getElementsByClassName('calc-l');
+    for (var i = 0; i < calcNodeBoxes.length; i++)
+      if (calcNodeBoxes[i].className.indexOf('node-selected') >= 0){
+        this._setMarkedCalc(calcNodeBoxes[i]);
+        return;
+      }
+  }
 
 
-	  init(){
-	    this.image.setAttribute('src','img/sorting_init.png');
-	  }
+  _setMarkedCalc(nodeBox){
+    if (this.markedNode !== null){
+      this.markedNode.className= this.markedNode.className.replace('-marked','');
+      this.markedNode.querySelector('div').style.display = 'none';
+      let folderIcon = this.markedNode.querySelector('.folder-icon');
+      if (folderIcon !== null ) folderIcon.src = util.IMAGE_DIR+'folder.png';
+    }
 
+    nodeBox.className += '-marked';
+    let folderIcon = nodeBox.querySelector('.folder-icon');
+    if (folderIcon !== null ) folderIcon.src = util.IMAGE_DIR+'folder-sel.png';
+    nodeBox.querySelector('div').style.display = 'block';
+    this.markedNode= nodeBox;
 
-	  setListener(listener){
-	    this.listener = listener;
-	  }
+    // The parent tree node is unfolded in order to show the leaf selected
+    let foldingElement = nodeBox.parentElement.previousElementSibling.firstElementChild;
+    if (foldingElement.className === 'node-folded'){
+      foldingElement.className = 'node-unfolded';
+      foldingElement.parentElement.nextElementSibling.style.display= 'block';
+    }
 
-	}
+    if (this.leafMarkedListener !== undefined)
+      this.leafMarkedListener(nodeBox.getAttribute('data-calc-id'));
+  }
 
-	// EXPORTS
-	module.exports = SortingButton;
+  showCalcsGraphDataAvalability(bool){
+    let elements= this.element.getElementsByClassName('calc-graph-aval');
+    for (var i = 0; i < elements.length; i++)
+      elements[i].style.display= (bool ? 'inline' : 'none');
+  }
 
+  setHeight(heightPx){
+    this.element.style.height = heightPx+'px';
+  }
 
-/***/ },
-/* 28 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-	 /*
-	  'Details' view container that shows the material calculations info related to
-	  their vibrational and thermal properties.
-	 */
-
-	"use strict";
-
-	let DetailsViewBase = __webpack_require__(20);
-	let util = __webpack_require__(1);
-	let InfoSys = __webpack_require__(12);
-	let DataStore = __webpack_require__(2);
-	let LoadingPopup = __webpack_require__(4);
-
-	let HeatCapPlotter = __webpack_require__(17);
-	let HelmholtzPlotter = __webpack_require__(29);
-	let PhononDispDOSPlotter = __webpack_require__(30);
-
-
-	class ThermalPropsDetails  extends DetailsViewBase{
-
-	  constructor() {
-	    super('Thermal Properties');
-	    this.firstId;
-	    this.lastId;
-	    this.element.innerHTML+=`
-	      <div style="float: left; width: 30%;">
-	        <div class="view-box">
-	          <div class="title">Calculations </div>
-	          <div class="navTreeWrapper"></div>
-	        </div>
-	      </div>
-
-	      <div style="float: right; width: 70%;">
-	        <div class="view-box thermal-properties-box">
-
-	          <div class="title">Vibrational and thermal properties</div>
-
-	          <div style="padding-top: 10px;">
-	            <div class="tree-leaf-title"></div>
-	          </div>
-
-	          <div class="calc-disp-dos-plotter" style="padding: 30px 100px; ">
-	            <div class="info-fields-label" style="float: left; width: 52%; ">
-	              <span info-sys-data="phonon-dispersion">Phonon dispersion </span>
-	            </div>
-	            <div class="info-fields-label" style="float: left;">
-	              <span info-sys-data="phonon-DOS">Phonon DOS  </span>
-	            </div>
-	            <div style="clear: both;"></div>
-	          </div>
-
-
-	          <div class="band" >
-	            <div style="padding: 30px 50px; display: flex; justify-content: space-around; ">
-
-	              <div >
-	                <div class="info-fields-label" >
-	                  <span info-sys-data="specific-heat-cv">Specific heat</span>
-	                </div>
-	                <div class="heat-plotter" >      </div>
-	              </div>
-
-	              <div>
-	                <div class="info-fields-label" >
-	                  <span info-sys-data="helmholtz-free-energy">Helmholtz free energy</span>
-	                </div>
-	                <div class="helmholtz-plotter" >      </div>
-	              </div>
-
-	            </div>
-	          </div>
-
-	        </div>
-	      </div>
-	    `;
-
-	    this.navTreeWrapper =
-	        this.element.getElementsByClassName("navTreeWrapper")[0];
-
-	    this.rightBox = this.element.querySelector('.thermal-properties-box');
-	    this.leafTitle = this.element.querySelector('.tree-leaf-title');
-
-	    this.dispDosPlotter = new PhononDispDOSPlotter();
-	    this.heatPlotter= new HeatCapPlotter();
-	    this.helmholtzPlotter= new HelmholtzPlotter();
-
-	    InfoSys.addToInfoSystem(this.element);
-	  }
+} // class NavTree
 
 
-	  _events() {
-	    super._events();
-	  }
 
+function keepTreeIntegrity(nodeBox, select){
 
-	  updateSelection(leafIds/*Set*/){
-	    //console.log('E-StructureDetails UPDATING calcs: ',calcs.values().next().value);
-	    if (leafIds.size > 0){
-	      this.rightBox.style.visibility = 'visible';
-	      let counter= 0;
-	      leafIds.forEach( calcId => {
-	        counter++;
-	        if (counter === 1) this.firstId = calcId;
-	        else if (counter === leafIds.size) this.lastId = calcId;
-	      });
-	    }else
-	      this.rightBox.style.visibility = 'hidden';
-	    //console.log('METHODOLOGY '+this.tbody.innerHTML);
-	  }
+  if (nodeBox.className.indexOf('material-l') >= 0) return;
+  let levelBox= nodeBox.parentElement;
 
+  for (let i = 0; i < levelBox.children.length; i++ ) {
+    let siblingNodeBox = levelBox.children[i++];
+    if (siblingNodeBox !== nodeBox &&
+          siblingNodeBox/*.children[1]*/.className.indexOf('selected') < 0)
+      return;
+  }
+  let parentNodeBox= levelBox.previousElementSibling;
+  if (select){
+    parentNodeBox.className += ' node-selected';
+  }else{
+    let index= parentNodeBox.className.indexOf(' node-selected');
+    parentNodeBox.className= parentNodeBox.className.substring(0,index);
+  }
+  keepTreeIntegrity(parentNodeBox, select);
+}
 
 
-	  updateMarkedLeaf(leafId){
-	    //console.log('updateMarkedCalc ',calc);
-	    if (leafId === null){
-	      this.leafTitle.innerHTML = 'NO SELECTION';
-	      return;
-	      //this.bandGapField.textContent= '';
-	    }else{
-	      if (DataStore.getGroups().has(leafId)){
-	        this.leafTitle.innerHTML = leafId+
-	          ' ('+DataStore.getGroups().get(leafId).calcs.size+')';
-	      }else
-	        this.leafTitle.innerHTML = leafId;
-	    }
-
-	    let calc = DataStore.getCalc(DataStore.getCalcReprIntId(leafId));
-
-	    if (!this.dispDosPlotter.isAttached()){
-	      this.dispDosPlotter.attach(this.element.querySelector('.calc-disp-dos-plotter'),undefined,360);
-	      this.heatPlotter.attach(this.element.querySelector('.heat-plotter'),317,317);
-	      this.helmholtzPlotter.attach(this.element.querySelector('.helmholtz-plotter'),317,317);
-	    }
-	    if (calc === null || (!calc.has_phonon_dos && !calc.has_phonon_dispersion
-	                          && !calc.has_thermal_properties)){
-	      this.dispDosPlotter.setNoData();
-	      this.heatPlotter.setNoData();
-	      this.helmholtzPlotter.setNoData();
-	    }else{
-	      LoadingPopup.show();
-	      let matId = DataStore.getMaterialData().id;
-
-
-
-	      util.serverReq(util.getMaterialCalcURL(matId, calc.id,'phonon_dos'), e=> {
-	        let dosData= JSON.parse(e.target.response).phonon_dos;
-
-	        util.serverReq(util.getMaterialCalcURL(matId, calc.id,
-	            'phonon_dispersion'), e2 => {
-	          let dispersionData= JSON.parse(e2.target.response).phonon_dispersion;
-	          this.dispDosPlotter.setUpAndData(dispersionData, dosData);
-
-	          if (calc.has_thermal_properties){
-
-	            util.serverReq(util.getMaterialCalcURL(matId, calc.id,
-	              'specific_heat_cv'), e3 => {
-	                let sHeatData= JSON.parse(e3.target.response).specific_heat_cv;
-	                this.heatPlotter.setData(sHeatData);
-	            });
-
-	            util.serverReq(util.getMaterialCalcURL(matId, calc.id,
-	              'helmholtz_free_energy'), e4 => {
-	                let helmholtzData = JSON.parse(e4.target.response).helmholtz_free_energy;
-	                this.helmholtzPlotter.setData(helmholtzData);
-	            });
-
-	          }else{
-	            this.heatPlotter.setNoData();
-	            this.helmholtzPlotter.setNoData();
-	          }
-
-	          LoadingPopup.hide();
-	        });
-	      });
-
-	    }
 
-	  }
 
+// EXPORTS
+module.exports = NavTree;
 
-	  setPrevCalcListener(listener){
-	    this.prevCalcListener= listener;
-	  }
 
+/***/ }),
+/* 22 */
+/***/ (function(module, exports, __webpack_require__) {
 
-	  setNextCalcListener(listener){
-	    this.nextCalcListener= listener;
-	  }
+"use strict";
 
-	}
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
 
-	// EXPORTS
-	module.exports = ThermalPropsDetails;
 
+ /*
+  This file implements the Overview view component in the  Material Module.
+ */
 
-/***/ },
-/* 29 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-	  Helmholtz free energy plotter implementation
-	 */
-
-	"use strict";
-
-	let svg = __webpack_require__(9);
-	let PlotterBase = __webpack_require__(18);
-
-
-	class HelmholtzPlotter extends PlotterBase{
-
-	  constructor() {
-	    super({left: 60, right: 16, top: 10, bottom: 32});
-	    this.tooltip;
-	  }
 
 
-	  setData(data){
-	    this.clear();
-	    // up to 600K data is taken
-	    let indexOf600K = data.temperature.indexOf(600)+1;
-	    let values = data.value.slice(0, indexOf600K);
-	    let temperatures = data.temperature.slice(0, indexOf600K);
 
-	    let yMaxValue = Math.max.apply(null, values);
-	    let yMinValue = Math.min.apply(null, values);
-	    let yAxisMaxValue = Math.ceil(yMaxValue/1000)*1000;
-	    let yAxisMinValue = Math.floor(yMinValue/1000)*1000;
+let util = __webpack_require__(0);
+let InfoSys = __webpack_require__(3);
+let LoadingPopup = __webpack_require__(4);
 
-	    this.setRangeAndLabels('T (K)', 0,  600,
-	      'F (J/kg)', yAxisMinValue, yAxisMaxValue);
-	    this.drawAxis(4, null, 0);
+let BSPlotter = __webpack_require__(7);
+let DOSPlotter = __webpack_require__(11);
+let HeatCapPlotter = __webpack_require__(12);
+let MaterialMod = __webpack_require__(9);
+let DataStore = __webpack_require__(1);
 
-	    let polylinePoints = '';
-	    temperatures.forEach( (t, i) => {
-	      let y = values[i];///1e-25;
-	      polylinePoints+= ' '+this.xRel*t+' -'+this.yRel*(y - this.yMin);
-	    });
-	    svg.addPolyline(this.plotArea, polylinePoints, 'plotSpin1');
-	  }
+const ELEMENT_INCLUDED_MSG = 'ELEMENT ALREADY INCLUDED';
 
-	}
 
+class Overview {
 
-	// EXPORTS
-	module.exports = HelmholtzPlotter;
+  constructor() {
 
+    this.element = document.createElement('div');
+    this.element.setAttribute('id','overview');
+    this.materialId;
+    this.element.innerHTML=`
 
-/***/ },
-/* 30 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-	 /*
-	 Implements a graphical UI component composed of
-	 a phonon DOS plotter (PhononDOSPlotter class, implemented in thsi file) and a
-	 BSPlotter (showing Phonon Dispersion)
-	 */
-
-
-	let BSPlotter = __webpack_require__(14);
-	let InteractivePlotterBase = __webpack_require__(15);
-	let svg = __webpack_require__(9);
-	let util = __webpack_require__(1);
-
-
-	class PhononDispDOSPlotter{
-
-	  constructor() {
-	    this.element = document.createElement('div');
-	    //this.element.setAttribute('id','elementable');
-	    this.parentElement= null;
-	    this.dispPlotter= new BSPlotter();
-	    this.dispPlotter.setPhononMode();
-
-	    this.dosPlotter= new PhononDOSPlotter();
-	  }
+    <div class="material-title">
+    </div>
 
+    <div style="float: left; width: 40%;">
+
+      <div id="structure-ov" class="view-box">
+        <div class="title">Structure
+          <img style="float: right" class="to-detail" src="img/more.svg" />
+          <div style="clear: both;"></div>
+        </div>
 
-	  attach(element, width, height){
-	    element.appendChild(this.element);
-	    this.dispPlotter.attach(this.element, height, height);
-	    this.dosPlotter.attach(this.element, undefined, height);
-	    this.parentElement= element;
-	  }
+        <div class="viz-box" style="height: 260px; position: relative"></div>
 
+        <div class="footer">
+          <div ><b><span>System type</span></b>:
+            <span class="system-type-field" ></span>
+          </div>
+          <div class="space-group-field" style="display: none">
+            <b><span info-sys-data="space-group">Space group</span></b>:
+            <span class="space-group-value" ></span>
+          </div>
+          <div class="structure-type-field" style="display: none">
+            <b><span info-sys-data="structure-type">Structure type</span></b>:
+            <span class="structure-type-value" ></span>
+          </div>
+        </div>
+      </div>
 
-	  isAttached(){
-	    return this.parentElement !== null;
-	  }
 
+<!-- ***** Elastic Constants Box
 
-	  setUpAndData(dispData, dosData){
-
-	    this.hasDispData = (dispData !== undefined && dispData !== null);
-	    this.hasDosData = (dosData !== undefined && dosData !== null);
-
-	    if (this.hasDispData){
-	      this.dispPlotter.setBandStructureData(dispData);
-	      if (this.hasDosData)
-	        this.dispPlotter.setRepaintListener( (yZoom, yOffset) => {
-	          this.dosPlotter.setYZoomAndOffset(yZoom, yOffset);
-	          this.dosPlotter.repaint();
-	        });
-	    }else
-	      this.dispPlotter.setNoData();
-
-	    if (this.hasDosData){
-	      this.dosPlotter.setPoints(dosData);
-	      if (this.hasDispData)
-	        this.dosPlotter.setRepaintListener( (yZoom, yOffset) => {
-	          this.dispPlotter.setYZoomAndOffset(yZoom, yOffset);
-	          this.dispPlotter.repaint();
-	        });
-	    }else
-	      this.dosPlotter.setNoData();
-	  }
+      <div id="elastic-ov" class="view-box">
+        <div class="title">Elastic constants
+          <img style="float: right" class="to-detail" src="img/more.svg" />
+          <div style="clear: both;"></div>
+        </div>
 
-	  setNoData(){
-	    this.dispPlotter.setNoData();
-	    this.dosPlotter.setNoData();
-	  }
+        <div class="info-fields">
+          Not analyzed yet
+        </div>
 
-	}
+      </div>
+-->
 
 
+      <div id="methodology-ov" class="view-box">
+        <div class="title">Methodology
+          <img style="float: right" class="to-detail" src="img/more.svg" />
+          <div style="clear: both;"></div>
+        </div>
 
-	class PhononDOSPlotter extends InteractivePlotterBase{
+        <div class="info-fields">
 
-	  constructor() {
-	    super({left: 4, right: 16, top: 0, bottom: 30});
-	    this.outOfRangeColorActivated = false;
-	  }
+          <div class="info-fields-label" > Available calculations </div>
 
-	  // detach if necessary and attach
-	  attach(element, width, height){
-	    super.attach(element, height/2+this.margins.left, height);
-	  }
+          <div style="float: left; width: 45%" >
+            <b><span info-sys-data="functional-type">Functional</span></b>
+            <div class="functional-field" > </div>
+          </div>
+          <div style="float: right; width: 45%" >
+            <b><span info-sys-data="code-name">Code</span></b>
+            <div class="code-field"> </div>
+           </div>
+           <div style="clear: both;"></div>
+        </div>
 
+      </div>
 
-	  setPoints(points){
-
-	    this.pointsSpin1 = [];
-	    this.pointsSpin2 = [];
-	    this._reset();
-
-	    let pSpin1= points.dos_values[0];
-	    let pSpin2 = null;
-	    if (points.dos_values.length === 2)  pSpin2 = points.dos_values[1];
-	    let pointsY= points.dos_energies;
-	    let pointsXInPlotRange = [];
-	    let pointsYInPlotRange = [];
-
-	    for (var i = 0; i < pointsY.length; i++) {
-	        let frecuency = pointsY[i]*5.034117012222e22;
-	        let dosSpin1 = pSpin1[i]*0.029979;
-	        let dosSpin2;
-	        if (pSpin2 !== null)  dosSpin2 = pSpin2[i]*0.029979246;
-	        //console.log('POINTS : ',frecuency);
-	        pointsXInPlotRange.push(dosSpin1);
-	        if (pSpin2 !== null) pointsXInPlotRange.push(dosSpin2);
-	        pointsYInPlotRange.push(frecuency);
-	        //console.log('POINTS : ',pointsX[i], energy);
-	        this.pointsSpin1.push({x: dosSpin1, y: frecuency});
-	        if (pSpin2 !== null) this.pointsSpin2.push({x: dosSpin2, y: frecuency});
-	    }
-
-	    let maxDosVal = Math.max.apply(null, pointsXInPlotRange);
-	    let maxEnergyVal = Math.max.apply(null, pointsYInPlotRange);
-	    let minEnergyVal = Math.min.apply(null, pointsYInPlotRange);
-
-	    // x axis steps generation
-	    let t = util.generateDiagramSteps(maxDosVal);
-	    let xSteps = t[0], exp = t[1];
-
-	    //console.log('formattedPoints paintPointsLine : ', this.formattedPoints.length);
-	    this.setAxisRangeAndLabels(null,0,xSteps[xSteps.length-1]/*maxDosVal*1.2*/,
-	      null,-50,320,minEnergyVal, maxEnergyVal, 100);
-
-	    svg.addText(this.axisGroup, this.plotRangeX/2, this.margins.bottom,
-	      'DOS (states/cm⁻¹)', 'middle', 'axis-steps-big');
-
-	    for (let i = 0; i < xSteps.length; i++) {
-	      let stepX = (this.plotRangeX*xSteps[i])/xSteps[xSteps.length-1];
-	      svg.addLine(this.axisGroup, stepX, 0, stepX, 3, 1);
-	      //console.log('step ',xSteps[i], stepX);
-	      svg.addText(this.axisGroup, stepX, 13,
-	        (i === 0 ? '0' : xSteps[i].toFixed(exp)), 'middle', 'axis-steps-smaller');
-	    }
-
-	    this.repaint();
-	  }
+    </div>
 
+    <div style="float: right; width: 60%;">
 
-	  repaintData(){
-	    let polylinePoints = '';
-	    for (var i = 0; i < this.pointsSpin1.length; i++) {
-	      polylinePoints+= ' '+this.xRel*this.pointsSpin1[i].x+
-	        ' '+this.transformY(this.pointsSpin1[i].y);
-	        //console.log('POINTS LAT : ',this.formattedPoints[i].x, this.formattedPoints[i].y);
-	    }
-	    svg.addPolyline(this.plotContent, polylinePoints, 'plotSpin1');
+      <div id="e-structure-ov"  class="view-box" > <!--style="height: 610px; "-->
+        <div class="title">Electronic structure
+          <img style="float: right" class="to-detail" src="img/more.svg" />
+          <div style="clear: both;"></div>
+        </div>
+
+        <div > <!-- style="margin: 12% 0; " -->
+
+        <div style="float: left; width: 60%;  ">
+        <div style="padding: 20px 0 20px 30px">
+          <div  class="info-fields-label">
+            <span info-sys-data="band-structure">Band structure</span>
+          </div>
+          <div>
+              <div id="band-plotter" >  </div>
+          </div>
+
+          <div class="footer-bs-calc"></div>
+        </div>
+        </div>
+
+        <div style="float: left; width: 40%;  ">
+          <div style="padding: 20px 30px 20px 60px">
+            <div class="info-fields-label">
+              <span info-sys-data="DOS">DOS</span>
+            </div>
+
+            <div>
+                <div id="dos-plotter" >  </div>
+            </div>
+            <div class="footer-dos-calc"></div>
+          </div>
+        </div>
+
+
+        <div style="clear: both;"></div>
+
+        <div class="spin-legend" style="font-size: 0.9em; padding: 6px 30px 10px; display: none">
+          <svg width="15px" height="10px"> <polyline points="0,5 15,5" class="plotSpin1"/></svg>
+          Spin <span style='font-size: 1.1em'>⇧</span>  &nbsp;&nbsp;&nbsp;
+
+          <svg width="15px" height="10px"> <polyline points="0,5 15,5" class="plotSpin2"/></svg>
+          Spin <span style='font-size: 1.1em'>⇩</span>
+        </div>
+
+        </div>
+
+        <!--
+        <div class="footer">
+          <b>Band gap</b>: <span class="e-struct-field" ></span>
+        </div>
+        -->
+      </div>
 
-	    polylinePoints = '';
-	    for (var i = 0; i < this.pointsSpin2.length; i++) {
-	      polylinePoints+= ' '+this.xRel*this.pointsSpin2[i].x+
-	        ' '+this.transformY(this.pointsSpin2[i].y);
-	        //console.log('POINTS LAT : ',this.formattedPoints[i].x, this.formattedPoints[i].y);
-	    }
-	    svg.addPolyline(this.plotContent, polylinePoints, 'plotSpin2');
+      <div id="thermal-props-ov"  class="view-box" >
+        <div class="title">Vibrational and thermal properties
+          <img style="float: right" class="to-detail thermal-props" src="img/more.svg" />
+          <div style="clear: both;"></div>
+        </div>
 
-	  }
-	}
+        <div style="padding: 36px; ">
+          <div class="info-fields-label">
+            <span info-sys-data="heat-capacity-cv">Specific heat</span>
+          </div>
 
-	// EXPORTS
-	module.exports = PhononDispDOSPlotter;
 
+          <div>
+              <div id="heat-plotter" >  </div>
+          </div>
+          <div class="footer-heat-calc" style="text-align: center"></div>
+        </div>
 
-/***/ },
-/* 31 */
-/***/ function(module, exports, __webpack_require__) {
+      </div>
 
-	
+    </div>
 
-	/*
-	Pending to implement
-	*/
-	"use strict";
+    <div style="clear: both;"></div>
+    `;
 
-	let DetailsViewBase = __webpack_require__(20);
-	let util = __webpack_require__(1);
-	let InfoSys = __webpack_require__(12);
-	//let DataStore = require('./DataStore.js');
+    this.materialTitle= this.element.getElementsByClassName('material-title')[0];
 
+    this.systemType= this.element.querySelector('.system-type-field');
+    this.spaceGroupField = this.element.querySelector('.space-group-field');
+    this.spaceGroupValue = this.element.querySelector('.space-group-value');
+    this.structTypeField= this.element.querySelector('.structure-type-field');
+    this.structTypeValue= this.element.querySelector('.structure-type-value');
+    //this.band_gap = this.element.getElementsByClassName('e-struct-field')[0];
 
+    //fields= this.element.getElementsByClassName('method-field');
+    this.functional= this.element.querySelector('.functional-field');//fields[0];
+    this.code= this.element.querySelector('.code-field');//fields[1];
 
-	class ElasticConstDetails extends DetailsViewBase {
+    let fields= this.element.getElementsByClassName('to-detail');
+    this.structureDetailBtn= fields[0];
+    this.electronicStructDetailBtn= fields[2];
+    this.methodologyDetailBtn= fields[1];
+    this.thermalDetailBtn= fields[3];
+/*
+    this.elasticDetailBtn= fields[1];
+    this.methodologyDetailBtn= fields[2];
+    this.electronicStructDetailBtn= fields[3];
+    this.thermalDetailBtn= fields[4];
+    */
 
-	  constructor() {
-	    super('Elastic constants');
+    this.vizBox = this.element.getElementsByClassName('viz-box')[0];
+    //this.cellViewer= null;
 
-	    this.sortedLeafs = [];
-	    this.markedCalc = null;
+    this.bandPlotter= null;
+    this.bsCalcIdBox = this.element.getElementsByClassName('footer-bs-calc')[0];
+    this.dosPlotter= null;
+    this.dosCalcIdBox = this.element.getElementsByClassName('footer-dos-calc')[0];
+    this.heatPlotter= null;
+    this.heatCalcIdBox = this.element.querySelector('.footer-heat-calc');
 
-	    this.element.innerHTML+=`
+    this.spinLegend = this.element.querySelector('.spin-legend');
 
-	      <div style="float: left; width: 27%;">
-	        <div class="view-box">
-	          <div class="title">Calculation </div>
-	          <div class="navTreeWrapper"></div>
-	        </div>
-	      </div>
+    // For static ones
+    InfoSys.addToInfoSystem(this.element);
 
-	      <div style="float: right; width: 73%;">
-	        <div class="view-box">
-	          <div class="title">Elastic constants</div>
+    // Store the state of the calcs chosen on the Elec. Structure box
+    this.eStructCalcs = { bs: null, dos: null};
+  }
 
-	          <div>Parameters</div>
-	          <div ></div>
 
+  attachAndSetEvents(element){
+    element.appendChild(this.element);
+    this._events();
+  }
 
-	        </div>
-	      </div>
 
-	      <div style="clear: both;"></div>
-	    `;
+  _events() {
 
-	    this.navTreeWrapper =
-	        this.element.querySelector('.navTreeWrapper');
+    this.structureDetailBtn.addEventListener( "click", (e) => {
+      util.setBrowserHashPath('material', this.materialId+'/'+util.MAT_VIEW.structure);
+    });
 
+    this.electronicStructDetailBtn.addEventListener( "click", (e) => {
+      util.setBrowserHashPath('material', this.materialId+'/'+util.MAT_VIEW.electronicstruct);
+    });
 
-	    // For static ones
-	    InfoSys.addToInfoSystem(this.element);
+    this.methodologyDetailBtn.addEventListener( "click", (e) => {
+      util.setBrowserHashPath('material', this.materialId+'/'+util.MAT_VIEW.methodology);
+    });
 
-	    this._events();
-	  }
+    this.thermalDetailBtn.addEventListener( "click", (e) => {
+      util.setBrowserHashPath('material', this.materialId+'/'+util.MAT_VIEW.thermalprops);
+    });
+
+/*
+    this.elasticDetailBtn.addEventListener( "click", (e) => {
+      util.setBrowserHashPath('material', this.materialId+'/'+util.MAT_VIEW.elasticconst);
+    });
+*/
 
 
-	  _events() {
-	    //super._events();
-	/*
-	    this.dataTableWrapper.addEventListener('click', (e) => {
+    //******* Optimize, genralize:
+    //this.element.querySelectorAll('.to-detail+.'+detailsId).addEventListener( "click", (e) => {
+    // util.setBrowserHashPath('material', this.materialId+'/'+detailsId);
+  }
 
-	      let rowElement = e.target.parentElement;
-	      if (rowElement.className.indexOf('data-row') < 0)
-	        rowElement = rowElement.parentElement;
-	      //console.log("TABLE EVENT ",rowElement);
 
-	      if (rowElement.className.indexOf('data-row') >= 0){
-	        let id= rowElement.getAttribute('data-calc-id');
+  getEStructChosenCalcs(){
+    return this.eStructCalcs;
+  }
 
 
-	      }
+  setDetailViewsListener(listener){
+    this.detailViewsListener= listener;
+  }
 
+  setVisible(){
+    this.element.style.display= 'block';
+  }
+
+
+  setMaterialData() {
+
+    let data = DataStore.getMaterialData();
+    this.materialTitle.innerHTML= util.getMaterialTitle(data);
+    this.materialId = data.id;
+
+    let isBulk = (data.system_type === 'bulk');
+    this.systemType.textContent= data.system_type;
+    this.structTypeField.style.display =
+      (isBulk && data.structure_type !== null ? 'block' : 'none');
+    this.spaceGroupField.style.display = (isBulk ? 'block' : 'none');
+
+    if (isBulk){
+      this.structTypeValue.textContent= data.structure_type;
+      this.spaceGroupValue.textContent = data.space_group_number+
+        ' ('+data.space_group_international_short_symbol+')';
+      InfoSys.addElementToInfoSystem(this.spaceGroupValue,
+        'space-group.value:'+data.space_group_number);
+    }
+
+  }
+
+
+  _evaluateCalc(calc){
+    let value = 0;
+    if (calc.functional_type === 'GGA') value += 100;
+    if (calc.has_band_structure && calc.has_dos) value += 10;
+    switch (calc.code_name.trim()) {
+      case 'FHI-aims': value += 3;  break;
+      case 'VASP': value += 2;  break;
+      case 'Quantum Espresso': value += 1;  break;
+    }
+    return value;
+  }
+
+
+  setCalcsData(markedTreeLeafs) {
+    //console.log('setCalcsData: '+JSON.stringify(data));
+    let calcs = DataStore.getCalculations();
+
+    let functionalMap = new Map();
+    let codeMap = new Map();
+    let calcWithBS = null, calcWithDOS = null, calcWithHeat = null;
+    let calcBSEvaluation = -1, calcDOSEvaluation = -1;
+
+    for (let i = 0; i < calcs.length; i++) {
+
+      if (functionalMap.has(calcs[i].functional_type)){
+        let num= functionalMap.get(calcs[i].functional_type);
+        // Because it's a number we can't use the returned value as a reference
+        functionalMap.set(calcs[i].functional_type,++num);
+      }else
+        functionalMap.set(calcs[i].functional_type,1);
+
+      let codeNameTrimed= calcs[i].code_name.trim();
+      if (codeMap.has(codeNameTrimed)){
+        let num= codeMap.get(codeNameTrimed);
+        // Because it's a number we can't use the returned value as a reference
+        codeMap.set(codeNameTrimed,++num);
+      }else
+        codeMap.set(codeNameTrimed,1);
+
+      let calcEvaluation = this._evaluateCalc(calcs[i]);
+      //console.log('calcEvaluation',calcEvaluation);
+
+      if (calcs[i].has_band_structure && calcEvaluation > calcBSEvaluation){
+        calcBSEvaluation = calcEvaluation;
+        calcWithBS = calcs[i];
+      }
+
+      if (calcs[i].has_dos && calcEvaluation > calcDOSEvaluation){
+        calcDOSEvaluation = calcEvaluation;
+        calcWithDOS = calcs[i];
+      }
+      //console.log('BS DOS Evaluation',calcBSEvaluation, calcDOSEvaluation);
+
+      if (calcWithHeat === null && calcs[i].has_thermal_properties)
+        calcWithHeat = calcs[i];
+    }
+
+    if (calcWithBS !== null)  this.eStructCalcs.bs = calcWithBS.id;
+    if (calcWithDOS !== null)  this.eStructCalcs.dos = calcWithDOS.id;
+
+    let tempCalcId = null;
+    if (calcWithBS !== null)  tempCalcId = calcWithBS.id;
+    else if (calcWithDOS !== null)  tempCalcId = calcWithDOS.id;
+
+    if (tempCalcId === null) markedTreeLeafs.eStruct = null; // no graph data
+    else if (DataStore.isInAnyNotDisabledGroup(tempCalcId)){
+      markedTreeLeafs.eStruct = DataStore.getGroupLeafId(tempCalcId);
+    }else
+      markedTreeLeafs.eStruct = +tempCalcId;
+
+    if (calcWithHeat === null) markedTreeLeafs.thermalProps = null;
+    else if (DataStore.isInAnyNotDisabledGroup(calcWithHeat.id)){
+      markedTreeLeafs.thermalProps = DataStore.getGroupLeafId(calcWithHeat.id);
+    }else
+      markedTreeLeafs.thermalProps = +calcWithHeat.id;
+    //console.log('Overview - thermalPropsDetailsTreeLeaf: ', markedTreeLeafs.thermalProps);
+
+    //this.band_gap.innerHTML= util.getBandGapStatsValue(calcs);
+
+    let functionalHTML= '';
+    functionalMap.forEach((number,functional) => {
+      functionalHTML+= '<span info-sys-data="functional-type.value:'+functional+
+        '">'+number+' '+functional+'</span> <br> ';
+    });
+
+    this.functional.innerHTML= functionalHTML;
+    InfoSys.addToInfoSystem(this.functional);
+
+    let codeHTML= '';
+    codeMap.forEach((number,codeName) => {
+      codeHTML+= '<span info-sys-data="code-name.value:'+codeName+
+        '">'+number+' '+codeName+'</span> <br> ';
+      //codeHTML+= number+' '+codeName+' <br> ';
+    });
+    this.code.innerHTML= codeHTML;
+    InfoSys.addToInfoSystem(this.code);
+
+
+    if (calcWithBS === null && calcWithDOS === null){
+      document.getElementById('e-structure-ov').style.display = 'none';
+      DataStore.hasElecStructureData = false;
+    }else{
+      document.getElementById('e-structure-ov').style.display = 'block';
+      DataStore.hasElecStructureData = true;
+
+      if (this.bandPlotter === null){
+        this.bandPlotter= new BSPlotter();
+        this.bandPlotter.attach(document.getElementById('band-plotter'),undefined,316);
+      }
+      if (this.dosPlotter === null){
+        this.dosPlotter= new DOSPlotter({left: 40, right: 16, top: 0, bottom: 30});
+        this.dosPlotter.attach(document.getElementById('dos-plotter'),undefined,317);
+      }
+
+      if (calcWithBS === null){
+        this.bandPlotter.setNoData();
+        this.bsCalcIdBox.innerHTML = '';
+      }else{
+        let url = util.getMaterialCalcURL(calcWithBS.material,calcWithBS.id,
+            'band_structure');
+        LoadingPopup.show();
+        util.serverReq(url, e => {
+          if (e.target.status === 200){
+            let bandStructData= JSON.parse(e.target.response).band_structure;
+            this.bandPlotter.setBandStructureData(bandStructData);
+            this.bsCalcIdBox.innerHTML = 'From calculation <b>'+calcWithBS.id+
+              '</b><br><span style="font-size: 0.8em">('+calcWithBS.functional_type+' - '+calcWithBS.code_name+')</span>';
+            if (bandStructData.segments[0].band_energies.length === 2)
+              this.spinLegend.style.display = 'block';
+          }
+          LoadingPopup.hide();
+        });
+      }
+
+      if (calcWithDOS === null){
+        this.dosPlotter.setNoData();
+        this.dosCalcIdBox.innerHTML = '';
+      }else{
+        let url = util.getMaterialCalcURL(calcWithDOS.material,calcWithDOS.id,
+            'dos');
+        LoadingPopup.show();
+        util.serverReq(url, e => {
+          if (e.target.status === 200){
+            let dosData= JSON.parse(e.target.response).dos;
+
+            this.dosPlotter.setPoints(dosData);//paintPointsLine(dosData);
+            this.dosCalcIdBox.innerHTML = 'From calculation <b>'+calcWithDOS.id+
+            '</b><br><span style="font-size: 0.8em">('+calcWithDOS.functional_type+' - '+calcWithDOS.code_name+')</span>';
+            if (dosData.dos_values.length === 2)
+              this.spinLegend.style.display = 'block';
+          }
+          LoadingPopup.hide();
+        });
+      }
+    }
+
+    if (calcWithHeat === null){
+      document.getElementById('thermal-props-ov').style.display = 'none';
+      DataStore.hasThermalData = false;
+    }else{
+      document.getElementById('thermal-props-ov').style.display = 'block';
+      DataStore.hasThermalData = true;
+
+      if (this.heatPlotter === null){
+        this.heatPlotter= new HeatCapPlotter();
+        this.heatPlotter.attach(document.getElementById('heat-plotter'),undefined,317);
+      }
+
+      if (calcWithHeat === null){
+        this.heatPlotter.setNoData();
+        this.heatCalcIdBox.innerHTML = '';
+      }else{
+        let url = util.getMaterialCalcURL(calcWithHeat.material, calcWithHeat.id,
+            'specific_heat_cv');
+        LoadingPopup.show();
+        util.serverReq(url, e => {
+          if (e.target.status === 200){
+            let heatData= JSON.parse(e.target.response).specific_heat_cv;
+            //console.log(heatData);
+            this.heatPlotter.setData(heatData);
+            this.heatCalcIdBox.innerHTML = 'From calculation <b>'+calcWithHeat.id+'</b>'+
+            '</b> <span style="font-size: 0.8em">('+calcWithHeat.functional_type+' - '+calcWithHeat.code_name+')</span>';
+          }
+          LoadingPopup.hide();
+        });
+      }
+    }
+
+  } // setCalcsData function
+
+}
+
+// EXPORTS
+module.exports = Overview;
+
+
+/***/ }),
+/* 23 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+ /*
+  'Details' view container that shows all the material info related to
+  its structure.
+
+  This container is extremely complex.
+
+  In the file there are two defined (classes) components used in the container:
+  - TreeLeafViewer: The panel on the right showing the data of the tree leaf marked
+  - SummaryByFunctionalsComponent: the component (central panel, below part)
+  showing a summary for the selected item on the tree (by functional)
+ */
+
+
+
+let DetailsViewBase = __webpack_require__(6);
+let util = __webpack_require__(0);
+let InfoSys = __webpack_require__(3);
+let CalcSelectorBar = __webpack_require__(13);
+let StatsViewer = __webpack_require__(14);
+let EquationOfStateViewer = __webpack_require__(24);
+let DataStore = __webpack_require__(1);
+let LoadingPopup = __webpack_require__(4);
+
+
+
+class StructureDetails extends DetailsViewBase {
+
+  constructor() {
+    super('Structure');
+    this.groupsData; // the calcs groups data is necesary to be shown
+
+    this.firstId;
+    this.lastId;
+
+    this.element.innerHTML+=`
+
+      <div style="float: left; width: 36%;">
+        <div class="view-box">
+          <div class="title">Structure </div>
+          <div class="viz-box" style="height: 400px; position: relative"></div>
+
+          <div class="footer-flex-wrapper">
+
+            <div class="fields-container">
+              <div><b><span>System type</span></b>:
+                <span class="struct-field" ></span>
+              </div>
+              <div class="structure-type-field" style="display: none">
+                <b><span info-sys-data="structure-type">Structure type</span></b>:
+                <span class="structure-type-value" ></span>
+              </div>
+              <div class="structure-prototype-field" style="display: none">
+                <b><span info-sys-data="structure-prototype">Structure prototype</span></b>:
+                <span class="structure-prototype-value" ></span>
+              </div>
+              <div class="strukturbericht-field" style="display: none">
+                <b><span info-sys-data="strukturbericht">Strukturbericht designation</span></b>:
+                <span class="strukturbericht-value" ></span>
+              </div>
+            </div>
+
+            <div class="footer-flex" style="display: none">
+
+              <div class="fields-container"
+                style="flex-basis: 70%; border-right: 1px solid #E4E4E4; ">
+
+                <div>
+                  <b><span info-sys-data="crystal-system">Lattice</span></b>:
+                  <span class="lattice-value" ></span>
+                </div>
+                <div>
+                  <b><span info-sys-data="space-group">Space group</span></b>:
+                  <span class="space-group-value" ></span>
+                </div>
+                <div>
+                  <b><span info-sys-data="point-group">Point group</span></b>:
+                  <span class="point-group-value" ></span>
+                </div>
+              </div>
+
+              <div style="flex-basis: 30%; margin-left: 30px;">
+                <div class="fields-container">
+                  <div><b><span info-sys-data="wyckoff-position-population">Wyckoff sites</span></b></div>
+                  <div class="wyckoff-sites-value"> </div>
+                </div>
+              </div>
+
+            </div>
+
+          </div>
+
+        </div>
+      </div>
+
+      <div style="float: left; width: 36%;">
+        <div class="view-box">
+          <div class="title">Calculations</div>
+          <div class="navTreeWrapper"></div>
+
+          <div class="summary-title">Summary  </div>
+          <div style="font-size: 0.85em; text-align: center; padding: 4px;">Based on the calculations selected above</div>
+
+          <div class="info-fields summary-box">
+          <!-- Lattice constants Cell volume, Density panel dynamically generated
+            -->
+          </div>
+        </div>
+      </div>
+
+      <div style="float: right; width: 28%;">
+        <div class="calc-specifics-box">
+
+          <div style="padding-top: 10px; " >
+            <div class="tree-leaf-title"></div>
+          </div>
+
+          <div class="tree-leaf-viewer-host"></div>
+
+          </div>
+        </div>
+
+      </div>
+    </div>
+    `;
+
+    this.navTreeWrapper =
+        this.element.getElementsByClassName("navTreeWrapper")[0];
+
+    let fields= this.element.getElementsByClassName('struct-field');
+    this.systemTypeField= fields[0];
+    this.structTypeField= this.element.querySelector('.structure-type-field');
+    this.structTypeValue= this.element.querySelector('.structure-type-value');
+    this.structPrototypeField= this.element.querySelector('.structure-prototype-field');
+    this.structPrototypeValue= this.element.querySelector('.structure-prototype-value');
+    this.strukturberichtField= this.element.querySelector('.strukturbericht-field');
+    this.strukturberichtValue= this.element.querySelector('.strukturbericht-value');
+
+    this.lowerBox = this.element.querySelector('.footer-flex');
+    this.latticeValue= this.element.querySelector('.lattice-value');
+    this.spaceGroupValue= this.element.querySelector('.space-group-value');
+    this.pointGroupValue= this.element.querySelector('.point-group-value');
+    this.wyckoffValue= this.element.querySelector('.wyckoff-sites-value');
+
+    this.summaryByFunctionals = null;
+
+    this.leafTitle = this.element.querySelector('.tree-leaf-title');
+
+    this.summaryBox = this.element.querySelector('.summary-box');
+
+    this.calcSpecificsBox = this.element.querySelector('.calc-specifics-box');
+
+    this.treeLeafViewer = new TreeLeafViewer();
+    this.element.querySelector('.tree-leaf-viewer-host').
+      appendChild(this.treeLeafViewer.element);
+
+    this.vizBox = this.element.querySelector('.viz-box');
+
+    // For static ones
+    InfoSys.addToInfoSystem(this.element);
+  }
+
+
+  setMaterialData() {
+    let data = DataStore.getMaterialData();
+    super.setMaterialData(data);
+    this.isBulk = (data.system_type === 'bulk');
+
+    this.systemTypeField.textContent= data.system_type;
+    this.structTypeField.style.display =
+      (this.isBulk && data.structure_type !== null ? 'block' : 'none');
+    this.structPrototypeField.style.display =
+      (this.isBulk && data.structure_prototype !== null ? 'block' : 'none');
+    this.strukturberichtField.style.display =
+      (this.isBulk && data.strukturbericht_designation !== null ? 'block' : 'none');
+
+    this.lowerBox.style.display = (this.isBulk ? 'flex' : 'none');
+
+    if (this.isBulk){
+      this.structTypeValue.textContent= data.structure_type;
+      this.structPrototypeValue.textContent= data.structure_prototype;
+      this.strukturberichtValue.textContent= data.strukturbericht_designation;
+      this.spaceGroupValue.textContent = data.space_group_number
+        +' ('+data.space_group_international_short_symbol+')';
+      this.pointGroupValue.textContent = data.point_group;
+      this.latticeValue.textContent = data.crystal_system;
+
+      // wyckoff processing
+      let wyckoffMap = new Map();
+      let valueSet= new Set();
+
+      for (var i = 0; i < data.elements.length; i++) {
+        let element = util.ELEMENTS[data.elements[i].label-1];
+        if (wyckoffMap.has(element)){
+          wyckoffMap.get(element).add(data.elements[i].wyckoff);
+        }else {
+          let newSet = new Set();
+          newSet.add(data.elements[i].wyckoff);
+          wyckoffMap.set(element, newSet);
+        }
+      }
+      let wyckoffHTML= '';
+      wyckoffMap.forEach((posSet, element) => {
+        let firstPos = true;
+        wyckoffHTML += '<tr> <td>'+element+': </td>';
+        posSet.forEach( pos => {
+          if (firstPos){
+            firstPos = false;
+            wyckoffHTML += '<td>'+pos+'</td></tr>';
+          }else
+            wyckoffHTML += '<tr><td> </td><td>'+pos+'</td></tr>';
+        });
+      });
+
+      this.wyckoffValue.innerHTML = '<table>' + wyckoffHTML+'</table>';
+    }
+
+    InfoSys.addElementToInfoSystem(this.spaceGroupValue,
+      'space-group.value:'+data.space_group_number);
+    InfoSys.addElementToInfoSystem(this.latticeValue,
+      'crystal-system.value:'+data.crystal_system);
+    InfoSys.addElementToInfoSystem(this.pointGroupValue,
+      'point-group.value:'+data.point_group);
+    //InfoSys.addElementToInfoSystem(this.wyckoffValue, 'wyckoff-position-population.value:'+);
+  }
+
+
+  updateSelection(leafIds /*Set*/) {
+    //console.log('StructureDetails.updateSelection: ', leafIds);
+    if (leafIds.size > 0){
+      this.summaryBox.style.visibility = 'visible';
+
+      let summaryCalcSet = new Set();
+      leafIds.forEach( leafId => {
+        let calc;
+        if (DataStore.getGroups().has(leafId)){
+          calc = DataStore.getCalc(DataStore.getGroups().get(leafId).method_representative);
+        }else
+          calc = DataStore.getCalc(parseInt(leafId));
+        summaryCalcSet.add(calc);
+      });
+
+      let calcMapByFunctional = getCalcMapByFunctional(summaryCalcSet);
+      if (this.summaryByFunctionals === null)
+        this.summaryByFunctionals =
+          new SummaryByFunctionalsComponent(calcMapByFunctional, this.summaryBox);
+      else
+        this.summaryByFunctionals.build(calcMapByFunctional);
+
+      let counter= 0;
+      leafIds.forEach( calcId => {
+        counter++;
+        if (counter === 1) this.firstId = calcId;
+        else if (counter === leafIds.size) this.lastId = calcId;
+      });
+
+    }else{
+      this.summaryBox.style.visibility = 'hidden';
+    }
+
+    function getCalcMapByFunctional(summaryCalcSet){
+
+      let functCalcMap = new Map();
+      summaryCalcSet.forEach( calc => {
+        if (functCalcMap.has(calc.functional_type)){
+          functCalcMap.get(calc.functional_type).add(calc);
+
+        }else{ // New functional
+          let newFunctionalArray = new Set();
+          newFunctionalArray.add(calc);
+          functCalcMap.set(calc.functional_type, newFunctionalArray);
+        }
+      });
+      //console.log('functCalcMap: ',functCalcMap);
+      return functCalcMap;
+    }
+  }
+
+
+  updateMarkedLeaf(leafId){
+
+    if (leafId !== null){
+      this.calcSpecificsBox.style.visibility = 'visible';
+      //this.calcSpecificsBox.style.backgroundColor= '#FFF7EB';
+
+      if (DataStore.getGroups().has(leafId)){
+        this.leafTitle.innerHTML = leafId+
+          ' ('+DataStore.getGroups().get(leafId).calcs.size+')';
+      }else
+        this.leafTitle.innerHTML = leafId;
+
+    }else
+      this.calcSpecificsBox.style.visibility = 'hidden';
+      //this.calcSpecificsBox.style.backgroundColor= 'white';
+      //this.leafTitle.innerHTML = 'NO SELECTION';
+
+    this.treeLeafViewer.update(leafId, DataStore.getGroups().get(leafId));
+  }
+
+}
+
+
+class TreeLeafViewer{
+
+  constructor(hostClass){
+    this.groupCalcs = null;
+    this.element = document.createElement('div');
+    this.element.innerHTML = `
+    <div>
+
+      <div class="group-components" style="display: none">
+        <div style="padding: 10px 0 30px 10px; " class="eos-host">
+        </div>
+
+        <div style="padding-top: 10px; " class="calc-selector-host">
+        </div>
+      </div>
+
+      <div class="info-fields">
+        <div><b>Lattice constants</b></div>
+        <div class="latt-constants"></div>
+        <div class="volume-field"><b><span info-sys-data="cell-volume">Volume</span></b>:
+          <span class="volume-value" ></span>
+        </div>
+        <!-- <div><b>Pressure</b>: <span class="" ></span>  </div>-->
+        <div class="density-field"><b>Density</b>:
+            <div class="stats-fields" >
+              <span info-sys-data="mass-density">Mass density</span> =
+              <span class="mass-density-value" ></span>
+            </div>
+            <div class="stats-fields" >
+              <span info-sys-data="atomic-density">Atomic density</span> =
+              <span class="atomic-density-value" ></span>
+            </div>
+        </div>
+
+        <div class="energy-field"><b><span info-sys-data="energies">Energies</span></b> (code-specific)</div>
+        <div class="energy-descomp"> </div>
+
+        <div class="wyckoff-pos-calc-field" >
+          <b><span info-sys-data="free-wyckoff-parameters">Wyckoff sites</span></b>
+          (fractional coordinates)
+          <div class="wyckoff-pos-calc-table"> </div>
+        </div>
+
+      </div>
+
+    </div>
+    `;
+
+    this.groupComponents = this.element.querySelector('.group-components');
+
+    this.calcSelector = new CalcSelectorBar('calc-selector-bar','60%');
+    this.element.querySelector('.calc-selector-host').
+      appendChild(this.calcSelector.element);
+
+    this.lattConstantsField = this.element.querySelector('.latt-constants');
+    this.volumeField = this.element.querySelector('.volume-field');
+    this.volumeValue = this.element.querySelector('.volume-value');
+    this.densityField = this.element.querySelector('.density-field');
+    this.massDensityValue = this.element.querySelector('.mass-density-value');
+    this.atomicDensityValue = this.element.querySelector('.atomic-density-value');
+
+    this.energyField= this.element.querySelector('.energy-field');
+    this.energyDescompValue= this.element.querySelector('.energy-descomp');
+
+    this.wyckoffPosField = this.element.querySelector('.wyckoff-pos-calc-field');
+    this.wyckoffPosTable = this.element.querySelector('.wyckoff-pos-calc-table');
+
+    this.eosViewer = new EquationOfStateViewer();
+    this.eosViewer.attach(this.element.querySelector('.eos-host'),320, 280);
+
+     this.eosViewer.setClickPointListener( calc => {
+      this.groupCalcUpdate(calc+'');
+    });
+
+    InfoSys.addToInfoSystem(this.element);
+
+    this._events();
+  }
+
+
+  _events() {
+
+    this.calcSelector.setPrevListener(e => {
+      //console.log('calcSelectorPrevBtn');
+      if (this.groupIndex > 0){
+        this.groupCalcUpdate(this.groupCalcs[--this.groupIndex]+'');
+        return this.groupIndex === 0; // the first
+      }
+    });
+
+    this.calcSelector.setNextListener( e => {
+      //console.log('calcSelectorNextBtn');
+      if (this.groupIndex < this.groupCalcs.length-1){
+        this.groupCalcUpdate(this.groupCalcs[++this.groupIndex]+'');
+        return this.groupIndex === this.groupCalcs.length-1; // the last
+      }
+    });
+
+  }
+
+
+  update(leafId, groupData){
+
+    this.representative = leafId;
+    this.isGroup = false;
+    //console.log('SET: ',groupData);
+    if (groupData !== undefined){
+
+      this.groupCalcs = Array.from(groupData.calcs);
+      this.groupIndex = this.groupCalcs.indexOf(
+        DataStore.getCalcReprIntId(this.representative));
+
+      this.isGroup = true;
+      this.groupComponents.style.display = 'block';
+
+      this.eosViewer.clear();
+      let pointsX = [], pointsY = [];//, calcIds = [];
+
+      this.groupCalcs.forEach( calcId => {
+        //calcIds.push(calcId);
+        let calc = DataStore.getCalc(calcId);
+        //console.log('CALC: ', calcId, calc);
+        pointsX.push(calc.cell_volume/1e-30);
+        let yVal = 555; // Trick: signal value
+        calc.energy.forEach( e => {
+          if (e.e_kind === 'Total E'){
+            yVal = e.e_val/1.602176565e-19;
+          }
+        });
+        pointsY.push(yVal);
+      });
+
+      // Method re
+      let mReprCalc = DataStore.getCalc(groupData.method_representative);
+      //console.log('mReprCalc: ', mReprCalc);
+      let eZero;
+      mReprCalc.energy.forEach( e => {
+        if (e.e_kind === 'Total E')
+          eZero = e.e_val/1.602176565e-19;
+      });
+      //console.log('CALC: ', pointsX, pointsY, groupCalcsForChart);
+      this.eosViewer.draw(pointsX, pointsY, this.groupCalcs, eZero);
+
+    }else{
+      this.groupComponents.style.display = 'none';
+    }
+    this.groupCalcUpdate(leafId);
+  }
+
+
+  groupCalcUpdate(leafId){
+
+    if (leafId !== null){
+
+      let calcId = DataStore.getCalcReprIntId(leafId);
+      if (this.groupCalcs !== null){
+        this.groupIndex = this.groupCalcs.indexOf(calcId);
+        if (this.groupIndex >= 0){
+          let t = calcId+' ('+(this.groupIndex+1)+'/'+this.groupCalcs.length+')';
+          this.calcSelector.setState(t, this.groupIndex === 0,
+            this.groupIndex === this.groupCalcs.length-1);
+
+          this.eosViewer.selectCalc(calcId);
+        }
+      }
+
+      //console.log('LEAF UPDATE', calc.id, this.groupIndex);
+      let is2Dsystem = (DataStore.getMaterialData().system_type === '2D');
+      let isBulk = (DataStore.getMaterialData().system_type === 'bulk');
+      let calc = DataStore.getCalc(calcId);
+      let lattParams= util.getNumberArray(calc.lattice_parameters);
+
+      let lattCFieldHTML = ((is2Dsystem  || isBulk) ?
+        `<div>b = ${util.m2Angstrom(lattParams[1])}</div>` : '');
+      lattCFieldHTML += (isBulk ?
+        `<div>c = ${util.m2Angstrom(lattParams[2])}</div>` : '');
+
+      let lattBetaGammaFieldHTML = ((is2Dsystem  || isBulk) ?
+          `<div>&alpha; = ${util.rad2degree(lattParams[3])}</div>` : '');
+
+      lattBetaGammaFieldHTML += (isBulk ?
+          `<div>&beta; = ${util.rad2degree(lattParams[4])}</div>
+          <div>&gamma; = ${util.rad2degree(lattParams[5])}</div>` : '');
+
+      this.lattConstantsField.innerHTML= `
+        <div style="float: left; ">
+          <div>a = ${util.m2Angstrom(lattParams[0])}</div>
+          ${lattCFieldHTML}
+        </div>
+        <div style="float: left; padding-left: 40px;">
+          ${lattBetaGammaFieldHTML}
+        </div>
+        <div style="clear: both;padding: 0"></div>
+      `;
+
+      this.densityField.style.display = (isBulk ? 'block' : 'none');
+      this.volumeField.style.display = (isBulk ? 'block' : 'none');
+      if (isBulk){ // bulk type
+        this.volumeValue.innerHTML= util.m3ToAngstrom3(calc.cell_volume);
+      //this.pressureCalcField.textContent= calc.pressure;
+        this.atomicDensityValue.innerHTML= util.toAngstromMinus3(calc.atomic_density);
+        this.massDensityValue.innerHTML= calc.mass_density.toFixed(1)+' kg/m<sup>3</sup>';
+      }
+
+      let r= util.serverReq(util.getCalcEnergiesURL(DataStore.getMaterialData().id, calc.id), () => {
+        let value = false;
+        if (r.status === 200){
+          let energies= JSON.parse(r.response).results;
+          for (var i = 0; i < energies.length; i++)
+            if (energies[i].e_kind === 'Total E'){
+              value = true;
+              this.energyDescompValue.innerHTML =
+                '<div>Total E = &nbsp; '+util.J2eV(energies[i].e_val)+' eV</div>';
+            }
+        }
+        this.energyField.style.display = (value ? 'block' : 'none');
+        this.energyDescompValue.style.display = (value ? 'block' : 'none');
+      });
+
+      let thereIsWyckoffData =
+        (DataStore.getMaterialData().has_free_wyckoff_parameters
+          && calc.wyckoff_groups_json.length > 0);
+
+      this.wyckoffPosField.style.display = (thereIsWyckoffData ? 'block' : 'none');
+
+      if (thereIsWyckoffData){
+        let wyckoffMap = new Map(); // Map(element, Array of pairArray[w-pos, coor])
+        calc.wyckoff_groups_json.forEach( d => {
+          // Only entries having items in .variables are included
+          if (  Object.keys(d.variables).length !== 0 ){
+
+            let varsHtml = '';
+            //d.variables.forEach( v => { varsHtml += '<p>'+v+'</p>'; } );
+            for (let v in d.variables) {
+              varsHtml += ''+v+' = '+d.variables[v].toFixed(2)+'<br>';
+            }
+
+            let wyckoffVarsPair = [];
+            wyckoffVarsPair.push(d.wyckoff_letter);
+            wyckoffVarsPair.push(varsHtml);
+
+            if (wyckoffMap.has(d.element)){
+              wyckoffMap.get(d.element).push(wyckoffVarsPair);
+            }else {
+              wyckoffMap.set(d.element, [wyckoffVarsPair]);
+            }
+          }
+
+        });
+        //console.log('wyckoffMap', wyckoffMap);
+
+        let wyckoffHTML= '';
+        wyckoffMap.forEach((posSet, element) => {
+
+          posSet.sort( (a, b) => {
+            return (a[0] > b[0] ? 1 : -1);
+          });
+
+          let firstPos = true;
+          wyckoffHTML += '<tr > <td style="width: 30%;">'+element+' </td>';
+          posSet.forEach( pos => {
+            if (firstPos){
+              firstPos = false;
+              wyckoffHTML += '<td style="width: 30%; ">'+pos[0]+'</td><td style="width: 40%;">'+pos[1]+'</td></tr>';
+            }else
+              wyckoffHTML += '<tr><td> </td><td>'+pos[0]+'</td><td>'+pos[1]+'</td></tr>';
+          });
+        });
+
+        this.wyckoffPosTable.innerHTML = '<table id="calc-wyckoff">' + wyckoffHTML+'</table>';
+
+/*
+        for (var i = 0; i < data.elements.length; i++) {
+          let element = util.ELEMENTS[data.elements[i].label-1];
+          if (wyckoffMap.has(element)){
+            wyckoffMap.get(element).add(data.elements[i].wyckoff);
+          }else {
+            let newSet = new Set();
+            newSet.add(data.elements[i].wyckoff);
+            wyckoffMap.set(element, newSet);
+          }
+        }
+        */
+
+      }
+
+
+    }else{
+      console.log('THIS dOESNT BE REACHED');
+    }
+  }
+
+}
+
+
+class SummaryByFunctionalsComponent{
+
+  constructor(calcMapByFunctional, hostElement){
+    this.calcMapByFunctional = calcMapByFunctional;
+    this.hostElement = hostElement;
+    this.graphTrigger = null;
+    this.viewType = 'text';
+    this.functional = null;
+    this.hostElement.innerHTML+=`
+      <div style="float: left" >
+        <svg xmlns="http://www.w3.org/2000/svg" class="chart-tab"
+          viewBox="0 0 15 15" width="15" height="15" style="fill: #c7c7c7;">
+            <rect x="0" y="0"  width="2" height="15" />
+            <rect   x="3" y="5"  width="1.8" height="7"  />
+            <rect  x="6" y="3"  width="1.8" height="9"  />
+            <rect   x="9" y="6"  width="1.8" height="6"  />
+            <rect  x="12" y="2"  width="1.8" height="10"  />
+            <rect x="2" y="13"   width="13" height="2" />
+        </svg>
+        <svg xmlns="http://www.w3.org/2000/svg" class="text-tab"
+          viewBox="0 0 15 15" width="15" height="15" style="fill: #777;">
+            <rect x="0" y="1"   width="15" height="2.5" />
+            <rect   x="0" y="6"  width="15" height="2.5"  />
+            <rect  x="0" y="11"  width="15" height="2.5"  />
+        </svg>
+      </div>
+
+      <div class="functional-tabs" style="float: right">
+      </div>
+
+      <div style="clear: both;"></div>
+
+      <div class="content-placeholder" >
+
+        <div style="display: block" class="text-panel" >
+          <div><b>Lattice constants</b>:
+            <div class="stats-fields latt-constants-field" >
+            </div>
+          </div>
+          <div class="volume-field"><b><span info-sys-data="cell-volume">Volume</span></b> (&#197;<sup>3</sup>):
+            <div class="stats-fields volume-value" > </div>
+          </div>
+          <div class="density-field"><b>Density</b> :
+            <div >
+              <div class="stats-fields" >
+                <span info-sys-data="mass-density">Mass density</span> (kg/m<sup>3</sup>) =
+                <span class="mass-density-value" ></span>
+              </div>
+              <div class="stats-fields" >
+                <span info-sys-data="atomic-density">Atomic density</span> (&#197;<sup>-3</sup>) =
+                <span class="atomic-density-value" ></span>
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <div style="display:none" class="chart-panel" >
+          <div class="charts-placeholder" > </div>
+          <div class="charts-selector" >
+
+          </div>
+        </div>
+
+      </div>
+    `;
+    this.chartTab = this.hostElement.querySelector('.chart-tab');
+    this.textTab = this.hostElement.querySelector('.text-tab');
+    this.functionalTabs = this.hostElement.querySelector('.functional-tabs');
+    this.chartPanel = this.hostElement.querySelector('.chart-panel');
+    this.textPanel = this.hostElement.querySelector('.text-panel');
+    this.lattConstantsField = this.hostElement.querySelector('.latt-constants-field');
+    this.volumeField = this.hostElement.querySelector('.volume-field');
+    this.volumeFieldValue = this.hostElement.querySelector('.volume-value');
+    this.densityField = this.hostElement.querySelector('.density-field');
+    this.massDensityValue = this.hostElement.querySelector('.mass-density-value');
+    this.atomicDensityValue = this.hostElement.querySelector('.atomic-density-value');
+
+
+    this.calcMapByFunctional.forEach( (calcs, functionalName) =>{
+      this.functionalTabs.innerHTML +=
+        '<span class="tab" data-tab="'+functionalName+'">'+functionalName+'</span>';
+    });
+
+
+    this.statsViewer = new StatsViewer();
+    let chartsPlaceholder = this.hostElement.querySelector('.charts-placeholder');
+    this.statsViewer.attach(chartsPlaceholder, 350, 200);
+
+    this.chartsSelector = this.hostElement.querySelector('.charts-selector');
+
+    this.build(calcMapByFunctional);
+
+    this.chartTab.addEventListener( "click", e => {
+      this.chartTab.style.fill = '#777';
+      this.viewType = 'chart';
+      this.textTab.style.fill = '#c7c7c7';
+      this.chartPanel.style.display = 'block';
+      this.textPanel.style.display = 'none';
+    });
+
+    this.textTab.addEventListener( "click", e => {
+      this.textTab.style.fill = '#777';
+      this.viewType = 'text';
+      this.chartTab.style.fill = '#c7c7c7';
+      this.textPanel.style.display = 'block';
+      this.chartPanel.style.display = 'none';
+    });
+
+    this.functionalTabs.addEventListener( "click", e => {
+      if (e.target.className === 'tab'){
+        this.statsViewer.clear();
+        this.functionalTabs.querySelector('[data-tab="'+this.functional+'"]')
+          .className = 'tab';
+        this.functional = e.target.getAttribute('data-tab');
+        this.functionalTabs.querySelector('[data-tab="'+this.functional+'"]')
+          .className = 'tab-selected';
+        this._setData();
+      }
+    });
+
+    this.chartsSelector.addEventListener( "click", e => {
+      if (e.target.className.indexOf('quantity') === 0){
+        this.statsViewer.clear();
+        let quantity = e.target.getAttribute('data-quantity');
+        let stats = this.functionalQuantityMap.get(this.functional).get(quantity);
+        this.statsViewer.drawPoints(stats.data, stats.label, stats.min, stats.max);
+
+        this.chartsSelector.querySelector('.quantity-selected').className = 'quantity';
+        e.target.className = 'quantity-selected';
+      }
+    });
+
+  }
+
+  _setData(){
+    let is2Dsystem = (DataStore.getMaterialData().system_type === '2D');
+    let isBulk = (DataStore.getMaterialData().system_type === 'bulk');
+    let statsMap = this.functionalQuantityMap.get(this.functional);
+
+    let lattCFieldHTML = ((is2Dsystem || isBulk) ?
+      `<div>b (&#197;) = ${statsMap.get('lattice_b').html}</div>` : '');
+
+    lattCFieldHTML += (isBulk ?
+      `<div>c (&#197;) = ${statsMap.get('lattice_c').html}</div>` : '');
+    // Set text data
+    this.lattConstantsField.innerHTML = `
+      <div style="float: left; ">
+        <div>a (&#197;) = ${statsMap.get('lattice_a').html}</div>
+        ${lattCFieldHTML}
+      </div>
+      <div style="float: left; padding-left: 40px;">
+        ${util.getLatticeAnglesValues(
+          this.calcMapByFunctional.get(this.functional), is2Dsystem, isBulk)}
+      </div>
+      <div style="clear: both;padding: 0"></div>
+      `;
+
+    let chartSelectorHTML= `
+    <span class="quantity-selected" data-quantity="lattice_a">a</span>
+    `;
+
+    if (is2Dsystem || isBulk)
+      chartSelectorHTML += `<span class="quantity" data-quantity="lattice_b">b</span>`;
+
+      //console.log('statsMap', statsMap, statsMap.get('volume'));
+    this.densityField.style.display = (isBulk ? 'block' : 'none');
+    this.volumeField.style.display = (isBulk ? 'block' : 'none');
+    if (isBulk){ // bulk type
+      this.volumeFieldValue.innerHTML = statsMap.get('volume').html;
+      this.massDensityValue.innerHTML = statsMap.get('mass_density').html;
+      this.atomicDensityValue.innerHTML = statsMap.get('atomic_density').html;
+      chartSelectorHTML += `
+        <span class="quantity" data-quantity="lattice_c">c</span>
+        <span class="quantity" data-quantity="volume">volume</span>
+        <span class="quantity" data-quantity="mass_density">mass density</span>
+        <span class="quantity" data-quantity="atomic_density">atomic density</span>
+      `;
+    }
+
+    this.chartsSelector.innerHTML = chartSelectorHTML;
+
+    // Set Charts data
+    let stats = statsMap.get('lattice_a');
+    this.statsViewer.drawPoints(stats.data, stats.label, stats.min, stats.max);
+  }
+
+
+
+  build(calcMapByFunctional){
+    this.calcMapByFunctional = calcMapByFunctional;
+    this.graphTrigger = null;
+    this.statsViewer.clear();
+    //this.functional = null;
+    //this.functionalTabs.innerHTML = '';
+    this.unfoldedElement = null;
+    this.functionalQuantityMap = new Map();
+
+    // Hide and deselect all the tabs before knowing the active ones
+    for (var i = 0; i < this.functionalTabs.children.length; i++) {
+      //console.log('functionalTabs',this.functionalTabs.children[i]);
+      this.functionalTabs.children[i].style.display = 'none';
+      this.functionalTabs.children[i].className = 'tab';
+    }
+
+    // For each active functional
+    this.calcMapByFunctional.forEach( (calcs, functionalName) =>{
+      let statsMap = util.getQuantityStatsMap(calcs);
+      this.functionalQuantityMap.set(functionalName, statsMap);
+      //show the active ones
+      this.functionalTabs.querySelector('[data-tab="'+functionalName+'"]')
+          .style.display = 'inline';
+    });
+
+    // Select the selected functional
+    let functionals = Array.from( this.calcMapByFunctional.keys() );
+    // If there isn't selected functional or the current functional is not active
+    if (this.functional === null || functionals.indexOf(this.functional) < 0)
+      this.functional = functionals[0]; // the first one is selected
+    this._setData();
+    this.functionalTabs.querySelector('[data-tab="'+this.functional+'"]')
+      .className = 'tab-selected';
+
+    InfoSys.addToInfoSystem(this.hostElement);
+  }
+
+}
+
+
+// EXPORTS
+module.exports = StructureDetails;
+
+
+/***/ }),
+/* 24 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+ /*
+  Equation of State plotter implementation
+ */
+
+
+
+let svg = __webpack_require__(2);
+let PlotterBase = __webpack_require__(5);
+
+
+class EquationOfStateViewer extends PlotterBase{
+
+  constructor() {
+    super({left: 60, right: 20, top: 30, bottom: 40});
+    this.tooltip;
+    this.calcPointMap= new Map();
+    this.pointSelected = null;
+  }
+
+
+  draw(pointsX, pointsY, calcIds, eZero){
+
+    for (let i = 0; i < pointsY.length; i++) {
+      if (pointsY[i] !== 555) pointsY[i] -= eZero;
+    }
+
+    function remove555(points){
+      let goodPoints = [];
+      points.forEach( p => {
+        if (p !== 555) goodPoints.push(p);
+      });
+      return goodPoints;
+    }
+    let goodPointsY = remove555(pointsY);
+
+    let xMin = Math.min.apply(null,pointsX);
+    let xMax = Math.max.apply(null,pointsX);
+    let yMin = 0;
+    let yMax = Math.max.apply(null,goodPointsY);
+
+    if (xMin === xMax) { xMin -= 1; xMax += 1; }
+    else{
+      let gap = xMax - xMin;
+      xMin -= gap*0.1; xMax += gap*0.1;
+    }
+    if (yMin === yMax) { yMin -= 1; yMax += 1; }
+    else{
+      let gap = yMax - yMin;
+      yMin -= gap*0.15; yMax += gap*0.1;
+    }
+
+    this.setRangeAndLabels('Volume (ų)', xMin, xMax,'E - Eₘᵢₙ (eV)', yMin, yMax);
+    this.drawAxis(2, null);
+    // Y axis labels drawing
+    let self = this;
+    function drawYAxisLabel(element, y){
+      let pixelY = self.y(y);
+      svg.addLine(element, 0, pixelY, -3, pixelY, 1);
+      let numberToPaint= -(pixelY/self.yRel) + self.yMin;
+      svg.addText(element,-5, pixelY+3, numberToPaint.toFixed(3), 'end', 'statisticsviewersteps');
+    }
+    drawYAxisLabel(this.plotArea, 0);
+    drawYAxisLabel(this.plotArea, yMax/2);
+    drawYAxisLabel(this.plotArea, yMax);
+
+    // zero line drawing
+    svg.addLine(this.plotArea, 0, this.y(0), this.plotRangeX, this.y(0), 'zeroline');
+
+    svg.addText(this.plotArea, this.x(xMax),
+      this.y(0)+12, 'Eₘᵢₙ: '+eZero.toFixed(3)+' eV', 'end', 'axis-steps');
+    // points drawing
+    for (let i = 0; i < pointsX.length; i++) {
+
+      let styleClass = (i === 0 ? 'eos-viewer-sel' : 'eos-viewer');
+      let r = (i === 0 ? 6 : 3);
+      let yVal = (pointsY[i] === 555 ? 20 : this.y(pointsY[i])); // Trick
+	    let pointElement =
+        svg.addPoint(this.plotArea,this.x(pointsX[i]), yVal, r
+        , styleClass);
+      if (i === 0) this.pointSelected = pointElement;
+
+	    pointElement.addEventListener('mouseover', e => {
+		    this.tooltip = svg.addText(this.plotArea, e.target.getBBox().x+10,
+          e.target.getBBox().y-10, 'Calc '+calcIds[i], 'middle', 'tooltip');
+      });
+	    pointElement.addEventListener('mouseout', e => {
+		    svg.removeElement(this.tooltip);
+	    });
+      pointElement.addEventListener('click', e => {
+		    //console.log('ID',calcIds[i]);
+        this.clickPointListener(calcIds[i]);
 	    });
-	*/
+      this.calcPointMap.set(calcIds[i], pointElement);
 	  }
+  }
 
 
-
-	  updateSelection( leafIds /*Set*/){
-	    console.log('ElasticDetails updateSelection ',leafIds);
-
-	  }
+  selectCalc(calcId){
+    this.pointSelected.setAttribute('class', 'eos-viewer');
+    this.pointSelected.setAttribute('r', 3);
+    this.pointSelected = this.calcPointMap.get(calcId);
+    this.pointSelected.setAttribute('class', 'eos-viewer-sel');
+    this.pointSelected.setAttribute('r', 6);
+  }
 
 
-	  updateMarkedLeaf(leafId){
+  setClickPointListener(listener){
+    this.clickPointListener = listener;
+  }
 
-	/* Do nothing for now...
-	    this.markedCalc = leafId;
-	    let rowElement= this.element.querySelector('.data-row-marked');
-	    if (rowElement !== null) rowElement.className= 'data-row';
 
-	    if (this.markedCalc  !== null){
-	      let rowElement1= document.querySelector('tr[data-calc-id="'+this.markedCalc+'"]');
-	      if (rowElement1 !== null) rowElement1.className= 'data-row-marked';
-	    }
-	    */
-	  }
+  x(x){
+    return this.xRel*(x - this.xMin);
+  }
 
-	}
 
+  y(y){
+    return -this.yRel*(y - this.yMin);
+  }
 
-	// EXPORTS
-	module.exports = ElasticConstDetails;
+}
 
 
-/***/ },
-/* 32 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-	   This file implements the Search Module of the application.
-	   It's a container UI component that shows the seach part of the application:
-	   front search interface and search results page.
-	 */
-
-	"use strict";
-
-	let util = __webpack_require__(1);
-	let UserGuidance = __webpack_require__(33);
-	let ElementTable = __webpack_require__(34);
-	let MaterialList = __webpack_require__(35);
-	//let PropertiesBox = require('./PropertiesBox.view.js');
-	let FilterPanel = __webpack_require__(36);
-	let SwitchComponent = __webpack_require__(13);
-
-
-
-	// local utility functions
-	function getTagHtml(tag, isFormula){
-	  return `<span class="search-label" data-el="${tag}" >
-	            <img src="img/${isFormula ? 'info' : 'tag'}.svg" height="16px" class="remove-label"
-	              style="vertical-align: bottom"/>
-	          ${isFormula ? util.getSubscriptedFormula(tag) : tag}
-	          <img src="img/cross.svg" height="6px" class="remove-label"
-	            style="vertical-align: middle; padding: 4px 3px 6px 5px;" />
-	          </span>`;
-	}
 
+// EXPORTS
+module.exports = EquationOfStateViewer;
 
-	function replaceDashes(s){
-	  return s.split('-').join('_');
-	}
+
+/***/ }),
+/* 25 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+ /*
+  'Details' view container that shows all the material info related to
+  its electronic structure.
+
+  This container is quite complex.
+
+  In the file there are two defined (classes) components used in the container:
+  - SummaryByFunctionalsComponent: the component (left panel, below part)
+  showing a band gap summary info by functional.
+  - BZViewerWrapper: This component is a wrapper for the Brillouin zone viewer
+ */
+
+
+
+let DetailsViewBase = __webpack_require__(6);
+let util = __webpack_require__(0);
+let InfoSys = __webpack_require__(3);
+let CalcSelectorBar = __webpack_require__(13);
+let StatsViewer = __webpack_require__(14);
+let BSDOSPlotter = __webpack_require__(26);
+let PlotterBase = __webpack_require__(5);
+let plotter= new PlotterBase();
+let DataStore = __webpack_require__(1);
+let LoadingPopup = __webpack_require__(4);
+
+function setFermiVizContent(fermiBox,url){
+  let sceneContent;
+  if (url === ''){
+    fermiBox.innerHTML= '';//fermiBox.removeChild(plotter.canvas);
+    plotter.attach(fermiBox,undefined,316);
+    plotter.setNoData();
+  }
+  else{
+    sceneContent= '<inline url="'+url+'"> </inline>';
+    fermiBox.innerHTML=
+      `<x3d id="x3dframe" width='290px' height='290px' >
+        <scene>${sceneContent} </scene>
+      </x3d>`;
+    x3dom.reload();
+  }
+
+}
+
+class ElectronicStructDetails  extends DetailsViewBase{
+
+  constructor() {
+    super('Electronic Structure');
+    this.firstId;
+    this.lastId;
+    this.element.innerHTML+=`
+      <div style="float: left; width: 30%;">
+        <div class="view-box">
+          <div class="title">Calculations </div>
+          <div class="navTreeWrapper"></div>
+
+
+          <div class="summary-title">Summary</div>
+          <div class="footer summary-box" style="border-top: 0">
+          </div>
+        </div>
+      </div>
+
+      <div style="float: right; width: 70%;">
+        <div class="view-box e-structure-box">
+
+          <div class="title">Electronic structure</div>
+
+          <div style="padding-top: 10px;">
+            <div class="calc-selector-host"></div>
+          </div>
+
+
+          <div>
+
+            <div  style="padding: 30px  100px 20px 100px; ">
+              <div class="info-fields-label" style="float: left; width: 54%; ">
+                <span info-sys-data="band-structure">Band structure</span>
+              </div>
+              <div class="info-fields-label" style="float: left;">
+                <span info-sys-data="DOS">DOS</span>
+              </div>
+              <div style="clear: both;"></div>
+
+              <div class="calc-bs-dos-plotter" >
+              </div>
+
+              <div>
+              <div class="band-gap-field" style="float: left; width: 56%; text-align: right">
+                <b><span info-sys-data="band-gap">Band gap</span></b>:
+                <span class="band-gap-value" ></span>
+              </div>
+              <div style="clear: both;"></div>
+
+              </div>
+            </div>
+
+            <div class="spin-legend" style="font-size: 0.9em; padding: 0 30px 10px; display: none">
+              <svg width="15px" height="10px"> <polyline points="0,5 15,5" class="plotSpin1"/></svg>
+              Spin <span style='font-size: 1.1em'>⇧</span>  &nbsp;&nbsp;&nbsp;
+              <svg width="15px" height="10px"> <polyline points="0,5 15,5" class="plotSpin2"/></svg>
+              Spin <span style='font-size: 1.1em'>⇩</span>
+            </div>
+
+          </div>
+
+          <div class="footer lower-section">
+
+            <div  style="float: left">
+              <div style="padding: 16px; ">
+                <div class="info-fields-label" >
+                  <span info-sys-data="brillouin-zone-viewer">Brillouin zone</span>
+                </div>
+                <div class="bz-viewer-wrapper" style="width: 400px; height: 400px">
+                </div>
+              </div>
+            </div>
+
+            <div class="band" style="float: right; width: 40%;">
+              <div style="padding: 16px; ">
+                <div class="info-fields-label" >
+                  <!-- <span info-sys-data="fermi-surface">Fermi surface </span> -->
+                </div>
+                <div class="fermi-box" >      </div>
+              </div>
+            </div>
+
+            <div style="clear: both;"></div>
+
+          </div> <!-- footer -->
+
+        </div>
+
+      </div> <!-- view-box -->
+    `;
+
+    this.navTreeWrapper =
+        this.element.getElementsByClassName("navTreeWrapper")[0];
+
+    //this.leafTitle = this.element.querySelector('.tree-leaf-title');
+    this.calcSelector = new CalcSelectorBar('calc-selector-bar','70%');
+    this.element.querySelector('.calc-selector-host').
+      appendChild(this.calcSelector.element);
+
+    this.rightBox = this.element.querySelector('.e-structure-box');
+
+    this.summaryByFunctionals = null;
+
+    this.bsDosPlotter = new BSDOSPlotter();
+
+    this.bandGapField = this.element.querySelector('.band-gap-field');
+    this.bandGapValue = this.element.querySelector('.band-gap-value');
+
+    this.spinLegend = this.element.querySelector('.spin-legend');
+
+    this.lowerSection = this.element.querySelector('.lower-section');
+
+    this.fermiBox= this.element.getElementsByClassName('fermi-box')[0];
+    // Load the x3dom library
+    util.loadLib("lib/x3dom.js");
+
+    this.bzViewerWrapper = this.element.querySelector('.bz-viewer-wrapper');
+    this.bzViewerWrapper = new BZViewerWrapper(this.bzViewerWrapper);
+
+    // For static ones
+    InfoSys.addToInfoSystem(this.element);
+
+    this._events();
+  }
+
+  _events() {
+    //super._events();
+
+    this.calcSelector.setPrevListener(e => {
+      if (this.groupIndex > 0){
+        let calcId = this.groupCalcs[--this.groupIndex];
+        this._loadGraphData(calcId);
+        this._updateSelectorState(calcId);
+        return this.groupIndex === 0; // the first
+      }
+    });
+
+    this.calcSelector.setNextListener( e => {
+      if (this.groupIndex < this.groupCalcs.length-1){
+        let calcId = this.groupCalcs[++this.groupIndex];
+        this._loadGraphData(calcId);
+        this._updateSelectorState(calcId);
+        return this.groupIndex === this.groupCalcs.length-1; // the last
+      }
+    });
+  }
+
+
+  updateSelection(leafIds/*Set*/){
+    //console.log('E-StructureDetails UPDATING calcs: ',calcs.values().next().value);
+    if (leafIds.size > 0){
+      this.rightBox.style.visibility = 'visible';
+      //console.log('E-StructureDetails UPDATING calcs:leafIds.size > 0 ',leafIds);
+      let calcMapByFunctional = getCalcMapByFunctional(leafIds);
+      if (this.summaryByFunctionals === null)
+        this.summaryByFunctionals =
+          new SummaryByFunctionalsComponent(calcMapByFunctional,
+            this.element.querySelector('.summary-box'));
+      else
+        this.summaryByFunctionals.build(calcMapByFunctional);
+      // let bandGapDirect= calcs.values().next().value.band_gap_direct;
+      //let bandGapType= (bandGapDirect ? "direct" : "indirect");
+
+      let counter= 0;
+      leafIds.forEach( calcId => {
+        counter++;
+        if (counter === 1) this.firstId = calcId;
+        if (counter === leafIds.size) this.lastId = calcId;
+      });
+    }else
+      this.rightBox.style.visibility = 'hidden';
+
+    function getCalcMapByFunctional(leafIds/*Set*/){
+      let functCalcMap = new Map();
+      leafIds.forEach( leafId => {
+        let calc = DataStore.getCalc(DataStore.getCalcReprIntId(leafId));
+        if (calc.has_band_structure){
+          //console.log('CALC BS ',calc.band_gap,calc.band_gap_direct);
+          if (functCalcMap.has(calc.functional_type)){
+            functCalcMap.get(calc.functional_type).add(calc);
+          }else{ // New functional
+            let newFunctionalArray = new Set();
+            newFunctionalArray.add(calc);
+            functCalcMap.set(calc.functional_type, newFunctionalArray);
+          }
+        }
+      });
+      return functCalcMap;
+    }
+
+  }
+
+
+
+  updateMarkedLeaf(leafId){
+    //console.log('updateMarkedCalc '+calc);
+    this.groupCalcs = null; // if the leafId is not a group else this.groupCalcs is array
+    if (leafId === null){
+      //this.leafTitle.innerHTML = 'NO SELECTION';
+      this.calcSelector.setState('NO SELECTION', true, true);
+      return;
+
+    }else{
+      if (DataStore.getGroups().has(leafId)){
+        //this.leafTitle.innerHTML = leafId+' ('+DataStore.getGroups().get(leafId).calcs.size+')';
+        this.groupCalcs =  Array.from(DataStore.getGroups().get(leafId).calcs);
+        let calcId = DataStore.getCalcReprIntId(leafId);
+        this.groupIndex = this.groupCalcs.indexOf(calcId);
+        this._updateSelectorState(calcId);
+      }else
+        //this.leafTitle.innerHTML = leafId;
+        this.calcSelector.setState(leafId, true, true);
+    }
+
+    this._loadGraphData(DataStore.getCalcReprIntId(leafId));
+
+    // calc.fermi_surface
+
+  }
+
+
+  _updateSelectorState(leafId){
+    let t = leafId+' ('+(this.groupIndex+1)+'/'+this.groupCalcs.length+')';
+    this.calcSelector.setState(t, this.groupIndex === 0,
+      this.groupIndex === this.groupCalcs.length-1);
+  }
+
+
+  _loadGraphData(calcId){
+
+    let calc = DataStore.getCalc(calcId);
+
+    if (!this.bsDosPlotter.isAttached())
+      this.bsDosPlotter.attach(this.element.querySelector('.calc-bs-dos-plotter')
+        ,undefined,360);
+
+    if (calc === null || (!calc.has_band_structure && !calc.has_dos)){
+      this.bsDosPlotter.setNoData();
+      this.bzViewerWrapper.setNoData();
+      this.bandGapField.style.display = 'none';
+      this.lowerSection.style.display = 'none';
+
+    }else{
+      LoadingPopup.show();
+      let matId = DataStore.getMaterialData().id;
+
+      util.serverReq(util.getMaterialCalcURL(matId, calc.id, 'dos'), e1 => {
+        let dosData = JSON.parse(e1.target.response).dos;
+
+        util.serverReq(util.getMaterialCalcURL(matId, calc.id, 'band_structure'),
+        e2 => {
+          let bsData= JSON.parse(e2.target.response).band_structure;
+          if (bothSpins(bsData, dosData))
+            this.spinLegend.style.display = 'block';
+
+          //***util.addBandGapData(calcData, bsData);
+          //console.log('CODE NAME:', calc.code_name);
+          this.bsDosPlotter.setUpAndData(bsData, dosData, calc.code_name );
+
+          if (calc.has_band_structure){
+
+            this.bandGapField.style.display = 'block';
+            this.bandGapValue.textContent= util.J2eV(calc.band_gap, 2)+' eV ';
+            // console.log('calc.brillouin_zone_json',calc.brillouin_zone_json);
+            if (calc.brillouin_zone_json !== null){
+              this.lowerSection.style.display = 'block';
+              this.bzViewerWrapper.setCalcData(calc.brillouin_zone_json, bsData.segments);
+            }else{
+              this.lowerSection.style.display = 'none';
+              this.bzViewerWrapper.setNoData();
+            }
+
+            //this.bzViewerWrapper.setCalcData(calc.brillouin_zone_json, bsData.segments);
+            // if there bandstruc data && calc.band_gap === 0  => show FermiSurface
+            //if (calc.band_gap === 0)
+              //setFermiVizContent(this.fermiBox, (calc === null ? '' : util.FERMI_SURFACE_URL));
+          }else{
+            this.lowerSection.style.display = 'none';
+            this.bandGapField.style.display = 'none';
+            this.bzViewerWrapper.setNoData();
+          }
+          LoadingPopup.hide();
+        });
+      });
+
+    }
+
+    function bothSpins(bsData, dosData){
+      if (bsData !== undefined){
+        if (bsData.segments[0].band_energies.length === 2) return true;
+      }
+      if (dosData !== undefined){
+        if (dosData.dos_values.length === 2) return true;
+      }
+      return false;
+    }
+  }
+
+
+  setPrevCalcListener(listener){
+    this.prevCalcListener= listener;
+  }
+
+
+  setNextCalcListener(listener){
+    this.nextCalcListener= listener;
+  }
+
+}
+
+
+
+class SummaryByFunctionalsComponent{
+
+  constructor(calcMapByFunctional, hostElement){
+    this.calcMapByFunctional = calcMapByFunctional;
+    this.hostElement = hostElement;
+    this.viewType = 'text';
+    this.functional = null;
+    this.hostElement.innerHTML+=`
+      <div style="float: left" >
+        <svg xmlns="http://www.w3.org/2000/svg" class="chart-tab"
+          viewBox="0 0 15 15" width="15" height="15" style="fill: #c7c7c7;">
+            <rect x="0" y="0"  width="2" height="15" />
+            <rect   x="3" y="5"  width="1.8" height="7"  />
+            <rect  x="6" y="3"  width="1.8" height="9"  />
+            <rect   x="9" y="6"  width="1.8" height="6"  />
+            <rect  x="12" y="2"  width="1.8" height="10"  />
+            <rect x="2" y="13"   width="13" height="2" />
+        </svg>
+        <svg xmlns="http://www.w3.org/2000/svg" class="text-tab"
+          viewBox="0 0 15 15" width="15" height="15" style="fill: #777;">
+            <rect x="0" y="1"   width="15" height="2.5" />
+            <rect   x="0" y="6"  width="15" height="2.5"  />
+            <rect  x="0" y="11"  width="15" height="2.5"  />
+        </svg>
+      </div>
+
+      <div class="functional-tabs" style="float: right">
+      </div>
+
+      <div style="clear: both;"></div>
+
+      <div class="content-placeholder" >
+
+        <div style="display: block" class="text-panel" >
+
+          <div><b><span info-sys-data="band gap">Band gap</span></b> (eV):
+            <div class="stats-fields summary-bandgap-field" > </div>
+          </div>
+        </div>
+
+        <div style="display:none" class="chart-panel" >
+          <div class="charts-placeholder" > </div>
+        </div>
+
+      </div>
+    `;
+    this.chartTab = this.hostElement.querySelector('.chart-tab');
+    this.textTab = this.hostElement.querySelector('.text-tab');
+    this.functionalTabs = this.hostElement.querySelector('.functional-tabs');
+    this.chartPanel = this.hostElement.querySelector('.chart-panel');
+    this.textPanel = this.hostElement.querySelector('.text-panel');
+    this.bandgapField = this.hostElement.querySelector('.summary-bandgap-field');
+
+    this.statsViewer = new StatsViewer();
+    let chartsPlaceholder = this.hostElement.querySelector('.charts-placeholder');
+    this.statsViewer.attach(chartsPlaceholder, 250, 150);
+
+    this.build(calcMapByFunctional);
+
+    this.chartTab.addEventListener( "click", e => {
+      this.chartTab.style.fill = '#777';
+      this.viewType = 'chart';
+      this.textTab.style.fill = '#c7c7c7';
+      this.chartPanel.style.display = 'block';
+      this.textPanel.style.display = 'none';
+    });
+
+    this.textTab.addEventListener( "click", e => {
+      this.textTab.style.fill = '#777';
+      this.viewType = 'text';
+      this.chartTab.style.fill = '#c7c7c7';
+      this.textPanel.style.display = 'block';
+      this.chartPanel.style.display = 'none';
+    });
+
+    this.functionalTabs.addEventListener( "click", e => {
+      if (e.target.className === 'tab'){
+        this.functionalTabs.querySelector('[data-tab="'+this.functional+'"]')
+          .className = 'tab';
+        this.functional = e.target.getAttribute('data-tab');
+        this.functionalTabs.querySelector('[data-tab="'+this.functional+'"]')
+          .className = 'tab-selected';
+        this._setData();
+      }
+    });
+
+  }
+
+  _setData(){
+    let stats = this.functionalBandGapMap.get(this.functional);
+    // Set text data
+
+    this.bandgapField.innerHTML = stats.html;
+
+    // Set Charts data
+    this.statsViewer.clear();
+    this.statsViewer.drawPoints(stats.data, stats.label, stats.min, stats.max);
+  }
+
+
+
+  build(calcMapByFunctional){
+
+    if (calcMapByFunctional.size === 0){
+      this.hostElement.style.display = 'none';
+      this.hostElement.previousElementSibling.style.display = 'none';
+    }else{
+      this.hostElement.style.display = 'block';
+      this.hostElement.previousElementSibling.style.display = 'block';
+    }
+
+    this.unfoldedElement = null;
+    this.functionalTabs.innerHTML = '';
+    this.functionalBandGapMap = new Map();
+    //console.log('calcMapByFunctional',calcMapByFunctional, this.hostElement);
+    calcMapByFunctional.forEach( (calcs, functionalName) =>{
+      //let statsMap = util.getQuantityStatsMap(calcs);
+      let array= [];
+      calcs.forEach( calc => {
+        array.push(calc.band_gap/1.602176565e-19);
+      });
+      let stats = {};
+      stats.data = array;
+      stats.min = Math.min.apply(null, array);
+      stats.max = Math.max.apply(null, array);
+      stats.equal = (stats.min === stats.max);
+      stats.label = 'band gap';
+      stats.html = util.getAverage(stats.data).toFixed(2)+
+        ' &nbsp; <span style="font-size: 0.9em">['+stats.min.toFixed(2)
+        +' , '+stats.max.toFixed(2)+']</span>';
+
+      this.functionalBandGapMap.set(functionalName, stats);
+
+      let tabClass= 'tab';
+      if (this.functional === null)     this.functional = functionalName;
+      if (this.functional === functionalName){
+        this._setData();
+        tabClass= 'tab-selected';
+      }
+
+      this.functionalTabs.innerHTML +=
+        '<span class="'+tabClass+'" data-tab="'+functionalName+'">'+functionalName+'</span>';
+    });
+
+    InfoSys.addToInfoSystem(this.hostElement);
+  }
+
+}
+
+
+
+class BZViewerWrapper{
+
+  constructor(hostElement) {
+    this.hostElement = hostElement;
+    this.bzViewer = null;
+  }
+
+
+  setCalcData(bzData, bsData){
+    if (this.bzViewer === null)
+      this.bzViewer = new BrillouinZoneViewer(this.hostElement);
+    this.bzViewer.load(this._getBZDataForViewer(bzData,bsData));
+    this.hostElement.style.visibility = 'visible';
+  }
+
+
+  setNoData(){
+    this.hostElement.style.visibility = 'hidden';
+  }
 
 
+  _getBZDataForViewer(bz_json, bs_json){
+    let labels = [];
+    let kPoints = [];
+    bs_json.forEach( segment => {
+      labels.push(segment.band_segm_labels);
+      kPoints.push(segment.band_k_points);
+    });
 
-	class NewSearchMod {
+    let data = {
+      vertices: bz_json.vertices,
+      faces: bz_json.faces,
+      basis: bz_json.basis,
+      labels: labels,
+      segments: kPoints
+    }
+    return data;
+  }
 
-	  constructor() {
+}
 
-	    this.userGuidance = true; // can enabled/disabled
 
-	    //this.showingSearchBox = false;
-	    this.searchQuery = [];
-	    this.queryTypes = []; //**** Types associated to query elements
-	    // Types: element (E), formula (F), symbol (S) and prop names
-	    this.searchFilters = [];
+// EXPORTS
+module.exports = ElectronicStructDetails;
 
-	    this.currentOperator = 'AND';
 
-	    this.element = document.createElement('div');
-	    this.element.setAttribute("id",'search-module');
-	    this.element.innerHTML=
-	    `
-	      <div class="search-filter-side">
+/***/ }),
+/* 26 */
+/***/ (function(module, exports, __webpack_require__) {
+
+
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+ /*
+  Implements a graphical UI component composed of a DOS plotter and a
+  Band Structure plotter
+ */
 
-	        <div>Filters</div>
 
-	        <!-- <div id="filter-panel-placeholder">  </div> -->
+let BSPlotter = __webpack_require__(7);
+let DOSPlotter = __webpack_require__(11);
+let svg = __webpack_require__(2);
 
-	      </div>
 
-	      <div class="search-main-side">
+class BSDOSPlotter{
 
-	        <div class="search-box" >
-	          <div class="search-query-wrapper" >
-	            <div class="search-query-box" style="float: left;">
-	            </div>
-	            <button class="clean-btn" style="float: right;">Clear all</button>
-	          </div>
+  constructor() {
+    this.element = document.createElement('div');
+    this.element.setAttribute('style','margin: 0 auto');
+    this.parentElement= null;
+    this.bsPlotter= new BSPlotter();
+    this.dosPlotter= new DOSPlotter({left: 4, right: 16, top: 0, bottom: 30});
+    this.dosYAxisLabeled = false;
+  }
 
-	          <button class="search-btn" >Search</button>
 
-	        </div>
+  attach(element, width, height){
+    element.appendChild(this.element);
+    //this.bsPlotter.attach(this.element, element.clientWidth/2 + 200 -20/*padding*/, height);
+    //this.dosPlotter.attach(this.element, element.clientWidth/2 - 200 -20/*padding*/, height);
+    this.bsPlotter.attach(this.element, height, height);
+    this.height = height;
+    this.dosPlotter.attach(this.element, this.height/2+20, height);
+    this.parentElement= element;
+  }
 
-	        <input type="checkbox" id="multiples-of-formula" value="">
-	          Include multiples of formula
-	          <br>
-	        <input type="checkbox" id="allow-other-elements" value="">
-	          Allow other elements
-	        <br>
 
+  isAttached(){
+    return this.parentElement !== null;
+  }
 
 
-	        <div class="add-buttons" >
-	          <div  class="tab-buttons" style="width: 70%; display: inline-block">
-	            <button class="element-add-btn" id="add-tab-selected">Element</button>
-	            <button class="formula-add-btn" style="padding: 10px 20px;" >Formula</button>
-	            <button class="name-add-btn" >Name</button>
-	          </div>
-	          <div class="bool-buttons" style="width: 28%; display: inline-block" >
-	            OR <span id="and-or-switch" ></span> AND
-	            <button >NOT</button>
-	            <button class="open-parentheses" >(</button>
-	            <button class="close-parentheses">)</button>
-	            <!--<input type="checkbox" name="and-or" class="not-symbol-btn" />NOT-->
-	          </div>
-	        </div>
+  setUpAndData(dispData, dosData, codeName){
 
+    this.hasDispData = (dispData !== undefined && dispData !== null);
+    this.hasDosData = (dosData !== undefined && dosData !== null);
 
-	        <div class="add-box">
-	          <div>
-	            <div class="triangle element-tri" style="margin: -10px 64px; visibility: visible"></div>
-	            <div class="triangle formula-tri" style="margin: -10px 30px; visibility: hidden"></div>
-	            <div class="triangle name-tri" style="margin: -10px 70px; visibility: hidden"></div>
-	          </div>
+    // Create a new DOS graph with/without left axis and labels
+    let newDosYAxisLabeled;
+    if (this.hasDosData && !this.hasDispData) newDosYAxisLabeled = true;
+    else newDosYAxisLabeled = false;
 
-	          <div class="add-panel">
-	          </div>
-	        </div>
+    if (this.dosYAxisLabeled !== newDosYAxisLabeled){
+      this.element.removeChild(this.dosPlotter.svg);
+      let newLeftMargin = (newDosYAxisLabeled ? 40 : 4)
+      this.dosPlotter= new DOSPlotter({left: newLeftMargin, right: 16, top: 0, bottom: 30});
+      let width = this.height/2 + newLeftMargin;
+      this.dosPlotter.attach(this.element, width, this.height);
+    }
+    this.dosYAxisLabeled = newDosYAxisLabeled;
 
-	        <div class="results-panel"  >  <!-- style="display: none"-->
-	        </div>
+    if (this.hasDispData){
+      this.bsPlotter.setBandStructureData(dispData);
+      if (this.hasDosData)
+        this.bsPlotter.setRepaintListener( (yZoom, yOffset) => {
+          this.dosPlotter.setYZoomAndOffset(yZoom, yOffset);
+          this.dosPlotter.repaint();
+        });
+    }else
+      this.bsPlotter.setNoData();
 
-	      </div> <!-- search-main-side -->
-	    `;
+    if (this.hasDosData){
 
-	    this.filterSidePanel = this.element.querySelector('.search-filter-side');
-	    this.searchQueryBox= this.element.getElementsByClassName("search-query-box")[0];
-	    this.searchBox = this.element.querySelector('.search-box');
+      this.dosPlotter.setPoints(dosData, codeName);
 
-	    this.mainButton= this.element.querySelector('.search-btn');
-	    this.cleanButton= this.element.querySelector('.clean-btn');
-	    this.addButtonsBox= this.element.querySelector('.add-buttons');
-	    this.addElementButton = this.addButtonsBox.querySelector('.element-add-btn');
-	    this.addFormulaButton = this.addButtonsBox.querySelector('.formula-add-btn');
-	    this.addMatNameButton = this.addButtonsBox.querySelector('.name-add-btn');
+      if (this.hasDispData){
+        this.bsPlotter.setExternalYAxisMax(this.dosPlotter.getYAxisMax());
 
-	    this.addPanel= this.element.querySelector('.add-panel');
+        this.dosPlotter.setRepaintListener( (yZoom, yOffset) => {
+          this.bsPlotter.setYZoomAndOffset(yZoom, yOffset);
+          this.bsPlotter.repaint();
+        });
+        // Remove y axis label
+        this.dosPlotter.svg.removeChild(this.dosPlotter.yLabelText);
+        this.dosPlotter.yLabelText = null;
+      }
+
+    }else
+      this.dosPlotter.setNoData();
 
-	    let andOrSwitch = new SwitchComponent(util.IMAGE_DIR+'switch');
-	    this.element.querySelector('#and-or-switch').appendChild(andOrSwitch.element);
-	    andOrSwitch.setListener( e => {
-	      this.currentOperator = ( e ? 'AND' : 'OR');
-	    });
+    this.dosPlotter.setYAxisLabelsVisibility(newDosYAxisLabeled);
+  }
 
-	    this.openParenthButton = this.element.querySelector('.open-parentheses');
-	    this.closeParenthButton = this.element.querySelector('.close-parentheses');
-	    this.openParenthButton.addEventListener( 'click', e => {
-	      this._addParenthesesInSearchQuery(true);
-	    });
-	    this.closeParenthButton.addEventListener( 'click', e => {
-	      this._addParenthesesInSearchQuery(false);
-	    });
 
-	    this.elementTable= new ElementTable();
-	    this.elementTable.setClickListener(elementArray => {
-	      this.addElementsInSearchQuery(elementArray);
-	      this.addMatNameButton.disabled = true; // Not always necessary but it simplifies the code
-	    });
-	    this.elementTable.setDeselectListener(e => this.removeElementORFormulaInSearchQuery(e));
+  setNoData(){
+    this.bsPlotter.setNoData();
+    this.dosPlotter.setNoData();
+  }
 
+}
 
-	    this.formulaBox = new FormulaBox();
-	    this.formulaBox.setAddFormulaListener(formula => {
-	      if (formula.trim() !== ''){
-	        this.addTagInSearchQuery(formula, 'F');
-	        //this.formulaBox.disable(true);
-	        this.addMatNameButton.disabled = true;
-	        this.materialNameBox.disable(true);
-	      }
-	    });
 
+// EXPORTS
+module.exports = BSDOSPlotter;
 
-	    this.materialNameBox = new MaterialNameBox();
-	    this.materialNameBox.setAddMaterialNameListener( name => {
-	      if (name.trim() !== ''){
-	        this.addTagInSearchQuery(name, 'MN');
-	        this.addElementButton.disabled = true;
-	        this.addFormulaButton.disabled = true;
-	        this.formulaBox.disable(true);
-	        this.materialNameBox.disable(true);
-	      }
-	    });
 
+/***/ }),
+/* 27 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+ /*
+  'Details' view container that shows a table with the methodology info used
+  to get the material calculations.
+
+  In the file there is a defined (class) component used as a filter widget for
+  the table: FilterInGroupsComponent.
+ */
+
+
+
+let DetailsViewBase = __webpack_require__(6);
+let util = __webpack_require__(0);
+let InfoSys = __webpack_require__(3);
+let DataStore = __webpack_require__(1);
+let SortingButton = __webpack_require__(28);
+
+
+const REPOSITORY_LINK =
+  'https://repository.nomad-coe.eu/NomadRepository-1.1/views/calculation.zul?pid=';
+
+const calcTypesMap = new Map([
+  ['single point', 'Single point'],
+  ['GW calculation', 'GW'],
+  ['geometry optimization', 'Geometry optimization'],
+  ['molecular dynamics', 'Molecular dynamics'],
+  ['phonon calculation', 'Phonon'],
+  ['equation of state', 'Equation of state'],
+  ['parameter variation', 'Parameter variation'],//['Convergence', 'convergence'],
+  ['QHA calculation', 'QHA']
+]);
+
+const densityFunctionalMap = new Map([
+  ['LDA', 'LDA'],
+  ['GGA', 'GGA'],
+  ['meta-GGA', 'meta-GGA'],
+  ['hybrid-GGA', 'hybrid-GGA'],
+  ['meta-hybrid-GGA', 'meta-hybrid-GGA'],
+  ['HF', 'HF']
+]);
+
+const codeMap = new Map([
+  ['exciting', 'exciting'],
+  ['VASP', 'VASP'],
+  ['FHI-aims', 'FHI-aims']
+]);
+
+const potentialMap = new Map([
+  ['full all electron', 'Full potential' ],
+  ['pseudopotential', 'Pseudo potential' ]
+]);
+
+const basicSetMap = new Map([
+  ['numeric AOs', 'Numeric AOs' ],
+  ['gaussians', 'Gaussians' ],
+  ['(L)APW+lo', '(L)APW+lo'],
+  ['plane waves', 'Plane waves']
+]);
+
+
+
+class FilterInGroupsComponent {
+
+  constructor(className) {
+    this.element = document.createElement('div');
+    this.element.className = className;
+    this.filtersOn = [];
+    this.folded = true;
+    this.element.innerHTML+=`
+      <div>
+        <div style="display: flex; justify-content: flex-end;">
+          <div class="filter-groups-c-folded" >
+            <span style="vertical-align: top;">Filtering &nbsp;&nbsp;</span>
+          </div>
+          <div class="filter-c-btn" >
+             <img src="${util.IMAGE_DIR}folded.png" />
+            <!--<button class="on">filter</button> -->
+          </div>
+        </div>
+        <div class="filter-groups-c-unfolded" style="display: none">
+          <table style="width: 100%">
+            <thead>
+            <tr>
+              <th style="width: 13%;"> </th>
+              <th style="width: 17%;">
+                <span>Type</span>
+              </th>
+              <th style="width: 19%;">
+                <span info-sys-data="functional-type">Density functional</span>
+              </th>
+              <th style="width: 13%;">
+                <span info-sys-data="code-name">Code</span>
+              </th>
+              <th style="width: 17%;">
+                <span info-sys-data="pseudopotential-type">Potential</span>
+              </th>
+              <th style="width: 12%;">
+                <span info-sys-data="basis-set-type">Basis set</span>
+              </th>
+              <th style="width: 9%;"> </th>
+            </tr>
+            </thead>
+            <tbody>
+              <tr id="filter-items-row"></tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
+    `;
+    //this.foldedPanel = this.element.querySelector('.filter-groups-c-folded');
+    this.unfoldedPanel = this.element.querySelector('.filter-groups-c-unfolded');
+    this.filterItemsRow = this.element.querySelector('#filter-items-row');
+
+    this.foldBtn = this.element.querySelector('img');
+
+    this.foldBtn.addEventListener('click', e => {
+      this.folded = !this.folded;
+      this.foldBtn.src = (this.folded ? util.IMAGE_DIR+'folded.png' :
+        util.IMAGE_DIR+'unfolded.png');
+      //this.foldedPanel.style.display = (this.folded ? 'block' : 'none');
+      this.unfoldedPanel.style.display = (this.folded ? 'none' : 'block');
+    });
+
+    // Add listener for checkboxes events
+    this.element.addEventListener('click', (e) => {
+
+      if (e.target.tagName === 'INPUT'){
+        let index = this.filtersOn.indexOf(e.target.value);
+        if (index >= 0)  this.filtersOn.splice( index, 1 );
+        else this.filtersOn.push(e.target.value);
+        this.itemListener(this.filtersOn);
+        //console.log('this.filtersOn',this.filtersOn);
+      }
+    });
+  }
+
+
+  addGroupsItems(calcs){
+    let lCalcTypesMap = new Map();
+    let lDensityFunctionalMap = new Map();
+    let lCodeMap = new Map();
+    let lPotentialMap = new Map();
+    let lBasicSetMap = new Map();
+    calcs.forEach( c => {
+      if (!lCalcTypesMap.has(c.type))
+        lCalcTypesMap.set(c.type, calcTypesMap.get(c.type));
+      if (!lDensityFunctionalMap.has(c.functional))
+        lDensityFunctionalMap.set(c.functional, densityFunctionalMap.get(c.functional));
+      if (!lCodeMap.has(c.code))
+        lCodeMap.set(c.code, codeMap.get(c.code));
+      if (!lPotentialMap.has(c.potential))
+        lPotentialMap.set(c.potential, potentialMap.get(c.potential));
+      if (!lBasicSetMap.has(c.basisSet))
+        lBasicSetMap.set(c.basisSet, basicSetMap.get(c.basisSet));
+    });
+    this.filterItemsRow.innerHTML = '<td></td>'; // calculation Id column
+    this.filtersOn = [];
+    this.addGroupItems(lCalcTypesMap);
+    this.addGroupItems(lDensityFunctionalMap);
+    this.addGroupItems(lCodeMap);
+    this.addGroupItems(lPotentialMap);
+    this.addGroupItems(lBasicSetMap);
+    this.filterItemsRow.innerHTML += '<td></td>'; // link column
+  }
+
+
+  addGroupItems(groupItemsMap){
+    let html = '<td>  ';
+    groupItemsMap.forEach( (itemName, itemId) => {
+      this.filtersOn.push(itemId);
+      html += '<input type="checkbox" value="'+itemId+'" checked>'+
+        '<span style="vertical-align: 20%">'+itemName+'</span> &nbsp;&nbsp; <br> ';
+    });
+    this.filterItemsRow.innerHTML += html+ '</td>';
+  }
+
+
+  setItemListener(listener){
+    this.itemListener = listener;
+  }
+}
+
+
+
+class MethodologyDetails extends DetailsViewBase {
+
+  constructor() {
+    super('Methodology');
+
+    this.sortedCalcs = [];
+    this.markedCalc = null;
+
+    this.element.innerHTML+=`
+
+      <div>
+        <div class="view-box">
+          <div class="title">Methodology</div>
+
+          <div class="filter-placeholder"></div>
+
+          <div class="dataTableWrapper"></div>
+        </div>
+      </div>
+    `;
+
+    // There is no this.navTreeWrapper = this.element.querySelector('.navTreeWrapper');
+
+    this.dataTableWrapper =
+        this.element.querySelector('.dataTableWrapper');
+
+    this.dataTableWrapper.innerHTML+=`
+      <table id="methodology-data">
+        <thead>
+        <tr>
+          <th style="width: 13%;">
+            <span>Calculation ID</span>
+            <span class="sorting-button"></span>
+          </th>
+          <th style="width: 17%;">
+            <span>Type</span>
+            <span class="sorting-button"></span>
+          </th>
+          <th style="width: 19%;">
+            <span info-sys-data="functional-type">Density functional</span>
+            <span class="sorting-button"></span>
+          </th>
+          <th style="width: 13%;">
+            <span info-sys-data="code-name">Code</span>
+            <span class="sorting-button"></span>
+          </th>
+          <th style="width: 17%;">
+            <span info-sys-data="pseudopotential-type">Potential</span>
+            <span class="sorting-button"></span>
+          </th>
+          <th style="width: 12%;">
+            <span info-sys-data="basis-set-type">Basis set</span>
+            <span class="sorting-button"></span>
+          </th>
+          <th style="width: 9%;">
+            <span info-sys-data="basis-set-type">Link</span>
+
+          </th>
+        </tr>
+        </thead>
+        <tbody>
+        </tbody>
+      </table>
+    `;
+
+    this.tbody = this.dataTableWrapper.querySelector("tbody");
+    this.moreInfoRow = document.createElement('tr'); //
+    this.moreInfoRow.className= 'moreinfo';
+    this.moreInfoCalcId = null;
+
+    // filtering feature initialitation
+    this.filterComponent = new FilterInGroupsComponent('meth-filter-component');
+    this.element.querySelector('.filter-placeholder').
+      appendChild(this.filterComponent.element);
+
+    this.filterComponent.setItemListener( propsSel/*ected*/ => {
+
+      let rows = this.tbody.querySelectorAll('tr');
+      for (let i = 0; i < rows.length; ++i){
+        let calcProps = rows[i].getAttribute('data-calc-props').split(',');
+        //console.log('FILTERING calcProps: ',calcProps);
+        let propsPresent = true;
+        calcProps.forEach( e => {
+          if (propsSel.indexOf(e) < 0) propsPresent = false;
+        });
+
+        if (propsPresent) rows[i].style.display = 'table-row';
+        else rows[i].style.display = 'none';
+      }
+    });
+
+    // row sorting feature initialitation
+    this.sortingButtonWrappers =
+      this.dataTableWrapper.querySelectorAll('.sorting-button');
+
+    this.sortingButtons = [];
+
+    let sortingButtonsMap = new Map([
+      [ 'id', undefined ],
+      [ 'type', undefined ],
+      [ 'functional', undefined ],
+      [ 'code', undefined ],
+      [ 'potential', undefined ],
+      [ 'basisSet', undefined ] ]);
+
+    let keysIter = sortingButtonsMap.keys();
+    this.sortingButtonWrappers.forEach( e => {
+      let field = keysIter.next().value;
+      let component = new SortingButton(field);
+      e.appendChild(component.element);
+      this.sortingButtons.push(component);
+
+      component.setListener( (descendingOrder, field) => {
+        //console.log(descendingOrder, field);
+        this.sortingButtons.forEach( el => {
+          if (el !== component) el.init();
+        });
+        this._sortRowsCalcDataBy(descendingOrder, field);
+        this._render();
+      });
+    });
+
+    // For static ones
+    InfoSys.addToInfoSystem(this.element);
+
+    this._events();
+  }
+
+
+  _events() {
+    //super._events();
+
+    this.dataTableWrapper.addEventListener('click', (e) => {
+
+      let rowElement = e.target.parentElement;
+      if (rowElement.className.indexOf('data-row') < 0)
+        rowElement = rowElement.parentElement;
+
+      if (rowElement.className.indexOf('data-row') >= 0){
+        let id= rowElement.getAttribute('data-calc-id');
+
+        if (this.moreInfoCalcId !== null){ // If more-info panel unfolded
+          this.moreInfoRow.parentElement.removeChild(this.moreInfoRow);
+          if (this.moreInfoCalcId === id){
+            this.moreInfoCalcId = null;
+            return;
+          }
+        }
+        this.moreInfoCalcId = id;
+        let moreInfoCalc, calcGroupType;
+        this.sortedCalcs.forEach( leafId => { //console.log(leafId, id);
+          if (leafId === id){
+            moreInfoCalc = DataStore.getCalc(DataStore.getCalcReprIntId(leafId));
+            calcGroupType = DataStore.getGroupType(leafId);
+
+          }
+        });
+        this.moreInfoRow.innerHTML= ' <td></td><td colspan="7"> '+
+          getHTMLCalcType(calcGroupType, moreInfoCalc)+' </td>';
+        rowElement.parentElement.insertBefore(this.moreInfoRow, rowElement.nextElementSibling);
+      }
+
+    });
+
+
+    function getHTMLCalcType(calcGroupType, calc){
+
+      let result = '';
+      let calcType = calcGroupType;
+      if (calcGroupType === null ) calcType = calc.run_type;
+      //console.log('getHTMLCalcType',calcType);
+      switch (calcType){
+
+        case calcTypesMap.get('Single point'):
+
+        case calcTypesMap.get('Geometry optimization'):
+          //console.log(calc.pseudopotential_type, calc.scf_threshold, calc.basis_set_short_name);
+          result = getValueHTML('pseudopotential type',calc.pseudopotential_type) +
+          getValueHTML('scf threshold',calc.scf_threshold) +
+          getValueHTML('basis set short name',calc.basis_set_short_name) +
+          getSmearingHTML(calc.smearing);
+          break;
+
+        case calcTypesMap.get('GW'):
+          result =  getValueHTML('gw starting point',calc.gw_starting_point) +
+            getValueHTML('gw type',calc.gw_type);
+          break;
+
+        case calcTypesMap.get('Equation of state'):
+          result =  getValueHTML('pseudopotential type',calc.pseudopotential_type) +
+            getValueHTML('basis set short name',calc.basis_set_short_name) +
+            getValueHTML('scf threshold',calc.scf_threshold) +
+            getSmearingHTML(calc.smearing) +
+            getValueHTML('k point grid description',calc.k_point_grid_description);
+          break;
+
+        case calcTypesMap.get('Parameter variation'):
+          result =  getValueHTML('pseudopotential type',calc.pseudopotential_type) +
+            getValueHTML('scf threshold',calc.scf_threshold);
+          break;
+
+        case calcTypesMap.get('Phonon'):
+          result =  getValueHTML('type', 'finite differences');
+          break;
+
+      }
+      if (result.trim() === '') return 'NO ADDITIONAL DATA';
+      else return result;
+    }
+
+  }
+
+
+  updateSelection( leafIds/* Not used */ ){
+
+    this.sortedCalcs = [];
+
+    DataStore.getCalculations().forEach( c => {
+
+      let calcType = c.run_type;
+      if (DataStore.getGroups().has(c.id)){//leafId))
+        calcType = DataStore.getGroupType(c.id);//leafId);
+        if (calcType === 'convergence') calcType = 'parameter variation';
+        //console.log('Group',DataStore.getGroupType(leafId));
+      }
+
+      this.sortedCalcs.push({
+        id: c.id,
+        type: calcType,
+        functional: c.functional_type,
+        code: c.code_name,
+        potential: c.core_electron_treatment,
+        basisSet: c.basis_set_type
+      });
+    });
+
+    this.filterComponent.addGroupsItems(this.sortedCalcs);
+
+    this._sortRowsCalcDataBy(true, 'id');
+    //console.log('sortedCalcs:', this.sortedCalcs);
+
+    this._render();
+  }
+
+
+  _sortRowsCalcDataBy(descendingOrder, field){
+
+    this.sortedCalcs.sort( (a, b) => {
+      if(a[field] < b[field]) return (descendingOrder ? -1 : 1);
+      if(a[field] > b[field]) return (descendingOrder ? 1 : -1);
+      return 0;
+    });
+  }
 
-	    this.filterPanel = new FilterPanel();
-	    this.filterSidePanel.appendChild(this.filterPanel.element);
 
-	    this.materialList= new MaterialList();
-	    this.resultsPage = this.element.querySelector('.results-panel');
-	    this.materialList.attachAndSetEvents(this.resultsPage);
+  updateMarkedLeaf(leafId){  }
 
-	    this.currentTab = 'element';
-	    this.addPanel.appendChild(this.elementTable.element);
 
+  _render(){
 
+    let html = '';
+    this.sortedCalcs.forEach( rowCalcData => { //leafId => {
+      //html+= getRowHtml(leafId, calc, calcType);
+      html+= getRowHtml(rowCalcData);
+    });
+    this.tbody.innerHTML = html;
 
-	    this._events();
-	  }
+    InfoSys.addToInfoSystem(this.tbody);
+
+    function getRowHtml(rowCalcData/*leafId, calc, calcType*/){
 
+      let calc = DataStore.getCalc( /*DataStore.getCalcReprIntId(*/rowCalcData.id);
+      let calcType = rowCalcData.type;
+      let calcProps = calcType+','+calc.functional_type+','+calc.code_name+
+        ','+calc.core_electron_treatment+','+calc.basis_set_type;
+
+      let repositoryLinkHtml = '';
+      if (calc.calculation_pid !== null && calc.calculation_pid !== undefined)
+        repositoryLinkHtml =
+          '<a href="'+REPOSITORY_LINK+calc.calculation_pid+'" target="blank"> '
+          +'<img src="img/download.svg" height="20px" /> </a>';
 
-	  _events() {
-	    // External event - Search button press
-	    this.mainButton.addEventListener( "click", (e) => {
-	      //console.log("this.labels: "+JSON.stringify(this.labels));
+      return  `
+        <tr data-calc-id="${calc.id/*leafId*/}" data-calc-props="${calcProps}" class="data-row">
+        <td>${calc.id/*leafId*/}</td>
+        <td>
+          <span info-sys-data="calculation-type.value:${calcType}">
+          ${calcType}</span>
+        </td>
+        <td>
+          <span info-sys-data="functional-type.value:${calc.functional_type}">
+            ${calc.functional_type}</span>
+          ${getOptValue(calc.functional_long_name)}
+        </td>
+        <td>
+          <span info-sys-data="code-name.value:${calc.code_name}">
+            ${calc.code_name}</span>
+           ${getOptValue(calc.code_version)}
+        </td>
 
-	      if (this.searchQuery.lenght === 0){
-	        util.showUserMsg('No query');
-	      }else{
-	        let searchExpressionQuery;
+        <td>
+          <span info-sys-data="core-electron-treatment.value:${calc.core_electron_treatment}">
+          ${getPotentialValue(calc.core_electron_treatment)}</span>
+        </td>
+        <td>
+          <span info-sys-data="basis-set-type.value:${calc.basis_set_type}">
+            ${calc.basis_set_type}</span>
+           ${getOptValue(calc.basis_set_quality_quantifier)}
+        </td>
 
-	        //************** Material name or complex search expression
-	        //if (this.queryTypes[i] === 'MN'){
-	          //queryObj.push(this._getESSimpleMatch('material_name', item));
+        <td style="padding-top: 8px;padding-bottom: 4px;">${repositoryLinkHtml}
+        </td>
 
+        </tr>`;
+    }
 
-	        if (this.element.querySelector('#allow-other-elements').checked)
-	          searchExpressionQuery = this._getESQueryFromSearchQuery_otherElements(
-	            this.searchQuery, this.queryTypes);
-	        // Regular case: search containing only the elements in the search expression
-	        else searchExpressionQuery =
-	            this._getESQueryFromSearchQuery(this.searchQuery, this.queryTypes);
+    function getOptValue(value){
+      if (value === undefined || value === null)  return '';
+      else return '('+value+')';
+    }
+
+    function getPotentialValue(value){
+      if (value === 'pseudopotential')  return 'pseudopotential';
+      else if (value === 'full all electron')  return 'full potential';
+      else return value;
+    }
+  }
 
-	        this.materialList.initSearch(
-	          this._addFiltersInSearchQuery( this.filterPanel.getValues(),
-	            searchExpressionQuery));
-	        //util.setBrowserHashPath('search','results');
+}
 
-	        this.element.querySelector('.add-box').style.display = 'none';
-	      }
+function getValueHTML(text,value){
+  if (value === undefined || value === null)  return '';
+  else return '<b>'+text+'</b>: '+value+'<br>';
+}
 
-	    });
 
+function getSmearingHTML(value){
+  let values = value.substring(1,value.length-1).split(',');
+  return (values[0] === 'none' ? '' : '<b>smearing kind</b>: '+values[0]+' , ')+
+         (values[1] === '0' ? '' : '<b>smearing width</b>: '+values[1]);
+}
 
-	    this.cleanButton.addEventListener( "click", (e) => {
-	      this.searchQuery = [];
-	      this.queryTypes = [];
-	      this.updateSearchQuery();
-	      this.addFormulaButton.disabled = false;
-	      this.addMatNameButton.disabled = false;
-	      this.addElementButton.disabled = false;
-	      this.formulaBox.disable(false);
-	      this.materialNameBox.disable(false);
-	      this.elementTable.deselectAllElements();
-	    });
 
-	    this.addButtonsBox.addEventListener( "click", (e) => {
-	      if (e.target !== e.currentTarget) { // When the event source is a child
-	        let className = e.target.className;
-	        let index = className.indexOf('add-btn');
-
-	        if (index > 0){
-	          let selectingElement;
-	          let selectingTab = className.substring(0, index-1);
-	          if (selectingTab === 'element')
-	            selectingElement = this.elementTable.element;
-	          else if (selectingTab === 'name')
-	            selectingElement = this.materialNameBox.element;
-	          else if (selectingTab === 'formula')
-	            selectingElement = this.formulaBox.element;
-
-	          this.addPanel.replaceChild(selectingElement, this.addPanel.lastChild);
-
-	          this.element.querySelector('.add-box').style.display = 'block';
-
-	          // Change the styles of the buttons
-	          let selEl = this.element.querySelector('.'+this.currentTab+'-add-btn');
-	          this._setTabSelectedStyles(selEl, false);
-	          this._setTabSelectedStyles(e.target, true);
-
-	          // Change the triangle
-	          this.element.querySelector('.'+this.currentTab+'-tri').style.visibility = 'hidden';
-	          this.element.querySelector('.'+selectingTab+'-tri').style.visibility = 'visible';
-
-	          this.currentTab = selectingTab;
-
-	/*
-	          if (this.userGuidance){
-	            if (selectingTab === 'element'){
-	              UserGuidance.showIndependentTip(7, false);
-	              UserGuidance.showIndependentTip(3, true);
-	            }
-	            else if (selectingTab === 'props'){
-	              UserGuidance.showIndependentTip(3, false);
-	              UserGuidance.showIndependentTip(7, true);
-	            }else if (selectingTab === 'formula'){
-	              UserGuidance.showIndependentTip(3, false);
-	              UserGuidance.showIndependentTip(7, false);
-	            }
-	          }
-	          */
-
-	        }
-	      }
-	    });
 
-	    this.searchQueryBox.addEventListener( "click", (e) => {
-	      let className = e.target.className;
-	      if (className === 'remove-label'){
-	        let elSymbol = e.target.parentElement.getAttribute('data-el');
-	        this.removeElementORFormulaInSearchQuery(elSymbol);
-	      }
-	    });
+// EXPORTS
+module.exports = MethodologyDetails;
 
-	  }
+
+/***/ }),
+/* 28 */
+/***/ (function(module, exports, __webpack_require__) {
 
 
-	  _getESQueryFromSearchQuery(searchQuery, queryTypes){
-	    let formulas = [];
-	    let parFormulas = [];
-	    let parOperator = null;
-	    let openIndex = -1;
-	    searchQuery.forEach( (item, i) => {
-	      if (queryTypes[i] === 'F' || queryTypes[i] === 'E'){
-	        addItem( (openIndex >= 0 ? parFormulas : formulas), i,
-	          item+(queryTypes[i] === 'E' ? '0' : ''));
-
-	      }else if ( searchQuery[i] === '(' ){
-	        if (i-1 >= 0 ) parOperator = searchQuery[i-1];
-	        openIndex = i;
-	      }
-	      else if ( searchQuery[i] === ')' ){
-	        if (parOperator === null){ // The starting ( was the first symbol of the expression
-	          formulas = parFormulas;
-	        }else if (parOperator === 'OR'){ // OR (...
-	          formulas = formulas.concat(parFormulas);
-	        }else{ // AND (...
-	          let rFormulas = [];
-	          formulas.forEach( formula => {
-	            parFormulas.forEach( parFormula => rFormulas.push(formula+parFormula) );
-	          });
-	          formulas = rFormulas;
-	        }
-	        parFormulas = []; // reset the array formulas inside the parentheses
-
-	        openIndex = -1;
-	      }
-	    });
-	    console.log('_getESQueryFromSearchQuery: ',formulas, parFormulas);
-
-	    //*********** Get the elastic search expression from the search expression
-	    // the elements inserted must be sorted for this to work
-	    // queryObj.bool.must.push(this._getESSimpleMatch('atom_labels_keyword', this._sortElements(elements) )); ///elements.join('')));
-	    // if ( this.element.querySelector('#multiples-of-formula').checked ){ // reduced search
-	    let rootQueryObj = { 'bool' : {} };
-	    rootQueryObj.bool.should = [];
-	    let queryObj = rootQueryObj.bool.should;
-	    let reduced = this.element.querySelector('#multiples-of-formula').checked;
-
-	    formulas.forEach( formula => {
-	      let pFormula;
-	      let searchByElement = (formula.indexOf('0') >= 0);
-	      if (searchByElement){ // There are some element in the search expression
-	        /** TDO**/
-	        let f = formula;
-	        if (reduced) f = this._reduceFormula(formula, false);
-	        pFormula = this._processFormula(f, 'element-string');
-	        let tempQueryObj = { 'bool' : { 'must' : [] } };
-
-	        if (pFormula[0].length > 0)  // length === 0 No formula, only elements
-	          tempQueryObj.bool.must.push(
-	            this._getESOperatorMatch(
-	              (reduced ? 'formula_reduced_terms' : 'formula_cell_terms'), pFormula[0]));
-	        tempQueryObj.bool.must.push(
-	          this._getESSimpleMatch('atom_labels_keyword', pFormula[1]));
-
-	        queryObj.push(tempQueryObj);
-
-	      }else{ // Only formulas
-	        if ( reduced ){ // reduced search
-	          pFormula = this._reduceFormula(formula, false);
-	          queryObj.push(this._getESSimpleMatch('formula_reduced_keyword', pFormula));
-	        }else{
-	          pFormula = this._processFormula(formula, 'canonical-formula');
-	          queryObj.push(this._getESSimpleMatch('formula_cell_keyword', pFormula));
-	        }
-	      }
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
 
-	    });
+ /*
+  Sorting button component implementation
+ */
 
-	    return rootQueryObj;
-
-	    function addItem(formulas, i, item){
-	      if (i === 0 || searchQuery[i-1] === '('){
-	        formulas.push(item);
-	      }else{
-	        if (searchQuery[i-1] === 'OR') formulas.push(item);
-	        else if (searchQuery[i-1] === 'AND')
-	          formulas.push(formulas.pop()+item);
-	      }
-	    }
 
-	  } // _getESQueryFromSearchQuery()
+let util = __webpack_require__(0);
 
+class SortingButton {
 
-	  _getESQueryFromSearchQuery_otherElements(searchQuery, queryTypes){
-	    // Query structure analysis - looking for parentheses (only one level supported)
-	    if ( searchQuery.indexOf('(') >= 0){ // Recursion
+  constructor(id) {
 
-	      let openIndex = -1;
-	      let prodQuery = [];
-	      let prodTypes = [];
-	      //let prodQueryIndex = 0;
-	      for (let i = 0; i < searchQuery.length; i++) {
-	        if ( searchQuery[i] === '(' ) openIndex = i;
-	        else if ( searchQuery[i] === ')' ){
-	          prodQuery.push(this._getESQueryFromSearchQuery_otherElements(
-	            searchQuery.slice(openIndex+1, i), queryTypes.slice(openIndex+1, i)));
-	          prodTypes.push('Q');
-	          openIndex = -1;
-	        }else if (openIndex < 0){ // outside a parentheses
-	          prodQuery.push(searchQuery[i]);
-	          prodTypes.push(queryTypes[i]);
-	        }
-	      }
-	      //console.log('prodQuery', prodQuery, prodTypes);
-	      return this._getESQueryFromSearchQuery_otherElements(prodQuery, prodTypes);
+    this.id = id;
+    this.ascending = true;
 
-	    }else{  // BASE CASE: there is no parentheses
+    this.element = document.createElement('span');
+    this.element.innerHTML+=`
+       <img src="img/sorting_init.png" width="12px"
+        style="margin-bottom: -1px; cursor: pointer"/>
+    `;
+    this.image = this.element.querySelector('img');
 
-	      let boolOperator;
-	      searchQuery.forEach( (item, i) => {
-	        if (searchQuery[i] === 'AND' || searchQuery[i] === 'OR')
-	          boolOperator = item;
-	      });
+    if (id === 'id')
+      this.image.setAttribute('src','img/sorting_ascending.png');
 
-	      let rootQueryObj = { 'bool' : {} };
-	      let queryObj;
-	      if (boolOperator === 'AND'){
-	        rootQueryObj.bool.must = [];
-	        queryObj = rootQueryObj.bool.must;
-	      }else{ // OR
-	        rootQueryObj.bool.should = [];
-	        queryObj = rootQueryObj.bool.should;
-	      }
+    this.element.addEventListener('click', e => {
+      this.ascending = !this.ascending;
+      this.image.setAttribute('src',
+        'img/sorting_'+(this.ascending ? 'ascending' : 'descending')+'.png');
+      this.listener(this.ascending, this.id);
+    });
+  }
 
-	      searchQuery.forEach( (item, i) => {
 
-	        if (queryTypes[i] === 'F'){ // Formula case
-	          let esMatchQuery;
-	          if ( this.element.querySelector('#multiples-of-formula').checked ){ // reduced search
-	            esMatchQuery = this._getESOperatorMatch('formula_reduced_terms', this._reduceFormula(item));
-	          }else
-	            esMatchQuery = this._getESOperatorMatch('formula_cell_terms', this._processFormula(item, 'tokens'));
-	          queryObj.push(esMatchQuery);
+  init(){
+    this.image.setAttribute('src','img/sorting_init.png');
+  }
 
-	        }else if (queryTypes[i] === 'E'){ // Element case
-	          queryObj.push(this._getESSimpleMatch('atom_labels_terms', item));
 
-	        }else if (queryTypes[i] === 'Q'){
-	          queryObj.push(item);
-	        }
-	      });
+  setListener(listener){
+    this.listener = listener;
+  }
 
-	      return rootQueryObj;
-	    } // else
-	  } // _getESQueryFromSearchQuery_otherElements()
+}
 
+// EXPORTS
+module.exports = SortingButton;
 
 
+/***/ }),
+/* 29 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+ /*
+  'Details' view container that shows the material calculations info related to
+  their vibrational and thermal properties.
+ */
+
+
+
+let DetailsViewBase = __webpack_require__(6);
+let util = __webpack_require__(0);
+let InfoSys = __webpack_require__(3);
+let DataStore = __webpack_require__(1);
+let LoadingPopup = __webpack_require__(4);
+
+let HeatCapPlotter = __webpack_require__(12);
+let HelmholtzPlotter = __webpack_require__(30);
+let PhononDispDOSPlotter = __webpack_require__(31);
+
+
+class ThermalPropsDetails  extends DetailsViewBase{
+
+  constructor() {
+    super('Thermal Properties');
+    this.firstId;
+    this.lastId;
+    this.element.innerHTML+=`
+      <div style="float: left; width: 30%;">
+        <div class="view-box">
+          <div class="title">Calculations </div>
+          <div class="navTreeWrapper"></div>
+        </div>
+      </div>
+
+      <div style="float: right; width: 70%;">
+        <div class="view-box thermal-properties-box">
+
+          <div class="title">Vibrational and thermal properties</div>
+
+          <div style="padding-top: 10px;">
+            <div class="tree-leaf-title"></div>
+          </div>
+
+          <div class="calc-disp-dos-plotter" style="padding: 30px 100px; ">
+            <div class="info-fields-label" style="float: left; width: 52%; ">
+              <span info-sys-data="phonon-dispersion">Phonon dispersion </span>
+            </div>
+            <div class="info-fields-label" style="float: left;">
+              <span info-sys-data="phonon-DOS">Phonon DOS  </span>
+            </div>
+            <div style="clear: both;"></div>
+          </div>
+
+
+          <div class="band" >
+            <div style="padding: 30px 50px; display: flex; justify-content: space-around; ">
+
+              <div >
+                <div class="info-fields-label" >
+                  <span info-sys-data="specific-heat-cv">Specific heat</span>
+                </div>
+                <div class="heat-plotter" >      </div>
+              </div>
+
+              <div>
+                <div class="info-fields-label" >
+                  <span info-sys-data="helmholtz-free-energy">Helmholtz free energy</span>
+                </div>
+                <div class="helmholtz-plotter" >      </div>
+              </div>
+
+            </div>
+          </div>
+
+        </div>
+      </div>
+    `;
+
+    this.navTreeWrapper =
+        this.element.getElementsByClassName("navTreeWrapper")[0];
+
+    this.rightBox = this.element.querySelector('.thermal-properties-box');
+    this.leafTitle = this.element.querySelector('.tree-leaf-title');
+
+    this.dispDosPlotter = new PhononDispDOSPlotter();
+    this.heatPlotter= new HeatCapPlotter();
+    this.helmholtzPlotter= new HelmholtzPlotter();
+
+    InfoSys.addToInfoSystem(this.element);
+  }
+
+
+  _events() {
+    super._events();
+  }
+
 
-	  _addFiltersInSearchQuery(filterMap, searchExpressionQuery){
-	    let rootQueryObj = { 'bool' : {} };
-	    rootQueryObj.bool.must = [];
-	    rootQueryObj.bool.must.push( searchExpressionQuery );
+  updateSelection(leafIds/*Set*/){
+    //console.log('E-StructureDetails UPDATING calcs: ',calcs.values().next().value);
+    if (leafIds.size > 0){
+      this.rightBox.style.visibility = 'visible';
+      let counter= 0;
+      leafIds.forEach( calcId => {
+        counter++;
+        if (counter === 1) this.firstId = calcId;
+        else if (counter === leafIds.size) this.lastId = calcId;
+      });
+    }else
+      this.rightBox.style.visibility = 'hidden';
+    //console.log('METHODOLOGY '+this.tbody.innerHTML);
+  }
 
 
-	    filterMap.forEach((values/*Array*/, filterName) => {
 
-	      let filterNameDef = replaceDashes(filterName);
+  updateMarkedLeaf(leafId){
+    //console.log('updateMarkedCalc ',calc);
+    if (leafId === null){
+      this.leafTitle.innerHTML = 'NO SELECTION';
+      return;
+      //this.bandGapField.textContent= '';
+    }else{
+      if (DataStore.getGroups().has(leafId)){
+        this.leafTitle.innerHTML = leafId+
+          ' ('+DataStore.getGroups().get(leafId).calcs.size+')';
+      }else
+        this.leafTitle.innerHTML = leafId;
+    }
 
-	      if (filterName === 'mass-density' || filterName === 'band-gap'){
-	        //***** util.eV2J() apply?
-	        rootQueryObj.bool.must.push( this._getFieldESRange(filterNameDef, values) );
+    let calc = DataStore.getCalc(DataStore.getCalcReprIntId(leafId));
 
-	      }else if (filterName === 'band-gap-type'){ // special case
-	        if ( values !== 'both')
-	          rootQueryObj.bool.must.push( this._getESSimpleMatch('band_gap_direct',
-	            ( values === 'direct' ? true : false ) ) );
+    if (!this.dispDosPlotter.isAttached()){
+      this.dispDosPlotter.attach(this.element.querySelector('.calc-disp-dos-plotter'),undefined,360);
+      this.heatPlotter.attach(this.element.querySelector('.heat-plotter'),317,317);
+      this.helmholtzPlotter.attach(this.element.querySelector('.helmholtz-plotter'),317,317);
+    }
+    if (calc === null || (!calc.has_phonon_dos && !calc.has_phonon_dispersion
+                          && !calc.has_thermal_properties)){
+      this.dispDosPlotter.setNoData();
+      this.heatPlotter.setNoData();
+      this.helmholtzPlotter.setNoData();
+    }else{
+      LoadingPopup.show();
+      let matId = DataStore.getMaterialData().id;
 
-	      }else if (filterName.startsWith('has')){ // has- filters
-	        rootQueryObj.bool.must.push( this._getESSimpleMatch(filterNameDef, values, false) );
-
-	      }else{ // normal case
-	        //rootQueryObj.bool.must.push( this._getESOperatorMatch(filterNameDef, values, false) );
-	        rootQueryObj.bool.must.push( this._getESTermsArray(filterNameDef, values) );
-
-	        //console.log(this._getESOperatorMatch(filterNameDef, values, false) );
-	      }
 
-	    });
 
+      util.serverReq(util.getMaterialCalcURL(matId, calc.id,'phonon_dos'), e=> {
+        let dosData= JSON.parse(e.target.response).phonon_dos;
 
-	    return rootQueryObj;
-	  }
+        util.serverReq(util.getMaterialCalcURL(matId, calc.id,
+            'phonon_dispersion'), e2 => {
+          let dispersionData= JSON.parse(e2.target.response).phonon_dispersion;
+          this.dispDosPlotter.setUpAndData(dispersionData, dosData);
 
+          if (calc.has_thermal_properties){
 
-	  _getESSimpleMatch(field, value){
-	    return {
-	      "match": { [field] : value }
-	    };
-	  }
+            util.serverReq(util.getMaterialCalcURL(matId, calc.id,
+              'specific_heat_cv'), e3 => {
+                let sHeatData= JSON.parse(e3.target.response).specific_heat_cv;
+                this.heatPlotter.setData(sHeatData);
+            });
 
-	  _getESTermsArray(field, value){
-	    return {
-	      "terms": { [field] : value }
-	    };
-	  }
+            util.serverReq(util.getMaterialCalcURL(matId, calc.id,
+              'helmholtz_free_energy'), e4 => {
+                let helmholtzData = JSON.parse(e4.target.response).helmholtz_free_energy;
+                this.helmholtzPlotter.setData(helmholtzData);
+            });
 
+          }else{
+            this.heatPlotter.setNoData();
+            this.helmholtzPlotter.setNoData();
+          }
 
-	  _getESOperatorMatch(field, elements, and = true){
-	    let elementsString = '';
-	    if (elements.length > 0)  elementsString = elements.join(' ');
+          LoadingPopup.hide();
+        });
+      });
 
-	    return {
-	      "match": {
-	        [field]: {
-	          "operator": (and ? "and" : 'or'),
-	          "query": elementsString
-	        }
-	      }
-	    };
-	  }
+    }
 
+  }
 
-	  _getFieldESRange(field, valuesString){
-	    let data = valuesString.split(':');
-	    console.log('_getFieldESRange data', data);
 
-	    return {
-	      "range": {
-	          [field]: { "gte" : parseInt(data[0]), "lte" : parseInt(data[1]) }
-	      }
-	    };
-	  }
+  setPrevCalcListener(listener){
+    this.prevCalcListener= listener;
+  }
 
 
+  setNextCalcListener(listener){
+    this.nextCalcListener= listener;
+  }
 
+}
 
-	  _setTabSelectedStyles(element, value){
-	    /*
-	    element.style.fontWeight = (value ? 'bold' : 'normal');
-	    element.style.color = (value ? '#E56400' : '#777');
-	    element.style.borderColor = (value ? '#E56400' : '#777');
-	    */
-	    element.id = (value ? 'add-tab-selected' : '');
-	  }
+// EXPORTS
+module.exports = ThermalPropsDetails;
 
 
-	/*
-	  _showSearchBox(){
-	    if (!this.showingSearchBox){
-	      this.showingSearchBox = true;
-	      this.searchLine.style.visibility = 'visible';
+/***/ }),
+/* 30 */
+/***/ (function(module, exports, __webpack_require__) {
 
-	      if (this.userGuidance)  UserGuidance.setFinal();
-	    }
-	  }*/
+"use strict";
 
-	  _addItemInSearchQuery(item, type){
-	      this.searchQuery.push(item);
-	      this.queryTypes.push(type);
-	  }
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
 
 
-	  addTagInSearchQuery(tag, type){
-	    // If the it's an element and is already in the query it's not inserted
-	    if (type === 'E' && this.searchQuery.indexOf(tag) >= 0) return;
+ /*
+  Helmholtz free energy plotter implementation
+ */
 
-	    if ( this.searchQuery.length > 0
-	          && this.searchQuery[this.searchQuery.length-1] !== '(')
-	      this._addItemInSearchQuery(this.currentOperator, 'S');
-	    this._addItemInSearchQuery(tag, type);
-	    this.updateSearchQuery();
-	    //this._showSearchBox();
-	  }
 
 
-	  addElementsInSearchQuery(elementArray){
-	    let index = elementArray.length;
-	    while (index--) {
-	      this.addTagInSearchQuery(elementArray[index], 'E');
-	    }
-	    return true;
-	  }
+let svg = __webpack_require__(2);
+let PlotterBase = __webpack_require__(5);
 
 
-	  _addParenthesesInSearchQuery(isOpen){
+class HelmholtzPlotter extends PlotterBase{
 
-	    if ( this.searchQuery.length > 0 && isOpen)
-	      this._addItemInSearchQuery(this.currentOperator, 'S');
-	    this._addItemInSearchQuery( (isOpen ? '(' : ')'), 'P');
-	    this.updateSearchQuery();
-	    //this._showSearchBox();
-	  }
+  constructor() {
+    super({left: 60, right: 16, top: 10, bottom: 32});
+    this.tooltip;
+  }
 
 
-	  removeElementORFormulaInSearchQuery(item){
-	    //console.log(" removeElementORFormulaInSearchQuery item: ",item, this.searchQuery.indexOf(item));
-
-	    // Travese the array removing the item and the bool operator related
-	    let itemIndex = this.searchQuery.indexOf(item);
-	    if (itemIndex >= 0){
-	      let i, elementsToRemove;
-	      if (this.queryTypes[itemIndex+1] === 'S'){ // bool operator on the left
-	        i = itemIndex; elementsToRemove = 2;
-	      }else if (this.queryTypes[itemIndex-1] === 'S'){ // bool operator on the right
-	        i = itemIndex-1; elementsToRemove = 2;
-	      }else{ // case: (item)
-	        i = itemIndex; elementsToRemove = 1;
-	      }
-	      this.searchQuery.splice(i, elementsToRemove);
-	      this.queryTypes.splice(i, elementsToRemove);
-	    }
-
-	    // Travese the array removing the unnecessary parethesis (only tested for one level nested)
-	    if ( this.searchQuery.indexOf('(') >= 0){ // Recursion
-
-	      for (let i = 0; i < this.searchQuery.length; i++) { // dangerous: modifing a array being traversed
-	        if ( this.searchQuery[i] === '(' ){
-	          if ( this.searchQuery[i+1] === ')'){ // '()' case
-	            this.searchQuery.splice(i, 2);
-	            this.queryTypes.splice(i, 2);
-	          }else if (searchQuery[i+2] === ')'){ // '(item)' case
-	            this.searchQuery.splice(i, 3, this.searchQuery[i+1]);
-	            this.queryTypes.splice(i, 3, this.queryTypes[i+1]);
-	          }
-	        }
-	      }
-	    }
-
-	    this.updateSearchQuery();
-
-	    if (util.ELEMENTS.indexOf(item) >= 0){ // It's an element (being removed)
-	      this.elementTable.deselectElement(item);
-	      if (this.queryTypes.indexOf('E') < 0){ // It's the last element
-	        //this.addFormulaButton.disabled = false;
-	        this.addMatNameButton.disabled = false;
-	      }
-
-	    }else{ // It's other than element (formula, material name ¿or prop???)
-	      this.addElementButton.disabled = false;
-	      this.formulaBox.disable(false);
-	      this.materialNameBox.disable(false);
-	      // Added ¿?
-	      this.addFormulaButton.disabled = false;
-	      this.addMatNameButton.disabled = false;
-	    }
-
-	    //console.log(" final searchQuery: ",this.searchQuery);
-	    //}
-
-	    return true;
-	  }
+  setData(data){
+    this.clear();
+    // up to 600K data is taken
+    let indexOf600K = data.temperature.indexOf(600)+1;
+    let values = data.value.slice(0, indexOf600K);
+    let temperatures = data.temperature.slice(0, indexOf600K);
 
+    let yMaxValue = Math.max.apply(null, values);
+    let yMinValue = Math.min.apply(null, values);
+    let yAxisMaxValue = Math.ceil(yMaxValue/1000)*1000;
+    let yAxisMinValue = Math.floor(yMinValue/1000)*1000;
 
-	  updateSearchQuery(){
-	    let html= '';
-	    for (let i = 0; i < this.searchQuery.length; i++) {
-	      let type = this.queryTypes[i];
+    this.setRangeAndLabels('T (K)', 0,  600,
+      'F (J/kg)', yAxisMinValue, yAxisMaxValue);
+    this.drawAxis(4, null, 0);
 
-	      if (type === 'S' || type === 'P')
-	        html+= `<span class="search-query-symbol" >  ${this.searchQuery[i]} </span>`;
-	      else
-	        html+= getTagHtml(this.searchQuery[i], ( type === 'F' ? true : false));
-	    }
-	    console.log('this.updateSearchQuery: ', this.searchQuery ,this.queryTypes);
-	    this.searchQueryBox.innerHTML = html;
-	  }
+    let polylinePoints = '';
+    temperatures.forEach( (t, i) => {
+      let y = values[i];///1e-25;
+      polylinePoints+= ' '+this.xRel*t+' -'+this.yRel*(y - this.yMin);
+    });
+    svg.addPolyline(this.plotArea, polylinePoints, 'plotSpin1');
+  }
 
-	 ///********* DELETE?
-	  showSearchResults(){
-	    /*
-	    this.searchPage.style.display= 'none';
-	    this.resultsPage.style.display= 'block';
-	*/
-	    //if (this.userGuidance) UserGuidance.show(false);
-	  }
+}
 
 
-	  showSearchPage(){
-	    /*
-	    this.searchPage.style.display= 'block';
-	    this.resultsPage.style.display= 'none';
-
-	    if (this.userGuidance){
-	      setTimeout(() => {
-	        UserGuidance.init(this.addButtonsBox, this.elementTable.element,
-	          this.searchBox, this.propertiesBox.tabsElement);
-	        UserGuidance.show(true, this.currentTab === 'element',
-	          this.currentTab === 'props');
-	      }, 400);
-	    }
-	    */
-	  }
+// EXPORTS
+module.exports = HelmholtzPlotter;
 
 
-	  _sortElements(elements){
-	    let numbers = [];
-	    let sortedElements = [];
-	    elements.forEach( e => numbers.push(util.ELEMENTS.indexOf(e)) );
-	    numbers.sort( (a, b) => a - b ); // atomic number-1
-	    numbers.forEach( n => sortedElements.push(util.ELEMENTS[n]) );
-	    //console.log('_sortElements ',numbers, elString);
-	    return sortedElements;
-	  }
+/***/ }),
+/* 31 */
+/***/ (function(module, exports, __webpack_require__) {
 
 
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
 
+ /*
+ Implements a graphical UI component composed of
+ a phonon DOS plotter (PhononDOSPlotter class, implemented in thsi file) and a
+ BSPlotter (showing Phonon Dispersion)
+ */
+
+
+let BSPlotter = __webpack_require__(7);
+let InteractivePlotterBase = __webpack_require__(8);
+let svg = __webpack_require__(2);
+let util = __webpack_require__(0);
+
+
+class PhononDispDOSPlotter{
+
+  constructor() {
+    this.element = document.createElement('div');
+    //this.element.setAttribute('id','elementable');
+    this.parentElement= null;
+    this.dispPlotter= new BSPlotter();
+    this.dispPlotter.setPhononMode();
+
+    this.dosPlotter= new PhononDOSPlotter();
+  }
+
+
+  attach(element, width, height){
+    element.appendChild(this.element);
+    this.dispPlotter.attach(this.element, height, height);
+    this.dosPlotter.attach(this.element, undefined, height);
+    this.parentElement= element;
+  }
+
+
+  isAttached(){
+    return this.parentElement !== null;
+  }
+
+
+  setUpAndData(dispData, dosData){
+
+    this.hasDispData = (dispData !== undefined && dispData !== null);
+    this.hasDosData = (dosData !== undefined && dosData !== null);
+
+    if (this.hasDispData){
+      this.dispPlotter.setBandStructureData(dispData);
+      if (this.hasDosData)
+        this.dispPlotter.setRepaintListener( (yZoom, yOffset) => {
+          this.dosPlotter.setYZoomAndOffset(yZoom, yOffset);
+          this.dosPlotter.repaint();
+        });
+    }else
+      this.dispPlotter.setNoData();
+
+    if (this.hasDosData){
+      this.dosPlotter.setPoints(dosData);
+      if (this.hasDispData)
+        this.dosPlotter.setRepaintListener( (yZoom, yOffset) => {
+          this.dispPlotter.setYZoomAndOffset(yZoom, yOffset);
+          this.dispPlotter.repaint();
+        });
+    }else
+      this.dosPlotter.setNoData();
+  }
+
+  setNoData(){
+    this.dispPlotter.setNoData();
+    this.dosPlotter.setNoData();
+  }
+
+}
+
+
+
+class PhononDOSPlotter extends InteractivePlotterBase{
+
+  constructor() {
+    super({left: 4, right: 16, top: 0, bottom: 30});
+    this.outOfRangeColorActivated = false;
+  }
+
+  // detach if necessary and attach
+  attach(element, width, height){
+    super.attach(element, height/2+this.margins.left, height);
+  }
+
+
+  setPoints(points){
+
+    this.pointsSpin1 = [];
+    this.pointsSpin2 = [];
+    this._reset();
+
+    let pSpin1= points.dos_values[0];
+    let pSpin2 = null;
+    if (points.dos_values.length === 2)  pSpin2 = points.dos_values[1];
+    let pointsY= points.dos_energies;
+    let pointsXInPlotRange = [];
+    let pointsYInPlotRange = [];
 
-	  _reduceFormula(formula, getTokens = true){
-	    let index = 0;
-	    let map = new Map();
-	    let key;
-	    while ( index < formula.length ){
-	      let el2 = formula.substring(index, index+2);
-	      let el1 = formula.substring(index, index+1);
-
-	      if (util.ELEMENTS.indexOf(el2) >= 0){
-	        map.set(el2, 1); // 1 default value
-	        index += 2;
-	        key = el2;
-	        //console.log('eleemnt 2chars', key);
-	      }else if (util.ELEMENTS.indexOf(el1) >= 0){
-	        map.set(el1, 1); // 1 default value
-	        index++;
-	        key = el1;
-	        //console.log('eleemnt 1chars', key);
-	      }else{ // It's a number
-	        let num = parseInt(el2);
-	        if (num >= 10) index += 2; // 2 figures number
-	        else index++;// 1 figure number
-	        //console.log('number ', num, key);
-	        map.set(key, num);
-	      }
-	      // console.log('FINAL LOOP', map, index);
-	    }
-
-	    let counter = 0;
-	    while ( !checkIfReduced(map) ){ // console.log('Reducing', map);
-	      let div = 1;
-	      if (isDivisibleBy(map, 2)) div = 2;
-	      else if (isDivisibleBy(map, 3)) div = 3;
-	      else if (isDivisibleBy(map, 5)) div = 5;
-	      else if (isDivisibleBy(map, 7)) div = 7;
-	      else if (isDivisibleBy(map, 11)) div = 11;
-
-	      map.forEach( (value, key) => {
-	        map.set(key, (value/div));
-	      });
-	      //console.log('Reducing DIV', map);
-	      counter++;
-	      if (counter > 5) break;
-	    }
-
-	    function checkIfReduced(formulaMap){
-	      let min = 100;
-	      formulaMap.forEach( (value, key) => {
-	        if (value < min) min = value;
-	      });
-	      return min === 1;
-	    }
-
-	    function isDivisibleBy(formulaMap, n){
-	      let div = true;
-	      formulaMap.forEach( (value, key) => {
-	        if (value % n !== 0) div = false;
-	      });
-	      return div;
-	    }
-
-	    let tokens = [];
-	    let canonicalFormula = '';
-	    if (getTokens){
-	      map.forEach( (value, key) => tokens.push(key+value) );
-	    }else{
-	      let sortedElements = this._sortElements( Array.from( map.keys() ) );
-	      sortedElements.forEach( element => {
-	        canonicalFormula += element+map.get(element);
-	        //canonicalFormula += element+(map.get(element) === 1 ? '' : map.get(element));
-	      });
-	    }
-
-
-	    console.log('_reduceFormula RETURN: ', map, tokens, canonicalFormula);
-	    return (getTokens ? tokens : canonicalFormula);
-	  }
+    for (var i = 0; i < pointsY.length; i++) {
+        let frecuency = pointsY[i]*5.034117012222e22;
+        let dosSpin1 = pSpin1[i]*0.029979;
+        let dosSpin2;
+        if (pSpin2 !== null)  dosSpin2 = pSpin2[i]*0.029979246;
+        //console.log('POINTS : ',frecuency);
+        pointsXInPlotRange.push(dosSpin1);
+        if (pSpin2 !== null) pointsXInPlotRange.push(dosSpin2);
+        pointsYInPlotRange.push(frecuency);
+        //console.log('POINTS : ',pointsX[i], energy);
+        this.pointsSpin1.push({x: dosSpin1, y: frecuency});
+        if (pSpin2 !== null) this.pointsSpin2.push({x: dosSpin2, y: frecuency});
+    }
+
+    let maxDosVal = Math.max.apply(null, pointsXInPlotRange);
+    let maxEnergyVal = Math.max.apply(null, pointsYInPlotRange);
+    let minEnergyVal = Math.min.apply(null, pointsYInPlotRange);
+
+    // x axis steps generation
+    let t = util.generateDiagramSteps(maxDosVal);
+    let xSteps = t[0], exp = t[1];
+
+    //console.log('formattedPoints paintPointsLine : ', this.formattedPoints.length);
+    this.setAxisRangeAndLabels(null,0,xSteps[xSteps.length-1]/*maxDosVal*1.2*/,
+      null,-50,320,minEnergyVal, maxEnergyVal, 100);
+
+    svg.addText(this.axisGroup, this.plotRangeX/2, this.margins.bottom,
+      'DOS (states/cm⁻¹)', 'middle', 'axis-steps-big');
+
+    for (let i = 0; i < xSteps.length; i++) {
+      let stepX = (this.plotRangeX*xSteps[i])/xSteps[xSteps.length-1];
+      svg.addLine(this.axisGroup, stepX, 0, stepX, 3, 1);
+      //console.log('step ',xSteps[i], stepX);
+      svg.addText(this.axisGroup, stepX, 13,
+        (i === 0 ? '0' : xSteps[i].toFixed(exp)), 'middle', 'axis-steps-smaller');
+    }
+
+    this.repaint();
+  }
+
+
+  repaintData(){
+    let polylinePoints = '';
+    for (var i = 0; i < this.pointsSpin1.length; i++) {
+      polylinePoints+= ' '+this.xRel*this.pointsSpin1[i].x+
+        ' '+this.transformY(this.pointsSpin1[i].y);
+        //console.log('POINTS LAT : ',this.formattedPoints[i].x, this.formattedPoints[i].y);
+    }
+    svg.addPolyline(this.plotContent, polylinePoints, 'plotSpin1');
+
+    polylinePoints = '';
+    for (var i = 0; i < this.pointsSpin2.length; i++) {
+      polylinePoints+= ' '+this.xRel*this.pointsSpin2[i].x+
+        ' '+this.transformY(this.pointsSpin2[i].y);
+        //console.log('POINTS LAT : ',this.formattedPoints[i].x, this.formattedPoints[i].y);
+    }
+    svg.addPolyline(this.plotContent, polylinePoints, 'plotSpin2');
+
+  }
+}
+
+// EXPORTS
+module.exports = PhononDispDOSPlotter;
 
 
-	  _processFormula(formula, type){
-	    let index = 0;
-	    let map = new Map();
-	    let key;
-	    while ( index < formula.length ){
-	      let el2 = formula.substring(index, index+2);
-	      let el1 = formula.substring(index, index+1);
-
-	      if (util.ELEMENTS.indexOf(el2) >= 0){
-	        map.set(el2, 1); // 1 default value
-	        index += 2;
-	        key = el2;
-	        //console.log('eleemnt 2chars', key);
-	      }else if (util.ELEMENTS.indexOf(el1) >= 0){
-	        map.set(el1, 1); // 1 default value
-	        index++;
-	        key = el1;
-	        //console.log('eleemnt 1chars', key);
-	      }else{ // It's a number
-	        let num = parseInt(el2);
-	        if (num >= 10) index += 2; // 2 figures number
-	        else index++;// 1 figure number
-	        //console.log('number ', num, key);
-	        map.set(key, num);
-	      }
-	      // console.log('FINAL LOOP', map, index);
-	    }
-
-
-
-	    if (type === 'tokens'){
-	      let tokens = [];
-	      map.forEach( (value, key) => tokens.push(key+value) );
-	      console.log('_processFormula RETURN: ', map, tokens);
-	      return tokens;
-	    }else{
-	      let sortedElements = this._sortElements( Array.from( map.keys() ) );
-	      if (type === 'canonical-formula'){
-	        let formulaString = '';
-	        sortedElements.forEach( element => {
-	          formulaString += element+map.get(element);
-	        });
-	        console.log('_processFormula RETURN: ', map, formulaString);
-	        return formulaString;
-	      }else{ // elements-string
-	        let elementsString = '';
-	        let elementsInFormulas = [];
-	        sortedElements.forEach( element => {
-	          elementsString += element;
-	          let val = map.get(element);
-	          if (val !== 0) elementsInFormulas.push(element+val);
-	        });
-	        console.log('_processFormula RETURN: ', map, [elementsInFormulas ,elementsString]);
-	        return [elementsInFormulas ,elementsString];
-	      }
-	    }
+/***/ }),
+/* 32 */
+/***/ (function(module, exports, __webpack_require__) {
 
-	  }
+"use strict";
 
-	}
 
+/*
+Pending to implement
+*/
 
-	class FormulaBox{
 
-	  constructor() {
-	    this.element = document.createElement('div');
-	    this.element.setAttribute("id",'formula-box');
-	    this.element.innerHTML=
-	    `
-	    <div style="padding-bottom: 20px;">
-	<!--
-	    <input type="checkbox" class="allow-other-elements" value="">
-	      Allow other elements
-	      <br>
+let DetailsViewBase = __webpack_require__(6);
+let util = __webpack_require__(0);
+let InfoSys = __webpack_require__(3);
+//let DataStore = require('./DataStore.js');
 
 
-	    <input type="checkbox" class="multiples-of-formula" value="">
-	      Include multiples of formula
-	      <br> -->
 
-	    <input type="text" class="formula-text-field"
-	      placeholder="Add formula to the search query above" >
-	      <button class="adding-formula-btn" disabled>Add to query</button>
-	    </div>
-	    `;
-	    this.formulaTextField = this.element.querySelector('.formula-text-field');
-	    this.formulaButton = this.element.querySelector('.adding-formula-btn');
+class ElasticConstDetails extends DetailsViewBase {
 
-	    this.formulaButton.addEventListener( "click", (e) => {
-	      this.addFormulaListener(this.formulaTextField.value);
-	      this.formulaTextField.value = '';
-	    });
+  constructor() {
+    super('Elastic constants');
 
-	    this.formulaTextField.addEventListener( 'input', e => {
-	      //console.log('formulaTextField input: ',this.formulaTextField.value);
-	      this.formulaButton.disabled = (this.formulaTextField.value === '');
-	    });
+    this.sortedLeafs = [];
+    this.markedCalc = null;
 
-	  }
+    this.element.innerHTML+=`
 
+      <div style="float: left; width: 27%;">
+        <div class="view-box">
+          <div class="title">Calculation </div>
+          <div class="navTreeWrapper"></div>
+        </div>
+      </div>
 
-	  setAddFormulaListener(listener) {
-	    this.addFormulaListener= listener;
-	  }
+      <div style="float: right; width: 73%;">
+        <div class="view-box">
+          <div class="title">Elastic constants</div>
 
+          <div>Parameters</div>
+          <div ></div>
 
-	  disable(bool) {
-	    this.formulaTextField.disabled = bool;
-	    this.formulaButton.disabled = true;//bool;
-	  }
 
-	/*
-	  getAllowOtherElements(){
-	    return  this.element.querySelector('.allow-other-elements').checked;
-	  }
+        </div>
+      </div>
 
+      <div style="clear: both;"></div>
+    `;
 
-	  getMultiplesOfFormula(){
-	    return  this.element.querySelector('.multiples-of-formula').checked;
-	  }*/
+    this.navTreeWrapper =
+        this.element.querySelector('.navTreeWrapper');
 
-	}
 
+    // For static ones
+    InfoSys.addToInfoSystem(this.element);
 
-	class MaterialNameBox{
-
-	  constructor() {
-	    this.element = document.createElement('div');
-	    this.element.setAttribute("id",'material-name-box');
-	    this.element.innerHTML=
-	    ` <div style="padding-bottom: 20px;">
-	      <input type="text" class="name-text-field"
-	        placeholder="Add a material name to the search query above" >
-	        <button class="adding-name-btn" disabled>Add to query</button>
-	      </div>
-	    `;
-	    this.textField = this.element.querySelector('.name-text-field');
-	    this.button = this.element.querySelector('.adding-name-btn');
-
-	    this.button.addEventListener( "click", (e) => {
-	      this.listener(this.textField.value);
-	      this.textField.value = '';
-	    });
+    this._events();
+  }
 
-	    this.textField.addEventListener( 'input', e => {
-	      //console.log('formulaTextField input: ',this.formulaTextField.value);
-	      this.button.disabled = (this.textField.value === '');
-	    });
 
-	  }
+  _events() {
+    //super._events();
+/*
+    this.dataTableWrapper.addEventListener('click', (e) => {
 
+      let rowElement = e.target.parentElement;
+      if (rowElement.className.indexOf('data-row') < 0)
+        rowElement = rowElement.parentElement;
+      //console.log("TABLE EVENT ",rowElement);
 
-	  setAddMaterialNameListener(listener) {
-	    this.listener = listener;
-	  }
+      if (rowElement.className.indexOf('data-row') >= 0){
+        let id= rowElement.getAttribute('data-calc-id');
 
 
-	  disable(bool) {
-	    this.textField.disabled = bool;
-	    this.button.disabled = true;//bool;
-	  }
-	}
+      }
 
-	// EXPORTS
-	module.exports = NewSearchMod;
+    });
+*/
+  }
 
 
-/***/ },
-/* 33 */
-/***/ function(module, exports) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-	    This file implements the user guidance system. This complex system for
-	    showing tips to the user is specified in the project documentation 
-	 */
-
-
-	"use strict";
-
-	//let util = require('util.js');
-
-	let body = document.querySelector('body');
-	let tips = [];
-	let tipData = [];
-	let currentTip;// = 1;
-	let independentTips = []; // if null => showing else if 'off' not showing
-	let addBox, table, searchBox, propertiesTabs;
-	let searchBarShowing = false;
-
-
-	function createUserMsg(i, width){
-	  let element= document.createElement('div');
-	  element.setAttribute('class','user-guidance');
-	  element.innerHTML = '<img src="img/tip'+i+'.png" width="'+width+'px" />';
-	  element.style.position = 'absolute';
-	  element.style.display = 'none';
-	  body.appendChild(element);
-	  return element;
-	}
 
+  updateSelection( leafIds /*Set*/){
+    console.log('ElasticDetails updateSelection ',leafIds);
 
-	function showTip(tipNumber){
-	  if (tipNumber === 8 && !searchBarShowing) return; // Do nothing
-	  if (tipNumber === 4 && !searchBarShowing) return; // Do nothing
+  }
 
-	  let r = tipData[tipNumber].domTarget.getBoundingClientRect();
-	//console.log("GGGGGGGGG: ",r);
-	  tips[tipNumber].style.top = (r.top + tipData[tipNumber].top + window.pageYOffset)+'px';
-	  tips[tipNumber].style.left = (r.left + tipData[tipNumber].left)+'px';
-	  tips[tipNumber].style.display = 'block';
-	}
 
-	// Init per user session
-	function init(addBoxP, tableP, searchBoxP, propertiesTabsP){
-	  addBox = addBoxP;
-	  table = tableP;
-	  searchBox = searchBoxP;
-	  propertiesTabs = propertiesTabsP;
-
-	  independentTips[3] = localStorage.getItem('tip3');
-	  independentTips[4] = localStorage.getItem('tip4');
-	  independentTips[7] = localStorage.getItem('tip7');
-
-	  createUserTips();
-	  let currentTip = localStorage.getItem('currentTip');
-	  if (currentTip === null){ // First time
-	    updateCurrentTip(1);
-	  }else{
-	    currentTip = parseInt(currentTip);
-	    if (currentTip < 10){ // regular case
-	      updateCurrentTip(currentTip);
-	    }//else {  currentTip === 10 the guidance has finished
-	  }
-	}
+  updateMarkedLeaf(leafId){
 
+/* Do nothing for now...
+    this.markedCalc = leafId;
+    let rowElement= this.element.querySelector('.data-row-marked');
+    if (rowElement !== null) rowElement.className= 'data-row';
 
-	function createUserTips(){
-
-	  if (tips.length === 0){
-	    tips[1] = createUserMsg(1, 220);
-	    tipData[1] = {domTarget: addBox, top: -70, left: -240 };
-	    tips[2] = createUserMsg(2, 280);
-	    tipData[2] = {domTarget: addBox, top: -110, left: 80 };
-	    tips[3] = createUserMsg(3, 180);
-	    tipData[3] = {domTarget: table, top: 180, left: 720 };
-	    tips[4] = createUserMsg(4, 240);
-	    tipData[4] = {domTarget: searchBox, top: 45, left: -250 };
-	    tips[5] = createUserMsg(5, 210);
-	    tipData[5] = {domTarget: addBox, top: -130, left: 70};
-	    tips[6] = createUserMsg(6, 240);
-	    tipData[6] = {domTarget: addBox, top: -100, left: 370};
-	    tips[7] = createUserMsg(7, 220);
-	    tipData[7] = {domTarget: propertiesTabs, top: 160, left: -40};
-	    tips[8] = createUserMsg(8, 240);
-	    tipData[8] = {domTarget: searchBox, top: 30, left: 760};
-
-	    // Event
-	    tips[1].addEventListener( "click", closeAndShowNext);
-	    tips[2].addEventListener( "click", closeAndShowNext);
-	    tips[3].addEventListener( "click", e => { closeIndependentTip(3) });
-	    tips[4].addEventListener( "click", e => { closeIndependentTip(4) });
-	    tips[5].addEventListener( "click", closeAndShowNext);
-	    tips[6].addEventListener( "click", closeAndShowNext);
-	    tips[7].addEventListener( "click",  e => { closeIndependentTip(7) });
-	    tips[8].addEventListener( "click", e => {
-	      e.target.style.display = 'none';
-	      updateCurrentTip(10);
-	    });
-	  }
-	}
+    if (this.markedCalc  !== null){
+      let rowElement1= document.querySelector('tr[data-calc-id="'+this.markedCalc+'"]');
+      if (rowElement1 !== null) rowElement1.className= 'data-row-marked';
+    }
+    */
+  }
 
+}
 
-	function setFinal(){
-	  searchBarShowing = true;
-	  if (currentTip < 10){
-	    tips[currentTip].style.display = 'none';
-	    updateCurrentTip(8);//currentTip = 4;
-	    showTip(currentTip);
-	  }
-	  showIndependentTip(4, true);
-	}
 
+// EXPORTS
+module.exports = ElasticConstDetails;
 
-	function closeIndependentTip( tipNumber){
-	  //e.preventDefault();
-	  tips[tipNumber].style.display = 'none';
-	  localStorage.setItem('tip'+tipNumber, 'off');
-	  independentTips[tipNumber] = 'off';
-	}
 
+/***/ }),
+/* 33 */
+/***/ (function(module, exports, __webpack_require__) {
 
-	function closeAndShowNext(e){
-	  e.preventDefault();
-	  //console.log("closeAndShowNext",currentTip);
-	  e.target.style.display = 'none';
+"use strict";
 
-	  switch (currentTip) {
-	    case 2:  currentTip = 5;  break;
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
 
-	    case 6:  currentTip = 8;  break;
 
-	    default: // 1 , 5
-	      currentTip++;
-	  }
-	  updateCurrentTip(currentTip);
-	  showTip(currentTip);
-	}
+ /*
+   This file implements the Search Module of the application.
+   It's a container UI component that shows the seach part of the application:
+   front search interface and search results page.
+ */
 
 
-	function showIndependentTip(tipNumber, value){
-	  //console.log("showIndependentTip",tipNumber);
-	  if (independentTips[tipNumber] === null){ // Tip has not been removed (clicked)
-	    if (value) showTip(tipNumber);
-	    else tips[tipNumber].style.display = 'none';
-	  }
-	}
 
+let util = __webpack_require__(0);
+let UserGuidance = __webpack_require__(15);
+let ElementTable = __webpack_require__(34);
+let MaterialList = __webpack_require__(35);
+//let PropertiesBox = require('./PropertiesBox.view.js');
+let FilterPanel = __webpack_require__(36);
+let SwitchComponent = __webpack_require__(10);
 
 
 
-	function show(value, tip3, tip7){ // Global show - the UserGuidance is shown or hidden at all
-	  if (currentTip < 10){ // sequential tips
-	    if (value) showTip(currentTip);
-	    else tips[currentTip].style.display = 'none';
-	  }
-	  // Independent tips
-	  showIndependentTip(3, value && tip3);
-	  showIndependentTip(4, value);
-	  showIndependentTip(7, value && tip7);
-	}
+// local utility functions
+function getTagHtml(tag, isFormula){
+  return `<span class="search-label" data-el="${tag}" >
+            <img src="img/tag.svg" height="16px" class="remove-label"
+              style="vertical-align: bottom"/>
+          ${isFormula ? util.getSubscriptedFormula(tag) : tag}
+          <img src="img/cross.svg" height="6px" class="remove-label"
+            style="vertical-align: middle; padding: 4px 3px 6px 5px;" />
+          </span>`;
+}
 
 
-	function updateCurrentTip(value){
-	  currentTip = value;
-	  localStorage.setItem('currentTip', value);
-	  //console.log('localStorage.currentTip:',localStorage.getItem('currentTip'));
-	}
+function replaceDashes(s){
+  return s.split('-').join('_');
+}
 
 
 
+class NewSearchMod {
 
-	// EXPORTS
-	module.exports = {init, setFinal, show, showIndependentTip}
+  constructor() {
 
+    this.userGuidance = true; // can enabled/disabled
 
-/***/ },
-/* 34 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-	   This is the UI component implementing the interactive  Element Table
-	   in the search front. It need to communicate to other UI components
-	   so it exposes several listeners
-	 */
-
-	"use strict";
-
-	let util = __webpack_require__(1);
-
-
-	// constans
-
-	const GROUPS = new Map([
-	  [1,['H', 'Li', 'Na', 'K', 'Rb', 'Cs', 'Fr']],
-	  [2,['Be', 'Mg', 'Ca', 'Sr', 'Ba', 'Ra']],
-	  [3,['Sc', 'Y']],
-	  [4,['Ti', 'Zr', 'Hf', 'Rf']],
-	  [5,['V', 'Nb', 'Ta', 'Ha']],
-	  [6,['Cr', 'Mo', 'W', 'Sg']],
-	  [7,['Mn', 'Tc', 'Re', 'Ns']],
-	  [8,['Fe', 'Ru', 'Os', 'Hs']],
-	  [9,['Co', 'Rh', 'Ir', 'Mt']],
-	  [10,['Ni', 'Pd', 'Pt', 'Ds']],
-	  [11,['Cu', 'Ag', 'Au', 'Rg']],
-	  [12,['Zn', 'Cd', 'Hg', 'Cn']],
-	  [13,['B', 'Al', 'Ga', 'In', 'Tl', 'Nh']],
-	  [14,['C', 'Si', 'Ge', 'Sn', 'Pb', 'Fl']],
-	  [15,['N', 'P', 'As', 'Sb', 'Bi', 'Mc']],
-	  [16,['O', 'S', 'Se', 'Te', 'Po', 'Lv']],
-	  [17,['F', 'Cl', 'Br', 'I', 'At', 'Ts']],
-	  [18,['He', 'Ne', 'Ar', 'Kr', 'Xe','Rn', 'Og']],
-	  [19,['La','Ce','Pr','Nd','Pm','Sm','Eu','Gd','Tb','Dy','Ho','Er','Tm','Yb','Lu']],
-	  [20,['Ac','Th','Pa','U','Np','Pu','Am','Cm','Bk','Cf','Es','Fm','Md','No','Lr']]
-	]);
-
-	const BLOCKS = new Map([
-	  ['metalloids',['B', 'Si', 'Ge', 'As', 'Sb', 'Te', 'Po']],
-	  ['other-non-metals',['H', 'C', 'N', 'O', 'P', 'S', 'Se']],
-	  ['halogens',['F', 'Cl', 'Br', 'I', 'At', 'Ts']],
-	  ['noble-gases',['He', 'Ne', 'Ar', 'Kr', 'Xe','Rn', 'Og']],
-	  ['alkali-metals',['Li', 'Na', 'K', 'Rb', 'Cs', 'Fr']],
-	  ['alkaline-earth-metals',['Be', 'Mg', 'Ca', 'Sr', 'Ba', 'Ra']],
-	  ['lanthanoids',['La','Ce','Pr','Nd','Pm','Sm','Eu','Gd','Tb','Dy','Ho','Er'
-	    ,'Tm','Yb','Lu']],
-	  ['actinoids',['Ac','Th','Pa','U','Np','Pu','Am','Cm','Bk','Cf','Es','Fm'
-	    ,'Md','No','Lr']],
-	  ['transition-metals', ['Sc', 'Y','Ti', 'Zr', 'Hf', 'Rf','V','Nb','Ta','Ha'
-	    ,'Cr','Mo','W','Sg','Mn','Tc','Re','Ns','Fe','Ru','Os','Hs','Co','Rh','Ir'
-	    , 'Mt','Ni','Pd','Pt', 'Ds', 'Cu','Ag','Au', 'Rg', 'Zn','Cd','Hg', 'Cn']],
-	  ['post-transition-metals', ['Al','Ga', 'In', 'Tl', 'Nh', 'Sn', 'Pb', 'Fl', 'Bi', 'Mc', 'Lv']]
-	]);
-
-	const BLOCKS_COLORS = new Map([
-	  ['metalloids','#F9E298'],
-	  ['other-non-metals','#F2B01D'],
-	  ['halogens','#85ADC1'],
-	  ['noble-gases','#F7D660'],
-	  ['alkali-metals','#D04629'],
-	  ['alkaline-earth-metals','#F7B57D'],
-	  ['transition-metals', '#F58737'],
-	  ['post-transition-metals', '#AE4747'],
-	  ['lanthanoids','#3B91AE'],
-	  ['actinoids','#E97147']
-	]);
-
-	let elementNames = ['Hydrogen',  'Helium', 'Lithium', 'Beryllium',
-	    'Boron',  'Carbon',  'Nitrogen',  'Oxygen',  'Fluorine',
-	    'Neon', 'Sodium', 'Magnesium', 'Aluminum', 'Silicon',
-	    'Phosphorus',  'Sulfur',  'Chlorine', 'Argon', 'Potassium',
-	    'Calcium', 'Scandium', 'Titanium', 'Vanadium',  'Chromium',
-	    'Manganese', 'Iron', 'Cobalt', 'Nickel', 'Copper',
-	    'Zinc', 'Gallium', 'Germanium', 'Arsenic', 'Selenium',
-	    'Bromine', 'Krypton', 'Rubidium', 'Strontium', 'Yttrium',
-	    'Zirconium', 'Niobium', 'Molybdenum', 'Technetium', 'Ruthenium',
-	    'Rhodium', 'Palladium', 'Silver', 'Cadmium', 'Indium',
-	    'Tin', 'Antimony', 'Tellurium', 'Iodine',  'Xenon',
-	    'Cesium', 'Barium', 'Lanthanum', 'Cerium', 'Praseodymium',
-	    'Neodymium', 'Promethium', 'Samarium', 'Europium', 'Gadolinium',
-	    'Terbium', 'Dysprosium', 'Holmium', 'Erbium', 'Thulium',
-	    'Ytterbium', 'Lutetium', 'Hafnium', 'Tantalum', 'Tungsten',
-	    'Rhenium', 'Osmium', 'Iridium', 'Platinum', 'Gold',
-	    'Mercury', 'Thallium', 'Lead', 'Bismuth', 'Polonium',
-	    'Astatine', 'Radon', 'Francium', 'Radium', 'Actinium',
-	    'Thorium', 'Protactinium', 'Uranium',  'Neptunium', 'Plutonium',
-	    'Americium', 'Curium', 'Berkelium', 'Californium', 'Einsteinium',
-	    'Fermium', 'Mendelevium', 'Nobelium', 'Lawrencium', 'Rutherfordium',
-	    'Dubnium', 'Seaborgium', 'Bohrium', 'Hassium', 'Meitnerium', 'Darmstadtium',
-	    'Roentgenium', 'Copernicium', 'Nihonium', 'Flerovium', 'Moscovium',
-	    'Livermorium', 'Tennessine', 'Oganesson'
-	];
-
-
-	// utility functions
-
-	function getElementBlock(elSymbol){
-	  let block;
-	  BLOCKS.forEach(function(value, key) {
-	    //console.log(key + " " + value);
-	    if (value.indexOf(elSymbol) >= 0)
-	      block= key;
-	  });
-	  return block;
-	}
+    //this.showingSearchBox = false;
+    this.searchQuery = [];
+    this.queryTypes = []; //**** Types associated to query elements
+    // Types: element (E), formula (F), symbol (S) and prop names
+    this.searchFilters = [];
 
+    this.currentOperator = 'AND';
+
+    this.element = document.createElement('div');
+    this.element.setAttribute("id",'search-module');
+    this.element.innerHTML=
+    `
+      <div class="search-filter-side">
 
-	let CELL_WIDTH= 36;
+        <div>Filters</div>
+
+        <!-- <div id="filter-panel-placeholder">  </div> -->
+
+      </div>
+
+      <div class="search-main-side">
 
-	function getCellHtml(elNum){
-	  let elSymbol= util.ELEMENTS[elNum-1];
-	  return '<td class="cell '+getElementBlock(elSymbol)+'" data-el="el-'+elSymbol+'">'+
-	          '<b>'+elSymbol+'</b> <div>'+elNum+'</div> </td>';
-	}
+        <div class="search-box" >
+          <div class="search-query-wrapper" >
+            <div class="search-query-box" style="float: left;">
+            </div>
+            <button class="clean-btn" style="float: right;">Clear all</button>
+          </div>
+
+          <button class="search-btn" >Search</button>
+
+        </div>
+
+        <input type="checkbox" id="multiples-of-formula" value="">
+          Include multiples of formula
+          <br>
+        <input type="checkbox" id="allow-other-elements" value="">
+          Allow other elements
+        <br>
+
+
+
+        <div class="add-buttons" >
+          <div  class="tab-buttons" style="width: 70%; display: inline-block">
+            <button class="element-add-btn" id="add-tab-selected">Element</button>
+            <button class="formula-add-btn" style="padding: 10px 20px;" >Formula</button>
+            <button class="name-add-btn" >Name</button>
+          </div>
+          <div class="bool-buttons" style="width: 28%; display: inline-block" >
+            OR <span id="and-or-switch" ></span> AND
+            <button >NOT</button>
+            <button class="open-parentheses" >(</button>
+            <button class="close-parentheses">)</button>
+            <!--<input type="checkbox" name="and-or" class="not-symbol-btn" />NOT-->
+          </div>
+        </div>
 
-	function getOddCellHtml(elNum){
-	  let elSymbol= util.ELEMENTS[elNum-1];
-	  return '<td class="cellpad '+getElementBlock(elSymbol)+'" data-el="el-X">'+
-	          '<b>&nbsp;</b> <div>&nbsp;</div> </td>';
-	}
 
+        <div class="add-box">
+          <div>
+            <div class="triangle element-tri" style="margin: -10px 64px; visibility: visible"></div>
+            <div class="triangle formula-tri" style="margin: -10px 30px; visibility: hidden"></div>
+            <div class="triangle name-tri" style="margin: -10px 70px; visibility: hidden"></div>
+          </div>
 
-	/**  Group selection not implemented
+          <div class="add-panel">
+          </div>
+        </div>
 
-	function getGroupSelectorHtml(num){
-	  return '<th class="group-sel" data-group="'+num+'"><div></div></th>';
-	}
+        <div class="results-panel"  >  <!-- style="display: none"-->
+        </div>
 
-	function getGroupSelectorHtmlLAcAc(num){
-	  return '<th class="group-sel-la-ac" data-group="'+num+'"><div></div></th>';
-	}*/
-
-	/************************/
-
-
-	class ElemenTable{
-
-	  constructor() {
-
-	    this.element = document.createElement('div');
-	    this.element.setAttribute('id','elementable');
-
-	    // header with dropdown
-	    let tempHtml = '<div class="element-info"></div>';
-
-	    tempHtml+= '<div class="ptWrapper">';
-
-	    tempHtml+= '<table id="pt-main">'; // table zone div
-
-	    /* Deactivated for the moment
-	    // header with group selectors
-	    tempHtml+= '<thead><tr>';//'<div id="group-selectors">';
-	    for (let i= 1; i<=18; i++){
-	      tempHtml+= getGroupSelectorHtml(i);
-	    }
-	    tempHtml+= '</tr></thead>';// selectors
-	    */
-
-	    tempHtml+= '<tbody>';
-	    // row 1
-	    tempHtml+=  '<tr>'+getCellHtml(1);
-	    tempHtml+= '<td class="cellpad" colspan="16"></td>';
-	    tempHtml+= getCellHtml(2)+'</tr>';
-
-	    let get8ElementRowHtml= (initPos) => {
-	      tempHtml+= '<tr>'+getCellHtml(initPos)+getCellHtml(initPos+1);
-	      tempHtml+= '<td class="cellpad" colspan="10"></td>';
-	      for (let i= initPos+2; i< initPos+8; i++)  tempHtml+= getCellHtml(i);
-	      tempHtml+= '</tr>';//div.row
-	    }
-
-	    // row 2 and 3
-	    get8ElementRowHtml(3);
-	    get8ElementRowHtml(11);
-
-	    // row 4,5, 6
-	    let counter= 19;
-	    for (let i= 0; i<4; i++){
-	      tempHtml+= '<tr>';
-	      for (let j= 0; j<18; j++){
-	        if (counter === 57 || counter === 89){
-	          tempHtml += getOddCellHtml(counter);
-	          counter += 15;
-	        }else{
-	          tempHtml+= getCellHtml(counter);
-	          counter++;
-	        }
-	      }
-	      tempHtml+= '</tr>';//div.row
-	    }
-
-
-	    tempHtml+= '</tbody></table>';
-
-	    // Lanthanides and Actinides
-	    tempHtml+= '<div id="specialRows"><table id="pt-laac">';
-	    for (let i= 0; i<2; i++){
-	      tempHtml+= '<tr>';
-	      counter = (i === 0 ? 57 : 89);
-	      //tempHtml+= getGroupSelectorHtmlLAcAc((i === 0 ? 19 : 20));
-	      for (let j= 0; j<15; j++){
-	        tempHtml+= getCellHtml(counter);
-	        counter++;
-	      }
-	      tempHtml+= '</tr>';//div.row
-	    }
-	    tempHtml+= '</table></div>'; //div#specialRows
-
-
-	    // Block labels
-	    tempHtml+= `<div class="legend">
-	      <div class="alkali-metals">Alkali metals</div>
-	      <div class="alkaline-earth-metals">Alkaline earth metals</div>
-	      <div class="transition-metals">Transition metals</div>
-	      <div class="post-transition-metals">Post-transition metals</div>
-	      <div class="metalloids">Metalloids</div>
-	      <div class="other-non-metals">Other nonmetals</div>
-	      <div class="halogens">Halogens</div>
-	      <div class="noble-gases">Noble gases</div>
-	      <div class="lanthanoids">Lanthanoids</div>
-	      <div class="actinoids">Actinoids</div>
-	    </div>`;//'<div id="group-selectors">';
-
-
-	    tempHtml+= '</div>'; // ptWrapper
-
-	    this.element.innerHTML= tempHtml;
-	    this.elementInfo= this.element.getElementsByClassName('element-info')[0];
-	    this.tableZone= this.element.getElementsByClassName('ptWrapper')[0];
-	    //this.specialRows= this.element.querySelector('#specialRows');
-
-	    this._events();
-	  }
+      </div> <!-- search-main-side -->
+    `;
 
+    this.filterSidePanel = this.element.querySelector('.search-filter-side');
+    this.searchQueryBox= this.element.getElementsByClassName("search-query-box")[0];
+    this.searchBox = this.element.querySelector('.search-box');
 
-	  _events() {
-
-	    // One listener for all diferent clicks (simple element, group)
-	    var adhocListener= (e) => {
-
-	      if (e.target !== e.currentTarget) { // When the event source is a child
-	        let className = e.target.className;
-	        let element = e.target;
-	        if (className  === ''){
-	          element= e.target.parentElement;
-	          className = e.target.parentElement.className;
-	        }
-
-	        if (className.indexOf('cellpad') >= 0) return; // structural empty table cells
-
-	        if (className.indexOf('group-sel') >= 0){ // group selector cells
-	          //*** Not working at the moment - group selection deactivated
-	          let elements=  GROUPS.get(parseInt(element.getAttribute('data-group')));
-	          //console.log("group-sel "+elements);
-	          this.clickListener(elements);//let done =
-	          //if (done)
-	          for (var i = 0; i < elements.length; i++)
-	            this.selectElement(elements[i]);
-
-	        }else if (className.indexOf('cell') >= 0){  // element cells
-	          let html= element.innerHTML;
-	          let elSymbol= html.substring(3,html.indexOf('<',3));
-	          if (elSymbol === '&nbsp;') return;  // blank cells
-	          //console.log("elSymbol-sel "+elSymbol);
-	          if (className.indexOf('el-selected') >= 0){ // If selected
-	            this.deselectListener(elSymbol);//this.deselectElement(elSymbol);
-	          }else{ // If not selected
-	            this.clickListener([elSymbol]);//let done = this.clickListener([elSymbol]);
-	            this.selectElement(elSymbol);//if (done) this.selectElement(elSymbol);
-	          }
-	        }
-	      }
-	      //e.stopPropagation();
-	    };
-
-	    // Event listener set in the root div element
-	    this.tableZone.addEventListener('click',adhocListener,true);
-
-	    this.tableZone.addEventListener('mouseover',e => {
-
-	      let elSymbol= getElement(e);
-	      //console.log("ENTERIG elSymbol-sel "+elSymbol);
-	      if (elSymbol !== null){
-	          //console.log("elSymbol-sel "+elSymbol);
-	          this.elementInfo.style.display = 'block';
-	          let borderColor= BLOCKS_COLORS.get(getElementBlock(elSymbol));
-	          this.elementInfo.style.borderColor = borderColor;
-	          let number= util.ELEMENTS.indexOf(elSymbol)+1;
-	          this.elementInfo.innerHTML= `
-	          <div>
-	            <div style="float: right; padding: 3px 4px;border-left: 3px solid ${borderColor};
-	              border-bottom: 3px solid ${borderColor}" > ${number} </div>
-	            <div style="clear: right;"></div>
-	          </div>
-	          <div class="symbol">${elSymbol} </div>
-	          <div class="">${elementNames[number-1]}  </div>
-	          `
-	      }
-	    });
+    this.mainButton= this.element.querySelector('.search-btn');
+    this.cleanButton= this.element.querySelector('.clean-btn');
+    this.addButtonsBox= this.element.querySelector('.add-buttons');
+    this.addElementButton = this.addButtonsBox.querySelector('.element-add-btn');
+    this.addFormulaButton = this.addButtonsBox.querySelector('.formula-add-btn');
+    this.addMatNameButton = this.addButtonsBox.querySelector('.name-add-btn');
 
-	    this.tableZone.addEventListener('mouseout',e => {
-	      let element= getElement(e);
-	      if (element !== null) this.elementInfo.style.display = 'none';
-	    });
+    this.addPanel= this.element.querySelector('.add-panel');
 
-	  }
+    let andOrSwitch = new SwitchComponent(util.IMAGE_DIR+'switch');
+    this.element.querySelector('#and-or-switch').appendChild(andOrSwitch.element);
+    andOrSwitch.setListener( e => {
+      this.currentOperator = ( e ? 'AND' : 'OR');
+    });
+
+    this.openParenthButton = this.element.querySelector('.open-parentheses');
+    this.closeParenthButton = this.element.querySelector('.close-parentheses');
+    this.openParenthButton.addEventListener( 'click', e => {
+      this._addParenthesesInSearchQuery(true);
+    });
+    this.closeParenthButton.addEventListener( 'click', e => {
+      this._addParenthesesInSearchQuery(false);
+    });
+
+    this.elementTable= new ElementTable();
+    this.elementTable.setClickListener(elementArray => {
+      this.addElementsInSearchQuery(elementArray);
+      this.addMatNameButton.disabled = true; // Not always necessary but it simplifies the code
+    });
+    this.elementTable.setDeselectListener(e => this.removeElementORFormulaInSearchQuery(e));
+
+
+    this.formulaBox = new FormulaBox();
+    this.formulaBox.setAddFormulaListener(formula => {
+      if (formula.trim() !== ''){
+        this.addTagInSearchQuery(formula, 'F');
+        //this.formulaBox.disable(true);
+        this.addMatNameButton.disabled = true;
+        this.materialNameBox.disable(true);
+      }
+    });
+
+
+    this.materialNameBox = new MaterialNameBox();
+    this.materialNameBox.setAddMaterialNameListener( name => {
+      if (name.trim() !== ''){
+        this.addTagInSearchQuery(name, 'MN');
+        this.addElementButton.disabled = true;
+        this.addFormulaButton.disabled = true;
+        this.formulaBox.disable(true);
+        this.materialNameBox.disable(true);
+      }
+    });
+
+
+    this.filterPanel = new FilterPanel();
+    this.filterSidePanel.appendChild(this.filterPanel.element);
+
+    this.materialList= new MaterialList();
+    this.resultsPage = this.element.querySelector('.results-panel');
+    this.materialList.attachAndSetEvents(this.resultsPage);
+
+    this.currentTab = 'element';
+    this.addPanel.appendChild(this.elementTable.element);
+
+
+
+    this._events();
+  }
+
+
+  _events() {
+    // External event - Search button press
+    this.mainButton.addEventListener( "click", (e) => {
+      //console.log("this.labels: "+JSON.stringify(this.labels));
+
+      if (this.searchQuery.lenght === 0){
+        util.showUserMsg('No query');
+      }else{
+        let searchExpressionQuery;
+
+        // Search by  Material name
+        if (this.queryTypes[0] === 'MN'){
+          //queryObj.push(this._getESSimpleMatch('material_name', item));
+          let rootQueryObj = { 'bool' : {} };
+          rootQueryObj.bool.must = [];
+          rootQueryObj.bool.must.push( this._getESSimpleMatch('material_name', this.searchQuery[0]) );
+          this.materialList.initSearch( rootQueryObj );
+
+        }else{ // Search by complex search expression
+
+          if (this.element.querySelector('#allow-other-elements').checked)
+            searchExpressionQuery = this._getESQueryFromSearchQuery_otherElements(
+              this.searchQuery, this.queryTypes);
+          // Regular case: search containing only the elements in the search expression
+          else searchExpressionQuery =
+              this._getESQueryFromSearchQuery(this.searchQuery, this.queryTypes);
+
+          this.materialList.initSearch(
+            this._addFiltersInSearchQuery( this.filterPanel.getValues(),
+              searchExpressionQuery));
+          //util.setBrowserHashPath('search','results');
+
+          this.element.querySelector('.add-box').style.display = 'none';
+        }
+      }
+
+    });
+
+
+    this.cleanButton.addEventListener( "click", (e) => {
+      this.searchQuery = [];
+      this.queryTypes = [];
+      this.updateSearchQuery();
+      this.addFormulaButton.disabled = false;
+      this.addMatNameButton.disabled = false;
+      this.addElementButton.disabled = false;
+      this.formulaBox.disable(false);
+      this.materialNameBox.disable(false);
+      this.elementTable.deselectAllElements();
+    });
+
+    this.addButtonsBox.addEventListener( "click", (e) => {
+      if (e.target !== e.currentTarget) { // When the event source is a child
+        let className = e.target.className;
+        let index = className.indexOf('add-btn');
+
+        if (index > 0){
+          let selectingElement;
+          let selectingTab = className.substring(0, index-1);
+          if (selectingTab === 'element')
+            selectingElement = this.elementTable.element;
+          else if (selectingTab === 'name')
+            selectingElement = this.materialNameBox.element;
+          else if (selectingTab === 'formula')
+            selectingElement = this.formulaBox.element;
+
+          this.addPanel.replaceChild(selectingElement, this.addPanel.lastChild);
+
+          this.element.querySelector('.add-box').style.display = 'block';
+
+          // Change the styles of the buttons
+          let selEl = this.element.querySelector('.'+this.currentTab+'-add-btn');
+          this._setTabSelectedStyles(selEl, false);
+          this._setTabSelectedStyles(e.target, true);
+
+          // Change the triangle
+          this.element.querySelector('.'+this.currentTab+'-tri').style.visibility = 'hidden';
+          this.element.querySelector('.'+selectingTab+'-tri').style.visibility = 'visible';
+
+          this.currentTab = selectingTab;
+
+/*
+          if (this.userGuidance){
+            if (selectingTab === 'element'){
+              UserGuidance.showIndependentTip(7, false);
+              UserGuidance.showIndependentTip(3, true);
+            }
+            else if (selectingTab === 'props'){
+              UserGuidance.showIndependentTip(3, false);
+              UserGuidance.showIndependentTip(7, true);
+            }else if (selectingTab === 'formula'){
+              UserGuidance.showIndependentTip(3, false);
+              UserGuidance.showIndependentTip(7, false);
+            }
+          }
+          */
+
+        }
+      }
+    });
+
+    this.searchQueryBox.addEventListener( "click", (e) => {
+      let className = e.target.className;
+      if (className === 'remove-label'){
+        let elSymbol = e.target.parentElement.getAttribute('data-el');
+        this.removeElementORFormulaInSearchQuery(elSymbol);
+      }
+    });
+
+  }
+
+
+  _getESQueryFromSearchQuery(searchQuery, queryTypes){
+    let formulas = [];
+    let parFormulas = [];
+    let parOperator = null;
+    let openIndex = -1;
+    searchQuery.forEach( (item, i) => {
+      if (queryTypes[i] === 'F' || queryTypes[i] === 'E'){
+        addItem( (openIndex >= 0 ? parFormulas : formulas), i,
+          item+(queryTypes[i] === 'E' ? '0' : ''));
+
+      }else if ( searchQuery[i] === '(' ){
+        if (i-1 >= 0 ) parOperator = searchQuery[i-1];
+        openIndex = i;
+      }
+      else if ( searchQuery[i] === ')' ){
+        if (parOperator === null){ // The starting ( was the first symbol of the expression
+          formulas = parFormulas;
+        }else if (parOperator === 'OR'){ // OR (...
+          formulas = formulas.concat(parFormulas);
+        }else{ // AND (...
+          let rFormulas = [];
+          formulas.forEach( formula => {
+            parFormulas.forEach( parFormula => rFormulas.push(formula+parFormula) );
+          });
+          formulas = rFormulas;
+        }
+        parFormulas = []; // reset the array formulas inside the parentheses
+
+        openIndex = -1;
+      }
+    });
+    console.log('_getESQueryFromSearchQuery: ',formulas, parFormulas);
+
+    //*********** Get the elastic search expression from the search expression
+    // the elements inserted must be sorted for this to work
+    // queryObj.bool.must.push(this._getESSimpleMatch('atom_labels_keyword', this._sortElements(elements) )); ///elements.join('')));
+    // if ( this.element.querySelector('#multiples-of-formula').checked ){ // reduced search
+    let rootQueryObj = { 'bool' : {} };
+    rootQueryObj.bool.should = [];
+    let queryObj = rootQueryObj.bool.should;
+    let reduced = this.element.querySelector('#multiples-of-formula').checked;
+
+    formulas.forEach( formula => {
+      let pFormula;
+      let searchByElement = (formula.indexOf('0') >= 0);
+      if (searchByElement){ // There are some element in the search expression
+        /** TDO**/
+        let f = formula;
+        if (reduced) f = this._reduceFormula(formula, false);
+        pFormula = this._processFormula(f, 'element-string');
+        let tempQueryObj = { 'bool' : { 'must' : [] } };
+
+        if (pFormula[0].length > 0)  // length === 0 No formula, only elements
+          tempQueryObj.bool.must.push(
+            this._getESOperatorMatch(
+              (reduced ? 'formula_reduced_terms' : 'formula_cell_terms'), pFormula[0]));
+        tempQueryObj.bool.must.push(
+          this._getESSimpleMatch('atom_labels_keyword', pFormula[1]));
+
+        queryObj.push(tempQueryObj);
+
+      }else{ // Only formulas
+        if ( reduced ){ // reduced search
+          pFormula = this._reduceFormula(formula, false);
+          queryObj.push(this._getESSimpleMatch('formula_reduced_keyword', pFormula));
+        }else{
+          pFormula = this._processFormula(formula, 'canonical-formula');
+          queryObj.push(this._getESSimpleMatch('formula_cell_keyword', pFormula));
+        }
+      }
+
+    });
+
+    return rootQueryObj;
+
+    function addItem(formulas, i, item){
+      if (i === 0 || searchQuery[i-1] === '('){
+        formulas.push(item);
+      }else{
+        if (searchQuery[i-1] === 'OR') formulas.push(item);
+        else if (searchQuery[i-1] === 'AND')
+          formulas.push(formulas.pop()+item);
+      }
+    }
+
+  } // _getESQueryFromSearchQuery()
+
+
+  _getESQueryFromSearchQuery_otherElements(searchQuery, queryTypes){
+    // Query structure analysis - looking for parentheses (only one level supported)
+    if ( searchQuery.indexOf('(') >= 0){ // Recursion
+
+      let openIndex = -1;
+      let prodQuery = [];
+      let prodTypes = [];
+      //let prodQueryIndex = 0;
+      for (let i = 0; i < searchQuery.length; i++) {
+        if ( searchQuery[i] === '(' ) openIndex = i;
+        else if ( searchQuery[i] === ')' ){
+          prodQuery.push(this._getESQueryFromSearchQuery_otherElements(
+            searchQuery.slice(openIndex+1, i), queryTypes.slice(openIndex+1, i)));
+          prodTypes.push('Q');
+          openIndex = -1;
+        }else if (openIndex < 0){ // outside a parentheses
+          prodQuery.push(searchQuery[i]);
+          prodTypes.push(queryTypes[i]);
+        }
+      }
+      //console.log('prodQuery', prodQuery, prodTypes);
+      return this._getESQueryFromSearchQuery_otherElements(prodQuery, prodTypes);
+
+    }else{  // BASE CASE: there is no parentheses
+
+      let boolOperator;
+      searchQuery.forEach( (item, i) => {
+        if (searchQuery[i] === 'AND' || searchQuery[i] === 'OR')
+          boolOperator = item;
+      });
+
+      let rootQueryObj = { 'bool' : {} };
+      let queryObj;
+      if (boolOperator === 'AND'){
+        rootQueryObj.bool.must = [];
+        queryObj = rootQueryObj.bool.must;
+      }else{ // OR
+        rootQueryObj.bool.should = [];
+        queryObj = rootQueryObj.bool.should;
+      }
+
+      searchQuery.forEach( (item, i) => {
+
+        if (queryTypes[i] === 'F'){ // Formula case
+          let esMatchQuery;
+          if ( this.element.querySelector('#multiples-of-formula').checked ){ // reduced search
+            esMatchQuery = this._getESOperatorMatch('formula_reduced_terms', this._reduceFormula(item));
+          }else
+            esMatchQuery = this._getESOperatorMatch('formula_cell_terms', this._processFormula(item, 'tokens'));
+          queryObj.push(esMatchQuery);
+
+        }else if (queryTypes[i] === 'E'){ // Element case
+          queryObj.push(this._getESSimpleMatch('atom_labels_terms', item));
+
+        }else if (queryTypes[i] === 'Q'){
+          queryObj.push(item);
+        }
+      });
+
+      return rootQueryObj;
+    } // else
+  } // _getESQueryFromSearchQuery_otherElements()
 
-	  // Observer pattern
-	  setClickListener(listener) {
-	    this.clickListener= listener;
-	  }
 
 
-	  setDeselectListener(listener) {
-	    this.deselectListener= listener;
-	  }
 
+  _addFiltersInSearchQuery(filterMap, searchExpressionQuery){
+    let rootQueryObj = { 'bool' : {} };
+    rootQueryObj.bool.must = [];
+    rootQueryObj.bool.must.push( searchExpressionQuery );
+
+
+    filterMap.forEach((values/*Array*/, filterName) => {
 
-	  selectElement(elSymbol) {
-	    this.element.querySelector('td[data-el="el-'+elSymbol+'"]')
-	      .className= 'cell el-selected';
-	  }
+      let filterNameDef = replaceDashes(filterName);
 
+      if (filterName === 'mass-density' || filterName === 'band-gap'){
+        //***** util.eV2J() apply?
+        rootQueryObj.bool.must.push( this._getFieldESRange(filterNameDef, values) );
 
-	  deselectElement(elSymbol) {
-	    //document.getElementById('el-'+elSymbol).className= 'cell '+getElementBlock(elSymbol);
-	    this.element.querySelector('td[data-el="el-'+elSymbol+'"]')
-	      .className= 'cell '+getElementBlock(elSymbol);
-	  }
+      }else if (filterName === 'band-gap-type'){ // special case
+        if ( values !== 'both')
+          rootQueryObj.bool.must.push( this._getESSimpleMatch('band_gap_direct',
+            ( values === 'direct' ? true : false ) ) );
 
+      }else if (filterName.startsWith('has')){ // has- filters
+        rootQueryObj.bool.must.push( this._getESSimpleMatch(filterNameDef, values, false) );
+
+      }else{ // normal case
+        //rootQueryObj.bool.must.push( this._getESOperatorMatch(filterNameDef, values, false) );
+        rootQueryObj.bool.must.push( this._getESTermsArray(filterNameDef, values) );
 
-	  deselectAllElements(){
-	    let selectedElements = this.element.querySelectorAll('td.el-selected');
+        //console.log(this._getESOperatorMatch(filterNameDef, values, false) );
+      }
 
-	    //selectedElements.forEach( element => {
-	    for (let i = 0; i < selectedElements.length; ++i){
-	      let elSymbol = selectedElements[i].getAttribute('data-el').substring(3);
-	      selectedElements[i].className= 'cell '+getElementBlock(elSymbol);
-	    }
-	  }
+    });
 
-	} // class ElemenTable
 
+    return rootQueryObj;
+  }
 
-	function getElement(e){
 
-	  let element = null;
-	  let className = null;
-	  //console.log("TARGET " +e.target.className+'  '+e.target.innerHTML+'   ');
-	  if (e.target.className.indexOf('cell ') >= 0){
-	    element= e.target;
-	    className = e.target.className;
+  _getESSimpleMatch(field, value){
+    return {
+      "match": { [field] : value }
+    };
+  }
 
-	  }else if (e.target.parentElement.className.indexOf('cell ') >= 0){
-	    element= e.target.parentElement;
-	    className = e.target.parentElement.className;
-	  }
+  _getESTermsArray(field, value){
+    return {
+      "terms": { [field] : value }
+    };
+  }
 
-	  if (element === null) return null;
-	  else{
-	    let html= element.innerHTML;
-	    let elSymbol= html.substring(3,html.indexOf('<',3));
-	    if (elSymbol === '&nbsp;') return null;  // blank cells
-	    else return elSymbol;
-	  }
-	}
 
+  _getESOperatorMatch(field, elements, and = true){
+    let elementsString = '';
+    if (elements.length > 0)  elementsString = elements.join(' ');
 
+    return {
+      "match": {
+        [field]: {
+          "operator": (and ? "and" : 'or'),
+          "query": elementsString
+        }
+      }
+    };
+  }
 
 
-	// EXPORTS
-	module.exports = ElemenTable;
+  _getFieldESRange(field, valuesString){
+    let data = valuesString.split(':');
+    console.log('_getFieldESRange data', data);
 
+    return {
+      "range": {
+          [field]: { "gte" : parseInt(data[0]), "lte" : parseInt(data[1]) }
+      }
+    };
+  }
 
-/***/ },
-/* 35 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-	   This component implements the list of materials found in the search
-	 */
-
-	"use strict";
-
-	let util = __webpack_require__(1);
-	let InfoSys = __webpack_require__(12);
-	let LoadingPopup = __webpack_require__(4);
-
-	const RESULTS_PER_PAGE = 20;
-
-
-	class MaterialList {
-
-	  constructor(){
-	    this.element = document.createElement('div');
-	    this.element.setAttribute("id",'matlist');
-	    // map containing an entry per system type (if there are materials for it)
-	    this.matMap = new Map();
-	    this.currentSystemType = 'bulk';
-	    this.esQueryObject = null;
-
-	    this.element.innerHTML=
-	    `
-	    <div id="system-type-tabs" style=" display: inline-block">
-	      <button id="system-tab-bulk" class="selected">BULK</button>
-	      <button id="system-tab-2D" >2D</button>
-	      <button id="system-tab-1D"  >1D</button>
-	        <span class="results-total" >Results<span>
-	    </div>
-	    <div class="pag-header">
-	      <span class="prevButton">
-	        <img src="img/prev.svg" style="display: inline;" width="7px"/> &nbsp; prev
-	      </span>   &nbsp;&nbsp;
-	      <span class="page"> X </span> &nbsp;&nbsp;
-	      <span class="nextButton"> next &nbsp;
-	        <img src="img/next.svg" width="7px" />
-	      </span>
-	    </div>
-	    <div class="data-container"> </div>`; // results data container
-
-	    this.titleBox = this.element.getElementsByClassName("results-total")[0];
-	    this.tabsBox = this.element.querySelector("#system-type-tabs");
-	    // Pagination components
-	    this.resultsNrTag = this.element.getElementsByClassName("pag-header")[0];
-
-	    this.prevButton = this.element.getElementsByClassName("prevButton")[0];
-	    this.pageElement = this.element.getElementsByClassName("page")[0];
-	    this.nextButton = this.element.getElementsByClassName("nextButton")[0];
-
-	    this.resultsContainer = this.element.getElementsByClassName("data-container")[0];
-	  }
 
 
-	  attachAndSetEvents(element){
-	    element.appendChild(this.element);
-	    this._events();
-	  }
 
+  _setTabSelectedStyles(element, value){
+    /*
+    element.style.fontWeight = (value ? 'bold' : 'normal');
+    element.style.color = (value ? '#E56400' : '#777');
+    element.style.borderColor = (value ? '#E56400' : '#777');
+    */
+    element.id = (value ? 'add-tab-selected' : '');
+  }
 
-	  _events() {
 
-	    this.tabsBox.addEventListener( "click", (e) => {
-	      if (e.target !== e.currentTarget) { // When the event source is a child
-	        let tabId = e.target.id;
-	        let index = tabId.indexOf('system-tab');
+/*
+  _showSearchBox(){
+    if (!this.showingSearchBox){
+      this.showingSearchBox = true;
+      this.searchLine.style.visibility = 'visible';
 
-	        if (index >= 0){
-	          let selectingTab = tabId.substring('system-tab'.length+1);
+      if (this.userGuidance)  UserGuidance.setFinal();
+    }
+  }*/
 
-	          this._updateUI(selectingTab);
-	          // Change the styles of the tabs
-	          this.element.querySelector('#system-tab-'+this.currentSystemType).className = '';
-	          this.element.querySelector('#system-tab-'+selectingTab).className = 'selected';
+  _addItemInSearchQuery(item, type){
+      this.searchQuery.push(item);
+      this.queryTypes.push(type);
+  }
 
-	          this.currentSystemType = selectingTab;
-	        }
-	      }
 
-	    });
+  addTagInSearchQuery(tag, type){
+    // If the it's an element and is already in the query it's not inserted
+    if (type === 'E' && this.searchQuery.indexOf(tag) >= 0) return;
+
+    if ( this.searchQuery.length > 0
+          && this.searchQuery[this.searchQuery.length-1] !== '(')
+      this._addItemInSearchQuery(this.currentOperator, 'S');
+    this._addItemInSearchQuery(tag, type);
+    this.updateSearchQuery();
+    //this._showSearchBox();
+  }
+
+
+  addElementsInSearchQuery(elementArray){
+    let index = elementArray.length;
+    while (index--) {
+      this.addTagInSearchQuery(elementArray[index], 'E');
+    }
+    return true;
+  }
+
+
+  _addParenthesesInSearchQuery(isOpen){
+
+    if ( this.searchQuery.length > 0 && isOpen)
+      this._addItemInSearchQuery(this.currentOperator, 'S');
+    this._addItemInSearchQuery( (isOpen ? '(' : ')'), 'P');
+    this.updateSearchQuery();
+    //this._showSearchBox();
+  }
+
+
+  removeElementORFormulaInSearchQuery(item){
+    //console.log(" removeElementORFormulaInSearchQuery item: ",item, this.searchQuery.indexOf(item));
+
+    let isMaterialName = (this.queryTypes[0] === 'MN');
+    // Travese the array removing the item and the bool operator related
+    let itemIndex = this.searchQuery.indexOf(item);
+    if (itemIndex >= 0){
+      let i, elementsToRemove;
+      if (this.queryTypes[itemIndex+1] === 'S'){ // bool operator on the left
+        i = itemIndex; elementsToRemove = 2;
+      }else if (this.queryTypes[itemIndex-1] === 'S'){ // bool operator on the right
+        i = itemIndex-1; elementsToRemove = 2;
+      }else{ // case: (item)
+        i = itemIndex; elementsToRemove = 1;
+      }
+      this.searchQuery.splice(i, elementsToRemove);
+      this.queryTypes.splice(i, elementsToRemove);
+    }
+
+    // Travese the array removing the unnecessary parethesis (only tested for one level nested)
+    if ( this.searchQuery.indexOf('(') >= 0){ // Recursion
+
+      for (let i = 0; i < this.searchQuery.length; i++) { // dangerous: modifing a array being traversed
+        if ( this.searchQuery[i] === '(' ){
+          if ( this.searchQuery[i+1] === ')'){ // '()' case
+            this.searchQuery.splice(i, 2);
+            this.queryTypes.splice(i, 2);
+          }else if (searchQuery[i+2] === ')'){ // '(item)' case
+            this.searchQuery.splice(i, 3, this.searchQuery[i+1]);
+            this.queryTypes.splice(i, 3, this.queryTypes[i+1]);
+          }
+        }
+      }
+    }
+
+    this.updateSearchQuery();
+
+    if (util.ELEMENTS.indexOf(item) >= 0){ // It's an element (being removed)
+      this.elementTable.deselectElement(item);
+    }
+
+    if (this.queryTypes.length === 0){ 
+
+      if (isMaterialName){
+        this.addElementButton.disabled = false;
+        this.addFormulaButton.disabled = false;
+        this.formulaBox.disable(false);
+      }else{ // element or formula
+        this.addMatNameButton.disabled = false;
+        
+      }
+      this.materialNameBox.disable(false);
+    }
+
+    //console.log(" final searchQuery: ",this.searchQuery);
+    //}
+
+    return true;
+  }
+
+
+  updateSearchQuery(){
+    let html= '';
+    for (let i = 0; i < this.searchQuery.length; i++) {
+      let type = this.queryTypes[i];
+
+      if (type === 'S' || type === 'P')
+        html+= `<span class="search-query-symbol" >  ${this.searchQuery[i]} </span>`;
+      else
+        html+= getTagHtml(this.searchQuery[i], ( type === 'F' ? true : false));
+    }
+    console.log('this.updateSearchQuery: ', this.searchQuery ,this.queryTypes);
+    this.searchQueryBox.innerHTML = html;
+  }
+
+ ///********* DELETE?
+  showSearchResults(){
+    /*
+    this.searchPage.style.display= 'none';
+    this.resultsPage.style.display= 'block';
+*/
+    //if (this.userGuidance) UserGuidance.show(false);
+  }
+
+
+  showSearchPage(){
+    /*
+    this.searchPage.style.display= 'block';
+    this.resultsPage.style.display= 'none';
+
+    if (this.userGuidance){
+      setTimeout(() => {
+        UserGuidance.init(this.addButtonsBox, this.elementTable.element,
+          this.searchBox, this.propertiesBox.tabsElement);
+        UserGuidance.show(true, this.currentTab === 'element',
+          this.currentTab === 'props');
+      }, 400);
+    }
+    */
+  }
+
+
+  _sortElements(elements){
+    let numbers = [];
+    let sortedElements = [];
+    elements.forEach( e => numbers.push(util.ELEMENTS.indexOf(e)) );
+    numbers.sort( (a, b) => a - b ); // atomic number-1
+    numbers.forEach( n => sortedElements.push(util.ELEMENTS[n]) );
+    //console.log('_sortElements ',numbers, elString);
+    return sortedElements;
+  }
+
+
+
+
+  _reduceFormula(formula, getTokens = true){
+    let index = 0;
+    let map = new Map();
+    let key;
+    while ( index < formula.length ){
+      let el2 = formula.substring(index, index+2);
+      let el1 = formula.substring(index, index+1);
+
+      if (util.ELEMENTS.indexOf(el2) >= 0){
+        map.set(el2, 1); // 1 default value
+        index += 2;
+        key = el2;
+        //console.log('eleemnt 2chars', key);
+      }else if (util.ELEMENTS.indexOf(el1) >= 0){
+        map.set(el1, 1); // 1 default value
+        index++;
+        key = el1;
+        //console.log('eleemnt 1chars', key);
+      }else{ // It's a number
+        let num = parseInt(el2);
+        if (num >= 10) index += 2; // 2 figures number
+        else index++;// 1 figure number
+        //console.log('number ', num, key);
+        map.set(key, num);
+      }
+      // console.log('FINAL LOOP', map, index);
+    }
+
+    let counter = 0;
+    while ( !checkIfReduced(map) ){ // console.log('Reducing', map);
+      let div = 1;
+      if (isDivisibleBy(map, 2)) div = 2;
+      else if (isDivisibleBy(map, 3)) div = 3;
+      else if (isDivisibleBy(map, 5)) div = 5;
+      else if (isDivisibleBy(map, 7)) div = 7;
+      else if (isDivisibleBy(map, 11)) div = 11;
+
+      map.forEach( (value, key) => {
+        map.set(key, (value/div));
+      });
+      //console.log('Reducing DIV', map);
+      counter++;
+      if (counter > 5) break;
+    }
+
+    function checkIfReduced(formulaMap){
+      let min = 100;
+      formulaMap.forEach( (value, key) => {
+        if (value < min) min = value;
+      });
+      return min === 1;
+    }
+
+    function isDivisibleBy(formulaMap, n){
+      let div = true;
+      formulaMap.forEach( (value, key) => {
+        if (value % n !== 0) div = false;
+      });
+      return div;
+    }
+
+    let tokens = [];
+    let canonicalFormula = '';
+    if (getTokens){
+      map.forEach( (value, key) => tokens.push(key+value) );
+    }else{
+      let sortedElements = this._sortElements( Array.from( map.keys() ) );
+      sortedElements.forEach( element => {
+        canonicalFormula += element+map.get(element);
+        //canonicalFormula += element+(map.get(element) === 1 ? '' : map.get(element));
+      });
+    }
+
+
+    console.log('_reduceFormula RETURN: ', map, tokens, canonicalFormula);
+    return (getTokens ? tokens : canonicalFormula);
+  }
+
+
+  _processFormula(formula, type){
+    let index = 0;
+    let map = new Map();
+    let key;
+    while ( index < formula.length ){
+      let el2 = formula.substring(index, index+2);
+      let el1 = formula.substring(index, index+1);
+
+      if (util.ELEMENTS.indexOf(el2) >= 0){
+        map.set(el2, 1); // 1 default value
+        index += 2;
+        key = el2;
+        //console.log('eleemnt 2chars', key);
+      }else if (util.ELEMENTS.indexOf(el1) >= 0){
+        map.set(el1, 1); // 1 default value
+        index++;
+        key = el1;
+        //console.log('eleemnt 1chars', key);
+      }else{ // It's a number
+        let num = parseInt(el2);
+        if (num >= 10) index += 2; // 2 figures number
+        else index++;// 1 figure number
+        //console.log('number ', num, key);
+        map.set(key, num);
+      }
+      // console.log('FINAL LOOP', map, index);
+    }
+
+
+
+    if (type === 'tokens'){
+      let tokens = [];
+      map.forEach( (value, key) => tokens.push(key+value) );
+      console.log('_processFormula RETURN: ', map, tokens);
+      return tokens;
+    }else{
+      let sortedElements = this._sortElements( Array.from( map.keys() ) );
+      if (type === 'canonical-formula'){
+        let formulaString = '';
+        sortedElements.forEach( element => {
+          formulaString += element+map.get(element);
+        });
+        console.log('_processFormula RETURN: ', map, formulaString);
+        return formulaString;
+      }else{ // elements-string
+        let elementsString = '';
+        let elementsInFormulas = [];
+        sortedElements.forEach( element => {
+          elementsString += element;
+          let val = map.get(element);
+          if (val !== 0) elementsInFormulas.push(element+val);
+        });
+        console.log('_processFormula RETURN: ', map, [elementsInFormulas ,elementsString]);
+        return [elementsInFormulas ,elementsString];
+      }
+    }
+
+  }
+
+}
+
+
+class FormulaBox{
+
+  constructor() {
+    this.element = document.createElement('div');
+    this.element.setAttribute("id",'formula-box');
+    this.element.innerHTML=
+    `
+    <div style="padding-bottom: 20px;">
+<!--
+    <input type="checkbox" class="allow-other-elements" value="">
+      Allow other elements
+      <br>
+
+
+    <input type="checkbox" class="multiples-of-formula" value="">
+      Include multiples of formula
+      <br> -->
+
+    <input type="text" class="formula-text-field"
+      placeholder="Add formula to the search query above" >
+      <button class="adding-formula-btn" disabled>Add to query</button>
+    </div>
+    `;
+    this.formulaTextField = this.element.querySelector('.formula-text-field');
+    this.formulaButton = this.element.querySelector('.adding-formula-btn');
+
+    this.formulaButton.addEventListener( "click", (e) => {
+      this.addFormulaListener(this.formulaTextField.value);
+      this.formulaTextField.value = '';
+    });
+
+    this.formulaTextField.addEventListener( 'input', e => {
+      //console.log('formulaTextField input: ',this.formulaTextField.value);
+      this.formulaButton.disabled = (this.formulaTextField.value === '');
+    });
+
+  }
+
+
+  setAddFormulaListener(listener) {
+    this.addFormulaListener= listener;
+  }
+
+
+  disable(bool) {
+    this.formulaTextField.disabled = bool;
+    this.formulaButton.disabled = true;//bool;
+  }
+
+/*
+  getAllowOtherElements(){
+    return  this.element.querySelector('.allow-other-elements').checked;
+  }
+
+
+  getMultiplesOfFormula(){
+    return  this.element.querySelector('.multiples-of-formula').checked;
+  }*/
+
+}
+
+
+class MaterialNameBox{
 
-	    this.nextButton.addEventListener('click', e => {
-	      let systemData = this.matMap.get(this.currentSystemType);
-	      if (systemData.page === systemData.totalPages) return;
-	      systemData.page++;
-	      this._paginationSearch();
-	    });
+  constructor() {
+    this.element = document.createElement('div');
+    this.element.setAttribute("id",'material-name-box');
+    this.element.innerHTML=
+    ` <div style="padding-bottom: 20px;">
+      <input type="text" class="name-text-field"
+        placeholder="Add a material name to the search query above" >
+        <button class="adding-name-btn" disabled>Add to query</button>
+      </div>
+    `;
+    this.textField = this.element.querySelector('.name-text-field');
+    this.button = this.element.querySelector('.adding-name-btn');
 
-	    this.prevButton.addEventListener('click', e =>  {
-	      let systemData = this.matMap.get(this.currentSystemType);
-	      if (systemData.page === 1) return;
-	      systemData.page--;
-	      this._paginationSearch();
-	    });
+    this.button.addEventListener( "click", (e) => {
+      this.listener(this.textField.value);
+      this.textField.value = '';
+    });
 
-	    this.resultsContainer.addEventListener('click', (e) => {
-	      if (e.target !== e.currentTarget) { // When the event source is a child
-
-	        let element;
-	        if (e.target.className === 'mat-row') element = e.target;
-	        else if (e.target.parentElement.className === 'mat-row')
-	          element = e.target.parentElement;
-	        else if (e.target.parentElement.parentElement.className === 'mat-row')
-	          element = e.target.parentElement.parentElement;
-
-	        if (element) {
-	          util.setBrowserHashPath('material', element.getAttribute('data-mat-id'));
-	        }
-	        e.stopPropagation();
-	      }
-	    });
+    this.textField.addEventListener( 'input', e => {
+      //console.log('formulaTextField input: ',this.formulaTextField.value);
+      this.button.disabled = (this.textField.value === '');
+    });
 
-	  }
+  }
 
 
-	  _paginationSearch(){
+  setAddMaterialNameListener(listener) {
+    this.listener = listener;
+  }
 
-	    let systemTypePosition = this.esQueryObject.bool.must.length-1;
-	    this.esQueryObject.bool.must[systemTypePosition].match.system_type = this.currentSystemType;
-	    let page = this.matMap.get(this.currentSystemType).page;
 
-	    let req = util.serverReqPOST(util.getSearchURL()+'?page='+page+
-	            '&per_page='+RESULTS_PER_PAGE, JSON.stringify(this.esQueryObject), e => {
+  disable(bool) {
+    this.textField.disabled = bool;
+    this.button.disabled = true;//bool;
+  }
+}
 
-	      let data = JSON.parse(e.target.response);
+// EXPORTS
+module.exports = NewSearchMod;
 
-	      this.matMap.set(this.currentSystemType, this._createSystemTypeData(data, page, true));
-	      //console.log('this.matMap: ', this.matMap);
-	      this._updateUI(this.currentSystemType);
-	    });
 
-	  }
+/***/ }),
+/* 34 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+ /*
+   This is the UI component implementing the interactive  Element Table
+   in the search front. It need to communicate to other UI components
+   so it exposes several listeners
+ */
+
+
+
+let util = __webpack_require__(0);
+
+
+// constans
+
+const GROUPS = new Map([
+  [1,['H', 'Li', 'Na', 'K', 'Rb', 'Cs', 'Fr']],
+  [2,['Be', 'Mg', 'Ca', 'Sr', 'Ba', 'Ra']],
+  [3,['Sc', 'Y']],
+  [4,['Ti', 'Zr', 'Hf', 'Rf']],
+  [5,['V', 'Nb', 'Ta', 'Ha']],
+  [6,['Cr', 'Mo', 'W', 'Sg']],
+  [7,['Mn', 'Tc', 'Re', 'Ns']],
+  [8,['Fe', 'Ru', 'Os', 'Hs']],
+  [9,['Co', 'Rh', 'Ir', 'Mt']],
+  [10,['Ni', 'Pd', 'Pt', 'Ds']],
+  [11,['Cu', 'Ag', 'Au', 'Rg']],
+  [12,['Zn', 'Cd', 'Hg', 'Cn']],
+  [13,['B', 'Al', 'Ga', 'In', 'Tl', 'Nh']],
+  [14,['C', 'Si', 'Ge', 'Sn', 'Pb', 'Fl']],
+  [15,['N', 'P', 'As', 'Sb', 'Bi', 'Mc']],
+  [16,['O', 'S', 'Se', 'Te', 'Po', 'Lv']],
+  [17,['F', 'Cl', 'Br', 'I', 'At', 'Ts']],
+  [18,['He', 'Ne', 'Ar', 'Kr', 'Xe','Rn', 'Og']],
+  [19,['La','Ce','Pr','Nd','Pm','Sm','Eu','Gd','Tb','Dy','Ho','Er','Tm','Yb','Lu']],
+  [20,['Ac','Th','Pa','U','Np','Pu','Am','Cm','Bk','Cf','Es','Fm','Md','No','Lr']]
+]);
+
+const BLOCKS = new Map([
+  ['metalloids',['B', 'Si', 'Ge', 'As', 'Sb', 'Te', 'Po']],
+  ['other-non-metals',['H', 'C', 'N', 'O', 'P', 'S', 'Se']],
+  ['halogens',['F', 'Cl', 'Br', 'I', 'At', 'Ts']],
+  ['noble-gases',['He', 'Ne', 'Ar', 'Kr', 'Xe','Rn', 'Og']],
+  ['alkali-metals',['Li', 'Na', 'K', 'Rb', 'Cs', 'Fr']],
+  ['alkaline-earth-metals',['Be', 'Mg', 'Ca', 'Sr', 'Ba', 'Ra']],
+  ['lanthanoids',['La','Ce','Pr','Nd','Pm','Sm','Eu','Gd','Tb','Dy','Ho','Er'
+    ,'Tm','Yb','Lu']],
+  ['actinoids',['Ac','Th','Pa','U','Np','Pu','Am','Cm','Bk','Cf','Es','Fm'
+    ,'Md','No','Lr']],
+  ['transition-metals', ['Sc', 'Y','Ti', 'Zr', 'Hf', 'Rf','V','Nb','Ta','Ha'
+    ,'Cr','Mo','W','Sg','Mn','Tc','Re','Ns','Fe','Ru','Os','Hs','Co','Rh','Ir'
+    , 'Mt','Ni','Pd','Pt', 'Ds', 'Cu','Ag','Au', 'Rg', 'Zn','Cd','Hg', 'Cn']],
+  ['post-transition-metals', ['Al','Ga', 'In', 'Tl', 'Nh', 'Sn', 'Pb', 'Fl', 'Bi', 'Mc', 'Lv']]
+]);
+
+const BLOCKS_COLORS = new Map([
+  ['metalloids','#F9E298'],
+  ['other-non-metals','#F2B01D'],
+  ['halogens','#85ADC1'],
+  ['noble-gases','#F7D660'],
+  ['alkali-metals','#D04629'],
+  ['alkaline-earth-metals','#F7B57D'],
+  ['transition-metals', '#F58737'],
+  ['post-transition-metals', '#AE4747'],
+  ['lanthanoids','#3B91AE'],
+  ['actinoids','#E97147']
+]);
+
+let elementNames = ['Hydrogen',  'Helium', 'Lithium', 'Beryllium',
+    'Boron',  'Carbon',  'Nitrogen',  'Oxygen',  'Fluorine',
+    'Neon', 'Sodium', 'Magnesium', 'Aluminum', 'Silicon',
+    'Phosphorus',  'Sulfur',  'Chlorine', 'Argon', 'Potassium',
+    'Calcium', 'Scandium', 'Titanium', 'Vanadium',  'Chromium',
+    'Manganese', 'Iron', 'Cobalt', 'Nickel', 'Copper',
+    'Zinc', 'Gallium', 'Germanium', 'Arsenic', 'Selenium',
+    'Bromine', 'Krypton', 'Rubidium', 'Strontium', 'Yttrium',
+    'Zirconium', 'Niobium', 'Molybdenum', 'Technetium', 'Ruthenium',
+    'Rhodium', 'Palladium', 'Silver', 'Cadmium', 'Indium',
+    'Tin', 'Antimony', 'Tellurium', 'Iodine',  'Xenon',
+    'Cesium', 'Barium', 'Lanthanum', 'Cerium', 'Praseodymium',
+    'Neodymium', 'Promethium', 'Samarium', 'Europium', 'Gadolinium',
+    'Terbium', 'Dysprosium', 'Holmium', 'Erbium', 'Thulium',
+    'Ytterbium', 'Lutetium', 'Hafnium', 'Tantalum', 'Tungsten',
+    'Rhenium', 'Osmium', 'Iridium', 'Platinum', 'Gold',
+    'Mercury', 'Thallium', 'Lead', 'Bismuth', 'Polonium',
+    'Astatine', 'Radon', 'Francium', 'Radium', 'Actinium',
+    'Thorium', 'Protactinium', 'Uranium',  'Neptunium', 'Plutonium',
+    'Americium', 'Curium', 'Berkelium', 'Californium', 'Einsteinium',
+    'Fermium', 'Mendelevium', 'Nobelium', 'Lawrencium', 'Rutherfordium',
+    'Dubnium', 'Seaborgium', 'Bohrium', 'Hassium', 'Meitnerium', 'Darmstadtium',
+    'Roentgenium', 'Copernicium', 'Nihonium', 'Flerovium', 'Moscovium',
+    'Livermorium', 'Tennessine', 'Oganesson'
+];
+
+
+// utility functions
+
+function getElementBlock(elSymbol){
+  let block;
+  BLOCKS.forEach(function(value, key) {
+    //console.log(key + " " + value);
+    if (value.indexOf(elSymbol) >= 0)
+      block= key;
+  });
+  return block;
+}
+
+
+let CELL_WIDTH= 36;
+
+function getCellHtml(elNum){
+  let elSymbol= util.ELEMENTS[elNum-1];
+  return '<td class="cell '+getElementBlock(elSymbol)+'" data-el="el-'+elSymbol+'">'+
+          '<b>'+elSymbol+'</b> <div>'+elNum+'</div> </td>';
+}
+
+function getOddCellHtml(elNum){
+  let elSymbol= util.ELEMENTS[elNum-1];
+  return '<td class="cellpad '+getElementBlock(elSymbol)+'" data-el="el-X">'+
+          '<b>&nbsp;</b> <div>&nbsp;</div> </td>';
+}
+
+
+/**  Group selection not implemented
+
+function getGroupSelectorHtml(num){
+  return '<th class="group-sel" data-group="'+num+'"><div></div></th>';
+}
+
+function getGroupSelectorHtmlLAcAc(num){
+  return '<th class="group-sel-la-ac" data-group="'+num+'"><div></div></th>';
+}*/
+
+/************************/
+
+
+class ElemenTable{
+
+  constructor() {
+
+    this.element = document.createElement('div');
+    this.element.setAttribute('id','elementable');
+
+    // header with dropdown
+    let tempHtml = '<div class="element-info"></div>';
+
+    tempHtml+= '<div class="ptWrapper">';
+
+    tempHtml+= '<table id="pt-main">'; // table zone div
+
+    /* Deactivated for the moment
+    // header with group selectors
+    tempHtml+= '<thead><tr>';//'<div id="group-selectors">';
+    for (let i= 1; i<=18; i++){
+      tempHtml+= getGroupSelectorHtml(i);
+    }
+    tempHtml+= '</tr></thead>';// selectors
+    */
+
+    tempHtml+= '<tbody>';
+    // row 1
+    tempHtml+=  '<tr>'+getCellHtml(1);
+    tempHtml+= '<td class="cellpad" colspan="16"></td>';
+    tempHtml+= getCellHtml(2)+'</tr>';
+
+    let get8ElementRowHtml= (initPos) => {
+      tempHtml+= '<tr>'+getCellHtml(initPos)+getCellHtml(initPos+1);
+      tempHtml+= '<td class="cellpad" colspan="10"></td>';
+      for (let i= initPos+2; i< initPos+8; i++)  tempHtml+= getCellHtml(i);
+      tempHtml+= '</tr>';//div.row
+    }
+
+    // row 2 and 3
+    get8ElementRowHtml(3);
+    get8ElementRowHtml(11);
+
+    // row 4,5, 6
+    let counter= 19;
+    for (let i= 0; i<4; i++){
+      tempHtml+= '<tr>';
+      for (let j= 0; j<18; j++){
+        if (counter === 57 || counter === 89){
+          tempHtml += getOddCellHtml(counter);
+          counter += 15;
+        }else{
+          tempHtml+= getCellHtml(counter);
+          counter++;
+        }
+      }
+      tempHtml+= '</tr>';//div.row
+    }
+
+
+    tempHtml+= '</tbody></table>';
+
+    // Lanthanides and Actinides
+    tempHtml+= '<div id="specialRows"><table id="pt-laac">';
+    for (let i= 0; i<2; i++){
+      tempHtml+= '<tr>';
+      counter = (i === 0 ? 57 : 89);
+      //tempHtml+= getGroupSelectorHtmlLAcAc((i === 0 ? 19 : 20));
+      for (let j= 0; j<15; j++){
+        tempHtml+= getCellHtml(counter);
+        counter++;
+      }
+      tempHtml+= '</tr>';//div.row
+    }
+    tempHtml+= '</table></div>'; //div#specialRows
+
+
+    // Block labels
+    tempHtml+= `<div class="legend">
+      <div class="alkali-metals">Alkali metals</div>
+      <div class="alkaline-earth-metals">Alkaline earth metals</div>
+      <div class="transition-metals">Transition metals</div>
+      <div class="post-transition-metals">Post-transition metals</div>
+      <div class="metalloids">Metalloids</div>
+      <div class="other-non-metals">Other nonmetals</div>
+      <div class="halogens">Halogens</div>
+      <div class="noble-gases">Noble gases</div>
+      <div class="lanthanoids">Lanthanoids</div>
+      <div class="actinoids">Actinoids</div>
+    </div>`;//'<div id="group-selectors">';
+
+
+    tempHtml+= '</div>'; // ptWrapper
+
+    this.element.innerHTML= tempHtml;
+    this.elementInfo= this.element.getElementsByClassName('element-info')[0];
+    this.tableZone= this.element.getElementsByClassName('ptWrapper')[0];
+    //this.specialRows= this.element.querySelector('#specialRows');
+
+    this._events();
+  }
+
+
+  _events() {
+
+    // One listener for all diferent clicks (simple element, group)
+    var adhocListener= (e) => {
+
+      if (e.target !== e.currentTarget) { // When the event source is a child
+        let className = e.target.className;
+        let element = e.target;
+        if (className  === ''){
+          element= e.target.parentElement;
+          className = e.target.parentElement.className;
+        }
+
+        if (className.indexOf('cellpad') >= 0) return; // structural empty table cells
+
+        if (className.indexOf('group-sel') >= 0){ // group selector cells
+          //*** Not working at the moment - group selection deactivated
+          let elements=  GROUPS.get(parseInt(element.getAttribute('data-group')));
+          //console.log("group-sel "+elements);
+          this.clickListener(elements);//let done =
+          //if (done)
+          for (var i = 0; i < elements.length; i++)
+            this.selectElement(elements[i]);
+
+        }else if (className.indexOf('cell') >= 0){  // element cells
+          let html= element.innerHTML;
+          let elSymbol= html.substring(3,html.indexOf('<',3));
+          if (elSymbol === '&nbsp;') return;  // blank cells
+          //console.log("elSymbol-sel "+elSymbol);
+          if (className.indexOf('el-selected') >= 0){ // If selected
+            this.deselectListener(elSymbol);//this.deselectElement(elSymbol);
+          }else{ // If not selected
+            this.clickListener([elSymbol]);//let done = this.clickListener([elSymbol]);
+            this.selectElement(elSymbol);//if (done) this.selectElement(elSymbol);
+          }
+        }
+      }
+      //e.stopPropagation();
+    };
+
+    // Event listener set in the root div element
+    this.tableZone.addEventListener('click',adhocListener,true);
+
+    this.tableZone.addEventListener('mouseover',e => {
+
+      let elSymbol= getElement(e);
+      //console.log("ENTERIG elSymbol-sel "+elSymbol);
+      if (elSymbol !== null){
+          //console.log("elSymbol-sel "+elSymbol);
+          this.elementInfo.style.display = 'block';
+          let borderColor= BLOCKS_COLORS.get(getElementBlock(elSymbol));
+          this.elementInfo.style.borderColor = borderColor;
+          let number= util.ELEMENTS.indexOf(elSymbol)+1;
+          this.elementInfo.innerHTML= `
+          <div>
+            <div style="float: right; padding: 3px 4px;border-left: 3px solid ${borderColor};
+              border-bottom: 3px solid ${borderColor}" > ${number} </div>
+            <div style="clear: right;"></div>
+          </div>
+          <div class="symbol">${elSymbol} </div>
+          <div class="">${elementNames[number-1]}  </div>
+          `
+      }
+    });
+
+    this.tableZone.addEventListener('mouseout',e => {
+      let element= getElement(e);
+      if (element !== null) this.elementInfo.style.display = 'none';
+    });
+
+  }
+
+  // Observer pattern
+  setClickListener(listener) {
+    this.clickListener= listener;
+  }
+
+
+  setDeselectListener(listener) {
+    this.deselectListener= listener;
+  }
+
+
+  selectElement(elSymbol) {
+    this.element.querySelector('td[data-el="el-'+elSymbol+'"]')
+      .className= 'cell el-selected';
+  }
 
 
-	  initSearchTest(rootQueryObj){
-	    //this.resultsContainer.style.visibility = 'hidden';
-	    this.matMap.clear();
+  deselectElement(elSymbol) {
+    //document.getElementById('el-'+elSymbol).className= 'cell '+getElementBlock(elSymbol);
+    this.element.querySelector('td[data-el="el-'+elSymbol+'"]')
+      .className= 'cell '+getElementBlock(elSymbol);
+  }
+
+
+  deselectAllElements(){
+    let selectedElements = this.element.querySelectorAll('td.el-selected');
+
+    //selectedElements.forEach( element => {
+    for (let i = 0; i < selectedElements.length; ++i){
+      let elSymbol = selectedElements[i].getAttribute('data-el').substring(3);
+      selectedElements[i].className= 'cell '+getElementBlock(elSymbol);
+    }
+  }
+
+} // class ElemenTable
+
+
+function getElement(e){
+
+  let element = null;
+  let className = null;
+  //console.log("TARGET " +e.target.className+'  '+e.target.innerHTML+'   ');
+  if (e.target.className.indexOf('cell ') >= 0){
+    element= e.target;
+    className = e.target.className;
+
+  }else if (e.target.parentElement.className.indexOf('cell ') >= 0){
+    element= e.target.parentElement;
+    className = e.target.parentElement.className;
+  }
+
+  if (element === null) return null;
+  else{
+    let html= element.innerHTML;
+    let elSymbol= html.substring(3,html.indexOf('<',3));
+    if (elSymbol === '&nbsp;') return null;  // blank cells
+    else return elSymbol;
+  }
+}
+
 
-	    let qqq = { 'bool' : {} };
-	    //qqq.bool.must = {"terms":{"crystal_system":{"operator":"or","query":"cubic"}}};
-	    qqq.bool.must = {"terms":{"crystal_system": ["hexagonal","cubic"]}};
 
-	    console.log('SENDING: ', JSON.stringify(qqq)); console.log(': ', qqq.bool.must);
 
-	    let bulkReq = util.serverReqPOST(util.getSearchURL()+'?page=1'+
-	            '&per_page='+RESULTS_PER_PAGE, JSON.stringify(qqq), bulke => {
+// EXPORTS
+module.exports = ElemenTable;
 
-	      let bulkData = JSON.parse(bulke.target.response);  console.log('GETTING: ', bulkData);
 
-	      this.matMap.set('bulk', this._createSystemTypeData(bulkData, 1, bulke.target.status === 200));
-	      LoadingPopup.hide();
-	    });
+/***/ }),
+/* 35 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+ /*
+   This component implements the list of materials found in the search
+ */
+
+
+
+let util = __webpack_require__(0);
+let InfoSys = __webpack_require__(3);
+let LoadingPopup = __webpack_require__(4);
+
+const RESULTS_PER_PAGE = 20;
+
+
+class MaterialList {
+
+  constructor(){
+    this.element = document.createElement('div');
+    this.element.setAttribute("id",'matlist');
+    // map containing an entry per system type (if there are materials for it)
+    this.matMap = new Map();
+    this.currentSystemType = 'bulk';
+    this.esQueryObject = null;
+
+    this.element.innerHTML=
+    `
+    <div id="system-type-tabs" style=" display: inline-block">
+      <button id="system-tab-bulk" class="selected">BULK</button>
+      <button id="system-tab-2D" >2D</button>
+      <button id="system-tab-1D"  >1D</button>
+        <span class="results-total" >Results<span>
+    </div>
+    <div class="pag-header">
+      <span class="prevButton">
+        <img src="img/prev.svg" style="display: inline;" width="7px"/> &nbsp; prev
+      </span>   &nbsp;&nbsp;
+      <span class="page"> X </span> &nbsp;&nbsp;
+      <span class="nextButton"> next &nbsp;
+        <img src="img/next.svg" width="7px" />
+      </span>
+    </div>
+    <div class="data-container"> </div>`; // results data container
+
+    this.titleBox = this.element.getElementsByClassName("results-total")[0];
+    this.tabsBox = this.element.querySelector("#system-type-tabs");
+    // Pagination components
+    this.resultsNrTag = this.element.getElementsByClassName("pag-header")[0];
 
-	  }
+    this.prevButton = this.element.getElementsByClassName("prevButton")[0];
+    this.pageElement = this.element.getElementsByClassName("page")[0];
+    this.nextButton = this.element.getElementsByClassName("nextButton")[0];
 
+    this.resultsContainer = this.element.getElementsByClassName("data-container")[0];
+  }
 
-	  initSearch(rootQueryObj){
-	    //this.resultsContainer.style.visibility = 'hidden';
-	    this.matMap.clear();
 
-	    rootQueryObj.bool.must.push( { "match": {"system_type" : "bulk"} } );
-	    console.log('SENDING: ', JSON.stringify(rootQueryObj)); console.log(': ', rootQueryObj.bool.must);
-	    let systemTypePosition = rootQueryObj.bool.must.length-1;
-	    this.esQueryObject = rootQueryObj;
+  attachAndSetEvents(element){
+    element.appendChild(this.element);
+    this._events();
+  }
 
-	    LoadingPopup.show();
 
-	    //let oReq = util.serverReqPOST('http://enc-staging-nomad.esc.rzg.mpg.de/current/v1.0/esmaterials', postQuery, e => {
-	    // Bulk materials request
-	    let bulkReq = util.serverReqPOST(util.getSearchURL()+'?page=1'+
-	            '&per_page='+RESULTS_PER_PAGE, JSON.stringify(rootQueryObj), bulke => {
+  _events() {
 
-	      let bulkData = JSON.parse(bulke.target.response);  console.log('GETTING: ', bulkData);
+    this.tabsBox.addEventListener( "click", (e) => {
+      if (e.target !== e.currentTarget) { // When the event source is a child
+        let tabId = e.target.id;
+        let index = tabId.indexOf('system-tab');
 
-	      this.matMap.set('bulk', this._createSystemTypeData(bulkData, 1, bulke.target.status === 200));
+        if (index >= 0){
+          let selectingTab = tabId.substring('system-tab'.length+1);
 
+          this._updateUI(selectingTab);
+          // Change the styles of the tabs
+          this.element.querySelector('#system-tab-'+this.currentSystemType).className = '';
+          this.element.querySelector('#system-tab-'+selectingTab).className = 'selected';
 
-	      // 2D materials request
-	      rootQueryObj.bool.must[systemTypePosition].match.system_type = '2D';
-	      let twoDReq = util.serverReqPOST(util.getSearchURL()+'?page=1'+
-	              '&per_page='+RESULTS_PER_PAGE, JSON.stringify(rootQueryObj), twoDe => {
+          this.currentSystemType = selectingTab;
+        }
+      }
 
-	        let twoDData = JSON.parse(twoDe.target.response);
+    });
 
-	        this.matMap.set('2D', this._createSystemTypeData(twoDData, 1, twoDe.target.status === 200));
+    this.nextButton.addEventListener('click', e => {
+      let systemData = this.matMap.get(this.currentSystemType);
+      if (systemData.page === systemData.totalPages) return;
+      systemData.page++;
+      this._paginationSearch();
+    });
 
+    this.prevButton.addEventListener('click', e =>  {
+      let systemData = this.matMap.get(this.currentSystemType);
+      if (systemData.page === 1) return;
+      systemData.page--;
+      this._paginationSearch();
+    });
 
-	        // 1D materials request
-	        rootQueryObj.bool.must[systemTypePosition].match.system_type = '1D';
-	        let oneDReq = util.serverReqPOST(util.getSearchURL()+'?page=1'+
-	                '&per_page='+RESULTS_PER_PAGE, JSON.stringify(rootQueryObj), oneDe => {
+    this.resultsContainer.addEventListener('click', (e) => {
+      if (e.target !== e.currentTarget) { // When the event source is a child
 
-	          let oneDData = JSON.parse(oneDe.target.response);
+        let element;
+        if (e.target.className === 'mat-row') element = e.target;
+        else if (e.target.parentElement.className === 'mat-row')
+          element = e.target.parentElement;
+        else if (e.target.parentElement.parentElement.className === 'mat-row')
+          element = e.target.parentElement.parentElement;
 
-	          this.matMap.set('1D', this._createSystemTypeData(oneDData, 1, oneDe.target.status === 200));
+        if (element) {
+          util.setBrowserHashPath('material', element.getAttribute('data-mat-id'));
+        }
+        e.stopPropagation();
+      }
+    });
 
-	          let selectedSystemType = null;
-	          this.matMap.forEach( (materials, systemType) => {
-	            this.element.querySelector('#system-tab-'+systemType).disabled =
-	              (materials.total === 0);
-	            if (selectedSystemType === null && materials.total > 0) {
-	              selectedSystemType = systemType;
-	              this.element.querySelector('#system-tab-'+this.currentSystemType).className = '';
-	              this.element.querySelector('#system-tab-'+selectedSystemType).className = 'selected';
+  }
 
-	              this.currentSystemType = selectedSystemType;
-	            }
-	          });
-	          rootQueryObj.bool.must[systemTypePosition].match.system_type = this.currentSystemType;
-	          this._updateUI(this.currentSystemType);
 
-	          //this.resultsContainer.style.visibility = 'visible';
-	          LoadingPopup.hide();
-	          this._launchMaterialViewerIfOnlyOne();
-	        });
+  _paginationSearch(){
 
-	      });
+    let systemTypePosition = this.esQueryObject.bool.must.length-1;
+    this.esQueryObject.bool.must[systemTypePosition].match.system_type = this.currentSystemType;
+    let page = this.matMap.get(this.currentSystemType).page;
 
-	    });
+    let req = util.serverReqPOST(util.getSearchURL()+'?page='+page+
+            '&per_page='+RESULTS_PER_PAGE, JSON.stringify(this.esQueryObject), e => {
 
-	/*
-	    oReq.addEventListener("error", e => { // Not valid query
-	      console.log('Search ERROR - Not valid query ');
-	      this.total_results= 0;
-	      this.setData([]);
-	      this._updateUI();
-	      this.resultsContainer.style.visibility = 'visible';
-	      LoadingPopup.hide();
-	    });
-	*/
+      let data = JSON.parse(e.target.response);
 
+      this.matMap.set(this.currentSystemType, this._createSystemTypeData(data, page, true));
+      //console.log('this.matMap: ', this.matMap);
+      this._updateUI(this.currentSystemType);
+    });
 
-	  }
+  }
 
-	  _launchMaterialViewerIfOnlyOne(){
-	    let mat;
-	    let sum = 0;
-	    this.matMap.forEach( (materials, systemType) => {
-	      sum += materials.total;
-	      if (materials.total === 1)
-	        mat = materials.materials.values().next().value[0];
-	    });
 
-	    if (sum === 1)  util.setBrowserHashPath('material',+(mat.id));
-	  }
+  initSearchTest(rootQueryObj){
+    //this.resultsContainer.style.visibility = 'hidden';
+    this.matMap.clear();
 
+    let qqq = { 'bool' : {} };
+    //qqq.bool.must = {"terms":{"crystal_system":{"operator":"or","query":"cubic"}}};
+    qqq.bool.must = {"terms":{"crystal_system": ["hexagonal","cubic"]}};
 
-	  _createSystemTypeData(data, page, status){
-
-	    if (status){
-	        let systemTypeMatMap = new Map();
-
-	        data.results.forEach( mat => {
-	          if (systemTypeMatMap.has(mat.formula_reduced)){
-	            let matArray= systemTypeMatMap.get(mat.formula_reduced);
-	            matArray.push(mat);
-	          }else{
-	            let newArray= []; newArray.push(mat);
-	            systemTypeMatMap.set(mat.formula_reduced, newArray);
-	          }
-	        });
-
-	        return { 'materials': systemTypeMatMap,
-	                 'page': page,
-	                 'total': data.total_results,
-	                 'totalPages': Math.ceil(data.total_results/RESULTS_PER_PAGE)
-	               };
-	    }else return null; // Right query - results not found
-	      //this.total_results = 0;
-	  }
+    console.log('SENDING: ', JSON.stringify(qqq)); console.log(': ', qqq.bool.must);
 
+    let bulkReq = util.serverReqPOST(util.getSearchURL()+'?page=1'+
+            '&per_page='+RESULTS_PER_PAGE, JSON.stringify(qqq), bulke => {
 
-	  _updateUI(systemType){
-
-	    let systemData = this.matMap.get(systemType);
-	    //console.log('_updateUI',systemType, systemData);
-	    this.titleBox.innerHTML= 'Results (total: '+systemData.total+')';
-	    this.pageElement.innerHTML= 'page '+systemData.page+' / '+systemData.totalPages;
-
-	    let html = '';
-
-	    if (systemData === null) {
-	      this.resultsNrTag.style.display = 'none';
-	      this.titleBox.style.display = 'none';
-
-	      //if (this.page === 1)
-	        //html+= `<div class="not-found"> No results found </div>`;
-	      // If there is search without results IF PAGE == 0 THERE ISN'T SEARCH
-
-	    }else{
-	      this.resultsNrTag.style.display = 'block';
-	      this.titleBox.style.display = 'inline';
-
-	      html +=`
-	        <table>
-	          <thead> <tr>
-	            <th style="width: 24%;"></th>
-	            <th style="width: 16%;">
-	              <span info-sys-data="space-group">Space group</span>
-	            </th>
-	            <th style="width: 20%;">
-	              <span >Space gr. int. symbol</span>
-	            </th>
-
-	            <th style="width: 22%;">
-	              <span info-sys-data="structure-type">Structure type</span>
-	            </th>
-	            <th style="width: 18%;">Nº calculations</th>
-	          </tr> </thead>
-	          <tbody>
-	      `;
-
-	      systemData.materials.forEach((mats, formula) => {
-
-	        let rFormula = util.getSubscriptedFormula(formula);
-	        html+= '<tr> <td class="formula" colspan="5"><b>'+rFormula+'</b>';
-	        if ( mats.length > 1)
-	        html += '<span style="font-size: 0.86em;"> ('+mats.length+' structures)</span>';
-	        html += '</td></tr>';
-
-	        mats.forEach( mat => {
-	          let label= (mat.material_name !== null ? mat.material_name : rFormula);
-	          //console.log("MATERIAL ",mat, mat.system_type);
-	          html+=
-	          `<tr class="mat-row" data-mat-id="${mat.id}">
-	            <td  > ${label} [${mat.formula}] </td>
-	            <td style="text-align:center" >
-	              ${mat.space_group_number === null ? '' : mat.space_group_number}
-	            </td>
-	            <td>
-	              ${mat.space_group_international_short_symbol === null ? '' :
-	                mat.space_group_international_short_symbol}
-	            </td>
-
-	            <td> ${mat.structure_type === null ? '' : mat.structure_type } </td>
-	            <td style="text-align:center" > ${mat.nr_of_calculations} </td>
-	          </tr>`;
-	        });
-	      });
-
-	      html +=` </tbody> </table>`;
-	    }
-
-	    this.resultsContainer.innerHTML = html;
-
-	    InfoSys.addToInfoSystem(this.resultsContainer);
-	  }
+      let bulkData = JSON.parse(bulke.target.response);  console.log('GETTING: ', bulkData);
 
-	}
+      this.matMap.set('bulk', this._createSystemTypeData(bulkData, 1, bulke.target.status === 200));
+      LoadingPopup.hide();
+    });
 
-	module.exports = MaterialList;
+  }
 
 
-/***/ },
-/* 36 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-
-	/**
-	 * Copyright 2016-2018 Iker Hurtado
-	 *
-	 * Licensed under the Apache License, Version 2.0 (the "License");
-	 * you may not use this file except in compliance with the License.
-	 * You may obtain a copy of the License at
-	 *
-	 * http://www.apache.org/licenses/LICENSE-2.0
-	 *
-	 * Unless required by applicable law or agreed to in writing, software
-	 * distributed under the License is distributed on an "AS IS" BASIS,
-	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	 * See the License for the specific language governing permissions and
-	 * limitations under the License.
-	 *
-	 */
-
-
-	 /*
-
-	 */
-
-
-	"use strict";
-
-	let util = __webpack_require__(1);
-	let InfoSys = __webpack_require__(12);
-
-
-
-	class FilterPanel {
-
-	  constructor() {
-	    //this.element = document.getElementById('filter-panel-placeholder');
-	    this.element = document.createElement('div');
-	    this.element.setAttribute("id",'filter-panel-placeholder');
-	    this.element.innerHTML=
-	    `     <br>
-	          <div>--- Structure ---</div>
-	          <br>
-	          <div class="field">
-	            <div class="field-title">System type</div>
-	            <input type="checkbox" class="system-type-field" value="bulk"> Bulk<br>
-	            <input type="checkbox" class="system-type-field" value="2D"> 2D<br>
-	            <input type="checkbox" class="system-type-field" value="1D"> 1D<br>
-	          </div>
-
-	          <div class="field">
-	            <div class="field-title"><span info-sys-data="crystal-system">Crystal system</span></div>
-	            <input type="checkbox" class="crystal-system-field" value="cubic">
-	              <span info-sys-data="crystal-system.value:cubic">Cubic</span><br>
-	            <input type="checkbox" class="crystal-system-field" value="hexagonal">
-	              <span info-sys-data="crystal-system.value:hexagonal">Hexagonal</span><br>
-	            <input type="checkbox" class="crystal-system-field" value="trigonal">
-	              <span info-sys-data="crystal-system.value:trigonal">Trigonal</span><br>
-	            <input type="checkbox" class="crystal-system-field" value="tetragonal">
-	              <span info-sys-data="crystal-system.value:tetragonal">Tetragonal</span><br>
-	            <input type="checkbox" class="crystal-system-field" value="orthorhombic">
-	              <span info-sys-data="crystal-system.value:orthorhombic">Orthorhombic</span><br>
-	            <input type="checkbox" class="crystal-system-field" value="monoclinic">
-	              <span info-sys-data="crystal-system.value:monoclinic">Monoclinic</span><br>
-	            <input type="checkbox" class="crystal-system-field" value="triclinic">
-	              <span info-sys-data="crystal-system.value:triclinic">Triclinic</span><br>
-	          </div>
-
-	          <div class="field">
-	            <div class="field-title"><span info-sys-data="space-group">Space group</span></div>
-	            <select id="space-group-dropdown-list">
-	              <option value="by-number">by number</option>
-	              <option value="by-symbol">by short symbol</option>
-	            </select>
-	            <input type="text" class="space-group-textfield" style="width: 60px">
-
-	          </div>
-
-	          <div class="field">
-	            <div class="field-title">Strukturbericht designation</div>
-	            <input type="text" class="strukturbericht-designation-field">
-	          </div>
-
-	          <div class="field">
-	            <div class="field-title"><span info-sys-data="structure-type">Structure type</span></div>
-	            <select class="structure-type-field" style="max-width: 174px">
-	              <option ></option>
-	            </select>
-	          </div>
-
-
-
-	          <br>
-	          <div>--- Properties ---</div>
-	          <br>
-
-	          <div class="field">
-	            <div class="field-title"><span info-sys-data="mass-density">Mass density</span> <span style="font-weight: normal;">(kg/m<sup>3</sup>)</span></div>
-	            <!-- <div class="test-slider">   </div> -->
-
-	            Min: <input type="text" class="mass-density-min-field">&nbsp;&nbsp;
-	            Max: <input type="text" class="mass-density-max-field">
-
-	          </div>
-
-	          <div class="field">
-	            <div class="field-title"><span info-sys-data="band-gap">Band gap</span> <span style="font-weight: normal;">(eV)</span></div>
-	            Min: <input type="text" class="band-gap-min-field">&nbsp;&nbsp;
-	            Max: <input type="text" class="band-gap-max-field">
-	            <!--
-	            <input type="range" class="band-gap-slider" min="5" max="200" step="5" value="100"/>
-	            <input type="range" class="band-gap-slider" min="5" max="200" step="5" value="100"/>
-	            -->
-	          </div>
-
-
-	          <div class="field" >
-	            <input type="radio" name="band-gap-type" value="direct"> Direct<br>
-	            <input type="radio" name="band-gap-type" value="indirect"> Indirect<br>
-	            <input type="radio" name="band-gap-type" value="both" checked> Both<br>
-	          </div>
-
-
-	          <div style="font-weight: bold; padding-bottom: 6px" >Results containing...</div>
-
-	          <input type="checkbox" class="has-band-structure-field" value="Band structure">
-	            <span info-sys-data="has-band-structure">Band structure</span><br>
-	          <input type="checkbox" class="has-dos-field" value="DOS">
-	            <span info-sys-data="has-dos">DOS</span><br>
-	          <input type="checkbox" class="has-fermi-surface-field" value="Fermi surface">
-	            <span info-sys-data="has-fermi-surface">Fermi surface</span><br>
-
-	          <input type="checkbox" class="has-thermal-properties-field" value="Thermal properties">
-	            <span info-sys-data="has-thermal-properties">Thermal properties</span>
-	          <br>
-	          <!-- <input type="checkbox" class="results-containing-field" value="EOS" disabled>Equation of state<br>-->
-
-	    `;
-
-
-	    let structureTypeSelect  = this.element.querySelector('.structure-type-field');
-	    let r1 = util.serverReq(util.getSuggestionURL('structure_type'), () => {
-	      JSON.parse(r1.response).structure_type.forEach( structureType => {
-	        structureTypeSelect.innerHTML += '<option>'+structureType+'</option>';
-	      });
-	    });
+  initSearch(rootQueryObj){
+    //this.resultsContainer.style.visibility = 'hidden';
+    this.matMap.clear();
 
-	    InfoSys.addToInfoSystem(this.element);
+    rootQueryObj.bool.must.push( { "match": {"system_type" : "bulk"} } );
+    console.log('SENDING: ', JSON.stringify(rootQueryObj)); console.log(': ', rootQueryObj.bool.must);
+    let systemTypePosition = rootQueryObj.bool.must.length-1;
+    this.esQueryObject = rootQueryObj;
 
-	/*  code for the MaxMinSlider component testing
-	    this.testSlider = this.element.querySelector('.test-slider');
-	    console.log("TAB: ",this.testSlider);
-	    this.slider = new MaxMinSlider();
-	    this.slider.setRange(0,10000);
-	    this.testSlider.appendChild(this.slider.element);
-	*/
+    LoadingPopup.show();
 
-	  }
+    //let oReq = util.serverReqPOST('http://enc-staging-nomad.esc.rzg.mpg.de/current/v1.0/esmaterials', postQuery, e => {
+    // Bulk materials request
+    let bulkReq = util.serverReqPOST(util.getSearchURL()+'?page=1'+
+            '&per_page='+RESULTS_PER_PAGE, JSON.stringify(rootQueryObj), bulke => {
 
+      let bulkData = JSON.parse(bulke.target.response);  console.log('GETTING: ', bulkData);
 
-	  getValues(){
-	    //let map = this.getPropsWithValueFromCurrentTab(false);
-	    let filterMap = new Map();
-	    this.addFilterFromCheckboxes(filterMap,'system-type');
-	    this.addFilterFromCheckboxes(filterMap, 'crystal-system');
-	    this.addSpaceGroupFilter(filterMap);//this.addFilterFromTextField(filterMap, 'space-group-number');
-	    this.addFilterFromTextField(filterMap, 'strukturbericht-designation');
-	    this.addFilterFromDropdownList(filterMap, 'structure-type');
-	    this.addRangeFilter(filterMap, 'mass-density');
-
-	    this.addRangeFilter(filterMap, 'band-gap');
-	    this.addBandgapTypeFilter(filterMap);
-	    this.addFiltersFromBoolCheckboxes(filterMap,
-	      ['has-band-structure', 'has-dos', 'has-fermi-surface', 'has-thermal-properties']);
-	    console.log('FilterPanel selected:', filterMap);
-	    return filterMap;
-	  }
+      this.matMap.set('bulk', this._createSystemTypeData(bulkData, 1, bulke.target.status === 200));
 
 
+      // 2D materials request
+      rootQueryObj.bool.must[systemTypePosition].match.system_type = '2D';
+      let twoDReq = util.serverReqPOST(util.getSearchURL()+'?page=1'+
+              '&per_page='+RESULTS_PER_PAGE, JSON.stringify(rootQueryObj), twoDe => {
 
-	  addFilterFromTextField(filterMap, filterName){
-	    let field = this.element.querySelector('.'+filterName+'-field');
-	    if (field.value !== '')  filterMap.set(filterName, [field.value]);
-	  }
+        let twoDData = JSON.parse(twoDe.target.response);
 
-	  addFilterFromCheckboxes(filterMap, filterName){
-	    let checkboxes = this.element.querySelectorAll('.'+filterName+'-field');
-	    let value = [];
-	    for (var i = 0; i < checkboxes.length; i++) {
-	      if (checkboxes[i].checked)  value.push(checkboxes[i].value);
-	        //if (reset) checkboxes[i].checked = false;
-	    }
-	    if (value.length > 0) filterMap.set(filterName, value);
-	  }
+        this.matMap.set('2D', this._createSystemTypeData(twoDData, 1, twoDe.target.status === 200));
 
-	  addFilterFromDropdownList(filterMap, filterName){
-	    let field = this.element.querySelector('.'+filterName+'-field');
-	    let value = field.options[field.selectedIndex].value;
-	    if (value.length > 2) filterMap.set(filterName, [value]);
-	    //if (reset) field.selectedIndex = 0;
-	  }
 
-	  addSpaceGroupFilter(filterMap){
-	    let filterName;
-	    let field = this.element.querySelector('#space-group-dropdown-list');
-	    let type = field.options[field.selectedIndex].value;
-	    if (type === 'by-number') filterName = 'space-group-number';
-	    else filterName = 'space-group-international-short-symbol';
-	    let value = this.element.querySelector('.space-group-textfield').value;
-	    if (value.trim() !== '')
-	      filterMap.set(filterName, [value]);
-	    //if (reset) field.selectedIndex = 0;
-	  }
+        // 1D materials request
+        rootQueryObj.bool.must[systemTypePosition].match.system_type = '1D';
+        let oneDReq = util.serverReqPOST(util.getSearchURL()+'?page=1'+
+                '&per_page='+RESULTS_PER_PAGE, JSON.stringify(rootQueryObj), oneDe => {
 
-	  addRangeFilter(filterMap, filterName){
-	    let minField = document.querySelector('.'+filterName+'-min-field');
-	    let maxField = document.querySelector('.'+filterName+'-max-field');
-	    let value = ':';
-	    //let label = 'Mass Density';
-	    if (minField.value !== ''){
-	      //label = minField.value+' < '+label;
-	      value = minField.value+value;
-	      //if (reset) minField.value = '';
-	    }
-	    if (maxField.value !== ''){
-	      //label += ' < '+maxField.value;
-	      value = value+maxField.value;
-	      //if (reset) maxField.value = '';
-	    }
-	    if (value !== ':')  filterMap.set(filterName, value);
-	  }
+          let oneDData = JSON.parse(oneDe.target.response);
 
+          this.matMap.set('1D', this._createSystemTypeData(oneDData, 1, oneDe.target.status === 200));
 
-	  addBandgapTypeFilter(filterMap){
-	    let val = document.querySelector('input[name="band-gap-type"]:checked').value;
-	    filterMap.set("band-gap-type", val);
-	  }
+          let selectedSystemType = null;
+          this.matMap.forEach( (materials, systemType) => {
+            this.element.querySelector('#system-tab-'+systemType).disabled =
+              (materials.total === 0);
+            if (selectedSystemType === null && materials.total > 0) {
+              selectedSystemType = systemType;
+              this.element.querySelector('#system-tab-'+this.currentSystemType).className = '';
+              this.element.querySelector('#system-tab-'+selectedSystemType).className = 'selected';
 
-	  addFiltersFromBoolCheckboxes(filterMap, boolFilters){
-	    boolFilters.forEach( filterName => {
-	      let checkboxes = this.element.querySelectorAll('.'+filterName+'-field');
-	      //let value = [];
-	      for (var i = 0; i < checkboxes.length; i++) {
-	        if (checkboxes[i].checked){
-	          //value.push(checkboxes[i].value);
-	          filterMap.set(filterName, true);
-	        }
-	      }
-	      //if (value.length > 0) propsMap.set(propName, value);
-	    });
-	  }
+              this.currentSystemType = selectedSystemType;
+            }
+          });
+          rootQueryObj.bool.must[systemTypePosition].match.system_type = this.currentSystemType;
+          this._updateUI(this.currentSystemType);
 
+          //this.resultsContainer.style.visibility = 'visible';
+          LoadingPopup.hide();
+          this._launchMaterialViewerIfOnlyOne();
+        });
 
-	  setAddPropertiesListener(listener) {
-	    this.addPropertiesListener= listener;
-	  }
+      });
 
+    });
 
-	}
+/*
+    oReq.addEventListener("error", e => { // Not valid query
+      console.log('Search ERROR - Not valid query ');
+      this.total_results= 0;
+      this.setData([]);
+      this._updateUI();
+      this.resultsContainer.style.visibility = 'visible';
+      LoadingPopup.hide();
+    });
+*/
 
-	// EXPORTS
-	module.exports = FilterPanel;
 
+  }
 
+  _launchMaterialViewerIfOnlyOne(){
+    let mat;
+    let sum = 0;
+    this.matMap.forEach( (materials, systemType) => {
+      sum += materials.total;
+      if (materials.total === 1)
+        mat = materials.materials.values().next().value[0];
+    });
+
+    if (sum === 1)  util.setBrowserHashPath('material',+(mat.id));
+  }
+
+
+  _createSystemTypeData(data, page, status){
+
+    if (status){
+        let systemTypeMatMap = new Map();
+
+        data.results.forEach( mat => {
+          if (systemTypeMatMap.has(mat.formula_reduced)){
+            let matArray= systemTypeMatMap.get(mat.formula_reduced);
+            matArray.push(mat);
+          }else{
+            let newArray= []; newArray.push(mat);
+            systemTypeMatMap.set(mat.formula_reduced, newArray);
+          }
+        });
+
+        return { 'materials': systemTypeMatMap,
+                 'page': page,
+                 'total': data.total_results,
+                 'totalPages': Math.ceil(data.total_results/RESULTS_PER_PAGE)
+               };
+    }else return null; // Right query - results not found
+      //this.total_results = 0;
+  }
 
-	/*  To be implemented in the future
 
-	class MaxMinSlider{
+  _updateUI(systemType){
+
+    let systemData = this.matMap.get(systemType);
+    //console.log('_updateUI',systemType, systemData);
+    this.titleBox.innerHTML= 'Results (total: '+systemData.total+')';
+    this.pageElement.innerHTML= 'page '+systemData.page+' / '+systemData.totalPages;
+
+    let html = '';
+
+    if (systemData === null) {
+      this.resultsNrTag.style.display = 'none';
+      this.titleBox.style.display = 'none';
+
+      //if (this.page === 1)
+        //html+= `<div class="not-found"> No results found </div>`;
+      // If there is search without results IF PAGE == 0 THERE ISN'T SEARCH
+
+    }else{
+      this.resultsNrTag.style.display = 'block';
+      this.titleBox.style.display = 'inline';
+
+      html +=`
+        <table>
+          <thead> <tr>
+            <th style="width: 24%;"></th>
+            <th style="width: 16%;">
+              <span info-sys-data="space-group">Space group</span>
+            </th>
+            <th style="width: 20%;">
+              <span >Space gr. int. symbol</span>
+            </th>
+
+            <th style="width: 22%;">
+              <span info-sys-data="structure-type">Structure type</span>
+            </th>
+            <th style="width: 18%;">Nº calculations</th>
+          </tr> </thead>
+          <tbody>
+      `;
+
+      systemData.materials.forEach((mats, formula) => {
+
+        let rFormula = util.getSubscriptedFormula(formula);
+        html+= '<tr> <td class="formula" colspan="5"><b>'+rFormula+'</b>';
+        if ( mats.length > 1)
+        html += '<span style="font-size: 0.86em;"> ('+mats.length+' structures)</span>';
+        html += '</td></tr>';
+
+        mats.forEach( mat => {
+          let label= (mat.material_name !== null ? mat.material_name : rFormula);
+          //console.log("MATERIAL ",mat, mat.system_type);
+          html+=
+          `<tr class="mat-row" data-mat-id="${mat.id}">
+            <td  > ${label} [${mat.formula}] </td>
+            <td style="text-align:center" >
+              ${mat.space_group_number === null ? '' : mat.space_group_number}
+            </td>
+            <td>
+              ${mat.space_group_international_short_symbol === null ? '' :
+                mat.space_group_international_short_symbol}
+            </td>
+
+            <td> ${mat.structure_type === null ? '' : mat.structure_type } </td>
+            <td style="text-align:center" > ${mat.nr_of_calculations} </td>
+          </tr>`;
+        });
+      });
+
+      html +=` </tbody> </table>`;
+    }
+
+    this.resultsContainer.innerHTML = html;
+
+    InfoSys.addToInfoSystem(this.resultsContainer);
+  }
+
+}
+
+module.exports = MaterialList;
+
+
+/***/ }),
+/* 36 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+/**
+ * Copyright 2016-2018 Iker Hurtado
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+ /*
+
+ */
 
-	  constructor(){
 
-	    this.element = document.createElement('div');
-	    this.element.innerHTML = `
-	      <svg class="maxminslider" xmlns="http://www.w3.org/2000/svg" width="100px" height="40px"
-	        viewBox="0 0 100 40" >
-	        <line class="slider-bar" x1="10" x2="90" y1="30" y2="30" stroke="blue"
-	        stroke-width="4"/>
-	        <circle class="min-btn" cx="10" cy="30" r="6" fill="black"/>
-	        <text class="min-text maxminslider-text" x="10" y="10" text-anchor="start"></text>
-	        <circle class="max-btn" cx="90" cy="30" r="6" fill="black"/>
-	        <text class="max-text maxminslider-text" x="90" y="10" text-anchor="end"></text>
-	      </svg>
-	    `;
 
-	    //this.bar = this.element.querySelector('.slider-bar');
-	    this.svg = this.element.querySelector('svg');
-	    this.minButton = this.element.querySelector('.min-btn');
-	    this.minText = this.element.querySelector('.min-text');
-	    this.maxButton = this.element.querySelector('.max-btn');
-	    this.maxText = this.element.querySelector('.max-text');
 
-	    this.BUTTON_R = 6;
+let util = __webpack_require__(0);
+let InfoSys = __webpack_require__(3);
+
+
+
+class FilterPanel {
+
+  constructor() {
+    //this.element = document.getElementById('filter-panel-placeholder');
+    this.element = document.createElement('div');
+    this.element.setAttribute("id",'filter-panel-placeholder');
+    this.element.innerHTML=
+    `     <br>
+          <div>--- Structure ---</div>
+          <br>
+          <div class="field">
+            <div class="field-title">System type</div>
+            <input type="checkbox" class="system-type-field" value="bulk"> Bulk<br>
+            <input type="checkbox" class="system-type-field" value="2D"> 2D<br>
+            <input type="checkbox" class="system-type-field" value="1D"> 1D<br>
+          </div>
+
+          <div class="field">
+            <div class="field-title"><span info-sys-data="crystal-system">Crystal system</span></div>
+            <input type="checkbox" class="crystal-system-field" value="cubic">
+              <span info-sys-data="crystal-system.value:cubic">Cubic</span><br>
+            <input type="checkbox" class="crystal-system-field" value="hexagonal">
+              <span info-sys-data="crystal-system.value:hexagonal">Hexagonal</span><br>
+            <input type="checkbox" class="crystal-system-field" value="trigonal">
+              <span info-sys-data="crystal-system.value:trigonal">Trigonal</span><br>
+            <input type="checkbox" class="crystal-system-field" value="tetragonal">
+              <span info-sys-data="crystal-system.value:tetragonal">Tetragonal</span><br>
+            <input type="checkbox" class="crystal-system-field" value="orthorhombic">
+              <span info-sys-data="crystal-system.value:orthorhombic">Orthorhombic</span><br>
+            <input type="checkbox" class="crystal-system-field" value="monoclinic">
+              <span info-sys-data="crystal-system.value:monoclinic">Monoclinic</span><br>
+            <input type="checkbox" class="crystal-system-field" value="triclinic">
+              <span info-sys-data="crystal-system.value:triclinic">Triclinic</span><br>
+          </div>
+
+          <div class="field">
+            <div class="field-title"><span info-sys-data="space-group">Space group</span></div>
+            <select id="space-group-dropdown-list">
+              <option value="by-number">by number</option>
+              <option value="by-symbol">by short symbol</option>
+            </select>
+            <input type="text" class="space-group-textfield" style="width: 60px">
+
+          </div>
+
+          <div class="field">
+            <div class="field-title">Strukturbericht designation</div>
+            <input type="text" class="strukturbericht-designation-field">
+          </div>
+
+          <div class="field">
+            <div class="field-title"><span info-sys-data="structure-type">Structure type</span></div>
+            <select class="structure-type-field" style="max-width: 174px">
+              <option ></option>
+            </select>
+          </div>
+
+
+
+          <br>
+          <div>--- Properties ---</div>
+          <br>
+
+          <div class="field">
+            <div class="field-title"><span info-sys-data="mass-density">Mass density</span> <span style="font-weight: normal;">(kg/m<sup>3</sup>)</span></div>
+            <!-- <div class="test-slider">   </div> -->
+
+            Min: <input type="text" class="mass-density-min-field">&nbsp;&nbsp;
+            Max: <input type="text" class="mass-density-max-field">
+
+          </div>
+
+          <div class="field">
+            <div class="field-title"><span info-sys-data="band-gap">Band gap</span> <span style="font-weight: normal;">(eV)</span></div>
+            Min: <input type="text" class="band-gap-min-field">&nbsp;&nbsp;
+            Max: <input type="text" class="band-gap-max-field">
+            <!--
+            <input type="range" class="band-gap-slider" min="5" max="200" step="5" value="100"/>
+            <input type="range" class="band-gap-slider" min="5" max="200" step="5" value="100"/>
+            -->
+          </div>
+
+
+          <div class="field" >
+            <input type="radio" name="band-gap-type" value="direct"> Direct<br>
+            <input type="radio" name="band-gap-type" value="indirect"> Indirect<br>
+            <input type="radio" name="band-gap-type" value="both" checked> Both<br>
+          </div>
+
+
+          <div style="font-weight: bold; padding-bottom: 6px" >Results containing...</div>
+
+          <input type="checkbox" class="has-band-structure-field" value="Band structure">
+            <span info-sys-data="has-band-structure">Band structure</span><br>
+          <input type="checkbox" class="has-dos-field" value="DOS">
+            <span info-sys-data="has-dos">DOS</span><br>
+          <input type="checkbox" class="has-fermi-surface-field" value="Fermi surface">
+            <span info-sys-data="has-fermi-surface">Fermi surface</span><br>
+
+          <input type="checkbox" class="has-thermal-properties-field" value="Thermal properties">
+            <span info-sys-data="has-thermal-properties">Thermal properties</span>
+          <br>
+          <!-- <input type="checkbox" class="results-containing-field" value="EOS" disabled>Equation of state<br>-->
+
+    `;
+
+
+    let structureTypeSelect  = this.element.querySelector('.structure-type-field');
+    let r1 = util.serverReq(util.getSuggestionURL('structure_type'), () => {
+      JSON.parse(r1.response).structure_type.forEach( structureType => {
+        structureTypeSelect.innerHTML += '<option>'+structureType+'</option>';
+      });
+    });
+
+    InfoSys.addToInfoSystem(this.element);
+
+/*  code for the MaxMinSlider component testing
+    this.testSlider = this.element.querySelector('.test-slider');
+    console.log("TAB: ",this.testSlider);
+    this.slider = new MaxMinSlider();
+    this.slider.setRange(0,10000);
+    this.testSlider.appendChild(this.slider.element);
+*/
+
+  }
+
+
+  getValues(){
+    //let map = this.getPropsWithValueFromCurrentTab(false);
+    let filterMap = new Map();
+    this.addFilterFromCheckboxes(filterMap,'system-type');
+    this.addFilterFromCheckboxes(filterMap, 'crystal-system');
+    this.addSpaceGroupFilter(filterMap);//this.addFilterFromTextField(filterMap, 'space-group-number');
+    this.addFilterFromTextField(filterMap, 'strukturbericht-designation');
+    this.addFilterFromDropdownList(filterMap, 'structure-type');
+    this.addRangeFilter(filterMap, 'mass-density');
+
+    this.addRangeFilter(filterMap, 'band-gap');
+    this.addBandgapTypeFilter(filterMap);
+    this.addFiltersFromBoolCheckboxes(filterMap,
+      ['has-band-structure', 'has-dos', 'has-fermi-surface', 'has-thermal-properties']);
+    console.log('FilterPanel selected:', filterMap);
+    return filterMap;
+  }
+
+
+
+  addFilterFromTextField(filterMap, filterName){
+    let field = this.element.querySelector('.'+filterName+'-field');
+    if (field.value !== '')  filterMap.set(filterName, [field.value]);
+  }
+
+  addFilterFromCheckboxes(filterMap, filterName){
+    let checkboxes = this.element.querySelectorAll('.'+filterName+'-field');
+    let value = [];
+    for (var i = 0; i < checkboxes.length; i++) {
+      if (checkboxes[i].checked)  value.push(checkboxes[i].value);
+        //if (reset) checkboxes[i].checked = false;
+    }
+    if (value.length > 0) filterMap.set(filterName, value);
+  }
+
+  addFilterFromDropdownList(filterMap, filterName){
+    let field = this.element.querySelector('.'+filterName+'-field');
+    let value = field.options[field.selectedIndex].value;
+    if (value.length > 2) filterMap.set(filterName, [value]);
+    //if (reset) field.selectedIndex = 0;
+  }
+
+  addSpaceGroupFilter(filterMap){
+    let filterName;
+    let field = this.element.querySelector('#space-group-dropdown-list');
+    let type = field.options[field.selectedIndex].value;
+    if (type === 'by-number') filterName = 'space-group-number';
+    else filterName = 'space-group-international-short-symbol';
+    let value = this.element.querySelector('.space-group-textfield').value;
+    if (value.trim() !== '')
+      filterMap.set(filterName, [value]);
+    //if (reset) field.selectedIndex = 0;
+  }
+
+  addRangeFilter(filterMap, filterName){
+    let minField = document.querySelector('.'+filterName+'-min-field');
+    let maxField = document.querySelector('.'+filterName+'-max-field');
+    let value = ':';
+    //let label = 'Mass Density';
+    if (minField.value !== ''){
+      //label = minField.value+' < '+label;
+      value = minField.value+value;
+      //if (reset) minField.value = '';
+    }
+    if (maxField.value !== ''){
+      //label += ' < '+maxField.value;
+      value = value+maxField.value;
+      //if (reset) maxField.value = '';
+    }
+    if (value !== ':')  filterMap.set(filterName, value);
+  }
+
+
+  addBandgapTypeFilter(filterMap){
+    let val = document.querySelector('input[name="band-gap-type"]:checked').value;
+    filterMap.set("band-gap-type", val);
+  }
+
+  addFiltersFromBoolCheckboxes(filterMap, boolFilters){
+    boolFilters.forEach( filterName => {
+      let checkboxes = this.element.querySelectorAll('.'+filterName+'-field');
+      //let value = [];
+      for (var i = 0; i < checkboxes.length; i++) {
+        if (checkboxes[i].checked){
+          //value.push(checkboxes[i].value);
+          filterMap.set(filterName, true);
+        }
+      }
+      //if (value.length > 0) propsMap.set(propName, value);
+    });
+  }
+
+
+  setAddPropertiesListener(listener) {
+    this.addPropertiesListener= listener;
+  }
+
+
+}
+
+// EXPORTS
+module.exports = FilterPanel;
+
+
+
+/*  To be implemented in the future
+
+class MaxMinSlider{
+
+  constructor(){
+
+    this.element = document.createElement('div');
+    this.element.innerHTML = `
+      <svg class="maxminslider" xmlns="http://www.w3.org/2000/svg" width="100px" height="40px"
+        viewBox="0 0 100 40" >
+        <line class="slider-bar" x1="10" x2="90" y1="30" y2="30" stroke="blue"
+        stroke-width="4"/>
+        <circle class="min-btn" cx="10" cy="30" r="6" fill="black"/>
+        <text class="min-text maxminslider-text" x="10" y="10" text-anchor="start"></text>
+        <circle class="max-btn" cx="90" cy="30" r="6" fill="black"/>
+        <text class="max-text maxminslider-text" x="90" y="10" text-anchor="end"></text>
+      </svg>
+    `;
+
+    //this.bar = this.element.querySelector('.slider-bar');
+    this.svg = this.element.querySelector('svg');
+    this.minButton = this.element.querySelector('.min-btn');
+    this.minText = this.element.querySelector('.min-text');
+    this.maxButton = this.element.querySelector('.max-btn');
+    this.maxText = this.element.querySelector('.max-text');
+
+    this.BUTTON_R = 6;
 
-	    this.minButtonDown = false;
-	    this.minButtonInitX = null;
+    this.minButtonDown = false;
+    this.minButtonInitX = null;
 
-	    this.MIN_BUTTON_INIT_X = 10;
-	    this.minX = 0;
+    this.MIN_BUTTON_INIT_X = 10;
+    this.minX = 0;
 
-	    this.maxButtonDown = false;
-	    this.maxButtonInitX = null;
-	    this.MAX_VALUE = 80;//this.MAX_BUTTON_INIT_X = 90;
-	    this.maxX = this.MAX_VALUE;
+    this.maxButtonDown = false;
+    this.maxButtonInitX = null;
+    this.MAX_VALUE = 80;//this.MAX_BUTTON_INIT_X = 90;
+    this.maxX = this.MAX_VALUE;
 
-	    console.log('minButton', this.minButton.getBoundingClientRect());
+    console.log('minButton', this.minButton.getBoundingClientRect());
 
-	    this._events();
-	  }
+    this._events();
+  }
 
 
-	  _events() {
+  _events() {
 
-	    this.minButton.addEventListener( "mousedown", e => this.minButtonDown = true );
-	    this.minButton.addEventListener( "mouseup", e => this.minButtonDown = false );
-	    this.minButton.addEventListener( "mouseleave", e => this.minButtonDown = false );
+    this.minButton.addEventListener( "mousedown", e => this.minButtonDown = true );
+    this.minButton.addEventListener( "mouseup", e => this.minButtonDown = false );
+    this.minButton.addEventListener( "mouseleave", e => this.minButtonDown = false );
 
-	    this.minButton.addEventListener( "mousemove", e => {
-	      //e.preventDefault();
-	      if (this.minButtonInitX === null){
-	        //this.minButtonInitX = this.svg.getBoundingClientRect().left;
-	        this.minButtonInitX = this.minButton.getBoundingClientRect().left+this.BUTTON_R;//
-	        //console.log('left', this.minButtonInitX);
-	      }
+    this.minButton.addEventListener( "mousemove", e => {
+      //e.preventDefault();
+      if (this.minButtonInitX === null){
+        //this.minButtonInitX = this.svg.getBoundingClientRect().left;
+        this.minButtonInitX = this.minButton.getBoundingClientRect().left+this.BUTTON_R;//
+        //console.log('left', this.minButtonInitX);
+      }
 
-	      if (this.minButtonDown){
-	        this.minX  = e.clientX-this.minButtonInitX ;
-	        if (this.minX > 0 && this.minX < this.maxX-this.BUTTON_R){
-	          this.minButton.setAttribute('cx', this.MIN_BUTTON_INIT_X + this.minX);
-	          this.minText.textContent = this.minX*this.factor-250;
-	        }
+      if (this.minButtonDown){
+        this.minX  = e.clientX-this.minButtonInitX ;
+        if (this.minX > 0 && this.minX < this.maxX-this.BUTTON_R){
+          this.minButton.setAttribute('cx', this.MIN_BUTTON_INIT_X + this.minX);
+          this.minText.textContent = this.minX*this.factor-250;
+        }
 
-	      }
-	    });
+      }
+    });
 
 
-	    this.maxButton.addEventListener( "mousedown", e => this.maxButtonDown = true );
-	    this.maxButton.addEventListener( "mouseup", e => this.maxButtonDown = false );
-	    this.maxButton.addEventListener( "mouseleave", e => this.maxButtonDown = false );
+    this.maxButton.addEventListener( "mousedown", e => this.maxButtonDown = true );
+    this.maxButton.addEventListener( "mouseup", e => this.maxButtonDown = false );
+    this.maxButton.addEventListener( "mouseleave", e => this.maxButtonDown = false );
 
-	    this.maxButton.addEventListener( "mousemove", e => {
-	      //e.preventDefault();
+    this.maxButton.addEventListener( "mousemove", e => {
+      //e.preventDefault();
 
-	      if (this.maxButtonInitX === null)
-	        this.maxButtonInitX = this.maxButton.getBoundingClientRect().left+this.BUTTON_R;//
+      if (this.maxButtonInitX === null)
+        this.maxButtonInitX = this.maxButton.getBoundingClientRect().left+this.BUTTON_R;//
 
-	      if (this.maxButtonDown){
+      if (this.maxButtonDown){
 
-	        this.maxX  = e.clientX - this.minButtonInitX;
-	        //console.log('maxButton', e.clientX, this.maxButtonInitX, this.maxX);
-	        if (this.maxX < this.MAX_VALUE  && this.minX+this.BUTTON_R < this.maxX){
-	          this.maxButton.setAttribute('cx', this.MIN_BUTTON_INIT_X + this.maxX);
-	          this.maxText.textContent = this.maxX*this.factor;
-	        }
+        this.maxX  = e.clientX - this.minButtonInitX;
+        //console.log('maxButton', e.clientX, this.maxButtonInitX, this.maxX);
+        if (this.maxX < this.MAX_VALUE  && this.minX+this.BUTTON_R < this.maxX){
+          this.maxButton.setAttribute('cx', this.MIN_BUTTON_INIT_X + this.maxX);
+          this.maxText.textContent = this.maxX*this.factor;
+        }
 
-	      }
+      }
 
-	    });
+    });
 
 
-	  }
+  }
 
 
-	  setRange(min, max){
-	    this.factor = (max-min)/80;
-	  }
+  setRange(min, max){
+    this.factor = (max-min)/80;
+  }
 
-	}
+}
 
-	*/
+*/
 
 
-/***/ }
+/***/ })
 /******/ ]);
\ No newline at end of file
diff --git a/client/src/search-mod/NewSearchMod.js b/client/src/search-mod/NewSearchMod.js
index a3f6644d..00a798df 100644
--- a/client/src/search-mod/NewSearchMod.js
+++ b/client/src/search-mod/NewSearchMod.js
@@ -38,7 +38,7 @@ let SwitchComponent = require('../common/SwitchComponent.js');
 // local utility functions
 function getTagHtml(tag, isFormula){
   return `<span class="search-label" data-el="${tag}" >
-            <img src="img/${isFormula ? 'info' : 'tag'}.svg" height="16px" class="remove-label"
+            <img src="img/tag.svg" height="16px" class="remove-label"
               style="vertical-align: bottom"/>
           ${isFormula ? util.getSubscriptedFormula(tag) : tag}
           <img src="img/cross.svg" height="6px" class="remove-label"
@@ -219,24 +219,30 @@ class NewSearchMod {
       }else{
         let searchExpressionQuery;
 
-        //************** Material name or complex search expression
-        //if (this.queryTypes[i] === 'MN'){
+        // Search by  Material name
+        if (this.queryTypes[0] === 'MN'){
           //queryObj.push(this._getESSimpleMatch('material_name', item));
-
-
-        if (this.element.querySelector('#allow-other-elements').checked)
-          searchExpressionQuery = this._getESQueryFromSearchQuery_otherElements(
-            this.searchQuery, this.queryTypes);
-        // Regular case: search containing only the elements in the search expression
-        else searchExpressionQuery =
-            this._getESQueryFromSearchQuery(this.searchQuery, this.queryTypes);
-
-        this.materialList.initSearch(
-          this._addFiltersInSearchQuery( this.filterPanel.getValues(),
-            searchExpressionQuery));
-        //util.setBrowserHashPath('search','results');
-
-        this.element.querySelector('.add-box').style.display = 'none';
+          let rootQueryObj = { 'bool' : {} };
+          rootQueryObj.bool.must = [];
+          rootQueryObj.bool.must.push( this._getESSimpleMatch('material_name', this.searchQuery[0]) );
+          this.materialList.initSearch( rootQueryObj );
+
+        }else{ // Search by complex search expression
+
+          if (this.element.querySelector('#allow-other-elements').checked)
+            searchExpressionQuery = this._getESQueryFromSearchQuery_otherElements(
+              this.searchQuery, this.queryTypes);
+          // Regular case: search containing only the elements in the search expression
+          else searchExpressionQuery =
+              this._getESQueryFromSearchQuery(this.searchQuery, this.queryTypes);
+
+          this.materialList.initSearch(
+            this._addFiltersInSearchQuery( this.filterPanel.getValues(),
+              searchExpressionQuery));
+          //util.setBrowserHashPath('search','results');
+
+          this.element.querySelector('.add-box').style.display = 'none';
+        }
       }
 
     });
@@ -608,6 +614,7 @@ class NewSearchMod {
   removeElementORFormulaInSearchQuery(item){
     //console.log(" removeElementORFormulaInSearchQuery item: ",item, this.searchQuery.indexOf(item));
 
+    let isMaterialName = (this.queryTypes[0] === 'MN');
     // Travese the array removing the item and the bool operator related
     let itemIndex = this.searchQuery.indexOf(item);
     if (itemIndex >= 0){
@@ -643,18 +650,19 @@ class NewSearchMod {
 
     if (util.ELEMENTS.indexOf(item) >= 0){ // It's an element (being removed)
       this.elementTable.deselectElement(item);
-      if (this.queryTypes.indexOf('E') < 0){ // It's the last element
-        //this.addFormulaButton.disabled = false;
+    }
+
+    if (this.queryTypes.length === 0){ 
+
+      if (isMaterialName){
+        this.addElementButton.disabled = false;
+        this.addFormulaButton.disabled = false;
+        this.formulaBox.disable(false);
+      }else{ // element or formula
         this.addMatNameButton.disabled = false;
+        
       }
-
-    }else{ // It's other than element (formula, material name ¿or prop???)
-      this.addElementButton.disabled = false;
-      this.formulaBox.disable(false);
       this.materialNameBox.disable(false);
-      // Added ¿?
-      this.addFormulaButton.disabled = false;
-      this.addMatNameButton.disabled = false;
     }
 
     //console.log(" final searchQuery: ",this.searchQuery);
-- 
GitLab