fully functional (if a bit limited) tracking WebApp, uses localStorage, so the data will be persisted and you can keep tracking
var g=Date,m=localStorage,o=JSON.parse(m.getItem("DidThis"))||{},p=document.createElement("p");
function q(){var f=[],h=1,i={},r={},u=0;a.strokeStyle="#0";n=(new g).getTime();for(k in o)f.push((new g(k)).getTime());f.sort();w=15*f.length+100;c.height=w+100;for(d=f[0];d<n;d+=864E5,h++)k=(new g(d)).toDateString(),o[k]&&o[k].forEach(function(f,v){var j="rgba(",l=o[k][v];for(z=0;3>z;z++)j+=parseInt(255*((l.charCodeAt(z)-97)/25))+",";j+="1)";a.fillStyle=j;a.fillRect(100+10*v,15*h-8,9,9);i[l]||(i[l]=0);i[l]++;u++;r[l]=j}),a.strokeText(k,0,15*h);s=0;h=0;for(t in i)e=s+6.28*(i[t]/u),a.beginPath(),a.moveTo(60,
w),a.arc(60,w,50,s,e,!1),a.closePath(),a.fillStyle=a.strokeStyle=r[t],a.fill(),a.strokeText(i[t]+"x "+t,120,w-35+15*h++),s=e}c.width=300;p.innerHTML="DidThis:<input/><button>1x</button>";b.appendChild(p);elements=b.children[3].children;elements[1].onclick=function(){var f=(new g(n)).toDateString(),h=elements[0].value;o[f]||(o[f]=[]);h&&(o[f].push(h),m.setItem("DidThis",JSON.stringify(o)),q())};q();
dmFyIGc9RGF0ZSxtPWxvY2FsU3RvcmFnZSxvPUpTT04ucGFyc2UobS5nZXRJdGVtKCJEaWRUaGlzIikpfHx7fSxwPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInAiKTsNCmZ1bmN0aW9uIHEoKXt2YXIgZj1bXSxoPTEsaT17fSxyPXt9LHU9MDthLnN0cm9rZVN0eWxlPSIjMCI7bj0obmV3IGcpLmdldFRpbWUoKTtmb3IoayBpbiBvKWYucHVzaCgobmV3IGcoaykpLmdldFRpbWUoKSk7Zi5zb3J0KCk7dz0xNSpmLmxlbmd0aCsxMDA7Yy5oZWlnaHQ9dysxMDA7Zm9yKGQ9ZlswXTtkPG47ZCs9ODY0RTUsaCsrKWs9KG5ldyBnKGQpKS50b0RhdGVTdHJpbmcoKSxvW2tdJiZvW2tdLmZvckVhY2goZnVuY3Rpb24oZix2KXt2YXIgaj0icmdiYSgiLGw9b1trXVt2XTtmb3Ioej0wOzM+ejt6Kyspais9cGFyc2VJbnQoMjU1KigobC5jaGFyQ29kZUF0KHopLTk3KS8yNSkpKyIsIjtqKz0iMSkiO2EuZmlsbFN0eWxlPWo7YS5maWxsUmVjdCgxMDArMTAqdiwxNSpoLTgsOSw5KTtpW2xdfHwoaVtsXT0wKTtpW2xdKys7dSsrO3JbbF09an0pLGEuc3Ryb2tlVGV4dChrLDAsMTUqaCk7cz0wO2g9MDtmb3IodCBpbiBpKWU9cys2LjI4KihpW3RdL3UpLGEuYmVnaW5QYXRoKCksYS5tb3ZlVG8oNjAsDQp3KSxhLmFyYyg2MCx3LDUwLHMsZSwhMSksYS5jbG9zZVBhdGgoKSxhLmZpbGxTdHlsZT1hLnN0cm9rZVN0eWxlPXJbdF0sYS5maWxsKCksYS5zdHJva2VUZXh0KGlbdF0rInggIit0LDEyMCx3LTM1KzE1KmgrKykscz1lfWMud2lkdGg9MzAwO3AuaW5uZXJIVE1MPSJEaWRUaGlzOjxpbnB1dC8+PGJ1dHRvbj4xeDwvYnV0dG9uPiI7Yi5hcHBlbmRDaGlsZChwKTtlbGVtZW50cz1iLmNoaWxkcmVuWzNdLmNoaWxkcmVuO2VsZW1lbnRzWzFdLm9uY2xpY2s9ZnVuY3Rpb24oKXt2YXIgZj0obmV3IGcobikpLnRvRGF0ZVN0cmluZygpLGg9ZWxlbWVudHNbMF0udmFsdWU7b1tmXXx8KG9bZl09W10pO2gmJihvW2ZdLnB1c2goaCksbS5zZXRJdGVtKCJEaWRUaGlzIixKU09OLnN0cmluZ2lmeShvKSkscSgpKX07cSgpOw==
var D = Date,
title = "DidThis",
storage = localStorage,
tasks = JSON.parse(storage.getItem(title)) || {}, // structure: {date: [task1, task2, ...]}
element = document.createElement("p"),
formatDate = function(timestamp) { return new D(timestamp).toDateString() },
redraw = function() {
var dates = [], j = 1,
pie = {}, pieColors = {}, pieTotal = 0;
a.strokeStyle = "#0";
n = new D().getTime();
// get earliest date
for(k in tasks) dates.push(new D(k).getTime());
dates.sort();
w = dates.length * 15 + 100;
c.height = w + 100;
d = dates[0];
// traw task matrix
for(; d < n; d += 86400000, j++) {
k = formatDate(d);
if (tasks[k]) tasks[k].forEach(function(value, i) {
// translate task into color by simply taking 1st three characters
// in lower case and map them to a range between 0 and 255
var color = "rgba(",
t = tasks[k][i];
for(z = 0; z < 3; z++) color += parseInt(255 * ((t.charCodeAt(z) - 97) / 25)) + ",";
color += "1)";
// draw tasks done per day
a.fillStyle = color;
a.fillRect(100 + 10 * i, 15 * j - 8, 9, 9);
// count tasks for pie
if(!pie[t]) pie[t] = 0;
pie[t]++;
pieTotal++;
pieColors[t] = color;
});
// date label
a.strokeText(k, 0, 15 * j);
}
// draw pie
s = 0, j=0;
for(t in pie) {
e = s + pie[t] / pieTotal * 6.28;
a.beginPath();
a.moveTo(60, w);
a.arc(60, w, 50, s, e, false);
a.closePath();
a.fillStyle = a.strokeStyle = pieColors[t];
a.fill();
a.strokeText(pie[t] + "x " + t, 120, w - 35 + 15 * j++);
s = e;
}
};
c.width = 300;
element.innerHTML = title + ":<input/><button>1x</button>";
b.appendChild(element);
elements = b.children[3].children;
// add new task
elements[1].onclick = function() {
var date = formatDate(n),
t = elements[0].value;
if(!tasks[date]) tasks[date] = [];
if(!t) return;
tasks[date].push(t);
storage.setItem(title, JSON.stringify(tasks));
redraw();
};
redraw();