|
|
|
@ -31,7 +31,8 @@ |
|
|
|
|
////////////////////////////////////////////////////
|
|
|
|
|
// DEFAULT INTERFACE BUILDING
|
|
|
|
|
var myHouse = PROJECTS.items[myNumber]; |
|
|
|
|
|
|
|
|
|
var myHouseXname = PROJECTS.items[myNumber].xname; |
|
|
|
|
cl(myHouseXname); |
|
|
|
|
document.getElementById("h1_title").innerHTML = h1_title; |
|
|
|
|
document.getElementById("subtitle").innerHTML = subtitle; |
|
|
|
|
|
|
|
|
@ -262,7 +263,7 @@ document.getElementById("HDParameter").innerHTML = listParametersOptions; |
|
|
|
|
var family = document.getElementById("PDFamSensor").value; |
|
|
|
|
var type = document.getElementById("PDParameter").value;
|
|
|
|
|
// Building API query
|
|
|
|
|
var apiUrl = "parallel/daily?family="+family+"&type="+type+"&day="+day; |
|
|
|
|
var apiUrl = "parallel/daily?hus="+myHouseXname+"&family="+family+"&type="+type+"&day="+day; |
|
|
|
|
makeApiRequest(formId, apiUrl, myid, myTitle, family, type, day); |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
@ -276,7 +277,7 @@ document.getElementById("HDParameter").innerHTML = listParametersOptions; |
|
|
|
|
var myTitle = document.getElementById("PWTitle").value; |
|
|
|
|
var type = document.getElementById("PWParameter").value; |
|
|
|
|
// BUILDING API query
|
|
|
|
|
var apiUrl = "parallel/weekly?family="+family+"&type="+type+"&year="+year+"&week="+week;
|
|
|
|
|
var apiUrl = "parallel/weekly?hus="+myHouseXname+"&family="+family+"&type="+type+"&year="+year+"&week="+week;
|
|
|
|
|
makeApiRequest(formId, apiUrl, myid, myTitle, family, type, year, week); |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
@ -290,7 +291,7 @@ document.getElementById("HDParameter").innerHTML = listParametersOptions; |
|
|
|
|
var myTitle = document.getElementById("PMTitle").value; |
|
|
|
|
var type = document.getElementById("PMParameter").value; |
|
|
|
|
// BUILDING API query
|
|
|
|
|
var apiUrl = "parallel/monthly?family="+family+"&type="+type+"&year="+year+"&month="+month; |
|
|
|
|
var apiUrl = "parallel/monthly?hus="+myHouseXname+"&family="+family+"&type="+type+"&year="+year+"&month="+month; |
|
|
|
|
makeApiRequest(formId, apiUrl, myid, myTitle, family, type, year, month) |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
@ -301,7 +302,7 @@ document.getElementById("HDParameter").innerHTML = listParametersOptions; |
|
|
|
|
var myTitle = document.getElementById("PYTitle").value; |
|
|
|
|
var type = document.getElementById("PYParameter").value; |
|
|
|
|
// BUILDING API query
|
|
|
|
|
var apiUrl = "parallel/yearly?family="+family+"&type="+type+"&year="+year; |
|
|
|
|
var apiUrl = "parallel/yearly?hus="+myHouseXname+"&family="+family+"&type="+type+"&year="+year; |
|
|
|
|
makeApiRequest(formId, apiUrl, myid, myTitle, family, type, year) |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
@ -321,7 +322,7 @@ document.getElementById("HDParameter").innerHTML = listParametersOptions; |
|
|
|
|
var sensor = document.getElementById("GWSensor").value; |
|
|
|
|
var type = document.getElementById("GWParameter").value; |
|
|
|
|
// BUILDING API query
|
|
|
|
|
var apiUrl = "grid/weekly?sensor="+sensor+"&type="+type+"&year="+year+"&week="+week;
|
|
|
|
|
var apiUrl = "grid/weekly?hus="+myHouseXname+"&sensor="+sensor+"&type="+type+"&year="+year+"&week="+week;
|
|
|
|
|
makeApiRequest(formId, apiUrl, myid, myTitle, sensor, type, inDate); |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
@ -334,7 +335,7 @@ document.getElementById("HDParameter").innerHTML = listParametersOptions; |
|
|
|
|
var sensor = document.getElementById("GMSensor").value; |
|
|
|
|
var type = document.getElementById("GMParameter").value; |
|
|
|
|
// BUILDING API query
|
|
|
|
|
var apiUrl = "grid/monthly?sensor="+sensor+"&type="+type+"&year="+year+"&month="+month;
|
|
|
|
|
var apiUrl = "grid/monthly?hus="+myHouseXname+"&sensor="+sensor+"&type="+type+"&year="+year+"&month="+month;
|
|
|
|
|
makeApiRequest(formId, apiUrl, myid, myTitle, sensor, type, year, month); |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
@ -344,7 +345,7 @@ document.getElementById("HDParameter").innerHTML = listParametersOptions; |
|
|
|
|
var year = document.getElementById("GYYear").value; |
|
|
|
|
var sensor = document.getElementById("GYSensor").value; |
|
|
|
|
var type = document.getElementById("GYParameter").value; |
|
|
|
|
var apiUrl = "grid/monthly?sensor="+sensor+"&type="+type+"&year="+year;
|
|
|
|
|
var apiUrl = "grid/yearly?hus="+myHouseXname+"&sensor="+sensor+"&type="+type+"&year="+year;
|
|
|
|
|
makeApiRequest(formId, apiUrl, myid, myTitle, sensor, type, year); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
@ -369,7 +370,7 @@ document.getElementById("HDParameter").innerHTML = listParametersOptions; |
|
|
|
|
var family = document.getElementById("HWFamSensor").value; |
|
|
|
|
var type = document.getElementById("HYParameter").value; |
|
|
|
|
// BUILDING API query
|
|
|
|
|
var apiUrl = "horizon/monthly?family="+family+"&type="+type+"&day="+day;
|
|
|
|
|
var apiUrl = "horizon/dayly?hus="+myHouseXname+"&family="+family+"&type="+type+"&day="+day;
|
|
|
|
|
makeApiRequest(formId, apiUrl, myid, myTitle, family, type, year); |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
@ -385,7 +386,7 @@ document.getElementById("HDParameter").innerHTML = listParametersOptions; |
|
|
|
|
var family = document.getElementById("HWFamSensor").value; |
|
|
|
|
var type = document.getElementById("HWParameter").value; |
|
|
|
|
// BUILDING API query
|
|
|
|
|
var apiUrl = "horizon/monthly?family="+family+"&type="+type+"&year="+year+"&week="+week; |
|
|
|
|
var apiUrl = "horizon/weekly?hus="+myHouseXname+"&family="+family+"&type="+type+"&year="+year+"&week="+week; |
|
|
|
|
makeApiRequest(formId, apiUrl, myid, myTitle, family, type, year, week); |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
@ -398,7 +399,7 @@ document.getElementById("HDParameter").innerHTML = listParametersOptions; |
|
|
|
|
var family = document.getElementById("HMFamSensor").value; |
|
|
|
|
var type = document.getElementById("HMParameter").value; |
|
|
|
|
// BUILDING API query
|
|
|
|
|
var apiUrl = "horizon/monthly?family="+family+"&type="+type+"&year="+year+"&month="+month;
|
|
|
|
|
var apiUrl = "horizon/monthly?hus="+myHouseXname+"&family="+family+"&type="+type+"&year="+year+"&month="+month;
|
|
|
|
|
makeApiRequest(formId, apiUrl, myid, myTitle, family, type, year, month); |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -410,7 +411,7 @@ document.getElementById("HDParameter").innerHTML = listParametersOptions; |
|
|
|
|
var family = document.getElementById("HYFamSensor").value; |
|
|
|
|
var type = document.getElementById("HYParameter").value; |
|
|
|
|
// BUILDING API query
|
|
|
|
|
var apiUrl = "horizon/monthly?family="+family+"&type="+type+"&year="+year; |
|
|
|
|
var apiUrl = "horizon/yearly?hus="+myHouseXname+"&family="+family+"&type="+type+"&year="+year; |
|
|
|
|
makeApiRequest(formId, apiUrl, myid, myTitle, family, type, year); |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -440,6 +441,7 @@ document.getElementById("HDParameter").innerHTML = listParametersOptions; |
|
|
|
|
|
|
|
|
|
// Parallel
|
|
|
|
|
function do_parallel(myid, myxs, mycolumns, inMyTitle) { |
|
|
|
|
cl(myxs); |
|
|
|
|
c3.generate({ |
|
|
|
|
bindto: myid, |
|
|
|
|
data: { |
|
|
|
@ -609,6 +611,13 @@ function do_grid_weekly(myid, startingDate, data) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// GRID MONTHLY d3 diagram
|
|
|
|
|
|
|
|
|
|
function getMonth(monthNumber) { |
|
|
|
|
const date = d3.timeParse("%m")(monthNumber); |
|
|
|
|
const monthName = d3.timeFormat("%B")(date); |
|
|
|
|
return monthName; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function do_grid_monthly(myid, month, year, data, apiUrl) { |
|
|
|
|
const margin = { top: 60, right: 20, bottom: 20, left: 20 }; |
|
|
|
|
const cellSize = 35; |
|
|
|
@ -643,8 +652,8 @@ function do_grid_monthly(myid, month, year, data, apiUrl) { |
|
|
|
|
.enter().append("rect") |
|
|
|
|
.attr("width", cellSize) |
|
|
|
|
.attr("height", cellSize) |
|
|
|
|
.attr("x", (d, i) => (i % 7) * cellSize) |
|
|
|
|
.attr("y", (d, i) => Math.floor(i / 7) * cellSize) |
|
|
|
|
.attr("x", (d, i) => ((i + getDayOffset(month, year)) % 7) * cellSize) |
|
|
|
|
.attr("y", (d, i) => Math.floor((i + getDayOffset(month, year)) / 7) * cellSize) |
|
|
|
|
.attr("fill", d => colorScale(d)) // Apply the color scale to data values
|
|
|
|
|
.on("mouseover", function (d) { |
|
|
|
|
// Show the tooltip on hover
|
|
|
|
@ -666,13 +675,13 @@ function do_grid_monthly(myid, month, year, data, apiUrl) { |
|
|
|
|
.data(numericData) |
|
|
|
|
.enter().append("text") |
|
|
|
|
.attr("class", "day-number") |
|
|
|
|
.attr("x", (d, i) => (i % 7) * cellSize + cellSize / 2) |
|
|
|
|
.attr("y", (d, i) => Math.floor(i / 7) * cellSize + cellSize / 2) |
|
|
|
|
.attr("x", (d, i) => ((i + getDayOffset(month, year)) % 7) * cellSize + cellSize / 2) |
|
|
|
|
.attr("y", (d, i) => Math.floor((i + getDayOffset(month, year)) / 7) * cellSize + cellSize / 2) |
|
|
|
|
.attr("text-anchor", "middle") |
|
|
|
|
.attr("alignment-baseline", "middle") |
|
|
|
|
.text((d, i) => i + 1); |
|
|
|
|
|
|
|
|
|
const weekDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; |
|
|
|
|
const weekDays = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; |
|
|
|
|
svg.selectAll(".weekday") |
|
|
|
|
.data(weekDays) |
|
|
|
|
.enter().append("text") |
|
|
|
@ -682,13 +691,36 @@ function do_grid_monthly(myid, month, year, data, apiUrl) { |
|
|
|
|
.attr("text-anchor", "middle") |
|
|
|
|
.text((d) => d); |
|
|
|
|
|
|
|
|
|
const firstDayOfMonth = new Date(year, month - 1, 1); |
|
|
|
|
const dayOffset = (firstDayOfMonth.getDay() + 6) % 7; // Calculate the day offset for the first day of the month
|
|
|
|
|
const monthName = getMonth(month); |
|
|
|
|
svg.append("text") |
|
|
|
|
.attr("class", "year-label") |
|
|
|
|
.attr("x", width) |
|
|
|
|
.attr("y", -30) |
|
|
|
|
.attr("text-anchor", "end") |
|
|
|
|
.text("December " + year); |
|
|
|
|
} |
|
|
|
|
.text(monthName + ", " + year); |
|
|
|
|
|
|
|
|
|
function getDayOffset(month, year) { |
|
|
|
|
const firstDayOfMonth = new Date(year, month - 1, 1); |
|
|
|
|
const dayOffset = (firstDayOfMonth.getDay() + 6) % 7; // Calculate the day offset for the first day of the month
|
|
|
|
|
return dayOffset; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function getMonth(month) { |
|
|
|
|
const months = [ |
|
|
|
|
"January", "February", "March", "April", "May", "June", |
|
|
|
|
"July", "August", "September", "October", "November", "December" |
|
|
|
|
]; |
|
|
|
|
return months[month - 1]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -697,7 +729,6 @@ function do_grid_monthly(myid, month, year, data, apiUrl) { |
|
|
|
|
|
|
|
|
|
//--------------------------------
|
|
|
|
|
// GRID YEARLY d3 diagram
|
|
|
|
|
|
|
|
|
|
function do_grid_yearly(myid, year, myData) { |
|
|
|
|
// Remove the existing SVG if it exists
|
|
|
|
|
d3.select(`#${myid} svg`).remove(); |
|
|
|
@ -742,6 +773,179 @@ function do_grid_yearly(myid, year, myData) { |
|
|
|
|
const maxValue = Math.max(...myData); |
|
|
|
|
const valueRange = maxValue - minValue; |
|
|
|
|
|
|
|
|
|
// Create a color scale based on the min, max, and range of values
|
|
|
|
|
const colorScale = d3.scaleLinear() |
|
|
|
|
.domain([minValue, maxValue]) |
|
|
|
|
.range(["#eff3ff", "#08519c"]); // Specify the range of colors
|
|
|
|
|
|
|
|
|
|
// Create a group for month labels
|
|
|
|
|
const monthLabelsGroup = svg.append("g") |
|
|
|
|
.attr("id", "month-labels"); |
|
|
|
|
|
|
|
|
|
// Function to handle mouseover event and display tooltip
|
|
|
|
|
function handleMouseover(day, value) { |
|
|
|
|
// Show the tooltip on hover
|
|
|
|
|
tooltip |
|
|
|
|
.style("left", (d3.event.pageX + 10) + "px") |
|
|
|
|
.style("top", (d3.event.pageY - 10) + "px") |
|
|
|
|
.style("background-color", "#c3c3c3") |
|
|
|
|
.style("opacity", 1) |
|
|
|
|
.html(`Value: ${value}`); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Create a tooltip element
|
|
|
|
|
const tooltip = d3.select("body") |
|
|
|
|
.append("div") |
|
|
|
|
.attr("class", "tooltip") |
|
|
|
|
.style("opacity", 0); |
|
|
|
|
|
|
|
|
|
// Loop through each month and create the calendar heatmap
|
|
|
|
|
for (let i = 0; i < months.length; i++) { |
|
|
|
|
const month = months[i]; |
|
|
|
|
// Calculate row and column positions
|
|
|
|
|
const row = Math.floor(i / columns); |
|
|
|
|
const col = i % columns; |
|
|
|
|
|
|
|
|
|
// Starting positions for months
|
|
|
|
|
const x = col * cellWidth + borderWidth; |
|
|
|
|
const y = row * cellHeight + borderWidth; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Calculate the y position for each month label
|
|
|
|
|
const monthLabelY = y + 20 + (row * 20); // Add 20px margin top for each row
|
|
|
|
|
|
|
|
|
|
// Month Label
|
|
|
|
|
const monthLabel = monthLabelsGroup.append("text") |
|
|
|
|
.attr("x", x + cellWidth / 2) |
|
|
|
|
.attr("y", monthLabelY) |
|
|
|
|
.attr("font-size", "18") |
|
|
|
|
.attr("text-anchor", "middle") |
|
|
|
|
.text(`${month.name} ${year}`); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Weekday labels
|
|
|
|
|
const weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; |
|
|
|
|
|
|
|
|
|
for (let w = 0; w < weekdays.length; w++) { |
|
|
|
|
const weekdayLabel = svg.append("text") |
|
|
|
|
.attr("x", x + (w * (cellWidth / 7)) + cellWidth / 14) |
|
|
|
|
.attr("y", y + 55) // Increased vertical position
|
|
|
|
|
.attr("font-size", "12") |
|
|
|
|
.attr("text-anchor", "middle") |
|
|
|
|
.text(weekdays[w]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Calculate the y position for each border rectangle
|
|
|
|
|
const borderY = y + 30 + (row * 20); // Add 20px margin top for each row
|
|
|
|
|
|
|
|
|
|
// Create a border around the month
|
|
|
|
|
const border = svg.append("rect") |
|
|
|
|
.attr("x", x) |
|
|
|
|
.attr("y", borderY) |
|
|
|
|
.attr("width", cellWidth - 2 * borderWidth) |
|
|
|
|
.attr("height", cellHeight - 10) // Decreased height to fit the day rectangles
|
|
|
|
|
.attr("fill", "none") |
|
|
|
|
.attr("stroke", "black") |
|
|
|
|
.attr("stroke-width", borderWidth); |
|
|
|
|
|
|
|
|
|
// Calculate the number of weeks in the month
|
|
|
|
|
const numWeeks = Math.ceil(month.days / 7); |
|
|
|
|
|
|
|
|
|
// Loop through each week and create the day rectangles
|
|
|
|
|
for (let week = 0; week < numWeeks; week++) { |
|
|
|
|
for (let day = 0; day < 7; day++) { |
|
|
|
|
const dayNumber = week * 7 + day + 1; // Calculate the day number
|
|
|
|
|
|
|
|
|
|
// Calculate the x and y positions for each day rectangle
|
|
|
|
|
const rectX = x + (day * (cellWidth / 7)); |
|
|
|
|
const rectY = y + 30 + ((week + 1) * (cellHeight / numWeeks)); |
|
|
|
|
|
|
|
|
|
// Calculate the value index for the current day
|
|
|
|
|
const valueIndex = (i * month.days) + (week * 7) + day; |
|
|
|
|
|
|
|
|
|
// Get the value for the current day
|
|
|
|
|
const value = myData[valueIndex]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Calculate the color based on the value
|
|
|
|
|
const color = colorScale(value); |
|
|
|
|
|
|
|
|
|
// Create the day rectangle
|
|
|
|
|
const rect = svg.append("rect") |
|
|
|
|
.attr("x", rectX) |
|
|
|
|
.attr("y", rectY) |
|
|
|
|
.attr("width", cellWidth / 7) |
|
|
|
|
.attr("height", cellHeight / numWeeks) |
|
|
|
|
.attr("fill", value ? color : "white") // Set white background for empty values
|
|
|
|
|
.attr("stroke", "none") |
|
|
|
|
.on("mouseover", () => handleMouseover(dayNumber, value)) |
|
|
|
|
.on("mouseout", () => tooltip.style("opacity", 0)); |
|
|
|
|
|
|
|
|
|
// Add the day number as text inside the day rectangle
|
|
|
|
|
const dayText = svg.append("text") |
|
|
|
|
.attr("x", rectX + (cellWidth / 14)) |
|
|
|
|
.attr("y", rectY + (cellHeight / (2 * numWeeks))) |
|
|
|
|
.attr("font-size", "12") |
|
|
|
|
.attr("text-anchor", "middle") |
|
|
|
|
.text(dayNumber); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function do_grid_yearlyXX(myid, year, myData) { |
|
|
|
|
// Remove the existing SVG if it exists
|
|
|
|
|
d3.select(`#${myid} svg`).remove(); |
|
|
|
|
|
|
|
|
|
// For demonstration purposes, let's create a simple SVG rectangle
|
|
|
|
|
const svg = d3.select(`#${myid}`).append("svg") |
|
|
|
|
.attr("width", 800) |
|
|
|
|
.attr("height", 650); // Increased height for a taller diagram
|
|
|
|
|
|
|
|
|
|
// Append the 'months' group inside the SVG
|
|
|
|
|
const monthsGroup = svg.append("g") |
|
|
|
|
.attr("id", "months"); |
|
|
|
|
|
|
|
|
|
const months = [ |
|
|
|
|
{ name: 'January', days: 31 }, |
|
|
|
|
{ name: 'February', days: 28 }, |
|
|
|
|
{ name: 'March', days: 31 }, |
|
|
|
|
{ name: 'April', days: 30 }, |
|
|
|
|
{ name: 'May', days: 31 }, |
|
|
|
|
{ name: 'June', days: 30 }, |
|
|
|
|
{ name: 'July', days: 31 }, |
|
|
|
|
{ name: 'August', days: 31 }, |
|
|
|
|
{ name: 'September', days: 30 }, |
|
|
|
|
{ name: 'October', days: 31 }, |
|
|
|
|
{ name: 'November', days: 30 }, |
|
|
|
|
{ name: 'December', days: 31 }, |
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
// Number of columns and rows
|
|
|
|
|
const columns = 4; |
|
|
|
|
const rows = 5; // Increased rows for more vertical space
|
|
|
|
|
|
|
|
|
|
// Calculate cell width and height
|
|
|
|
|
const cellWidth = 660 / columns; |
|
|
|
|
const cellHeight = (800 / rows); // Increased cell height to 40px per month
|
|
|
|
|
|
|
|
|
|
// Border width
|
|
|
|
|
const borderWidth = 1; |
|
|
|
|
|
|
|
|
|
// Calculate min and max values for the color scale
|
|
|
|
|
const minValue = Math.min(...myData); |
|
|
|
|
const maxValue = Math.max(...myData); |
|
|
|
|
const valueRange = maxValue - minValue; |
|
|
|
|
|
|
|
|
|
// Create a color scale based on the min, max, and range of values
|
|
|
|
|
const colorScale = d3.scaleLinear() |
|
|
|
|
.domain([minValue, maxValue]) |
|
|
|
@ -800,7 +1004,7 @@ function do_grid_yearly(myid, year, myData) { |
|
|
|
|
// Calendar Days
|
|
|
|
|
for (let day = 1; day <= month.days; day++) { |
|
|
|
|
// Get the value for the current day
|
|
|
|
|
const value = myData[day - 1]; // Subtract 1 because array index starts from 0
|
|
|
|
|
const value = myData[month.days * i + day - 1]; // Calculate index based on month and day
|
|
|
|
|
|
|
|
|
|
// Calculate the color based on the value
|
|
|
|
|
const color = d3.interpolateViridis(colorScale(value)); |
|
|
|
@ -819,7 +1023,7 @@ function do_grid_yearly(myid, year, myData) { |
|
|
|
|
.attr("stroke", "#ffffff") // white border
|
|
|
|
|
.attr("class", "day") |
|
|
|
|
.on("mouseover", () => { |
|
|
|
|
const dayValue = myData[day - 1]; // Subtract 1 because array index starts from 0
|
|
|
|
|
const dayValue = myData[month.days * i + day - 1]; // Calculate index based on month and day
|
|
|
|
|
// Call the handleMouseover function with the correct value
|
|
|
|
|
handleMouseover(day, dayValue); |
|
|
|
|
}) |
|
|
|
@ -827,9 +1031,97 @@ function do_grid_yearly(myid, year, myData) { |
|
|
|
|
tooltip.style("opacity", 0); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
// Weekday labels
|
|
|
|
|
const weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; |
|
|
|
|
|
|
|
|
|
// Loop through each month and create the calendar heatmap
|
|
|
|
|
for (let i = 0; i < months.length; i++) { |
|
|
|
|
const month = months[i]; |
|
|
|
|
// Calculate row and column positions
|
|
|
|
|
const row = Math.floor(i / columns); |
|
|
|
|
const col = i % columns; |
|
|
|
|
|
|
|
|
|
// Starting positions for months
|
|
|
|
|
const x = col * cellWidth + borderWidth; |
|
|
|
|
const y = row * cellHeight + borderWidth; |
|
|
|
|
|
|
|
|
|
// Month Label
|
|
|
|
|
const monthLabel = monthLabelsGroup.append("text") |
|
|
|
|
.attr("x", x + cellWidth / 2) |
|
|
|
|
.attr("y", y + 20) // Increased vertical position
|
|
|
|
|
.attr("font-size", "18") |
|
|
|
|
.attr("text-anchor", "middle") |
|
|
|
|
.text(`${month.name} ${year}`); |
|
|
|
|
|
|
|
|
|
// Weekday labels
|
|
|
|
|
for (let w = 0; w < weekdays.length; w++) { |
|
|
|
|
const weekdayLabel = svg.append("text") |
|
|
|
|
.attr("x", x + (w * (cellWidth / 7)) + cellWidth / 14) |
|
|
|
|
.attr("y", y + 55) // Increased vertical position
|
|
|
|
|
.attr("font-size", "12") |
|
|
|
|
.attr("text-anchor", "middle") |
|
|
|
|
.text(weekdays[w]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Create a border around the month
|
|
|
|
|
const border = svg.append("rect") |
|
|
|
|
.attr("x", x) |
|
|
|
|
.attr("y", y + 30) // Increased vertical position
|
|
|
|
|
.attr("width", cellWidth - 2 * borderWidth) |
|
|
|
|
.attr("height", cellHeight - 2 * borderWidth - 30) // Adjusted height to avoid overlap
|
|
|
|
|
.attr("fill", "none") |
|
|
|
|
.attr("stroke", "#ffffff") // Border
|
|
|
|
|
.attr("stroke-width", borderWidth); |
|
|
|
|
|
|
|
|
|
// Calendar Days
|
|
|
|
|
for (let day = 1; day <= month.days; day++) { |
|
|
|
|
// Get the value for the current day
|
|
|
|
|
const value = myData[month.days * i + day - 1]; // Calculate index based on month and day
|
|
|
|
|
|
|
|
|
|
// Calculate the color based on the value
|
|
|
|
|
const color = d3.interpolateViridis(colorScale(value)); |
|
|
|
|
|
|
|
|
|
// Calculate the position of the current day
|
|
|
|
|
const dayRow = Math.floor((day - 1) / 7); |
|
|
|
|
const dayCol = (day - 1) % 7; |
|
|
|
|
|
|
|
|
|
// Create a rectangle for each day
|
|
|
|
|
svg.append("rect") |
|
|
|
|
.attr("x", x + (dayCol * (cellWidth / 7))) |
|
|
|
|
.attr("y", y + 60 + (dayRow * (cellHeight / 6))) // Increased vertical position
|
|
|
|
|
.attr("width", cellWidth / 7) |
|
|
|
|
.attr("height", cellHeight / 6) |
|
|
|
|
.attr("fill", color) |
|
|
|
|
.attr("stroke", "#ffffff") // white border
|
|
|
|
|
.attr("class", "day") |
|
|
|
|
.on("mouseover", () => { |
|
|
|
|
const dayValue = myData[month.days * i + day - 1]; // Calculate index based on month and day
|
|
|
|
|
// Call the handleMouseover function with the correct value
|
|
|
|
|
handleMouseover(day, dayValue); |
|
|
|
|
}) |
|
|
|
|
.on("mouseout", () => { |
|
|
|
|
tooltip.style("opacity", 0); |
|
|
|
|
}) |
|
|
|
|
.append("text") // Add text to display the day number
|
|
|
|
|
.attr("x", x + (dayCol * (cellWidth / 7)) + cellWidth / 14) |
|
|
|
|
.attr("y", y + 85 + (dayRow * (cellHeight / 6))) // Increased vertical position
|
|
|
|
|
.attr("font-size", "12") |
|
|
|
|
.attr("text-anchor", "middle") |
|
|
|
|
.text(day); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1530,7 +1822,7 @@ function makeApiRequest(formId, apiUrl, myid, myTitle, ...args) { |
|
|
|
|
do_grid_weekly(myid, inDate, data[2]); |
|
|
|
|
break;
|
|
|
|
|
case "GM": |
|
|
|
|
do_grid_monthly(myid, week, month, data[2], apiUrl);
|
|
|
|
|
do_grid_monthly(myid, month, year, data[2], apiUrl);
|
|
|
|
|
break;
|
|
|
|
|
case "GY": |
|
|
|
|
do_grid_yearly(myid, year, data[2]);
|
|
|
|
|