Listening to Events

Listening to events is a two-part process. The first is creating a listener function and second is attaching this function to one of the events raised by a chart.

The listener function

A listener function is a JavaScript function that optionally accepts two arguments eventObj and eventArgs. These two arguments receive information specific to the event to which the listener is attached.

var myEventListener = function (eventObj, eventArgs) {
   console.log(eventObj.eventType +
       " was raised by the chart whose ID is " +
       eventObj.sender.id);
};

The above snippet of code defines a listener function which uses the eventObj argument to extract and log the name of the event and the Id of the chart. To know more about the parameters passed to the event listeners, read the API reference FusionCharts~eventListener.

This listener function would not perform the work unless it is "attached" to an event. We would use the first chart we created and attach this listener to the renderComplete event of the chart. This is achieved using the FusionCharts#addEventListener function available on every instance of chart. It is added right before we call the chart to render.

revenueChart.addEventListener("renderComplete", myEventListener);

The final chart HTML would look like what we see next. You may open up your JavaScript console and expect to see a line renderComplete event was raised by the chart whose ID is chartobject-1.

FusionCharts should load here..

<html>
<head>
   <title>My first chart using FusionCharts Suite XT</title>
   <script type="text/javascript" src="fusioncharts/fusioncharts.js"></script>
   <script type="text/javascript" src="fusioncharts/themes/fusioncharts.theme.fint.js"></script>
   <script type="text/javascript">
   FusionCharts.ready(function() {
       var revenueChart,
           myEventListener;

       revenueChart = new FusionCharts({
          type: 'column2d',
           renderAt: 'chart-container',
           width: '500',
           height: '300',
           dataFormat: 'json',
           dataSource: {
               "chart": {
                   "caption": "Monthly revenue for last year",
                   "subCaption": "Harry's SuperMart",
                   "xAxisName": "Month",
                   "yAxisName": "Revenues (In USD)",
                   "numberPrefix": "$",
                   "theme": "fint"
               },
               "data": [{
                   "label": "Jan",
                   "value": "420000"
               }, {
                   "label": "Feb",
                   "value": "810000"
               }, {
                   "label": "Mar",
                   "value": "720000"
               }, {
                   "label": "Apr",
                   "value": "550000"
               }, {
                   "label": "May",
                   "value": "910000"
               }, {
                   "label": "Jun",
                   "value": "510000"
               }, {
                   "label": "Jul",
                   "value": "680000"
               }, {
                   "label": "Aug",
                   "value": "620000"
               }, {
                   "label": "Sep",
                   "value": "610000"
               }, {
                   "label": "Oct",
                   "value": "490000"
               }, {
                   "label": "Nov",
                   "value": "900000"
               }, {
                   "label": "Dec",
                   "value": "730000"
               }]
           }
       });
       // We create the event listener
       myEventListener = function(eventObj, eventArgs) {
           console.log(eventObj.eventType +
               " was raised by the chart whose ID is " +
               eventObj.sender.id);
       };

       // Attach the event listener to the renderComplete event of the chart.
       revenueChart.addEventListener("renderComplete", myEventListener);

       // Render the chart
       revenueChart.render();
   });
   </script>
</head>
<body>
   <div id="chartContainer">FusionCharts XT will load here!</div>
</body>
</html>

Embed the listener function inside the event listener

In our previous example, we had separately defined the listener function as myEventListener variable. This is not needed if you do not intend to use the listener function for anything else. As such, the code can be rewritten to create listener and attach it at one go.

