Yo, dudes.
We last left off with what looked like a really messy line graph layout. This was deliberate, because now with all the individual column groups separated out, it's easier to test your data. Things are going to get a little math-heavy.
Let's begin by modifying the 
displayData() function. After deriving 
max, we declare a whole series of variables - 
percentage, 
nextpercentage, 
actual, 
nextactual, 
margintop and 
nextmargintop. These are the variables needed for node and line manipulation.
Then there are the variables 
node, 
line and 
tx. These are the variables that are objects. More on that later.
For now, create a nested 
For loop. The outer loop should iterate through the 
cols array of the 
graphdata object while the inner loop should iterate through the 
rows array of the 
graphdata object.
            function displayData()
            {
                var stat = document.getElementById("ddlStat").value;
                var max = getMaxStatistic(stat);
                var percentage,nextpercentage,actual,nextactual,margintop,nextmargintop;
                var node,line,tx;
                for (var i=0;i<graphdata.cols.length;i++)
                {
                    for (var j=0;j<graphdata.rows.length;j++)
                    {
                    }
                }
                displayScale(max);
            }
Now, right in the inner loop, set 
actual by running the 
getStatistic() function. The function is pretty much identical to the one we created for the bar chart...
            function displayData()
            {
                var stat = document.getElementById("ddlStat").value;
                var max = getMaxStatistic(stat);
                var percentage,nextpercentage,actual,nextactual,margintop,nextmargintop;
                var node,line,tx;
                for (var i=0;i<graphdata.cols.length;i++)
                {
                    for (var j=0;j<graphdata.rows.length;j++)
                    {
                        actual = getStatistic(graphdata.cols[i],graphdata.rows[j],stat);
                    }
                }
                displayScale(max);
            }
            function getStatistic(data,row,stat)
            {
                var temp;
                temp = data.stats.filter(function (x) {return x.year==row;});
                if (temp.length>0)
                {
                    return temp[0][stat];
                }
                return 0;
            }
...except for this. This is necessary because in some cases, data would be 
undefined.
            function getStatistic(data,row,stat)
            {
                if (data==undefined) return 0;
                var temp;
                temp = data.stats.filter(function (x) {return x.year==row;});
                if (temp.length>0)
                {
                    return temp[0][stat];
                }
                return 0;
            }
Now that we have the value of the statistic set to the variable 
actual, just as for the bar chart, we define 
percentage. 
margintop will use 
percentage to determine how many pixels the node needs to be from the top, going by a height of 80% of 500 pixels. Minus 5 because the node is 10 pixels in height and we want its center to be at the level specified, see?
            function displayData()
            {
                var stat = document.getElementById("ddlStat").value;
                var max = getMaxStatistic(stat);
                var percentage,nextpercentage,actual,nextactual,margintop,nextmargintop;
                var node,line,tx;
                for (var i=0;i<graphdata.cols.length;i++)
                {
                    for (var j=0;j<graphdata.rows.length;j++)
                    {
                        actual = getStatistic(graphdata.cols[i],graphdata.rows[j],stat);
                        percentage = 100 - ((actual/max) * 100);
                        margintop = ((percentage/100 * (0.8*500)) -5);
                    }
                }
                displayScale(max);
            }
And the we set the variable 
node to the element whose id corresponds to the 
i and 
j value (remember setting ids for those nodes?), set the 
margin-top property using the 
margintop variable, and display the value of 
actual using the 
innerHTML property for good measure.
            function displayData()
            {
                var stat = document.getElementById("ddlStat").value;
                var max = getMaxStatistic(stat);
                var percentage,nextpercentage,actual,nextactual,margintop,nextmargintop;
                var node,line,tx;
                for (var i=0;i<graphdata.cols.length;i++)
                {
                    for (var j=0;j<graphdata.rows.length;j++)
                    {
                        actual = getStatistic(graphdata.cols[i],graphdata.rows[j],stat);
                        percentage = 100 - ((actual/max) * 100);
                        margintop = ((percentage/100 * (0.8*500)) -5);
                        node = document.getElementById("node_" + i + "_" +j);
                        node.style.marginTop = margintop + "px";
                        node.innerHTML = actual;
                    }
                }
                displayScale(max);
            }
