Revert "Updated application sources"
[apps/web/sample/CallLog.git] / project / js / app.ui.js
index 483675f..073572a 100644 (file)
-/*
-*      Copyright 2013  Samsung Electronics Co., Ltd
-*
-*      Licensed under the Flora License, Version 1.1 (the "License");
-*      you may not use this file except in compliance with the License.
-*      You may obtain a copy of the License at
-*
-*              http://floralicense.org/license/
-*
-*      Unless required by applicable law or agreed to in writing, software
-*      distributed under the License is distributed on an "AS IS" BASIS,
-*      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-*      See the License for the specific language governing permissions and
-*      limitations under the License.
-*/
-
 /*jslint devel: true*/
 /*global tizen, document, $, jQuery, app, UiPanel, UiContact, TemplateManager, window, Helpers */
 
 /**
-* @class Ui
-*/
+ * @class Ui
+ */
+
 function Ui(contacts) {
-    'use strict';
-    this.init();
+       'use strict';
+       this.init();
 }
 
 (function () { // strict mode wrapper
-    'use strict';
-
-    Ui.prototype = {
-
-        /**
-        * UI remove mode
-        * @type {boolean}
-        */
-        removeMode: false,
-
-        /**
-         * Default tizen address book
-         * @type {AddressBook}
-         */
-        addressBook: tizen.contact.getDefaultAddressBook(),
-
-        /**
-         * Default photo uri
-         * @type {String}
-         */
-        photoURIdefault: null,
-
-        /**
-         * Cached contacts from address book
-         * @type {Array}
-         */
-        contactsLoaded: null,
-
-        /**
-         * identifiers of currently checked checkboxes
-         * @type {Array}
-         */
-        checkedLogs: [],
-
-        /**
-        * @type {TemplateManager}
-        */
-        templateManager: null,
-
-        /**
-        * UI Initializer
-        */
-        init: function Ui_init() {
-            this.loadContacts();
-            this.templateManager = new TemplateManager();
-            this.helpers = new Helpers();
-            $(document).ready(this.domInit.bind(this));
-            $.mobile.tizen.disableSelection(document);
-        },
-
-        /**
-        * When DOM is ready, initialise it (bind events)
-        */
-        domInit: function Ui_domInit() {
-            this.templateManager.loadToCache(['callView',
-                'callerHistory',
-                'callItemRow',
-                'callerCallItemRow',
-                'messageWindow',
-                'errorWindow',
-                'dateRow'], this.initPages.bind(this));
-        },
-
-        /**
-        * UI pages initializer
-        */
-        initPages: function Ui_initPages() {
-            var pages = [], body = $('body');
-
-            body
-                .append(this.templateManager.get('messageWindow'))
-                .append(this.templateManager.get('errorWindow'))
-                .trigger('create');
-            $('#callView')
-                .append(
-                    $(this.templateManager.get('callView')).children()
-                )
-                .trigger('pagecreate')
-                .trigger('pageshow');
-            pages.push(this.templateManager.get('callerHistory'));
-            body.append(pages.join(''));
-            this.removeSearchBarToHeader();
-
-            this.addEvents();
-            app.showCallHistory();
-
-            this.photoURIdefault = $("#header .photo").css('background-image');
-        },
-
-        /**
-        * Add UI events
-        */
-        addEvents: function Ui_addEvents() {
-            var self = this;
-
-            // recalculating page size when window resize
-            // (eg. when soft keybord appear)
-            $(window).on('resize', function () {
-                $.mobile.activePage.page('refresh');
-            });
-
-            // creating call history view
-            $('#callView').on('pagebeforeshow', function () {
-                app.showCallHistory();
-            });
-
-            // creating single contact history view
-            $('#historyForCallerView').on('pagebeforeshow', function () {
-                self.hideCheckboxes();
-                // move scrollbar to top
-                $('#historyForCallerView')
-                    .find('.ui-content.ui-scrollview-clip')
-                    .find('.ui-scrollview-view')
-                    .css('-webkit-transform', 'translate3d(0px, 0px, 0px)');
-                $('#selectAllDetails').on('change', function () {
-                    self.selectAll();
-                });
-            });
-
-
-            // HACK not dissapearing scrollview indicator
-            $('#historyForCallerView').on('pageshow', function () {
-                $('#content').css('top', '160px');
-                $('#header').css('height', '160px');
-                $('#callerListContainer')
-                    .children(
-                        '.ui-overflow-indicator-top',
-                        '.ui-overflow-indicator-bottom'
-                    ).hide();
-            });
-
-            // HACK not dissapearing scrollview indicator
-            $('#callerListContainer').on('scrollstart', function () {
-                $(this)
-                    .children(
-                        '.ui-overflow-indicator-top',
-                        '.ui-overflow-indicator-bottom'
-                    ).fadeIn(200);
-            });
-
-            // HACK not dissapearing scrollview indicator
-            $('#callerListContainer').on('scrollstop', function () {
-                $(this)
-                    .children(
-                        '.ui-overflow-indicator-top',
-                        '.ui-overflow-indicator-bottom'
-                    ).fadeOut(200);
-            });
-
-            // selecting all checkboxes
-            $('.selectAllBox').children().on('click', function () {
-                $('.selectAllBox input[type=checkbox]').trigger('click');
-                self.selectAll();
-                self.selectAllDetailsEach();
-            });
-
-            $('#calllogList').on('click', '.date', function (event) {
-                event.stopPropagation();
-            });
-
-            // when clicked on a log display all history from that contact
-            $('#calllogList').on(
-                'click keypress',
-                '.call',
-                function onCalllogEntryClick(event) {
-                    if (event.type === 'keypress' && event.keyCode !== 13) {
-                        return;
-                    }
-                    var remoteParty = $(this)
-                        .data('entries')[0]
-                        .remoteParties[0]
-                        .remoteParty;
-                    app.showHistoryForCaller(remoteParty);
-                    $.mobile.changePage('#historyForCallerView');
-                }
-            );
-
-            // run sms service on click
-            $('#smsActionBtn').on('click', function (event) {
-                event.stopPropagation();
-                event.preventDefault();
-                self.lockButtons('#smsActionBtn, #callActionBtn');
-                self.hideCheckboxes();
-                self.lockButtons('#deleteActionBtn');
-                app.sendSms($('#forCallerList').data('remoteParty'));
-            });
-
-            // run call service on btn click
-            $('#callActionBtn').on("click", function (event) {
-                self.lockButtons('#callActionBtn, #smsActionBtn');
-                self.hideCheckboxes();
-                self.lockButtons('#deleteActionBtn');
-                app.makeCall($('#forCallerList').data('remoteParty'));
-            });
-
-            $('#deleteActionBtn').on('click', function () {
-                self.changeDetailsToRemoveState();
-            });
-
-            // selecting all checkboxes
-            $('.selectAllBox').on('click', 'li', function () {
-                var checkbox = $(this).find(':checkbox');
-                if (self.removeMode === true) {
-                    if (checkbox.attr('checked')) {
-                        checkbox.attr('checked', false)
-                            .data('checkboxradio')
-                            .refresh();
-                    } else {
-                        checkbox.attr('checked', true)
-                            .data('checkboxradio')
-                            .refresh();
-                    }
-                    self.setSelectAllDetails();
-                }
-            });
-
-            $('#popup')
-                .on(
-                    'click',
-                    '#popupCancelActionBtn',
-                    this.closePopup.bind(this)
-                ).on(
-                    'click',
-                    '#popupSubmitActionBtn',
-                    this.deleteCheckedLogs.bind(this)
-                );
-
-            $('#errorPopup').on(
-                'click',
-                '#errorPopupOkBtn',
-                this.closeErrorPopup
-            );
-
-            $('#errorPopup').bind(
-                {
-                    popupafterclose: function () {
-                        self.unlockButtons();
-                    }
-                }
-            );
-
-            $(window).keyup(function (e) {
-                if (e.which === 13) {
-                    $('input:focus').blur();
-                }
-            });
-
-            // bind hardware back button
-            window.addEventListener('tizenhwkey', function (e) {
-                if (e.keyName === "back") {
-                    // if there is any popup close it
-                    if ($.mobile.popup.active) {
-                        $.mobile.popup.active.close();
-                    // if app is in remove mode close it
-                    } else if (self.removeMode === true) {
-                        app.ui.changeDetailsToRemoveState(undefined, true);
-                    // if app is on calls page close app
-                    } else if ($.mobile.activePage.attr('id') === 'callView') {
-                        tizen.application.getCurrentApplication().exit();
-                    // else back to calls page
-                    } else {
-                        history.back();
-                    }
-                }
-            });
-            // bind callback to visbility change event
-            self.onVisibilityChange();
-        },
-
-        /**
-         * Bind change event
-         */
-        addEventsForCallerListCheckboxes:
-            function Ui_addEventsForCallerListCheckboxes() {
-            var self = this;
-            $('#forCallerList :checkbox').on('change', function (event) {
-                if ($(this).attr('checked')) {
-                    $(this).attr('checked', true);
-                } else {
-                    $(this).attr('checked', false);
-                }
-                self.setSelectAllDetails();
-            });
-        },
-
-        /**
-         * Callback function for click on select all element
-         */
-        selectAll: function () {
-            // if select all checkbox is checked
-            if ($('#selectAllDetails').attr('checked')) {
-                this.selectCheckbox($('#selectAllDetails'), true);
-            } else {
-                this.selectCheckbox($('#selectAllDetails'), false);
-            }
-            // select each checkbox separatly
-            this.selectAllDetailsEach();
-        },
-
-        /**
-         * Select single checkbox and enable delete button
-         */
-        selectCheckbox: function (obj, state) {
-            var deleteButton = $('#deleteActionBtn'), numChecked;
-            // check checkbox and refresh its view
-            obj.attr('checked', state)
-                .data('checkboxradio')
-                .refresh();
-
-            // check if there is any checked checkbox
-            // and toggle delete button availability
-            numChecked = $('#forCallerList input:checked').length;
-            if (this.removeMode && numChecked === 0) {
-                deleteButton
-                    .addClass('ui-disabled')
-                    .attr('tabIndex', '-1')
-                    .blur();
-            } else if (deleteButton.hasClass('ui-disabled')) {
-                deleteButton
-                    .removeClass('ui-disabled')
-                    .attr('tabIndex', '0');
-            }
-        },
-
-        /**
-        * Returns number of selected call logs
-        * @return {number} length
-        */
-        getCountSelectedLogEntries: function Ui_getCountSelectedLogEntries() {
-            return $('#forCallerList li .toRemove label.ui-checkbox-on').length;
-        },
-
-        /**
-         * Select each checkbox separatly
-         */
-        selectAllDetailsEach: function Ui_selectAllDetailsEach() {
-            var self = this;
-            $('#forCallerList').find('input').each(function () {
-                if ($('#selectAllDetails').attr('checked')) {
-                    self.selectCheckbox($(this), true);
-                } else {
-                    self.selectCheckbox($(this), false);
-                }
-            });
-        },
-
-        /**
-        * Hides checkboxes
-        */
-        hideCheckboxes: function Ui_hideCheckboxes() {
-            var self = this;
-            this.selectCheckbox($('#selectAllDetails'), false);
-
-            $('#forCallerList').find('input').each(function () {
-                self.selectCheckbox($(this), false);
-            });
-            this.changeDetailsToRemoveState('hide');
-        },
-
-        /**
-        * Returns css classes for specified entry
-        *
-        * @param {CallHistoryEntry} entry
-        * @returns {string}
-        */
-        cssClassesForEntry: function Ui_cssClassesForEntry(entry) {
-            return 'call dir_' +
-                entry.direction.toLowerCase() +
-                ' type_' +
-                entry.type.replace('.', '-').toLowerCase();
-        },
-
-        /**
-         * Check if all details checkboxes are selected
-         * and if so check selectAll element
-         */
-        setSelectAllDetails: function Ui_setSelectAllDetails() {
-            if (
-                $('#forCallerList input[type="checkbox"]').length ===
-                    $('#forCallerList input[checked="checked"]').length
-            ) {
-                this.selectCheckbox($('#selectAllDetails'), true);
-            } else {
-                this.selectCheckbox($('#selectAllDetails'), false);
-            }
-        },
-
-        /**
-        * Shows popup with specified message
-        * @param {string} message
-        */
-        showPopup: function Ui_showPopup(message) {
-            $('#popupMessage').html(message);
-            $('#popup').popup('open', {'positionTo': 'window'});
-        },
-
-        /**
-        * Hides popup
-        */
-        closePopup: function Ui_closePopup() {
-            $('#popup').popup('close');
-        },
-
-        /**
-         * Display error popup
-         */
-        showErrorPopup: function Ui_showErrorPopup(message) {
-            $('#errorPopupMessage').html(message);
-            $('#errorPopup').popup('open', {'positionTo': 'window'});
-        },
-
-        /**
-         * Hides error popup
-         */
-        closeErrorPopup: function Ui_closeErrorPopup() {
-            $('#errorPopup').popup('close');
-        },
-
-        /**
-        * Deletes checked log entries
-        */
-        deleteCheckedLogs: function Ui_deleteCheckedLogs(e) {
-            // if there is popup open close it
-            this.closePopup();
-
-            // uncheck SelectAll checkbox
-            this.selectCheckbox($('#selectAllDetails'), false);
-
-            // iterate through all entries
-            $('#forCallerList li.call').each(function () {
-                // if entry contains selected checkbox
-                if ($(this).find('form label').hasClass('ui-checkbox-on')) {
-                    // remove that entry
-                    app.deleteLog($(this).data('entries')[0]);
-                    // and remove connected html element
-                    $(this).remove();
-                }
-            });
-
-            // if there are still some entries
-            if ($('#forCallerList li.call').length > 0) {
-                // update header info
-                this.updateCallerHeaderNumberOfEntries(
-                    $('#forCallerList li.call').length
-                );
-            } else {
-                // if no entries change page
-                e.preventDefault();
-                $('.ui-listview-filter .ui-input-text').val('');
-                $('.ui-listview-filter .ui-input-text').trigger('change');
-                $.mobile.changePage('#callView');
-            }
-
-            this.changeDetailsToRemoveState(true);
-            this.scrollToBottom();
-        },
-
-        /**
-         * TODO Dont really know what that method exacly doing
-         * and what should do
-         * TODO need refactor
-         */
-        changeDetailsToRemoveState: function Ui_changeDetailsToRemoveState(
-            set,
-            clear
-        ) {
-            var counter = this.getCountSelectedLogEntries(),
-                numChecked = $('#forCallerList input:checked').length,
-                matrix,
-                pos;
-            if (clear === true) {
-                counter = 0;
-                // uncheck all checkboxes
-                $('#forCallerList').find(':checkbox').attr('checked', false)
-                    .data('checkboxradio').refresh();
-                $('.selectAllBox').find(':checkbox').attr('checked', false)
-                    .data('checkboxradio').refresh();
-            }
-            // TODO it is hard ot understand this
-            if (set !== undefined) {
-                this.removeMode = false;
-            } else if (counter === 0) {
-                this.removeMode = !this.removeMode;
-            }
-
-            // if app is in remove mode and there are no selected checkboxes
-            if (this.removeMode && numChecked === 0) {
-                // disable delete button
-                $('#deleteActionBtn')
-                    .addClass('ui-disabled')
-                    .attr('tabIndex', '-1')
-                    .blur();
-            // if app is not in removeMode
-            } else if (!this.removeMode) {
-                // set delete button to enabled
-                $('#deleteActionBtn')
-                    .removeClass('ui-disabled')
-                    .attr('tabIndex', '0');
-                this.selectAllDetailsEach();
-            }
-
-            // if there are no selected entries
-            if (counter === 0) {
-                // again checking removeMode
-                if (this.removeMode) {
-                    // show buttons from remove mode
-                    $('#historyForCallerView .toRemove').removeClass('hidden');
-                    $('#historyForCallerView .selectAllBox')
-                        .removeClass('hidden');
-                } else {
-                    $('#historyForCallerView .toRemove').addClass('hidden');
-                    $('#historyForCallerView .selectAllBox').addClass('hidden');
-                }
-            } else {
-                // TODO I dont understand
-                this.showPopup(
-                    counter > 1 ?
-                        'Are you sure you want to delete selected logs?' :
-                        'Are you sure you want to delete selected log?'
-                );
-            }
-
-            // TODO need refactorin
-            // HACK probably scrollview hack
-            matrix =
-                $('#historyForCallerView .ui-scrollview-view')
-                .css('transform');
-            pos = matrix.substr(7, matrix.length - 8).split(',')[5];
-            if (pos !== undefined) {
-                $('#callerListContainer')
-                    .scrollview('scrollTo', 100, parseInt(pos, 10), 10);
-            } else {
-                this.refreshScrollView();
-            }
-        },
-
-        /**
-        * Renders call history list
-        *
-        * @param {CallHistoryEntry[]} callEntries
-        */
-        showCallHistory: function Ui_showCallHistory(callEntries) {
-            var self = this,
-                pdate = null, // previous date
-                date = '',
-                elements = [], // list elements
-                len = callEntries.length, // entries length
-                tempLength = 0, // length of temporary table;
-                i, // loop counter
-                j, // loop counter
-                current, // current entry object
-                today = this.helpers.getShortDate(new Date()),
-                entryShortDate,
-                filterResult,
-                groupsOfDays = [],
-                dayLog,
-                index = 0,
-                calllogList = $('#calllogList'),
-                calllogListContent = $('#calllogListContent'),
-                calllogListContentPos;
-
-            // return duplicated entries
-            function filterForSameEntry(element) {
-                return self.getNumber(current) === self.getNumber(element)
-                    && current.direction === element.direction;
-            }
-
-            $('.selectedCount').hide();
-
-            for (i = 0; i < len; i = i + 1) {
-                current = callEntries[i];
-                date = this.helpers.toNativeDate(current.startTime);
-
-                // if date is changed create new deyLog;
-                if (date !== pdate) {
-                    dayLog = {};
-                    dayLog.date = date;
-                    dayLog.entries = [];
-                    dayLog.counters = [];
-                    groupsOfDays.push(dayLog);
-                    pdate = date;
-                }
-
-                // group entries by remote Party;
-                filterResult = dayLog.entries.filter(filterForSameEntry);
-                if (filterResult.length) {
-                    index = dayLog.entries.indexOf(filterResult[0]);
-                    dayLog.counters[index] += 1;
-                } else {
-                    dayLog.entries.push(current);
-                    dayLog.counters[dayLog.entries.length - 1] = 1;
-                }
-            }
-            // Create UL list with dividers;
-            len = groupsOfDays.length;
-            for (i = 0; i < len; i += 1) {
-                dayLog = groupsOfDays[i];
-                tempLength = dayLog.entries.length;
-                entryShortDate = this.helpers.getShortDate(
-                    dayLog.entries[0].startTime
-                );
-                for (j = 0; j < tempLength; j = j + 1) {
-                    elements.push(
-                        this.getCallItemRow(
-                            dayLog.entries[j],
-                            dayLog.counters[j]
-                        )
-                    );
-                }
-            }
-            calllogListContentPos = this.helpers.getScrollPosition(
-                calllogListContent
-            );
-            calllogList.empty().append(elements);
-
-            //workaround solution for searching phrase remain
-            // TODO FIXME
-            if ($("[data-type='search']").val().length !== "") {
-                calllogList.listview('refresh');
-                $("[data-type='search']").trigger("keyup");
-                $(".ui-li-divider")
-                    .removeClass("ui-li ui-li-divider ui-bar-s")
-                    .addClass("date");
-            } else {
-                calllogList.listview({
-                    autodividers: true,
-                    //filter: true,
-                    autodividersSelector: function (li) {
-                        return $(li).find('.callDate').text() ===
-                            app.ui.helpers.toNativeDate(new Date()) ?
-                            "Today" : $(li).find('.callDate').text();
-                    }
-                }).listview('refresh');
-                $(".ui-li-divider").removeClass().addClass("date");
-            }
-
-            setTimeout(
-                this.helpers.scrollTo.bind(
-                    this,
-                    calllogListContent,
-                    calllogListContentPos
-                ),
-                10
-            );
-        },
-
-        /**
-        * @param: {CallHistoryEntry} entry
-        */
-        getNumber: function (entry) {
-            return entry.remoteParties[0].remoteParty;
-        },
-
-        /**
-        * Returns HTML for single log entry
-        *
-        * @param {CallHistoryEntry} entry
-        * @param {number} counter
-        * @returns {HTMLPartial}
-        */
-        getCallItemRow: function Ui_getCallItemRow(entry, counter) {
-            var party = entry.remoteParties[0],
-                name = this.getNameByNumber(party.remoteParty),
-                tpl;
-
-            if (counter > 1) {
-                name += ' (' + counter + ')';
-            }
-
-            // prepare html string
-            tpl = this.templateManager.get('callItemRow', {
-                'name': name,
-                'callTime': this.helpers.toNativeTime(entry.startTime),
-                'callDate': this.helpers.toNativeDate(entry.startTime),
-                'cssClasses': this.cssClassesForEntry(entry),
-                'uid': entry.uid
-            });
-
-            // return clean DOM element so that array of those could be appended
-            // at once
-            return $(tpl)
-                .data('remoteParty', entry.remoteParties[0].remoteParty)
-                .data('entries', [entry])
-                .get(0); 
-        },
-
-        /**
-         * Return readable number identifier
-         *
-         * @param {string} number
-         * @returns {string}
-         */
-        getNameByNumber: function (number) {
-            var i, j, contact, name;
-            // iterate through loaded contacts
-            for (i in this.contactsLoaded) {
-                if (this.contactsLoaded.hasOwnProperty(i)) {
-                    contact = this.contactsLoaded[i];
-                    // iterate through numbers of contact
-                    for (j in contact.phoneNumbers) {
-                        if (contact.phoneNumbers.hasOwnProperty(j)) {
-                            // check if first 9 characters match number
-                            if (contact.phoneNumbers[j].number.substr(-9)
-                                    === number.substr(-9)) {
-                                // get display name
-                                name = contact.name.displayName;
-                                break;
-                            }
-                        }
-                    }
-                }
-            }
-            return name || number || 'Unknown';
-        },
-
-        /**
-        * Returns HTML for single caller log entry
-        *
-        * @param {CallHistoryEntry} entry
-        * @returns {HTMLElement}
-        */
-        getCallerCallLogRow: function Ui_getCallerCallLogRow(entry) {
-            return $(this.templateManager.get('callerCallItemRow', {
-                'cssClass': this.cssClassesForEntry(entry),
-                'callTime': this.helpers.toNativeTime(entry.startTime),
-                'callDuration': this.helpers.secondsToHours(entry.duration),
-                'uid': entry.uid
-            })).data('entries', [entry]).get(0);
-        },
-
-        /**
-        * Renders call log list for specified caller
-        * TODO that methods is too long!
-        *
-        * @param {string} remoteParty
-        * @param {CallHistoryEntry[]} entries
-        */
-        showHistoryForCaller: function Ui_showHistoryForCaller(
-            remoteParty,
-            entries
-        ) {
-            var pdate = '', // previous data
-                date = '',
-                elements = [],
-                len = entries.length, // number of entries
-                i,
-                checkbox;
-
-            if (len) {
-                this.updateCallerHeader(entries[0], entries.length);
-            } else {
-                // if last call log has been removed
-                this.removedLastLog();
-                this.app.lastViewedCaller = 0;
-            }
-
-            // clean the list
-            $('#forCallerList')
-                .data('remoteParty', remoteParty)
-                .data('modified', false)
-                .empty();
-
-            // group caller log entries by date
-            for (i = 0; i < len; i = i + 1) {
-                date = this.helpers.toNativeDate(entries[i].startTime);
-
-                // if date is changed render new header
-                if (date !== pdate) {
-                    elements.push(
-                        $(this.templateManager.get(
-                            'dateRow',
-                            {'date': date}
-                        )).get(0)
-                    );
-                    pdate = date;
-                }
-                elements.push(this.getCallerCallLogRow(entries[i]));
-            }
-
-            $('#forCallerList')
-                .empty()
-                .append(elements);
-
-            // set state of delete button
-            if (elements.length > 0) {
-                $('li#delete > a').addClass('ui-btn-active');
-            } else {
-                $('li#delete > a').removeClass('ui-btn-active');
-            }
-
-            $('#forCallerList').trigger('create');
-
-            // change to remove mode if it was active before registering call
-            if (this.removeMode) {
-                this.removeMode = !this.removeMode;
-                this.changeDetailsToRemoveState();
-                // check previous checked entries
-                this.checkedLogs.forEach(function (logUid) {
-                    checkbox =
-                        $('#forCallerList li.call[data-uid="' + logUid + '"]')
-                        .find(':checkbox');
-                    if (checkbox.length > 0) {
-                        checkbox.attr('checked', true)
-                            .data('checkboxradio')
-                            .refresh();
-                        $('#deleteActionBtn')
-                            .removeClass('ui-disabled')
-                            .attr('tabIndex', '0');
-                    }
-                });
-
-                this.setSelectAllDetails();
-
-                // close popup if there are no checked checkboxes
-                if (!$("#forCallerList input:checked").length) {
-                    if ($.mobile.popup.active) {
-                        $.mobile.popup.active.close();
-                    }
-                }
-            }
-            this.addEventsForCallerListCheckboxes();
-            // lock buttons if unknown caller
-            if (remoteParty) {
-                this.unlockButtons();
-            } else {
-                this.lockButtons(
-                    '#callActionBtn, #smsActionBtn, #deleteActionBtn'
-                );
-            }
-        },
-
-        /**
-        * Update accoundId
-        * @param {string} accountId
-        */
-        updateCallerHeaderAccountId: function Ui_updateCallerHeaderAccountId(
-            accountId
-        ) {
-            $('.infoContainer .accountId').html(accountId);
-        },
-
-        /**
-        * Update number of entries
-        * @param numberOfEntries
-        */
-        updateCallerHeaderNumberOfEntries:
-            function Ui_updateCallerHeaderNumberOfEntries(numberOfEntries) {
-            $('.infoContainer .numberOfEntries').html(
-                numberOfEntries +
-                    ' ' +
-                    (numberOfEntries === 1 ? 'call' : 'calls')
-            );
-        },
-
-        /**
-        * Updates caller main info
-        * @param {CallHistoryEntry} entry
-        * @param {number} numberOfEntries
-        */
-        updateCallerHeader: function Ui_updateCallerHeader(
-            entry,
-            numberOfEntries
-        ) {
-            // TODO need to refactor
-            // looks complicated
-            var name = '', party, imgPath, personId;
-
-            $('#header .photo').css('background-image', this.photoURIdefault);
-
-            if (entry.remoteParties !== null) {
-                party = entry.remoteParties[0];
-                personId = parseInt(party.personId, 10);
-                name = this.getNameByNumber(party.remoteParty);
-                if (party.displayName) {
-                    this.updateCallerHeaderAccountId(party.remoteParty);
-                }
-                this.updateCallerHeaderNumberOfEntries(numberOfEntries);
-                if (personId !== 0) {
-                    imgPath = app.getPhotoURIForContact(personId);
-                    if (imgPath !== false) {
-                        $('#header .photo')
-                            .css('background-image', 'url(' + imgPath + ')');
-                    }
-                }
-            } else if (entry.contactId !== null) {
-                name = entry.accountId;
-                this.updateCallerHeaderAccountId(entry.accountId);
-                this.updateCallerHeaderNumberOfEntries(numberOfEntries);
-            } else {
-                name = entry.accountId;
-                this.updateCallerHeaderAccountId('');
-                this.updateCallerHeaderNumberOfEntries(numberOfEntries);
-            }
-            $('.contact > .infoContainer > .name').html(
-                this.templateManager.modifiers.escape(name)
-            );
-        },
-
-        // TODO FIXME why that method is in the UI ?
-        loadContacts: function Model_loadContacts(callback) {
-            var contactsFoundCB, errorCB;
-
-            this.contactsLoaded = null;
-
-            contactsFoundCB = function (contacts) {
-                this.contactsLoaded = contacts;
-                if (callback instanceof Function) {
-                    callback();
-                }
-            };
-
-            errorCB = function (error) {
-                console.error(
-                    'Model_loadContacts, problem with find() method: ' +
-                        error.message
-                );
-            };
-
-            this.addressBook.find(contactsFoundCB.bind(this), errorCB);
-        },
-
-        /**
-        * Remove search filter from content and appends it to header
-        */
-        // TODO FIXME HACK it is one big hack for web-ui-fw
-        // title need to be changed
-        removeSearchBarToHeader: function () {
-            $('#page-header').append($('#callView .ui-listview-filter'));
-            $.mobile.activePage.page('refresh');
-            $('.ui-input-cancel').remove(); // patch for WebUI bug
-            $('#calllogListContent').trigger('resize'); // WebUi scrollview fix
-        },
-
-        /**
-         * Scroll to bottom
-         */
-        scrollToBottom: function () {
-            var scrollView = $(".ui-scrollview-view");
-            scrollView.css("-webkit-transform", "translate3d(0px, -" +
-                        scrollView.height() + "px, 0px)");
-        },
-
-        /**
-         * Binding visibility state change event
-         */
-        onVisibilityChange: function () {
-            var self = this;
-            document.addEventListener('webkitvisibilitychange', function () {
-                if (document.webkitVisibilityState === 'hidden') {
-                    self.updateCheckboxes();
-                } else {
-                    self.loadContacts(app.updateCallLists.bind(app));
-                    $('#callActionBtn, #smsActionBtn')
-                        .removeClass('ui-disabled');
-                }
-            });
-        },
-
-        /**
-         * Store uid of checked entries in checkedLogs Array
-         */
-        updateCheckboxes: function Ui_updateCheckboxes() {
-            // empty checkedLogs logs array
-            var checkedLogs = this.checkedLogs = [];
-            // iterate through the entries
-            $('#forCallerList li.call').each(function () {
-                // if entry cotains checked checkbox
-                if ($(this).find('form label').hasClass('ui-checkbox-on')) {
-                    var checkedEntry = $(this).data('entries')[0];
-                    // push the entry uid to checkedLogs array
-                    checkedLogs.push(checkedEntry.uid);
-                }
-            });
-        },
-
-        /**
-         * Disabling element
-         * @param {jQuery} element
-         */
-        lockButtons: function Ui_lockButtons(buttons) {
-            $(buttons).addClass('ui-disabled').attr('tabIndex', '-1').blur();
-        },
-
-        /**
-         * Enabling element
-         * @param {jQuery} element
-         */
-        unlockButtons: function Ui_unlockButtons() {
-            $('#callActionBtn, #smsActionBtn, #deleteActionBtn')
-                .removeClass('ui-disabled')
-                .attr('tabIndex', '0');
-        },
-
-        /**
-        * HACK TODO FIXME;
-        * Patch for UI, bad refresh scrollView
-        */
-        refreshScrollView: function () {
-            var scrollView = $('.ui-scrollview-view'),
-                show = function () {
-                    scrollView.show();
-                };
-            scrollView.hide();
-            setTimeout(show, 0);
-        },
-
-        /**
-         * Handle event when last log is removed
-         */
-        removedLastLog: function () {
-            this.hideCheckboxes();
-            $(".ui-popup").popup('close');
-            $.mobile.changePage('#callView');
-        }
-    };
+       'use strict';
+       Ui.prototype = {
+               /**
+                * UI remove mode
+                * @type {boolean}
+                */
+               removeMode: false,
+
+               addressBook: tizen.contact.getDefaultAddressBook(),
+
+               photoURIdefault: null,
+
+               contactsLoaded: null,
+
+               checkedLogs: [],
+
+               /**
+                * @type {TemplateManager}
+                */
+               templateManager: null,
+
+               /**
+                * UI Initializer
+                */
+               init: function Ui_init() {
+                       this.loadContacts();
+                       this.templateManager = new TemplateManager();
+                       this.helpers = new Helpers();
+                       $(document).ready(this.domInit.bind(this));
+                       $.mobile.tizen.disableSelection(document);
+               },
+
+               /**
+                * When DOM is ready, initialise it (bind events)
+                */
+               domInit: function Ui_domInit() {
+                       this.templateManager.loadToCache(['callView',
+                               'callerHistory',
+                               'callItemRow',
+                               'callerCallItemRow',
+                               'messageWindow',
+                               'errorWindow',
+                               'dateRow'], this.initPages.bind(this));
+               },
+
+               /**
+                * UI pages initializer
+                */
+               initPages: function Ui_initPages() {
+                       var pages = [], body = $('body');
+
+                       body
+                               .append(this.templateManager.get('messageWindow'))
+                               .append(this.templateManager.get('errorWindow'))
+                               .trigger('create');
+                       $('#callView')
+                               .append($(this.templateManager.get('callView'))
+                                       .children())
+                                       .trigger('pagecreate')
+                                       .trigger('pageshow');
+                       pages.push(this.templateManager.get('callerHistory'));
+                       body.append(pages.join(''));
+                       this.removeSearchBarToHeader();
+
+                       this.addEvents();
+                       app.showCallHistory();
+
+                       this.photoURIdefault = $("#header .photo").css('background-image');
+               },
+
+               /**
+                * Add UI events
+                */
+               addEvents: function Ui_addEvents() {
+                       var self = this;
+
+                       $(window).on('resize', function () {
+                               $.mobile.activePage.page('refresh');
+                       });
+
+                       $('#callView').on('pagebeforeshow', function () {
+                               app.showCallHistory();
+                       });
+
+                       //original code, do not remove until web-ui release; N_SE-48946
+                       //$(".ui-scrollview-view").listview();
+
+                       $('#historyForCallerView').on('pagebeforeshow', function () {
+                               self.hideCheckboxes();
+                               $('#historyForCallerView .ui-content.ui-scrollview-clip .ui-scrollview-view')
+                                       .css('-webkit-transform', 'translate3d(0px, 0px, 0px)');
+                               $('#selectAllDetails').on('change', function () {
+                                       self.selectAll();
+                               });
+                       });
+
+                       $('#historyForCallerView').on('pageshow', function () {
+                               $('#content').css('top', '160px');
+                               $('#header').css('height', '160px');
+                               $('#callerListContainer')
+                                       .children('.ui-overflow-indicator-top', '.ui-overflow-indicator-bottom')
+                                       .hide();
+                       });
+
+                       $('#callerListContainer').on('scrollstart', function () {
+                               $(this)
+                                       .children('.ui-overflow-indicator-top', '.ui-overflow-indicator-bottom')
+                                       .fadeIn(200);
+                       });
+
+                       $('#callerListContainer').on('scrollstop', function () {
+                               $(this)
+                                       .children('.ui-overflow-indicator-top', '.ui-overflow-indicator-bottom')
+                                       .fadeOut(200);
+                       });
+
+                       $('.selectAllBox').children().on('click', function () {
+                               $('.selectAllBox input[type=checkbox]').trigger('click');
+                               self.selectAll();
+                               self.selectAllDetailsEach();
+                       });
+
+                       $('#calllogList').on('click', '.date', function (event) {
+                               event.stopPropagation();
+                       });
+
+                       $('#calllogList').on('click', '.call', function onCalllogEntryClick(event) {
+                               var remoteParty = $(this)
+                                       .data('entries')[0]
+                                       .remoteParties[0]
+                                       .remoteParty;
+                               app.showHistoryForCaller(remoteParty);
+                               $.mobile.changePage('#historyForCallerView');
+                       });
+
+                       $('#smsActionBtn').on('click', function (event) {
+                               event.stopPropagation();
+                               event.preventDefault();
+                               self.lockButtons('#smsActionBtn');
+                               self.hideCheckboxes();
+                               app.sendSms($('#forCallerList').data('remoteParty'));
+                       });
+
+                       $('#callActionBtn').on("click", function (event) {
+                               self.lockButtons('#callActionBtn');
+                               self.hideCheckboxes();
+                               app.makeCall($('#forCallerList').data('remoteParty'));
+                       });
+
+                       $('#deleteActionBtn').on('click', function () {
+                               self.changeDetailsToRemoveState();
+                       });
+
+                       $('.selectAllBox').on('click', 'li', function () {
+                               var checkbox = $(this).find(':checkbox');
+                               if (self.removeMode === true) {
+                                       if (checkbox.attr('checked')) {
+                                               checkbox.attr('checked', false)
+                                                       .data('checkboxradio')
+                                                       .refresh();
+                                       } else {
+                                               checkbox.attr('checked', true)
+                                                       .data('checkboxradio')
+                                                       .refresh();
+                                       }
+                                       self.setSelectAllDetails();
+                               }
+                       });
+
+                       $('#popup')
+                               .on('click', '#popupCancelActionBtn', this.closePopup.bind(this))
+                               .on('click', '#popupSubmitActionBtn', this.deleteCheckedLogs.bind(this));
+
+                       $('#errorPopup').on('click', '#errorPopupOkBtn', this.closeErrorPopup);
+
+                       $( "#errorPopup" ).bind({
+                               popupafterclose: function(){
+                                       self.unlockButtons();
+                               }
+                       });
+
+                       $(window).keyup(function(e){
+                               if (e.which === 13) {
+                                       $('input:focus').blur();
+                               }
+                       });
+
+                       window.addEventListener('tizenhwkey', function(e) {
+                               if (e.keyName == "back") {
+                                       if ($.mobile.popup.active) {
+                                               $.mobile.popup.active.close();
+                                       } else if (self.removeMode === true) {
+                                               app.ui.changeDetailsToRemoveState(undefined, true);
+                                       } else if ($.mobile.activePage.attr('id') === 'callView') {
+                                               tizen.application.getCurrentApplication().exit();
+                                       } else {
+                                               history.back();
+                                       }
+                               }
+                       });
+                       self.onVisibilityChange();
+               },
+
+               addEventsForCallerListCheckboxes: function Ui_addEventsForCallerListCheckboxes() {
+                       var self = this;
+                       $('#forCallerList :checkbox').on('change', function (event) {
+                               if ($(this).attr('checked')) {
+                                       $(this).attr('checked', true);
+                               } else {
+                                       $(this).attr('checked', false);
+                               }
+                               self.setSelectAllDetails();
+                       });
+               },
+
+               selectAll: function () {
+                       if ($('#selectAllDetails').attr('checked')) {
+                               this.selectCheckbox($('#selectAllDetails'), true);
+                       } else {
+                               this.selectCheckbox($('#selectAllDetails'), false);
+                       }
+                       this.selectAllDetailsEach();
+               },
+
+               selectCheckbox: function (obj, state) {
+                       var deleteButton = $('#deleteActionBtn'), numChecked;
+                       obj.attr('checked', state)
+                               .data('checkboxradio')
+                               .refresh();
+
+                       numChecked = $('#forCallerList input:checked').length;
+                       if (this.removeMode && numChecked === 0 && !deleteButton.hasClass('ui-disabled')) {
+                               deleteButton.addClass('ui-disabled').attr('tabIndex', '-1').blur();
+                       } else if (deleteButton.hasClass('ui-disabled')) {
+                               deleteButton.removeClass('ui-disabled').attr('tabIndex', '0');
+                       }
+               },
+
+               /**
+                * Returns number of selected call logs
+                * @return {number} length
+                */
+               getCountSelectedLogEntries: function Ui_getCountSelectedLogEntries() {
+                       return $('#forCallerList li .toRemove label.ui-checkbox-on').length;
+               },
+
+               selectAllDetailsEach: function Ui_selectAllDetailsEach() {
+                       var self = this;
+                       $('#forCallerList').find('input').each(function () {
+                               if ($('#selectAllDetails').attr('checked')) {
+                                       self.selectCheckbox($(this), true);
+                               } else {
+                                       self.selectCheckbox($(this), false);
+                               }
+                       });
+               },
+
+               /**
+                * Hides checkboxes
+                */
+               hideCheckboxes: function Ui_hideCheckboxes() {
+                       var self = this;
+                       this.selectCheckbox($('#selectAllDetails'), false);
+
+                       $('#forCallerList').find('input').each(function () {
+                               self.selectCheckbox($(this), false);
+                       });
+                       this.changeDetailsToRemoveState('hide');
+               },
+
+               /**
+                * Returns css classes for specified entry
+                *
+                * @param {CallHistoryEntry} entry
+                * @returns {string}
+                */
+               cssClassesForEntry: function Ui_cssClassesForEntry(entry) {
+                       return 'call dir_' + entry.direction.toLowerCase() + ' type_' + entry.type.replace('.', '-').toLowerCase();
+               },
+
+               setSelectAllDetails: function Ui_setSelectAllDetails() {
+                       if ($('#forCallerList input[type="checkbox"]').length ===
+                               $('#forCallerList input[checked="checked"]').length) {
+                               this.selectCheckbox($('#selectAllDetails'), true);
+                       } else {
+                               this.selectCheckbox($('#selectAllDetails'), false);
+                       }
+               },
+
+               /**
+                * Shows popup with specified message
+                * @param {string} message
+                */
+               showPopup: function Ui_showPopup(message) {
+                       $('#popupMessage').html(message);
+                       $('#popup').popup('open', {'positionTo': 'window'});
+               },
+
+               /**
+                * Hides popup
+                */
+               closePopup: function Ui_closePopup() {
+                       $('#popup').popup('close');
+               },
+
+               showErrorPopup: function Ui_showErrorPopup(message) {
+                       $('#errorPopupMessage').html(message);
+                       $('#errorPopup').popup('open', {'positionTo': 'window'});
+               },
+
+               closeErrorPopup: function Ui_closeErrorPopup() {
+                       $('#errorPopup').popup('close');
+               },
+
+               /**
+                * Deletes checked log entries
+                */
+               deleteCheckedLogs: function Ui_deleteCheckedLogs(e) {
+                       this.closePopup();
+
+                       this.selectCheckbox($('#selectAllDetails'), false);
+
+                       $('#forCallerList li.call').each(function () {
+                               if ($(this).find('form label').hasClass('ui-checkbox-on')) {
+                                       app.deleteLog($(this).data('entries')[0]);
+                                       $(this).remove();
+                               }
+                       });
+
+                       if ($('#forCallerList li.call').length > 0) {
+                               this.updateCallerHeaderNumberOfEntries($('#forCallerList li.call').length);
+                       } else {
+                               e.preventDefault();
+                               $('.ui-listview-filter .ui-input-text').val('');
+                               $('.ui-listview-filter .ui-input-text').trigger('change');
+                               $.mobile.changePage('#callView');
+                       }
+
+                       this.changeDetailsToRemoveState(true);
+                       this.scrollToBottom();
+               },
+
+               changeDetailsToRemoveState: function Ui_changeDetailsToRemoveState(set, clear) {
+                       var counter = this.getCountSelectedLogEntries(),
+                               numChecked = $('#forCallerList input:checked').length,
+                               matrix, pos;
+                       if (clear === true) {
+                               counter = 0;
+                               $('#forCallerList').find(':checkbox').attr('checked', false)
+                                       .data('checkboxradio').refresh();
+                               $('.selectAllBox').find(':checkbox').attr('checked', false)
+                                       .data('checkboxradio').refresh();
+                       }
+                       if (set !== undefined) {
+                               this.removeMode = false;
+                       } else if (counter === 0) {
+                               this.removeMode = !this.removeMode;
+                       }
+
+                       if (this.removeMode && numChecked === 0) {
+                               $('#deleteActionBtn').addClass('ui-disabled').attr('tabIndex', '-1').blur();
+                       } else if (!this.removeMode) {
+                               $('#deleteActionBtn').removeClass('ui-disabled').attr('tabIndex', '0');
+                               this.selectAllDetailsEach();
+                       }
+
+                       if (counter === 0) {
+                               if (this.removeMode) {
+                                       $('#historyForCallerView .toRemove').removeClass('hidden');
+                                       $('#historyForCallerView .selectAllBox')
+                                               .removeClass('hidden');
+                               } else {
+                                       $('#historyForCallerView .toRemove').addClass('hidden');
+                                       $('#historyForCallerView .selectAllBox').addClass('hidden');
+                               }
+                       } else if (counter > 1) {
+                               this.showPopup('Are you sure you want to delete selected logs?');
+                       } else {
+                               this.showPopup('Are you sure you want to delete selected log?');
+                       }
+
+                       matrix = $('#historyForCallerView .ui-scrollview-view').css('transform');
+                       pos = matrix.substr(7, matrix.length -8).split(',')[5];
+                       if (pos !== undefined) {
+                               $('#callerListContainer').scrollview('scrollTo', 100, parseInt(pos), 10);
+                       } else {
+                               this.refreshScrollView();
+                       }
+               },
+
+               /**
+                * Renders call history list
+                *
+                * @param {CallHistoryEntry[]} callEntries
+                */
+               showCallHistory: function Ui_showCallHistory(callEntries) {
+                       var self = this,
+                               pdate = null, // previous date
+                               date = '',
+                               elements = [], // list elements
+                               len = callEntries.length, // entries length
+                               tempLength = 0, // length of temporary table;
+                               i, // loop counter
+                               j, // loop counter
+                               current, // current entry object
+                               today = this.helpers.getShortDate(new Date()), // today short date
+                               entryShortDate,
+                               filterResult,
+                               groupsOfDays = [],
+                               dayLog,
+                               index = 0,
+                               calllogList = $('#calllogList'),
+                               calllogListContent = $('#calllogListContent'),
+                               calllogListContentPos;
+
+                       function filterForSameEntry(element) {
+                               return self.getNumber(current) === self.getNumber(element)
+                                       && current.direction === element.direction;
+                       }
+
+                       $('.selectedCount').hide();
+
+                       for (i = 0; i < len; i = i + 1) {
+                               current = callEntries[i];
+                               date = this.helpers.toNativeDate(current.startTime);
+
+                               // if date is changed create new deyLog;
+                               if (date !== pdate) {
+                                       dayLog = {};
+                                       dayLog.date = date;
+                                       dayLog.entries = [];
+                                       dayLog.counters = [];
+                                       groupsOfDays.push(dayLog);
+                                       pdate = date;
+                               }
+
+                               // group entries by remote Party;
+                               filterResult = dayLog.entries.filter(filterForSameEntry);
+                               if (filterResult.length) {
+                                       index = dayLog.entries.indexOf(filterResult[0]);
+                                       dayLog.counters[index] += 1;
+                               } else {
+                                       dayLog.entries.push(current);
+                                       dayLog.counters[dayLog.entries.length - 1] = 1;
+                               }
+                       }
+                       // Create UL list with dividers;
+                       len = groupsOfDays.length;
+                       for (i = 0; i < len; i += 1) {
+                               dayLog = groupsOfDays[i];
+                               tempLength = dayLog.entries.length;
+                               entryShortDate = this.helpers.getShortDate(dayLog.entries[0].startTime);
+                               // add date header;
+                               //original code, do not remove until web-ui release; N_SE-48946
+//                             elements.push($(this.templateManager.get('dateRow', {
+//                                     'date': today === entryShortDate ? 'Today' : dayLog.date
+//                             })).get(0));
+
+                               for (j = 0; j < tempLength; j = j + 1) {
+                                       elements.push(this.getCallItemRow(dayLog.entries[j], dayLog.counters[j]));
+                               }
+                       }
+                       calllogListContentPos = this.helpers.getScrollPosition(calllogListContent);
+                       calllogList.empty().append(elements);
+
+                       /* workaround solution for searching phrase remain*/
+                       if ($("[data-type='search']").val().length != "") {
+                               calllogList.listview('refresh');
+                               $("[data-type='search']").trigger("keyup");
+                               $(".ui-li-divider").removeClass("ui-li ui-li-divider ui-bar-s").addClass("date");
+                       } else {
+                           calllogList.listview({
+                                       autodividers: true,
+                                       //filter: true,
+                                       autodividersSelector: function ( li ) {
+                                               return $(li).find('.callDate').text() === app.ui.helpers.toNativeDate(new Date())
+                                               ? "Today" : $(li).find('.callDate').text();
+                                       }
+                               }).listview('refresh');
+                               $(".ui-li-divider").removeClass().addClass("date");
+                       }
+
+                       setTimeout(this.helpers.scrollTo.bind(this, calllogListContent, calllogListContentPos), 10);
+               },
+
+               /**
+                * @param: {CallHistoryEntry} entry
+                */
+               getNumber: function (entry) {
+                       return entry.remoteParties[0].remoteParty;
+               },
+
+               /**
+                * Returns HTML for single log entry
+                *
+                * @param {CallHistoryEntry} entry
+                * @param {number} counter
+                * @returns {HTMLPartial}
+                */
+               getCallItemRow: function Ui_getCallItemRow(entry, counter) {
+                       var party = entry.remoteParties[0],
+                               name = this.getNameByNumber(party.remoteParty),
+                               tpl;
+
+                       if (counter > 1) {
+                               name += ' (' + counter + ')';
+                       }
+
+                       tpl = this.templateManager.get('callItemRow', {
+                               'name': name,
+                               'callTime': this.helpers.toNativeTime(entry.startTime),
+                               'callDate': this.helpers.toNativeDate(entry.startTime),
+                               'cssClasses': this.cssClassesForEntry(entry),
+                               'uid': entry.uid
+                       });
+
+                       return $(tpl)
+                               .data('remoteParty', entry.remoteParties[0].remoteParty)
+                               .data('entries', [entry])
+                               .get(0); // return clean DOM element so array of those could be appended at once*/
+               },
+
+               getNameByNumber: function (number) {
+                       var i, j, contact, name;
+                       for (i in this.contactsLoaded) {
+                               if (this.contactsLoaded.hasOwnProperty(i)) {
+                                       contact = this.contactsLoaded[i];
+                                       for (j in contact.phoneNumbers) {
+                                               if (contact.phoneNumbers.hasOwnProperty(j)) {
+                                                       if (contact.phoneNumbers[j].number.substr(-9)
+                                                                       === number.substr(-9)) {
+                                                               name = contact.name.displayName;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       return name || number || 'Unknown';
+               },
+
+               /**
+                * Returns HTML for single caller log entry
+                *
+                * @param {CallHistoryEntry} entry
+                * @returns {HTMLElement}
+                */
+               getCallerCallLogRow: function Ui_getCallerCallLogRow(entry) {
+                       return $(this.templateManager.get('callerCallItemRow', {
+                               'cssClass': this.cssClassesForEntry(entry),
+                               'callTime': this.helpers.toNativeTime(entry.startTime),
+                               'callDuration': this.helpers.secondsToHours(entry.duration),
+                               'uid': entry.uid
+                       })).data('entries', [entry]).get(0);
+               },
+
+               /**
+                * Renders call log list for specified caller
+                *
+                * @param {string} remoteParty
+                * @param {CallHistoryEntry[]} entries
+                */
+               showHistoryForCaller: function Ui_showHistoryForCaller(remoteParty, entries) {
+                       var pdate = '',
+                               date = '',
+                               elements = [],
+                               len = entries.length,
+                               i,
+                               checkbox;
+
+                       if (len) {
+                               this.updateCallerHeader(entries[0], entries.length);
+                       } else {
+                               // if last call log has been removed
+                               this.removedLastLog();
+                               this.app.lastViewedCaller = 0;
+                       }
+
+                       $('#forCallerList')
+                               .data('remoteParty', remoteParty)
+                               .data('modified', false)
+                               .empty();
+
+                       // group caller log entries by date
+                       for (i = 0; i < len; i = i + 1) {
+                               date = this.helpers.toNativeDate(entries[i].startTime);
+
+                               // if date is changed render new header
+                               if (date !== pdate) {
+                                       elements.push($(this.templateManager.get('dateRow', {'date': date})).get(0));
+                                       pdate = date;
+                               }
+                               elements.push(this.getCallerCallLogRow(entries[i]));
+                       }
+
+                       $('#forCallerList')
+                               .empty()
+                               .append(elements);
+
+                       if (elements.length > 0) {
+                               $('li#delete > a').addClass('ui-btn-active');
+                       } else {
+                               $('li#delete > a').removeClass('ui-btn-active');
+                       }
+
+                       $('#forCallerList').trigger('create');
+
+                       // change to remove mode if it was active before registering call
+                       if (this.removeMode) {
+                               this.removeMode = !this.removeMode;
+                               this.changeDetailsToRemoveState();
+                               // check previous checked entries
+                               this.checkedLogs.forEach(function(logUid){
+                                       checkbox = $('#forCallerList li.call[data-uid="' + logUid + '"]')
+                                               .find(':checkbox');
+
+                                       if (checkbox.length > 0) {
+                                               checkbox.attr('checked', true)
+                                                       .data('checkboxradio')
+                                                       .refresh();
+                                               $('#deleteActionBtn').removeClass('ui-disabled').attr('tabIndex', '0');
+                                       }
+                               });
+
+                               this.setSelectAllDetails();
+
+                               // close popup if there are no checked checkboxes
+                               if (!$("#forCallerList input:checked").length) {
+                                       if ($.mobile.popup.active) {
+                                               $.mobile.popup.active.close();
+                                       }
+                               }
+                       }
+                       this.addEventsForCallerListCheckboxes();
+                       // lock buttons if unknown caller
+                       if (remoteParty) {
+                               this.unlockButtons();
+                       } else {
+                               this.lockButtons('#callActionBtn, #smsActionBtn');
+                       }
+               },
+
+               /**
+                * Update accoundId
+                * @param {string} accountId
+                */
+               updateCallerHeaderAccountId: function Ui_updateCallerHeaderAccountId(accountId) {
+                       $('.infoContainer .accountId').html(accountId);
+               },
+
+               /**
+                * Update number of entries
+                * @param numberOfEntries
+                */
+               updateCallerHeaderNumberOfEntries: function Ui_updateCallerHeaderNumberOfEntries(numberOfEntries) {
+                       $('.infoContainer .numberOfEntries').html('' + numberOfEntries + ' ' + (numberOfEntries === 1 ? 'call' : 'calls'));
+               },
+
+               /**
+                * Updates caller main info
+                * @param {CallHistoryEntry} entry
+                * @param {number} numberOfEntries
+                */
+               updateCallerHeader: function Ui_updateCallerHeader(entry, numberOfEntries) {
+                       var name = '', party, imgPath, personId;
+
+                       $('#header .photo').css('background-image', this.photoURIdefault);
+
+                       if (entry.remoteParties !== null) {
+                               party = entry.remoteParties[0];
+                               personId = parseInt(party.personId, 10);
+                               name = this.getNameByNumber(party.remoteParty);
+                               if (party.displayName) {
+                                       this.updateCallerHeaderAccountId(party.remoteParty);
+                               }
+                               this.updateCallerHeaderNumberOfEntries(numberOfEntries);
+                               if (personId !== 0) {
+                                       imgPath = app.getPhotoURIForContact(personId);
+                                       if (imgPath !== false) {
+                                               $('#header .photo').css('background-image', 'url(' + imgPath + ')');
+                                       }
+                               }
+                       } else if (entry.contactId !== null) {
+                               name = entry.accountId;
+                               this.updateCallerHeaderAccountId(entry.accountId);
+                               this.updateCallerHeaderNumberOfEntries(numberOfEntries);
+                       } else {
+                               name = entry.accountId;
+                               this.updateCallerHeaderAccountId('');
+                               this.updateCallerHeaderNumberOfEntries(numberOfEntries);
+                       }
+                       $('.contact > .infoContainer > .name').html(this.templateManager.modifiers.escape(name));
+
+               },
+
+               loadContacts: function Model_loadContacts(callback) {
+                       var contactsFoundCB, errorCB;
+
+                       this.contactsLoaded = null;
+
+                       contactsFoundCB = function (contacts) {
+                               this.contactsLoaded = contacts;
+                               if (callback instanceof Function) {
+                                       callback();
+                               }
+                       };
+
+                       errorCB = function (error) {
+                               console.error('Model_loadContacts, problem with find() method: ' + error.message);
+                       };
+
+                       this.addressBook.find(contactsFoundCB.bind(this), errorCB);
+               },
+
+               /**
+                * Remove search filter from content and appends it to header
+                */
+               removeSearchBarToHeader: function () {
+                       $('#page-header').append($('#callView .ui-listview-filter'));
+                       $.mobile.activePage.page('refresh');
+                       $('.ui-input-cancel').remove(); // patch for WebUI bug
+                       $('#calllogListContent').trigger('resize'); // WebUi scrollview fix
+               },
+
+               scrollToBottom: function () {
+                       var scrollView = $(".ui-scrollview-view");
+                       scrollView.css("-webkit-transform", "translate3d(0px, -" +
+                                               scrollView.height() + "px, 0px)");
+               },
+
+               onVisibilityChange: function () {
+                       var self = this;
+                       document.addEventListener('webkitvisibilitychange', function () {
+                               if (document.webkitVisibilityState === 'hidden') {
+                                       self.checkedLogs = [];
+                                       $('#forCallerList li.call').each(function () {
+                                               if ($(this).find('form label')
+                                                       .hasClass('ui-checkbox-on')) {
+                                                       var checkedEntry = $(this).data('entries')[0];
+                                                       self.checkedLogs.push(checkedEntry.uid);
+                                               }
+                                       });
+                               } else {
+                                       self.loadContacts(app.updateCallLists.bind(app));
+                                       $('#callActionBtn, #smsActionBtn')
+                                               .removeClass('ui-disabled');
+                               }
+                       });
+               },
+
+               lockButtons: function Ui_lockButtons(buttons) {
+                       $(buttons).addClass('ui-disabled').attr('tabIndex', '-1').blur();
+               },
+
+               unlockButtons: function Ui_unlockButtons(){
+                       $('#callActionBtn, #smsActionBtn').removeClass('ui-disabled').attr('tabIndex', '0');
+               },
+
+               /**
+                * WORKAROUND;
+                * Patch for UI, bad refresh scrollView
+                */
+               refreshScrollView: function () {
+                       var scrollView = $('.ui-scrollview-view'),
+                               show = function () {
+                                       scrollView.show();
+                               };
+                       scrollView.hide();
+                       setTimeout(show, 0);
+               },
+
+               removedLastLog: function () {
+                       this.hideCheckboxes();
+                       $(".ui-popup").popup('close');
+                       $.mobile.changePage('#callView');
+               }
+       };
 
 }());