Introduced simple datepicker
diff --git a/dev/js/src/datepicker.js b/dev/js/src/datepicker.js
new file mode 100644
index 0000000..1a1d9fe
--- /dev/null
+++ b/dev/js/src/datepicker.js
@@ -0,0 +1,222 @@
+/**
+ * Date picker for the
+ * Virtual Collection builder.
+ */
+define(['util'], function () {
+  "use strict";
+
+  var loc = KorAP.Locale;
+
+  loc.WDAY = loc.WDAY || [
+    'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'
+  ];
+
+  loc.MONTH = loc.MONTH || [
+    'January', 'February', 'March', 'April',
+    'May', 'June', 'July', 'August',
+    'September', 'October', 'November',
+    'December'
+  ];
+
+  var d = document;
+
+  return {
+    create : function () {
+      return Object.create(this)._init();
+    },
+
+    _init : function () {
+      return this;
+    },
+
+    select : function (year, month, day) {
+      if (arguments.length >= 1) {
+	this._selected = {'year' : year};
+	if (arguments.length >= 2) {
+	  this._selected['month'] = month;
+	  if (arguments.length >= 3)
+	    this._selected['day'] = day;
+	};
+	return this;
+      };
+      return this._selected;
+    },
+
+    show : function (year, month) {
+      var picker = d.createElement('div');
+      picker.classList.add('datepicker');
+      this._showYear = year;
+      this._showMonth = month;
+      picker.appendChild(this._yearHelper());
+      picker.appendChild(this._monthHelper());
+      picker.appendChild(this._dayHelper());
+      return picker;
+    },
+
+    incrYear : function () {
+      this._showYear++;
+      this._updateYear();
+      this._updateMonth();
+      this._updateDay();
+      return;
+    },
+
+    decrYear : function () {
+      this._showYear--;
+      this._updateYear();
+      this._updateMonth();
+      this._updateDay();
+      return;
+    },
+
+    incrMonth : function () {
+      this._showMonth++;
+      if (this._showMonth > 12) {
+	this._showMonth = 1;
+	this.incrYear();
+      }
+      else {
+	this._updateMonth();
+	this._updateDay();
+      };
+    },
+
+    decrMonth : function () {
+      this._showMonth--;
+      if (this._showMonth < 1) {
+	this._showMonth = 12;
+	this.decrYear();
+      }
+      else {
+	this._updateMonth();
+	this._updateDay();
+      };
+    },
+
+    _yearHelper : function () {
+      var year = d.createElement('div');
+      year.classList.add('year');
+
+      // Decrement year
+      year.appendChild(d.createElement('span'))
+	.onclick = this.decrYear.bind(this);
+
+      this._yElement = year.appendChild(d.createElement('span'));
+      this._yElement.appendChild(document.createTextNode(this._showYear));
+
+      // Increment year
+      year.appendChild(d.createElement('span'))
+	.onclick = this.incrYear.bind(this);
+
+      return year;
+    },
+
+    _updateYear : function () {
+      this._yElement.firstChild.data = this._showYear;
+    },
+
+    _monthHelper : function () {
+      var month = d.createElement('div');
+      month.classList.add('month');
+
+      // Decrement month
+      month.appendChild(d.createElement('span'))
+	.onclick = this.decrMonth.bind(this);
+      
+      this._mElement = month.appendChild(d.createElement('span'));
+      this._mElement.appendChild(
+	document.createTextNode(loc.MONTH[this._showMonth-1])
+      );
+      
+      // Increment month
+      month.appendChild(d.createElement('span'))
+	.onclick = this.incrMonth.bind(this);
+
+      return month;
+    },
+
+    _updateMonth : function () {
+      this._mElement.firstChild.data = loc.MONTH[this._showMonth-1];
+    },
+
+    _dayHelper : function () {
+      var table = d.createElement('table');
+
+      var tr = table.appendChild(d.createElement('thead'))
+	.appendChild(d.createElement('tr'));
+      for (var i = 0; i < 7; i++) {
+	tr.appendChild(d.createElement('th'))
+	  .appendChild(d.createTextNode(loc.WDAY[i]));
+      };
+
+      this._dBElement = this._dayBody();
+
+      table.appendChild(this._dBElement);
+      return table;
+    },
+
+    _dayBody : function () {
+      var showDate = new Date(this._showYear, this._showMonth - 1, 1, 0, 0, 0, 0);
+      var date     = new Date(this._showYear, this._showMonth - 1, 1, 0, 0, 0, 0);
+      var today    = new Date();
+
+      // Skip back to the previous monday (may be in the last month)
+      date.setDate(date.getDate() - ((date.getDay() + 6) % 7));
+
+      var tb = d.createElement('tbody');
+
+      var s = this.select();
+
+      // Iterate over all days of the table
+      while (1) {
+
+	// Loop through the week
+	var tr = tb.appendChild(d.createElement('tr'));
+	for (var i = 0; i < 7; i++) {
+	  var td = tr.appendChild(d.createElement('td'));
+
+	  // Not part of the current month
+	  if (date.getMonth() !== showDate.getMonth())
+	    td.classList.add('out');
+	  
+	  // This is the current day
+	  if (date.getDate()     === today.getDate() &&
+	      date.getMonth()    === today.getMonth() &&
+	      date.getFullYear() === today.getFullYear()) {
+	    td.classList.add('today');
+	  };
+
+	  // This is the day selected
+	  if (s['day']) {
+	    if (date.getDate()     === s['day'] &&
+		date.getMonth()    === s['month']-1 &&
+		date.getFullYear() === s['year']) {
+	      td.classList.add('selected');
+	    };
+	  };
+
+	  // Add the current day to the table
+	  td.appendChild(
+	    d.createTextNode(date.getDate())
+	  );
+	  
+	  // Next day
+	  date.setDate(date.getDate() + 1);
+	};
+
+	if (date.getMonth() !== showDate.getMonth())
+	  break;
+      };
+      return tb;
+    },
+
+    _updateDay : function () {
+      var newBody = this._dayBody();
+      this._dBElement.parentNode.replaceChild(
+	newBody,
+	this._dBElement
+      );
+      this._dBElement = newBody;
+    }
+  };
+});