011db17a3bc9b99f5671f48e145fb859de96d552
[samples/web/CallLog.git] / js / app.ui.js
1 /*jslint devel: true*/
2 /*global tizen, document, $, app, UiPanel, UiContact, TemplateManager, window, Helpers */
3
4 /**
5  * @class Ui
6  */
7
8 function Ui(contacts) {
9         'use strict';
10         this.init();
11 }
12
13 (function () { // strict mode wrapper
14         'use strict';
15         Ui.prototype = {
16                 /**
17                  * UI remove mode
18                  * @type {boolean}
19                  */
20                 removeMode: false,
21
22                 /**
23                  * @type {TemplateManager}
24                  */
25                 templateManager: null,
26
27                 /**
28                  * UI Initializer
29                  */
30                 init: function Ui_init() {
31                         console.log('Ui_init');
32                         this.templateManager = new TemplateManager();
33                         this.helpers = new Helpers();
34                         $(document).ready(this.domInit.bind(this));
35                 },
36
37                 /**
38                  * When DOM is ready, initialise it (bind events)
39                  */
40                 domInit: function Ui_domInit() {
41                         console.log('Ui_domInit');
42                         this.templateManager.loadToCache(['callView', 'callerHistory', 'callItemRow', 'callerCallItemRow', 'messageWindow', 'dateRow'], this.initPages.bind(this));
43                 },
44
45                 /**
46                  * UI pages initializer
47                  */
48                 initPages: function Ui_initPages() {
49                         console.log('Ui_initPages');
50                         var pages = [];
51
52                         $('#callView').append($(this.templateManager.get('callView')).children()).trigger('pagecreate');
53
54                         pages.push(this.templateManager.get('callerHistory'));
55                         $('body').append(pages.join(''));
56                         this.removeSearchBarToHeader();
57
58                         this.addEvents();
59                         app.showCallHistory();
60                 },
61
62                 /**
63                  * Add UI events
64                  */
65                 addEvents: function Ui_addEvents() {
66                         console.log('Ui_addEvents');
67                         var self = this;
68
69                         $('#callView .ui-btn-back').on('tap', app.exit.bind(app));
70
71                         $('#callView').on('pagebeforeshow', function () {
72                                 app.showCallHistory();
73                         });
74
75                         $('#historyForCallerView').on('pagebeforeshow', function () {
76                                 self.hideCheckboxes();
77                                 $('#historyForCallerView .ui-content')
78                                         .scrollview('scrollTo', 0, 0);
79                                 $('#historyForCallerView .ui-content .ui-scrollview-view')
80                                         .css('-webkit-transform', 'translate3d(0px, 0px, 0px)');
81                                 $('#selectAllDetails').on('change', function () {
82                                         self.selectAllDetails();
83                                 });
84                         });
85
86                         $('#historyForCallerView').on('pageshow', function () {
87                                 console.log('(event) #historyForCallerView:pageshow');
88                                 $('#content').css('top', '160px');
89                                 $('#header').css('height', '160px');
90                                 $('#delete-toolbar').css('width', '70px');
91                         });
92
93                         $(window).on('resize', function () {
94                                 $('#delete-toolbar').css('width', '70px');
95                         });
96
97                         $('.selectAllBox').on('tap', function () {
98                                 self.selectAll();
99                                 self.selectAllDetailsEach();
100                         });
101
102                         $('#calllogList').on('tap', '.date', function (event) {
103                                 event.stopPropagation();
104                         });
105
106                         $('#calllogList').on('click', '.call', function onCalllogEntryClick(event) {
107                                 console.log('onclick', $(this).data('entries'));
108                                 app.showHistoryForCaller($(this).data('entries')[0].remoteParties[0].remoteParty);
109                                 $.mobile.changePage('#historyForCallerView');
110                         });
111
112                         $('#smsActionBtn').on('tap', function () {
113                                 self.hideCheckboxes();
114                                 app.sendSms($('#forCallerList').data('remoteParty'));
115                         });
116
117                         $('#callActionBtn').on('tap', function () {
118                                 self.hideCheckboxes();
119                                 app.makeCall($('#forCallerList').data('remoteParty'));
120                         });
121
122                         $('#deleteActionBtn').on('tap', function () {
123                                 self.changeDetailsToRemoveState();
124                         });
125
126                         $('#forCallerList').on('tap', 'li', function () {
127                                 console.log('handle click', this.removeMode);
128                                 var checkbox = $(this).find(':checkbox');
129                                 if (self.removeMode === true) {
130                                         if (checkbox.attr('checked')) {
131                                                 checkbox.attr('checked', false)
132                                                         .data('checkboxradio')
133                                                         .refresh();
134                                         } else {
135                                                 checkbox.attr('checked', true)
136                                                         .data('checkboxradio')
137                                                         .refresh();
138                                         }
139                                         self.setSelectAllDetails();
140                                 }
141                         });
142                 },
143
144                 addEventsForCallerListCheckboxes: function Ui_addEventsForCallerListCheckboxes() {
145                         console.log('Ui_addEventsForCallerListCheckboxes');
146                         var self = this;
147                         $('#forCallerList :checkbox').on('change', function (event) {
148                                 if ($(this).attr('checked')) {
149                                         $(this).attr('checked', true);
150                                 } else {
151                                         $(this).attr('checked', false);
152                                 }
153                                 console.log('#forCallerList :checkbox', 'onchange');
154                                 self.setSelectAllDetails();
155                         });
156                 },
157
158                 selectAll: function Ui_selectAll() {
159                         console.log('Ui_selectAll');
160                         if ($('#selectAllDetails').attr('checked')) {
161                                 $('#selectAllDetails')
162                                         .attr('checked', false)
163                                         .data('checkboxradio')
164                                         .refresh();
165                         } else {
166                                 $('#selectAllDetails')
167                                         .attr('checked', true)
168                                         .data('checkboxradio')
169                                         .refresh();
170                         }
171                 },
172
173                 selectAllDetails: function Ui_selectAllDetails() {
174                         console.log('Ui_selectAllDetails');
175                         if ($('#selectAllDetails').attr('checked')) {
176                                 $('#selectAllDetails').attr('checked', true);
177                         } else {
178                                 $('#selectAllDetails').attr('checked', false);
179                         }
180                         this.selectAllDetailsEach();
181                 },
182
183                 /**
184                  * Returns number of selected call logs
185                  * @return {number} length
186                  */
187                 getCountSelectedLogEntries: function Ui_getCountSelectedLogEntries() {
188                         console.log('Ui_getCountSelectedLogEntries');
189                         return $('#forCallerList li .toRemove label.ui-checkbox-on').length;
190                 },
191
192                 selectAllDetailsEach: function Ui_selectAllDetailsEach() {
193                         $('#forCallerList').find('input').each(function () {
194                                 if ($('#selectAllDetails').attr('checked')) {
195                                         $(this).attr('checked', true)
196                                                 .data('checkboxradio')
197                                                 .refresh();
198                                 } else {
199                                         $(this).attr('checked', false)
200                                                 .data('checkboxradio')
201                                                 .refresh();
202                                 }
203                         });
204                 },
205
206                 /**
207                  * Hides checkboxes
208                  */
209                 hideCheckboxes: function Ui_hideCheckboxes() {
210                         console.log('Ui_hideCheckboxes');
211                         $('#selectAllDetails')
212                                 .attr('checked', false)
213                                 .data('checkboxradio')
214                                 .refresh();
215
216                         $('#forCallerList').find('input').each(function () {
217                                 $(this).attr('checked', false)
218                                         .data('checkboxradio')
219                                         .refresh();
220                         });
221                         this.changeDetailsToRemoveState('hide');
222                 },
223
224                 /**
225                  * Returns css classes for specified entry
226                  *
227                  * @param {CallHistoryEntry} entry
228                  * @returns {string}
229                  */
230                 cssClassesForEntry: function Ui_cssClassesForEntry(entry) {
231                         console.log('Ui_cssClassesForEntry', entry);
232                         return 'call dir_' + entry.direction.toLowerCase() + ' type_' + entry.type.replace('.', '-').toLowerCase();
233                 },
234
235                 setSelectAllDetails: function Ui_setSelectAllDetails() {
236                         console.log('Ui_setSelectAllDetails');
237                         if ($('#forCallerList input[type="checkbox"]').length === $('#forCallerList input[checked="checked"]').length) {
238                                 $('#selectAllDetails')
239                                         .attr('checked', true)
240                                         .data('checkboxradio')
241                                         .refresh();
242                         } else {
243                                 $('#selectAllDetails')
244                                         .attr('checked', false)
245                                         .data('checkboxradio')
246                                         .refresh();
247                         }
248                 },
249
250                 /**
251                  * Shows popup with specified message
252                  * @param {string} message
253                  */
254                 showPopup: function Ui_showPopup(message) {
255                         console.log('Ui_showPopup', message);
256                         $('body')
257                                 .append(this.templateManager.get('messageWindow'))
258                                 .trigger('create');
259                         $('#popupMessage').html(message);
260
261                         $('#popup')
262                                 .on('tap', '#popupCancelActionBtn', this.closePopup.bind(this))
263                                 .on('tap', '#popupSubmitActionBtn', this.deleteCheckedLogs.bind(this));
264
265                         $('#popup').popupwindow('open');
266                 },
267
268                 /**
269                  * Hides popup
270                  */
271                 closePopup: function Ui_closePopup() {
272                         console.log('Ui_closePopup');
273                         $('#popup')
274                                 .popupwindow('close')
275                                 .remove();
276                 },
277
278                 /**
279                  * Deletes checked log entries
280                  */
281                 deleteCheckedLogs: function Ui_deleteCheckedLogs() {
282                         console.log('Ui_deleteCheckedLogs');
283
284                         this.closePopup();
285
286                         $('#selectAllDetails')
287                                 .attr('checked', false)
288                                 .data('checkboxradio')
289                                 .refresh();
290
291                         $('#forCallerList li.call').each(function () {
292                                 if ($(this).find('form label').hasClass('ui-checkbox-on')) {
293                                         app.deleteLog($(this).data('entries')[0]);
294                                         $(this).remove();
295                                 }
296                         });
297
298                         if ($('#forCallerList li.call').length > 0) {
299                                 $('.number').html('(' + $('#forCallerList li').length + ')');
300                         } else {
301                                 $.mobile.changePage('#callView');
302                         }
303                 },
304
305                 changeDetailsToRemoveState: function changeDetailsToRemoveState(set) {
306                         console.log('changeDetailsToRemoveState', set);
307                         var counter = this.getCountSelectedLogEntries();
308
309                         if (set !== undefined) {
310                                 this.removeMode = false;
311                         } else if (counter === 0) {
312                                 this.removeMode = !this.removeMode;
313                         }
314
315                         if (counter === 0) {
316                                 if (this.removeMode) {
317                                         $('#historyForCallerView .toRemove').removeClass('hidden');
318                                         $('#historyForCallerView .selectAllBox').removeClass('hidden');
319                                 } else {
320                                         $('#historyForCallerView .toRemove').addClass('hidden');
321                                         $('#historyForCallerView .selectAllBox').addClass('hidden');
322                                 }
323                         } else if (counter > 1) {
324                                 this.showPopup('Are you sure you want to delete selected logs?');
325                         } else {
326                                 this.showPopup('Are you sure you want to delete selected log?');
327                         }
328                         this.refreshScrollView();
329                 },
330
331                 /**
332                  * Renders call history list
333                  *
334                  * @param {CallHistoryEntry[]} callEntries
335                  */
336                 showCallHistory: function Ui_showCallHistory(callEntries) {
337                         console.log('Ui_showCallHistory', callEntries);
338                         var counter = 0, //
339                                 pdate = '', // previous date
340                                 date = '',
341                                 elements = [], // list elements
342                                 len = callEntries.length, // entries length
343                                 i, // loop counter
344                                 current, // current entry object
345                                 next, // next entry object
346                                 today = this.helpers.getShortDate(new Date()), // today short date
347                                 entryShortDate;
348
349                         $('.selectedCount').hide();
350
351                         for (i = 0; i < len; i = i + 1) {
352                                 counter += 1;
353                                 current = callEntries[i];
354                                 date = current.startTime.toLocaleDateString();
355                                 entryShortDate = this.helpers.getShortDate(callEntries[i].startTime);
356                                 next = callEntries[i + 1];
357
358                                 // if date is changed render new header
359                                 if (date !== pdate) {
360                                         elements.push($(this.templateManager.get('dateRow', {
361                                                 'date': today === entryShortDate ? 'Today' : date
362                                         })).get(0));
363                                 }
364
365                                 if (date !== pdate || next === undefined
366                                                 || current.remoteParties[0].remoteParty !== next.remoteParties[0].remoteParty) {
367                                         elements.push(this.getCallItemRow(current, counter));
368                                         counter = 0; // reset counter after render
369                                 }
370
371                                 if (date !== pdate) {
372                                         pdate = date;
373                                 }
374                         }
375
376                         $('#calllogList')
377                                 .empty()
378                                 .append(elements);
379                 },
380
381                 /**
382                  * Returns HTML for single log entry
383                  *
384                  * @param {CallHistoryEntry} entry
385                  * @param {number} counter
386                  * @returns {HTMLPartial}
387                  */
388                 getCallItemRow: function Ui_getCallItemRow(entry, counter) {
389                         console.log('Ui_getCallItemRow', entry, counter);
390                         var party = entry.remoteParties[0],
391                                 name = party.displayName || party.remoteParty,
392                                 tpl;
393
394                         if (counter > 1) {
395                                 name += ' (' + counter + ')';
396                         }
397
398                         tpl = this.templateManager.get('callItemRow', {
399                                 'name': name,
400                                 'callTime': entry.startTime.toLocaleTimeString(),
401                                 'cssClasses': this.cssClassesForEntry(entry)
402                         });
403
404                         return $(tpl)
405                                 .data('remoteParty', entry.remoteParties[0].remoteParty)
406                                 .data('entries', [entry])
407                                 .get(0); // return clean DOM element so array of those could be appended at once*/
408                 },
409
410                 /**
411                  * Returns HTML for single caller log entry
412                  *
413                  * @param {CallHistoryEntry} entry
414                  * @returns
415                  */
416                 getCallerCallLogRow: function Ui_getCallerCallLogRow(entry) {
417                         console.log('Ui_getCallerCallLogRow', entry);
418
419                         return $(this.templateManager.get('callerCallItemRow', {
420                                 'cssClass': this.cssClassesForEntry(entry),
421                                 'callTime': entry.startTime.toLocaleTimeString(),
422                                 'callDuration': this.helpers.secondsToHours(entry.duration)
423                         })).data('entries', [entry]).get(0);
424                 },
425
426                 /**
427                  * Renders call log list for specified caller
428                  *
429                  * @param {string} remoteParty
430                  * @param {CallHistoryEntry[]} entries
431                  */
432                 showHistoryForCaller: function Ui_showHistoryForCaller(remoteParty, entries) {
433                         console.log('Ui_showHistoryForCaller', entries);
434                         var pdate = '',
435                                 date = '',
436                                 elements = [],
437                                 len = entries.length,
438                                 i;
439
440                         if (len) {
441                                 this.updateCallerHeader(entries[0], entries.length);
442                         }
443
444                         $('#forCallerList')
445                                 .data('remoteParty', remoteParty)
446                                 .data('modified', false)
447                                 .empty();
448
449                         // group caller log entries by date
450                         for (i = 0; i < len; i = i + 1) {
451                                 date = entries[i].startTime.toLocaleDateString();
452
453                                 // if date is changed render new header
454                                 if (date !== pdate) {
455                                         elements.push($(this.templateManager.get('dateRow', {'date': date})).get(0));
456                                         pdate = date;
457                                 }
458                                 elements.push(this.getCallerCallLogRow(entries[i]));
459                         }
460
461                         $('#forCallerList')
462                                 .empty()
463                                 .append(elements);
464
465                         if (elements.length > 0) {
466                                 $('li#delete > a').addClass('ui-btn-active');
467                         } else {
468                                 $('li#delete > a').removeClass('ui-btn-active');
469                         }
470
471                         $('#forCallerList').trigger('create');
472
473                         this.addEventsForCallerListCheckboxes();
474                 },
475
476                 /**
477                  * Updates caller main info
478                  * @param {CallHistoryEntry} entry
479                  * @param {number} numberOfEntries
480                  */
481                 updateCallerHeader: function Ui_updateCallerHeader(entry, numberOfEntries) {
482                         console.log('Ui_updateCallerHeader', entry, numberOfEntries);
483                         var name = '',
484                                 num = '',
485                                 photoURIdefault = '../images/no_photo.png',
486                                 party,
487                                 imgPath;
488
489                         $('.contact > .infoContainer > .photo').css('background-image', photoURIdefault);
490
491                         if (entry.remoteParties !== null) {
492                                 party = entry.remoteParties[0];
493                                 name = party.displayName || party.remoteParty;
494                                 if (party.displayName) {
495                                         num = party.remoteParty + ' (' + numberOfEntries + ')';
496                                 } else {
497                                         num = ' (' + numberOfEntries + ')';
498                                 }
499
500                                 if (party.contactRef) {
501                                         imgPath = app.getPhotoURIForContact(party.contactRef.addressBookId, party.contactRef.contactId);
502                                         if (imgPath !== false) {
503                                                 $('.contact > .infoContainer > .photo').css('background-image', imgPath);
504                                         }
505                                 }
506                         } else if (entry.contactId !== null) {
507                                 name = entry.accountId;
508                                 num = entry.accountId + ' (' + numberOfEntries + ')';
509                         } else {
510                                 name = entry.accountId;
511                                 num = ' (' + numberOfEntries + ')';
512                         }
513                         $('.contact > .infoContainer > .name').html(name);
514                         $('.contact > .infoContainer > .number').html(num);
515                 },
516
517                 /**
518                  * Remove search filter from content and appends it to header
519                  */
520                 removeSearchBarToHeader: function () {
521                         $('#page-content').css('top', '102px');
522                         $('#page-header')
523                                 .css('height', '102px')
524                                 .append($('#callView .ui-listview-filter'));
525                         $.mobile.activePage.page('refresh');
526                         $('.ui-input-cancel').remove(); // patch for WebUI bug;
527                 },
528
529                 /**
530                  * WORKAROUND;
531                  * Patch for UI, bad refresh scrollView
532                  */
533                 refreshScrollView: function () {
534                         var scrollView = $('.ui-scrollview-view'),
535                                 show = function () {
536                                         scrollView.show();
537                                 };
538                         scrollView.hide();
539                         setTimeout(show, 0);
540                 }
541         };
542
543 }());