amCharts meets RequireJS

Many modern websites rely heavily on JavaScript. Each one has at least several home-cooked and 3rd party libraries. With the number of them growing, it becomes increasingly difficult to manage all of them, especially if you want to make sure to minimize traffic overhead by loading only what's absolutely necessary for the particular page.

That's where libraries like RequireJS come into play.

It helps reducing the initial load of the web page by implementing asynchronous loading of JavaScript files, as well as manages dependencies for you.

If you're not familiar with RequireJS, we suggest you go through their get started article first. If you're already up to speed, read on.

This tutorial focuses on how you can use RequireJS to load amCharts libraries.

Download RequireJS

Before you can do anything with RequireJS, you will need to download it and install on your web server.

Alternatively, you can use one of the many CDN mirrors, to load RequireJS files.

Scaffolding

We are using almost the same scaffolding as in their tutorial, so for that please create something like as below:

  • project-directory/
    • project.html
    • scripts/
      • main.js
      • require.js
      • amcharts/
        • amcharts.js
        • pie.js
        • ...

Less HTML code

There is not that much HTML code to write here - just ensure we have the require.js API and our chart container in the project.html file.

<!DOCTYPE html>
<html>
    <head>
        <title>requireJS | amCharts.com</title>
        <script data-main="scripts/main" src="scripts/require.js"></script>
    </head>
    <body>
        <div id="chartdiv" style="width: 600px; height: 400px;"></div>
    </body>
</html>

RequireJS reads its data-main attribute and loads our main.js file, which gets filled up in the next step.

Config

RequireJS needs to know where amCharts is located. To do so, copy following code into main.js

// SETUP CONFIG
requirejs.config( {

  // Define paths; relative from js folder
  "paths": {
    "amcharts": "//www.amcharts.com/lib/3/amcharts",
    "amcharts.funnel": "//www.amcharts.com/lib/3/funnel",
    "amcharts.gauge": "//www.amcharts.com/lib/3/gauge",
    "amcharts.pie": "//www.amcharts.com/lib/3/pie",
    "amcharts.radar": "//www.amcharts.com/lib/3/radar",
    "amcharts.serial": "//www.amcharts.com/lib/3/serial",
    "amcharts.xy": "//www.amcharts.com/lib/3/xy"
  },

  // Define dependencies
  "shim": {
    "amcharts.funnel": {
      "deps": [ "amcharts" ],
      "exports": "AmCharts",
      "init": function() {
        AmCharts.isReady = true;
      }
    },
    "amcharts.gauge": {
      "deps": [ "amcharts" ],
      "exports": "AmCharts",
      "init": function() {
        AmCharts.isReady = true;
      }
    },
    "amcharts.pie": {
      "deps": [ "amcharts" ],
      "exports": "AmCharts",
      "init": function() {
        AmCharts.isReady = true;
      }
    },
    "amcharts.radar": {
      "deps": [ "amcharts" ],
      "exports": "AmCharts",
      "init": function() {
        AmCharts.isReady = true;
      }
    },
    "amcharts.serial": {
      "deps": [ "amcharts" ],
      "exports": "AmCharts",
      "init": function() {
        AmCharts.isReady = true;
      }
    },
    "amcharts.xy": {
      "deps": [ "amcharts" ],
      "exports": "AmCharts",
      "init": function() {
        AmCharts.isReady = true;
      }
    }
  }
} );

The paths defines the module names with its source location, requireJS adds automatically the ".js" extension.

The shim contains the requirements for the modules and exports the AmCharts variable to the RequireJS modules, since it's loaded we need to set AmCharts.isReady manually because the framework has been loaded asynchronously otherwise the framework will wait for the "onload" event.

The fun part

So now RequireJS knows where the files are and what to do when they are ready. Now we can create the actual worker modules, simply copy following code after the config:

// LOAD DEPENDENCIES; CREATE CHART
require( [ "amcharts.pie" ], function( amRef ) {
  var chart = amRef.makeChart( "chartdiv", {
    "type": "pie",
    "dataProvider": [ {
      "country": "Lithuania",
      "litres": 501.9
    }, {
      "country": "Czech Republic",
      "litres": 301.9
    }, {
      "country": "Ireland",
      "litres": 201.1
    }, {
      "country": "Germany",
      "litres": 165.8
    }, {
      "country": "Australia",
      "litres": 139.9
    }, {
      "country": "Austria",
      "litres": 128.3
    }, {
      "country": "UK",
      "litres": 99
    }, {
      "country": "Belgium",
      "litres": 60
    }, {
      "country": "The Netherlands",
      "litres": 50
    } ],
    "valueField": "litres",
    "titleField": "country"
  } );

  // ERROR HANDLER
}, function( err ) {
  console.log( "Something went wront: ", err );
} );