Now, you see that the nodes have shifted. The values displayed in each node should correspond with the scale.
Next, you want to start rotating the lines so that they join to the next node. First, we need an 
If block to ensure that we only attempt this for columns preceding the final column (which only has a node and no line to manipulate).
            function displayData()
            {
                var stat = document.getElementById("ddlStat").value;
                var max = getMaxStatistic(stat);
                var percentage,nextpercentage,actual,nextactual,margintop,nextmargintop;
                var node,line,tx;
                for (var i=0;i<graphdata.cols.length;i++)
                {
                    for (var j=0;j<graphdata.rows.length;j++)
                    {
                        actual = getStatistic(graphdata.cols[i],graphdata.rows[j],stat);
                        percentage = 100 - ((actual/max) * 100);
                        margintop = ((percentage/100 * (0.8*500)) -5);
                        node = document.getElementById("node_" + i + "_" +j);
                        node.style.marginTop = margintop + "px";
                        node.innerHTML = actual;
                        if (j<graphdata.rows.length-1)
                        {
                        }
                    }
                }
                displayScale(max);
            }
Before going further, I want to bring to your attention 
Pythagoras's Theorem. Your objective is to rotate the 
magenta line so that the end touches the next node. The length of the line will need to be increased as well, naturally. So as per the diagram below, we need the angle 
x and we need the hypotenuse, 
h. 
a is definitely 200 pixels due to the specification of the 
col_container CSS class. 
The length of 
o needs to be derived. It's not as simple as 24 - 14 = 10. We have to take into account that the number of pixels is based on a height of 80% of 500 pixels!
But basically, once you have 
o and 
a, you can get 
h and 
x.
We'll begin by getting the statistic of the next node, running 
getStatistic() and setting the returned value to the variable 
nextactual. 
nextpercentage and 
nextmargintop are then derived the same way as 
percentage and 
margintop.
Then we set the variable 
tx by running 
getLineTransform(), which will return an object. We will pass in the difference between 
margintop and 
nextmargintop, and the number 200 as arguments. And of course, we'll create the 
getLineTransform() function.
            function displayData()
            {
                var stat = document.getElementById("ddlStat").value;
                var max = getMaxStatistic(stat);
                var percentage,nextpercentage,actual,nextactual,margintop,nextmargintop;
                var node,line,tx;
                for (var i=0;i<graphdata.cols.length;i++)
                {
                    for (var j=0;j<graphdata.rows.length;j++)
                    {
                        actual = getStatistic(graphdata.cols[i],graphdata.rows[j],stat);
                        percentage = 100 - ((actual/max) * 100);
                        margintop = ((percentage/100 * (0.8*500)) -5);
                        node = document.getElementById("node_" + i + "_" +j);
                        node.style.marginTop = margintop + "px";
                        node.innerHTML = actual;
                        if (j<graphdata.rows.length-1)
                        {
                            nextactual = getStatistic(graphdata.cols[i],graphdata.rows[j+1],stat);
                            nextpercentage = 100 - ((nextactual/max) * 100);
                            nextmargintop = ((nextpercentage/100 * (0.8*500)) -5);
                            tx = getLineTransform((margintop-nextmargintop),200);
                        }
                    }
                }
                displayScale(max);
            }
            function getLineTransform(o,a)
            {
            }
For the 
getLineTransform() function, we first declare the variables 
angle and 
hypotenuse. These will be returned in an object.
            function getLineTransform(o,a)
            {
                var angle, hypotenuse;
                return {"rotate":angle,"width":hypotenuse+100};
            }
If 
o is zero, this means that the next node has the same value as the previous node. This in turn means that the line does not need to be rotated, and the length of the line is the same as 
a.
            function getLineTransform(o,a)
            {
                var angle, hypotenuse;
                if (o==0)
                {
                    hypotenuse = a;
                    angle = 0;
                }
                else
                {
                }
                return {"rotate":angle,"width":hypotenuse+100};
            }
