/*******************************************************************************
** Author: Peter McCutcheon
** Date Created: 3/31/2017
** Last Modified: 12/02/2017
**
**------------------------------------------------------------------------------
**Description of Code:
**
**
********************************************************************************/
function pageLoaded()
{
var frmtTime = d3.timeParse(":%S");
btnGenPlot = document.getElementById("btnGenPlot");
btnGenPlot.addEventListener("click", function () {getDataForGraph("daily", "")}, false);
apRequest = new XMLHttpRequest();
apRequest.open("POST", "../php/getAirportList.php");
apRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
if (!apRequest)
{
alert("Error - Ajax object not created, browser may not support Ajax.");
return false;
}
apRequest.onreadystatechange = function ()
{
if (apRequest.readyState == 4 && apRequest.status === 200)
{
if (apRequest.responseText != null)
{
var apData = JSON.parse(apRequest.responseText);
var airportSelect = document.getElementById("airportselect");
for (var i = 0; i < apData.apID.length; i++)
{
var opt = document.createElement("option");
opt.setAttribute("value", apData.apID[i]);
opt.text = apData.apDesc[i];
airportSelect.appendChild(opt);
}
}
}
else
{
if (apRequest.status != 200)
{
alert("AJAX Error: " + apRequest.readyState + " --- " + apRequest.status);
}
}
};
//
// Send the ajax request to the server.
//
apRequest.send();
alRequest = new XMLHttpRequest();
alRequest.open("POST", "../php/getAirlineList.php");
alRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
if (!alRequest)
{
alert("Error - Ajax object not created, browser may not support Ajax.");
return false;
}
alRequest.onreadystatechange = function ()
{
if (alRequest.readyState == 4 && alRequest.status === 200)
{
if (alRequest.responseText != null)
{
var alData = JSON.parse(alRequest.responseText);
var airlineSelect = document.getElementById("airlineselect");
for (var i = 0; i < alData.alID.length; i++)
{
var opt = document.createElement("option");
opt.setAttribute("value", alData.alID[i]);
opt.text = alData.alDesc[i];
airlineSelect.appendChild(opt);
}
}
}
else
{
if (alRequest.status != 200)
{
alert("AJAX Error: " + alRequest.readyState + " --- " + alRequest.status);
}
}
};
//
// Send the ajax request to the server.
//
alRequest.send();
}
function getDataForGraph(chartToGenerate, selectDate, flightNum)
{
// Date to string conversion.
var strDate = d3.timeFormat("%Y-%m-%d");
// String to date conversion.
var parseTime = d3.timeParse("%Y-%m-%d");
//
// Gather the form information to send in the Ajax request to generate the plot per the user.
// Get the user selection for the chart. This will be used to create
// a an Ajax message to select the desired data from the database.
//
var airportSelected = document.getElementById("airportselect").value;
var airlineSelected = document.getElementById("airlineselect").value;
var startDate = document.getElementById("startdate").value;
var endDate = document.getElementById("enddate").value;
//
// Get the type of chart, from the DOM, that the user wants.
//
var plotCircle = document.getElementById("plotcircle");
var plotBar = document.getElementById("plotbar");
if (plotCircle.checked)
{
var chartType = "C";
}
else
{
if (plotBar.checked)
{
var chartType = "B";
}
else
{
alert("You did not select a chart type, please select one.");
return;
}
}
var msg = "";
//
// First clear out the div that contains the chart in preparation for the new plot.
// Then set up the Ajax message based on the chart that will be generated.
//
if (chartToGenerate == "daily")
{
chartImageDiv = document.getElementById("chartimage");
chartImageDiv.innerHTML = "";
msg = "type=" + chartToGenerate + "&airport=" + airportSelected + "&airline=" + airlineSelected + "&startdate=" + startDate + "&enddate=" + endDate;
alert("Retrieving flight information, this could take a minute or two...");
}
else
{
if (chartToGenerate == "detail")
{
chartImageDiv = document.getElementById("detailimage")
chartImageDiv.innerHTML = "";
//
// On the detail for a given day force the graph to always be bar, regardless of what was selected.
// This is so the flight numbers display ok, otherwise on the circle graph they can all run together.
//
chartType = "B";
//selectDate = startDate.substring(0, startDate.lastIndexOf("-"));
//selectDate = selectDate + "-" + day;
selectDate = strDate(selectDate);
msg = "type=" + chartToGenerate + "&airport=" + airportSelected + "&airline=" + airlineSelected + "&selectdate=" + selectDate;
}
else
{
if (chartToGenerate == "flight")
{
chartImageDiv = document.getElementById("flightimage")
chartImageDiv.innerHTML = "";
//selectDate = startDate.substring(0, startDate.lastIndexOf("-"));
var tmpDate = parseTime(selectDate);
selectDate = strDate(tmpDate);
msg = "type=" + chartToGenerate + "&airport=" + airportSelected + "&airline=" + airlineSelected + "&selectdate=" + selectDate + "&flightnumber=" + flightNum;
}
}
}
//
// Create the Ajax request and send it with our generated message.
//
frmrequest = new XMLHttpRequest();
frmrequest.open("POST", "../php/getFlightData.php");
frmrequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
if (!frmrequest)
{
alert("Error - Ajax object not created, browser may not support Ajax.");
return false;
}
frmrequest.onreadystatechange = function ()
{
if (frmrequest.readyState == 4 && frmrequest.status === 200)
{
if (frmrequest.responseText != null)
{
if (frmrequest.responseText == "0 results")
{
alert("No flights for the data selection. Please try a different selection.");
return;
}
if (chartToGenerate == "daily")
{
var chartImageDiv = document.getElementById("chartimage");
}
else
{
var chartImageDiv = document.getElementById("detailimage");
}
var flightData = JSON.parse(frmrequest.responseText);
if (chartToGenerate == "daily" || chartToGenerate == "detail")
{
var ret = generateGraph(chartType, flightData, chartImageDiv, chartToGenerate, selectDate)
if (ret)
{
alert("Error encountered attempting to generate the graph.");
}
}
else
{
if (chartToGenerate == "flight")
{
ret = displayFlightInfo(flightData);
}
else
{
alert("We are back with our specific flight data.");
}
}
}
}
else
{
if (frmrequest.status != 200)
{
alert("AJAX Error: " + frmrequest.readyState + " --- " + frmrequest.status + " text " + frmrequest.responseText);
}
}
}.bind(chartType);
//
// Send the ajax request to the server.
//
frmrequest.send(msg);
}
function generateGraph(typ, fd, ci, chartToGenerate, sDate)
{
var margin = {"top": 30, "right": 30, "bottom": 30, "left": 40},
height = 500 - margin.top - margin.bottom,
width = 800 - margin.right - margin.left;
var hDiv2 = height / 2;
var padding = 40;
var barPadding = 1;
var circlePadding = 20;
var hScaleFactor = 4;
var txtTitle = "";
var tipText = "";
var xScale, yScale, xAxis, yAxis; //Empty, for now
var flightData = new Array(new Object());
var startDate = document.getElementById("startdate").value;
var endDate = document.getElementById("enddate").value;
// For converting strings to dates.
var parseTime = d3.timeParse("%Y-%m-%d");
//For converting Dates to strings
var formatTime = d3.timeFormat("%d");
var formatNiceDate = d3.timeFormat("%B %d, %Y");
//Function for converting CSV values from strings to Dates and numbers
if (chartToGenerate == "daily")
{
flightData[0] = {'xValue': parseTime(fd[0].xValue), 'yValue': parseInt(fd[0].yValue)};
txtTitle = "Flight Delay for " + formatNiceDate(parseTime(startDate)) + " To " + formatNiceDate(parseTime(endDate));
tipText = "Date: ";
}
else
{
if (chartToGenerate == "detail")
{
flightData[0] = {'xValue': fd[0].xValue, 'yValue': parseInt(fd[0].yValue)};
txtTitle = "Flight Information for " + formatNiceDate(parseTime(sDate));
tipText = "Flight Number: ";
}
}
for (var i = 1; i < fd.length; i++)
{
if (chartToGenerate == "daily")
{
flightData.push({'xValue': parseTime(fd[i].xValue), 'yValue': parseInt(fd[i].yValue)});
}
else
{
flightData.push({'xValue': fd[i].xValue, 'yValue': parseInt(fd[i].yValue)});
}
}
//***************************************************************************
//***************************************************************************
//Convert the array of objects to an object with arrays.
var ds = {"xValue": new Array(), "yValue": new Array()};
for (var i = 0; i < flightData.length; i++)
{
ds.xValue.push(flightData[i].xValue);
ds.yValue.push(+flightData[i].yValue);
}
var svg = d3.select("#chartimage")
.append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var dMax = d3.max(flightData, function(d) {
return d.yValue;
});
var dMin = d3.min(flightData, function(d) {
return d.yValue;
});
if (typ == "C")
{
//
// Set up the y-axis scale.
//
var yScale = d3.scaleLinear()
.domain([dMin, dMax])
.range([height, 0]);
//
// set up the x-axis scale.
//
var ordScale = d3.scalePoint()
.domain(ds.xValue)
.range([margin.left,width]);
//
// This graph actually is an implementation of a scatterplot.
// Here we just make the area of the circles dependent
// on there y-value.
//
// Generate all of the circle for the scatterplot graph.
//
svg.selectAll("circle")
.data(flightData)
.enter()
.append("circle")
.attr("cx", function(d, i) {
return ordScale(d.xValue);
})
.attr("cy", function(d) {
if (d.yValue < 0)
{
return yScale(d.yValue);
}
else
{
return yScale(d.yValue);
}
})
.attr("r", function(d) {return Math.sqrt(Math.abs(d.yValue))})
.attr("fill", function(d) {
if (d.yValue < 0)
{
return "yellow";
}
else
{
return "red";
}
})
.on("mouseover", function() {
d3.select(this).attr("fill", "green")
})
.on("mouseout", function(d, i) {
d3.select(this).attr("fill", function(d) {
if (d.yValue < 0)
{
return "yellow";
}
else
{
return "red";
}
})
})
.on("click", function(d) {if (chartToGenerate == "daily") getDataForGraph("detail", d.xValue, ""); else if (chartToGenerate == "detail") getDataForGraph("flight", sDate, d.xValue);});
var txtElem = svg.selectAll("text")
.data(flightData)
.enter()
.append("text")
.text(function(d){return formatTime(d.xValue);})
.attr("x", function(d, i) {return ordScale(d.xValue) + 4;})
.attr("y", function(d) {
if (d.yValue < 0)
{
return yScale(d.yValue);
}
else
{
return yScale(d.yValue);
}
})
.attr("font-family", "sans-serif")
.attr("font-size", "20px")
.attr("fill", "steelblue");
var xAxis1 = d3.axisBottom()
.scale(ordScale)
.tickSize(-height,0,0)
.tickFormat("");
svg.append("g")
.attr("class", "xAxis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis1);
var yAxisPos = d3.axisLeft()
.scale(yScale)
.tickSize(-width,0,0);
var yAxisNeg = d3.axisLeft()
.scale(yScale)
.tickSize(-width,0,0);
svg.append("g")
.attr("class", "yAxis")
.attr("transform", "translate(" + padding + ", 0)")
.call(yAxisPos);
svg.append("g")
.attr("class", "yAxis")
.attr("transform", "translate(" + padding + ", 0)")
.call(yAxisNeg);
svg.append("text")
.attr("x", yScale(0)-30)
.attr("y", margin.left - 30)
.text("Minutes")
.attr("text-anchor", "middle")
.attr("font-size", "20px")
.attr("fill", "steelblue")
.attr("transform", "rotate(90)");
svg.append("text")
.attr("x", (width / 2))
.attr("y", 0 - (margin.top / 2))
.attr("text-anchor", "middle")
.style("font-size", "20px")
.text(txtTitle)
.attr("font-family", "sans-serif")
.attr("fill", "steelblue");
}
else
{
var yScale = d3.scaleLinear()
.domain([dMin, dMax])
.range([height, 0]);
var xScale = d3.scaleBand()
.domain(d3.range(flightData.length))
.range([margin.left, width])
.round(true)
.paddingInner(0.1);
svg.selectAll("rect")
.data(flightData)
.enter()
.append("rect")
.attr("x", function(d, i) {return xScale(i);})
.attr("width", xScale.bandwidth())
.attr("y", function(d) {if (d.yValue < 0) return yScale(0); else return yScale(d.yValue);})
.attr("height", function(d) {return yScale(0) - yScale(Math.abs(d.yValue));})
.attr("fill", function(d) {if (d.yValue < 0) return "yellow"; else return "red";})
.on("mouseover", function() {
d3.select(this).attr("fill", "green")})
.on("mouseout", function(d, i) {
d3.select(this).attr("fill", function(d) {
if (d.yValue < 0)
{
return "yellow";
}
else
{
return "red";
}
})
})
.on("click", function(d) {if (chartToGenerate == "daily") getDataForGraph("detail", d.xValue, ""); else if (chartToGenerate == "detail") getDataForGraph("flight", sDate, d.xValue);})
.append("title")
.text(function(d) {if (chartToGenerate == "daily") return tipText + formatNiceDate(d.xValue); else return tipText + d.xValue;});
/* var txtElem = svg.selectAll("text")
.data(flightData)
.enter()
.append("text")
.text(function(d){return formatTime(d.xValue);})
.attr("x", function(d, i) {return xScale(i) + ((xScale.bandwidth()) / 2) - 4;})
.attr("y", function(d) {
if (d.yValue < 0)
{
return yScale(0);
}
else
{
return yScale(0);
}
})
.attr("font-family", "sans-serif")
.attr("font-size", "18px")
.attr("fill", "white"); */
var yAxisPos = d3.axisLeft()
.scale(yScale)
.tickSize(-width,0,0);
svg.append("g")
.attr("class", "yAxis")
.attr("transform", "translate(" + padding + ", 0)")
.call(yAxisPos);
svg.append("text")
.attr("x", yScale(0)-30)
.attr("y", margin.left - 30)
.text("Minutes")
.attr("text-anchor", "middle")
.attr("font-size", "20px")
.attr("fill", "steelblue")
.attr("transform", "rotate(90)");
svg.append("text")
.attr("x", (width / 2))
.attr("y", 0 - (margin.top / 2))
.attr("text-anchor", "middle")
.style("font-size", "20px")
.text(txtTitle)
.attr("font-family", "sans-serif")
.attr("fill", "steelblue");
}
}
function displayFlightInfo(data)
{
var flightInfo = "";
var flightDelay;
flightInfo = data[data.length-1].yValue.split("|");
var flightInfoLen = flightInfo.length
var flightInfoDiv = document.getElementById("flightinfo")
flightInfoDiv.innerHTML = "";
var totalTime = 0;
var delayTime = 0;
var numData = [];
for (var i = 0; i < data.length-2; i++)
{
delayTime = parseFloat(data[i].yValue);
numData[i] = delayTime
totalTime = totalTime + delayTime;
}
var aveTime = Math.round(totalTime / (data.length - 1));
var maxTime = d3.max(numData, function(d) {return d;});
var minTime = d3.min(numData, function(d) {return d;});
//
// Create the form and the fieldset that will display the flight information.
//
var flightForm = document.createElement("form");
flightForm.setAttribute("class","flightform");
var flightFldSet = document.createElement("fieldset");
var fldsetLegend = document.createElement("legend");
var txtNode = document.createTextNode("Fligh Number: " + flightInfo[flightInfoLen-1]);
fldsetLegend.appendChild(txtNode);
flightFldSet.appendChild(fldsetLegend)
//
// Create the paragraph element for the first form row.
//
var p1 = document.createElement("p");
p1.setAttribute("class", "formrow");
//
// Average delay for the year for flight number.
//
var aveLabel = document.createElement("label");
var aveText = document.createTextNode("Average Delay:");
aveLabel.appendChild(aveText);
aveLabel.setAttribute("class", "formcelllbl");
var aveInput = document.createElement("input");
aveInput.setAttribute("class", "formcellinp");
aveInput.setAttribute("value", aveTime);
p1.appendChild(aveLabel);
p1.appendChild(aveInput);
//
// Minimum delay for the year for flight number.
//
var minLabel = document.createElement("label");
var minText = document.createTextNode("Minimum Delay:");
minLabel.appendChild(minText);
minLabel.setAttribute("class", "formcelllbl");
var minInput = document.createElement("input");
minInput.setAttribute("class", "formcellinp");
minInput.setAttribute("value", minTime);
p1.appendChild(minLabel);
p1.appendChild(minInput);
//
// Maximum delay for the year for flight number.
//
var maxLabel = document.createElement("label");
var maxText = document.createTextNode("Maximum Delay:");
maxLabel.appendChild(maxText);
maxLabel.setAttribute("class", "formcelllbl");
var maxInput = document.createElement("input");
maxInput.setAttribute("class", "formcellinp");
maxInput.setAttribute("value", maxTime);
p1.appendChild(maxLabel);
p1.appendChild(maxInput);
flightFldSet.appendChild(p1);
//
// Create the paragraph element for the second form row.
//
var p2 = document.createElement("p");
p2.setAttribute("class", "formrow");
//
// Airplane tail number.
//
var tnLabel = document.createElement("label");
var tnText = document.createTextNode("Tail Number:");
tnLabel.appendChild(tnText);
tnLabel.setAttribute("class", "formcelllbl");
var tnInput = document.createElement("input");
tnInput.setAttribute("class", "formcellinp");
tnInput.setAttribute("value", flightInfo[0]);
p2.appendChild(tnLabel);
p2.appendChild(tnInput);
//
// Flight destination.
//
var destLabel = document.createElement("label");
var destText = document.createTextNode("Destination:");
destLabel.appendChild(destText);
destLabel.setAttribute("class", "formcelllbl");
var destInput = document.createElement("input");
destInput.setAttribute("class", "formcellinp");
destInput.setAttribute("value", flightInfo[1]);
p2.appendChild(destLabel);
p2.appendChild(destInput);
//
// Flight delay time.
//
var fdLabel = document.createElement("label");
var fdText = document.createTextNode("Flight Delay:");
fdLabel.appendChild(fdText);
fdLabel.setAttribute("class", "formcelllbl");
var fdInput = document.createElement("input");
fdInput.setAttribute("class", "formcellinp");
fdInput.setAttribute("value", flightInfo[2]);
p2.appendChild(fdLabel);
p2.appendChild(fdInput);
flightFldSet.appendChild(p2);
//
// Create the paragraph element for the third form row.
//
var p3 = document.createElement("p");
p3.setAttribute("class", "formrow");
//
// Carrier delay time.
//
var cdLabel = document.createElement("label");
var cdText = document.createTextNode("Carrier Delay:");
cdLabel.appendChild(cdText);
cdLabel.setAttribute("class", "formcelllbl");
var cdInput = document.createElement("input");
cdInput.setAttribute("class", "formcellinp");
cdInput.setAttribute("value", flightInfo[3]);
p3.appendChild(cdLabel);
p3.appendChild(cdInput);
//
// Weather delay time.
//
var wdLabel = document.createElement("label");
var wdText = document.createTextNode("Weather Delay:");
wdLabel.appendChild(wdText);
wdLabel.setAttribute("class", "formcelllbl");
var wdInput = document.createElement("input");
wdInput.setAttribute("class", "formcellinp");
wdInput.setAttribute("value", flightInfo[4]);
p3.appendChild(wdLabel);
p3.appendChild(wdInput);
flightFldSet.appendChild(p3);
//
// Create the paragraph element for the fourth form row.
//
var p4 = document.createElement("p");
p4.setAttribute("class", "formrow");
//
// Security delay time.
//
var sdLabel = document.createElement("label");
var sdText = document.createTextNode("Security Delay:");
sdLabel.appendChild(sdText);
sdLabel.setAttribute("class", "formcelllbl");
var sdInput = document.createElement("input");
sdInput.setAttribute("class", "formcellinp");
sdInput.setAttribute("value", flightInfo[5]);
p4.appendChild(sdLabel);
p4.appendChild(sdInput);
//
// NAS delay time.
//
var ndLabel = document.createElement("label");
var ndText = document.createTextNode("NAS Delay:");
ndLabel.appendChild(ndText);
ndLabel.setAttribute("class", "formcelllbl");
var ndInput = document.createElement("input");
ndInput.setAttribute("class", "formcellinp");
ndInput.setAttribute("value", flightInfo[6]);
p4.appendChild(ndLabel);
p4.appendChild(ndInput);
flightFldSet.appendChild(p4);
//
// Create the paragraph element for the fifth form row.
//
var p5 = document.createElement("p");
p5.setAttribute("class", "formrow");
//
// Late Aircraft delay time.
//
var laLabel = document.createElement("label");
var laText = document.createTextNode("Late Aircraft Delay:");
laLabel.appendChild(laText);
laLabel.setAttribute("class", "formcelllbl");
var laInput = document.createElement("input");
laInput.setAttribute("class", "formcellinp");
laInput.setAttribute("value", flightInfo[6]);
p5.appendChild(laLabel);
p5.appendChild(laInput);
flightFldSet.appendChild(p5);
//
// Finally append the field set to the form.
//
flightForm.appendChild(flightFldSet);
flightInfoDiv.appendChild(flightForm);
}