luftikus143
luftikus143

Reputation: 1285

How to render Highcharts graph into user-selected DIV

I have multiple buttons, representing webservices in form of maps and Highcharts graphs, which the user can drag into one of several containers (DIVs) on the page, in which these webservices are then displayed.

It works fine for the map/image-webservices. But it is not clear to me how to make it possible with the Highcharts graphs. I guess I have to indicate somewhere a chart.renderTo("DIVx"), but not sure about that process.

I have setup a fiddle here. For the moment, the graph is being displayed in the DIV "container". But this should disappear, and once the user drags the button "Graph :: XXX" into one of the DIVs, the graph should display there.

The HTML part:

    <script src="https://code.highcharts.com/highcharts.js"></script>
    <script src="https://code.highcharts.com/modules/exporting.js"></script>

    <!-- this container should disappear -->
    <div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></div>

    <!-- buttons -->
    <div id="map_npp" draggable="true" ondragend="onDragEnd(event)" ondragstart="onDragStart(event)" style="float: left">
      <h4 style="float: left">Map :: NPP</h4>
    </div>
    <div id="map_precipitations" draggable="true" ondragend="onDragEnd(event)" ondragstart="onDragStart(event)" style="float: left">
      <h4 style="float: left">Map :: Precipitations</h4>
    </div>
    <div id="map_temperature" draggable="true" ondragend="onDragEnd(event)" ondragstart="onDragStart(event)" style="float: left">
      <h4 style="float: left">Map :: Temperature</h4>
    </div>
    <div id="graph_gdp" draggable="true" ondragend="onDragEnd(event)" ondragstart="onDragStart(event)" style="float: left">
      <h4 style="float: left">Graph :: GDP</h4>
    </div>
    <div id="graph_xxx" draggable="true" ondragend="onDragEnd(event)" ondragstart="onDragStart(event)" style="float: left">
      <h4 style="float: left">Graph :: XXX</h4>
    </div>

    <br clear="all" />

    <!-- dropzone DIVs -->
    <div id="dropzone1" class="static dropzone" ondrop="onDrop(event)" ondragover="onDragOver(event)" ondragleave="onDragLeave(event)"></div>
    <div id="dropzone2" class="static dropzone" ondrop="onDrop(event)" ondragover="onDragOver(event)" ondragleave="onDragLeave(event)"></div>
    <div id="dropzone3" class="static dropzone" ondrop="onDrop(event)" ondragover="onDragOver(event)" ondragleave="onDragLeave(event)"></div>
    <div id="dropzone4" class="static dropzone" ondrop="onDrop(event)" ondragover="onDragOver(event)" ondragleave="onDragLeave(event)"></div>

The javascript/jquery part for the graph:

    var csv = "2010/01/01,51.67074582499006,13.789093928493081,-0.0010074468085106377\n" +
      "2010/02/01,51.67074582499006,13.789093928493081,0.0024117021276595747\n" +
      "2010/03/01,51.67074582499006,13.789093928493081,0.026550000000000004\n" +
      "2010/04/01,51.67074582499006,13.789093928493081,0.08252659574468087\n" +
      "2010/05/01,51.67074582499006,13.789093928493081,0.12837446808510639\n" +
      "2010/06/01,51.67074582499006,13.789093928493081,0.140618085106383\n" +
      "2010/07/01,51.67074582499006,13.789093928493081,0.0668787234042553\n" +
      "2010/08/01,51.67074582499006,13.789093928493081,0.10335744680851064\n" +
      "2010/09/01,51.67074582499006,13.789093928493081,0.08095000000000001\n" +
      "2010/10/01,51.67074582499006,13.789093928493081,0.0400159574468085\n" +
      "2010/11/01,51.67074582499006,13.789093928493081,0.004214893617021277\n" +
      "2010/12/01,51.67074582499006,13.789093928493081,-0.0018680851063829788\n" +
      "2011/01/01,51.67074582499006,13.789093928493081,0.0011914893617021279\n" +
      "2011/02/01,51.67074582499006,13.789093928493081,0.003752127659574468\n" +
      "2011/03/01,51.67074582499006,13.789093928493081,0.027225531914893623"

    function extract(csv) {
      var rows = csv.split(/\r\n|\n/);
      var data;
      var series = [];
      var serie = {
        name: -1,
        data: []
      };
      for (var i = 0; i < rows.length; i++) {
        data = rows[i].split(',');
        if (serie.name === -1) {
          serie.name = data[0].substr(0, 4);
        } else {
          if (serie.name !== data[0].substr(0, 4)) {
            series.push(serie);
            serie = {
              name: data[0].substr(0, 4),
              data: []
            };
          }
        }
        serie.data.push(parseFloat(data[3]));
      }
      series.push(serie);
      return series;
    }

    $(function() {
      Highcharts.chart('container', {
        title: {
          text: 'Monthly Average Temperature',
          x: -20 //center
        },
        subtitle: {
          text: 'Source: WorldClimate.com',
          x: -20
        },
        xAxis: {
          categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
            'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
          ]
        },
        yAxis: {
          title: {
            text: 'Temperature (°C)'
          },
          plotLines: [{
            value: 0,
            width: 1,
            color: '#808080'
          }]
        },
        tooltip: {
          valueSuffix: '°C'
        },
        legend: {
          layout: 'vertical',
          align: 'right',
          verticalAlign: 'middle',
          borderWidth: 0
        },
        series: extract(csv),
      });
    });

