<commit_before>var properties = ["current", "voltage", "cputemp", "hddtemp", "pmutemp", "cpu0freq",
"cpu1freq","txbytes","rxbytes","Free_RAM","Uptime","Users_logged_on","Load"];

var hosts = [];

var units = {"current": "[A]", "voltage": "[V]", "cputemp": "[°C]", "hddtemp" : "[°C]",
"pmutemp": "[°C]", "cpu0freq": "[MHz]","cpu1freq": "[MHz]","txbytes": "MB","rxbytes": "MB","Free_RAM": "MB","Uptime":"","Users_logged_on":"","Load":"[%]" };

var defaultValues = {
  properties: ["voltage", "current", "cputemp", "pmutemp", "hddtemp"]
};

var jsonData = {"x":[]};
var charts = {};
var dateRange = [];

var graphInformation = {}; // caches graph info before drawing
var charts = {}; // holds references to drawn charts
var progressbar;



function setupPropertySelection(){
  var citynames = new Bloodhound({
    datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    prefetch: {
      url: 'propertynames.json',
      filter: function(list) {
        return $.map(list, function(cityname) {
          return { name: cityname }; });
        }
      }
    });
  citynames.initialize();

  $( "#property-selection input[type='text']" ).tagsinput({
    typeaheadjs: {
      name: 'propertynames',
      displayKey: 'name',
      valueKey: 'name',
      source: citynames.ttAdapter()
    }
  });

  $("#property-selection input[type='text']").on('beforeItemAdd', function(event) {
    var propertyName = event.item;
    if(properties.indexOf(propertyName) === -1){
      event.cancel = true; // prevent item from being added, when it is not in the properties-array
    }
  });

  $("#property-selection input[type='text']" ).eq(2).on('itemAdded', function(event) {
    var propertyName = event.item;
    if($("#p_" + propertyName).length){
      $("#p_" + propertyName).show();
    }
    else{
      $("#sortable").append('<li id="p_' + propertyName +'" class="ui-state-default">' +
      '<div class="paperLikeShadow"><p class="propertyTitle">' +  propertyName +" "+ units[propertyName] + '</p><div id="chart_' + propertyName +'"></div></div></li>');

      // setup sortable divs
      $( "#sortable" ).sortable();

      $("#chk_" + propertyName).prop('checked', true);
      $("#chk_" + propertyName).button( "refresh" );

      setupChart(propertyName);
    }
    $.notify({title: "<strong>" + propertyName + "</strong>", message: ": Graph added"},
      {
        placement: {from: "bottom", align: "right"},
        newest_on_top: true,
        animate: {
          enter: 'animated fadeInDown',
          exit: 'animated fadeOutUp'
        },
        type: 'success'
      });
  });

  $("#property-selection input[type='text']").eq(2).on('itemRemoved', function(event) {
    if($("#p_" + event.item).length){
      $("#p_" + event.item).hide();
      $("#chk_" + event.item).prop('checked', false);
      $("#chk_" + event.item).button( "refresh" );

      $.notify({title: "<strong>" + event.item + "</strong>", message: ": Graph removed"},
        {
          placement: {from: "bottom", align: "right"},
          newest_on_top: true,
          animate: {
            enter: 'animated fadeInDown',
            exit: 'animated fadeOutUp'
          },
          type: 'danger'
        });
    }
  });

  $("#property-selection div.bootstrap-tagsinput").first().append(
    '<button id="propertyBtn" class="tagsBtn"><i class="fa fa-cog" aria-hidden="true"></i></button>');

  $("#propertyBtn").button().on( "click", function() {
    propertyDialog.dialog( "open" );
  });

}

function setupPropertyDialog(){
  properties.forEach(function(property) {
    $("#dialog-properties form fieldset").append('<label for="chk_' + property +'">' + property +'</label>');
    $("#dialog-properties form fieldset").append('<input class="chkbox" id="chk_' + property +'" type="checkbox"' +
    'value="' + property +'">');
  });

  $( "#dialog-properties .chkbox" ).checkboxradio();

  $("#dialog-properties .chkbox").bind('change', function(){
    if($(this).is(':checked')){
      $("#property-selection input[type='text']").eq(2).tagsinput('add', $(this).attr('value'),{preventPost: true});
      console.log("adding tag" + $(this).attr('value'));
    }else{

      $("#property-selection input[type='text']").eq(2).tagsinput('remove', $(this).attr('value'));
    }
  });

  propertyDialog = $( "#dialog-properties" ).dialog({
    autoOpen: false,
    resizable: true,
    modal: false,
    height: 'auto',
    width:'500px'
  });
}

