2 /*global tizen, document, $, jQuery, app, UiPanel, UiContact, TemplateManager, window, Helpers */
8 function Ui(contacts) {
13 (function () { // strict mode wrapper
22 addressBook: tizen.contact.getDefaultAddressBook(),
24 photoURIdefault: null,
31 * @type {TemplateManager}
33 templateManager: null,
38 init: function Ui_init() {
40 this.templateManager = new TemplateManager();
41 this.helpers = new Helpers();
42 $(document).ready(this.domInit.bind(this));
43 $.mobile.tizen.disableSelection(document);
47 * When DOM is ready, initialise it (bind events)
49 domInit: function Ui_domInit() {
50 this.templateManager.loadToCache(['callView',
56 'dateRow'], this.initPages.bind(this));
60 * UI pages initializer
62 initPages: function Ui_initPages() {
63 var pages = [], body = $('body');
66 .append(this.templateManager.get('messageWindow'))
67 .append(this.templateManager.get('errorWindow'))
70 .append($(this.templateManager.get('callView'))
72 .trigger('pagecreate')
74 pages.push(this.templateManager.get('callerHistory'));
75 body.append(pages.join(''));
76 this.removeSearchBarToHeader();
79 app.showCallHistory();
81 this.photoURIdefault = $("#header .photo").css('background-image');
87 addEvents: function Ui_addEvents() {
90 $(window).on('resize', function () {
91 $.mobile.activePage.page('refresh');
94 $('#callView').on('tap', '.ui-btn-back', app.exit.bind(app));
96 $('#callView').on('pagebeforeshow', function () {
97 app.showCallHistory();
100 //original code, do not remove until web-ui release; N_SE-48946
101 //$(".ui-scrollview-view").listview();
103 $('#historyForCallerView').on('tap', '.ui-btn-back', function (event) {
104 event.preventDefault();
105 event.stopPropagation();
106 $.mobile.changePage('#callView');
109 $('#historyForCallerView').on('pagebeforeshow', function () {
110 self.hideCheckboxes();
111 $('#historyForCallerView .ui-content.ui-scrollview-clip .ui-scrollview-view')
112 .css('-webkit-transform', 'translate3d(0px, 0px, 0px)');
113 $('#selectAllDetails').on('change', function () {
118 $('#historyForCallerView').on('pageshow', function () {
119 $('#content').css('top', '160px');
120 $('#header').css('height', '160px');
121 $('#callerListContainer')
122 .children('.ui-overflow-indicator-top', '.ui-overflow-indicator-bottom')
126 $('#callerListContainer').on('scrollstart', function () {
128 .children('.ui-overflow-indicator-top', '.ui-overflow-indicator-bottom')
132 $('#callerListContainer').on('scrollstop', function () {
134 .children('.ui-overflow-indicator-top', '.ui-overflow-indicator-bottom')
138 $('.selectAllBox').children().on('click', function () {
139 $('.selectAllBox input[type=checkbox]').trigger('click');
141 self.selectAllDetailsEach();
144 $('#calllogList').on('tap', '.date', function (event) {
145 event.stopPropagation();
148 $('#calllogList').on('click', '.call', function onCalllogEntryClick(event) {
149 var remoteParty = $(this)
153 app.showHistoryForCaller(remoteParty);
154 $.mobile.changePage('#historyForCallerView');
157 $('#smsActionBtn').on('tap', function (event) {
158 event.stopPropagation();
159 event.preventDefault();
161 self.hideCheckboxes();
162 app.sendSms($('#forCallerList').data('remoteParty'));
165 $('#callActionBtn').on("tap", function (event) {
167 self.hideCheckboxes();
168 app.makeCall($('#forCallerList').data('remoteParty'));
171 $('#deleteActionBtn').on('click', function () {
172 self.changeDetailsToRemoveState();
175 $('.selectAllBox').on('tap', 'li', function () {
176 var checkbox = $(this).find(':checkbox');
177 if (self.removeMode === true) {
178 if (checkbox.attr('checked')) {
179 checkbox.attr('checked', false)
180 .data('checkboxradio')
183 checkbox.attr('checked', true)
184 .data('checkboxradio')
187 self.setSelectAllDetails();
192 .on('click', '#popupCancelActionBtn', this.closePopup.bind(this))
193 .on('click', '#popupSubmitActionBtn', this.deleteCheckedLogs.bind(this));
195 $('#errorPopup').on('tap', '#errorPopupOkBtn', this.closeErrorPopup);
197 $( "#errorPopup" ).bind({
198 popupafterclose: function(){
199 self.unlockOptionButtons();
203 $(window).keyup(function(e){
204 if (e.which === 13) {
205 $('input:focus').blur();
209 document.addEventListener('tizenhwkey', function(e) {
210 if (e.keyName == "back") {
211 if ($.mobile.popup.active) {
212 $.mobile.popup.active.close();
213 } else if (self.removeMode === true) {
214 app.ui.changeDetailsToRemoveState(undefined, true);
215 } else if ($.mobile.activePage.attr('id') === 'callView') {
216 tizen.application.getCurrentApplication().exit();
223 self.onVisibilityChange();
226 addEventsForCallerListCheckboxes: function Ui_addEventsForCallerListCheckboxes() {
228 $('#forCallerList :checkbox').on('change', function (event) {
229 if ($(this).attr('checked')) {
230 $(this).attr('checked', true);
232 $(this).attr('checked', false);
234 self.setSelectAllDetails();
238 selectAll: function () {
239 if ($('#selectAllDetails').attr('checked')) {
240 this.selectCheckbox($('#selectAllDetails'), true);
242 this.selectCheckbox($('#selectAllDetails'), false);
244 this.selectAllDetailsEach();
247 selectCheckbox: function (obj, state) {
248 var deleteButton = $('#deleteActionBtn'), numChecked;
249 obj.attr('checked', state)
250 .data('checkboxradio')
253 numChecked = $('#forCallerList input:checked').length;
254 if (this.removeMode && numChecked === 0 && !deleteButton.hasClass('ui-disabled')) {
255 deleteButton.addClass('ui-disabled');
256 } else if (deleteButton.hasClass('ui-disabled')) {
257 deleteButton.removeClass('ui-disabled');
262 * Returns number of selected call logs
263 * @return {number} length
265 getCountSelectedLogEntries: function Ui_getCountSelectedLogEntries() {
266 return $('#forCallerList li .toRemove label.ui-checkbox-on').length;
269 selectAllDetailsEach: function Ui_selectAllDetailsEach() {
271 $('#forCallerList').find('input').each(function () {
272 if ($('#selectAllDetails').attr('checked')) {
273 self.selectCheckbox($(this), true);
275 self.selectCheckbox($(this), false);
283 hideCheckboxes: function Ui_hideCheckboxes() {
285 this.selectCheckbox($('#selectAllDetails'), false);
287 $('#forCallerList').find('input').each(function () {
288 self.selectCheckbox($(this), false);
290 this.changeDetailsToRemoveState('hide');
294 * Returns css classes for specified entry
296 * @param {CallHistoryEntry} entry
299 cssClassesForEntry: function Ui_cssClassesForEntry(entry) {
300 return 'call dir_' + entry.direction.toLowerCase() + ' type_' + entry.type.replace('.', '-').toLowerCase();
303 setSelectAllDetails: function Ui_setSelectAllDetails() {
304 if ($('#forCallerList input[type="checkbox"]').length ===
305 $('#forCallerList input[checked="checked"]').length) {
306 this.selectCheckbox($('#selectAllDetails'), true);
308 this.selectCheckbox($('#selectAllDetails'), false);
313 * Shows popup with specified message
314 * @param {string} message
316 showPopup: function Ui_showPopup(message) {
317 $('#popupMessage').html(message);
318 $('#popup').popup('open', {'positionTo': 'window'});
324 closePopup: function Ui_closePopup() {
325 $('#popup').popup('close');
328 showErrorPopup: function Ui_showErrorPopup(message) {
329 $('#errorPopupMessage').html(message);
330 $('#errorPopup').popup('open', {'positionTo': 'window'});
333 closeErrorPopup: function Ui_closeErrorPopup() {
334 $('#errorPopup').popup('close');
338 * Deletes checked log entries
340 deleteCheckedLogs: function Ui_deleteCheckedLogs(e) {
343 this.selectCheckbox($('#selectAllDetails'), false);
345 $('#forCallerList li.call').each(function () {
346 if ($(this).find('form label').hasClass('ui-checkbox-on')) {
347 app.deleteLog($(this).data('entries')[0]);
352 if ($('#forCallerList li.call').length > 0) {
353 this.updateCallerHeaderNumberOfEntries($('#forCallerList li.call').length);
356 $('.ui-listview-filter .ui-input-text').val('');
357 $('.ui-listview-filter .ui-input-text').trigger('change');
358 $.mobile.changePage('#callView');
361 this.changeDetailsToRemoveState(true);
362 this.scrollToBottom();
365 changeDetailsToRemoveState: function Ui_changeDetailsToRemoveState(set, clear) {
366 var counter = this.getCountSelectedLogEntries(),
367 numChecked = $('#forCallerList input:checked').length;
368 if (clear === true) {
370 $('#forCallerList').find(':checkbox').attr('checked', false)
371 .data('checkboxradio').refresh();
372 $('.selectAllBox').find(':checkbox').attr('checked', false)
373 .data('checkboxradio').refresh();
375 if (set !== undefined) {
376 this.removeMode = false;
377 } else if (counter === 0) {
378 this.removeMode = !this.removeMode;
381 if (this.removeMode && numChecked === 0) {
382 $('#deleteActionBtn').addClass('ui-disabled');
383 } else if (!this.removeMode) {
384 $('#deleteActionBtn').removeClass('ui-disabled');
385 this.selectAllDetailsEach();
389 if (this.removeMode) {
390 $('#historyForCallerView .toRemove').removeClass('hidden');
391 $('#historyForCallerView .selectAllBox')
392 .removeClass('hidden');
394 $('#historyForCallerView .toRemove').addClass('hidden');
395 $('#historyForCallerView .selectAllBox').addClass('hidden');
397 } else if (counter > 1) {
398 this.showPopup('Are you sure you want to delete selected logs?');
400 this.showPopup('Are you sure you want to delete selected log?');
402 this.refreshScrollView();
406 * Renders call history list
408 * @param {CallHistoryEntry[]} callEntries
410 showCallHistory: function Ui_showCallHistory(callEntries) {
412 pdate = null, // previous date
414 elements = [], // list elements
415 len = callEntries.length, // entries length
416 tempLength = 0, // length of temporary table;
419 current, // current entry object
420 today = this.helpers.getShortDate(new Date()), // today short date
427 function filterForSameEntry(element) {
428 return self.getNumber(current) === self.getNumber(element)
429 && current.direction === element.direction;
432 $('.selectedCount').hide();
434 for (i = 0; i < len; i = i + 1) {
435 current = callEntries[i];
436 date = current.startTime.toLocaleDateString();
438 // if date is changed create new deyLog;
439 if (date !== pdate) {
443 dayLog.counters = [];
444 groupsOfDays.push(dayLog);
448 // group entries by remote Party;
449 filterResult = dayLog.entries.filter(filterForSameEntry);
450 if (filterResult.length) {
451 index = dayLog.entries.indexOf(filterResult[0]);
452 dayLog.counters[index] += 1;
454 dayLog.entries.push(current);
455 dayLog.counters[dayLog.entries.length - 1] = 1;
458 // Create UL list with dividers;
459 len = groupsOfDays.length;
460 for (i = 0; i < len; i += 1) {
461 dayLog = groupsOfDays[i];
462 tempLength = dayLog.entries.length;
463 entryShortDate = this.helpers.getShortDate(dayLog.entries[0].startTime);
465 //original code, do not remove until web-ui release; N_SE-48946
466 // elements.push($(this.templateManager.get('dateRow', {
467 // 'date': today === entryShortDate ? 'Today' : dayLog.date
470 for (j = 0; j < tempLength; j = j + 1) {
471 elements.push(this.getCallItemRow(dayLog.entries[j], dayLog.counters[j]));
478 /* workaround solution for not auto refreshing list view*/
479 setTimeout(function () {
480 // original code, do not remove until web-ui release; N_SE-48946
481 $( "#calllogList" ).listview({
484 autodividersSelector: function ( li ) {
485 return $(li).find('.callDate').text() === new Date().toLocaleDateString()
486 ? "Today" : $(li).find('.callDate').text();
488 }).listview('refresh');
489 $(".ui-li-divider").removeClass().addClass("date");
492 /* workaround for registering call during working app in removeMode */
493 if (this.removeMode) {
494 if ($('#selectAllDetails').attr('checked')){
497 $('.toRemove, .selectAllBox', $('#historyForCallerView'))
498 .removeClass('hidden');
499 $('#forCallerList .toRemove').show()
504 * @param: {CallHistoryEntry} entry
506 getNumber: function (entry) {
507 return entry.remoteParties[0].remoteParty;
511 * Returns HTML for single log entry
513 * @param {CallHistoryEntry} entry
514 * @param {number} counter
515 * @returns {HTMLPartial}
517 getCallItemRow: function Ui_getCallItemRow(entry, counter) {
518 var party = entry.remoteParties[0],
519 name = this.getNameByNumber(party.remoteParty),
523 name += ' (' + counter + ')';
526 tpl = this.templateManager.get('callItemRow', {
528 'callTime': entry.startTime.toTimeString(),
529 'callDate': entry.startTime.toLocaleDateString(),
530 'cssClasses': this.cssClassesForEntry(entry),
535 .data('remoteParty', entry.remoteParties[0].remoteParty)
536 .data('entries', [entry])
537 .get(0); // return clean DOM element so array of those could be appended at once*/
540 getNameByNumber: function (number) {
541 var i, j, contact, name;
542 for (i in this.contactsLoaded) {
543 if (this.contactsLoaded.hasOwnProperty(i)) {
544 contact = this.contactsLoaded[i];
545 for (j in contact.phoneNumbers) {
546 if (contact.phoneNumbers.hasOwnProperty(j)) {
547 if (contact.phoneNumbers[j].number.substr(-9)
548 === number.substr(-9)) {
549 name = contact.name.displayName;
556 return name || number || 'Unknown';
560 * Returns HTML for single caller log entry
562 * @param {CallHistoryEntry} entry
563 * @returns {HTMLElement}
565 getCallerCallLogRow: function Ui_getCallerCallLogRow(entry) {
566 return $(this.templateManager.get('callerCallItemRow', {
567 'cssClass': this.cssClassesForEntry(entry),
568 'callTime': entry.startTime.toLocaleTimeString(),
569 'callDuration': this.helpers.secondsToHours(entry.duration),
571 })).data('entries', [entry]).get(0);
575 * Renders call log list for specified caller
577 * @param {string} remoteParty
578 * @param {CallHistoryEntry[]} entries
580 showHistoryForCaller: function Ui_showHistoryForCaller(remoteParty, entries) {
584 len = entries.length,
589 this.updateCallerHeader(entries[0], entries.length);
591 // if last call log has been removed
592 this.removedLastLog();
593 this.app.lastViewedCaller = 0;
597 .data('remoteParty', remoteParty)
598 .data('modified', false)
601 // group caller log entries by date
602 for (i = 0; i < len; i = i + 1) {
603 date = entries[i].startTime.toLocaleDateString();
605 // if date is changed render new header
606 if (date !== pdate) {
607 elements.push($(this.templateManager.get('dateRow', {'date': date})).get(0));
610 elements.push(this.getCallerCallLogRow(entries[i]));
617 if (elements.length > 0) {
618 $('li#delete > a').addClass('ui-btn-active');
620 $('li#delete > a').removeClass('ui-btn-active');
623 $('#forCallerList').trigger('create');
625 // change to remove mode if it was active before registering call
626 if (this.removeMode) {
627 this.removeMode = !this.removeMode;
628 this.changeDetailsToRemoveState();
629 // check previous checked entries
630 this.checkedLogs.forEach(function(logUid){
631 checkbox = $('#forCallerList li.call[data-uid="' + logUid + '"]')
634 if (checkbox.length > 0) {
635 checkbox.attr('checked', true)
636 .data('checkboxradio')
638 $('#deleteActionBtn').removeClass('ui-disabled');
642 // close popup if there are no checked checkboxes
643 if (!$("#forCallerList input:checked").length) {
644 if ($.mobile.popup.active) {
645 $.mobile.popup.active.close();
649 this.addEventsForCallerListCheckboxes();
650 // lock buttons if unknown caller
652 this.unlockOptionButtons();
660 * @param {string} accountId
662 updateCallerHeaderAccountId: function Ui_updateCallerHeaderAccountId(accountId) {
663 $('.infoContainer .accountId').html(accountId);
667 * Update number of entries
668 * @param numberOfEntries
670 updateCallerHeaderNumberOfEntries: function Ui_updateCallerHeaderNumberOfEntries(numberOfEntries) {
671 $('.infoContainer .numberOfEntries').html(numberOfEntries);
675 * Updates caller main info
676 * @param {CallHistoryEntry} entry
677 * @param {number} numberOfEntries
679 updateCallerHeader: function Ui_updateCallerHeader(entry, numberOfEntries) {
680 var name = '', party, imgPath, personId;
682 $('#header .photo').css('background-image', this.photoURIdefault);
684 if (entry.remoteParties !== null) {
685 party = entry.remoteParties[0];
686 personId = parseInt(party.personId, 10);
687 name = this.getNameByNumber(party.remoteParty);
688 if (party.displayName) {
689 this.updateCallerHeaderAccountId(party.remoteParty);
691 this.updateCallerHeaderNumberOfEntries(numberOfEntries);
692 if (personId !== 0) {
693 imgPath = app.getPhotoURIForContact(personId);
694 if (imgPath !== false) {
695 $('#header .photo').css('background-image', 'url(' + imgPath + ')');
698 } else if (entry.contactId !== null) {
699 name = entry.accountId;
700 this.updateCallerHeaderAccountId(entry.accountId);
701 this.updateCallerHeaderNumberOfEntries(numberOfEntries);
703 name = entry.accountId;
704 this.updateCallerHeaderAccountId('');
705 this.updateCallerHeaderNumberOfEntries(numberOfEntries);
707 $('.contact > .infoContainer > .name').html(name);
711 loadContacts: function Model_loadContacts(callback) {
712 var contactsFoundCB, errorCB;
714 this.contactsLoaded = null;
716 contactsFoundCB = function (contacts) {
717 this.contactsLoaded = contacts;
718 if (callback instanceof Function) {
723 errorCB = function (error) {
724 console.error('Model_loadContacts, problem with find() method: ' + error.message);
727 this.addressBook.find(contactsFoundCB.bind(this), errorCB);
731 * Remove search filter from content and appends it to header
733 removeSearchBarToHeader: function () {
734 $('#page-header').append($('#callView .ui-listview-filter'));
735 $.mobile.activePage.page('refresh');
736 $('.ui-input-cancel').remove(); // patch for WebUI bug;
739 scrollToBottom: function () {
740 var scrollView = $(".ui-scrollview-view");
741 scrollView.css("-webkit-transform", "translate3d(0px, -" +
742 scrollView.height() + "px, 0px)");
745 onVisibilityChange: function () {
747 document.addEventListener('webkitvisibilitychange', function () {
748 if (document.webkitVisibilityState === 'hidden') {
749 self.checkedLogs = [];
750 $('#forCallerList li.call').each(function () {
751 if ($(this).find('form label')
752 .hasClass('ui-checkbox-on')) {
753 var checkedEntry = $(this).data('entries')[0];
754 self.checkedLogs.push(checkedEntry.uid);
758 self.loadContacts(app.updateCallLists.bind(app));
759 $('#callActionBtn, #smsActionBtn')
760 .removeClass('ui-disabled');
765 lockButtons: function () {
766 $('#callActionBtn, #smsActionBtn').addClass('ui-disabled');
769 unlockOptionButtons : function Ui_unlockOptionButtons(){
770 $('#callActionBtn, #smsActionBtn').removeClass('ui-disabled');
775 * Patch for UI, bad refresh scrollView
777 refreshScrollView: function () {
778 var scrollView = $('.ui-scrollview-view'),
786 removedLastLog: function () {
787 this.hideCheckboxes();
788 $(".ui-popup").popup('close');
789 $.mobile.changePage('#callView');