Otherwise, derive 
hypotenuse by using the 
hypot() method of the 
Math object. It will give you the square root of the sum of all arguments squared. Remember to use the absolute value of 
o instead.
            function getLineTransform(o,a)
            {
                var angle, hypotenuse;
                if (o==0)
                {
                    hypotenuse = a;
                    angle = 0;
                }
                else
                {
                    hypotenuse = Math.hypot(Math.abs(o),a).toFixed(0);
                }
                return {"rotate":angle,"width":hypotenuse+100};
            }
Then derive 
angle. The tangent of 
angle is 
o divided by 
a, so you can derive 
angle by getting the arctangent of the result of dividing 
o by 
a. Again, remember to use the absolute value of 
o. The result is in 
radians, and we need to convert it to degrees using the 
getDegrees() function.
            function getLineTransform(o,a)
            {
                var angle, hypotenuse;
                if (o==0)
                {
                    hypotenuse = a;
                    angle = 0;
                }
                else
                {
                    hypotenuse = Math.hypot(Math.abs(o),a).toFixed(0);
                    angle = getDegrees(Math.atan((Math.abs(o)/a))).toFixed(1);
                }
                return {"rotate":angle,"width":hypotenuse+100};
            }
            function getDegrees(radians) {
                return radians * 180 / Math.PI;
            };
Now, if 
o is greater than 0, it means that the value of the next node is higher and therefore the line needs to be rotated counter-clockwise rather than clockwise. So make sure the value is negative.
            function getLineTransform(o,a)
            {
                var angle, hypotenuse;
                if (o==0)
                {
                    hypotenuse = a;
                    angle = 0;
                }
                else
                {
                    hypotenuse = Math.hypot(Math.abs(o),a).toFixed(0);
                    angle = getDegrees(Math.atan((Math.abs(o)/a))).toFixed(1);
                    if (o>0)
                    {
                        angle = angle * -1;
                    }
                }
                return {"rotate":angle,"width":hypotenuse+100};
            }
            function getDegrees(radians) {
                return radians * 180 / Math.PI;
            };
Back to the 
displayData() function, we access the element that corresponds to the id derived from 
i and 
j, assign it to the variable 
line, then set the rotation and length of line using the object 
tx.
            function displayData()
            {
                var stat = document.getElementById("ddlStat").value;
                var max = getMaxStatistic(stat);
                var percentage,nextpercentage,actual,nextactual,margintop,nextmargintop;
                var node,line,tx;
                for (var i=0;i<graphdata.cols.length;i++)
                {
                    for (var j=0;j<graphdata.rows.length;j++)
                    {
                        actual = getStatistic(graphdata.cols[i],graphdata.rows[j],stat);
                        percentage = 100 - ((actual/max) * 100);
                        margintop = ((percentage/100 * (0.8*500)) -5);
                        node = document.getElementById("node_" + i + "_" +j);
                        node.style.marginTop = margintop + "px";
                        node.innerHTML = actual;
                        if (j<graphdata.rows.length-1)
                        {
                            nextactual = getStatistic(graphdata.cols[i],graphdata.rows[j+1],stat);
                            nextpercentage = 100 - ((nextactual/max) * 100);
                            nextmargintop = ((nextpercentage/100 * (0.8*500)) -5);
                            tx = getLineTransform((margintop-nextmargintop),200);
                            line = document.getElementById("line_" + i + "_" + j);
                            line.style.width = tx.width + "px";
                            line.style.WebkitTransform = "rotate(" + tx.rotate + "deg)"; 
                            line.style.transform = "rotate(" + tx.rotate + "deg)";
                        }
                    }
                }
                displayScale(max);
            }
And there you are!
Change this back,
            .col_container
            {
                height:100%;
                width:95%;
                float:left;
                margin-right:-100%;
            }
Taking shape now...
And of course, do this...
div {outline:0px solid #FFAA00;}
Here's your line graph! Try changing the value in the drop-down list. Do the lines and nodes shift?
There was even more math than the last one, and we even had to pull out good ol' Pythagoras. It's a hoot though - we got the job done! There's plenty of room for improvement, and plenty of variations on this idea, so have at it.
Wasn't that easy? There's node-thing to it,
T___T