revenueChart.addEventListener("renderComplete", function (eventObj) {
   console.log(eventObj.eventType +
       " was raised by the chart whose ID is " +
       eventObj.sender.id);
};

Listening to events on all charts

Events can also be attached to the window.FusionCharts object. Attaching event to this FusionCharts constructor causes the event listener to be attached to all charts on a page that are already created or will be created later.

To demonstrate this, we would again take up the first chart we created using FusionCharts and add a global event listener to check when a chart has been initialised.

FusionCharts.addEventListener("initialized", function(eventObj, eventArgs) {
   console.log(eventObj.eventType +
       " was raised by the chart whose ID is " +
       eventObj.sender.id);
});

When this code is added as the first few lines within FusionCharts.ready we get to see a JavaScript console log for every chart that fires the initialised event.

FusionCharts should load here..

Listening to multiple events at once

On a number of occasion, we might want to listen to multiple events raised by a chart using a single listener. We would end up writing something like

var myEventListener = function (eventObj, eventArgs) {
   console.log(eventObj.eventType +
       " was raised by the chart whose ID is " +
       eventObj.sender.id);
};

myChart.addEventListener("initialized", myEventListener);
myChart.addEventListener("dataUpdated", myEventListener);
myChart.addEventListener("renderComplete", myEventListener);
myChart.addEventListener("disposed", myEventListener);

The above code logs the major events that might happen on a chart (in our case myChart) through its entire lifecycle. The last four lines of repeated event attachment can be reduced to a single line where event names are passed as array to the addEventListener function. We can also get rid of the myEventListener variable and pass the listener directly as an anonymous function.

myChart.addEventListener(["initialized",
   "dataUpdated",
   "renderComplete",
   "disposed"], function (eventObj, eventArgs) {
   console.log(eventObj.eventType +
       " was raised by the chart whose ID is " +
       eventObj.sender.id);
});

Listening to event once

There can be instances where you need to listen to an event once and then forget about it. In such cases, the detachHandler function passed inside the eventObj parameter of the listener comes handy.

myChart.addEventListener("dataUpdated", function (eventObj) {
   console.log("Data was updated for the first time in chart");
   // Call detachHandler to stop listening to this event
   eventObj.detachHandler();
});

The above code executes the listener when dataUpdated event is fired on myChart and then detaches itself. The next time dataUpdated event is fired, on the same chart, this listener will no longer be called.

Passing event listeners during chart creation / construction

FusionCharts also provides a unified way to pass all event listeners to a chart while creating the chart itself. This is done by passing all events within an object through the events constructor parameter.

For example , we can use event listeners to create a button that, when clicked, exports the chart. This can be achieved by creating a button before the chart is rendered and then activating the button when the chart is completely rendered.

The following piece of code can be passed as the events parameter to the constructor.

events: {
   "beforeRender": function(eventObj, eventArgs) {
       var container = eventArgs.container, // access container
           // create a button
           exportButton = document.createElement("input");
       exportButton.setAttribute("type", "button");
       exportButton.setAttribute("value", "Export Chart");
       // set an id to the button for a lookup later
       exportButton.setAttribute("id", eventObj.sender.id + "-export-button");
       // disable the button
       exportButton.setAttribute("disabled", "disabled");
       // add button after chart
       container.parentNode.insertBefore(exportButton,
           container.nextSibling);
   },
   "renderComplete": function(eventObj) {
       var exportButton = document.getElementById(eventObj.sender.id + "-export-button");
       // enable the button
       exportButton.removeAttribute("disabled");
       // call export on chart when button is clicked
       exportButton.onclick = function() {
           eventObj.sender.exportChart();
       };
   }
}

The result would be

FusionCharts should load here..

...

The beforeInitialize event for a chart can be listened either via global event listeners or when passed as a constructor parameter. Using the addEventListener method on a chart instance, this event cannot be intercepted since by the time this event is attached a chart has already been initialized.

Removing and cancelling event listeners

We remove an attached event listener by calling the FusionCharts#removeEventListener function on a chart. Removing unnecessary event listeners ensure we do not needlessly increase memory consumed by charts on a page.

Event listeners attached globally on all charts can be removed by calling the removeEventListener on FusionCharts object.

It is always a good practice to remove all event listeners of a chart before the chart is destroyed or removed from the page.

Cancelling an event

Events are cancelled using eventObj.preventDefault() function. This is achieved by attaching an event listener to the event and using preventDefault function of the event.

For example, if you call eventObj.preventDefault() inside the beforeRender event listener of a chart, the chart will not render.