function setupHostSelection(){
  var hostnames = new Bloodhound({
    datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    prefetch: {
      url: 'hostnames.json',
      filter: function(list) {
        return $.map(list, function(hostname) {
          return { name: hostname }; });
        }
      }
    });
  hostnames.initialize();

  $( "#host-selection input[type='text']" ).tagsinput({
    typeaheadjs: {
      name: 'hostnames',
      displayKey: 'name',
      valueKey: 'name',
      source: hostnames.ttAdapter()
    }
  });

  $("#host-selection input[type='text']").on('beforeItemAdd', function(event) {
    if(hosts.indexOf(event.item) === -1){
      event.cancel = true; // prevent item from being added, when it is not in the hosts-array
    }
  });

  $("#host-selection input[type='text']" ).eq(2).on('itemAdded', function(event) {
    var hostname = event.item;
    $("#chk_" + hostname).prop('checked', true);
    $("#chk_" + hostname).button( "refresh" );
    if(! jsonData.hasOwnProperty(hostname)){
      $.getJSON("history/" + hostname + "_hist.json").done(function(json){
        integrateJsonData(hostname, json);
      })
      .fail(function( jqxhr, textStatus, error ) {
        var err = textStatus + ", " + error;
        console.log( "Request Failed: " + err );
      });
    }else{
      // immediately update existing charts (data is there)
      for(var propertyName in charts) {
        charts[propertyName].show([hostname],{withLegend: true});
      }
    }
    console.log(hostname + " added");
  });

  $("#host-selection input[type='text']" ).eq(2).on('itemRemoved', function(event) {
    var hostname = event.item;
    $("#chk_" + hostname).prop('checked', false);
    $("#chk_" + hostname).button( "refresh" );

    // update existing charts
    for(var propertyName in charts) {
      //charts[propertyName].unload({ids: [hostname]});
      charts[propertyName].hide([hostname],{withLegend: true});
    }
    console.log(hostname + " removed");
  });

  $("#host-selection div.bootstrap-tagsinput").first().append(
    '<button id="hostBtn" class="tagsBtn"><i class="fa fa-cog" aria-hidden="true"></i></button>');

  $("#hostBtn").button().on( "click", function() {
    hostDialog.dialog( "open" );
  });

}

function conformJsonValue(propertyName, value){
  switch(propertyName){
    case "voltage":
    case "current":
    return value / 1000000;
    case "cpu0freq":
    case "cpu1freq":
    return value / 1000;
    case "cputemp":
    case "pmutemp":
    return value.replace("°C","");
    case "txbytes":
    case "rxbytes":
    return value / 1000000;
    default:
    return value;
  }
}

function setupHostDialog(){
  hosts.forEach(function(host) {
    $("#dialog-host form fieldset").append('<label for="chk_' + host +'">' + host +'</label>');
    $("#dialog-host form fieldset").append('<input class="chkbox" id="chk_' + host +'" type="checkbox"' +
    'value="' + host +'">');
  });

  $( "#dialog-host .chkbox" ).checkboxradio();

  $("#dialog-host .chkbox").bind('change', function(){
    if($(this).is(':checked')){
      $("#host-selection input[type='text']").eq(2).tagsinput('add', $(this).attr('value'),{preventPost: true});
      console.log("adding tag" + $(this).attr('value'));
    }else{

      $("#host-selection input[type='text']").eq(2).tagsinput('remove', $(this).attr('value'));
    }
  });

  hostDialog = $( "#dialog-host" ).dialog({
    autoOpen: false,
    resizable: true,
    modal: false,
    height: 'auto',
    width:'500px'
  });
}

