Skip to content

Instantly share code, notes, and snippets.

@imohitmayank
Last active March 30, 2017 07:00
Show Gist options
  • Save imohitmayank/e48bdba25ff24d12ad4a3b07cce6e575 to your computer and use it in GitHub Desktop.
Save imohitmayank/e48bdba25ff24d12ad4a3b07cce6e575 to your computer and use it in GitHub Desktop.
Single Page Calender View

A modified version of Calendar view, showing year based on node click.

date count criteria
01/04/2016 1 Medium
01/07/2016 1 Medium
01/12/2017 2 High
01/18/2016 1 Medium
01/29/2016 1 Medium
02/20/2016 1 Medium
03/07/2016 1 Medium
03/21/2016 1 Medium
03/24/2016 3 High
04/01/2016 1 Medium
04/07/2016 2 High
04/11/2016 1 Medium
04/15/2016 1 Medium
04/28/2016 1 Medium
05/03/2016 1 Medium
05/12/2016 2 High
05/19/2016 2 High
05/25/2016 1 Medium
05/26/2016 1 Medium
06/23/2016 1 Medium
06/25/2016 2 High
06/30/2016 1 Medium
07/04/2016 1 Medium
07/05/2016 1 Medium
07/06/2016 2 High
07/07/2016 1 Medium
07/13/2016 1 Medium
08/06/2016 1 Medium
08/17/2016 1 Medium
08/25/2016 1 Medium
10/01/2016 1 Medium
10/14/2016 1 Medium
11/01/2016 1 Medium
11/02/2016 2 High
11/11/2016 1 Medium
11/16/2016 1 Medium
11/24/2016 1 Medium
12/01/2016 2 High
12/02/2016 1 Medium
12/15/2016 1 Medium
12/20/2016 1 Medium
12/28/2016 1 Medium
designCalender = function(container, configurations) {
var preparedCalender = {};
var config = {
width: configurations.width,
height: configurations.height,
cellSize: (configurations.width) / 60
};
var numberOfYearsData = d3.range(configurations.startYear, configurations.endYear).length;
var svg = undefined;
var calender = undefined;
var rectangle = undefined;
var percent = d3.format(".1%");
var calendarGroup = undefined;
var switchGroup = undefined;
var outerMajorGroup = undefined;
var outerTopGroup = undefined;
var outerBottomGroup = undefined;
var leftGroup = undefined;
var rightGroup = undefined;
var defaultSwitchNodeSize = 30;
var calendarGroupHeight = configurations.height * 0.8;
var calendarGroupWidth = configurations.width;
var switchGroupHeight = configurations.height * 0.2;
var switchGroupWidth = configurations.width;
var majorGroupHeight = calendarGroupHeight * 0.6;
var majorGroupWidth = calendarGroupWidth;
var sideGroupHeight = calendarGroupHeight;
var sideGroupWidth = calendarGroupWidth * 0.1;
var topGroupHeight = calendarGroupHeight * 0.3;
var topGroupWidth = calendarGroupWidth;
var tsFormat = d3.time.format("%m/%d/%Y");
var week = d3.time.format("%U");
var month = d3.time.format("%m");
var year = d3.time.format("%Y");
var day = d3.time.format("%w");
var parseDate = d3.time.format('%m/%d/%Y').parse;
var group = undefined;
var distributionLength = undefined;
var headerString = undefined;
// var svgHeight = (config.height)*0.80;
// var svgWidth = (config.width)*0.80;
var timeseriesDistribution = configurations.distributionValues;
var text = undefined;
var color = ['#b4dfed', '#37abd1', '#04789e'];
function colourCode(d) {
var colourCode = "";
if (dataColourCode[d] === 1) {
colourCode = '#b4dfed';
} else if (dataColourCode[d] === 2) {
colourCode = '#37abd1';
} else if (dataColourCode[d] === 3) {
colourCode = '#04789e';
}
return colourCode;
}
function monthPath(t0) {
var t1 = new Date(t0.getFullYear(), t0.getMonth() + 1, 0),
d0 = t0.getDay(),
w0 = d3.time.weekOfYear(t0),
d1 = t1.getDay(),
w1 = d3.time.weekOfYear(t1);
return "M" + (w0 + 1) * config.cellSize + "," + d0 * config.cellSize +
"H" + w0 * config.cellSize + "V" + 7 * config.cellSize +
"H" + w1 * config.cellSize + "V" + (d1 + 1) * config.cellSize +
"H" + (w1 + 1) * config.cellSize + "V" + 0 +
"H" + (w0 + 1) * config.cellSize + "Z";
}
function monthTitle(t0) {
return t0.toLocaleString("en-us", {
month: "short"
});
}
svg = d3.select(container)
.append("svg")
.attr("height", "100%")
.attr("width", "100%");
// Appending gradient fill
var grads = svg.append("defs")
.append("radialGradient")
.attr("gradientUnits", "objectBoundingBox")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", "100%")
.attr("id", "gradientFill");
grads.append("stop")
.attr("offset", "0%")
.style("stop-color", "white");
grads.append("stop")
.attr("offset", "100%")
.style("stop-color", function(d) {
return "#31C0EF";
});
// Main drawing begins
calendarGroup = svg.
append('g')
.attr("width", calendarGroupWidth)
.attr("height", calendarGroupHeight)
.attr("transform", "translate(0,0)")
.selectAll("g")
.data(d3.range(configurations.startYear, configurations.endYear))
.enter()
.append("g")
.attr("id", function(d) {
return d;
})
.attr("width", "100%")
.attr("height", "100%")
.attr("transform", "translate(0,0)")
.attr("visibility", function(d) {
return d == configurations.startYear ? 'visible' : 'hidden';
});
outerTopGroup = calendarGroup.append("g")
.attr("width", topGroupWidth)
.attr("height", topGroupHeight)
.attr("transform", "translate(" + (sideGroupWidth) + "," + (0) + ")");
outerMajorGroup = calendarGroup.append("g")
.attr("width", majorGroupWidth)
.attr("height", majorGroupHeight)
.attr("transform", "translate(" + (sideGroupWidth) + "," + (topGroupHeight) + ")");
outerBottomGroup = calendarGroup.append("g")
.attr("width", topGroupWidth)
.attr("height", topGroupHeight)
.attr("transform", "translate(" + (sideGroupWidth) + "," + (topGroupHeight + majorGroupHeight) + ")");
leftGroup = calendarGroup.append("g")
.attr("width", sideGroupWidth)
.attr("height", sideGroupHeight)
.attr("transform", "translate(" + (0) + "," + (topGroupHeight) + ")");
rightGroup = calendarGroup.append("g")
.attr("width", sideGroupWidth)
.attr("height", sideGroupHeight)
.attr("transform", "translate(" + (sideGroupWidth + majorGroupWidth) + "," + (topGroupHeight) + ")");
switchGroup = svg.append("g")
.attr("width", switchGroupWidth)
.attr("height", switchGroupHeight)
.attr("transform", "translate(" + (0) + "," + (calendarGroupHeight) + ")");
var getSwitchX = function(index) {
var xOffset = (index) * (defaultSwitchNodeSize * numberOfYearsData);
return ((switchGroupWidth / 2) - (defaultSwitchNodeSize * numberOfYearsData)/2) + xOffset;
};
var switches = switchGroup.selectAll("g")
.data(d3.range(configurations.startYear, configurations.endYear))
.enter()
.append("g")
.attr("class", "calendarSwitchClass");
var switchNodes = switches
.append("circle")
.attr("r", 7)
.style("stroke", "lightgrey")
.style("fill", function(d, i) {
return d == configurations.startYear ? "url(#gradientFill)" : "white";
})
// .style("fill", "blue")
.attr("cx", function(d, i) {
return getSwitchX(i);
})
.attr("cy", function(d, i) {
return switchGroupHeight / 2;
})
var switchText = switches
.append("text")
.attr("x", function(d, i) {
return getSwitchX(i);
})
.attr("y", function(d, i) {
return (switchGroupHeight / 2) + 25;
})
.attr("text-anchor", "middle")
.attr("class","fontstyle-string")
.text(function(d) {
return d;
});
switches
.on("click", function(d) {
calendarGroup
.attr("visibility", function(v) {
return v == d ? 'visible' : 'hidden';
});
switchNodes
.style("fill", function(v) {
return d == v ? "url(#gradientFill)" : "white";
});
});
// For adding tip on mouse-hover
// var tip = d3.tip().attr('class', 'd3-tip').html(function(d) {
// return "<span>" + d + "</span>"; });
// svg.call(tip);
leftGroup.append("text")
//.attr("transform","translate("+ (sideGroupWidth/2)+"," + (config.cellSize*4)+")rotate(-90)")
.attr("transform", "translate(" + (sideGroupWidth * .25) + "," + (majorGroupHeight / 4) + ")rotate(-90)")
.attr('class', 'fontstyle-string')
.style("text-anchor", "middle")
.style("fill", "Black")
.style("font-size", "12px")
.text(function(d) {
return d;
});
rectangle = outerMajorGroup.selectAll(".day")
.data(function(d) {
return d3.time.days(new Date(d, 0, 1), new Date(d + 1, 0, 1));
})
.enter().append("rect")
.attr("class", "day")
.attr("width", config.cellSize)
.attr("height", config.cellSize)
.attr("x", function(d) {
return d3.time.weekOfYear(d) * config.cellSize;
})
.attr("y", function(d) {
return d.getDay() * config.cellSize;
})
.datum(tsFormat);
outerMajorGroup.selectAll(".month")
.data(function(d) {
return d3.time.months(new Date(d, 0, 1), new Date(d + 1, 0, 1));
})
.enter().append("path")
.attr("class", "month")
.attr("d", monthPath);
var week_days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
for (i = 0; i < week_days.length; i++) {
// console.log(i);
outerMajorGroup.append("text")
.attr("transform", "translate(-8," + config.cellSize * (i + 1) + ")")
.attr("class", "fontstyle-string")
.style("font-size", "10px")
.style("text-anchor", "end")
.attr("dy", "-.5em")
.text(function(d) {
return week_days[i];
});
}
outerTopGroup.selectAll(".month-title") // Jan, Feb, Mar and the whatnot
.data(function(d) {
return d3.time.months(new Date(d, 0, 1), new Date(d + 1, 0, 1));
})
.enter().append("text")
.text(monthTitle)
.attr("x", function(d) {
return (config.cellSize * 3) + (d3.time.weekOfYear(d) * config.cellSize);
})
.attr("y", topGroupHeight * 0.75)
.attr("class", "fontstyle-string")
.style("font-size", "12px")
.style("text-anchor", "middle")
.attr("d", monthTitle);
var dataColourCode = d3.nest()
.key(function(d) {
return tsFormat(parseDate(d.date));
})
.rollup(function(d) {
if (d[0].criteria === 'Low') {
return 1;
} else if (d[0].criteria === 'Medium') {
return 2;
} else {
return 3;
}
})
.map(timeseriesDistribution);
var dataForShow = d3.nest()
.key(function(d) {
return tsFormat(parseDate(d.date));
})
.rollup(function(d) {
// console.log(d[0].count);
return (d[0].count);
})
.map(timeseriesDistribution);
rectangle.filter(function(d) {
return d in dataColourCode;
})
.style("fill", function(d) {
return colourCode(d);
});
rectangle.append("title")
.text(function(d) {
return "Date: " + d + "\nCount: " + dataForShow[d];
});
// Adding legends to the calender
var legendCount = color.length;
var criteria = ["Low", "Medium", "High"];
var legendGroup = undefined;
legendGroup = outerBottomGroup.selectAll(".legend")
.data(criteria)
.enter().append("g")
// .attr("class", "legend")
.append("g");
legendGroup.append("rect") // make a matching color rect
.attr("width", 12)
.attr("height", 12)
.style("fill", function(d, i) {
return color[i];
})
.style("stroke", function(d, i) {
return color[i];
})
// .style("class","fontstyle-string")
.attr("transform", function(d, i) {
return "translate(" + (topGroupWidth * 0.20 * (i + 1)) + "," + (0) + ")";
});
legendGroup.append("text")
.attr("class", "fontstyle-string")
.style('text-anchor', 'start')
.text(function(d, i) {
return criteria[i];
})
.attr("transform", function(d, i) {
return "translate(" + (topGroupWidth * 0.20 * (i + 1) + config.cellSize * 2) + "," + (10) + ")";
});
headerString = outerTopGroup.append("text")
.text(configurations.stringValue)
.attr("transform", "translate(" + (topGroupWidth / 2 - sideGroupWidth) + "," + (topGroupHeight * 0.35) + ")")
// .attr("transform", "translate(" + (topGroupWidth / 2 - sideGroupWidth / 2) + "," + (topGroupHeight * 0.35) + ")")
.attr('class', 'fontstyle-Headerstring');
// .style("text-anchor","middle")
// .style("fill","Black")
// .style("font-size","12px");
}
getCalender = function(calenderPanelId, distributionValues, stringValue) {
//Input TS FORMAT : mm/dd/yyyy
var width = d3.select("#" + calenderPanelId).style("width").replace(/px$/, "");
var height = d3.select("#" + calenderPanelId).style("height").replace(/px$/, "");
var tsFormat = d3.time.format("%m/%d/%Y").parse;
distributionValues1 = distributionValues.map(function(d) {
return tsFormat(d.date);
});
// distributionValues1 = distributionValues.map(function(d){ return new Date(d.date); });
var minDate = d3.min(distributionValues1);
var maxDate = d3.max(distributionValues1);
var startYear = minDate.getFullYear();
var endYear = maxDate.getFullYear() + 1;
var configurations = {
distributionValues: distributionValues,
startYear: startYear,
endYear: endYear,
width: parseFloat(width),
height: parseFloat(height),
stringValue: stringValue
};
designCalender("#" + calenderPanelId, configurations);
}
d3.csv("calendar.csv", function(data){
getCalender("container", data, "Calendar");
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" type="text/css" href="styleCalendar.css">
</head>
<body>
<div id= "container"></div>
<!-- Libs -->
<script src="https://d3js.org/d3.v3.js"></script>
<!-- D3 Element -->
<script src="calendar.js"></script>
</body>
</html>
html, body{
width: 100%;
height: 100%;
}
.day {
fill: #fff;
stroke: #ccc;
}
.month {
fill: none;
stroke: #000;
stroke-width: 2px;
}
#container{
width: 100%;
height: 100%;
}
.switchClass{
cursor: pointer;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment