Integrating with other Frameworks

Highcharts Cookbook


March 2014

$26.99

Javascript developers can add the most amazing charts to their web applications by using Highcharts and this step-by-step guide gives you the works with over 80 practical recipes. Unleash its potential.

(For more resources related to this topic, see here.)

Using NodeJS as a data provider

JavaScript has become a formidable language in its own right. Google's work on the V8 JavaScript engine has created something very performant, and has enabled others to develop Node.js, and with it, allow the development of JavaScript on the serverside. This article will take a look at how we can serve data using NodeJS, specifically using a framework known as express.

Getting ready

We will need to set up a simple project before we can get started:

  1. Download and install NodeJS (http://nodejs.org/download/).
  2. Create a folder nodejs for our project.
  3. Create a file nodejs/package.json and fill it with the following contents:

    {
    "name": "highcharts-cookbook-nodejs",
    "description": "An example application for using highcharts
    with nodejs",
    "version": "0.0.1",
    "private": true,
    "dependencies": {
    "express": "3.4.4"
    }
    }

  4. From within the nodejs folder, install our dependencies locally (that is, within the nodejs folder) using npm (NodeJS package manager):

    npm install

    If we wanted to install packages globally, we could have instead done the following:

    npm install -g

  5. Create a folder nodejs/static which will later contain our static assets (for example, a webpage and our JavaScript).
  6. Create a file nodejs/app.js which will later contain our express application and data provider.
  7. Create a file nodejs/bower.json to list our JavaScript dependencies for the page:

    {
    "name": "highcharts-cookbook-chapter-8",
    "dependencies": {
    "jquery": "^1.9",
    "highcharts": "~3.0"
    }
    }

  8. Create a file nodejs/.bowerrc to configure where our JavaScript dependencies will be installed:

    { "directory": "static/js" }

How to do it...

Let’s begin:

  1. Create an example file nodejs/static/index.html for viewing our charts

    <html> <head> </head> <body> <div id='example'></div> <script src = './js/jquery/jquery.js'></script> <script src = './js/highcharts/highcharts.js'></script> <script type = 'text/javascript'>
    $(document).ready(function() { var options = {
    chart: { type: 'bar', events: {
    load: function () { var self = this; setInterval(function() {
    $.getJSON('/ajax/series', function(data) { var series = self.series[0];
    series.setData(data); }); }, 1000); } } }, title: { text: 'Using AJAX for polling charts'
    }, series: [{ name: 'AJAX data (series)', data: [] }] }; $('#example').highcharts(options); }); </script> </body> </html>

  2. In nodejs/app.js, import the express framework:

    var express = require('express');

  3. Create a new express application:

    var app = express();

  4. Tell our application where to serve static files from:

    var app = express(); app.use(express.static('static'));

  5. Create a method to return data:

    app.use(express.static('static')); app.get('/ajax/series', function(request, response) { var count = 10, results = []; for(var i = 0; i < count; i++) { results.push({ "y": Math.random()*100 }); } response.json(results); });

  6. Listen on port 8888:

    response.json(results); }); app.listen(8888);

  7. Start our application:

    node app.js

  8. View the output on http://localhost:8888/index.html

How it works...

Most of what we've done in our application is fairly simple: create an express instance, create request methods, and listen on a certain port.

With express, we could also process different HTTP verbs like POST or DELETE. We can handle these methods by creating a new request method. In our example, we handled GET requests (that is, app.get) but in general, we can use app.VERB (Where VERB is an HTTP verb). In fact, we can also be more flexible in what our URLs look like: we can use JavaScript regular expressions as well. More information on the express API can be found at http://expressjs.com/api.html.

Using Django as a data provider

Django is likely one of the more robust python frameworks, and certainly one of the oldest. As such, Django can be used to tackle a variety of different cases, and has a lot of support and extensions available. This recipe will look at how we can leverage Django to provide data for Highcharts.

