Improve test coverage for date picker and improve code
Change-Id: I9e6756fd555140739edc0318b8fb7e9fbe39ea8b
diff --git a/Changes b/Changes
index bbccd2b..fd5a054 100755
--- a/Changes
+++ b/Changes
@@ -3,6 +3,8 @@
- add roll() method to state object.
- Fix wrong hint-mirror behaviour in Firefox.
- Fix VC fragments for redundant constraints.
+ - Modernize ES and improve variable declarations.
+ - Improve JS test coverage for Datepicker.
0.39 2020-10-07
- Add information on secret file to Readme.
diff --git a/dev/js/spec/datepickerSpec.js b/dev/js/spec/datepickerSpec.js
index 865b721..33dee43 100644
--- a/dev/js/spec/datepickerSpec.js
+++ b/dev/js/spec/datepickerSpec.js
@@ -142,5 +142,29 @@
expect(e.querySelector('div.month > span:nth-child(2)').firstChild.data).toEqual('January');
});
+
+ it('should parse from string', function () {
+ var dp = dpClass.create();
+ expect(dp.fromString()).toBeFalsy();
+ expect(dp.fromString("2020-September")).toBeFalsy();
+ expect(dp.fromString("2020")).toBeTruthy();
+ expect(dp.fromString("2020-10")).toBeTruthy();
+ expect(dp.fromString("2020-10-9")).toBeFalsy();
+ expect(dp.fromString("2020-10-09")).toBeTruthy();
+
+ expect(dp._selected['year']).toEqual(2020);
+ expect(dp._selected['month']).toEqual(10);
+ expect(dp._selected['day']).toEqual(9);
+
+ var e = dp.show(2020, 11);
+
+ expect(e.querySelector('div.year > span:nth-child(2)').firstChild.data).toEqual('2020');
+ expect(e.querySelector('div.year > span:nth-child(2)').classList.contains('selected')).toBeTruthy();
+ expect(e.querySelector('div.month > span:nth-child(2)').firstChild.data).toEqual('November');
+ expect(e.querySelector('div.month > span:nth-child(2)').classList.contains('selected')).toBeFalsy();
+ expect(e.querySelector('div.month > span:nth-child(2)').classList.contains('selected')).toBeFalsy();
+
+ expect(dp.toString()).toEqual("2020-10-09");
+ });
});
});
diff --git a/dev/js/src/datepicker.js b/dev/js/src/datepicker.js
index 89a9a68..8d79bdb 100644
--- a/dev/js/src/datepicker.js
+++ b/dev/js/src/datepicker.js
@@ -1,19 +1,20 @@
/**
- * Simple Date picker for the
+ * Date picker for the
* Virtual Collection builder.
*
* @author Nils Diewald
*/
define(['util'], function () {
+
"use strict";
- KorAP._validDateMatchRE = new RegExp("^(?:[lg]?eq|ne)$");
- KorAP._validDateRE = new RegExp("^(?:\\d{4})(?:-\\d\\d(?:-\\d\\d)?)?$");
+ KorAP._validDateMatchRE = new RegExp("^(?:[lg]?eq|ne)$");
+ KorAP._validDateRE = new RegExp("^(?:\\d{4})(?:-\\d\\d(?:-\\d\\d)?)?$");
/*
* Localizations
*/
- var loc = KorAP.Locale;
+ const loc = KorAP.Locale;
loc.WDAY = loc.WDAY || [
'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'
];
@@ -24,7 +25,7 @@
'December'
];
- var d = document;
+ const d = document;
// The datepicker class
return {
@@ -48,22 +49,23 @@
* Get or select a specific date.
*/
select : function (year, month, day) {
+ const t = this;
if (arguments.length >= 1) {
- this._selected = {'year' : year};
- this._showYear = year;
+ t._selected = {'year' : year};
+ t._showYear = year;
if (arguments.length >= 2) {
- this._selected['month'] = month;
- this._showMonth = month;
+ t._selected['month'] = month;
+ t._showMonth = month;
if (arguments.length >= 3) {
- this._selected['day'] = day;
- this._showDay = day;
+ t._selected['day'] = day;
+ t._showDay = day;
};
};
- return this;
+ return t;
};
- return this._selected;
+ return t._selected;
},
@@ -73,11 +75,12 @@
*/
set : function (year, month, day) {
this.select(year, month, day);
- this.store();
+ this._store();
},
-
- store : function () {
+
+ // Store the selected value
+ _store : function () {
if (this._click !== undefined)
this._click(this._selected);
else
@@ -97,6 +100,9 @@
},
+ /**
+ * The associated input field.
+ */
input : function () {
return this._input;
},
@@ -110,35 +116,36 @@
*/
show : function (year, month) {
- var e = this._element = d.createElement('div');
+ const e = this._element = d.createElement('div');
e.setAttribute('tabindex', 0);
e.style.outline = 0;
e.classList.add('datepicker');
- var today = new Date();
+ const today = new Date();
+ const t = this;
// Show year
- this._showYear = (year !== undefined) ? year :
- (this._selected['year'] ? this._selected['year'] :
+ t._showYear = (year !== undefined) ? year :
+ (t._selected['year'] ? this._selected['year'] :
today.getYear() + 1900);
// Show month
- this._showMonth = month ? month :
- (this._selected['month'] ? this._selected['month'] :
+ t._showMonth = month ? month :
+ (t._selected['month'] ? t._selected['month'] :
(today.getMonth() + 1));
// Append all helpers
- e.appendChild(this._monthHelper());
- e.appendChild(this._yearHelper());
- e.appendChild(this._dayHelper());
- this._input = e.appendChild(this._stringHelper());
+ e.appendChild(t._monthHelper());
+ e.appendChild(t._yearHelper());
+ e.appendChild(t._dayHelper());
+ t._input = e.appendChild(t._stringHelper());
// Always focus
e.addEventListener(
'mousedown',
function (ev) {
this._inField = true
- }.bind(this)
+ }.bind(t)
);
e.addEventListener(
@@ -146,31 +153,31 @@
function (ev) {
this._inField = false;
this._input.focus();
- }.bind(this)
+ }.bind(t)
);
- this._input.addEventListener(
+ t._input.addEventListener(
'blur',
function (ev) {
if (!this._inField) {
if (this.fromString(this._input.value)) {
- this.store();
+ this._store();
};
};
ev.halt();
- }.bind(this)
+ }.bind(t)
);
- this._input.focus();
+ t._input.focus();
- return this._element;
+ return t._element;
},
_stringHelper : function () {
// Create element
// Add input field
- var input = d.createElement('input');
+ const input = d.createElement('input');
input.value = this.toString();
input.setAttribute('tabindex', 0);
@@ -190,7 +197,7 @@
function (e) {
if (e.keyCode == 13) {
if (this.fromString(input.value))
- this.store();
+ this._store();
e.halt();
return false;
@@ -201,6 +208,7 @@
return input;
},
+
/**
* Get the HTML element associated with the datepicker.
*/
@@ -213,20 +221,23 @@
* Get the current date in string format.
*/
today : function () {
- var today = new Date();
- var str = today.getYear() + 1900;
- var m = today.getMonth() + 1;
- var d = today.getDate();
+ const today = new Date();
+ let str = today.getYear() + 1900;
+ const m = today.getMonth() + 1;
+ const d = today.getDate();
str += '-' + (m < 10 ? '0' + m : m);
str += '-' + (d < 10 ? '0' + d : d);
return str;
},
+ /**
+ * Stringification
+ */
toString : function () {
// There are values selected
- var v = '';
- var s = this._selected;
+ let v = '';
+ const s = this._selected;
if (s['year']) {
v += s['year'];
if (s['month']) {
@@ -246,12 +257,13 @@
* Increment the year.
*/
incrYear : function () {
- if (this._showYear < 9999) {
- this._showYear++;
- this._updateYear();
- this._updateMonth();
- this._updateDay();
- return this;
+ const t = this;
+ if (t._showYear < 9999) {
+ t._showYear++;
+ t._updateYear();
+ t._updateMonth();
+ t._updateDay();
+ return t;
};
return;
},
@@ -261,12 +273,13 @@
* Decrement the year.
*/
decrYear : function () {
- if (this._showYear > 0) {
- this._showYear--;
- this._updateYear();
- this._updateMonth();
- this._updateDay();
- return this;
+ const t = this;
+ if (t._showYear > 0) {
+ t._showYear--;
+ t._updateYear();
+ t._updateMonth();
+ t._updateDay();
+ return t;
};
return;
},
@@ -276,16 +289,17 @@
* Increment the month.
*/
incrMonth : function () {
- this._showMonth++;
- if (this._showMonth > 12) {
- this._showMonth = 1;
- this.incrYear();
+ const t = this;
+ t._showMonth++;
+ if (t._showMonth > 12) {
+ t._showMonth = 1;
+ t.incrYear();
}
else {
- this._updateMonth();
- this._updateDay();
+ t._updateMonth();
+ t._updateDay();
};
- return this;
+ return t;
},
@@ -293,44 +307,47 @@
* Decrement the month.
*/
decrMonth : function () {
- this._showMonth--;
- if (this._showMonth < 1) {
- this._showMonth = 12;
- this.decrYear();
+ const t = this;
+ t._showMonth--;
+ if (t._showMonth < 1) {
+ t._showMonth = 12;
+ t.decrYear();
}
else {
- this._updateMonth();
- this._updateDay();
+ t._updateMonth();
+ t._updateDay();
};
- return this;
+ return t;
},
// Create the year helper element.
_yearHelper : function () {
- var year = d.createElement('div');
+ const t = this;
+ const year = d.createElement('div');
year.classList.add('year');
// Decrement year
year.addE('span')
- .onclick = this.decrYear.bind(this);
+ .onclick = t.decrYear.bind(t);
- this._yElement = year.addE('span');
- this._yElement.addT(this._showYear);
+ t._yElement = year.addE('span');
+ t._yElement.addT(t._showYear);
- this._yElement.onclick = function () {
- this.set(this._showYear);
- }.bind(this);
- this._selectYear();
+ t._yElement.onclick = function () {
+ t.set(t._showYear);
+ }.bind(t);
+ t._selectYear();
// Increment year
year.addE('span')
- .onclick = this.incrYear.bind(this);
+ .onclick = t.incrYear.bind(t);
return year;
},
+
// Update the year helper view.
_updateYear : function () {
this._yElement.firstChild.data = this._showYear;
@@ -349,24 +366,25 @@
// Create the month helper element.
_monthHelper : function () {
- var month = d.createElement('div');
+ const t = this;
+ const month = d.createElement('div');
month.classList.add('month');
// Decrement month
month.addE('span')
- .onclick = this.decrMonth.bind(this);
+ .onclick = t.decrMonth.bind(t);
- this._mElement = month.addE('span');
- this._mElement.addT(loc.MONTH[this._showMonth-1]);
- this._mElement.onclick = function () {
+ t._mElement = month.addE('span');
+ t._mElement.addT(loc.MONTH[t._showMonth-1]);
+ t._mElement.onclick = function () {
this.set(this._showYear, this._showMonth);
- }.bind(this);
+ }.bind(t);
- this._selectMonth();
+ t._selectMonth();
// Increment month
month.addE('span')
- .onclick = this.incrMonth.bind(this);
+ .onclick = t.incrMonth.bind(t);
return month;
},
@@ -383,21 +401,22 @@
// Check if the viewed month is current
_selectMonth : function () {
- if (this._showYear === this.select()['year'] &&
- this._showMonth === this.select()['month'])
- this._mElement.classList.add('selected');
+ const t = this;
+ if (t._showYear === t.select()['year'] &&
+ t._showMonth === t.select()['month'])
+ t._mElement.classList.add('selected');
else
- this._mElement.classList.remove('selected');
+ t._mElement.classList.remove('selected');
},
// Create the day (calendar) helper element.
_dayHelper : function () {
- var table = d.createElement('table');
+ const table = d.createElement('table');
// Localized day view
- var tr = table.addE('thead').addE('tr');
- for (var i = 0; i < 7; i++) {
+ const tr = table.addE('thead').addE('tr');
+ for (let i = 0; i < 7; i++) {
tr.addE('th').addT(loc.WDAY[i]);
};
@@ -407,8 +426,10 @@
return table;
},
+
+ // Create day body for calendar table
_dayBody : function () {
- var showDate = new Date(
+ const showDate = new Date(
this._showYear,
this._showMonth - 1,
1,
@@ -417,7 +438,7 @@
0,
0
);
- var date = new Date(
+ const date = new Date(
this._showYear,
this._showMonth - 1,
1,
@@ -426,12 +447,12 @@
0,
0
);
- var today = new Date();
- var that = this;
+ const today = new Date();
+ const that = this;
// What happens, in case someone clicks
// on a date
- var click = function () {
+ const click = function () {
that.set(
that._showYear,
that._showMonth,
@@ -442,17 +463,19 @@
// 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');
+ const tb = d.createElement('tbody');
- var s = this.select();
+ const s = this.select();
+
+ let tr, i, td;
// Iterate over all days of the table
while (1) {
// Loop through the week
- var tr = tb.addE('tr');
- for (var i = 0; i < 7; i++) {
- var td = tr.addE('td');
+ tr = tb.addE('tr');
+ for (i = 0; i < 7; i++) {
+ td = tr.addE('td');
// Not part of the current month
if (date.getMonth() !== showDate.getMonth()) {
@@ -477,14 +500,14 @@
td.classList.add('selected');
};
};
-
+
// Add the current day to the table
td.addT(date.getDate());
// Next day
date.setDate(date.getDate() + 1);
};
-
+
if (date.getMonth() !== showDate.getMonth())
break;
};
@@ -493,7 +516,7 @@
// Update the calendar view
_updateDay : function () {
- var newBody = this._dayBody();
+ const newBody = this._dayBody();
this._dBElement.parentNode.replaceChild(
newBody,
this._dBElement
@@ -501,6 +524,10 @@
this._dBElement = newBody;
},
+
+ /**
+ * Parse date from string.
+ */
fromString : function (v) {
if (v === undefined)
return false;
@@ -508,7 +535,7 @@
if (!KorAP._validDateRE.test(v))
return false;
- var d = v.split('-', 3);
+ const d = v.split('-', 3);
d[0] = parseInt(d[0]);
if (d[1]) d[1] = parseInt(d[1]);
if (d[2]) d[2] = parseInt(d[2]);