blob: 59a3ec2b473c9fb99e1cfe1096cf3f394cf64522 [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 Diewald7148c6f2015-05-04 15:07:53 +0000121
122 /**
123 * Increment the year.
124 */
Nils Diewalda1228622015-04-25 01:59:10 +0000125 incrYear : function () {
126 this._showYear++;
127 this._updateYear();
128 this._updateMonth();
129 this._updateDay();
130 return;
131 },
132
Nils Diewald7148c6f2015-05-04 15:07:53 +0000133 /**
134 * Decrement the year.
135 */
Nils Diewalda1228622015-04-25 01:59:10 +0000136 decrYear : function () {
137 this._showYear--;
138 this._updateYear();
139 this._updateMonth();
140 this._updateDay();
141 return;
142 },
143
Nils Diewald7148c6f2015-05-04 15:07:53 +0000144 /**
145 * Increment the month.
146 */
Nils Diewalda1228622015-04-25 01:59:10 +0000147 incrMonth : function () {
148 this._showMonth++;
149 if (this._showMonth > 12) {
150 this._showMonth = 1;
151 this.incrYear();
152 }
153 else {
154 this._updateMonth();
155 this._updateDay();
156 };
157 },
158
Nils Diewald7148c6f2015-05-04 15:07:53 +0000159 /**
160 * Decrement the month.
161 */
Nils Diewalda1228622015-04-25 01:59:10 +0000162 decrMonth : function () {
163 this._showMonth--;
164 if (this._showMonth < 1) {
165 this._showMonth = 12;
166 this.decrYear();
167 }
168 else {
169 this._updateMonth();
170 this._updateDay();
171 };
172 },
173
Nils Diewald7148c6f2015-05-04 15:07:53 +0000174
175 // Create the year helper element.
Nils Diewalda1228622015-04-25 01:59:10 +0000176 _yearHelper : function () {
177 var year = d.createElement('div');
178 year.classList.add('year');
179
180 // Decrement year
181 year.appendChild(d.createElement('span'))
182 .onclick = this.decrYear.bind(this);
183
184 this._yElement = year.appendChild(d.createElement('span'));
185 this._yElement.appendChild(document.createTextNode(this._showYear));
186
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000187 this._yElement.onclick = function () {
188 this.set(this._showYear);
189 }.bind(this);
Nils Diewald7148c6f2015-05-04 15:07:53 +0000190 this._selectYear();
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000191
Nils Diewalda1228622015-04-25 01:59:10 +0000192 // Increment year
193 year.appendChild(d.createElement('span'))
194 .onclick = this.incrYear.bind(this);
195
196 return year;
197 },
198
Nils Diewald7148c6f2015-05-04 15:07:53 +0000199 // Update the year helper view.
Nils Diewalda1228622015-04-25 01:59:10 +0000200 _updateYear : function () {
201 this._yElement.firstChild.data = this._showYear;
Nils Diewald7148c6f2015-05-04 15:07:53 +0000202 this._selectYear();
Nils Diewalda1228622015-04-25 01:59:10 +0000203 },
204
Nils Diewald7148c6f2015-05-04 15:07:53 +0000205
206 // Check if the viewed year is current
207 _selectYear : function () {
208 if (this._showYear === this.select()['year'])
209 this._yElement.classList.add('selected');
210 else
211 this._yElement.classList.remove('selected');
212 },
213
214
215 // Create the month helper element.
Nils Diewalda1228622015-04-25 01:59:10 +0000216 _monthHelper : function () {
217 var month = d.createElement('div');
218 month.classList.add('month');
219
220 // Decrement month
221 month.appendChild(d.createElement('span'))
222 .onclick = this.decrMonth.bind(this);
223
224 this._mElement = month.appendChild(d.createElement('span'));
225 this._mElement.appendChild(
226 document.createTextNode(loc.MONTH[this._showMonth-1])
227 );
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000228 this._mElement.onclick = function () {
229 this.set(this._showYear, this._showMonth);
230 }.bind(this);
Nils Diewald7148c6f2015-05-04 15:07:53 +0000231
232 this._selectMonth();
Nils Diewalda1228622015-04-25 01:59:10 +0000233
234 // Increment month
235 month.appendChild(d.createElement('span'))
236 .onclick = this.incrMonth.bind(this);
237
238 return month;
239 },
240
Nils Diewald7148c6f2015-05-04 15:07:53 +0000241 // Update the month helper view.
Nils Diewalda1228622015-04-25 01:59:10 +0000242 _updateMonth : function () {
243 this._mElement.firstChild.data = loc.MONTH[this._showMonth-1];
Nils Diewald7148c6f2015-05-04 15:07:53 +0000244 this._selectMonth();
Nils Diewalda1228622015-04-25 01:59:10 +0000245 },
246
Nils Diewald7148c6f2015-05-04 15:07:53 +0000247
248 // Check if the viewed month is current
249 _selectMonth : function () {
250 if (this._showYear === this.select()['year'] &&
251 this._showMonth === this.select()['month'])
252 this._mElement.classList.add('selected');
253 else
254 this._mElement.classList.remove('selected');
255 },
256
257
258 // Create the day (calendar) helper element.
Nils Diewalda1228622015-04-25 01:59:10 +0000259 _dayHelper : function () {
260 var table = d.createElement('table');
261
Nils Diewald7148c6f2015-05-04 15:07:53 +0000262 // Localized day view
Nils Diewalda1228622015-04-25 01:59:10 +0000263 var tr = table.appendChild(d.createElement('thead'))
264 .appendChild(d.createElement('tr'));
265 for (var i = 0; i < 7; i++) {
266 tr.appendChild(d.createElement('th'))
267 .appendChild(d.createTextNode(loc.WDAY[i]));
268 };
269
270 this._dBElement = this._dayBody();
271
272 table.appendChild(this._dBElement);
273 return table;
274 },
275
276 _dayBody : function () {
Nils Diewald7148c6f2015-05-04 15:07:53 +0000277 var showDate = new Date(
278 this._showYear,
279 this._showMonth - 1,
280 1,
281 0,
282 0,
283 0,
284 0
285 );
286 var date = new Date(
287 this._showYear,
288 this._showMonth - 1,
289 1,
290 0,
291 0,
292 0,
293 0
294 );
295 var today = new Date();
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000296 var that = this;
Nils Diewald7148c6f2015-05-04 15:07:53 +0000297
298 // What happens, in case someone clicks
299 // on a date
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000300 var click = function () {
301 that.set(
302 that._showYear,
303 that._showMonth,
304 parseInt(this.firstChild.data)
305 );
306 };
Nils Diewalda1228622015-04-25 01:59:10 +0000307
308 // Skip back to the previous monday (may be in the last month)
309 date.setDate(date.getDate() - ((date.getDay() + 6) % 7));
310
311 var tb = d.createElement('tbody');
312
313 var s = this.select();
314
315 // Iterate over all days of the table
316 while (1) {
317
318 // Loop through the week
319 var tr = tb.appendChild(d.createElement('tr'));
320 for (var i = 0; i < 7; i++) {
321 var td = tr.appendChild(d.createElement('td'));
322
323 // Not part of the current month
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000324 if (date.getMonth() !== showDate.getMonth()) {
Nils Diewalda1228622015-04-25 01:59:10 +0000325 td.classList.add('out');
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000326 }
327 else {
328 td.onclick = click;
329 };
Nils Diewalda1228622015-04-25 01:59:10 +0000330
331 // This is the current day
332 if (date.getDate() === today.getDate() &&
333 date.getMonth() === today.getMonth() &&
334 date.getFullYear() === today.getFullYear()) {
335 td.classList.add('today');
336 };
337
338 // This is the day selected
Nils Diewald87507832015-05-01 23:36:41 +0000339 if (s && s['day']) {
Nils Diewalda1228622015-04-25 01:59:10 +0000340 if (date.getDate() === s['day'] &&
341 date.getMonth() === s['month']-1 &&
342 date.getFullYear() === s['year']) {
343 td.classList.add('selected');
344 };
345 };
346
347 // Add the current day to the table
348 td.appendChild(
349 d.createTextNode(date.getDate())
350 );
351
352 // Next day
353 date.setDate(date.getDate() + 1);
354 };
355
356 if (date.getMonth() !== showDate.getMonth())
357 break;
358 };
359 return tb;
360 },
361
Nils Diewald7148c6f2015-05-04 15:07:53 +0000362 // Update the calendar view
Nils Diewalda1228622015-04-25 01:59:10 +0000363 _updateDay : function () {
364 var newBody = this._dayBody();
365 this._dBElement.parentNode.replaceChild(
366 newBody,
367 this._dBElement
368 );
369 this._dBElement = newBody;
370 }
371 };
372});