blob: 6d3086dbb4418ddd9e99d18e2403cde4d86d05c5 [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 () {
38 return this;
39 },
40
Nils Diewald7148c6f2015-05-04 15:07:53 +000041 /**
42 * Get or select a specific date.
43 */
Nils Diewalda1228622015-04-25 01:59:10 +000044 select : function (year, month, day) {
45 if (arguments.length >= 1) {
46 this._selected = {'year' : year};
47 if (arguments.length >= 2) {
48 this._selected['month'] = month;
49 if (arguments.length >= 3)
50 this._selected['day'] = day;
51 };
52 return this;
53 };
54 return this._selected;
55 },
56
Nils Diewald7148c6f2015-05-04 15:07:53 +000057
58 /**
59 * Select a specific date and
60 * init the accompanied action.
61 */
62 set : function (year, month, day) {
63 this.select(year, month, day);
64 if (this._click !== undefined)
65 this._click(this._selected);
66 else
67 console.dir(this._selected);
68 },
69
70
71 /**
72 * Set the action for clicking as a callback.
73 * The callback will retrieve a an object with
74 * an optional year attribute,
75 * an optional month attribute,
76 * and an optional day attribute
77 */
78 onclick : function (cb) {
79 this._click = cb;
80 },
81
82 /**
83 * Show the datepicker.
84 * Will either show the selected year/month
85 * or the current date.
86 * Will return the element for appending to the dom.
87 */
Nils Diewalda1228622015-04-25 01:59:10 +000088 show : function (year, month) {
Nils Diewald7148c6f2015-05-04 15:07:53 +000089 var e = this._element = d.createElement('div');
90 e.setAttribute('tabindex', 0);
91 e.style.outline = 0;
92 e.classList.add('datepicker');
93
94 var today = new Date();
95
96 // Show year
97 this._showYear = year ? year :
98 (this._selected['year'] ? this._selected['year'] :
99 today.getYear());
100
101 // Show month
102 this._showMonth = month ? month :
103 (this._selected['month'] ? this._selected['month'] :
104 (today.getMonth() + 1));
105
106 // Append all helpers
Nils Diewald87507832015-05-01 23:36:41 +0000107 this._element.appendChild(this._monthHelper());
108 this._element.appendChild(this._yearHelper());
109 this._element.appendChild(this._dayHelper());
110 return this._element;
111 },
112
Nils Diewald7148c6f2015-05-04 15:07:53 +0000113 /**
114 * Get the HTML element associated with the datepicker.
115 */
Nils Diewald87507832015-05-01 23:36:41 +0000116 element : function () {
117 return this._element;
Nils Diewalda1228622015-04-25 01:59:10 +0000118 },
119
Nils Diewald7148c6f2015-05-04 15:07:53 +0000120
121 /**
122 * Increment the year.
123 */
Nils Diewalda1228622015-04-25 01:59:10 +0000124 incrYear : function () {
125 this._showYear++;
126 this._updateYear();
127 this._updateMonth();
128 this._updateDay();
129 return;
130 },
131
Nils Diewald7148c6f2015-05-04 15:07:53 +0000132 /**
133 * Decrement the year.
134 */
Nils Diewalda1228622015-04-25 01:59:10 +0000135 decrYear : function () {
136 this._showYear--;
137 this._updateYear();
138 this._updateMonth();
139 this._updateDay();
140 return;
141 },
142
Nils Diewald7148c6f2015-05-04 15:07:53 +0000143 /**
144 * Increment the month.
145 */
Nils Diewalda1228622015-04-25 01:59:10 +0000146 incrMonth : function () {
147 this._showMonth++;
148 if (this._showMonth > 12) {
149 this._showMonth = 1;
150 this.incrYear();
151 }
152 else {
153 this._updateMonth();
154 this._updateDay();
155 };
156 },
157
Nils Diewald7148c6f2015-05-04 15:07:53 +0000158 /**
159 * Decrement the month.
160 */
Nils Diewalda1228622015-04-25 01:59:10 +0000161 decrMonth : function () {
162 this._showMonth--;
163 if (this._showMonth < 1) {
164 this._showMonth = 12;
165 this.decrYear();
166 }
167 else {
168 this._updateMonth();
169 this._updateDay();
170 };
171 },
172
Nils Diewald7148c6f2015-05-04 15:07:53 +0000173
174 // Create the year helper element.
Nils Diewalda1228622015-04-25 01:59:10 +0000175 _yearHelper : function () {
176 var year = d.createElement('div');
177 year.classList.add('year');
178
179 // Decrement year
180 year.appendChild(d.createElement('span'))
181 .onclick = this.decrYear.bind(this);
182
183 this._yElement = year.appendChild(d.createElement('span'));
184 this._yElement.appendChild(document.createTextNode(this._showYear));
185
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000186 this._yElement.onclick = function () {
187 this.set(this._showYear);
188 }.bind(this);
Nils Diewald7148c6f2015-05-04 15:07:53 +0000189 this._selectYear();
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000190
Nils Diewalda1228622015-04-25 01:59:10 +0000191 // Increment year
192 year.appendChild(d.createElement('span'))
193 .onclick = this.incrYear.bind(this);
194
195 return year;
196 },
197
Nils Diewald7148c6f2015-05-04 15:07:53 +0000198 // Update the year helper view.
Nils Diewalda1228622015-04-25 01:59:10 +0000199 _updateYear : function () {
200 this._yElement.firstChild.data = this._showYear;
Nils Diewald7148c6f2015-05-04 15:07:53 +0000201 this._selectYear();
Nils Diewalda1228622015-04-25 01:59:10 +0000202 },
203
Nils Diewald7148c6f2015-05-04 15:07:53 +0000204
205 // Check if the viewed year is current
206 _selectYear : function () {
207 if (this._showYear === this.select()['year'])
208 this._yElement.classList.add('selected');
209 else
210 this._yElement.classList.remove('selected');
211 },
212
213
214 // Create the month helper element.
Nils Diewalda1228622015-04-25 01:59:10 +0000215 _monthHelper : function () {
216 var month = d.createElement('div');
217 month.classList.add('month');
218
219 // Decrement month
220 month.appendChild(d.createElement('span'))
221 .onclick = this.decrMonth.bind(this);
222
223 this._mElement = month.appendChild(d.createElement('span'));
224 this._mElement.appendChild(
225 document.createTextNode(loc.MONTH[this._showMonth-1])
226 );
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000227 this._mElement.onclick = function () {
228 this.set(this._showYear, this._showMonth);
229 }.bind(this);
Nils Diewald7148c6f2015-05-04 15:07:53 +0000230
231 this._selectMonth();
Nils Diewalda1228622015-04-25 01:59:10 +0000232
233 // Increment month
234 month.appendChild(d.createElement('span'))
235 .onclick = this.incrMonth.bind(this);
236
237 return month;
238 },
239
Nils Diewald7148c6f2015-05-04 15:07:53 +0000240 // Update the month helper view.
Nils Diewalda1228622015-04-25 01:59:10 +0000241 _updateMonth : function () {
242 this._mElement.firstChild.data = loc.MONTH[this._showMonth-1];
Nils Diewald7148c6f2015-05-04 15:07:53 +0000243 this._selectMonth();
Nils Diewalda1228622015-04-25 01:59:10 +0000244 },
245
Nils Diewald7148c6f2015-05-04 15:07:53 +0000246
247 // Check if the viewed month is current
248 _selectMonth : function () {
249 if (this._showYear === this.select()['year'] &&
250 this._showMonth === this.select()['month'])
251 this._mElement.classList.add('selected');
252 else
253 this._mElement.classList.remove('selected');
254 },
255
256
257 // Create the day (calendar) helper element.
Nils Diewalda1228622015-04-25 01:59:10 +0000258 _dayHelper : function () {
259 var table = d.createElement('table');
260
Nils Diewald7148c6f2015-05-04 15:07:53 +0000261 // Localized day view
Nils Diewalda1228622015-04-25 01:59:10 +0000262 var tr = table.appendChild(d.createElement('thead'))
263 .appendChild(d.createElement('tr'));
264 for (var i = 0; i < 7; i++) {
265 tr.appendChild(d.createElement('th'))
266 .appendChild(d.createTextNode(loc.WDAY[i]));
267 };
268
269 this._dBElement = this._dayBody();
270
271 table.appendChild(this._dBElement);
272 return table;
273 },
274
275 _dayBody : function () {
Nils Diewald7148c6f2015-05-04 15:07:53 +0000276 var showDate = new Date(
277 this._showYear,
278 this._showMonth - 1,
279 1,
280 0,
281 0,
282 0,
283 0
284 );
285 var date = new Date(
286 this._showYear,
287 this._showMonth - 1,
288 1,
289 0,
290 0,
291 0,
292 0
293 );
294 var today = new Date();
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000295 var that = this;
Nils Diewald7148c6f2015-05-04 15:07:53 +0000296
297 // What happens, in case someone clicks
298 // on a date
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000299 var click = function () {
300 that.set(
301 that._showYear,
302 that._showMonth,
303 parseInt(this.firstChild.data)
304 );
305 };
Nils Diewalda1228622015-04-25 01:59:10 +0000306
307 // Skip back to the previous monday (may be in the last month)
308 date.setDate(date.getDate() - ((date.getDay() + 6) % 7));
309
310 var tb = d.createElement('tbody');
311
312 var s = this.select();
313
314 // Iterate over all days of the table
315 while (1) {
316
317 // Loop through the week
318 var tr = tb.appendChild(d.createElement('tr'));
319 for (var i = 0; i < 7; i++) {
320 var td = tr.appendChild(d.createElement('td'));
321
322 // Not part of the current month
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000323 if (date.getMonth() !== showDate.getMonth()) {
Nils Diewalda1228622015-04-25 01:59:10 +0000324 td.classList.add('out');
Nils Diewaldbdf79c52015-04-29 23:47:13 +0000325 }
326 else {
327 td.onclick = click;
328 };
Nils Diewalda1228622015-04-25 01:59:10 +0000329
330 // This is the current day
331 if (date.getDate() === today.getDate() &&
332 date.getMonth() === today.getMonth() &&
333 date.getFullYear() === today.getFullYear()) {
334 td.classList.add('today');
335 };
336
337 // This is the day selected
Nils Diewald87507832015-05-01 23:36:41 +0000338 if (s && s['day']) {
Nils Diewalda1228622015-04-25 01:59:10 +0000339 if (date.getDate() === s['day'] &&
340 date.getMonth() === s['month']-1 &&
341 date.getFullYear() === s['year']) {
342 td.classList.add('selected');
343 };
344 };
345
346 // Add the current day to the table
347 td.appendChild(
348 d.createTextNode(date.getDate())
349 );
350
351 // Next day
352 date.setDate(date.getDate() + 1);
353 };
354
355 if (date.getMonth() !== showDate.getMonth())
356 break;
357 };
358 return tb;
359 },
360
Nils Diewald7148c6f2015-05-04 15:07:53 +0000361 // Update the calendar view
Nils Diewalda1228622015-04-25 01:59:10 +0000362 _updateDay : function () {
363 var newBody = this._dayBody();
364 this._dBElement.parentNode.replaceChild(
365 newBody,
366 this._dBElement
367 );
368 this._dBElement = newBody;
369 }
370 };
371});