Sometime last year, I concluded two truly awesome (to me, at least) web tutorials on 
Bar Charts and 
Line Graphs using HTML, a lot of CSS, and a bit of JavaScript. Today, I bring you... the Pie Chart.
Pie Charts are primarily used to show relative amounts, or percentages. And they're useful for determining, at a glance, what the majority statistic is. Bar Charts can do that too - they're versatile that way - but not as well as a Pie Chart. There's going to be a fair amount of math involved in this one. You'll need to understand percentages and geometry, at the very least.
For the purposes of this web tutorial, we will be using the same dataset that was employed during the last two web tutorials. We'll also be reusing some functions and CSS classes.
Without further ado...
Here's the beginning HTML. You'll see that I've included, in the interest of saving time, some of the HTML and CSS we used during the 
Bar Chart and 
Line Graph web tutorials. The 
graph_container div is there, as well as 
legend_container div, and the two dropdown lists, 
ddlRow and 
ddlStat. 
For the JavaScript, I've included the dataset 
graphdata, as well as the functions 
populate(), 
getMaxStatistic(), 
displayData() and 
displayLegend(). There will be changes to some of the stuff, but as with the previous web tutorials, 
populate() will call 
displayData() and 
displayLegend() at the end. 
displayLegend() and 
getMaxStatistic() are unchanged from the last tutorial.
The page loads 
populate() and the dropdown lists trigger 
displayData(), as per the last web tutorials.
For the CSS, I've left the styling for the 
graph_container largely intact (except it's now a 400 pixel square and centered), and the styling for the legend is identical to the 
Line Graph web tutorial's.
<!DOCTYPE html>
<html>
    <head>
        <title>Pie Chart</title>
        <style>
            #graph_container
            {
                height: 400px;
                width: 400px;
                margin: 0 auto 0 auto;
            }        
            #legend_container
            {
                color: #FFFFFF;
                font-weight: bold;
                font-family: verdana;
                font-size: 1em;
                width: 50%;
                margin: 5% auto 0 auto;
                padding: 0.5em;
            }
            .legend_row
            {
                width: 100%;
                height: 1.5em;
            }
            #legend_row: after
            {
                display: block;
                content: "";
                clear: both;
            }
            .legend_color
            {
                width: 1em;
                height: 1em;
                float: left;
            }
            .legend_label
            {
                height: 1em;
                float: left;
                color: #000000;
                font-weight: bold;
                font-family: verdana;
                font-size: 1em;
                margin-left: 1em;
            }
        </style>
        <script>
            var graphdata = 
            {
                "cols": 
                [
                    {
                        "title": "Fernando Torres",
                        "color": "#FF00FF",
                        "stats": 
                        [
                            {"year": 2007, "goals": 24, "appearances": 33},
                            {"year": 2008, "goals": 14, "appearances": 24},
                            {"year": 2009, "goals": 18, "appearances": 22},
                            {"year": 2010, "goals": 9, "appearances": 23},
                        ]
                    },
                    {
                        "title": "Steven Gerrard",
                        "color": "#440000",
                        "stats": 
                        [
                            {"year": 2007, "goals": 11, "appearances": 36},
                            {"year": 2008, "goals": 16, "appearances": 34},
                            {"year": 2009, "goals": 9, "appearances": 31},
                            {"year": 2010, "goals": 4, "appearances": 33},
                        ]
                    },
                    {
                        "title": "Dirk Kuyt",
                        "color": "#FFFF00",
                        "stats": 
                        [
                            {"year": 2007, "goals": 3, "appearances": 34},
                            {"year": 2008, "goals": 12, "appearances": 32},
                            {"year": 2009, "goals": 9, "appearances": 38},
                            {"year": 2010, "goals": 13, "appearances": 37},
                        ]
                    },
                    {
                        "title": "Ryan Babel",
                        "color": "#00AA00",
                        "stats": 
                        [
                            {"year": 2007, "goals": 4, "appearances": 30},
                            {"year": 2008, "goals": 3, "appearances": 27},
                            {"year": 2009, "goals": 4, "appearances": 25},
                            {"year": 2010, "goals": 1, "appearances": 1},
                        ]
                    },
                    {
                        "title": "Yossi Benayoun",
                        "color": "#000044",
                        "stats": 
                        [
                            {"year": 2007, "goals": 4, "appearances": 30},
                            {"year": 2008, "goals": 8, "appearances": 32},
                            {"year": 2009, "goals": 6, "appearances": 30},
                        ]
                    },
                    {
                        "title": "David N'gog",
                        "color": "#006699",
                        "stats": 
                        [
                            {"year": 2008, "goals": 2, "appearances": 14},
                            {"year": 2009, "goals": 5, "appearances": 24},
                            {"year": 2010, "goals": 2, "appearances": 25},
                        ]
                    },
                ],
                "rows": [2007, 2008, 2009, 2010],
                "stats": ["goals", "appearances"]
            }; 
            function populate()
            {
                displayLegend();
                displayData();
            }
            function displayData()
            {
            }
            function getMaxStatistic(haystack, needle)
            {
                for (var i = 0; i < haystack.length; i++)
                {    
                    if (haystack[i].stats < haystack[needle].stats)
                    {
                        return false;
                    }
                }
                return true;
            }
            function displayLegend()
            {
                var legend = document.getElementById("legend_container");
                legend.innerHTML = "";
                var color, label;
                var row;
                for (var i = 0; i < graphdata.cols.length; i++)
                {
                    color = document.createElement("div");
                    color.className = "legend_color";
                    color.style.backgroundColor = graphdata.cols[i].color;
                    label = document.createElement("div");
                    label.className = "legend_label";
                    label.innerHTML = graphdata.cols[i].title;
                    row = document.createElement("div");
                    row.className = "legend_row";
                    row.appendChild(color);
                    row.appendChild(label);
                    legend.appendChild(row);
                }
            }
        </script>
    </head>
    
    <body onload="populate();">
        <div id="graph_container">
        </div>
        <div id="legend_container">
        </div>
        <select id="ddlRow" onchange="displayData();">
        </select>
        <select id="ddlStat" onchange="displayData();">
        </select>
    </body>
</html>
So let's do this now. Set all divs to have a 
red outline.
            div {outline: 1px solid #FFAA00;}
            #graph_container
            {
                height: 400px;
                width: 400px;
                margin: 0 auto 0 auto;
            }
For the sake of visibility, this is what you have now.
Let's start with some smaller stuff. Populate the drop-down lists as shown. If you've been following the previous web tutorials, this should be clear; I'd rather not repeat myself.
            function populate()
            {
                var ddl,option;
                ddl = document.getElementById("ddlRow");
                for (var i=0;i<graphdata.rows.length;i++)
                {
                    option = document.createElement("option");
                    option.text = graphdata.rows[i] + " - " + (parseInt(graphdata.rows[i])+1);
                    option.value = graphdata.rows[i];
                    ddl.add(option);
                }
                ddl = document.getElementById("ddlStat");
                for (var i=0;i<graphdata.stats.length;i++)
                {
                    option = document.createElement("option");
                    option.text = graphdata.stats[i];
                    option.value = graphdata.stats[i];
                    ddl.add(option);
                }
                displayLegend();
                displayData();
            }
Your drop-down lists! Right now, they don't do anything (other than fire off the empty displayData() function), but that's fine.
OK, down to (more) serious business! Within your 
graph_container div, you should have a div for your data labels, id 
label_wrapper, followed by a div for your pie, id 
pie_container.
        <div id="graph_container">
            <div id="label_wrapper">
            </div>
            <div id="pie_container">
            </div>
        </div>
Here's the styling. Both of these divs will occupy the 
graph_container div fully (100% height and width) and floated left. 
pie_container will be circular, so the 
border-radius property is at 50%, and 
overflow is set to 
hidden. 
label_wrapper will overlap 
pie_container, so the 
margin-right property is set to negative 100% while a 
display and 
z-index property needs to be specified. You won't see any change in your browser after refreshing it. It's a perfect overlap.
            div {outline:0px solid #FFAA00;}
            #graph_container
            {
                height: 400px;
                width: 400px;
                margin: 0 auto 0 auto;
            }
            #pie_container
            {
                height: 100%;
                width: 100%;
                border-radius: 50%;
                float: left;
                overflow: hidden;
            }            
            #label_wrapper
            {
                height: 100%;
                width: 100%;
                margin-right: -100%;
                float: left;
                position: relative;
                z-index: 2000;
            }
Now we're gonna add another div inside label_wrapper. This will have an id of 
label_quad_wrapper.
        <div id="graph_container">
            <div id="label_wrapper">
                <div id="label_quad_wrapper">
                </div>
            </div>
            <div id="pie_container">
            </div>
        </div>
It'll be styled this way. It's going to occupy the top right quarter of the 
label_wrapper div.
            #label_wrapper
            {
                height: 100%;
                width: 100%;
                margin-right: -100%;
                float: left;
                position: relative;
                z-index: 2000;
            }
            #label_quad_wrapper
            {
                height: 50%;
                width: 50%;
                margin-left: 50%;
            }
            #legend_container
            {
                color: #FFFFFF;
                font-weight: bold;
                font-family: verdana;
                font-size: 1em;
                width: 50%;
                margin: 5% auto 0 auto;
                padding: 0.5em;
            }
Next, we add two divs in the 
pie_container div. One will be 
quad_wrapper_left and the other will be 
quad_wrapper_right. The ids are important! They will both have the style 
quad_wrapper.
        <div id="graph_container">
            <div id="label_wrapper">
                <div id="label_quad_wrapper">
                </div>
            </div>
            <div id="pie_container">
                <div id="quad_wrapper_left" class="quad_wrapper">
                </div>
                <div id="quad_wrapper_right" class="quad_wrapper">
                </div>
            </div>
        </div>
This is how we'll style these. They will take up both halves of the pie_container div.
            #pie_container
            {
                height: 100%;
                width: 100%;
                border-radius: 50%;
                float: left;
                overflow: hidden;
            }            
            .quad_wrapper
            {
                width: 50%;
                height: 100%;
                float: left;
            }
            #label_wrapper
            {
                height: 100%;
                width: 100%;
                margin-right: -100%;
                float: left;
                position: relative;
                z-index: 2000;
            }
See that? 
pie_container has two equal-sized divs, one taking the left side, and one taking the right. And because it's overlapped with 
label_wrapper, the 
label_quad_wrapper div can still be seen on the top right corner!
Now for the hard part...
We'll be working with the data, to put in the labels.
First, let's define a class for those labels. 
The class 
label_quad will be used to store those pie slices we'll be putting in 
label_quad_wrapper. The pie slices will be the full size of 
label_quad_wrapper, floated left, and they'll be rotated by the bottom left corner.
data_label is another class. I'm setting the text to 
black for now. But the other properties are mostly cosmetic. I set the 
position property explicitly to 
relative for these two classes so there's no misunderstanding on the part of the browser.
            #label_quad_wrapper
            {
                height: 50%;
                width: 50%;
                margin-left: 50%;
            }
            .label_quad
            {
                width: 100%;
                height: 100%;
                margin-bottom: -100%;
                -webkit-transform-origin: 0% 100%; 
                transform-origin: 0% 100%;
                position: relative;
            }
            .data_label
            {
                color: #000000;
                font-weight: bold;
                font-family: verdana;
                font-size: 0.8em;
                position: relative;
            }
            #legend_container
            {
                color: #FFFFFF;
                font-weight: bold;
                font-family: verdana;
                font-size: 1em;
                width: 50%;
                margin: 5% auto 0 auto;
                padding: 0.5em;
            }
Now that we've defined those classes, let's get to work with the JavaScript. Pay close attention, because there'll be quite a few moving parts in this one. We're just going to place the data labels first.
Here, we start with the 
displayData() function. Get the current values of the 
ddlStat and 
ddlRow drop-down lists and assign them to the variables 
stat and 
row, respectively.
            function displayData()
            {
                var stat = document.getElementById("ddlStat").value;
                var row = document.getElementById("ddlRow").value;
            }
Create the variable 
nonzero and set it to the value of a function, 
getNonZero(), with 
row and 
stat passed in as arguments. Then create the function 
getNonZero. It'll take in two parameters - you guessed it - 
row and 
stat. The purpose of this function is to return 
only values that are non-zero... because showing data that is zero in a pie chart just doesn't make much sense, does it?
            function displayData()
            {
                var stat = document.getElementById("ddlStat").value;
                var row = document.getElementById("ddlRow").value;
                var nonzero = getNonZero(row, stat);
            }
            function getNonZero(row, stat)
            {
            }
First, define an array, 
nonzero. Then variables 
temp and 
player. At the end of the function, you will return the array 
nonzero.
            function getNonZero(row, stat)
            {
                var nonzero = [];
                var temp;
                var player;
                return nonzero;
            }
Now, let's iterate through the cols array of the 
graphdata object. In the 
For loop, get the 
stats array filtered. We only want those whose 
year property match the 
row variable. Set the resultant array to the variable 
temp.
            function getNonZero(row, stat)
            {
                var nonzero = [];
                var temp;
                var player;
                for (var i = 0; i < graphdata.cols.length; i++)
                {
                    temp = graphdata.cols[i].stats.filter(function (x) {return x.year == row;});
                }
                return nonzero;
            }
Now, we only want to do stuff if the 
temp array is not empty. There should be only one item in the array, so reference 
temp[0], and grab the property corresponding with 
stat. This being a JSON object, an array is really another type of object, so we can reference the 
temp[0] object's properties by treating it as a two-dimensional array! Again, we only want to do stuff if the stat in question is greater than zero.
            function getNonZero(row, stat)
            {
                var nonzero = [];
                var temp;
                var player;
                for (var i = 0; i < graphdata.cols.length; i++)
                {
                    temp = graphdata.cols[i].stats.filter(function (x) {return x.year == row;});
                    if (temp.length > 0)
                    {
                        if (temp[0][stat] > 0)
                        {
                        }    
                    }
                }
                return nonzero;
            }
If there's non-zero data, set 
player to a newly created object and assign it two properties - 
color and 
stats. Grab the appropriate data from the 
graphdata and 
temp[0] object, then add the resultant object to the 
nonzero array. Basically, this function gives you an array of objects corresponding to the year and statistic selected in the drop-down lists, and their corresponding color and value in the 
graphdata object! And makes sure the values selected are non-zero, of course.
            function getNonZero(row, stat)
            {
                var nonzero = [];
                var temp;
                var player;
                for (var i = 0; i < graphdata.cols.length; i++)
                {
                    temp = graphdata.cols[i].stats.filter(function (x) {return x.year == row;});
                    if (temp.length > 0)
                    {
                        if (temp[0][stat] > 0)
                        {
                            player = 
                            {
                                "color": graphdata.cols[i].color,
                                "stats": temp[0][stat]    
                            };
                            nonzero.push(player);
                        }    
                    }
                }
                return nonzero;
            }
For instance, if you passed "2009" and "goals" into the 
getNonZero() function, you would get an array of objects like this.
[
    {
        "color": "#FF00FF",
        "stats": 18    
    },
    {
        "color": "#440000",
        "stats": 9    
    },
    {
        "color": "#FFFF00",
        "stats": 9    
    },
    {
        "color": "#00AA00",
        "stats": 4    
    },
    {
        "color": "#000044",
        "stats": 6    
    },
    {
        "color": "#006699",
        "stats": 5    
    }
]
So back to the 
displayData() function. After obtaining the array of non-zero statistics, run it through the 
getSorted() function and assign the result to the 
sorted variable. And then create the 
getSorted() function.
            function displayData()
            {
                var stat = document.getElementById("ddlStat").value;
                var row = document.getElementById("ddlRow").value;
                var nonzero = getNonZero(row, stat);
                var sorted = getSorted(nonzero);
            }
            function getNonZero(row, stat)
            {
                var nonzero = [];
                var temp;
                var player;
                for (var i = 0; i < graphdata.cols.length; i++)
                {
                    temp = graphdata.cols[i].stats.filter(function (x) {return x.year == row;});
                    if (temp.length > 0)
                    {
                        if (temp[0][stat] > 0)
                        {
                            player = 
                            {
                                "title": graphdata.cols[i].title,
                                "color": graphdata.cols[i].color,
                                "stats": temp[0][stat]    
                            };
                            nonzero.push(player);
                        }    
                    }
                }
                return nonzero;
            }
            function getSorted(nonzero)
            {
            }
We first define 
sorted as an empty array, and 
temp as a variable, assigning the value of 
nonzero to it. At the end of the function, we return 
sorted. This function basically accepts the array of non-zero values, 
nonzero, and sorts them from largest to smallest. There's a reason why we need this. It will all be clear later.
            function getSorted(nonzero)
            {
                var sorted = [];
                var temp = nonzero;
                return sorted;
            }
Now we'll be running the next segment of code for as long as 
temp is not an empty array. If 
temp has only one element, we add that element to 
sorted, then remove it from 
temp using the 
splice() method. That would make 
temp an empty array, which is when the loop ends.
            function getSorted(nonzero)
            {
                var sorted = [];
                var temp = nonzero;
                while (temp.length > 0)
                {
                    if (temp.length == 1)
                    {
                        sorted.push(temp[0]);
                        temp.splice(0, 1);
                    }
                    else
                    {
                    }
                }
                return sorted;
            }
But if 
temp has more than one element, we iterate through 
temp. And run the 
getMaxStatistic() function, passing in 
temp and the current pointer. 
            function getSorted(nonzero)
            {
                var sorted = [];
                var temp = nonzero;
                while (temp.length > 0)
                {
                    if (temp.length == 1)
                    {
                        sorted.push(temp[0]);
                        temp.splice(0, 1);
                    }
                    else
                    {
                        for (var i = 0; i < temp.length; i++)
                        {    
                            if (getMaxStatistic(temp, i))
                            {
                            }
                        }
                    }
                }
                return sorted;
            }
If the result is 
true, push the current element in the 
temp array into 
sorted, then remove that element from 
temp. We already have the 
getMaxStatistic() function. It will return 
true if the element in the 
temp array pointed to by 
i, has the highest stat in the array.
So what this does, is probably not all that efficient... but it works and that's all we really need from it right now.
            function getSorted(nonzero)
            {
                var sorted = [];
                var temp = nonzero;
                while (temp.length > 0)
                {
                    if (temp.length == 1)
                    {
                        sorted.push(temp[0]);
                        temp.splice(0, 1);
                    }
                    else
                    {
                        for (var i = 0; i < temp.length; i++)
                        {    
                            if (getMaxStatistic(temp, i))
                            {
                                sorted.push(temp[i]);
                                temp.splice(i, 1);
                            }
                        }
                    }
                }
                return sorted;
            }
After using the 
getSorted() function, the returned data should look like this.
[
    {
        "color": "#FF00FF",
        "stats": 18    
    },
    {
        "color": "#440000",
        "stats": 9    
    },
    {
        "color": "#FFFF00",
        "stats": 9    
    },
    {
        "color": "#000044",
        "stats": 6    
    },
    {
        "color": "#006699",
        "stats": 5    
    },
    {
        "color": "#00AA00",
        "stats": 4    
    },
]
Got all that? Great? We're going back to the 
displayData() function now...
Now that we have sorted which is the array holding the sorted statistics from largest to smallest, we pass the array into the 
getPieces() function as an argument and set the variable 
pieces to the result. This function will derive all the pieces required to hold the data. We'll get to that in a moment.
            function displayData()
            {
                var stat = document.getElementById("ddlStat").value;
                var row = document.getElementById("ddlRow").value;
                var nonzero = getNonZero(row, stat);
                var sorted = getSorted(nonzero);
                var pieces = getPieces(sorted);
            }
In the 
getPieces() function, we first define a variable, 
total, intitialized to 0. Then an empty array, 
pieces. Then we have another two variables, 
currentPiece and 
currentTotalPiece. 
currentTotalPiece is also initialized to 0. 
pieces is returned at the end of the function.
            function getSorted(nonzero)
            {
                var sorted = [];
                var temp = nonzero;
                while (temp.length > 0)
                {
                    if (temp.length == 1)
                    {
                        sorted.push(temp[0]);
                        temp.splice(0, 1);
                    }
                    else
                    {
                        for (var i = 0; i < temp.length; i++)
                        {    
                            if (getMaxStatistic(temp, i))
                            {
                                sorted.push(temp[i]);
                                temp.splice(i, 1);
                            }
                        }
                    }
                }
                return sorted;
            }
            function getPieces(sorted)
            {
                var total = 0;
                var pieces = [];
                var currentPiece;
                var currentTotalPiece = 0;
                return pieces;
            }
            function getMaxStatistic(haystack, needle)
            {
                for (var i = 0; i < haystack.length; i++)
                {    
                    if (haystack[i].stats < haystack[needle].stats)
                    {
                        return false;
                    }
                }
                return true;
            }
Next, we will obtain 
total by iterating through the array 
sorted and tallying up all the stats.
            function getPieces(sorted)
            {
                var total = 0;
                var pieces = [];
                var currentPiece;
                var currentTotalPiece = 0;
                for (var i = 0; i < sorted.length; i++)
                {    
                    total += sorted[i].stats;
                }
                return pieces;
            }
Next, we iterate through the 
sorted array in reverse order. Why? Because 
sorted is sorted from largest stat to smallest. We want to process the largest stats first. And why is 
that? Relax, it'll be clear soon.
Our aim here is to determine how many degrees, out of a possible 360 degrees (which, geometrically, is what a circle offers), that each stat will take.
Inside the loop, if 
i is 0, that means you are at the first element of 
sorted (and smallest stat), in which case the size of 
currentPiece is 360 degrees minus 
currentTotalPiece. eBar that in mind, for now.
If not, we derive 
currentPiece by calculating the ratio, which is the current stat divided by 
total. Then we multiple that by 360 to get the number of degrees the stat will take. Using the 
toFixed() method with 0 as an argument, will ensure that the decimal places are trimmed off. However, we want to use 
currentPiece in another calculation next, so we have to use the 
parseInt() function. 
currentTotalPiece is the number of degrees that have been used up by your pieces so far, so it will be incremented by 
currentPiece. Of course, when you get to the final and smallest stat, we merely have to take 360 less 
currentTotalPiece!
            function getPieces(sorted)
            {
                var total = 0;
                var pieces = [];
                var currentPiece;
                var currentTotalPiece = 0;
                for (var i = 0; i < sorted.length; i++)
                {    
                    total += sorted[i].stats;
                }
                for (var i = sorted.length - 1; i >= 0; i--)
                {    
                    if (i == 0)
                    {
                        currentPiece = 360 - currentTotalPiece;
                    }
                    else
                    {
                        currentPiece = ((sorted[i].stats/total) * 360).toFixed(0);
                        currentTotalPiece += parseInt(currentPiece);
                    }
                }
                return pieces;
            }
Of course, with each piece that is being processed, create an object with the 
color, 
stats, and the 
piece property, which is set to the value of 
currentPiece. Then added it to the 
pieces array. Since we're using the 
push() method and the 
sorted array is being iterated through in reverse order, that means we'll get a sorted array with the largest piece, to the smallest piece!
            function getPieces(sorted)
            {
                var total = 0;
                var pieces = [];
                var currentPiece;
                var currentTotalPiece = 0;
                for (var i = 0; i < sorted.length; i++)
                {    
                    total += sorted[i].stats;
                }
                for (var i = sorted.length - 1; i >= 0; i--)
                {    
                    if (i == 0)
                    {
                        currentPiece = 360 - currentTotalPiece;
                    }
                    else
                    {
                        currentPiece = ((sorted[i].stats / total) * 360).toFixed(0);
                        currentTotalPiece += parseInt(currentPiece);
                    }
                    pieces.push
                    (
                        {
                            "color": sorted[i].color,
                            "stats": sorted[i].stats,
                            "piece": currentPiece
                        }
                    );
                }
                return pieces;
            }
The data derived from 
getPieces() should be this...
[
    {
        "color": "#FF00FF",
        "stats": 18,
        "piece": 127    
    },
    {
        "color": "#440000",
        "stats": 9,
        "piece": 64
    },
    {
        "color": "#FFFF00",
        "stats": 9,
        "piece": 64
    },
    {
        "color": "#000044",
        "stats": 6,
        "piece": 42    
    },
    {
        "color": "#006699",
        "stats": 5,
        "piece": 35
    },
    {
        "color": "#00AA00",
        "stats": 4,
        "piece": 28    
    }
]
Next thing we do is clear the 
label_quad_wrapper div.
            function displayData()
            {
                var stat = document.getElementById("ddlStat").value;
                var row = document.getElementById("ddlRow").value;
                var nonzero = getNonZero(row, stat);
                var sorted = getSorted(nonzero);
                var pieces = getPieces(sorted);
                var label_quad_wrapper = document.getElementById("label_quad_wrapper");
                label_quad_wrapper.innerHTML = "";
            }
Now declare an object, 
lastPieceAngle, and put in properties 
prevangle and 
newangle. Initialize both to 0. Set the value of 
lastPieceAngle to the function 
placeLabel(), using the first piece in 
pieces and 
lastPieceAngle as arguments. Then create the 
placeLabel() function.
            function displayData()
            {
                var stat = document.getElementById("ddlStat").value;
                var row = document.getElementById("ddlRow").value;
                var nonzero = getNonZero(row, stat);
                var sorted = getSorted(nonzero);
                var pieces = getPieces(sorted);
                var lastPieceAngle = {"prevangle": 0, "newangle": 0};
                var label_quad_wrapper = document.getElementById("label_quad_wrapper");
                label_quad_wrapper.innerHTML = "";
                lastPieceAngle = placeLabel(pieces[0], lastPieceAngle);
            }
            function placeLabel(piece, angle)
            {
            }
We'll get started with the 
placeLabel() function now. Declare 
newangle and 
midangle as variables. Since each pie slice is supposed to begin and end at a particular angle, we derive 
newangle from the 
newangle variable, and the 
newangle property of the 
angle object becomes the previous angle, 
prevangle.
As for 
midangle, I'll explain in the next few paragraphs.
            function placeLabel(piece, angle)
            {
                var newangle, midangle;
                return {"prevangle" : angle.newangle, "newangle": newangle};
            }
Here, we define the variable 
label_quad as a newly created div element, and set its class to "label_quad". Remember, we created the CSS class earlier!
            function placeLabel(piece, angle)
            {
                var newangle, midangle;
                var label_quad = document.createElement("div");
                label_quad.className = "label_quad";
                return {"prevangle" : angle.newangle, "newangle": newangle};
            }
Here, we append 
label_quad as a child within 
label_quad_wrapper. Then we create a span element and assign it to the variable 
label. We give label a class of 
data_label (which we've already defined in the CSS), set 
label's text to the 
stat property of the 
piece object in the parameter, and append 
label as a child within 
label_quad! 
            function placeLabel(piece, angle)
            {
                var newangle, midangle;
                var label_quad = document.createElement("div");
                label_quad.className = "label_quad";
                var label_quad_wrapper = document.getElementById("label_quad_wrapper");
                label_quad_wrapper.appendChild(label_quad);
                var label = document.createElement("span");
                label.className = "data_label";
                label.innerHTML = piece.stats;
                label_quad.appendChild(label);
                return {"prevangle" : angle.newangle, "newangle": newangle};
            }
See that? You've just placed your first label. Change the value in the Seasons drop-down list to "2009 to 2010". The number should change to 18! Fernando Torres scored 18 goals in the 2009 to 2010 season, and naturally it's the highest stat of that season, so it comes first. However, we want it to appear in the middle of the slice. 18 out of 51 total goals (count all the goals scored in that season as a whole) is almost a third of the pie, so the number 18 should appear much further along.
Here, 
newangle is set to the ending angle of the last piece, plus the size of the current piece. 
            function placeLabel(piece, angle)
            {
                var newangle, midangle;
                var label_quad = document.createElement("div");
                label_quad.className = "label_quad";
                newangle = angle.newangle + parseInt(piece.piece);
                var label_quad_wrapper = document.getElementById("label_quad_wrapper");
                label_quad_wrapper.appendChild(label_quad);
                var label = document.createElement("span");
                label.className = "data_label";
                label.innerHTML = piece.stats;
                label_quad.appendChild(label);
                return {"prevangle" : angle.newangle, "newangle": newangle};
            }
midangle is the angle right in the middle of the current slice. We define 
midangle as the size of the current slice, 
piece.piece, divided by two, and added to the previous angle, 
angle.newangle.  Then we rotate 
label_quad by 
midangle.
            function placeLabel(piece, angle)
            {
                var newangle, midangle;
                var label_quad = document.createElement("div");
                label_quad.className = "label_quad";
                newangle = angle.newangle + parseInt(piece.piece);
                midangle = ((parseInt(piece.piece)) / 2) + angle.newangle;
                label_quad.style.WebkitTransform = "rotate(" + midangle + "deg)";
                label_quad.style.transform = "rotate(" + midangle + "deg)";
                var label_quad_wrapper = document.getElementById("label_quad_wrapper");
                label_quad_wrapper.appendChild(label_quad);
                var label = document.createElement("span");
                label.className = "data_label";
                label.innerHTML = piece.stats;
                label_quad.appendChild(label);
                return {"prevangle" : angle.newangle, "newangle": newangle};
            }
There. Since 18 would occupy roughly a third of the pie (120 degrees), half of that is about 60 degrees, which is what we've rotated the div by! 
Now let's add another label.
            function displayData()
            {
                var stat = document.getElementById("ddlStat").value;
                var row = document.getElementById("ddlRow").value;
                var nonzero = getNonZero(row, stat);
                var sorted = getSorted(nonzero);
                var pieces = getPieces(sorted);
                var lastPieceAngle = {"prevangle": 0, "newangle": 0};
                var label_quad_wrapper = document.getElementById("label_quad_wrapper");
                label_quad_wrapper.innerHTML = "";
                lastPieceAngle = placeLabel(pieces[0], lastPieceAngle);
                lastPieceAngle = placeLabel(pieces[1], lastPieceAngle);
            }
Your next label is a 9. It takes up a fifth of the total of 51 goals, so its size is about 20% of the pie (roughly 70 degrees) and half of that is abut 35 degrees! 35 degrees from the last angle of 120 (or so) degrees, that is. If math isn't your thing or my explanation just sucks, worry not, The next part of this tutorial will make things visually clear.
Now, adding all these labels one by one is a pain in the ass, so let's put this in a 
For loop.
            function displayData()
            {
                var stat = document.getElementById("ddlStat").value;
                var row = document.getElementById("ddlRow").value;
                var nonzero = getNonZero(row, stat);
                var sorted = getSorted(nonzero);
                var pieces = getPieces(sorted);
                var lastPieceAngle = {"prevangle": 0, "newangle": 0};
                var label_quad_wrapper = document.getElementById("label_quad_wrapper");
                label_quad_wrapper.innerHTML = "";
                for (var i = 0; i < pieces.length; i++)
                {
                    lastPieceAngle = placeLabel(pieces[i], lastPieceAngle);
                }
            }
There you go! But hell, it's devilishly hard to read the numbers when they're all rotated, so...
...let's rotate the label the other direction by the same number of degrees!
            function placeLabel(piece, angle)
            {
                var newangle, midangle;
                var label_quad = document.createElement("div");
                label_quad.className = "label_quad";
                newangle = angle.newangle + parseInt(piece.piece);
                midangle = ((newangle - angle.newangle) / 2) + angle.newangle;
                label_quad.style.WebkitTransform = "rotate(" + midangle + "deg)";
                label_quad.style.transform = "rotate(" + midangle + "deg)";
                var label_quad_wrapper = document.getElementById("label_quad_wrapper");
                label_quad_wrapper.appendChild(label_quad);
                var label = document.createElement("span");
                label.className = "data_label";
                label.innerHTML = piece.stats;
                label.style.WebkitTransform = "rotate(" + (midangle * -1) + "deg)";
                label.style.transform = "rotate(" + (midangle * -1) + "deg)";
                label_quad.appendChild(label);
                return {"prevangle" : angle.newangle, "newangle": newangle};
            }
And we'll have to make the CSS class 
data_label rotatable by giving it a 
display property of inline-block. While we're there, let's make it rotate by its exact center by setting the 
transform-origin property.
            .data_label
            {
                color: #000000;
                font-weight: bold;
                font-family: verdana;
                font-size: 0.8em;
                position: relative;
                display: inline-block;
                -webkit-transform-origin: 50% 50%;
                transform-origin: 50% 50%;
            }
There you go.
Just set this back...
div {outline: 0px solid #FFAA00;}
Gettin' clear as shit!
Next
Time to start coloring the pie chart. You don't want to miss this!