function setupChart(propertyName){
  columns = [['x'].concat(jsonData.x)];
  console.log("setting up chart for " + propertyName);
  $("#host-selection input[type='text']").eq(2).tagsinput('items').forEach(function(hostname){
    console.log("adding data from " + hostname);
    if(jsonData.hasOwnProperty(hostname)){
      columns.push([hostname].concat(jsonData[hostname][propertyName]));
    }
  });

  charts[propertyName] = c3.generate({
    bindto: '#chart_' + propertyName,
    data: {
      x: 'x',
      xFormat: '%a %b %d %H:%M:%S %Y',
      columns: columns
    },
    point: {
      show: false
    },
    transition: {
      duration: 0
    },
    interaction: {
      enabled: false
    },
    axis: {
      x: {
        type: 'timeseries',
        min: dateRange[0],
        max: dateRange[1],
        tick: {
          format: '%d.%m.%Y %H:%M:%S',
        }
      },
      y: {
        tick: {
          format: d3.format(",.2f")
        }
      }
    },
    grid: {
      x: {
        show: false
      },
      y: {
        show: true
      }
    },
    padding: {
      bottom: 30
    }
  });
}

function integrateJsonData(hostname, json){
  if(Object.keys(jsonData).length == 1){
    // adding first PI
    json.history.forEach(function(histEntry){
      //TODO: reliably filter out zone, or find appropriate format-string!
      jsonData.x.push(histEntry.date.replace("CEST ",""));
    });

    $("#datefrom").datepicker({
      minDate: new Date(jsonData.x[0]),
      maxDate:  new Date(jsonData.x[jsonData.x.length-1]),
      onSelect: function(date) {
        dateRange[0] = new Date(date);

        // if the user selected the first day on record, do not start chart
        // with 00:00, start instead with time of first entry (e.g. 09:00) (no leading "empty-space")
        var firstdate = new Date(jsonData.x[0]);
        if(dateRange[0].toDateString() == firstdate.toDateString()){
          dateRange[0] = firstdate;
        }

        // update existing charts
        for(var propertyName in charts) {
          charts[propertyName].axis.range({min: {x: dateRange[0]}});
        }
      }
    });
    $("#datefrom").datepicker('setDate', new Date(jsonData.x[0]));

    $("#dateto").datepicker({
      value: new Date(jsonData.x[jsonData.x.length-1]),
      minDate: new Date(jsonData.x[0]),
      maxDate:  new Date(jsonData.x[jsonData.x.length-1]),
      onSelect: function(date) {
        dateRange[1] = new Date(date);

        // if the user selected the last day on record, do not end chart
        // with 00:00, end instead with time of last entry (e.g. 09:00) (no trailing "empty-space")
        var lastdate = new Date(jsonData.x[jsonData.x.length-1]);
        if(dateRange[1].toDateString() == lastdate.toDateString()){
          dateRange[1] = lastdate;
        }

        // update existing charts
        for(var propertyName in charts) {
          charts[propertyName].axis.range({max:{x: dateRange[1]}});
        }
      }
    });
    $("#dateto").datepicker('setDate', new Date(jsonData.x[jsonData.x.length-1]));

  }

  var data = {};
  properties.forEach(function(property){
    data[property.split("_").join(" ")] = [];
  });

  json.history.forEach(function(histEntry){
    data.voltage.push(histEntry.voltage / 1000000);
    data.current.push(histEntry.current / 1000000);
    data.cpu0freq.push(histEntry.cpu0freq / 1000);
    data.cpu1freq.push(histEntry.cpu1freq / 1000);
    data.cputemp.push(histEntry.cputemp.replace("°C",""));
    data.pmutemp.push(histEntry.pmutemp.replace("°C",""));
    data.txbytes.push(histEntry.txbytes / 1000000);
    data.rxbytes.push(histEntry.rxbytes / 1000000);

    data.hddtemp.push(histEntry.hddtemp);
    data["Free RAM"].push(histEntry["Free RAM"]);
    data.Uptime.push(histEntry.Uptime);
    data["Users logged on"].push(histEntry["Users logged on"]);
    data.Load.push(histEntry.Load);
  });

  jsonData[hostname] = data;
  console.log(hostname + " integrated");
  // hosts.length+1 ... compensate x-property present in jsonData
  progressbar.progressbar( "value", (Object.keys(jsonData).length / (hosts.length+1))*100);
}

function getHostHistoryInformation(){
  // start displaying progress indicator
  progressbar.show();

  // for host in hosts, request history_file
  hosts.forEach(function(host){
    $("#host-selection input[type='text']").eq(2).tagsinput('add', host);
  });

  // progress is updated when a file has been downloaded and integrated
  // progress 100% -> hide progressbar and display default-charts
}
<commit_msg>changed initialization of typeahead.js to use locally specified values (stop requesting two unneccessary JSON-files)<commit_after>var properties = ["current", "voltage", "cputemp", "hddtemp", "pmutemp", "cpu0freq",
"cpu1freq","txbytes","rxbytes","Free_RAM","Uptime","Users_logged_on","Load"];

var hosts = [];

var units = {"current": "[A]", "voltage": "[V]", "cputemp": "[°C]", "hddtemp" : "[°C]",
"pmutemp": "[°C]", "cpu0freq": "[MHz]","cpu1freq": "[MHz]","txbytes": "MB","rxbytes": "MB","Free_RAM": "MB","Uptime":"","Users_logged_on":"","Load":"[%]" };

var defaultValues = {
  properties: ["voltage", "current", "cputemp", "pmutemp", "hddtemp"]
};

var jsonData = {"x":[]};
var charts = {};
var dateRange = [];

var graphInformation = {}; // caches graph info before drawing
var charts = {}; // holds references to drawn charts
var progressbar;



function setupPropertySelection(){

  var propertyList = [];
  properties.forEach(function(property){
    propertyList.push({name: property});
  });

  var propertyNames = new Bloodhound({
      datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
      queryTokenizer: Bloodhound.tokenizers.whitespace,
      local: propertyList
    });
  propertyNames.initialize();

  $( "#property-selection input[type='text']" ).tagsinput({
    typeaheadjs: {
      name: 'propertynames',
      displayKey: 'name',
      valueKey: 'name',
      source: propertyNames.ttAdapter()
    }
  });

  $("#property-selection input[type='text']").on('beforeItemAdd', function(event) {
    var propertyName = event.item;
    if(properties.indexOf(propertyName) === -1){
      event.cancel = true; // prevent item from being added, when it is not in the properties-array
    }
  });

  $("#property-selection input[type='text']" ).eq(2).on('itemAdded', function(event) {
    var propertyName = event.item;
    if($("#p_" + propertyName).length){
      $("#p_" + propertyName).show();
    }
    else{
      $("#sortable").append('<li id="p_' + propertyName +'" class="ui-state-default">' +
      '<div class="paperLikeShadow"><p class="propertyTitle">' +  propertyName +" "+ units[propertyName] + '</p><div id="chart_' + propertyName +'"></div></div></li>');

      // setup sortable divs
      $( "#sortable" ).sortable();

      $("#chk_" + propertyName).prop('checked', true);
      $("#chk_" + propertyName).button( "refresh" );

      setupChart(propertyName);
    }
    $.notify({title: "<strong>" + propertyName + "</strong>", message: ": Graph added"},
      {
        placement: {from: "bottom", align: "right"},
        newest_on_top: true,
        animate: {
          enter: 'animated fadeInDown',
          exit: 'animated fadeOutUp'
        },
        type: 'success'
      });
  });

  $("#property-selection input[type='text']").eq(2).on('itemRemoved', function(event) {
    if($("#p_" + event.item).length){
      $("#p_" + event.item).hide();
      $("#chk_" + event.item).prop('checked', false);
      $("#chk_" + event.item).button( "refresh" );

      $.notify({title: "<strong>" + event.item + "</strong>", message: ": Graph removed"},
        {
          placement: {from: "bottom", align: "right"},
          newest_on_top: true,
          animate: {
            enter: 'animated fadeInDown',
            exit: 'animated fadeOutUp'
          },
          type: 'danger'
        });
    }
  });

  $("#property-selection div.bootstrap-tagsinput").first().append(
    '<button id="propertyBtn" class="tagsBtn"><i class="fa fa-cog" aria-hidden="true"></i></button>');

  $("#propertyBtn").button().on( "click", function() {
    propertyDialog.dialog( "open" );
  });

}

function setupPropertyDialog(){
  properties.forEach(function(property) {
    $("#dialog-properties form fieldset").append('<label for="chk_' + property +'">' + property +'</label>');
    $("#dialog-properties form fieldset").append('<input class="chkbox" id="chk_' + property +'" type="checkbox"' +
    'value="' + property +'">');
  });

  $( "#dialog-properties .chkbox" ).checkboxradio();

  $("#dialog-properties .chkbox").bind('change', function(){
    if($(this).is(':checked')){
      $("#property-selection input[type='text']").eq(2).tagsinput('add', $(this).attr('value'),{preventPost: true});
      console.log("adding tag" + $(this).attr('value'));
    }else{

      $("#property-selection input[type='text']").eq(2).tagsinput('remove', $(this).attr('value'));
    }
  });

  propertyDialog = $( "#dialog-properties" ).dialog({
    autoOpen: false,
    resizable: true,
    modal: false,
    height: 'auto',
    width:'500px'
  });
}

