blob: 8608efeb74b28986942ce584c94d9f09b39231c4 [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 Diewald7148c6f2015-05-04 15:07:53 +000042 /**
43 * Get or select a specific date.
44 */
Nils Diewalda1228622015-04-25 01:59:10 +000045 select : function (year, month, day) {
46 if (arguments.length >= 1) {
47 this._selected = {'year' : year};
48 if (arguments.length >= 2) {
49 this._selected['month'] = month;
50 if (arguments.length >= 3)
51 this._selected['day'] = day;
52 };
53 return this;
54 };
55 return this._selected;
56 },
57
Nils Diewald7148c6f2015-05-04 15:07:53 +000058
59 /**
60 * Select a specific date and
61 * init the accompanied action.
62 */
63 set : function (year, month, day) {
64 this.select(year, month, day);
65 if (this._click !== undefined)
66 this._click(this._selected);
67 else
68 console.dir(this._selected);
69 },
70
71
72 /**
73 * Set the action for clicking as a callback.
74 * The callback will retrieve a an object with
75 * an optional year attribute,
76 * an optional month attribute,
77 * and an optional day attribute
78 */
79 onclick : function (cb) {
80 this._click = cb;
81 },
82
83 /**
84 * Show the datepicker.
85 * Will either show the selected year/month
86 * or the current date.
87 * Will return the element for appending to the dom.
88 */
Nils Diewalda1228622015-04-25 01:59:10 +000089 show : function (year, month) {
Nils Diewald7148c6f2015-05-04 15:07:53 +000090 var e = this._element = d.createElement('div');
91 e.setAttribute('tabindex', 0);
92 e.style.outline = 0;
93 e.classList.add('datepicker');
94
95 var today = new Date();
96
97 // Show year
98 this._showYear = year ? year :
99 (this._selected['year'] ? this._selected['year'] :
Nils Diewald652e5f42015-05-10 18:11:45 +0000100 today.getYear() + 1900);
Nils Diewald7148c6f2015-05-04 15:07:53 +0000101
102 // Show month
103 this._showMonth = month ? month :
104 (this._selected['month'] ? this._selected['month'] :
105 (today.getMonth() + 1));
106
107 // Append all helpers
Nils Diewald87507832015-05-01 23:36:41 +0000108 this._element.appendChild(this._monthHelper());
109 this._element.appendChild(this._yearHelper());
110 this._element.appendChild(this._dayHelper());
111 return this._element;
112 },
113
Nils Diewald7148c6f2015-05-04 15:07:53 +0000114 /**
115 * Get the HTML element associated with the datepicker.
116 */
Nils Diewald87507832015-05-01 23:36:41 +0000117 element : function () {
118 return this._element;
Nils Diewalda1228622015-04-25 01:59:10 +0000119 },
120
Nils Diewald845282c2015-05-14 07:53:03 +0000121 /**
122 * Get the current date in string format.
123 */
124 today : function () {
125 var today = new Date();
126 var str = today.getYear() + 1900;
127 var m = today.getMonth() + 1;
128 var d = today.getDate();
129 str += '-' + (m < 10 ? '0' + m : m);
130 str += '-' + (d < 10 ? '0' + d : d);
131 return str;
132 },
Nils Diewald7148c6f2015-05-04 15:07:53 +0000133
134 /**
135 * Increment the year.
136 */
Nils Diewalda1228622015-04-25 01:59:10 +0000137 incrYear : function () {
138 this._showYear++;
139 this._updateYear();
140 this._updateMonth();
141 this._updateDay();
142 return;
143 },
144
Nils Diewald7148c6f2015-05-04 15:07:53 +0000145 /**
146 * Decrement the year.
147 */
Nils Diewalda1228622015-04-25 01:59:10 +0000148 decrYear : function () {
149 this._showYear--;
150 this._updateYear();
151 this._updateMonth();
152 this._updateDay();
153 return;
154 },
155
Nils Diewald7148c6f2015-05-04 15:07:53 +0000156 /**
157 * Increment the month.
158 */
Nils Diewalda1228622015-04-25 01:59:10 +0000159 incrMonth : function () {
160 this._showMonth++;
161 if (this._showMonth > 12) {
162 this._showMonth = 1;
163 this.incrYear();
164 }
165 else {
166 this._updateMonth();
167 this._updateDay();
168 };
169 },
170
Nils Diewald7148c6f2015-05-04 15:07:53 +0000171 /**
172 * Decrement the month.
173 */
Nils Diewalda1228622015-04-25 01:59:10 +0000174 decrMonth : function () {
175 this._showMonth--;
176 if (this._showMonth < 1) {
177 this._showMonth = 12;
178 this.decrYear();
179 }
180 else {
181 this._updateMonth();
182 this._updateDay();
183 };
184 },
185
Nils Diewald7148c6f2015-05-04 15:07:53 +0000186
187 // Create the year helper element.
Nils Diewalda1228622015-04-25 01:59:10 +0000188 _yearHelper : function () {
189 var year = d.createElement('div');
190 year.classList.add('year');
191
192 // Decrement year
193 year.appendChild(d.createElement('span'))
194 .onclick = this.decrYear.bind(this);
195
196 this._yElement = year.appendChild(d.createElement('span'));
197 this._yElement.appendChild(document.createTextNode(this._showYear));
198
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000199 this._yElement.onclick = function () {
200 this.set(this._showYear);
201 }.bind(this);
Nils Diewald7148c6f2015-05-04 15:07:53 +0000202 this._selectYear();
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000203
Nils Diewalda1228622015-04-25 01:59:10 +0000204 // Increment year
205 year.appendChild(d.createElement('span'))
206 .onclick = this.incrYear.bind(this);
207
208 return year;
209 },
210
Nils Diewald7148c6f2015-05-04 15:07:53 +0000211 // Update the year helper view.
Nils Diewalda1228622015-04-25 01:59:10 +0000212 _updateYear : function () {
213 this._yElement.firstChild.data = this._showYear;
Nils Diewald7148c6f2015-05-04 15:07:53 +0000214 this._selectYear();
Nils Diewalda1228622015-04-25 01:59:10 +0000215 },
216
Nils Diewald7148c6f2015-05-04 15:07:53 +0000217
218 // Check if the viewed year is current
219 _selectYear : function () {
220 if (this._showYear === this.select()['year'])
221 this._yElement.classList.add('selected');
222 else
223 this._yElement.classList.remove('selected');
224 },
225
226
227 // Create the month helper element.
Nils Diewalda1228622015-04-25 01:59:10 +0000228 _monthHelper : function () {
229 var month = d.createElement('div');
230 month.classList.add('month');
231
232 // Decrement month
233 month.appendChild(d.createElement('span'))
234 .onclick = this.decrMonth.bind(this);
235
236 this._mElement = month.appendChild(d.createElement('span'));
237 this._mElement.appendChild(
238 document.createTextNode(loc.MONTH[this._showMonth-1])
239 );
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000240 this._mElement.onclick = function () {
241 this.set(this._showYear, this._showMonth);
242 }.bind(this);
Nils Diewald7148c6f2015-05-04 15:07:53 +0000243
244 this._selectMonth();
Nils Diewalda1228622015-04-25 01:59:10 +0000245
246 // Increment month
247 month.appendChild(d.createElement('span'))
248 .onclick = this.incrMonth.bind(this);
249
250 return month;
251 },
252
Nils Diewald7148c6f2015-05-04 15:07:53 +0000253 // Update the month helper view.
Nils Diewalda1228622015-04-25 01:59:10 +0000254 _updateMonth : function () {
255 this._mElement.firstChild.data = loc.MONTH[this._showMonth-1];
Nils Diewald7148c6f2015-05-04 15:07:53 +0000256 this._selectMonth();
Nils Diewalda1228622015-04-25 01:59:10 +0000257 },
258
Nils Diewald7148c6f2015-05-04 15:07:53 +0000259
260 // Check if the viewed month is current
261 _selectMonth : function () {
262 if (this._showYear === this.select()['year'] &&
263 this._showMonth === this.select()['month'])
264 this._mElement.classList.add('selected');
265 else
266 this._mElement.classList.remove('selected');
267 },
268
269
270 // Create the day (calendar) helper element.
Nils Diewalda1228622015-04-25 01:59:10 +0000271 _dayHelper : function () {
272 var table = d.createElement('table');
273
Nils Diewald7148c6f2015-05-04 15:07:53 +0000274 // Localized day view
Nils Diewalda1228622015-04-25 01:59:10 +0000275 var tr = table.appendChild(d.createElement('thead'))
276 .appendChild(d.createElement('tr'));
277 for (var i = 0; i < 7; i++) {
278 tr.appendChild(d.createElement('th'))
279 .appendChild(d.createTextNode(loc.WDAY[i]));
280 };
281
282 this._dBElement = this._dayBody();
283
284 table.appendChild(this._dBElement);
285 return table;
286 },
287
288 _dayBody : function () {
Nils Diewald7148c6f2015-05-04 15:07:53 +0000289 var showDate = new Date(
290 this._showYear,
291 this._showMonth - 1,
292 1,
293 0,
294 0,
295 0,
296 0
297 );
298 var date = new Date(
299 this._showYear,
300 this._showMonth - 1,
301 1,
302 0,
303 0,
304 0,
305 0
306 );
307 var today = new Date();
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000308 var that = this;
Nils Diewald7148c6f2015-05-04 15:07:53 +0000309
310 // What happens, in case someone clicks
311 // on a date
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000312 var click = function () {
313 that.set(
314 that._showYear,
315 that._showMonth,
316 parseInt(this.firstChild.data)
317 );
318 };
Nils Diewalda1228622015-04-25 01:59:10 +0000319
320 // Skip back to the previous monday (may be in the last month)
321 date.setDate(date.getDate() - ((date.getDay() + 6) % 7));
322
323 var tb = d.createElement('tbody');
324
325 var s = this.select();
326
327 // Iterate over all days of the table
328 while (1) {
329
330 // Loop through the week
331 var tr = tb.appendChild(d.createElement('tr'));
332 for (var i = 0; i < 7; i++) {
333 var td = tr.appendChild(d.createElement('td'));
334
335 // Not part of the current month
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000336 if (date.getMonth() !== showDate.getMonth()) {
Nils Diewalda1228622015-04-25 01:59:10 +0000337 td.classList.add('out');
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000338 }
339 else {
340 td.onclick = click;
341 };
Nils Diewalda1228622015-04-25 01:59:10 +0000342
343 // This is the current day
344 if (date.getDate() === today.getDate() &&
345 date.getMonth() === today.getMonth() &&
346 date.getFullYear() === today.getFullYear()) {
347 td.classList.add('today');
348 };
349
350 // This is the day selected
Nils Diewald87507832015-05-01 23:36:41 +0000351 if (s && s['day']) {
Nils Diewalda1228622015-04-25 01:59:10 +0000352 if (date.getDate() === s['day'] &&
353 date.getMonth() === s['month']-1 &&
354 date.getFullYear() === s['year']) {
355 td.classList.add('selected');
356 };
357 };
358
359 // Add the current day to the table
360 td.appendChild(
361 d.createTextNode(date.getDate())
362 );
363
364 // Next day
365 date.setDate(date.getDate() + 1);
366 };
367
368 if (date.getMonth() !== showDate.getMonth())
369 break;
370 };
371 return tb;
372 },
373
Nils Diewald7148c6f2015-05-04 15:07:53 +0000374 // Update the calendar view
Nils Diewalda1228622015-04-25 01:59:10 +0000375 _updateDay : function () {
376 var newBody = this._dayBody();
377 this._dBElement.parentNode.replaceChild(
378 newBody,
379 this._dBElement
380 );
381 this._dBElement = newBody;
382 }
383 };
384});