Use Javascsript in particular D3.js in Jekyll bookstrap and Markdown syntax.
Jekyll is a fantastic tool to make a personal blog. See my blog here and there to get a quick start of using Jekyll to set up you blog and get addition supports e.g., Latex and Emoji. A typical Jekyll website or blog is quite often hosted in Github and with a domain name purchased from e.g., Namecheap.com. My website and blog follow exactly the same setup.
Markdown allows you to write a easy-to-read and easy-to-write plain text format which is later rendered into HTML. The language is support in e.g., Github and Jekyll. Or, you would love to use markdown syntax to write blogs in Jekyll :laughing:
Working with data science, I usually come with the problem of showing a plot on my website after I have collected some data or done some analysis. In particular, rendering an image on standard HTML is not very difficult and can be achieved by using some Javascript eg., D3.js
. However, when working with markdown, it starts to get a bit complicated. This is because you first write everything in markdown syntax and it is then rendered into HTML.
Here I will introduce the technologies and ticks to make the calendar view of data shown in Jekyll markdown syntax with D3.js
.
I have collected all my exercises data in json
format including date and amount of exercises I did for each particular date. A part of data is shown in the following block.
var sessions = [
{'date': '2015-11-11', 'pull_up': 40, 'push_up': 0 , 'ab_wheel_roll': 0 , 'bar_dip': 60 , 'gym': 1, 'arm': 0 , 'shoulder': 0 , 'bouldering': 0 },
{'date': '2015-10-30', 'pull_up': 50, 'push_up': 70 , 'ab_wheel_roll': 0 , 'bar_dip': 0 , 'gym': 1, 'arm': 0 , 'shoulder': 0 , 'bouldering': 0 },
{'date': '2015-10-27', 'pull_up': 0, 'push_up': 150 , 'ab_wheel_roll': 0 , 'bar_dip': 0 , 'gym': 0, 'arm': 0 , 'shoulder': 0 , 'bouldering': 0 },
...
{'date': '2015-05-08', 'pull_up': 20, 'push_up': 100 , 'ab_wheel_roll': 0 , 'bar_dip': 0 , 'gym': 0, 'arm': 0 , 'shoulder': 0 , 'bouldering': 0 },
];
D3.js
.First add d3.js
interpreter into markdown file.
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
The most important thing here is to write your Javascript within the environment shown as follows so that markdown interpreter will understant the script.
<example>
<script>
...
</script>
</example>
In addition, in your Javascript, you should initialize an object by selecting the environment you have defined. For example, in the above case, you should select example
.
With the following Javascript, a table will be printed on the screen with the JSON data we have defined in the very beginning.
```javascript
- Basically, you need to define a object to be rendered on `example2` and render the table with `tabulate` function.
### Calendar view of the JSON data
- With the following Javascript, you will be able to render a calendar view of the JSON data.
```javascript
<example1>
<script type="text/javascript">
var sessions = ....
/*-----------------------------*/
var width = 700,
height = 400,
cellSize = 13; // cell size
var no_months_in_a_row = Math.floor(width / (cellSize * 7 + 50));
var shift_up = cellSize * 3;
var day = d3.time.format("%w"), // day of the week
day_of_month = d3.time.format("%e") // day of the month
day_of_year = d3.time.format("%j")
week = d3.time.format("%U"), // week number of the year
month = d3.time.format("%m"), // month number
year = d3.time.format("%Y"),
percent = d3.format(".1%"),
format = d3.time.format("%Y-%m-%d");
var color = d3.scale.linear().range(["white", 'red']).domain([0, 350])
var dateParse = d3.time.format("%Y-%m-%d");
var svg = d3.select("example1").selectAll("svg")
.data(d3.range(2015, 2016))
.enter().append("svg")
.attr("width", width)
.attr("height", height)
.attr("class", "RdYlGn")
.append("g")
svg.append("text")
.attr("transform", "translate(-6," + cellSize * 3.5 + ")rotate(-90)")
.style("text-anchor", "middle")
.text(function(d) { return d; });
var rect = svg.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", cellSize)
.attr("height", cellSize)
.attr("x", function(d) {
var month_padding = 1.2 * cellSize*7 * ((month(d)-1) % (no_months_in_a_row));
return day(d) * cellSize + month_padding;
})
.attr("y", function(d) {
var week_diff = week(d) - week(new Date(year(d), month(d)-1, 1) );
var row_level = Math.ceil(month(d) / (no_months_in_a_row));
return (week_diff*cellSize) + row_level*cellSize*8 - cellSize/2 - shift_up;
})
.datum(format);
var month_titles = svg.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, i) {
var month_padding = 1.2 * cellSize*7* ((month(d)-1) % (no_months_in_a_row));
return month_padding;
})
.attr("y", function(d, i) {
var week_diff = week(d) - week(new Date(year(d), month(d)-1, 1) );
var row_level = Math.ceil(month(d) / (no_months_in_a_row));
return (week_diff*cellSize) + row_level*cellSize*8 - cellSize - shift_up;
})
.attr("class", "month-title")
.attr("d", monthTitle);
var year_titles = svg.selectAll(".year-title") // Jan, Feb, Mar and the whatnot
.data(function(d) {
return d3.time.years(new Date(d, 0, 1), new Date(d + 1, 0, 1)); })
.enter().append("text")
.text(yearTitle)
.attr("x", function(d, i) { return width/2 - 100; })
.attr("y", function(d, i) { return cellSize*5.5 - shift_up; })
.attr("class", "year-title")
.attr("d", yearTitle);
var tooltip = d3.select("body")
.append("div").attr("id", "tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.text("a simple tooltip");
d3.json("", function(error, data) {
sessions.forEach(function(d) {
d.dd = format(dateParse.parse(d.date));
});
var nest = d3.nest()
.key(function(d) { return d.dd; })
.map(sessions);
rect.filter(function(d) { return d in nest; })
.attr("class", function(d) { return "day"; })
.style("fill", function(d) { return color(nest[d][0].pull_up+nest[d][0].push_up+nest[d][0].ab_wheel_roll+nest[d][0].bar_dip+nest[d][0].arm+nest[d][0].shoulder); })
// Tooltip
rect.on("mouseover", mouseover);
rect.on("mouseout", mouseout);
function mouseover(d) {
tooltip.style("visibility", "visible");
var textcontent = (nest[d] !== undefined) ? "\n pull up:\t\t" + nest[d][0].pull_up + "\n push up:\t\t" + nest[d][0].push_up + "\n ab wheel roll:\t" + nest[d][0].ab_wheel_roll + "\n bar dip:\t\t" + nest[d][0].bar_dip + "\n arm:\t\t\t" + nest[d][0].arm + "\n shoulder:\t\t" + nest[d][0].shoulder: '\n No GYM ?? Kidding me ??';
var textdata = d + ":" + textcontent;
tooltip.transition()
.duration(200)
.style("opacity", 1);
tooltip.html(textdata)
.style("left", (d3.event.pageX)+30 + "px")
.style("top", (d3.event.pageY) + "px");
}
function mouseout (d) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
var $tooltip = $("#tooltip");
$tooltip.empty();
}
});
function monthPath(t0) {
var t1 = new Date(t0.getFullYear(), t0.getMonth() + 1, 0),
d0 = +day(t0), w0 = +week(t0),
d1 = +day(t1), w1 = +week(t1);
return "M" + (w0 + 1) * cellSize + "," + d0 * cellSize
+ "H" + w0 * cellSize + "V" + 7 * cellSize
+ "H" + w1 * cellSize + "V" + (d1 + 1) * cellSize
+ "H" + (w1 + 1) * cellSize + "V" + 0
+ "H" + (w0 + 1) * cellSize + "Z";
}
function dayTitle (t0) {
return t0.toString().split(" ")[2];
}
function monthTitle (t0) {
return t0.toString().split(" ")[1];
}
function yearTitle (t0) {
return t0.toString().split(" ")[3];
}
</script>
</example1>
In addition, a style block is also need for better visualization
```javascript
```