function setupHostSelection(){
  var hostList = [];
  hosts.forEach(function(property){
    hostList.push({name: property});
  });

  var hostNames = new Bloodhound({
      datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
      queryTokenizer: Bloodhound.tokenizers.whitespace,
      local: hostList
    });
  hostNames.initialize();

  $( "#host-selection input[type='text']" ).tagsinput({
    typeaheadjs: {
      name: 'hostNames',
      displayKey: 'name',
      valueKey: 'name',
      source: hostNames.ttAdapter()
    }
  });

  $("#host-selection input[type='text']").on('beforeItemAdd', function(event) {
    if(hosts.indexOf(event.item) === -1){
      event.cancel = true; // prevent item from being added, when it is not in the hosts-array
    }
  });

  $("#host-selection input[type='text']" ).eq(2).on('itemAdded', function(event) {
    var hostname = event.item;
    $("#chk_" + hostname).prop('checked', true);
    $("#chk_" + hostname).button( "refresh" );
    if(! jsonData.hasOwnProperty(hostname)){
      $.getJSON("history/" + hostname + "_hist.json").done(function(json){
        integrateJsonData(hostname, json);
      })
      .fail(function( jqxhr, textStatus, error ) {
        var err = textStatus + ", " + error;
        console.log( "Request Failed: " + err );
      });
    }else{
      // immediately update existing charts (data is there)
      for(var propertyName in charts) {
        charts[propertyName].show([hostname],{withLegend: true});
      }
    }
    console.log(hostname + " added");
  });

  $("#host-selection input[type='text']" ).eq(2).on('itemRemoved', function(event) {
    var hostname = event.item;
    $("#chk_" + hostname).prop('checked', false);
    $("#chk_" + hostname).button( "refresh" );

    // update existing charts
    for(var propertyName in charts) {
      charts[propertyName].hide([hostname],{withLegend: true});
    }
    console.log(hostname + " removed");
  });

  $("#host-selection div.bootstrap-tagsinput").first().append(
    '<button id="hostBtn" class="tagsBtn"><i class="fa fa-cog" aria-hidden="true"></i></button>');

  $("#hostBtn").button().on( "click", function() {
    hostDialog.dialog( "open" );
  });

}

function conformJsonValue(propertyName, value){
  switch(propertyName){
    case "voltage":
    case "current":
    return value / 1000000;
    case "cpu0freq":
    case "cpu1freq":
    return value / 1000;
    case "cputemp":
    case "pmutemp":
    return value.replace("°C","");
    case "txbytes":
    case "rxbytes":
    return value / 1000000;
    default:
    return value;
  }
}

function setupHostDialog(){
  hosts.forEach(function(host) {
    $("#dialog-host form fieldset").append('<label for="chk_' + host +'">' + host +'</label>');
    $("#dialog-host form fieldset").append('<input class="chkbox" id="chk_' + host +'" type="checkbox"' +
    'value="' + host +'">');
  });

  $( "#dialog-host .chkbox" ).checkboxradio();

  $("#dialog-host .chkbox").bind('change', function(){
    if($(this).is(':checked')){
      $("#host-selection input[type='text']").eq(2).tagsinput('add', $(this).attr('value'),{preventPost: true});
      console.log("adding tag" + $(this).attr('value'));
    }else{

      $("#host-selection input[type='text']").eq(2).tagsinput('remove', $(this).attr('value'));
    }
  });

  hostDialog = $( "#dialog-host" ).dialog({
    autoOpen: false,
    resizable: true,
    modal: false,
    height: 'auto',
    width:'500px'
  });
}

function setupChart(propertyName){
  columns = [['x'].concat(jsonData.x)];
  console.log("setting up chart for " + propertyName);
  $("#host-selection input[type='text']").eq(2).tagsinput('items').forEach(function(hostname){
    console.log("adding data from " + hostname);
    if(jsonData.hasOwnProperty(hostname)){
      columns.push([hostname].concat(jsonData[hostname][propertyName]));
    }
  });

  charts[propertyName] = c3.generate({
    bindto: '#chart_' + propertyName,
    data: {
      x: 'x',
      xFormat: '%a %b %d %H:%M:%S %Y',
      columns: columns
    },
    point: {
      show: false
    },
    transition: {
      duration: 0
    },
    interaction: {
      enabled: false
    },
    axis: {
      x: {
        type: 'timeseries',
        min: dateRange[0],
        max: dateRange[1],
        tick: {
          format: '%d.%m.%Y %H:%M:%S',
        }
      },
      y: {
        tick: {
          format: d3.format(",.2f")
        }
      }
    },
    grid: {
      x: {
        show: false
      },
      y: {
        show: true
      }
    },
    padding: {
      bottom: 30
    }
  });
}

