4edf0793a89dc2b713ffa4f415d65455aee4929e
[samples/web/ExercisePlanner.git] / js / UI.js
1 /*jslint nomen: true*/
2 /*global $, GraphSchedule, range, history, setTimeout */
3 function UI() {
4         "use strict";
5 }
6
7 (function () {
8         "use strict";
9         UI.prototype = {
10                 sentence : {
11                         'lazy' : {
12                                 text : 'He does not seem to me to be a free man who does not sometimes do nothing.',
13                                 signature : 'Marcus T. Cicero'
14                         },
15                         'run' : {
16                                 text : 'A journey of a thousand miles begins with a  single step.',
17                                 signature : 'Lao-tzu'
18                         }
19                 },
20                 graphSchedule : null,
21                 app : null
22         };
23
24         UI.prototype.fillExercises = function (exercisesData) {
25                 var i, len, self = this;
26
27                 $('#exercises').replaceWith(
28                         $('<ul data-role="listview" id="exercises"></ul>')
29                 );
30                 for (i = 0, len = exercisesData.length; i < len; i += 1) {
31                         $('#exercises').append(
32                                 $(this.getExercisesTemplate(exercisesData[i], i))
33                         );
34                 }
35                 $('#exercises').listview();
36                 $('#exercises :jqmData(role="slider")').slider();
37                 $('#exercises li').on('click', function () {
38                         var $toggle = $(this).find(':jqmData(role="slider")');
39                         $toggle.val(($toggle.val() === 'off') ? 'on' : 'off');
40                         $toggle.slider('refresh');
41                         self.app.saveExercises(self.getExercisesList());
42                 });
43                 $('#exercises :jqmData(role="slider")').on('change', function (e) {
44                         e.preventDefault();
45                         e.stopPropagation();
46                         self.app.saveExercises(self.getExercisesList());
47                 });
48         };
49
50         UI.prototype.popup = function (text, callback) {
51                 var i, popup = $("#popup"),
52                         buttons = {'Cancel': function () { $("#popup").popup('close') }};
53                 // to hide default button give {'Cancel': false} in callback
54
55                 for (i in callback) {
56                         if (callback.hasOwnProperty(i)) {
57                                 buttons[i] = callback[i];
58                         }
59                 }
60
61                 $(".ui-popup-button-bg", popup).empty();
62                 for (i in buttons) {
63                         if (buttons.hasOwnProperty(i)) {
64                                 if (buttons[i]) {
65                                         $('<a/>')
66                                                 .text(i)
67                                                 .attr({'data-role': 'button', 'data-inline': 'true'})
68                                                 .bind('click', buttons[i])
69                                                 .appendTo($(".ui-popup-button-bg", popup));
70                                 }
71                         }
72                 }
73                 $(".text", popup).text(text);
74
75                 popup.trigger("create");
76                 popup.popup('open', {positionTo: 'window'});
77
78                 // N_SE-49979 workaround to unlock forbidden keys
79                 popup.one("popupafterclose", function () {
80                         $(document).off('keydown');
81                 });
82         };
83
84         UI.prototype.clearTabbars = function () {
85                 $('[data-role = "tabbar"] li > a').removeClass('ui-focus, ui-btn-active');
86         };
87
88         UI.prototype.fillTimesRanges = function (timesData) {
89                 var self = this, len, i;
90
91                 $('#availableTime').replaceWith(
92                         $('<ul data-role="listview" id="availableTime"></ul>')
93                 );
94                 for (i = 0, len = timesData.length; i < len; i += 1) {
95                         $('#availableTime')
96                                 .append($(this.getAvailableTimeTemplate(timesData[i])));
97                 }
98                 $('#availableTime').trigger('create');
99                 $('#availableTime').listview().listview('refresh');
100                 $('#availableTime :jqmData(name=edit)').on('click', function (e) {
101                         if (self.app.config.trainingEnabled) {
102                                 self.popup('You should stop the training first');
103                         } else {
104                                 e.preventDefault();
105                                 e.stopPropagation();
106                                 self.editTimeRange($(this).data('val'));
107                         }
108                 });
109                 $('#availableTime :jqmData(name=disable)').on('click', function (e) {
110                         if (self.app.config.trainingEnabled) {
111                                 self.popup('You should stop the training first');
112                         } else {
113                                 e.stopPropagation();
114                                 self.app.disableTimeRange($(this).data('val'));
115                         }
116                 });
117                 $('#availableTime :jqmData(name=delete)').on('click', function (e) {
118                         var value = $(this).data('val');
119                         e.stopPropagation();
120                         if (self.app.config.trainingEnabled) {
121                                 self.popup('You should stop the training first');
122                                 return;
123                         }
124                         self.popup('Are you sure?', {
125                                 'Delete': function () {
126                                         self.app.deleteTimeRange(value);
127                                         $("#popup").popup('close');
128                                 }
129                         });
130                 });
131         };
132
133         UI.prototype.fillTimeRangeForm = function fillTimeRangeForm(timeRange) {
134                 var tmpData = new Date();
135                 // Filling form;
136                 $('#startTime').attr('data-val',
137                                 new Date(tmpData.setHours(timeRange.start)));
138                 $('#duration').attr('data-val', timeRange.duration);
139
140                 if ($('#startTime').data('datetimepicker')) {
141                         $('#startTime').data('datetimepicker').options.date
142                                 .setHours(timeRange.start);
143                         $('#startTime').data('datetimepicker').ui
144                                 .find('.ui-datefield-hour').html(
145                                         (timeRange.start < 10) ? '0' + timeRange.start : timeRange.start
146                                 );
147                 }
148                 if ($('#duration').data('datetimepicker')) {
149                         $('#duration').data('datetimepicker').options.date
150                                 .setHours(timeRange.duration);
151                         $('#duration').data('datetimepicker').ui.find('.ui-datefield-hour')
152                                 .html(
153                                         (timeRange.duration < 10) ? '0'
154                                                 + timeRange.duration : timeRange.duration
155                                 );
156                         $('#duration').data('datetimepicker')._populateDataSelector = function (field, pat) {
157                                 var result = $.tizen.datetimepicker.prototype._populateDataSelector
158                                                 .call(this, field, pat);
159                                 result.values = range(1, 20);
160                                 result.data = range(1, 20);
161                                 result.current -= 1;
162                                 return result;
163                         };
164                 }
165                 $.each($("input[name='periodType']"), function () {
166                         $(this).attr('checked', $(this).val() === timeRange.style)
167                                 .checkboxradio('refresh');
168                 });
169                 $('#formEnablePeriod')[0].value = timeRange.enabled ? 'on' : 'off';
170                 $('#formEnablePeriod').slider('refresh');
171         };
172
173         UI.prototype.editTimeRange = function (nr, event) {
174                 if (event && typeof event.stopPropagation === 'function') {
175                         event.preventDefault();
176                         event.stopPropagation();
177                 }
178
179                 if (this.app.editTimeRange(nr) >= 0) {
180                         $('#updateTime').val('modify');
181                         $('#rangesOfTimes h1').text('Edit Time');
182                 } else {
183                         $('#updateTime').val('add');
184                         $('#rangesOfTimes h1').text('Add Time');
185                 }
186
187                 // change page to form;
188                 $.mobile.changePage("#rangesOfTimes");
189         };
190
191         UI.prototype.getExercisesList = function () {
192                 return $('#exercises :jqmData(role=slider)').map(function (o, v) {
193                         return ({
194                                 index : $(v).attr('data-index'),
195                                 checked : ($(v).val() === 'on') ? true : false
196                         });
197                 });
198         };
199
200         UI.prototype.addExercise = function () {
201                 var trimmedName = $("#newExerciseName").val().trim();
202                 trimmedName = $('<span>').text(trimmedName).html();
203                 if (trimmedName !== '') {
204                         if (this.app.addExercise(trimmedName)) {
205                                 $("#newExerciseName").trigger('blur');
206                                 setTimeout(history.back.bind(history), 50);
207                         }
208                 } else {
209                         this.showErrors([ {
210                                 name : 'Name of exercise is not correct.',
211                                 code : 100
212                         } ]);
213                 }
214         };
215
216         UI.prototype.configToUI = function () {
217         };
218
219         UI.prototype.updateMainUI = function () {
220                 this.setStatusRun(this.app.config.trainingEnabled);
221                 this.graphSchedule.setTimeRanges(this.app.periodsWeekToBoolArray());
222         };
223
224         UI.prototype.getTimeRangeFromForm = function () {
225                 return {
226                         start : $('#startTime').data('datetimepicker').options.date
227                                         .getHours(),
228                         duration : $('#duration').data('datetimepicker').options.date
229                                         .getHours(),
230                         stop : $('#startTime').data('datetimepicker').options.date
231                                         .getHours()
232                                         + $('#duration').data('datetimepicker').options.date
233                                                         .getHours(),
234                         style : $('.selectPeriodType :radio:checked').val(),
235                         enabled : ($('#formEnablePeriod')[0].value === 'on' ? true : false)
236                 };
237         };
238
239         UI.prototype.editTimeRangeAction = function (nr) {
240                 if (this.app.saveTimeRange(nr, this.getTimeRangeFromForm())) {
241                         history.back();
242                 } else {
243                         throw ({
244                                 message : 'Time start and stop is not present.',
245                                 code : 1
246                         });
247                 }
248         };
249
250         UI.prototype.showNoticeInMonitor = function (notice, alarm) {
251                 $('#communicate').html(notice);
252                 $('#communicate').toggleClass('onAlert', alarm);
253         };
254
255         UI.prototype.changeButtonAddTime = function (text) {
256                 $('#addTime').html(text);
257         };
258
259         UI.prototype.showErrors = function (errors) {
260                 var i; // count;
261                 for (i = 0; i < errors.length; i += 1) {
262                         this.popup(errors[i].name);
263                 }
264                 this.unblockButtons();
265         };
266
267         UI.prototype.unblockButtons = function () {
268                 $('#btnNewExercise').data('disabled', false);
269         };
270
271         UI.prototype.showAlarmInMonitor = function (data) {
272                 var notice = '';
273                 function formatNN(val) {
274                         return (val < 10) ? ('0' + val) : val;
275                 }
276
277                 if (data && data.alarm && this.app.config.trainingEnabled) {
278                         this.app.currentAlarm = this.app.findCurrentAlarm();
279                         if (this.app.currentAlarm.length > 0) {
280                                 notice += 'Go... go... go...!<br>' + data.exerciseName + ' x '
281                                         + data.numberOfTimes;
282                         } else {
283                                 notice += 'Next exercises set at: '
284                                         + formatNN(data.alarm.getHours()) + ':'
285                                         + formatNN(data.alarm.getMinutes()) + '<br>'
286                                         + data.exerciseName + ' x ' + data.numberOfTimes;
287                         }
288                 } else {
289                         notice += '<br/>You have no workouts scheduled for now.<br/>';
290                 }
291                 this.showNoticeInMonitor(notice, false);
292         };
293
294         UI.prototype.getSentence = function UI_getSentence(type) {
295                 return (this.sentence[type] || {
296                         text : 'No sentence',
297                         signature : 'anonymous'
298                 });
299         };
300
301         UI.prototype.setSentence = function (type) {
302                 var sentence = this.getSentence(type);
303                 $('#sentence').html('"' + sentence.text + '"');
304                 $('#signature').html('- ' + sentence.signature);
305         };
306
307         UI.prototype.showWaitOk = function () {
308                 $('#mainControl').hide();
309                 $('#one .ui-btn-back').hide();
310
311                 $('#onAlertControl').tabbar();
312                 $('#onAlertControl').show();
313                 $('#onAlertControl').css('width', '');
314         };
315
316         UI.prototype.setStatusRun = function (bool) {
317                 if (bool) {
318                         // icon;
319                         $('#status').removeClass('lazy').addClass('run');
320                         // sentence;
321                         this.setSentence('run');
322                         // button in control bar;
323                         $('#startStop .ui-btn-text').html('Stop Training');
324                 } else {
325                         $('#status').removeClass('run').addClass('lazy');
326                         this.setSentence('lazy');
327                         $('#communicate').html('');
328                         $('#startStop .ui-btn-text').html('Start Training');
329                 }
330         };
331
332         UI.prototype.bindEvents = function bindEvents() {
333                 var self = this;
334
335                 // bind events;
336                 $("#popup").popup();
337
338                 $('#one .ui-btn-back').on('click', this.app.exit.bind(this.app));
339
340                 $('#ok').on('click', self.app.ok.bind(self.app));
341                 $('#wait').on('click', self.app.wait.bind(self.app));
342                 $('#todayOffAll').on('click', self.app.todayOffAll.bind(self.app));
343
344                 $('[data-role = "tabbar"] li > a').on('click', function () {
345                         self.clearTabbars();
346                 });
347
348                 $('#startStop').on('click', function () {
349                         self.app.appStartStop();
350                 });
351
352                 document.addEventListener('tizenhwkey', function(e) {
353                         if (e.keyName == 'back') {
354                                 if ($.mobile.popup.active) {
355                                         $.mobile.popup.active.close();
356                                 } else if ($.mobile.activePage.attr('id') === 'one') {
357                                         tizen.application.getCurrentApplication().exit();
358                                 } else {
359                                         history.back();
360                                 }
361                         }
362                 });
363
364                 $('#one').on(
365                         'pageshow',
366                         function (page, options) {
367                                 if (self.graphSchedule.ui) {
368                                         $('#one .schedule').append(self.graphSchedule.ui);
369                                         self.app.updateGraph();
370                                         self.graphSchedule.refresh();
371                                         self.graphSchedule.setVisibleWeekend(!self.app
372                                                 .todayIsWorkday());
373                                         self.graphSchedule.setVisibleWorkdays(self.app
374                                                 .todayIsWorkday());
375                                 }
376                                 $('#one .schedule').on('touchstart', function (ev) {
377                                         ev.stopPropagation();
378                                 });
379
380                                 // workaround for scroll lock;
381                                 $.mobile.activePage.css('position', 'fixed');
382
383                                 if ($('a.ui-btn-back').is(':hidden')) {
384                                         $('div#mainControl').removeClass('ui-tabbar-margin-back');
385                                 }
386                         }
387                 );
388
389                 $('#two').on('pageshow', function (page, options) {
390                         self.fixPageHeight('#two');
391
392                         if (self.graphSchedule.ui) {
393                                 $('#two .scheduleOptions').append(self.graphSchedule.ui);
394                                 self.graphSchedule.refresh();
395                                 self.graphSchedule.setVisibleWeekend(true);
396                                 self.graphSchedule.setVisibleWorkdays(true);
397                         }
398
399                         if ($('a.ui-btn-back').is(':hidden')) {
400                                 $('div#selectExercisesBar').removeClass('ui-tabbar-margin-back');
401                         }
402                 });
403
404                 $('#two').on('pageinit', function (page, options) {
405                         $('.ui-radio input', $('#frequency')).change(function (ev) {
406                                 var that = this;
407                                 self.startProgress();
408                                 setTimeout(function (){
409                                         self.app.setFrequency(that.value);
410                                         self.updateMainUI();
411                                         self.endProgress();
412                                 }, 100);
413                         });
414
415                         $('.ui-radio input', $('#strength')).change(function (ev) {
416                                 self.app.setStrength(this.value);
417                                 self.updateMainUI();
418                         });
419
420                         $('#frequency')[0].select(self.app.config.frequency);
421                         $('#strength')[0].select(self.app.config.strength);
422
423                         $('#two .scheduleOptions').append(self.graphSchedule.ui);
424                         $('#two .scheduleOptions').on('touchstart', function (ev) {
425                                 ev.stopPropagation();
426                         });
427
428                         $('#workdaysType').on('click', function (ev) {
429                                 var that = $(this).children("a");
430                                 setTimeout(function(){
431                                         that.removeClass("ui-btn-active");
432                                 }, 400);
433
434                                 self.app.changeTypeOfPeriods('workday');
435                         });
436
437                         $('#weekendType').on('click', function (ev) {
438                                 var that = $(this).children("a");
439                                 setTimeout(function(){
440                                         that.removeClass("ui-btn-active");
441                                 }, 400);
442
443                                 self.app.changeTypeOfPeriods('weekend');
444                         });
445
446                         $('#addTimeRange').on('click', function (e) {
447                                 if (self.app.config.trainingEnabled) {
448                                         self.popup('You should stop the training first');
449                                 } else {
450                                         self.editTimeRange(-1, e);
451                                 }
452                         });
453
454                         self.app.updateTimesRanges();
455                         self.configToUI();
456                 });
457
458                 $('#selectExercises').on('pageinit', function (page, options) {
459                         self.app.updateExercises();
460                         self.configToUI();
461                 });
462
463                 $('#selectExercises').on('pageshow', function (page, options) {
464                         self.fixPageHeight('#selectExercises');
465                 });
466
467                 $('#customExercises').on('pageinit', function (page, options) {
468                         $('#btnNewExercise').on('click', function (e) {
469                                 e.preventDefault();
470                                 e.stopPropagation();
471                                 if ($(this).data('disabled') !== true) {
472                                         $(this).data('disabled', true);
473                                         self.addExercise();
474                                 }
475                         });
476                 });
477
478                 $('#customExercises').on('pageshow', function (page, options) {
479                         self.unblockButtons();
480
481                         $('#newExerciseName').val('');
482                 });
483
484                 $('#rangesOfTimes').on('pageinit', function (page, options) {
485                         $("#updateTime").on("click", function (e) {
486                                 e.preventDefault();
487                                 e.stopPropagation();
488                                 self.startProgress('Saving');
489                                 self.editTimeRangeAction(self.app.currentEditingTimePeriodId);
490                         });
491                 });
492
493                 $('#rangesOfTimes').on('pageshow', function (page, options) {
494                         self.fixPageHeight('#rangesOfTimes');
495
496                         $('#updateTime').data('button').refresh();
497                         self.fillTimeRangeForm(self.app.currentEditingTimePeriod);
498                 });
499
500                 $('#increasingStrength').on('change', function () {
501                         self.app.config.increasingStrength = this.checked;
502                         self.app.saveConfig();
503
504                         self.configToUI();
505                 });
506
507                 $('#add_custom_workout_btn').on('click', function (e) {
508                         e.preventDefault();
509                         e.stopPropagation();
510                         $.mobile.changePage('#customExercises');
511                 });
512         };
513
514         UI.prototype.onGraphSchedule = function onGraphSchedule(onInitEnd) {
515                 this.updateMainUI();
516
517                 $('#one .schedule').append(this.graphSchedule.ui);
518                 this.app.updateGraph();
519                 this.graphSchedule.refresh();
520                 this.graphSchedule.setVisibleWeekend(!this.app.todayIsWorkday());
521                 this.graphSchedule.setVisibleWorkdays(this.app.todayIsWorkday());
522
523                 if (typeof onInitEnd === 'function') {
524                         onInitEnd();
525                 }
526         };
527
528         UI.prototype.initialize = function (onInitEnd) {
529                 $.mobile.tizen.disableSelection(document);
530
531                 this.bindEvents();
532
533                 $('html, body').css('font-size', '');
534                 $('[data-role=footer]').height('');
535
536                 this.graphSchedule = new GraphSchedule({
537                         onSuccess : this.onGraphSchedule.bind(this, onInitEnd)
538                 });
539
540                 this.fixContentHeight();
541         };
542
543         UI.prototype.fixPageHeight = function (element) {
544                 //FIXME (two scrollbar workaround)
545                 setTimeout(
546                         function () {
547                                 var newHeight = $(element).find('[data-role="content"]').prop('style').height;
548                                 $(element).css({'min-height': newHeight, 'height': newHeight});
549                         },
550                         0
551                 );
552         };
553
554         UI.prototype.fixContentHeight = function () {
555                 var contentHeight = screen.availHeight - $('div[data-role="header"]').outerHeight() - $('div[data-role="footer"]').outerHeight();
556                 $('div[data-role="content"]').css('height', contentHeight);
557         };
558
559         UI.prototype.startProgress = function (title) {
560                 title = title || "Updating schedule";
561                 $("#progress").show();
562                 $("#progresstitle").text(title);
563                 $("#progressbar").progressbar({value: false});
564         };
565
566         UI.prototype.endProgress = function () {
567                 $("#progress").fadeOut();
568         };
569 }());