[ExercisePlanner] updated ExercisePlanner sources
[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
310                 $('#onAlertControl').tabbar();
311                 $('#onAlertControl').show();
312                 $('#onAlertControl').css('width', '');
313         };
314
315         UI.prototype.setStatusRun = function (bool) {
316                 if (bool) {
317                         // icon;
318                         $('#status').removeClass('lazy').addClass('run');
319                         // sentence;
320                         this.setSentence('run');
321                         // button in control bar;
322                         $('#startStop .ui-btn-text').html('Stop Training');
323                 } else {
324                         $('#status').removeClass('run').addClass('lazy');
325                         this.setSentence('lazy');
326                         $('#communicate').html('');
327                         $('#startStop .ui-btn-text').html('Start Training');
328                 }
329         };
330
331         UI.prototype.bindEvents = function bindEvents() {
332                 var self = this;
333
334                 // bind events;
335                 $("#popup").popup();
336
337                 $('#one .ui-btn-back').on('click', this.app.exit.bind(this.app));
338
339                 $('#ok').on('click', self.app.ok.bind(self.app));
340                 $('#wait').on('click', self.app.wait.bind(self.app));
341                 $('#todayOffAll').on('click', self.app.todayOffAll.bind(self.app));
342
343                 $('[data-role = "tabbar"] li > a').on('click', function () {
344                         self.clearTabbars();
345                 });
346
347                 $('#startStop').on('click', function () {
348                         self.app.appStartStop();
349                         $('#startStop').blur();
350                 });
351
352                 $('#options').on('click', function () {
353                         $.mobile.changePage('#two');
354                 });
355
356                 $('#selectExercisesBar').on('click', function () {
357                         $.mobile.changePage('#selectExercises');
358                 });
359
360                 $('#add_custom_workout_btn').on('click', function () {
361                         $.mobile.changePage('#customExercises');
362                 });
363
364                 window.addEventListener('tizenhwkey', function(e) {
365                         if (e.keyName == 'back') {
366                                 if ($.mobile.popup.active) {
367                                         $.mobile.popup.active.close();
368                                 } else if ($.mobile.activePage.attr('id') === 'one') {
369                                         tizen.application.getCurrentApplication().exit();
370                                 } else {
371                                         history.back();
372                                 }
373                         }
374                 });
375
376                 $('#one').on(
377                         'pageshow',
378                         function (page, options) {
379                                 if (self.graphSchedule.ui) {
380                                         $('#one .schedule').append(self.graphSchedule.ui);
381                                         self.app.updateGraph();
382                                         self.graphSchedule.refresh();
383                                         self.graphSchedule.setVisibleWeekend(!self.app
384                                                 .todayIsWorkday());
385                                         self.graphSchedule.setVisibleWorkdays(self.app
386                                                 .todayIsWorkday());
387                                 }
388                                 $('#one .schedule').on('touchstart', function (ev) {
389                                         ev.stopPropagation();
390                                 });
391
392                                 // workaround for scroll lock;
393                                 $.mobile.activePage.css('position', 'fixed');
394
395                                 if ($('a.ui-btn-back').is(':hidden')) {
396                                         $('div#mainControl').removeClass('ui-tabbar-margin-back');
397                                 }
398                         }
399                 );
400
401                 $('#two').on('pageshow', function (page, options) {
402                         self.fixPageHeight('#two');
403
404                         if (self.graphSchedule.ui) {
405                                 $('#two .scheduleOptions').append(self.graphSchedule.ui);
406                                 self.graphSchedule.refresh();
407                                 self.graphSchedule.setVisibleWeekend(true);
408                                 self.graphSchedule.setVisibleWorkdays(true);
409                         }
410
411                         if ($('a.ui-btn-back').is(':hidden')) {
412                                 $('div#selectExercisesBar').removeClass('ui-tabbar-margin-back');
413                         }
414                 });
415
416                 $('#two').on('pageinit', function (page, options) {
417                         $('.ui-radio input', $('#frequency')).change(function (ev) {
418                                 var that = this;
419                                 self.startProgress();
420                                 setTimeout(function (){
421                                         self.app.setFrequency(that.value);
422                                         self.updateMainUI();
423                                         self.endProgress();
424                                 }, 100);
425                         });
426
427                         $('.ui-radio input', $('#strength')).change(function (ev) {
428                                 self.app.setStrength(this.value);
429                                 self.updateMainUI();
430                         });
431
432                         $('#frequency')[0].select(self.app.config.frequency);
433                         $('#strength')[0].select(self.app.config.strength);
434
435                         $('#two .scheduleOptions').append(self.graphSchedule.ui);
436                         $('#two .scheduleOptions').on('touchstart', function (ev) {
437                                 ev.stopPropagation();
438                         });
439
440                         $('#workdaysType').on('click', function (ev) {
441                                 var that = $(this).children("a");
442                                 setTimeout(function(){
443                                         that.removeClass("ui-btn-active");
444                                 }, 400);
445
446                                 self.app.changeTypeOfPeriods('workday');
447                         });
448
449                         $('#weekendType').on('click', function (ev) {
450                                 var that = $(this).children("a");
451                                 setTimeout(function(){
452                                         that.removeClass("ui-btn-active");
453                                 }, 400);
454
455                                 self.app.changeTypeOfPeriods('weekend');
456                         });
457
458                         $('#addTimeRange').on('click', function (e) {
459                                 if (self.app.config.trainingEnabled) {
460                                         self.popup('You should stop the training first.');
461                                 } else {
462                                         self.editTimeRange(-1, e);
463                                 }
464                         });
465
466                         self.app.updateTimesRanges();
467                         self.configToUI();
468                 });
469
470                 $('#selectExercises').on('pageinit', function (page, options) {
471                         self.app.updateExercises();
472                         self.configToUI();
473                 });
474
475                 $('#selectExercises').on('pageshow', function (page, options) {
476                         self.fixPageHeight('#selectExercises');
477                 });
478
479                 $('#customExercises').on('pageinit', function (page, options) {
480                         $('#btnNewExercise').on('click', function (e) {
481                                 e.preventDefault();
482                                 e.stopPropagation();
483                                 if ($(this).data('disabled') !== true) {
484                                         $(this).data('disabled', true);
485                                         self.addExercise();
486                                 }
487                         });
488                 });
489
490                 $('#customExercises').on('pageshow', function (page, options) {
491                         self.unblockButtons();
492
493                         $('#newExerciseName').val('');
494                 });
495
496                 $('#rangesOfTimes').on('pageinit', function (page, options) {
497                         $("#updateTime").on("click", function (e) {
498                                 e.preventDefault();
499                                 e.stopPropagation();
500                                 self.startProgress('Saving');
501                                 self.editTimeRangeAction(self.app.currentEditingTimePeriodId);
502                         });
503                 });
504
505                 $('#rangesOfTimes').on('pageshow', function (page, options) {
506                         self.fixPageHeight('#rangesOfTimes');
507
508                         $('#updateTime').data('button').refresh();
509                         self.fillTimeRangeForm(self.app.currentEditingTimePeriod);
510                 });
511
512                 $('#increasingStrength').on('change', function () {
513                         self.app.config.increasingStrength = this.checked;
514                         self.app.saveConfig();
515
516                         self.configToUI();
517                 });
518
519                 $('#add_custom_workout_btn').on('click', function (e) {
520                         e.preventDefault();
521                         e.stopPropagation();
522                         $.mobile.changePage('#customExercises');
523                 });
524         };
525
526         UI.prototype.onGraphSchedule = function onGraphSchedule(onInitEnd) {
527                 this.updateMainUI();
528
529                 $('#one .schedule').append(this.graphSchedule.ui);
530                 this.app.updateGraph();
531                 this.graphSchedule.refresh();
532                 this.graphSchedule.setVisibleWeekend(!this.app.todayIsWorkday());
533                 this.graphSchedule.setVisibleWorkdays(this.app.todayIsWorkday());
534
535                 if (typeof onInitEnd === 'function') {
536                         onInitEnd();
537                 }
538         };
539
540         UI.prototype.initialize = function (onInitEnd) {
541                 $.mobile.tizen.disableSelection(document);
542
543                 this.bindEvents();
544
545                 $('html, body').css('font-size', '');
546                 $('[data-role=footer]').height('');
547
548                 this.graphSchedule = new GraphSchedule({
549                         onSuccess : this.onGraphSchedule.bind(this, onInitEnd)
550                 });
551
552                 this.fixContentHeight();
553         };
554
555         UI.prototype.fixPageHeight = function (element) {
556                 //FIXME (two scrollbar workaround)
557                 setTimeout(
558                         function () {
559                                 var newHeight = $(element).find('[data-role="content"]').prop('style').height;
560                                 $(element).css({'min-height': newHeight, 'height': newHeight});
561                         },
562                         0
563                 );
564         };
565
566         UI.prototype.fixContentHeight = function () {
567                 var contentHeight = screen.availHeight - $('div[data-role="header"]').outerHeight() - $('div[data-role="footer"]').outerHeight();
568                 $('div[data-role="content"]').css('height', contentHeight);
569         };
570
571         UI.prototype.startProgress = function (title) {
572                 title = title || "Updating schedule";
573                 $("#progress").show();
574                 $("#progresstitle").text(title);
575                 $("#progressbar").progressbar({value: false});
576         };
577
578         UI.prototype.endProgress = function () {
579                 $("#progress").fadeOut();
580         };
581 }());