application sources from tizen_2.2 74/10474/1 tizen
authorPiotr Dabrowski <p.dabrowski2@samsung.com>
Wed, 2 Oct 2013 08:19:28 +0000 (10:19 +0200)
committerPiotr Dabrowski <p.dabrowski2@samsung.com>
Wed, 2 Oct 2013 08:19:28 +0000 (10:19 +0200)
Change-Id: I59c808dcbf2eae37a445bdfbc5464b2f41ebd8d4

46 files changed:
calllog-snapshot.png [new file with mode: 0644]
description.xml [new file with mode: 0755]
description.xsl [new file with mode: 0755]
project/.project [new file with mode: 0644]
project/AUTHORS [new file with mode: 0644]
project/LICENSE.Flora [new file with mode: 0644]
project/NOTICE [new file with mode: 0644]
project/config.xml [new file with mode: 0644]
project/css/style.css [new file with mode: 0644]
project/icon.png [new file with mode: 0644]
project/images/address_minus_btn.png [new file with mode: 0644]
project/images/address_plus_btn.png [new file with mode: 0644]
project/images/checkboxChecked.png [new file with mode: 0644]
project/images/exit.png [new file with mode: 0644]
project/images/logs_list_block_icon.png [new file with mode: 0644]
project/images/logs_list_blocked_icon.png [new file with mode: 0644]
project/images/logs_list_call_icon.png [new file with mode: 0644]
project/images/logs_list_dialled_icon.png [new file with mode: 0644]
project/images/logs_list_missed_icon.png [new file with mode: 0644]
project/images/logs_list_missed_unchecked_icon.png [new file with mode: 0644]
project/images/logs_list_mms_icon.png [new file with mode: 0644]
project/images/logs_list_received_icon.png [new file with mode: 0644]
project/images/logs_list_rejected_icon.png [new file with mode: 0644]
project/images/logs_list_sms_icon.png [new file with mode: 0644]
project/images/logs_list_vtcall_icon.png [new file with mode: 0644]
project/images/no_photo.png [new file with mode: 0644]
project/images/trash.png [new file with mode: 0644]
project/index.html [new file with mode: 0644]
project/js/app.config.js [new file with mode: 0644]
project/js/app.helpers.js [new file with mode: 0644]
project/js/app.js [new file with mode: 0644]
project/js/app.model.js [new file with mode: 0644]
project/js/app.ui.js [new file with mode: 0644]
project/js/app.ui.templateManager.js [new file with mode: 0644]
project/js/app.ui.templateManager.modifiers.js [new file with mode: 0644]
project/js/main.js [new file with mode: 0644]
project/templates/callItemRow.tpl [new file with mode: 0644]
project/templates/callView.tpl [new file with mode: 0644]
project/templates/callerCallItemRow.tpl [new file with mode: 0644]
project/templates/callerHistory.tpl [new file with mode: 0644]
project/templates/dateRow.tpl [new file with mode: 0644]
project/templates/errorWindow.tpl [new file with mode: 0644]
project/templates/messageWindow.tpl [new file with mode: 0644]
tizen-app-template.xml [new file with mode: 0755]
tizen_32.png [new file with mode: 0644]
tizen_64.png [new file with mode: 0644]