Before RequireJS loads our pie.js class, it will load its dependencies that we've defined in the config above within the shim parameter. Since pie.js is ready with all it's requirements it will call our passed callback with a reference of AmCharts to build the chart (we used our Simple Pie Chart from our demos).

Here's a working demo of the above:

See the Pen RequireJS demo by amCharts (@amcharts) on CodePen.light

What about plugins?

Our plugins have the same dependency as the chart types, the core itself amcharts.js. You just need to append the plugins to your paths, add the shim and your plugin is ready to get opt-in.

// SETUP CONFIG
requirejs.config( {

 // Define paths; relative from js folder
 paths: {
 //...
 'amcharts.plugins.responsive': '//www.amcharts.com/lib/3/plugins/responsive',
 'amcharts.plugins.dataloader': '//www.amcharts.com/lib/3/plugins/dataloader'
 },

 // Define dependencies
 shim: {
 // ...
 'amcharts.plugins.responsive': {
 deps: [ 'amcharts' ]
 },
 'amcharts.plugins.dataloader': {
 deps: [ 'amcharts' ]
 }
} );

Handling Export plugin

Export plugin is a bit more complicated, because it relies on a number of external libraries, that it tries do load dynamically, which might seriously mess up your Require setup.

To fix that, you will need to add all those dependencies to the RequireJS setup. Furthermore, we need to ensure that correct hierarchy of dependencies is maintained. I.e. Export plugin relies on amcharts.js being loaded. pdfmake library needs to be loaded only when export.min.js was loaded. While pdfFonts.js needs pdfmake to be there when it loads.

This all leads to a rather more complicated path and dependency setup:

requirejs.config( {
  "paths": {
    "amcharts": "https://www.amcharts.com/lib/3/amcharts",
    "amcharts.serial": "https://www.amcharts.com/lib/3/serial",
    "amcharts.theme.light": "https://www.amcharts.com/lib/3/themes/light",
    "amcharts.export": "https://www.amcharts.com/lib/3/plugins/export/export.min",
    "amcharts.plugins.export.libs.blob": "https://www.amcharts.com/lib/3/plugins/export/libs/blob.js/blob",
    "amcharts.plugins.export.libs.fabric": "https://www.amcharts.com/lib/3/plugins/export/libs/fabric.js/fabric",
    "amcharts.plugins.export.libs.fileSaver": "https://www.amcharts.com/lib/3/plugins/export/libs/FileSaver.js/FileSaver",
    "amcharts.plugins.export.libs.jszip": "https://www.amcharts.com/lib/3/plugins/export/libs/jszip/jszip",
    "amcharts.plugins.export.libs.pdfmake": "https://www.amcharts.com/lib/3/plugins/export/libs/pdfmake/pdfmake",
    "amcharts.plugins.export.libs.pdfFonts": "https://www.amcharts.com/lib/3/plugins/export/libs/pdfmake/vfs_fonts",
    "amcharts.plugins.export.libs.xlsx": "https://www.amcharts.com/lib/3/plugins/export/libs/xlsx/xlsx"
  },
  "shim": {
    "amcharts.serial": {
      "deps": [ "amcharts" ],
      "exports": "AmCharts",
      "init": function() {
        AmCharts.isReady = true;
      }
    },
    "amcharts.theme.light": {
      "deps": [ "amcharts" ],
      "exports": "AmCharts",
      "init": function() {
        AmCharts.isReady = true;
      }
    },
    "amcharts.plugins.export.libs.pdfFonts": {
      "deps": [ "amcharts.plugins.export.libs.pdfmake" ]
    },
    "amcharts.export": {
      "deps": [ "amcharts", "amcharts.plugins.export.libs.blob", "amcharts.plugins.export.libs.fabric", "amcharts.plugins.export.libs.fileSaver", "amcharts.plugins.export.libs.jszip", "amcharts.plugins.export.libs.pdfmake", "amcharts.plugins.export.libs.pdfFonts", "amcharts.plugins.export.libs.xlsx" ],
      "exports": "AmCharts",
      "init": function() {
        AmCharts.isReady = true;

        // CSS exception; load once it's ready
        var link = document.createElement( "link" );
        link.type = "text/css";
        link.rel = "stylesheet";
        link.href = "https://www.amcharts.com/lib/3/plugins/export/export.css";
        document.getElementsByTagName( "head" )[ 0 ].appendChild( link );
      }
    }
  }
} );

IMPORTANT! You will also need to disable the automatic loading of libraries by the Export plugin:

"export": {
  "enabled": true,
    "libs": {
      "autoLoad": false
   }
}

You may also need to separately require the jszip library before creating the chart:

require(['amcharts.plugins.export.libs.jszip'], function(jszip) {
    window.JSZip = jszip;
});

Here's a demo that shows all of this in action:

See the Pen Using RequireJS with amCharts (with export) by amCharts (@amcharts) on CodePen.light