(function() {
const n = 50;
const duration = 750;
let now = new Date(Date.now() - duration);
const data = d3.range(n).map(function() { return 0; });

const margin = {
    top: 10,
    right: 40,
    bottom: 40,
    left: 40,
};
const width = 860 - margin.right;
const height = 520 - margin.top - margin.bottom;

var x = d3.time.scale()
    .domain([now - (n - 2) * duration, now - duration])
    .range([0, width]);

var y = d3.scale.linear()
    .range([height, 0])
    .domain([0, 100])

var line = d3.svg.line()
    .interpolate('basis')
    .x(function(d, i) { return x(now - (n - 1 - i) * duration); })
    .y(function(d, i) { return y(d); });

var svg = d3.select('body').append('p').append('svg')
    .attr('width', width + margin.left + margin.right)
    .attr('height', height + margin.top + margin.bottom)
    .style('margin-left', `${-margin.left}px`)
    .append('g')
    .attr('transform', `translate(${margin.left}, ${margin.top})`);

svg.append('defs').append('clipPath')
    .attr('id', 'clip')
    .append('rect')
    .attr('width', width)
    .attr('height', height);

var axisx = svg.append('g')
    .attr('class', 'x axis')
    .attr('transform', `translate(0, ${height})`)
    .call(x.axis = d3.svg.axis().scale(x).orient('bottom').tickPadding(10));

var axisy = svg.append('g')
    .attr('class', 'y axis')
    .attr('transform', `translate(${width}, 0)`)
    .call(y.axis = d3.svg.axis().scale(y).orient('right').tickPadding(10));

var path = svg.append('g')
    .attr('clip-path', 'url(#clip)')
    .append('path')
    .datum(data)
    .attr('class', 'line');

var transition = d3.select({}).transition()
    .duration(duration)
    .ease('linear');

(function tick() {
    transition = transition.each(function() {

        // Update the domain of the x-axis
        now = new Date();
        x.domain([now - (n - 2) * duration, now - duration]);

        // Push the new data point
        data.push(Math.random() * (80 - 20) + 20);

        // Redraw the line
        svg.select('.line')
            .attr('d', line)
            .attr('transform', null);

        // Slide the x-axis left
        axisx.call(x.axis);

        // Slide the line left
        path.transition()
            .attr('transform', `translate(${x(now - (n - 1) * duration)})`);

        // Pop the old data point off the front
        data.shift();

    }).transition().each('start', tick);
})();

})()