function integrateJsonData(hostname, json){
  if(Object.keys(jsonData).length == 1){
    // adding first PI
    json.history.forEach(function(histEntry){
      //TODO: reliably filter out zone, or find appropriate format-string!
      jsonData.x.push(histEntry.date.replace("CEST ",""));
    });

    $("#datefrom").datepicker({
      minDate: new Date(jsonData.x[0]),
      maxDate:  new Date(jsonData.x[jsonData.x.length-1]),
      onSelect: function(date) {
        dateRange[0] = new Date(date);

        // if the user selected the first day on record, do not start chart
        // with 00:00, start instead with time of first entry (e.g. 09:00) (no leading "empty-space")
        var firstdate = new Date(jsonData.x[0]);
        if(dateRange[0].toDateString() == firstdate.toDateString()){
          dateRange[0] = firstdate;
        }

        // update existing charts
        for(var propertyName in charts) {
          charts[propertyName].axis.range({min: {x: dateRange[0]}});
        }
      }
    });
    $("#datefrom").datepicker('setDate', new Date(jsonData.x[0]));

    $("#dateto").datepicker({
      value: new Date(jsonData.x[jsonData.x.length-1]),
      minDate: new Date(jsonData.x[0]),
      maxDate:  new Date(jsonData.x[jsonData.x.length-1]),
      onSelect: function(date) {
        dateRange[1] = new Date(date);

        // if the user selected the last day on record, do not end chart
        // with 00:00, end instead with time of last entry (e.g. 09:00) (no trailing "empty-space")
        var lastdate = new Date(jsonData.x[jsonData.x.length-1]);
        if(dateRange[1].toDateString() == lastdate.toDateString()){
          dateRange[1] = lastdate;
        }

        // update existing charts
        for(var propertyName in charts) {
          charts[propertyName].axis.range({max:{x: dateRange[1]}});
        }
      }
    });
    $("#dateto").datepicker('setDate', new Date(jsonData.x[jsonData.x.length-1]));

  }

  var data = {};
  properties.forEach(function(property){
    data[property.split("_").join(" ")] = [];
  });

  json.history.forEach(function(histEntry){
    data.voltage.push(histEntry.voltage / 1000000);
    data.current.push(histEntry.current / 1000000);
    data.cpu0freq.push(histEntry.cpu0freq / 1000);
    data.cpu1freq.push(histEntry.cpu1freq / 1000);
    data.cputemp.push(histEntry.cputemp.replace("°C",""));
    data.pmutemp.push(histEntry.pmutemp.replace("°C",""));
    data.txbytes.push(histEntry.txbytes / 1000000);
    data.rxbytes.push(histEntry.rxbytes / 1000000);

    data.hddtemp.push(histEntry.hddtemp);
    data["Free RAM"].push(histEntry["Free RAM"]);
    data.Uptime.push(histEntry.Uptime);
    data["Users logged on"].push(histEntry["Users logged on"]);
    data.Load.push(histEntry.Load);
  });

  jsonData[hostname] = data;
  console.log(hostname + " integrated");
  // hosts.length+1 ... compensate x-property present in jsonData
  progressbar.progressbar( "value", (Object.keys(jsonData).length / (hosts.length+1))*100);
}

function getHostHistoryInformation(){
  // start displaying progress indicator
  progressbar.show();

  // for host in hosts, request history_file
  hosts.forEach(function(host){
    $("#host-selection input[type='text']").eq(2).tagsinput('add', host);
  });

  // progress is updated when a file has been downloaded and integrated
  // progress 100% -> hide progressbar and display default-charts
}

{'fraction_non_alphanumeric': 0.193739323878759, 'fraction_numerical': 0.010487427005124539, 'mean_word_length': 3.195666666666667, 'pattern_counts': {'":': 46, '<': 55, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2161414', 'n_tokens_mistral': 8156, 'n_tokens_neox': 7968, 'n_words': 1573}