diff --git a/calllog-snapshot.png b/calllog-snapshot.png
new file mode 100644 (file)
index 0000000..ad4d77c
Binary files /dev/null and b/calllog-snapshot.png differ
diff --git a/description.xml b/description.xml
new file mode 100755 (executable)
index 0000000..f95d288
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<?xml-stylesheet type="text/xsl" href="description.xsl"?>\r
+<Overview version="1.0">\r
+  <SampleName>CallLog</SampleName>\r
+  <SampleVersion>1.0.0</SampleVersion>\r
+  <Preview>calllog-snapshot.png</Preview>\r
+  <Description>\r
+         A sample application demonstrating the tizen device API usage.\r
+  </Description>\r
+</Overview>\r
diff --git a/description.xsl b/description.xsl
new file mode 100755 (executable)
index 0000000..bb92b88
--- /dev/null
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    This file provides a functionality to show template's description.xml in the project wizard.
+    Don't delete or move this file.
+ -->
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+  <xsl:template match="/">
+    <html>
+      <head>
+        <style type="text/css">
+          html,body {
+          font-family:Arial;
+          margin: 0px;
+          }
+          td
+          {
+          font-size:13px;
+          }
+          .samplename
+          {
+          font-size:16px;
+          color:#ffffff;
+          height:26px;
+          background-color:#6d96ac;
+          }
+          .category
+          {
+          font-size:16px;
+          color:#ffffff;
+          height:30px;
+          background-color:#6d96ac;
+          }
+          .contents
+          {
+          padding: 6px 10px 14px 10px;
+          }
+          table#widgets td
+          {
+          border: solid 1px #6d96ac;
+          border-collapse: collapse;
+          }
+          .widgetname
+          {
+          font-weight: bold;
+          text-align: center;
+          width: 20%;
+          word-break:break-all;
+          }
+          table#references td
+          {
+          width: 100%;
+          border: 0px;
+          border-spacing: 0px;
+          padding: 5px;
+          }
+          .refname
+          {
+          width: 100%;
+          font-weight: bold;
+          }
+        </style>
+      </head>
+      <body>
+        <table width="400px" border="0" cellspacing="0">
+          <tr>
+            <td class="samplename" align="center">
+              <xsl:value-of select="Overview/SampleName"/>
+              <xsl:text disable-output-escaping="yes"><![CDATA[&nbsp;]]></xsl:text>
+                         <!--
+              <xsl:value-of select="Overview/SampleVersion"/>
+                         -->
+            </td>
+          </tr>
+          <tr bgcolor="#FFFFFF">
+            <td class="contents">
+                         <strong>Type</strong>: JavaScript
+                         <p>
+              <xsl:value-of select="Overview/Description"/>
+                         </p>
+            </td>
+          </tr>
+          <tr>
+            <td align="center" bgcolor="#FFFFFF" height="260px">
+              <img>
+                <xsl:attribute name="src">
+                  <xsl:value-of select="Overview/Preview"/>
+                </xsl:attribute>
+              </img>
+            </td>
+          </tr>
+        </table>
+      </body>
+    </html>
+  </xsl:template>
+
+</xsl:stylesheet>
diff --git a/project/.project b/project/.project
new file mode 100644 (file)
index 0000000..0b84754
--- /dev/null
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>CallLog</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.wst.common.project.facet.core.builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>json.validation.builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.tizen.web.jslint.nature.JSLintBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.tizen.web.css.nature.CSSBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.wst.validation.validationbuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.tizen.web.project.builder.WebBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.tizen.web.privilege.nature.PrivilegeBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.tizen.web.editor.css.nature.CSSBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>json.validation.nature</nature>
+               <nature>org.tizen.web.jslint.nature.JSLintNature</nature>
+               <nature>org.tizen.web.css.nature.CSSNature</nature>
+               <nature>org.eclipse.wst.jsdt.core.jsNature</nature>
+               <nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+               <nature>org.tizen.web.project.builder.WebNature</nature>
+               <nature>org.tizen.web.privilege.nature.PrivilegeNature</nature>
+               <nature>org.tizen.web.editor.css.nature.CSSNature</nature>
+       </natures>
+</projectDescription>
diff --git a/project/AUTHORS b/project/AUTHORS
new file mode 100644 (file)
index 0000000..31f0274
--- /dev/null
@@ -0,0 +1,6 @@
+Dariusz Paziewski <d.paziewski at samsung dot com>
+Tomasz Lukawski <t.lukawski at samsung dot com>
+Piotr Wronski <p.wronski at samsung dot com>
+Pawel Sierszen <p.sierszen at samsung dot com>
+Artur Kobylinski <a.kobylinski at samsung dot com>
+Tomasz Paciorek <t.paciorek at samsung dot com>
diff --git a/project/LICENSE.Flora b/project/LICENSE.Flora
new file mode 100644 (file)
index 0000000..4a0af40
--- /dev/null
@@ -0,0 +1,206 @@
+Flora License
+
+Version 1.1, April, 2013
+
+http://floralicense.org/license/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction,
+and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by
+the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and
+all other entities that control, are controlled by, or are
+under common control with that entity. For the purposes of
+this definition, "control" means (i) the power, direct or indirect,
+to cause the direction or management of such entity,
+whether by contract or otherwise, or (ii) ownership of fifty percent (50%)
+or more of the outstanding shares, or (iii) beneficial ownership of
+such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity
+exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications,
+including but not limited to software source code, documentation source,
+and configuration files.
+
+"Object" form shall mean any form resulting from mechanical
+transformation or translation of a Source form, including but
+not limited to compiled object code, generated documentation,
+and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form,
+made available under the License, as indicated by a copyright notice
+that is included in or attached to the work (an example is provided
+in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form,
+that is based on (or derived from) the Work and for which the editorial
+revisions, annotations, elaborations, or other modifications represent,
+as a whole, an original work of authorship. For the purposes of this License,
+Derivative Works shall not include works that remain separable from,
+or merely link (or bind by name) to the interfaces of, the Work and
+Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original
+version of the Work and any modifications or additions to that Work or
+Derivative Works thereof, that is intentionally submitted to Licensor
+for inclusion in the Work by the copyright owner or by an individual or
+Legal Entity authorized to submit on behalf of the copyright owner.
+For the purposes of this definition, "submitted" means any form of
+electronic, verbal, or written communication sent to the Licensor or
+its representatives, including but not limited to communication on
+electronic mailing lists, source code control systems, and issue
+tracking systems that are managed by, or on behalf of, the Licensor
+for the purpose of discussing and improving the Work, but excluding
+communication that is conspicuously marked or otherwise designated
+in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity
+on behalf of whom a Contribution has been received by Licensor and
+subsequently incorporated within the Work.
+
+"Tizen Certified Platform" shall mean a software platform that complies
+with the standards set forth in the Tizen Compliance Specification
+and passes the Tizen Compliance Tests as defined from time to time
+by the Tizen Technical Steering Group and certified by the Tizen
+Association or its designated agent.
+
+2. Grant of Copyright License.  Subject to the terms and conditions of
+this License, each Contributor hereby grants to You a perpetual,
+worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the
+Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License.  Subject to the terms and conditions of
+this License, each Contributor hereby grants to You a perpetual,
+worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+(except as stated in this section) patent license to make, have made,
+use, offer to sell, sell, import, and otherwise transfer the Work
+solely as incorporated into a Tizen Certified Platform, where such
+license applies only to those patent claims licensable by such
+Contributor that are necessarily infringed by their Contribution(s)
+alone or by combination of their Contribution(s) with the Work solely
+as incorporated into a Tizen Certified Platform to which such
+Contribution(s) was submitted. If You institute patent litigation
+against any entity (including a cross-claim or counterclaim
+in a lawsuit) alleging that the Work or a Contribution incorporated
+within the Work constitutes direct or contributory patent infringement,
+then any patent licenses granted to You under this License for that
+Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.  You may reproduce and distribute copies of the
+Work or Derivative Works thereof pursuant to the copyright license
+above, in any medium, with or without modifications, and in Source or
+Object form, provided that You meet the following conditions:
+
+  1. You must give any other recipients of the Work or Derivative Works
+     a copy of this License; and
+  2. You must cause any modified files to carry prominent notices stating
+     that You changed the files; and
+  3. You must retain, in the Source form of any Derivative Works that
+     You distribute, all copyright, patent, trademark, and attribution
+     notices from the Source form of the Work, excluding those notices
+     that do not pertain to any part of the Derivative Works; and
+  4. If the Work includes a "NOTICE" text file as part of its distribution,
+     then any Derivative Works that You distribute must include a readable
+     copy of the attribution notices contained within such NOTICE file,
+     excluding those notices that do not pertain to any part of
+     the Derivative Works, in at least one of the following places:
+     within a NOTICE text file distributed as part of the Derivative Works;
+     within the Source form or documentation, if provided along with the
+     Derivative Works; or, within a display generated by the Derivative Works,
+     if and wherever such third-party notices normally appear.
+     The contents of the NOTICE file are for informational purposes only
+     and do not modify the License. You may add Your own attribution notices
+     within Derivative Works that You distribute, alongside or as an addendum
+     to the NOTICE text from the Work, provided that such additional attribution
+     notices cannot be construed as modifying the License. You may add Your own
+     copyright statement to Your modifications and may provide additional or
+     different license terms and conditions for use, reproduction, or
+     distribution of Your modifications, or for any such Derivative Works
+     as a whole, provided Your use, reproduction, and distribution of
+     the Work otherwise complies with the conditions stated in this License
+     and your own copyright statement or terms and conditions do not conflict
+     the conditions stated in the License including section 3.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+any Contribution intentionally submitted for inclusion in the Work
+by You to the Licensor shall be under the terms and conditions of
+this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify
+the terms of any separate license agreement you may have executed
+with Licensor regarding such Contributions.
+
+6. Trademarks.  This License does not grant permission to use the trade
+names, trademarks, service marks, or product names of the Licensor,
+except as required for reasonable and customary use in describing the
+origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+agreed to in writing, Licensor provides the Work (and each
+Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+implied, including, without limitation, any warranties or conditions
+of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+PARTICULAR PURPOSE. You are solely responsible for determining the
+appropriateness of using or redistributing the Work and assume any
+risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+whether in tort (including negligence), contract, or otherwise,
+unless required by applicable law (such as deliberate and grossly
+negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special,
+incidental, or consequential damages of any character arising as a
+result of this License or out of the use or inability to use the
+Work (including but not limited to damages for loss of goodwill,
+work stoppage, computer failure or malfunction, or any and all
+other commercial damages or losses), even if such Contributor
+has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+the Work or Derivative Works thereof, You may choose to offer,
+and charge a fee for, acceptance of support, warranty, indemnity,
+or other liability obligations and/or rights consistent with this
+License. However, in accepting such obligations, You may act only
+on Your own behalf and on Your sole responsibility, not on behalf
+of any other Contributor, and only if You agree to indemnify,
+defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason
+of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Flora License to your work
+
+To apply the Flora License to your work, attach the following
+boilerplate notice, with the fields enclosed by brackets "[]"
+replaced with your own identifying information. (Don't include
+the brackets!) The text should be enclosed in the appropriate
+comment syntax for the file format. We also recommend that a
+file or class name and description of purpose be included on the
+same "printed page" as the copyright notice for easier
+identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
diff --git a/project/NOTICE b/project/NOTICE
new file mode 100644 (file)
index 0000000..092bc04
--- /dev/null
@@ -0,0 +1,4 @@
+Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
+Except as noted, this software is licensed under Flora License, Version 1.1
+Please, see the LICENSE.Flora file for Flora License, Version 1.1 terms and conditions.
+
diff --git a/project/config.xml b/project/config.xml
new file mode 100644 (file)
index 0000000..6442a3b
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://sample-web-application.tizen.org/CallLog" version="2.2.0" viewmodes="maximized">
+       <tizen:application id="1I49ZSFY56.CallLog" package="1I49ZSFY56" required_version="2.2"/>
+       <content src="index.html"/>
+       <icon src="icon.png"/>
+       <name>Call Log</name>
+       <feature name="http://tizen.org/feature/screen.size.normal.720.1280"/>
+       <tizen:privilege name="http://tizen.org/privilege/application.launch"/>
+       <tizen:privilege name="http://tizen.org/privilege/callhistory.read"/>
+       <tizen:privilege name="http://tizen.org/privilege/callhistory.write"/>
+       <tizen:privilege name="http://tizen.org/privilege/contact.read"/>
+       <tizen:setting screen-orientation="portrait" context-menu="disable" background-support="disable" encryption="disable" install-location="auto"/>
+</widget>
diff --git a/project/css/style.css b/project/css/style.css
new file mode 100644 (file)
index 0000000..e613077
--- /dev/null
@@ -0,0 +1,404 @@
+html,body {
+       margin: 0px 0px;
+       width: 100%;
+       height: 100%;
+       color: #fff;
+       font-family: Lucida Sans, Arial, Helvetica, sans-serif;
+       overflow: hidden;
+}
+
+ul.calllogList li.date {
+       background-color: #424242;
+       color: #9B9B9B;
+       height: 22px;
+       font-size: 15px;
+       padding-left: 10px;
+       padding-top: 5px;
+}
+
+ul {
+       list-style-type: none;
+       margin: 0;
+       padding: 0;
+       padding-bottom: 60px;
+       width: 100%;
+       /*float: left;*/
+}
+
+li {
+       border-bottom: 1px solid #5A99BA;
+       padding: 8px 8px 6px 8px;
+       background-color: #FFF;
+       /*
+       float: left;
+       width: 100%;
+       */
+}
+li.ui-screen-hidden{
+       display: none !important;
+}
+
+#delete span {
+       border-bottom: 0px;
+}
+
+.hidden {
+       display: none !important;
+}
+
+.call .numberOrName {
+       white-space: nowrap;
+       text-overflow: ellipsis;
+       width: 95%;
+       overflow: hidden;
+       font-size: 20px;
+}
+
+.date {
+       background-color: #5A99BA;
+       color: #FFF;
+}
+
+.call {
+       -moz-border-radius-bottomleft: 0;
+       -webkit-border-bottom-left-radius: 0;
+       border-bottom-left-radius: 0;
+       -moz-border-radius-bottomright: 0;
+       -webkit-border-bottom-right-radius: 0;
+       border-bottom-right-radius: 0;
+}
+
+.call .callTime {
+       font-size: 14px;
+       color: #646464;
+       margin-left: 20px;
+       /*float: left;*/
+       margin-top: 2px;
+}
+
+.call .callAllTime {
+       font-size: 20px;
+}
+
+.call .callDuration {
+       font-size: 14px;
+       color: #646464;
+       margin-left: 20px;
+       /*float: left;*/
+       margin-top: 2px;
+}
+
+.footer {
+       background-color: #242F36;
+       height: 45px;
+}
+
+.details {
+       background-color: #5A99BA;
+       height: 30px;
+       color: white;
+       text-align: center;
+       padding-top: 10px;
+       margin-top: 0px;
+}
+
+.detailsView {
+       background-color: #0f0f0f;
+}
+
+.contact {
+       border-bottom: 1px solid #5A99BA;
+       background-color: #FFF;
+       height: 110px;
+}
+
+.contact .photo {
+       width: 50px;
+       height: 50px;
+       background-image: url('../images/no_photo.png');
+       background-repeat: no-repeat;
+       margin: 8px;
+       float: left;
+       background-size: 50px 50px;
+       border: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+.contact .name {
+       white-space: nowrap;
+       text-overflow: ellipsis;
+       width: 75%;
+       overflow: hidden;
+       font-size: 20px;
+       padding-top: 10px;
+       color: #555;
+}
+
+.contact .number {
+       font-size: 20px;
+       color: #948676;
+       clear: right;
+}
+
+.contact .number .numberOfEntries {
+       font-size: 16px;
+}
+
+.contact .infoContainer {
+       width: 100%;
+       height: 66px;
+}
+
+.contact .options {
+       clear: both;
+       margin: 0px 0px 8px 8px;
+       float: left;
+       width: 100%;
+}
+
+.contact .options p {
+       float: left;
+       margin: 5px 5px 5px 10px;
+       border: 1px solid #2F2F2F;
+       padding: 4px;
+       width: 25%;
+       text-align: center;
+       background-color: black;
+       border-radius: 3px;
+       border-color: #090909 #1F1F1F #1F1F1F #090909;
+       font-size: 28px;
+}
+
+.options .actionButton {
+       width: 43%;
+}
+
+#historyForCallerView .actionButton.ui-btn-down-s .ui-btn-inner {
+       color:inherit;
+}
+.trash {
+       background-image: url(../images/trash.png);
+       width: 21px;
+       height: 100%;
+       float: left;
+       margin: 15px;
+       background-size: 100%;
+       background-repeat: no-repeat;
+}
+
+#detailsStandardFooter {
+       height: 100%;
+}
+
+#detailsRemoveFooter {
+       height: 80px;
+}
+
+.trashDisabled {
+       background-image: url(../images/trash.png);
+       width: 18px;
+       height: 20px;
+       float: left;
+       margin: 13px;
+       background-size: 18px;
+       opacity: 0.5;
+}
+
+.cancel {
+       width: 64px;
+       height: 27px;
+       float: right;
+       border: 0;
+       margin-right: 15px;
+       margin-top: 8px;
+       background-color: #353535;
+       color: #fff;
+       border-radius: 4px;
+       width: 200px;
+       height: 80px;
+       font-size: 44px;
+       float: right;
+       margin-top: 18px;
+       margin-right: 10px;
+}
+
+.call .iconStatus {
+       width: 14px;
+       height: 14px;
+       float: left;
+       background-size: 14px;
+       margin-top: 2px;
+}
+
+.call.type_tizen-tel .iconStatus {
+       background-image: url('../images/logs_list_call_icon.png');
+}
+
+.call.dir_dialed .iconStatus {
+       background-image: url('../images/logs_list_dialled_icon.png');
+}
+
+.call.dir_missed .iconStatus {
+       background-image: url('../images/logs_list_missed_icon.png');
+}
+
+.call.dir_missednew .iconStatus {
+       background-image: url('../images/logs_list_missed_unchecked_icon.png');
+}
+
+.call.dir_received .iconStatus {
+       background-image: url('../images/logs_list_received_icon.png');
+}
+
+.call.dir_rejected .iconStatus {
+       background-image: url('../images/logs_list_rejected_icon.png');
+}
+
+.call.dir_blocked .iconStatus {
+       background-image: url('../images/logs_list_blocked_icon.png');
+}
+
+.noPhoto {
+       background-image: url('../images/no_photo.png');
+}
+
+.toRemove {
+       float: left;
+       background-size: 100%;
+       border-radius: 4px;
+       margin-right: 5px;
+}
+
+.toRemove input {
+       opacity: 0;
+       width: 20px;
+       height: 20px;
+}
+
+.toRemove .ui-checkbox {
+       position: relative !important;
+       height: auto;
+}
+
+.checked {
+       background-image: url('../images/checkboxChecked.png');
+}
+
+.selectAllBox {
+       background: #5A99BA;
+       float: left;
+       height: 33px;
+       width: 100%;
+       border-bottom: solid 1px white;
+       padding: 5px 0;
+}
+
+.selectAllBox .toRemove {
+       margin-top: 0px;
+       height: 30px;
+       width: 40px;
+       padding-left: 4px;
+}
+
+.selectAllBox p {
+       float: left;
+       margin: 5px 0 0;
+       color: #FFF;
+}
+
+.selectedCount {
+       height: 20px;
+       text-align: center;
+       background-color: #424242;
+       padding: 4px 0;
+}
+
+.calllogList .toRemove {
+       display: none;
+}
+
+.find {
+       height: 40px;
+       text-align: left;
+       background-color: #424242;
+       padding: 4px 0;
+}
+
+.find input {
+       width: 200px;
+       float: left;
+}
+
+.ui-image-search {
+       width: auto;
+       right: 0;
+       left: auto;
+}
+
+.ui-checkbox, .ui-radio {
+       height: 0;
+}
+
+.my-ui-checkbox {
+       position: relative;
+       float: left;
+       margin-top: -1rem;
+       margin-right: 1.5rem;
+       left: 0rem;
+}
+
+.ui-listview {
+       margin: 0px;
+       padding: 0px;
+       border-top-width: 0px;
+}
+
+.input-search-bar {
+       margin: 0px;
+}
+
+.ui-content.ui-scrollview-clip > div.ui-scrollview-view {
+       margin: 0px;
+       padding: 0px;
+}
+
+.ui-content .ui-listview {
+       margin: 0px;
+       padding: 0px;
+}
+
+.ui-controlbar-s, .ui-controlbar-left, .ui-controlbar-right {
+       border: 0px;
+}
+
+#header.ui-bar-s .ui-btn {
+       /*width: 100px; // this property changed back button width*/
+}
+
+.ui-popupwindow {
+       color: black;
+       padding:0.4em;
+}
+
+#popupCancelActionBtn {
+       width: 80px;
+}
+
+#popupSubmitActionBtn {
+       width: 80px;
+}
+
+#popupMessage {
+       margin-bottom: 10px;
+}
+
+#page-header a {
+       text-decoration: none;
+}
+
+.ui-footer .ui-btn-text {
+       text-transform: uppercase;
+}
+
+.date.ui-corner-top, .date.ui-corner-bottom {
+       border-radius: 0;
+}
diff --git a/project/icon.png b/project/icon.png
new file mode 100644 (file)
index 0000000..5934757
Binary files /dev/null and b/project/icon.png differ
diff --git a/project/images/address_minus_btn.png b/project/images/address_minus_btn.png
new file mode 100644 (file)
index 0000000..96f514b
Binary files /dev/null and b/project/images/address_minus_btn.png differ
diff --git a/project/images/address_plus_btn.png b/project/images/address_plus_btn.png
new file mode 100644 (file)
index 0000000..e23e6ff
Binary files /dev/null and b/project/images/address_plus_btn.png differ
diff --git a/project/images/checkboxChecked.png b/project/images/checkboxChecked.png
new file mode 100644 (file)
index 0000000..3482362
Binary files /dev/null and b/project/images/checkboxChecked.png differ
diff --git a/project/images/exit.png b/project/images/exit.png
new file mode 100644 (file)
index 0000000..5e5b54e
Binary files /dev/null and b/project/images/exit.png differ
diff --git a/project/images/logs_list_block_icon.png b/project/images/logs_list_block_icon.png
new file mode 100644 (file)
index 0000000..cb718a9
Binary files /dev/null and b/project/images/logs_list_block_icon.png differ
diff --git a/project/images/logs_list_blocked_icon.png b/project/images/logs_list_blocked_icon.png
new file mode 100644 (file)
index 0000000..7153ca2
Binary files /dev/null and b/project/images/logs_list_blocked_icon.png differ
diff --git a/project/images/logs_list_call_icon.png b/project/images/logs_list_call_icon.png
new file mode 100644 (file)
index 0000000..0e2444a
Binary files /dev/null and b/project/images/logs_list_call_icon.png differ
diff --git a/project/images/logs_list_dialled_icon.png b/project/images/logs_list_dialled_icon.png
new file mode 100644 (file)
index 0000000..828fc96
Binary files /dev/null and b/project/images/logs_list_dialled_icon.png differ
diff --git a/project/images/logs_list_missed_icon.png b/project/images/logs_list_missed_icon.png
new file mode 100644 (file)
index 0000000..8ee1df3
Binary files /dev/null and b/project/images/logs_list_missed_icon.png differ
diff --git a/project/images/logs_list_missed_unchecked_icon.png b/project/images/logs_list_missed_unchecked_icon.png
new file mode 100644 (file)
index 0000000..43f4314
Binary files /dev/null and b/project/images/logs_list_missed_unchecked_icon.png differ
diff --git a/project/images/logs_list_mms_icon.png b/project/images/logs_list_mms_icon.png
new file mode 100644 (file)
index 0000000..86f594c
Binary files /dev/null and b/project/images/logs_list_mms_icon.png differ
diff --git a/project/images/logs_list_received_icon.png b/project/images/logs_list_received_icon.png
new file mode 100644 (file)
index 0000000..30e397a
Binary files /dev/null and b/project/images/logs_list_received_icon.png differ
diff --git a/project/images/logs_list_rejected_icon.png b/project/images/logs_list_rejected_icon.png
new file mode 100644 (file)
index 0000000..af1f97a
Binary files /dev/null and b/project/images/logs_list_rejected_icon.png differ
diff --git a/project/images/logs_list_sms_icon.png b/project/images/logs_list_sms_icon.png
new file mode 100644 (file)
index 0000000..cb58c22
Binary files /dev/null and b/project/images/logs_list_sms_icon.png differ
diff --git a/project/images/logs_list_vtcall_icon.png b/project/images/logs_list_vtcall_icon.png
new file mode 100644 (file)
index 0000000..dcd0664
Binary files /dev/null and b/project/images/logs_list_vtcall_icon.png differ
diff --git a/project/images/no_photo.png b/project/images/no_photo.png
new file mode 100644 (file)
index 0000000..10a4d5b
Binary files /dev/null and b/project/images/no_photo.png differ
diff --git a/project/images/trash.png b/project/images/trash.png
new file mode 100644 (file)
index 0000000..d85e734
Binary files /dev/null and b/project/images/trash.png differ
diff --git a/project/index.html b/project/index.html
new file mode 100644 (file)
index 0000000..c3c0778
--- /dev/null
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+       <meta charset="utf-8"/>
+       <meta name="description" content="Call log Web Sample App"/>
+       <meta name="viewport" content="width=360, user-scalable=no"/>
+
+       <title>Call log</title>
+
+       <script src="tizen-web-ui-fw/latest/js/jquery.min.js"></script>
+       <script src="tizen-web-ui-fw/latest/js/tizen-web-ui-fw-libs.min.js"></script>
+       <script src="tizen-web-ui-fw/latest/js/tizen-web-ui-fw.min.js" data-framework-theme="tizen-white" data-framework-viewport-scale="false"></script>
+
+       <script type="text/javascript" src="./js/main.js"></script>
+       <link rel="stylesheet" type="text/css" href="./css/style.css"/>
+</head>
+<body>
+       <div data-role="page" data-footer-Exist="false" id="callView"></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/project/js/app.config.js b/project/js/app.config.js
new file mode 100644 (file)
index 0000000..03eb992
--- /dev/null
@@ -0,0 +1,30 @@
+/*global tizen*/
+
+/**
+ * @class Config
+ */
+function Config() {
+       'use strict';
+}
+
+(function () { // strict mode wrapper
+       'use strict';
+       Config.prototype = {
+
+               properties: {
+                       'templateDir': 'templates',
+                       'templateExtension': '.tpl'
+               },
+
+               /**
+                * Returns config value
+                */
+               get: function (value, defaultValue) {
+
+                       if (this.properties.hasOwnProperty(value)) {
+                               return this.properties[value];
+                       }
+                       return defaultValue;
+               }
+       };
+}());
diff --git a/project/js/app.helpers.js b/project/js/app.helpers.js
new file mode 100644 (file)
index 0000000..868f551
--- /dev/null
@@ -0,0 +1,112 @@
+/*jslint devel: true*/
+/*global $ */
+
+/**
+ * @class Helpers
+ */
+function Helpers() {
+       'use strict';
+}
+
+(function () { // strict mode wrapper
+       'use strict';
+       Helpers.prototype = {
+
+               /**
+                * Returns date in format YYYY/MM/DD
+                * @param dateObj
+                * @returns {String} formatted
+                */
+               getShortDate: function Helpers_getShortDate(dateObj) {
+                       var dd, mm, yyyy;
+
+                       try {
+                               yyyy = dateObj.getFullYear().toString();
+                               mm = (dateObj.getMonth() + 1).toString(); // getMonth() is zero-based
+                               dd  = dateObj.getDate().toString();
+                       } catch (e) {
+                               console.error('error', e);
+                       }
+
+                       return yyyy + '/' + (mm[1] ? mm : '0' + mm[0]) + '/' + (dd[1] ? dd : '0' + dd[0]);
+               },
+               /**
+                * Returns date in format DD short_month YYYY
+                * @param dateObj
+                * @returns {String} formatted
+                */
+               toNativeDate: function Helpers_toNativeDate(dateObj) {
+                       var date = dateObj.toDateString().split(" ");
+
+                       return  date[2] + ' ' + date[1] + ' ' + date[3];
+               },
+               /**
+                * Returns time in format HH:mm or hh:mm ap
+                * @param dateObj
+                * @returns {String} formatted
+                */
+               toNativeTime: function Helpers_toNativeDate(dateObj) {
+                       var hours, apHours;
+
+                       if (tizen.time.getTimeFormat().indexOf('ap') != -1) {
+                               hours = dateObj.getHours();
+                               apHours = hours % 12 < 10 ? '0' + hours % 12 : hours % 12;
+
+                               return apHours.toString().replace("00", "12") + ':' +
+                                       (dateObj.getMinutes() < 10 ? "0" + dateObj.getMinutes() :
+                                       dateObj.getMinutes()) + (hours > 11 ? ' PM' : ' AM');
+                       }
+
+                       return dateObj.toTimeString().substring(0, 5);
+               },
+               /**
+                * Seconds to hours converter
+                *
+                * @param seconds
+                * @returns {string}
+                */
+               secondsToHours: function Helpers_secondsToHours(seconds) {
+                       var str = '';
+                       str = ((seconds % 60 < 10) ? '0' : '') + (seconds % 60);
+                       seconds = parseInt(seconds / 60, 10);
+                       str = ':' + str;
+                       str = ((seconds % 60 < 10) ? '0' : '') + (seconds % 60) + str;
+                       seconds = parseInt(seconds / 60, 10);
+                       str = ':' + str;
+                       str = ((seconds % 24 < 10) ? '0' : '') + (seconds % 24) + str;
+                       seconds = parseInt(seconds / 24, 10);
+                       return str;
+               },
+
+               /**
+                * Returns scroll position of the given scroll view.
+                * @param {object} element ScrollView element
+                * @returns {number} scroll position
+                */
+               getScrollPosition: function Helpers_getScrollPosition(element) {
+                       return element.scrollview('getScrollPosition').y;
+               },
+
+               /**
+                * Scrolls given jQuery ScrollView to given Y position.
+                * @param {object} element ScrollView element to be scrolled.
+                * @param {number} position Y position to scroll to
+                */
+               scrollTo: function Helpers_scrollTo(element, position) {
+                       // don't allow scrolling too much
+                       var maxPosition = element.children().first().outerHeight(true) - element.height();
+                       if (maxPosition < 0) {
+                               maxPosition = 0;
+                       }
+                       if (position > maxPosition) {
+                               position = maxPosition;
+                       }
+                       if (position < 0) {
+                               position = 0;
+                       }
+                       // scroll
+                       element.scrollview('scrollTo', 0, -position);
+               }
+
+       };
+}());
diff --git a/project/js/app.js b/project/js/app.js
new file mode 100644 (file)
index 0000000..e58ca9d
--- /dev/null
@@ -0,0 +1,176 @@
+/*jslint devel: true*/
+/*global Config, Model, Ui, tizen, setTimeout, navigator */
+
+var App = null;
+
+(function () { // strict mode wrapper
+       'use strict';
+
+       /**
+        * Creates a new application object
+        *
+        * @class Application
+        */
+       App = function App() {
+               this.configData = {};
+       };
+
+       App.prototype = {
+               /**
+                * @type Array
+                */
+               requires: ['js/app.config.js', 'js/app.model.js', 'js/app.ui.js', 'js/app.ui.templateManager.js', 'js/app.ui.templateManager.modifiers.js', 'js/app.helpers.js'],
+
+               /**
+                * @type Model
+                */
+               model: null,
+
+               /**
+                * @type Ui
+                */
+               ui: null,
+
+               /**
+                * @type Config
+                */
+               config: null,
+
+               /**
+                * @type {number}
+                */
+               lastViewedCaller: 0,
+
+               /**
+                * Initialisation function
+                */
+               init: function App_init() {
+                       // instantiate the libs
+                       this.config = new Config();
+                       this.model = new Model();
+                       this.model.registerChangeListener(this.updateCallLists.bind(this));
+                       this.ui = new Ui();
+                       this.updateCallLists();
+
+                       return this;
+               },
+
+               /**
+                * Updates call history and caller detailed history lists
+                */
+               updateCallLists: function App_updateCallLists() {
+                       // workaround - time zone update
+                       tizen.time.getCurrentDateTime().toLocalTimezone();
+                       // workaround;
+                       setTimeout(this.showHistoryForCaller(this.lastViewedCaller), 500);
+                       this.showCallHistory();
+               },
+
+               /**
+                * Renders call history view
+                */
+               showCallHistory: function App_showCallHistory() {
+                       this.model.getCallHistory(this.ui.showCallHistory.bind(this.ui));
+               },
+
+               /**
+                * Renders history for caller view
+                * @param {string} phoneNumber
+                */
+               showHistoryForCaller: function App_showHistoryForCaller(phoneNumber) {
+                       this.lastViewedCaller = phoneNumber;
+                       this.model.getCallHistoryForCaller(phoneNumber, this.ui.showHistoryForCaller.bind(this.ui, phoneNumber));
+               },
+
+               /**
+                * @param {number} addressBookId
+                * @param {number} contactId
+                * @returns {string} photoURI Photo URI for specified contact
+                */
+               getPhotoURIForContact: function App_getPhotoURIForContact(personId) {
+                       return this.model.getPhotoURIForContact(personId);
+               },
+
+               /**
+                * Launch extension call service
+                * @param {string} phoneNumber
+                */
+               makeCall: function App_makeCall(phoneNumber) {
+                       var self = this,
+                               appControl = new tizen.ApplicationControl(
+                                       'http://tizen.org/appcontrol/operation/call',
+                                       'tel:' + phoneNumber
+                               );
+                       tizen.application.launchAppControl(
+                               appControl,
+                               null,
+                               function () {
+                               },
+                               function (e) {
+                                       console.error('Call to ' + phoneNumber
+                                               + ' failed. Call service is unavailable.', e);
+                                       self.ui.showErrorPopup('Call failed. '
+                                               + 'Call service is unavailable.');
+                               },
+                               {
+                                       onsuccess: function () {
+                                       },
+                                       onfailure: function (e) {
+                                               console.log('App_makeCall: Call to ' + phoneNumber
+                                                       + ' failed. Call service was busy.', e);
+                                               //self.ui.showErrorPopup('Call failed.'
+                                               //      + 'Call service was busy.');
+                                       }
+                               }
+                       );
+               },
+
+               /**
+                * Launch extension sms service
+                * @param {string} phoneNumber
+                */
+               sendSms: function App_sendSms(phoneNumber) {
+
+                       var self = this,
+                               appControl = new tizen.ApplicationControl(
+                                       'http://tizen.org/appcontrol/operation/compose',
+                                       'sms:' + phoneNumber
+                               );
+
+                       tizen.application.launchAppControl(
+                               appControl,
+                               null,
+                               null,
+                               function (e) {
+                                       console.error('Message launch error: ', e);
+                                       self.ui.showErrorPopup('Message service is unavailable');
+                                       app.ui.unlockOptionButtons();
+                               },
+                               {
+                                       onfailure: function (er) {
+                                               console.error('Message service launch error: ', er);
+                                               self.ui.showErrorPopup('Message service is unavailable');
+                                               app.ui.unlockOptionButtons();
+                                       }
+                               }
+                       );
+               },
+
+               /**
+                * Deletes specified log entry
+                * @param {CallHistoryEntry} entry
+                */
+               deleteLog: function App_deleteLogs(entry) {
+                       this.model.deleteLog(entry);
+               },
+
+               /**
+                * App exit
+                */
+               exit: function App_exit(event) {
+                       event.preventDefault();
+                       event.stopPropagation();
+                       tizen.application.getCurrentApplication().exit();
+               }
+       };
+}());
diff --git a/project/js/app.model.js b/project/js/app.model.js
new file mode 100644 (file)
index 0000000..42c3c64
--- /dev/null
@@ -0,0 +1,113 @@
+/*jslint devel: true*/
+/*global tizen, $, app, localStorage */
+
+/**
+ * @class Model
+ */
+function Model() {
+       'use strict';
+
+       this.init();
+}
+
+(function () { // strict mode wrapper
+       'use strict';
+       Model.prototype = {
+
+               /**
+                * API module initialisation
+                */
+               init: function Model_init() {
+               },
+
+               /**
+                * Registers listener for call history change
+                * @param {onSuccessCallback} function
+                */
+               registerChangeListener: function Model_registerChangeListener(onSuccessCallback) {
+
+                       var callHistoryListener = {
+                               onadded: onSuccessCallback,
+                               onchanged: onSuccessCallback,
+                               onremoved: onSuccessCallback
+                       };
+
+                       tizen.callhistory.addChangeListener(callHistoryListener);
+               },
+
+               /**
+                * @param {function} onSuccess callback
+                * @param {function} onError callback
+                */
+               getCallHistory: function Model_getCallHistory(onSuccess, onError) {
+                       if (typeof onError !== 'function') {
+                               onError = function (e) {
+                                       console.error('Model_getCallHistory error', e);
+                               };
+                       }
+
+                       tizen.callhistory.find(onSuccess, onError, null, new tizen.SortMode('startTime', 'DESC'));
+               },
+
+               /**
+                * @param {number} phoneNumber
+                * @param {function} onSuccess Callback
+                */
+               getCallHistoryForCaller: function Model_getCallHistoryForCaller(phoneNumber, onSuccess) {
+                       var filter = null, success;
+                       if (phoneNumber) {
+                               filter = new tizen.AttributeFilter('remoteParties.remoteParty', 'EXACTLY', phoneNumber);
+                               success = onSuccess;
+                       } else {
+                               success = function (calls) {
+                                       onSuccess(calls.filter(function (element) {
+                                               if(!element.remoteParties[0].remoteParty) {
+                                                       return element;
+                                               }
+                                       }));
+                               };
+                       }
+
+                       tizen.callhistory.find(success,
+                                       function (e) {
+                                               console.error(e);
+                                       },
+                                       filter,
+                                       new tizen.SortMode('startTime', 'DESC')
+                                       );
+               },
+
+               /**
+                * Deletes specified log entry
+                * @param {CallHistoryEntry} entry
+                */
+               deleteLog: function Model_deleteLog(entry) {
+                       try {
+                               tizen.callhistory.remove(entry);
+                       } catch (e) {
+                               console.error('Error on entry delete: ' + e.message);
+                       }
+               },
+
+               /**
+                * @param {number} addressBookId
+                * @param {number} contactId
+                * @returns {string} photoURI
+                */
+               getPhotoURIForContact: function Model_getPhotoURIForContact(personId) {
+                       try {
+                               var addressBook = tizen.contact.getDefaultAddressBook(),
+                                       contact;
+
+                               if (addressBook) {
+                                       contact = addressBook.get(personId);
+                                       return contact.photoURI || false;
+                               }
+                       } catch (e) {
+                               console.error('updatePhotoByContactId error:' + e.message);
+                       }
+                       return false;
+               }
+
+       };
+}());
diff --git a/project/js/app.ui.js b/project/js/app.ui.js
new file mode 100644 (file)
index 0000000..073572a
--- /dev/null
@@ -0,0 +1,792 @@
+/*jslint devel: true*/
+/*global tizen, document, $, jQuery, app, UiPanel, UiContact, TemplateManager, window, Helpers */
+
+/**
+ * @class Ui
+ */
+
+function Ui(contacts) {
+       'use strict';
+       this.init();
+}
+
+(function () { // strict mode wrapper
+       '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');
+               }
+       };
+
+}());
diff --git a/project/js/app.ui.templateManager.js b/project/js/app.ui.templateManager.js
new file mode 100644 (file)
index 0000000..463c032
--- /dev/null
@@ -0,0 +1,139 @@
+/*global tizen, $, app, ModifierManager */
+/**
+ * @class TemplateManager
+ */
+function TemplateManager() {
+       'use strict';
+       this.init();
+}
+
+(function () { // strict mode wrapper
+       'use strict';
+       TemplateManager.prototype = {
+
+               /**
+                * Template cache
+                */
+               cache: {},
+
+               /**
+                * UI module initialisation
+                */
+               init: function init() {
+                       this.modifiers = new ModifierManager().getAll();
+               },
+
+               /**
+                * Returns template html (from cache)
+                * @param {string} tplName
+                * @param {string} tplParams
+                */
+               get: function TemplateManager_get(tplName, tplParams) {
+                       if (this.cache[tplName] !== undefined) {
+                               return this.getCompleted(this.cache[tplName], tplParams);
+                       }
+                       return '';
+               },
+
+               /**
+                * Load templates to cache
+                * @param {string} tplNames
+                * @param {function} onSuccess
+                */
+               loadToCache: function TemplateManager_loadToCache(tplNames, onSuccess) {
+                       var self = this,
+                               cachedTemplates = 0,
+                               tplName,
+                               tplPath;
+
+                       if ($.isArray(tplNames)) {
+
+                               // for each template
+                               $.each(tplNames, function (index, fileName) {
+
+                                       // cache template html
+                                       if (self.cache[fileName] === undefined) {
+                                               tplName = [fileName, app.config.get('templateExtension')].join('');
+                                               tplPath = [app.config.get('templateDir'), tplName].join('/');
+
+                                               $.ajax({
+                                                       url: tplPath,
+                                                       cache: true,
+                                                       dataType: 'html',
+                                                       async: true,
+                                                       success: function (data) {
+                                                               // increase counter
+                                                               cachedTemplates += 1;
+
+                                                               // save to cache
+                                                               self.cache[fileName] = data;
+
+                                                               // if all templates are cached launch callback
+                                                               if (cachedTemplates >= tplNames.length && typeof onSuccess === 'function') {
+                                                                       onSuccess();
+                                                               }
+                                                       },
+                                                       error: function (jqXHR, textStatus, errorThrown) {
+                                                               console.error('templateManagerError: ' + errorThrown);
+                                                       }
+                                               });
+                                       } else {
+                                               // template is already cached
+                                               cachedTemplates += 1;
+                                               // if all templates are cached launch callback
+                                               if (cachedTemplates >= tplNames.length && typeof onSuccess === 'function') {
+                                                       onSuccess();
+                                               }
+                                       }
+                               });
+
+                       }
+               },
+
+               /**
+                * Returns template completed by specified params
+               * @param {string} tplHtml
+               * @param {string} tplParams
+                */
+               getCompleted: function TemplateManager_getCompleted(tplHtml, tplParams) {
+                       var tplParam;
+
+                       for (tplParam in tplParams) {
+                               if (tplParams.hasOwnProperty(tplParam)) {
+                                       tplHtml = this.passThruModifiers(tplHtml, tplParam, tplParams[tplParam]);
+                               }
+                       }
+
+                       return tplHtml;
+               },
+
+               passThruModifiers: function (tplHtml, tplParam, content) {
+                       var regModOn = new RegExp('%' + tplParam + '(\\|(.+?)){1,}%', 'g'),
+                               regModOff = new RegExp(['%', tplParam, '%'].join(''), 'g'),
+                               regModGet = new RegExp('%' + tplParam + '\\|(.+?)%'),
+                               regModPut = new RegExp('%' + tplParam + '\\|(.+?)%', 'g'),
+                               specRegExp = new RegExp('\\$','g'),
+                               modifiers, i;
+
+                       if (content && (typeof content === 'string')) {
+                               content = content.replace(specRegExp, '$$$$');
+                       }
+
+                       if (regModOn.test(tplHtml)) {
+                               modifiers = tplHtml.match(regModGet)[1].split('|');
+                               for (i in modifiers) {
+                                       if (this.modifiers[modifiers[i]] instanceof Function){
+                                               content = this.modifiers[modifiers[i]](content);
+                                       } else {
+                                               console.error('unknown modifier: ' + modifiers[i]);
+                                       }
+                               }
+                               tplHtml = tplHtml.replace(regModPut, content);
+                       }
+                       tplHtml = tplHtml.replace(regModOff, content);
+
+                       return tplHtml;
+               }
+       };
+
+}());
\ No newline at end of file
diff --git a/project/js/app.ui.templateManager.modifiers.js b/project/js/app.ui.templateManager.modifiers.js
new file mode 100644 (file)
index 0000000..1d57ce7
--- /dev/null
@@ -0,0 +1,36 @@
+/*global $*/
+/**
+ * @class ModifierManager
+ */
+function ModifierManager() {
+       'use strict';
+       this.init();
+}
+
+(function () {
+       'use strict';
+       ModifierManager.prototype = {
+
+               /**
+                * UI module initialisation
+                */
+               init: function () {
+               },
+
+               /**
+                * @return modifiers object
+                */
+               getAll: function () {
+                       return this.modifiers;
+               },
+
+               /**
+                * modifiers definitions
+                */
+               modifiers: {
+                       escape: function escape(str) {
+                               return $('<span>').text(str).html();
+                       }
+               }
+       };
+}());
\ No newline at end of file
diff --git a/project/js/main.js b/project/js/main.js
new file mode 100644 (file)
index 0000000..8a205f5
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ *      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, App  */
+
+/**
+ * This file acts as a loader for the application and its dependencies
+ *
+ * First, the 'app.js' script is loaded .
+ * Then, scripts defined in 'app.requires' are loaded.
+ * Finally, the app is initialised - the app is instantiated ('app = new App()')
+ * and 'app.init()' is called.
+ */
+
+
+var app = null;
+
+(function () { // strict mode wrapper
+       'use strict';
+
+       ({
+               /**
+                * Loader init - load the App constructor
+                */
+               init: function init() {
+                       var self = this;
+                       $.getScript('js/app.js')
+                               .done(function () {
+                                       // once the app is loaded, create the app object
+                                       // and load the libraries
+                                       app = new App();
+                                       self.loadLibs();
+                               })
+                               .fail(this.onGetScriptError);
+               },
+
+               /**
+                * Load dependencies
+                */
+               loadLibs: function loadLibs() {
+                       var loadedLibs = 0;
+                       if ($.isArray(app.requires)) {
+                               $.each(app.requires, function (index, filename) {
+                                       $.getScript(filename)
+                                               .done(function () {
+                                                       loadedLibs += 1;
+                                                       if (loadedLibs >= app.requires.length) {
+                                                               // All dependencies are loaded - initialise the app
+                                                               app.init();
+                                                       }
+                                               })
+                                               .fail(this.onGetScriptError);
+                               });
+                       }
+               },
+
+               /**
+                * Handle ajax errors
+                */
+               onGetScriptError: function onGetScriptError(e, jqxhr, setting, exception) {
+                       console.error('An error occurred: ' + e.message);
+               }
+       }).init(); // run the loader
+}());
diff --git a/project/templates/callItemRow.tpl b/project/templates/callItemRow.tpl
new file mode 100644 (file)
index 0000000..7cdb23a
--- /dev/null
@@ -0,0 +1,7 @@
+<li data-filtertext="%name|escape%" class="%cssClasses%">
+       <div class="toRemove hidden"><input type="checkbox" /></div>
+       <div class="numberOrName">%name|escape%</div>
+       <div class="iconStatus"></div>
+       <div class="callTime">%callTime%</div>
+       <div class="callDate hidden">%callDate%</div>
+</li>
\ No newline at end of file
diff --git a/project/templates/callView.tpl b/project/templates/callView.tpl
new file mode 100644 (file)
index 0000000..15c7610
--- /dev/null
@@ -0,0 +1,16 @@
+       <div data-role="page" id="callView" data-add-back-btn="header">
+               <div data-role="header" id="page-header" data-position="fixed">
+                       <h1>Call log</h1>
+               </div>
+               <div data-role="content" id="calllogListContent">
+                       <ul data-role="listview"
+                               id="calllogList"
+                               data-filter="true"
+                               data-autodividers="true"
+                               data-position="fixed"
+                               data-inset="true">
+                       </ul>
+               </div>
+               </div>
+               <!-- <div data-role="footer" data-position="fixed"></div> -->
+       </div>
\ No newline at end of file
diff --git a/project/templates/callerCallItemRow.tpl b/project/templates/callerCallItemRow.tpl
new file mode 100644 (file)
index 0000000..08c6f67
--- /dev/null
@@ -0,0 +1,6 @@
+<li class="ui-li-has-multiline call %cssClass%" data-uid="%uid%">
+       <div class="toRemove hidden"><form><input type="checkbox" /></form></div>
+       <div class="callAllTime">%callTime%</div>
+       <div class="iconStatus"></div>
+       <div class="callDuration">%callDuration%</div>
+</li>
\ No newline at end of file
diff --git a/project/templates/callerHistory.tpl b/project/templates/callerHistory.tpl
new file mode 100644 (file)
index 0000000..f936220
--- /dev/null
@@ -0,0 +1,36 @@
+       <div data-role="page" id="historyForCallerView">
+               <div data-role="header" data-position="fixed" id="header">
+                       <h1>History for caller</h1>
+                       <div class="contact">
+                               <div class="infoContainer">
+                                       <div class="photo"></div>
+                                       <div class="name"></div>
+                                       <div class="number"><span class="accountId"></span><span class="numberOfEntries"></span></div>
+                               </div>
+                               <div class="options">
+                                       <a href="javascript:void(0)" data-role="button" class="actionButton" id="callActionBtn" data-inline="true">Call</a>
+                                       <a href="javascript:void(0)" data-role="button" class="actionButton" id="smsActionBtn" data-inline="true">Message</a>
+                               </div>
+                       </div>
+               </div>
+               <div data-role="content" id="callerListContainer">
+                       <div class="selectAllBox">
+                               <div class="toRemove">
+                                       <input type="checkbox" id="selectAllDetails"/>
+                               </div>
+                               <p id="selectAllText">Select all</p>
+                       </div>
+                       <div id="content">
+                               <ul data-role="listview" id="forCallerList"></ul>
+                       </div>
+               </div>
+               <div data-role="footer" data-position="fixed">
+                       <div data-role="tabbar" data-style="toolbar" id="delete-toolbar">
+                               <ul>
+                                       <li id="delete">
+                                               <a id="deleteActionBtn">Delete</a>
+                                       </li>
+                               </ul>
+                       </div>
+               </div>
+       </div>
\ No newline at end of file
diff --git a/project/templates/dateRow.tpl b/project/templates/dateRow.tpl
new file mode 100644 (file)
index 0000000..9e6caa9
--- /dev/null
@@ -0,0 +1 @@
+<li class="date">%date%</li>
\ No newline at end of file
diff --git a/project/templates/errorWindow.tpl b/project/templates/errorWindow.tpl
new file mode 100644 (file)
index 0000000..f0b0216
--- /dev/null
@@ -0,0 +1,6 @@
+               <div id="errorPopup" data-role="popup" class="center_basic_2btn">
+                       <div class="ui-popup-text" id="errorPopupMessage"></div>
+                       <div class="ui-popup-button-bg">
+                               <a data-role="button" data-inline="true" id="errorPopupOkBtn">OK</a>
+                       </div>
+               </div>
diff --git a/project/templates/messageWindow.tpl b/project/templates/messageWindow.tpl
new file mode 100644 (file)
index 0000000..d916cae
--- /dev/null
@@ -0,0 +1,7 @@
+               <div id="popup" data-role="popup" class="center_basic_2btn">
+                       <div class="ui-popup-text" id="popupMessage"></div>
+                       <div class="ui-popup-button-bg">
+                               <a data-role="button" data-inline="true" id="popupCancelActionBtn">No</a>
+                               <a data-role="button" data-inline="true" id="popupSubmitActionBtn">Yes</a>
+                       </div>
+               </div>
diff --git a/tizen-app-template.xml b/tizen-app-template.xml
new file mode 100755 (executable)
index 0000000..247e616
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<tizen-app-template xmlns="http://www.tizen.org/tizen-app-template" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" template-version="" sdk-version="" icon32="tizen_32.png" icon64="tizen_64.png" xsi:schemaLocation="http://www.tizen.org/tizen-app-template tizen-app-template.xsd ">
+    <template-name>CallLog</template-name>
+    <widget-type>TIZEN</widget-type>
+    <build-property key="usedLibraryType" value="WebUIFramework"/>
+    <description-file-name>description.xml</description-file-name>
+    <options>
+        <supportLibraries>
+          <library name="Tizen Web UI Framework"/>
+        </supportLibraries>
+    </options>
+</tizen-app-template>
diff --git a/tizen_32.png b/tizen_32.png
new file mode 100644 (file)
index 0000000..61f35c0
Binary files /dev/null and b/tizen_32.png differ
diff --git a/tizen_64.png b/tizen_64.png
new file mode 100644 (file)
index 0000000..b188083
Binary files /dev/null and b/tizen_64.png differ