Getting ready

  1. Download and install Python 2.7 (http://www.python.org/getit/)
  2. Download and install Django (http://www.djangoproject.com/download/)
  3. Create a new folder for our project, django.
  4. From within the django folder, run the following to create a new project:

    django-admin.py startproject example

  5. Create a file django/bower.json to list our JavaScript dependencies

    { "name": "highcharts-cookbook-chapter-8", "dependencies": { "jquery": "^1.9", "highcharts": "~3.0" } }

  6. Create a file django/.bowerrc to configure where our JavaScript dependencies will be installed.

    { "directory": "example/static/js" }

  7. Create a folder example/templates for any templates we may have.

How to do it...

To get started, follow the instructions below:

  1. Create a folder example/templates, and include a file index.html as follows:

    {% load staticfiles %} <html> <head> </head> <body> <div class='example' id='example'></div> <script src = '{% static "js/jquery/jquery.js" %}'></script> <script src = '{% static "js/highcharts/highcharts.js" %}'></script> <script type='text/javascript'> $(document).ready(function() { var options = { chart: { type: 'bar', events: { load: function () { var self = this; setInterval(function() { $.getJSON('/ajax/series', function(data) { var series = self.series[0]; series.setData(data); }); }, 1000); } } }, title: { text: 'Using AJAX for polling charts' }, series: [{ name: 'AJAX data (series)', data: [] }] }; $('#example').highcharts(options); }); </script> </body> </html>

  2. Edit example/example/settings.py and include the following at the end of the file:

    STATIC_URL = '/static/' TEMPLATE_DIRS = ( os.path.join(BASE_DIR, 'templates/') ) STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static/'), )

  3. Create a file example/example/views.py and create a handler to show our page:

    from django.shortcuts import render_to_response def index(request): return render_to_response('index.html')

  4. Edit example/example/views.py and create a handler to serve our data:

    import json from random import randint from django.http import HttpResponse from django.shortcuts import render_to_response def index(request): return render_to_response('index.html') def series(request): results = [] for i in xrange(1, 11): results.append({ 'y': randint(0, 100) }) json_results = json.dumps(results) return HttpResponse(json_results, mimetype='application/json')

  5. Edit example/example/urls.py to register our URL handlers:

    from django.conf.urls import patterns, include, url from django.contrib import admin admin.autodiscover() import views urlpatterns = patterns('', # Examples: # url(r'^$', 'example.views.home', name='home'), # url(r'^blog/', include('blog.urls')), url(r'^admin/', include(admin.site.urls)), url(r'^/?$', views.index, name='index'), url(r'^ajax/series/?$', views.series, name='series'), )

  6. Run the following command from the django folder to start the server: python example/manage.py runserver
  7. Observe the page by visiting http://localhost:8000

Using Flask / Bottle as a data provider

Many different microframeworks have emerged to tackle small, specific problems that developers may have. In the Python world, there are two prominent examples: Flask, and Bottle. Flask and Bottle are very similar, and so in this recipe we examine how we can use either as a data provider for Highcharts.

Getting ready

First, we will need to setup Python:

  1. Download and install Python 2.7 (http://www.python.org/getit/)
  2. Download and install Flask (http://flask.pocoo.org)
  3. Download and install Bottle (http://bottlepy.org/)
  4. Create a folder flask_bottle for our project.
  5. Create a file flask_bottle/bower.json to list our JavaScript dependencies

    { "name": "highcharts-cookbook-chapter-8", "dependencies": { "jquery": "^1.9", "highcharts": "~3.0" } }

  6. Create a file flask_bottle/.bowerrc to configure where our JavaScript dependencies will be installed.

    { "directory": "static/js" }

How to do it...

To get started, follow the instructions below:

  1. Create a file static/index.html as follows:

    <html> <head> </head> <body> <div id='example'></div> <script src = './js/jquery/jquery.js'></script> <script src = './js/highcharts/highcharts.js'></script> <script type = 'text/javascript'> $(document).ready(function() { var options = { chart: { type: 'bar', events: { load: function () { var self = this; setInterval(function() { $.getJSON('/ajax/series', function(data) { var series = self.series[0]; series.setData(data); }); }, 1000); } } }, title: { text: 'Using AJAX for polling charts' }, series: [{ name: 'AJAX data (series)', data: [] }] }; $('#example').highcharts(options); }); </script> </body> </html>

  2. Create a file server.py and create a Flask instance:

    from flask import Flask app = Flask(__name__)

  3. Create a route to serve our data:

    from flask import Flask app = Flask(__name__) @app.route('/ajax/series') def series(): return None

  4. Return some data in our route:

    from flask import Flask, Response import json import random app = Flask(__name__) @app.route('/ajax/series') def series(): series = [] for x in xrange(0,11): series.append({ 'y': random.randint(0,100) }) return Response(json.dumps(series), mimetype='application/json')

  5. If the file is run as an executable, run our application in debug mode:

    from flask import Flask, Response import json import random app = Flask(__name__) @app.route('/ajax/series') def series(): series = [] for x in xrange(0,11): series.append({ 'y': random.randint(0, 100) }) return Response(json.dumps(series), mimetype='application/json') if __name__ == '__main__': app.run(debug=True)

  6. Start the server:

    python server.py

  7. Visit http://localhost:5000/static/index.html

How it works...

app.route is a decorator we can apply to python methods to handle HTTP requests. In addition to specifying the path, we can also specify which HTTP methods we want to handle (e.g. app.route('/path', methods=['GET']) to just handle GET requests).

Flask will automatically server files from the static folder at http://localhost:5000/static, which is why we did not need to add any special configuration to see index.html.

Integrating with Backbone

In addition to serverside microframeworks, a number of client-side microframeworks have also appeared. Many aim to provide a simple means to send data from end-to-end with a clear separation of concerns. In this recipe, we'll take a look at Backbone, specifically, integrating with its models (an abstraction of our interface with a backend) and collections (a means of managing multiple models).

Getting ready

We will need to make some small changes.

  1. Create a folder, backbone, for our project, and setup a basic project in that folder as described above.
  2. Modify backbone/bower.json as follows:

    { "name": "highcharts-cookbook-chapter-8", "dependencies": { "highcharts": "~3.0", "jquery": "^1.9", "underscore": "^1.5", // Used by Backbone, functional programming "backbone": "~1.1.0", // Model-view-controller library for JavaScript "backbone.localStorage": "~1.1.7"
    // Handles persistence using brower's localStorage
    } }

  3. Install our dependencies from within the backbone folder:

    bower install

How to do it...

To get started, follow the instructions below:

  1. Create our skeleton HTML file, backbone/index.html:

    <!doctype html> <html> <head> <script src = './bower_components/jquery/jquery.js'></script> <script src = './bower_components/highcharts/highcharts.src.js'></script> <script src = './bower_components/highcharts/
    highcharts-more.src.js'></script> <script src = './bower_components/underscore/underscore.js'></script> <script src = './bower_components/backbone/backbone.js'></script> <script src = './bower_components/backbone.localStorage/
    backbone.localStorage.js'></script> <script src = './example.js'></script> <style type='text/css'> #monsters { list-style: none; padding: 0px; } #monsters li { margin-bottom: 5px; } #monsters .card { clear: both; padding: 10px; border: 1px solid #aaa; } #monsters .card .graph { float: left; width: 300px; height: 300px; } #monsters .card .stats .row > label { display: inline-block; width: 100px; font-size: 1.0em; text-transform: capitalize; } #monsters .card .stats .row > input { width: 50px; padding: 5px; text-align: right; font-size: 1.2em; } </style> </head> <body> <div id='main'> <input id='monster-name' type='text' /> <input id='new-monster' type='button'
    value='Create New Monster' /> <ul id='monsters'> </ul> </div> </body> </html>

  2. Create a template for our model instances:

    <!doctype html> <html> <head> <!-- … --> </head> <body> <div id='main'> <!-- … --> </div> <script type='text/template' id='monster-template'> <div class='card'> <div class='graph' id='monster-<%= stats.name %>'> </div> <div class='stats'> <h2><%= stats.name %> <input class='feed'
    type='button' value='Feed Me!' /></h2> <% var keys = ['hp', 'attack', 'defense', 'special_attack',
    'special_defense', 'speed']; %> <% var key_stats = _.chain(stats).pick(keys).value(); %> <% _.each(key_stats , function(value, key) { %> <div class='row'> <label for='<%= key %>'><%= key %></label> <input type='text' name='<%= key %>' value='<%= value %>' /> </div> <% }); %> </div> </div> </script>
    </body> </html>

  3. Create a file backbone/example.js, and include an immediate function using jQuery:

    $(function() { });

  4. Define a Backbone model:

    $(function() { var Monster = Backbone.Model.extend({ defaults: { name: 'Unknown', height: 0.0, weight: 0.0, hp: 0, attack: 0, defense: 0, special_attack: 0, special_defense: 0, speed: 0 } }); });

  5. Define a Backbone collection:

    $(function() { //... var MonsterCollection = Backbone.Collection.extend({ model: Monster , localStorage: new Backbone.LocalStorage("example") }); });

  6. Create a MonsterCollection:

    $(function(){ // ... var MonsterCollection = Backbone.Collection.extend(/* … */); var Monsters = new MonsterCollection(); });

  7. Create a view for our Monster model. This will handle interaction with our model as well as make any changes to the UI for a model:

    $(function() { // ... var MonsterView = Backbone.View.extend({ tagName: 'li', template: _.template($('#monster-template').html()), initialize: function () { this.listenTo(this.model, 'change', this.render); }, render: function() { this.$el.html(this.template({ 'stats': this.model.toJSON() })); return this; } }); });

  8. Create a view for our application in general

    $(function() { // ... var AppView = Backbone.View.extend({ el: $('#main'), events: { 'click #new-monster': 'createMonster', 'keypress #monster-name': 'createMonster' }, initialize: function() { this.listenTo(Monsters, 'add', this.addMonster); }, createMonster: function(event) { var $name = $('#monster-name'); if (event.type === 'keypress' && event.keyCode !== 13) { return; } if (!$name.val()) { return; } Monsters.create({name: $name.val()}); $name.val(''); }, addMonster: function(monster) { var view = new MonsterView({model: monster}); this.$("#monsters").append(view.render().el); }, }); });

  9. Create an instance of our application view

    $(function() { // ... var App = new AppView(); });

  10. Modify MonsterView.render to render our highchart:

    var MonsterView = Backbone.View.extend({ // … chartOptions: { chart: { polar: true, type: 'line' }, legend: { enabled: false }, xAxis: { tickmarkPlacement: 'on', labels: { overflow: 'justify', style: { fontSize: '10px' } } }, yAxis: {gridLineInterpolation: 'polygon', min: 0}, tooltip: { pointFormat: '<span style="color:series.color}
    ">{series.name}: <b>{point.y:,.0f}</b><br/>' } }, render: function() { this.$el.html(this.template({ 'stats': this.model.toJSON() })); // get the key stats from the model var key_stats = this.model.pick([ 'hp', 'attack', 'defense', 'special_attack', 'special_defense', 'speed' ]); // turn those stats into a highcharts data series var series = _.chain(key_stats).map(function(value, key) { return parseInt(value, 10); }); // extend the default options var options = _.extend(this.chartOptions, { title: { text: this.model.get('name') }, xAxis: { categories: _.chain(key_stats).keys().value() }, series: [{ data: series.value() }] }); this.$('.graph').highcharts(options); return this; }, });

  11. Modify MonsterView to handle us changing the different stats:

    var MonsterView = Backbone.View.extend({ // ... events: { 'keyup .row input': 'statChange' }, statChange: function(event) { // figure out which element this is from var $target = this.$(event.target) // get the text value from the element var value = parseInt($target.val(), 10); var key = $target.attr('name'); if (!_.isNumber(value) || _.isNaN(value) || value < 0) { return; } // update the underlying model this.model.set(key, value); } });

How it works...

Our models and collections are fairly straightforward, especially as there is presently no backend interaction: we only store information in a local copy of our models. Our models only contain some simple information, a set of default values, and our collection only has one really interesting piece, the key model which defines what type of models this collection holds.

Most of the interesting work in our example comes from our two views. Backbone is able to handle events after we've defined either a template (as we did in our MonsterView) or an existing element with el (as we did in AppView). After that, we're able to register events via the events object using jQuery-like selectors of the form '<event> <selector>': 'function_name'.

Summary

In this article we looked at some of the more popular Web frameworks and tools and how we can get them up and running with Highcharts.

Resources for Article:


Further resources on this subject:


Books to Consider

comments powered by Disqus
X

An Introduction to 3D Printing

Explore the future of manufacturing and design  - read our guide to 3d printing for free