[EventManager]update EventManager(tizen_2.1)
[samples/web/EventManager.git] / js / app.ui.js
1 /*jslint devel: true*/
2 /*global $, app, TemplateManager */
3
4 /**
5  * @class Ui
6  */
7 function Ui() {
8         'use strict';
9 }
10
11 (function () { // strict mode wrapper
12         'use strict';
13         Ui.prototype = {
14
15                 templateManager: null,
16
17                 /**
18                  * UI module initialisation
19                  */
20                 init: function UI_init(app) {
21                         this.app = app;
22                         this.templateManager = new TemplateManager();
23                         $(document).ready(this.domInit.bind(this));
24
25                         // init inner objects
26                         this.home.context = this;
27                         this.alarm.context = this;
28                         this.new_event.context = this;
29                 },
30
31                 /**
32                  * When DOM is ready, initialise it
33                  */
34                 domInit: function UI_domInit() {
35                         this.templateManager.loadToCache(['home', 'alarm', 'new_event', 'event'], this.initPages.bind(this));
36                         // Disable text selection
37                         $.mobile.tizen.disableSelection(document);
38                 },
39
40                 /**
41                  * Append pages to body and initialise them
42                  */
43                 initPages: function UI_initPages() {
44                         var pages = [];
45
46                         pages.push(this.templateManager.get('home'));
47                         pages.push(this.templateManager.get('alarm'));
48                         pages.push(this.templateManager.get('new_event'));
49
50                         $('body').append(pages.join(''));
51
52                         this.home.init();
53                         this.alarm.init();
54                         this.new_event.init();
55
56                         $.mobile.changePage('#home', 'pop', false, true);
57                 },
58
59
60                 /**
61                  * Contains methods related to the #home page
62                  * @namespace
63                  */
64                 home: {
65                         init: function UI_home_init() {
66                                 var app = this.context.app, self = this, alarm = this.context.alarm;
67
68                                 $('#exit_btn').on('tap', app.exit.bind(app));
69                                 $("input:radio").checkboxradio();
70                                 alarm.selectOption();
71
72                                 // buttons in the events list
73                                 $('#events_list').on('tap', '.remove_event_btn', function () {
74                                         var eventId = $(this).parents('.event').data('eventid');
75                                         app.model.deleteEvent(eventId);
76                                 });
77
78                                 $('#events_list').on('click', '.edit_event_btn', function () {
79                                         var eventId = $(this).parents('.event').data('eventid'),
80                                                 event = app.model.editEvent(eventId), field, date, duration, key;
81
82                                         app.ui.new_event.dateResetLock(true);
83                                         app.eventId = eventId;
84                                         for (key in event) {
85                                                 if (event.hasOwnProperty(key)) {
86                                                         field = $('#new_event input[name="' + key + '"]');
87                                                         if (field.length !== 0) {
88                                                                 if (field.attr('type') === 'datetime') {
89                                                                         date = self.TZD2Date(event[key]);
90                                                                         field.datetimepicker('value', date);
91                                                                 } else {
92                                                                         field.val(event[key]);
93                                                                 }
94                                                         }
95                                                 }
96                                         }
97
98                                         $('#new_event h1').text('Edit Event');
99                                         $('#add_alarm').hide();
100
101                                         if (event.alarms.length !== 0) {
102                                                 duration = event.alarms[0].before.length;
103                                         }
104                                         alarm.selectOption(alarm.getValue(duration || 0));
105                                         $.mobile.changePage("#new_event");
106                                 });
107
108                                 $('#newEventBtn').on('tap', function () {
109                                         app.ui.new_event.dateResetLock(false);
110                                         app.eventId = 0;
111                                         $('#new_event h1').text('New Event');
112                                         $('#title').val('');
113                                         $('#add_alarm').css('display', 'inline-block');
114                                         alarm.selectOption();
115                                 });
116
117                                 this.loadEvents();
118                         },
119
120                         TZD2Date: function (tzdate) {
121                                 return new Date(
122                                         tzdate.getFullYear(),
123                                         tzdate.getMonth(),
124                                         tzdate.getDate(),
125                                         tzdate.getHours(),
126                                         tzdate.getMinutes(),
127                                         tzdate.getSeconds(),
128                                         tzdate.getMilliseconds()
129                                 );
130                         },
131
132                         /**
133                          * Get start date value from the form (#demo-date-1 field)
134                          *
135                          * @returns {string}
136                          */
137                         getStartDate: function UI_home_getStartDate() {
138                                 var startDate = $('#demo-date-1').attr('data-date');
139                                 return startDate;
140                         },
141                         /**
142                          * Get end date value from the form (#demo-date-2 field)
143                          *
144                          * @returns {string}
145                          */
146                         getEndDate: function UI_home_getEndDate() {
147                                 var endDate = $('#demo-date-2').attr('data-date');
148                                 return endDate;
149                         },
150                         /**
151                          * Get the title from the form (#title field)
152                          *
153                          * @returns {string}
154                          */
155                         getTitle: function UI_home_getTitle() {
156                                 return $('#title').val();
157                         },
158                         /**
159                          * Get the description from the form (#des field)
160                          *
161                          * @returns {string}
162                          */
163                         getDescription: function UI_home_getDescription() {
164                                 return $('#des').val();
165                         },
166                         /**
167                          * Get the location from the form (#location field)
168                          *
169                          * @returns {string}
170                          */
171                         getLocation: function UI_home_getLocation() {
172                                 return $('#location').val();
173                         },
174                         /**
175                          * Wrapper for app.loadEvents
176                          * @param {Object} e event
177                          * @param {Date} date selected date
178                          */
179                         loadEvents: function UI_home_loadEvents(e, date) {
180                                 this.context.app.loadEvents(date);
181                         },
182
183                         /**
184                          * Returns text for separating list items with events
185                          * Skips repeated values
186                          *
187                          * @param {Object} event
188                          * @returns {string}
189                          */
190                         getSeparatorText: function UI_home_getSeparatorText(event) {
191                                 var previous = '';
192
193                                 // redefine itself
194                                 this.getSeparatorText = function (event) {
195                                         if (event === undefined) {
196                                                 previous = '';
197                                                 return undefined;
198                                         }
199
200                                         var startDate = event.startDate,
201                                                 str = this.formatDate(startDate);
202
203                                         if (previous === str) {
204                                                 return ''; // skip it - already returned
205                                         }
206                                         previous = str; // store in the closure for future comparison
207
208                                         return str;
209                                 };
210
211                                 return this.getSeparatorText(event);
212                         },
213
214                         formatDate: function UI_home_formatDate(date) {
215                                 var monthNames = [
216                                         "January", "February", "March", "April", "May", "June",
217                                         "July", "August", "September", "October", "November", "December" ];
218
219                                 this.formatDate = function UI_home_formatDate(date) {
220                                         return date.getDate() + ". " + monthNames[date.getMonth()] + " " + date.getFullYear();
221                                 };
222                                 return this.formatDate(date);
223                         },
224
225                         /**
226                          * Format hour
227                          * @param {TZDate} date
228                          * @returns {string}
229                          */
230                         formatHour: function UI_home_formatHour(date) {
231                                 return date.getHours() + ':' + this.pad(date.getMinutes());
232                         },
233
234                         /**
235                          * Zero-pads a positive number to 2 digits
236                          */
237                         pad: function UI_home_pad(number) {
238                                 return number < 10 ? '0' + number : number;
239                         },
240
241                         /**
242                          * Creates HTML representing the given array of alarms
243                          *
244                          * @param {Alarm[]} alarms
245                          * @returns {string}
246                          */
247                         getAlarmsHtml: function UI_home_getAlarmsHtml(alarms) {
248                                 var alarm = '', j, len;
249
250                                 len = alarms.length;
251
252                                 if (len) {
253                                         alarm += '<p class="ui-li-aside ui-li-desc"><img src="img/clock.png"/>';
254
255                                         for (j = 0; j < len; j += 1) {
256                                                 alarm += alarms[j].before.length;
257                                                 alarm += ' ' + alarms[j].before.unit;
258                                         }
259                                         alarm += '</p>';
260                                 }
261                                 return alarm;
262                         },
263                         /**
264                          * Load the events into the #event_popup.
265                          *
266                          * Callback function for app.loadEvents.
267                          * @param {Array} events
268                          */
269                         onEventSearchSuccess: function UI_home_onEventSearchSuccess(events) {
270                                 var i = 0, j = 0,
271                                         str = "",
272                                         event,
273                                         alarm = '',
274                                         dividerText = '',
275                                         templateParameters = {};
276
277                                 // content
278                                 str = '';
279
280                                 for (i = 0; i < events.length; i += 1) {
281                                         event = events[i];
282
283                                         dividerText = this.getSeparatorText(event);
284
285                                         if (dividerText) {
286                                                 str += '<li data-role="list-divider">' + dividerText + '</li>';
287                                         }
288
289                                         alarm = this.getAlarmsHtml(event.alarms);
290
291                                         templateParameters = {
292                                                 uid: event.id.uid,
293                                                 startDate: this.formatHour(event.startDate),
294                                                 endDate: this.formatHour(event.endDate),
295                                                 summary: event.summary || '[No title]',
296                                                 location: event.location,
297                                                 description: event.description,
298                                                 alarm: alarm
299                                         };
300
301                                         str += this.context.templateManager.get('event', templateParameters);
302
303                                 }
304                                 this.getSeparatorText(); // clear the separator state
305
306                                 $('#events_list ul').html(str);
307                                 $('#events_list ul').listview();
308                                 $('#events_list ul').data('listview').refresh();
309                                 $('#events_list ul input.edit_event_btn').button();
310                                 $('#events_list ul input.remove_event_btn').button();
311                         },
312
313                         /**
314                          * Error handler for event search
315                          */
316                         onEventSearchError: function UI_home_onEventSearchError() {
317                                 console.error("event search error");
318                         }
319                 },
320
321                 /**
322                  * Contains methods related to the #alarm page
323                  * @namespace
324                  */
325                 alarm: {
326                         init: function UI_alarm_init() {
327                         },
328                         /**
329                          * Read alarm duration from the UI
330                          *
331                          * @returns {int} Alarm duration in minutes
332                          */
333                         selectOption: function (val) {
334                                 val = val || 1;
335                                 $.each($('#new_alarm input:radio'), function () {
336                                         $(this).attr('checked', parseInt($(this).val(), 10) === val)
337                                                 .checkboxradio('refresh');
338                                 });
339                                 this.updateDurationLabel();
340                         },
341
342                         getDuration: function UI_alarm_getDuration() {
343                                 var radioValue = 0,
344                                         radiobutton = null;
345
346                                 radiobutton = $('#new_alarm :jqmData(role=controlgroup) input:radio[checked]');
347
348                                 radioValue = parseInt(radiobutton.val(), 10);
349
350                                 switch (radioValue) {
351                                 case 1: // no alarm
352                                         return 0;
353                                 case 2: // 5 minutes before
354                                         return 5;
355                                 case 3: // 30 minutes before
356                                         return 30;
357                                 case 4: // 1 hour before
358                                         return 60;
359                                 default:
360                                         console.warn('Unexpected duration value');
361                                         return 0;
362                                 }
363                         },
364                         getValue: function (duration) {
365                                 var table = {0: 1, 5: 2, 30: 3, 60: 4};
366                                 return table[duration];
367                         },
368
369                         /**
370                          * Read and set alarm duration label
371                          *
372                          * @returns {string} Label
373                          */
374                         updateDurationLabel: function () {
375                                 var label = $('#new_alarm input:radio[checked]').next().text();
376                                 $('#alarm').text(label);
377                                 return label;
378                         }
379                 },
380
381                 /**
382                  * Contains methods related to the new event page
383                  * @namespace
384                  */
385                 new_event: {
386                         init: function UI_newEvent_init() {
387                                 var app = this.context.app,
388                                         self = this;
389                                 $("#demo-date-1, #demo-date-2").datetimepicker();
390                                 $("#demo-date-1").bind("date-changed", function UI_newEvent_onDateChanged(e, newStartDate) {
391                                         var startOptions = $(this).data('datetimepicker').options,
392                                                 endData = $("#demo-date-2").data('datetimepicker'),
393                                                 endOptions = typeof endData === 'object' ? endData.options : null,
394                                                 oldStartDate,
395                                                 diff,
396                                                 endDate;
397                                         // get the old date
398                                         oldStartDate = startOptions.oldDate;
399                                         startOptions.oldDate = newStartDate;
400
401                                         if (!oldStartDate) {
402                                                 console.warn('date-changed handler: old date empty');
403                                                 return;
404                                         }
405
406                                         // calculate time difference in minutes
407                                         diff = (newStartDate.getTime() - oldStartDate.getTime()) / 1000 / 60;
408
409                                         endDate = endOptions.date;
410
411                                         // move the end date by 'diff'
412                                         endDate.setMinutes(endDate.getMinutes() + diff);
413
414                                         $("#demo-date-2").datetimepicker('value', endDate);
415                                 });
416
417                                 $("#demo-date-2").bind("date-changed", function (e, newEndDate) {
418                                         var endOptions = $(this).data('datetimepicker').options,
419                                                 self = $(this),
420                                                 stardDate = $("#demo-date-1").data('datetimepicker').options.date,
421                                                 oldEndDate;
422
423                                         oldEndDate = endOptions.oldDate;
424
425                                         if (newEndDate - stardDate < 0) {
426                                                 $("#date-2 .ui-datefield span").animationComplete(function () {
427                                                         alert('End date cannot be earlier than initial date');
428                                                         self.datetimepicker('value', oldEndDate);
429                                                         self.datetimepicker();
430                                                 });
431                                         } else {
432                                                 endOptions.oldDate = newEndDate;
433                                         }
434                                 });
435
436                                 $('#new_event').on('pageshow', function UI_newEvent_onPageShow(event) {
437                                         var startOptions = $("#demo-date-1").data('datetimepicker').options,
438                                                 date2 = $("#demo-date-2"),
439                                                 tmpDate;
440                                         // get the start date
441                                         tmpDate = new Date(startOptions.date.getTime());
442
443                                         // store it for future use
444                                         startOptions.oldDate = new Date(startOptions.date.getTime());
445
446                                         // add 1 hour
447                                         tmpDate.setHours(tmpDate.getHours() + 1);
448                                         if (self.dateResetLock() !== true) {
449                                                 if (typeof date2.datetimepicker === 'function') {
450                                                         // set end date
451                                                         date2.datetimepicker('value', tmpDate);
452                                                 } else {
453                                                         console.warn('pageinit: cant set end time');
454                                                 }
455                                         }
456
457                                         // enable OK button
458                                         $('#add-event-btn').removeClass('disabled');
459                                 });
460
461                                 $('#switch-1').bind('changed', app.switchFullDay.bind(app));
462
463                                 $('#add-event-btn').bind('tap', this.addEvent.bind(this));
464
465                                 $('#new-event-cancel-btn').bind('tap', this.cancel.bind(this));
466
467                                 //alarm selection confirm
468                                 $('#add-alarm').bind('tap', app.switchAlarm.bind(app));
469
470                                 // go to alarm selection
471                                 $('#add_alarm').bind('tap', this.dateResetLock.bind(this, true));
472
473                                 $('#new_event').on('tap', '[data-role="content"]', function (e) {
474                                         e.stopPropagation();
475                                 });
476                         },
477
478                         /**
479                          * Select an alarm value
480                          */
481                         switchAlarm: function Ui_newEvent_switchAlarm(e) {
482                                 console.log('Ui_newEvent_switchAlarm');
483                                 this.dateResetLock(false);
484                                 this.context.app.switchAlarm(e);
485                         },
486
487                         /**
488                          * Set reset lock (true - locked, false - unlocked)
489                          * If no or undefined value given, return the current value
490                          * @param {bool} value
491                          * @returns {bool}
492                          */
493                         dateResetLock: function Ui_newEvent_dateResetLock(value) {
494                                 if (value === undefined) {
495                                         return $("#demo-date-2").data('resetLock');
496                                 }
497                                 $("#demo-date-2").data('resetLock', value);
498                                 return value;
499                         },
500
501                         addEvent: function Ui_newEvent_addEvent(e) {
502                                 var button = $('#add-event-btn');
503                                 this.dateResetLock(false);
504                                 if (!button.hasClass('disabled')) {
505                                         button.addClass('disabled');
506                                         if (app.eventId === 0) {
507                                                 this.context.app.addEvent(e);
508                                         } else {
509                                                 this.context.app.updateEvent(e);
510                                         }
511                                 }
512                         },
513
514                         cancel: function Ui_newEvent_cancel(e) {
515                                 this.dateResetLock(false);
516                         }
517                 }
518         };
519
520 }());