The javascript/jquery part for the draggable buttons and target DIVs:

    //just to know which button is being dragged we will use this variable
    var draggingDiv;

    function onDragOver(e) {
      e.preventDefault();
      e.target.classList.add("over-me");
    }

    function onDragLeave(e) {
      e.target.classList.add("static");
      e.target.classList.remove("over-me");
    }

    function onDragStart(e) {
      draggingDiv = e.target;
      e.target.innerHTML = "<h4>You are Dragging me</h4>";
    }

    function onDragEnd(e) {

      e.target.innerHTML = "<h4>Drag Me into the Box :)</h4>";
      e.target.parentElement.classList.add("static");
      draggingDiv.innerHTML = "<h4>Dragged once Can't drag me now:)</h4>";
      // e.target.innerHTML = "<h4>You Dropped Me In "+e.target.parentElement.id+"</h4>"; 
    }

    function onDrop(e) {
      e.preventDefault();
      e.target.classList.remove("over-me");
      //uncommment the below line if want that the button should not be draggable once it has been dropped in a div already
      //draggingDiv.draggable=false;
      //e.target.appendChild(draggingDiv);/commented as this will take the button to the div but we want it to at the original pposition
      //e.target.innerHTML="<span>Please Change My innerHTML or call some function that loads data That handles the graph/map creation in this Div</span>";
      if (draggingDiv.id == "map_npp") {
        e.target.innerHTML = "<img style='margin-top: 0' src='http://npp.unepgrid.ch/images/wms_fake.png'>";
      } else if (draggingDiv.id == "map_precipitations") {
        e.target.innerHTML = "<img style='margin-top: 0' src='http://npp.unepgrid.ch/images/wms_fake.png'>";
      } else if (draggingDiv.id == "map_temperature") {
        e.target.innerHTML = "<img style='margin-top: 0' src='http://npp.unepgrid.ch/images/wms_fake.png'>";
      } else if (draggingDiv.id == "graph_gdp") {
        e.target.innerHTML = "<img style='margin-top: 0' src='http://npp.unepgrid.ch/images/wms_fake.png'>";
      } else if (draggingDiv.id == "graph_xxx") {
        e.target.innerHTML = "<img style='margin-top: 0' src='http://npp.unepgrid.ch/images/wms_fake.png'>";
      }
    }

Thanks for any hints how this could be implemented.

Upvotes: 0

Views: 490

Answers (1)

morganfree
morganfree

Reputation: 12472

You need to render the chart onDrop event. The container for the chart will be the target of that event. An element in which the chart will be rendered can be set via chart.renderTo property or as a parameter in the chart constructing function - see API.

The example can be found below. I also destroy the previous chart before a new one is created.

var chart;

function onDrop(e) {
  e.preventDefault();
  e.target.classList.remove("over-me");

  if (chart) {
    chart.destroy();
  }

  var options = {
    chart: {},
    series: [{
      data: [1,2,3,4,5]
    }]
  };

  if (draggingDiv.id == "map_npp") {
  } else if (draggingDiv.id == "map_precipitations") {
    options.chart.type = 'column';
  } else if (draggingDiv.id == "map_temperature") {
  } else if (draggingDiv.id == "graph_gdp") {
    options.series.data = [5,4,3,2,1];
  } else if (draggingDiv.id == "graph_xxx") {
    options.series.data = [5,4,3,2,1];
    options.chart.type = 'column';
  }

  chart = Highcharts.chart(e.target, options);
}

example: https://jsfiddle.net/1nye1zk7/

Upvotes: 1

Related Questions