<!DOCTYPE HTML>
							 | 
						|
								<html>
							 | 
						|
									<head>
							 | 
						|
										<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
							 | 
						|
										<title>Highcharts Example</title>
							 | 
						|
								
							 | 
						|
										<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
							 | 
						|
										<style type="text/css">
							 | 
						|
								${demo.css}
							 | 
						|
										</style>
							 | 
						|
										<script type="text/javascript">
							 | 
						|
								/**
							 | 
						|
								 * This is a complex demo of how to set up a Highcharts chart, coupled to a
							 | 
						|
								 * dynamic source and extended by drawing image sprites, wind arrow paths
							 | 
						|
								 * and a second grid on top of the chart. The purpose of the demo is to inpire
							 | 
						|
								 * developers to go beyond the basic chart types and show how the library can
							 | 
						|
								 * be extended programmatically. This is what the demo does:
							 | 
						|
								 *
							 | 
						|
								 * - Loads weather forecast from www.yr.no in form of an XML service. The XML
							 | 
						|
								 *   is translated on the Higcharts website into JSONP for the sake of the demo
							 | 
						|
								 *   being shown on both our website and JSFiddle.
							 | 
						|
								 * - When the data arrives async, a Meteogram instance is created. We have
							 | 
						|
								 *   created the Meteogram prototype to provide an organized structure of the different
							 | 
						|
								 *   methods and subroutines associated with the demo.
							 | 
						|
								 * - The parseYrData method parses the data from www.yr.no into several parallel arrays. These
							 | 
						|
								 *   arrays are used directly as the data option for temperature, precipitation
							 | 
						|
								 *   and air pressure. As the temperature data gives only full degrees, we apply
							 | 
						|
								 *   some smoothing on the graph, but keep the original data in the tooltip.
							 | 
						|
								 * - After this, the options structure is build, and the chart generated with the
							 | 
						|
								 *   parsed data.
							 | 
						|
								 * - In the callback (on chart load), we weather icons on top of the temperature series.
							 | 
						|
								 *   The icons are sprites from a single PNG image, placed inside a clipped 30x30
							 | 
						|
								 *   SVG <g> element. VML interprets this as HTML images inside a clipped div.
							 | 
						|
								 * - Lastly, the wind arrows are built and added below the plot area, and a grid is
							 | 
						|
								 *   drawn around them. The wind arrows are basically drawn north-south, then rotated
							 | 
						|
								 *   as per the wind direction.
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								function Meteogram(xml, container) {
							 | 
						|
								    // Parallel arrays for the chart data, these are populated as the XML/JSON file
							 | 
						|
								    // is loaded
							 | 
						|
								    this.symbols = [];
							 | 
						|
								    this.symbolNames = [];
							 | 
						|
								    this.precipitations = [];
							 | 
						|
								    this.windDirections = [];
							 | 
						|
								    this.windDirectionNames = [];
							 | 
						|
								    this.windSpeeds = [];
							 | 
						|
								    this.windSpeedNames = [];
							 | 
						|
								    this.temperatures = [];
							 | 
						|
								    this.pressures = [];
							 | 
						|
								
							 | 
						|
								    // Initialize
							 | 
						|
								    this.xml = xml;
							 | 
						|
								    this.container = container;
							 | 
						|
								
							 | 
						|
								    // Run
							 | 
						|
								    this.parseYrData();
							 | 
						|
								}
							 | 
						|
								/**
							 | 
						|
								 * Return weather symbol sprites as laid out at http://om.yr.no/forklaring/symbol/
							 | 
						|
								 */
							 | 
						|
								Meteogram.prototype.getSymbolSprites = function (symbolSize) {
							 | 
						|
								    return {
							 | 
						|
								        '01d': {
							 | 
						|
								            x: 0,
							 | 
						|
								            y: 0
							 | 
						|
								        },
							 | 
						|
								        '01n': {
							 | 
						|
								            x: symbolSize,
							 | 
						|
								            y: 0
							 | 
						|
								        },
							 | 
						|
								        '16': {
							 | 
						|
								            x: 2 * symbolSize,
							 | 
						|
								            y: 0
							 | 
						|
								        },
							 | 
						|
								        '02d': {
							 | 
						|
								            x: 0,
							 | 
						|
								            y: symbolSize
							 | 
						|
								        },
							 | 
						|
								        '02n': {
							 | 
						|
								            x: symbolSize,
							 | 
						|
								            y: symbolSize
							 | 
						|
								        },
							 | 
						|
								        '03d': {
							 | 
						|
								            x: 0,
							 | 
						|
								            y: 2 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '03n': {
							 | 
						|
								            x: symbolSize,
							 | 
						|
								            y: 2 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '17': {
							 | 
						|
								            x: 2 * symbolSize,
							 | 
						|
								            y: 2 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '04': {
							 | 
						|
								            x: 0,
							 | 
						|
								            y: 3 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '05d': {
							 | 
						|
								            x: 0,
							 | 
						|
								            y: 4 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '05n': {
							 | 
						|
								            x: symbolSize,
							 | 
						|
								            y: 4 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '18': {
							 | 
						|
								            x: 2 * symbolSize,
							 | 
						|
								            y: 4 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '06d': {
							 | 
						|
								            x: 0,
							 | 
						|
								            y: 5 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '06n': {
							 | 
						|
								            x: symbolSize,
							 | 
						|
								            y: 5 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '07d': {
							 | 
						|
								            x: 0,
							 | 
						|
								            y: 6 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '07n': {
							 | 
						|
								            x: symbolSize,
							 | 
						|
								            y: 6 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '08d': {
							 | 
						|
								            x: 0,
							 | 
						|
								            y: 7 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '08n': {
							 | 
						|
								            x: symbolSize,
							 | 
						|
								            y: 7 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '19': {
							 | 
						|
								            x: 2 * symbolSize,
							 | 
						|
								            y: 7 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '09': {
							 | 
						|
								            x: 0,
							 | 
						|
								            y: 8 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '10': {
							 | 
						|
								            x: 0,
							 | 
						|
								            y: 9 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '11': {
							 | 
						|
								            x: 0,
							 | 
						|
								            y: 10 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '12': {
							 | 
						|
								            x: 0,
							 | 
						|
								            y: 11 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '13': {
							 | 
						|
								            x: 0,
							 | 
						|
								            y: 12 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '14': {
							 | 
						|
								            x: 0,
							 | 
						|
								            y: 13 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '15': {
							 | 
						|
								            x: 0,
							 | 
						|
								            y: 14 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '20d': {
							 | 
						|
								            x: 0,
							 | 
						|
								            y: 15 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '20n': {
							 | 
						|
								            x: symbolSize,
							 | 
						|
								            y: 15 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '20m': {
							 | 
						|
								            x: 2 * symbolSize,
							 | 
						|
								            y: 15 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '21d': {
							 | 
						|
								            x: 0,
							 | 
						|
								            y: 16 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '21n': {
							 | 
						|
								            x: symbolSize,
							 | 
						|
								            y: 16 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '21m': {
							 | 
						|
								            x: 2 * symbolSize,
							 | 
						|
								            y: 16 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '22': {
							 | 
						|
								            x: 0,
							 | 
						|
								            y: 17 * symbolSize
							 | 
						|
								        },
							 | 
						|
								        '23': {
							 | 
						|
								            x: 0,
							 | 
						|
								            y: 18 * symbolSize
							 | 
						|
								        }
							 | 
						|
								    };
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Function to smooth the temperature line. The original data provides only whole degrees,
							 | 
						|
								 * which makes the line graph look jagged. So we apply a running mean on it, but preserve
							 | 
						|
								 * the unaltered value in the tooltip.
							 | 
						|
								 */
							 | 
						|
								Meteogram.prototype.smoothLine = function (data) {
							 | 
						|
								    var i = data.length,
							 | 
						|
								        sum,
							 | 
						|
								        value;
							 | 
						|
								
							 | 
						|
								    while (i--) {
							 | 
						|
								        data[i].value = value = data[i].y; // preserve value for tooltip
							 | 
						|
								
							 | 
						|
								        // Set the smoothed value to the average of the closest points, but don't allow
							 | 
						|
								        // it to differ more than 0.5 degrees from the given value
							 | 
						|
								        sum = (data[i - 1] || data[i]).y + value + (data[i + 1] || data[i]).y;
							 | 
						|
								        data[i].y = Math.max(value - 0.5, Math.min(sum / 3, value + 0.5));
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Callback function that is called from Highcharts on hovering each point and returns
							 | 
						|
								 * HTML for the tooltip.
							 | 
						|
								 */
							 | 
						|
								Meteogram.prototype.tooltipFormatter = function (tooltip) {
							 | 
						|
								
							 | 
						|
								    // Create the header with reference to the time interval
							 | 
						|
								    var index = tooltip.points[0].point.index,
							 | 
						|
								        ret = '<small>' + Highcharts.dateFormat('%A, %b %e, %H:%M', tooltip.x) + '-' +
							 | 
						|
								            Highcharts.dateFormat('%H:%M', tooltip.points[0].point.to) + '</small><br>';
							 | 
						|
								
							 | 
						|
								    // Symbol text
							 | 
						|
								    ret += '<b>' + this.symbolNames[index] + '</b>';
							 | 
						|
								
							 | 
						|
								    ret += '<table>';
							 | 
						|
								
							 | 
						|
								    // Add all series
							 | 
						|
								    Highcharts.each(tooltip.points, function (point) {
							 | 
						|
								        var series = point.series;
							 | 
						|
								        ret += '<tr><td><span style="color:' + series.color + '">\u25CF</span> ' + series.name +
							 | 
						|
								            ': </td><td style="white-space:nowrap">' + Highcharts.pick(point.point.value, point.y) +
							 | 
						|
								            series.options.tooltip.valueSuffix + '</td></tr>';
							 | 
						|
								    });
							 | 
						|
								
							 | 
						|
								    // Add wind
							 | 
						|
								    ret += '<tr><td style="vertical-align: top">\u25CF Wind</td><td style="white-space:nowrap">' + this.windDirectionNames[index] +
							 | 
						|
								        '<br>' + this.windSpeedNames[index] + ' (' +
							 | 
						|
								        Highcharts.numberFormat(this.windSpeeds[index], 1) + ' m/s)</td></tr>';
							 | 
						|
								
							 | 
						|
								    // Close
							 | 
						|
								    ret += '</table>';
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								    return ret;
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Draw the weather symbols on top of the temperature series. The symbols are sprites of a single
							 | 
						|
								 * file, defined in the getSymbolSprites function above.
							 | 
						|
								 */
							 | 
						|
								Meteogram.prototype.drawWeatherSymbols = function (chart) {
							 | 
						|
								    var meteogram = this,
							 | 
						|
								        symbolSprites = this.getSymbolSprites(30);
							 | 
						|
								
							 | 
						|
								    $.each(chart.series[0].data, function (i, point) {
							 | 
						|
								        var sprite,
							 | 
						|
								            group;
							 | 
						|
								
							 | 
						|
								        if (meteogram.resolution > 36e5 || i % 2 === 0) {
							 | 
						|
								
							 | 
						|
								            sprite = symbolSprites[meteogram.symbols[i]];
							 | 
						|
								            if (sprite) {
							 | 
						|
								
							 | 
						|
								                // Create a group element that is positioned and clipped at 30 pixels width and height
							 | 
						|
								                group = chart.renderer.g()
							 | 
						|
								                    .attr({
							 | 
						|
								                        translateX: point.plotX + chart.plotLeft - 15,
							 | 
						|
								                        translateY: point.plotY + chart.plotTop - 30,
							 | 
						|
								                        zIndex: 5
							 | 
						|
								                    })
							 | 
						|
								                    .clip(chart.renderer.clipRect(0, 0, 30, 30))
							 | 
						|
								                    .add();
							 | 
						|
								
							 | 
						|
								                // Position the image inside it at the sprite position
							 | 
						|
								                chart.renderer.image(
							 | 
						|
								                    'http://www.highcharts.com/samples/graphics/meteogram-symbols-30px.png',
							 | 
						|
								                    -sprite.x,
							 | 
						|
								                    -sprite.y,
							 | 
						|
								                    90,
							 | 
						|
								                    570
							 | 
						|
								                )
							 | 
						|
								                    .add(group);
							 | 
						|
								            }
							 | 
						|
								        }
							 | 
						|
								    });
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Create wind speed symbols for the Beaufort wind scale. The symbols are rotated
							 | 
						|
								 * around the zero centerpoint.
							 | 
						|
								 */
							 | 
						|
								Meteogram.prototype.windArrow = function (name) {
							 | 
						|
								    var level,
							 | 
						|
								        path;
							 | 
						|
								
							 | 
						|
								    // The stem and the arrow head
							 | 
						|
								    path = [
							 | 
						|
								        'M', 0, 7, // base of arrow
							 | 
						|
								        'L', -1.5, 7,
							 | 
						|
								        0, 10,
							 | 
						|
								        1.5, 7,
							 | 
						|
								        0, 7,
							 | 
						|
								        0, -10 // top
							 | 
						|
								    ];
							 | 
						|
								
							 | 
						|
								    level = $.inArray(name, ['Calm', 'Light air', 'Light breeze', 'Gentle breeze', 'Moderate breeze',
							 | 
						|
								        'Fresh breeze', 'Strong breeze', 'Near gale', 'Gale', 'Strong gale', 'Storm',
							 | 
						|
								        'Violent storm', 'Hurricane']);
							 | 
						|
								
							 | 
						|
								    if (level === 0) {
							 | 
						|
								        path = [];
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if (level === 2) {
							 | 
						|
								        path.push('M', 0, -8, 'L', 4, -8); // short line
							 | 
						|
								    } else if (level >= 3) {
							 | 
						|
								        path.push(0, -10, 7, -10); // long line
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if (level === 4) {
							 | 
						|
								        path.push('M', 0, -7, 'L', 4, -7);
							 | 
						|
								    } else if (level >= 5) {
							 | 
						|
								        path.push('M', 0, -7, 'L', 7, -7);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if (level === 5) {
							 | 
						|
								        path.push('M', 0, -4, 'L', 4, -4);
							 | 
						|
								    } else if (level >= 6) {
							 | 
						|
								        path.push('M', 0, -4, 'L', 7, -4);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if (level === 7) {
							 | 
						|
								        path.push('M', 0, -1, 'L', 4, -1);
							 | 
						|
								    } else if (level >= 8) {
							 | 
						|
								        path.push('M', 0, -1, 'L', 7, -1);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    return path;
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Draw the wind arrows. Each arrow path is generated by the windArrow function above.
							 | 
						|
								 */
							 | 
						|
								Meteogram.prototype.drawWindArrows = function (chart) {
							 | 
						|
								    var meteogram = this;
							 | 
						|
								
							 | 
						|
								    $.each(chart.series[0].data, function (i, point) {
							 | 
						|
								        var sprite, arrow, x, y;
							 | 
						|
								
							 | 
						|
								        if (meteogram.resolution > 36e5 || i % 2 === 0) {
							 | 
						|
								
							 | 
						|
								            // Draw the wind arrows
							 | 
						|
								            x = point.plotX + chart.plotLeft + 7;
							 | 
						|
								            y = 255;
							 | 
						|
								            if (meteogram.windSpeedNames[i] === 'Calm') {
							 | 
						|
								                arrow = chart.renderer.circle(x, y, 10).attr({
							 | 
						|
								                    fill: 'none'
							 | 
						|
								                });
							 | 
						|
								            } else {
							 | 
						|
								                arrow = chart.renderer.path(
							 | 
						|
								                    meteogram.windArrow(meteogram.windSpeedNames[i])
							 | 
						|
								                ).attr({
							 | 
						|
								                    rotation: parseInt(meteogram.windDirections[i], 10),
							 | 
						|
								                    translateX: x, // rotation center
							 | 
						|
								                    translateY: y // rotation center
							 | 
						|
								                });
							 | 
						|
								            }
							 | 
						|
								            arrow.attr({
							 | 
						|
								                stroke: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black',
							 | 
						|
								                'stroke-width': 1.5,
							 | 
						|
								                zIndex: 5
							 | 
						|
								            })
							 | 
						|
								            .add();
							 | 
						|
								
							 | 
						|
								        }
							 | 
						|
								    });
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Draw blocks around wind arrows, below the plot area
							 | 
						|
								 */
							 | 
						|
								Meteogram.prototype.drawBlocksForWindArrows = function (chart) {
							 | 
						|
								    var xAxis = chart.xAxis[0],
							 | 
						|
								        x,
							 | 
						|
								        pos,
							 | 
						|
								        max,
							 | 
						|
								        isLong,
							 | 
						|
								        isLast,
							 | 
						|
								        i;
							 | 
						|
								
							 | 
						|
								    for (pos = xAxis.min, max = xAxis.max, i = 0; pos <= max + 36e5; pos += 36e5, i += 1) {
							 | 
						|
								
							 | 
						|
								        // Get the X position
							 | 
						|
								        isLast = pos === max + 36e5;
							 | 
						|
								        x = Math.round(xAxis.toPixels(pos)) + (isLast ? 0.5 : -0.5);
							 | 
						|
								
							 | 
						|
								        // Draw the vertical dividers and ticks
							 | 
						|
								        if (this.resolution > 36e5) {
							 | 
						|
								            isLong = pos % this.resolution === 0;
							 | 
						|
								        } else {
							 | 
						|
								            isLong = i % 2 === 0;
							 | 
						|
								        }
							 | 
						|
								        chart.renderer.path(['M', x, chart.plotTop + chart.plotHeight + (isLong ? 0 : 28),
							 | 
						|
								            'L', x, chart.plotTop + chart.plotHeight + 32, 'Z'])
							 | 
						|
								            .attr({
							 | 
						|
								                'stroke': chart.options.chart.plotBorderColor,
							 | 
						|
								                'stroke-width': 1
							 | 
						|
								            })
							 | 
						|
								            .add();
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Get the title based on the XML data
							 | 
						|
								 */
							 | 
						|
								Meteogram.prototype.getTitle = function () {
							 | 
						|
								    return 'Meteogram for ' + this.xml.location.name + ', ' + this.xml.location.country;
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Build and return the Highcharts options structure
							 | 
						|
								 */
							 | 
						|
								Meteogram.prototype.getChartOptions = function () {
							 | 
						|
								    var meteogram = this;
							 | 
						|
								
							 | 
						|
								    return {
							 | 
						|
								        chart: {
							 | 
						|
								            renderTo: this.container,
							 | 
						|
								            marginBottom: 70,
							 | 
						|
								            marginRight: 40,
							 | 
						|
								            marginTop: 50,
							 | 
						|
								            plotBorderWidth: 1,
							 | 
						|
								            width: 800,
							 | 
						|
								            height: 310
							 | 
						|
								        },
							 | 
						|
								
							 | 
						|
								        title: {
							 | 
						|
								            text: this.getTitle(),
							 | 
						|
								            align: 'left'
							 | 
						|
								        },
							 | 
						|
								
							 | 
						|
								        credits: {
							 | 
						|
								            text: 'Forecast from <a href="http://yr.no">yr.no</a>',
							 | 
						|
								            href: this.xml.credit.link['@attributes'].url,
							 | 
						|
								            position: {
							 | 
						|
								                x: -40
							 | 
						|
								            }
							 | 
						|
								        },
							 | 
						|
								
							 | 
						|
								        tooltip: {
							 | 
						|
								            shared: true,
							 | 
						|
								            useHTML: true,
							 | 
						|
								            formatter: function () {
							 | 
						|
								                return meteogram.tooltipFormatter(this);
							 | 
						|
								            }
							 | 
						|
								        },
							 | 
						|
								
							 | 
						|
								        xAxis: [{ // Bottom X axis
							 | 
						|
								            type: 'datetime',
							 | 
						|
								            tickInterval: 2 * 36e5, // two hours
							 | 
						|
								            minorTickInterval: 36e5, // one hour
							 | 
						|
								            tickLength: 0,
							 | 
						|
								            gridLineWidth: 1,
							 | 
						|
								            gridLineColor: (Highcharts.theme && Highcharts.theme.background2) || '#F0F0F0',
							 | 
						|
								            startOnTick: false,
							 | 
						|
								            endOnTick: false,
							 | 
						|
								            minPadding: 0,
							 | 
						|
								            maxPadding: 0,
							 | 
						|
								            offset: 30,
							 | 
						|
								            showLastLabel: true,
							 | 
						|
								            labels: {
							 | 
						|
								                format: '{value:%H}'
							 | 
						|
								            }
							 | 
						|
								        }, { // Top X axis
							 | 
						|
								            linkedTo: 0,
							 | 
						|
								            type: 'datetime',
							 | 
						|
								            tickInterval: 24 * 3600 * 1000,
							 | 
						|
								            labels: {
							 | 
						|
								                format: '{value:<span style="font-size: 12px; font-weight: bold">%a</span> %b %e}',
							 | 
						|
								                align: 'left',
							 | 
						|
								                x: 3,
							 | 
						|
								                y: -5
							 | 
						|
								            },
							 | 
						|
								            opposite: true,
							 | 
						|
								            tickLength: 20,
							 | 
						|
								            gridLineWidth: 1
							 | 
						|
								        }],
							 | 
						|
								
							 | 
						|
								        yAxis: [{ // temperature axis
							 | 
						|
								            title: {
							 | 
						|
								                text: null
							 | 
						|
								            },
							 | 
						|
								            labels: {
							 | 
						|
								                format: '{value}°',
							 | 
						|
								                style: {
							 | 
						|
								                    fontSize: '10px'
							 | 
						|
								                },
							 | 
						|
								                x: -3
							 | 
						|
								            },
							 | 
						|
								            plotLines: [{ // zero plane
							 | 
						|
								                value: 0,
							 | 
						|
								                color: '#BBBBBB',
							 | 
						|
								                width: 1,
							 | 
						|
								                zIndex: 2
							 | 
						|
								            }],
							 | 
						|
								            // Custom positioner to provide even temperature ticks from top down
							 | 
						|
								            tickPositioner: function () {
							 | 
						|
								                var max = Math.ceil(this.max) + 1,
							 | 
						|
								                    pos = max - 12, // start
							 | 
						|
								                    ret;
							 | 
						|
								
							 | 
						|
								                if (pos < this.min) {
							 | 
						|
								                    ret = [];
							 | 
						|
								                    while (pos <= max) {
							 | 
						|
								                        ret.push(pos += 1);
							 | 
						|
								                    }
							 | 
						|
								                } // else return undefined and go auto
							 | 
						|
								
							 | 
						|
								                return ret;
							 | 
						|
								
							 | 
						|
								            },
							 | 
						|
								            maxPadding: 0.3,
							 | 
						|
								            tickInterval: 1,
							 | 
						|
								            gridLineColor: (Highcharts.theme && Highcharts.theme.background2) || '#F0F0F0'
							 | 
						|
								
							 | 
						|
								        }, { // precipitation axis
							 | 
						|
								            title: {
							 | 
						|
								                text: null
							 | 
						|
								            },
							 | 
						|
								            labels: {
							 | 
						|
								                enabled: false
							 | 
						|
								            },
							 | 
						|
								            gridLineWidth: 0,
							 | 
						|
								            tickLength: 0
							 | 
						|
								
							 | 
						|
								        }, { // Air pressure
							 | 
						|
								            allowDecimals: false,
							 | 
						|
								            title: { // Title on top of axis
							 | 
						|
								                text: 'hPa',
							 | 
						|
								                offset: 0,
							 | 
						|
								                align: 'high',
							 | 
						|
								                rotation: 0,
							 | 
						|
								                style: {
							 | 
						|
								                    fontSize: '10px',
							 | 
						|
								                    color: Highcharts.getOptions().colors[2]
							 | 
						|
								                },
							 | 
						|
								                textAlign: 'left',
							 | 
						|
								                x: 3
							 | 
						|
								            },
							 | 
						|
								            labels: {
							 | 
						|
								                style: {
							 | 
						|
								                    fontSize: '8px',
							 | 
						|
								                    color: Highcharts.getOptions().colors[2]
							 | 
						|
								                },
							 | 
						|
								                y: 2,
							 | 
						|
								                x: 3
							 | 
						|
								            },
							 | 
						|
								            gridLineWidth: 0,
							 | 
						|
								            opposite: true,
							 | 
						|
								            showLastLabel: false
							 | 
						|
								        }],
							 | 
						|
								
							 | 
						|
								        legend: {
							 | 
						|
								            enabled: false
							 | 
						|
								        },
							 | 
						|
								
							 | 
						|
								        plotOptions: {
							 | 
						|
								            series: {
							 | 
						|
								                pointPlacement: 'between'
							 | 
						|
								            }
							 | 
						|
								        },
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								        series: [{
							 | 
						|
								            name: 'Temperature',
							 | 
						|
								            data: this.temperatures,
							 | 
						|
								            type: 'spline',
							 | 
						|
								            marker: {
							 | 
						|
								                enabled: false,
							 | 
						|
								                states: {
							 | 
						|
								                    hover: {
							 | 
						|
								                        enabled: true
							 | 
						|
								                    }
							 | 
						|
								                }
							 | 
						|
								            },
							 | 
						|
								            tooltip: {
							 | 
						|
								                valueSuffix: '°C'
							 | 
						|
								            },
							 | 
						|
								            zIndex: 1,
							 | 
						|
								            color: '#FF3333',
							 | 
						|
								            negativeColor: '#48AFE8'
							 | 
						|
								        }, {
							 | 
						|
								            name: 'Precipitation',
							 | 
						|
								            data: this.precipitations,
							 | 
						|
								            type: 'column',
							 | 
						|
								            color: '#68CFE8',
							 | 
						|
								            yAxis: 1,
							 | 
						|
								            groupPadding: 0,
							 | 
						|
								            pointPadding: 0,
							 | 
						|
								            borderWidth: 0,
							 | 
						|
								            shadow: false,
							 | 
						|
								            dataLabels: {
							 | 
						|
								                enabled: true,
							 | 
						|
								                formatter: function () {
							 | 
						|
								                    if (this.y > 0) {
							 | 
						|
								                        return this.y;
							 | 
						|
								                    }
							 | 
						|
								                },
							 | 
						|
								                style: {
							 | 
						|
								                    fontSize: '8px'
							 | 
						|
								                }
							 | 
						|
								            },
							 | 
						|
								            tooltip: {
							 | 
						|
								                valueSuffix: 'mm'
							 | 
						|
								            }
							 | 
						|
								        }, {
							 | 
						|
								            name: 'Air pressure',
							 | 
						|
								            color: Highcharts.getOptions().colors[2],
							 | 
						|
								            data: this.pressures,
							 | 
						|
								            marker: {
							 | 
						|
								                enabled: false
							 | 
						|
								            },
							 | 
						|
								            shadow: false,
							 | 
						|
								            tooltip: {
							 | 
						|
								                valueSuffix: ' hPa'
							 | 
						|
								            },
							 | 
						|
								            dashStyle: 'shortdot',
							 | 
						|
								            yAxis: 2
							 | 
						|
								        }]
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Post-process the chart from the callback function, the second argument to Highcharts.Chart.
							 | 
						|
								 */
							 | 
						|
								Meteogram.prototype.onChartLoad = function (chart) {
							 | 
						|
								
							 | 
						|
								    this.drawWeatherSymbols(chart);
							 | 
						|
								    this.drawWindArrows(chart);
							 | 
						|
								    this.drawBlocksForWindArrows(chart);
							 | 
						|
								
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Create the chart. This function is called async when the data file is loaded and parsed.
							 | 
						|
								 */
							 | 
						|
								Meteogram.prototype.createChart = function () {
							 | 
						|
								    var meteogram = this;
							 | 
						|
								    this.chart = new Highcharts.Chart(this.getChartOptions(), function (chart) {
							 | 
						|
								        meteogram.onChartLoad(chart);
							 | 
						|
								    });
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Handle the data. This part of the code is not Highcharts specific, but deals with yr.no's
							 | 
						|
								 * specific data format
							 | 
						|
								 */
							 | 
						|
								Meteogram.prototype.parseYrData = function () {
							 | 
						|
								
							 | 
						|
								    var meteogram = this,
							 | 
						|
								        xml = this.xml,
							 | 
						|
								        pointStart;
							 | 
						|
								
							 | 
						|
								    if (!xml || !xml.forecast) {
							 | 
						|
								        $('#loading').html('<i class="fa fa-frown-o"></i> Failed loading data, please try again later');
							 | 
						|
								        return;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // The returned xml variable is a JavaScript representation of the provided XML,
							 | 
						|
								    // generated on the server by running PHP simple_load_xml and converting it to
							 | 
						|
								    // JavaScript by json_encode.
							 | 
						|
								    $.each(xml.forecast.tabular.time, function (i, time) {
							 | 
						|
								        // Get the times - only Safari can't parse ISO8601 so we need to do some replacements
							 | 
						|
								        var from = time['@attributes'].from + ' UTC',
							 | 
						|
								            to = time['@attributes'].to + ' UTC';
							 | 
						|
								
							 | 
						|
								        from = from.replace(/-/g, '/').replace('T', ' ');
							 | 
						|
								        from = Date.parse(from);
							 | 
						|
								        to = to.replace(/-/g, '/').replace('T', ' ');
							 | 
						|
								        to = Date.parse(to);
							 | 
						|
								
							 | 
						|
								        if (to > pointStart + 4 * 24 * 36e5) {
							 | 
						|
								            return;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        // If it is more than an hour between points, show all symbols
							 | 
						|
								        if (i === 0) {
							 | 
						|
								            meteogram.resolution = to - from;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        // Populate the parallel arrays
							 | 
						|
								        meteogram.symbols.push(time.symbol['@attributes']['var'].match(/[0-9]{2}[dnm]?/)[0]);
							 | 
						|
								        meteogram.symbolNames.push(time.symbol['@attributes'].name);
							 | 
						|
								
							 | 
						|
								        meteogram.temperatures.push({
							 | 
						|
								            x: from,
							 | 
						|
								            y: parseInt(time.temperature['@attributes'].value),
							 | 
						|
								            // custom options used in the tooltip formatter
							 | 
						|
								            to: to,
							 | 
						|
								            index: i
							 | 
						|
								        });
							 | 
						|
								
							 | 
						|
								        meteogram.precipitations.push({
							 | 
						|
								            x: from,
							 | 
						|
								            y: parseFloat(time.precipitation['@attributes'].value)
							 | 
						|
								        });
							 | 
						|
								        meteogram.windDirections.push(parseFloat(time.windDirection['@attributes'].deg));
							 | 
						|
								        meteogram.windDirectionNames.push(time.windDirection['@attributes'].name);
							 | 
						|
								        meteogram.windSpeeds.push(parseFloat(time.windSpeed['@attributes'].mps));
							 | 
						|
								        meteogram.windSpeedNames.push(time.windSpeed['@attributes'].name);
							 | 
						|
								
							 | 
						|
								        meteogram.pressures.push({
							 | 
						|
								            x: from,
							 | 
						|
								            y: parseFloat(time.pressure['@attributes'].value)
							 | 
						|
								        });
							 | 
						|
								
							 | 
						|
								        if (i == 0) {
							 | 
						|
								            pointStart = (from + to) / 2;
							 | 
						|
								        }
							 | 
						|
								    });
							 | 
						|
								
							 | 
						|
								    // Smooth the line
							 | 
						|
								    this.smoothLine(this.temperatures);
							 | 
						|
								
							 | 
						|
								    // Create the chart when the data is loaded
							 | 
						|
								    this.createChart();
							 | 
						|
								};
							 | 
						|
								// End of the Meteogram protype
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								$(function () { // On DOM ready...
							 | 
						|
								
							 | 
						|
								    // Set the hash to the yr.no URL we want to parse
							 | 
						|
								    if (!location.hash) {
							 | 
						|
								        var place = 'United_Kingdom/England/London';
							 | 
						|
								        //place = 'France/Rhône-Alpes/Val_d\'Isère~2971074';
							 | 
						|
								        //place = 'Norway/Sogn_og_Fjordane/Vik/Målset';
							 | 
						|
								        //place = 'United_States/California/San_Francisco';
							 | 
						|
								        //place = 'United_States/Minnesota/Minneapolis';
							 | 
						|
								        location.hash = 'http://www.yr.no/place/' + place + '/forecast_hour_by_hour.xml';
							 | 
						|
								
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // Then get the XML file through Highcharts' jsonp provider, see
							 | 
						|
								    // https://github.com/highslide-software/highcharts.com/blob/master/samples/data/jsonp.php
							 | 
						|
								    // for source code.
							 | 
						|
								    $.getJSON(
							 | 
						|
								        'http://www.highcharts.com/samples/data/jsonp.php?url=' + location.hash.substr(1) + '&callback=?',
							 | 
						|
								        function (xml) {
							 | 
						|
								            var meteogram = new Meteogram(xml, 'container');
							 | 
						|
								        }
							 | 
						|
								    );
							 | 
						|
								
							 | 
						|
								});
							 | 
						|
										</script>
							 | 
						|
									</head>
							 | 
						|
									<body>
							 | 
						|
								
							 | 
						|
								<script src="../../js/highcharts.js"></script>
							 | 
						|
								<script src="../../js/modules/exporting.js"></script>
							 | 
						|
								<link href="http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
							 | 
						|
								
							 | 
						|
								<div id="container" style="width: 800px; height: 310px; margin: 0 auto">
							 | 
						|
									<div style="margin-top: 100px; text-align: center" id="loading">
							 | 
						|
										<i class="fa fa-spinner fa-spin"></i> Loading data from external source
							 | 
						|
									</div>
							 | 
						|
								</div>
							 | 
						|
								<!--
							 | 
						|
								<div style="width: 800px; margin: 0 auto">
							 | 
						|
									<a href="#http://www.yr.no/place/United_Kingdom/England/London/forecast_hour_by_hour.xml">London</a>,
							 | 
						|
									<a href="#http://www.yr.no/place/France/Rhône-Alpes/Val_d\'Isère~2971074/forecast_hour_by_hour.xml">Val d'Isère</a>,
							 | 
						|
									<a href="#http://www.yr.no/place/United_States/California/San_Francisco/forecast_hour_by_hour.xml">San Francisco</a>,
							 | 
						|
									<a href="#http://www.yr.no/place/Norway/Vik/Vikafjell/forecast_hour_by_hour.xml">Vikjafjellet</a>
							 | 
						|
								</div>
							 | 
						|
								-->
							 | 
						|
									</body>
							 | 
						|
								</html>
							 |