blob: 98823641f60b1676c3877d79ba3e09b97d898004 [file] [log] [blame]
Nils Diewalda1228622015-04-25 01:59:10 +00001/**
Nils Diewald7148c6f2015-05-04 15:07:53 +00002 * Simple Date picker for the
Nils Diewalda1228622015-04-25 01:59:10 +00003 * Virtual Collection builder.
Nils Diewald7148c6f2015-05-04 15:07:53 +00004 *
5 * @author Nils Diewald
Nils Diewalda1228622015-04-25 01:59:10 +00006 */
7define(['util'], function () {
8 "use strict";
9
Nils Diewald7148c6f2015-05-04 15:07:53 +000010 /*
11 * Localizations
12 */
Nils Diewalda1228622015-04-25 01:59:10 +000013 var loc = KorAP.Locale;
Nils Diewalda1228622015-04-25 01:59:10 +000014 loc.WDAY = loc.WDAY || [
15 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'
16 ];
Nils Diewalda1228622015-04-25 01:59:10 +000017 loc.MONTH = loc.MONTH || [
18 'January', 'February', 'March', 'April',
19 'May', 'June', 'July', 'August',
20 'September', 'October', 'November',
21 'December'
22 ];
23
24 var d = document;
25
Nils Diewald7148c6f2015-05-04 15:07:53 +000026 // The datepicker class
Nils Diewalda1228622015-04-25 01:59:10 +000027 return {
Nils Diewald7148c6f2015-05-04 15:07:53 +000028
29 /**
30 * Create a new datepicker view.
31 */
Nils Diewalda1228622015-04-25 01:59:10 +000032 create : function () {
33 return Object.create(this)._init();
34 },
35
Nils Diewald7148c6f2015-05-04 15:07:53 +000036 // Init datepicker
Nils Diewalda1228622015-04-25 01:59:10 +000037 _init : function () {
Nils Diewald652e5f42015-05-10 18:11:45 +000038 this._selected = [];
Nils Diewalda1228622015-04-25 01:59:10 +000039 return this;
40 },
41
Nils Diewalda79b2682015-05-18 18:34:06 +000042
Nils Diewald7148c6f2015-05-04 15:07:53 +000043 /**
44 * Get or select a specific date.
45 */
Nils Diewalda1228622015-04-25 01:59:10 +000046 select : function (year, month, day) {
47 if (arguments.length >= 1) {
48 this._selected = {'year' : year};
49 if (arguments.length >= 2) {
50 this._selected['month'] = month;
51 if (arguments.length >= 3)
52 this._selected['day'] = day;
53 };
54 return this;
55 };
56 return this._selected;
57 },
58
Nils Diewald7148c6f2015-05-04 15:07:53 +000059
60 /**
61 * Select a specific date and
62 * init the accompanied action.
63 */
64 set : function (year, month, day) {
65 this.select(year, month, day);
66 if (this._click !== undefined)
67 this._click(this._selected);
68 else
69 console.dir(this._selected);
70 },
71
72
73 /**
74 * Set the action for clicking as a callback.
75 * The callback will retrieve a an object with
76 * an optional year attribute,
77 * an optional month attribute,
78 * and an optional day attribute
79 */
80 onclick : function (cb) {
81 this._click = cb;
82 },
83
Nils Diewalda79b2682015-05-18 18:34:06 +000084
Nils Diewald7148c6f2015-05-04 15:07:53 +000085 /**
86 * Show the datepicker.
87 * Will either show the selected year/month
88 * or the current date.
89 * Will return the element for appending to the dom.
90 */
Nils Diewalda1228622015-04-25 01:59:10 +000091 show : function (year, month) {
Nils Diewald7148c6f2015-05-04 15:07:53 +000092 var e = this._element = d.createElement('div');
93 e.setAttribute('tabindex', 0);
94 e.style.outline = 0;
95 e.classList.add('datepicker');
96
97 var today = new Date();
98
99 // Show year
100 this._showYear = year ? year :
101 (this._selected['year'] ? this._selected['year'] :
Nils Diewald652e5f42015-05-10 18:11:45 +0000102 today.getYear() + 1900);
Nils Diewald7148c6f2015-05-04 15:07:53 +0000103
104 // Show month
105 this._showMonth = month ? month :
106 (this._selected['month'] ? this._selected['month'] :
107 (today.getMonth() + 1));
108
109 // Append all helpers
Nils Diewald87507832015-05-01 23:36:41 +0000110 this._element.appendChild(this._monthHelper());
111 this._element.appendChild(this._yearHelper());
112 this._element.appendChild(this._dayHelper());
113 return this._element;
114 },
115
Nils Diewalda79b2682015-05-18 18:34:06 +0000116
Nils Diewald7148c6f2015-05-04 15:07:53 +0000117 /**
118 * Get the HTML element associated with the datepicker.
119 */
Nils Diewald87507832015-05-01 23:36:41 +0000120 element : function () {
121 return this._element;
Nils Diewalda1228622015-04-25 01:59:10 +0000122 },
123
Nils Diewalda79b2682015-05-18 18:34:06 +0000124
Nils Diewald845282c2015-05-14 07:53:03 +0000125 /**
126 * Get the current date in string format.
127 */
128 today : function () {
129 var today = new Date();
130 var str = today.getYear() + 1900;
131 var m = today.getMonth() + 1;
132 var d = today.getDate();
133 str += '-' + (m < 10 ? '0' + m : m);
134 str += '-' + (d < 10 ? '0' + d : d);
135 return str;
136 },
Nils Diewald7148c6f2015-05-04 15:07:53 +0000137
Nils Diewalda79b2682015-05-18 18:34:06 +0000138
Nils Diewald7148c6f2015-05-04 15:07:53 +0000139 /**
140 * Increment the year.
141 */
Nils Diewalda1228622015-04-25 01:59:10 +0000142 incrYear : function () {
Nils Diewalda79b2682015-05-18 18:34:06 +0000143 if (this._showYear < 9999) {
144 this._showYear++;
145 this._updateYear();
146 this._updateMonth();
147 this._updateDay();
148 return this;
149 };
Nils Diewalda1228622015-04-25 01:59:10 +0000150 return;
151 },
152
Nils Diewalda79b2682015-05-18 18:34:06 +0000153
Nils Diewald7148c6f2015-05-04 15:07:53 +0000154 /**
155 * Decrement the year.
156 */
Nils Diewalda1228622015-04-25 01:59:10 +0000157 decrYear : function () {
Nils Diewalda79b2682015-05-18 18:34:06 +0000158 if (this._showYear > 0) {
159 this._showYear--;
160 this._updateYear();
161 this._updateMonth();
162 this._updateDay();
163 return this;
164 };
Nils Diewalda1228622015-04-25 01:59:10 +0000165 return;
166 },
167
Nils Diewalda79b2682015-05-18 18:34:06 +0000168
Nils Diewald7148c6f2015-05-04 15:07:53 +0000169 /**
170 * Increment the month.
171 */
Nils Diewalda1228622015-04-25 01:59:10 +0000172 incrMonth : function () {
173 this._showMonth++;
174 if (this._showMonth > 12) {
175 this._showMonth = 1;
176 this.incrYear();
177 }
178 else {
179 this._updateMonth();
180 this._updateDay();
181 };
Nils Diewalda79b2682015-05-18 18:34:06 +0000182 return this;
Nils Diewalda1228622015-04-25 01:59:10 +0000183 },
184
Nils Diewalda79b2682015-05-18 18:34:06 +0000185
Nils Diewald7148c6f2015-05-04 15:07:53 +0000186 /**
187 * Decrement the month.
188 */
Nils Diewalda1228622015-04-25 01:59:10 +0000189 decrMonth : function () {
190 this._showMonth--;
191 if (this._showMonth < 1) {
192 this._showMonth = 12;
193 this.decrYear();
194 }
195 else {
196 this._updateMonth();
197 this._updateDay();
198 };
Nils Diewalda79b2682015-05-18 18:34:06 +0000199
200 return this;
Nils Diewalda1228622015-04-25 01:59:10 +0000201 },
202
Nils Diewald7148c6f2015-05-04 15:07:53 +0000203
204 // Create the year helper element.
Nils Diewalda1228622015-04-25 01:59:10 +0000205 _yearHelper : function () {
206 var year = d.createElement('div');
207 year.classList.add('year');
208
209 // Decrement year
210 year.appendChild(d.createElement('span'))
211 .onclick = this.decrYear.bind(this);
212
213 this._yElement = year.appendChild(d.createElement('span'));
214 this._yElement.appendChild(document.createTextNode(this._showYear));
215
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000216 this._yElement.onclick = function () {
217 this.set(this._showYear);
218 }.bind(this);
Nils Diewald7148c6f2015-05-04 15:07:53 +0000219 this._selectYear();
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000220
Nils Diewalda1228622015-04-25 01:59:10 +0000221 // Increment year
222 year.appendChild(d.createElement('span'))
223 .onclick = this.incrYear.bind(this);
224
225 return year;
226 },
227
Nils Diewald7148c6f2015-05-04 15:07:53 +0000228 // Update the year helper view.
Nils Diewalda1228622015-04-25 01:59:10 +0000229 _updateYear : function () {
230 this._yElement.firstChild.data = this._showYear;
Nils Diewald7148c6f2015-05-04 15:07:53 +0000231 this._selectYear();
Nils Diewalda1228622015-04-25 01:59:10 +0000232 },
233
Nils Diewald7148c6f2015-05-04 15:07:53 +0000234
235 // Check if the viewed year is current
236 _selectYear : function () {
237 if (this._showYear === this.select()['year'])
238 this._yElement.classList.add('selected');
239 else
240 this._yElement.classList.remove('selected');
241 },
242
243
244 // Create the month helper element.
Nils Diewalda1228622015-04-25 01:59:10 +0000245 _monthHelper : function () {
246 var month = d.createElement('div');
247 month.classList.add('month');
248
249 // Decrement month
250 month.appendChild(d.createElement('span'))
251 .onclick = this.decrMonth.bind(this);
252
253 this._mElement = month.appendChild(d.createElement('span'));
254 this._mElement.appendChild(
255 document.createTextNode(loc.MONTH[this._showMonth-1])
256 );
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000257 this._mElement.onclick = function () {
258 this.set(this._showYear, this._showMonth);
259 }.bind(this);
Nils Diewald7148c6f2015-05-04 15:07:53 +0000260
261 this._selectMonth();
Nils Diewalda1228622015-04-25 01:59:10 +0000262
263 // Increment month
264 month.appendChild(d.createElement('span'))
265 .onclick = this.incrMonth.bind(this);
266
267 return month;
268 },
269
Nils Diewald7148c6f2015-05-04 15:07:53 +0000270 // Update the month helper view.
Nils Diewalda1228622015-04-25 01:59:10 +0000271 _updateMonth : function () {
272 this._mElement.firstChild.data = loc.MONTH[this._showMonth-1];
Nils Diewald7148c6f2015-05-04 15:07:53 +0000273 this._selectMonth();
Nils Diewalda1228622015-04-25 01:59:10 +0000274 },
275
Nils Diewald7148c6f2015-05-04 15:07:53 +0000276
277 // Check if the viewed month is current
278 _selectMonth : function () {
279 if (this._showYear === this.select()['year'] &&
280 this._showMonth === this.select()['month'])
281 this._mElement.classList.add('selected');
282 else
283 this._mElement.classList.remove('selected');
284 },
285
286
287 // Create the day (calendar) helper element.
Nils Diewalda1228622015-04-25 01:59:10 +0000288 _dayHelper : function () {
289 var table = d.createElement('table');
290
Nils Diewald7148c6f2015-05-04 15:07:53 +0000291 // Localized day view
Nils Diewalda1228622015-04-25 01:59:10 +0000292 var tr = table.appendChild(d.createElement('thead'))
293 .appendChild(d.createElement('tr'));
294 for (var i = 0; i < 7; i++) {
295 tr.appendChild(d.createElement('th'))
296 .appendChild(d.createTextNode(loc.WDAY[i]));
297 };
298
299 this._dBElement = this._dayBody();
300
301 table.appendChild(this._dBElement);
302 return table;
303 },
304
305 _dayBody : function () {
Nils Diewald7148c6f2015-05-04 15:07:53 +0000306 var showDate = new Date(
307 this._showYear,
308 this._showMonth - 1,
309 1,
310 0,
311 0,
312 0,
313 0
314 );
315 var date = new Date(
316 this._showYear,
317 this._showMonth - 1,
318 1,
319 0,
320 0,
321 0,
322 0
323 );
324 var today = new Date();
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000325 var that = this;
Nils Diewald7148c6f2015-05-04 15:07:53 +0000326
327 // What happens, in case someone clicks
328 // on a date
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000329 var click = function () {
330 that.set(
331 that._showYear,
332 that._showMonth,
333 parseInt(this.firstChild.data)
334 );
335 };
Nils Diewalda1228622015-04-25 01:59:10 +0000336
337 // Skip back to the previous monday (may be in the last month)
338 date.setDate(date.getDate() - ((date.getDay() + 6) % 7));
339
340 var tb = d.createElement('tbody');
341
342 var s = this.select();
343
344 // Iterate over all days of the table
345 while (1) {
346
347 // Loop through the week
348 var tr = tb.appendChild(d.createElement('tr'));
349 for (var i = 0; i < 7; i++) {
350 var td = tr.appendChild(d.createElement('td'));
351
352 // Not part of the current month
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000353 if (date.getMonth() !== showDate.getMonth()) {
Nils Diewalda1228622015-04-25 01:59:10 +0000354 td.classList.add('out');
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000355 }
356 else {
357 td.onclick = click;
358 };
Nils Diewalda1228622015-04-25 01:59:10 +0000359
360 // This is the current day
361 if (date.getDate() === today.getDate() &&
362 date.getMonth() === today.getMonth() &&
363 date.getFullYear() === today.getFullYear()) {
364 td.classList.add('today');
365 };
366
367 // This is the day selected
Nils Diewald87507832015-05-01 23:36:41 +0000368 if (s && s['day']) {
Nils Diewalda1228622015-04-25 01:59:10 +0000369 if (date.getDate() === s['day'] &&
370 date.getMonth() === s['month']-1 &&
371 date.getFullYear() === s['year']) {
372 td.classList.add('selected');
373 };
374 };
375
376 // Add the current day to the table
377 td.appendChild(
378 d.createTextNode(date.getDate())
379 );
380
381 // Next day
382 date.setDate(date.getDate() + 1);
383 };
384
385 if (date.getMonth() !== showDate.getMonth())
386 break;
387 };
388 return tb;
389 },
390
Nils Diewald7148c6f2015-05-04 15:07:53 +0000391 // Update the calendar view
Nils Diewalda1228622015-04-25 01:59:10 +0000392 _updateDay : function () {
393 var newBody = this._dayBody();
394 this._dBElement.parentNode.replaceChild(
395 newBody,
396 this._dBElement
397 );
398 this._dBElement = newBody;
399 }
400 };
401});