Initial commit of the Appmanager app 92/17392/2 accepted/tizen/ivi/20140307.010918 submit/tizen/20140307.000244 submit/tizen/20140307.001143
authorbrianjjones <brian.j.jones@intel.com>
Thu, 6 Mar 2014 23:18:15 +0000 (15:18 -0800)
committerbrianjjones <brian.j.jones@intel.com>
Thu, 6 Mar 2014 23:52:09 +0000 (15:52 -0800)
Change-Id: Ia1ca0c7298ce6018f27ca2fc556b6a743c6f8cf5

18 files changed:
Makefile [new file with mode: 0644]
config.xml [new file with mode: 0644]
css/carouselview.css [new file with mode: 0644]
css/popularApps.css [new file with mode: 0644]
css/store_library.css [new file with mode: 0644]
css/style.css [new file with mode: 0644]
icon.png [new file with mode: 0644]
index.html [new file with mode: 0644]
js/main.js [new file with mode: 0644]
js/packagerepository.js [new file with mode: 0644]
js/popularController.js [new file with mode: 0644]
js/store_library.js [new file with mode: 0644]
packaging/html5-ui-appmanager.changes [new file with mode: 0644]
packaging/html5-ui-appmanager.spec [new file with mode: 0644]
templates/carouselDelegate.html [new file with mode: 0644]
templates/detailApplicationContainer.html [new file with mode: 0644]
templates/popularAppsContainer.html [new file with mode: 0644]
templates/storeLibraryAppsDelegate.html [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..5dbf4c1
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,20 @@
+PROJECT = html5UIAppmanager
+
+VERSION := 0.0.1
+PACKAGE = $(PROJECT)-$(VERSION)
+
+INSTALL_FILES = $(PROJECT).wgt
+INSTALL_DIR = ${DESTDIR}/opt/usr/apps/.preinstallWidgets
+
+wgtPkg:
+       cp -r ${DESTDIR}/opt/usr/apps/_common/js/services js/
+       cp -r ${DESTDIR}/opt/usr/apps/_common/css/* css/
+       zip -r $(PROJECT).wgt config.xml css icon.png index.html js templates
+
+install:
+       @echo "Installing Appmanager, stand by..."
+       mkdir -p $(INSTALL_DIR)/
+       cp $(PROJECT).wgt $(INSTALL_DIR)/
+
+dist:
+       tar czf ../$(PACKAGE).tar.bz2 .
diff --git a/config.xml b/config.xml
new file mode 100644 (file)
index 0000000..78b5cb2
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://com.intel.tizen/store" version="0.5.0" viewmodes="fullscreen">
+       <name>AppManager</name>
+       <tizen:application id="html5POC03.AppManager" package="html5POC03" required_version="2.1"/>
+    <feature name="http://tizen.org/feature/network.wifi"/>
+    <feature name="http://tizen.org/feature/network.telephony"/>
+    <tizen:privilege name="http://tizen.org/privilege/application.launch"/>
+    <tizen:privilege name="http://tizen.org/privilege/package.info"/>
+    <tizen:privilege name="http://tizen.org/privilege/filesystem.write"/>
+    <tizen:privilege name="http://tizen.org/privilege/filesystem.read"/>
+    <tizen:privilege name="http://tizen.org/privilege/packagemanager.install"/>
+    <tizen:privilege name="http://tizen.org/privilege/download"/>
+    <tizen:privilege name="http://tizen.org/privilege/content.read" />
+    <tizen:privilege name="http://tizen.org/privilege/speech" />
+    <tizen:privilege name="http://tizen.org/privilege/bluetooth.admin" />
+    <tizen:privilege name="http://tizen.org/privilege/bluetooth.spp" />
+    <tizen:privilege name="http://tizen.org/privilege/bluetooth.gap" />
+       <content src="index.html"/>
+       <icon src="icon.png"/>
+       <access origin="*" subdomains="true"/>
+</widget>
diff --git a/css/carouselview.css b/css/carouselview.css
new file mode 100644 (file)
index 0000000..3fecf1c
--- /dev/null
@@ -0,0 +1,65 @@
+.carousel {
+       -webkit-transition: 2s;
+       position: absolute;
+       top: 230px;
+       left: -15px;
+       width: 12000px;
+       padding: 0;
+       margin: 0;
+}
+
+.appsCarousel li {
+       display: block;
+       float: left;
+}
+
+.carouselItem {
+       /*float: left;*/
+       width: 240px;
+       height: 240px;
+       margin-right: 15px;
+       padding: 0;
+       white-space: normal;
+       background-color: rgb(0, 0, 0);
+       background-color: rgba(0, 0, 0, 0.2);
+       box-shadow: 0 2px 30px rgba(0, 0, 0, .7);
+       border-width: 1px;
+       border-style: solid;
+       text-transform: uppercase;
+}
+
+.carouselItemSelected {
+       box-shadow: 0 0 5px 1px #1DA2FF /*background-color:#BFBFFF;*/
+}
+
+.carouselImage {
+       width: 100%;
+       height: 100%;
+}
+
+.albumCarouselDescription {
+       position: absolute;
+       width: 100%;
+       top: 145px;
+       left: 0;
+       height: 95px;
+       text-align: center;
+}
+
+.albumCarouselDescriptionText {
+       width: 220px;
+       margin: 18px auto 0 auto;
+       text-align: center;
+       overflow: hidden;
+}
+
+.carouselShadow {
+       position: relative;
+       width: 246px;
+       height: 110px;
+       top: -100px;
+       opacity: 0.2;
+       -webkit-transform: rotateX(180deg);
+       -webkit-transform-origin: 50% 50%;
+       display: none;
+}
\ No newline at end of file
diff --git a/css/popularApps.css b/css/popularApps.css
new file mode 100644 (file)
index 0000000..52e6dcc
--- /dev/null
@@ -0,0 +1,83 @@
+.divider {
+       border-bottom: solid 1px;
+       margin-top: 50px;
+       position: absolute;
+       top: 480px;
+       width: 100%;
+}
+
+.popularHeader {
+       position: absolute;
+       top: 80px;
+}
+
+.popularAppsContainer {
+       margin-left: -30px;
+       position: absolute;
+       width: 720px;
+       top: 145px;
+       overflow-x: hidden;
+       overflow-y: scroll;
+       height: 80%;
+       right: -40px;
+}
+
+.popularItem {
+       height: 182px;
+       width: 182px;
+       margin: 0 29px 58px 29px;
+       float: left;
+}
+
+.detailPopIcon {
+       width: 182px;
+       height: 182px;
+       margin: 0 auto;
+}
+
+.storePopAppInfo {
+       float: left;
+       position: relative;
+       width: 100%;
+       height: 96px;
+       left: 0;
+       top: -95px;
+       text-transform: uppercase;
+       text-align: center;
+       z-index: 9;
+}
+
+.storePopAppTitle {
+       margin-top: 5px;
+       overflow: hidden;
+       height: 28px;
+}
+
+
+.storePopAppInfoImage {
+       width: 182px;
+       height: 182px;
+}
+
+.ratingPopTable
+{
+    width:182px;
+    height:36px;
+       margin: 3px 45px;
+}
+
+.iconPopStarActive
+{
+       display:inline-block;
+}
+
+
+.transparent {
+       background-color: #111;
+       position: relative;
+       opacity: 0.65;
+       z-index: 8;
+       top: -95px;
+}
+
+
diff --git a/css/store_library.css b/css/store_library.css
new file mode 100644 (file)
index 0000000..4a9b7c6
--- /dev/null
@@ -0,0 +1,104 @@
+.storeLibraryContentList .appElement {
+       padding: 10px 0 10px 0;
+       height: 70px;
+       box-shadow: none;
+       border-bottom-style: solid;
+       border-bottom-width: 2px;
+       overflow: hidden;
+       white-space: nowrap;
+       line-height: 0;
+       text-align: left;
+       cursor: pointer;
+}
+
+.storeLibraryContentList .appImage {
+       width: 70px;
+       height: 70px;
+       display: inline-block;
+       margin-right: 20px;
+       background-position: center center;
+       background-repeat: no-repeat;
+       background-size: 100% 100%;
+}
+
+.storeLibraryContentList .appImage img {
+       width: 100%;
+       height: 100%;
+}
+
+.storeLibraryContentList .appInfoBox {
+       display: inline-block;
+       vertical-align: top;
+       padding-top: 11px;
+       background-color: transparent !important;
+}
+
+.storeLibraryContentList .appTitle {
+       text-transform: uppercase;
+}
+
+.storeLibraryContentList .appSubtitle {
+       text-transform: uppercase;
+       display: inline-block;
+       vertical-align: middle;
+}
+
+.storeLibraryContentList .appRating {
+       display: inline-block;
+       vertical-align: middle;
+}
+
+.storeLibraryContentGrid {
+       line-height: 0;
+}
+
+.storeLibraryContentGrid .appElement {
+       width: 180px;
+       height: 180px;
+       display: inline-block;
+       margin-right: 7px;
+       margin-bottom: 10px;
+       line-height: 0;
+       vertical-align: top;
+       cursor: pointer;
+}
+
+.storeLibraryContentGrid .appImage {
+       width: 100%;
+       height: 100%;
+       background-position: center center;
+       background-repeat: no-repeat;
+       background-size: 100% 100%;
+}
+
+.storeLibraryContentGrid .appImage img {
+       width: 100%;
+       height: 100%;
+}
+
+.storeLibraryContentGrid .appInfoBox {
+       position: absolute;
+       top: 95px;
+       left: 0;
+       width: 180px;
+       height: 85px;
+       text-align: center;
+}
+
+.storeLibraryContentGrid .appTitle {
+       white-space: nowrap;
+       overflow: hidden;
+       width: 160px;
+       margin: 10px auto 0 auto;
+       text-transform: uppercase;
+}
+
+.storeLibraryContentGrid .appSubtitle {
+       text-transform: uppercase;
+}
+
+.storeLibraryContentGrid .appRating {
+       width: 100px;
+       text-align: center;
+       margin: 0 auto;
+}
diff --git a/css/style.css b/css/style.css
new file mode 100644 (file)
index 0000000..ebf5512
--- /dev/null
@@ -0,0 +1,175 @@
+#backgroundStore
+{
+       position: absolute;
+       width: 720px;
+       height: 1280px;
+
+}
+#appDetailWraper{
+       /*position: absolute;*/
+       top:480px;
+       left :30px;
+       width:660px;
+       height:600px;
+}
+
+.storePromotedAppsCellHidden {
+       display: none;
+}
+
+.storePromotedAppsCellImage {
+       height: 148px;
+       width: 181px;
+       margin: 3px;
+}
+.storePromotedAppsCellText {
+       text-align: center;
+       font-size: x-large;
+       color: white;
+       text-shadow: none;
+       position: relative;
+       background-color: #111111;
+       width: 100%;
+       height: 30px;
+       opacity: 0.6;
+       left: 0;
+       top: -30px;
+
+}
+.ratingIcons
+{
+       width: 20px;
+       height: 18px;
+       background-repeat: no-repeat;
+}
+
+
+/*new added after code clear in detailApplication.css*/
+.iconElement {
+       position: absolute;
+       top: 30px;
+       left: 15px;
+       width: 145px;
+       height: 136px;
+       margin: 0 auto;
+}
+
+.detailIcon {
+       width: 145px;
+       height: 145px;
+       margin: 0 auto;
+}
+
+.ratingTableDetail {
+       position: absolute;
+       top: 155px;
+       left: 20px;
+       width: 250px;
+       height: 40px;
+}
+
+.ratingIcons {
+       float: left;
+}
+.iconStarActive {
+       display: block;
+               background-repeat: no-repeat;
+}
+.iconStarInActive {
+       display: block;
+       background-repeat: no-repeat;
+}
+
+.priceElement {
+       position: absolute;
+       left: 250px;
+       top: 35px;
+       width: 250px;
+}
+.priceTitle {
+       display: inline-block;
+       width: 100px;
+}
+.priceAmount {
+       position: relative;
+       display: inline-block;
+}
+.installButtons{
+       position: relative;
+       top:20px;
+       width:150px;
+       height:30px;
+       padding:10px;
+       border:5px;
+       border-style:solid;
+}
+.btnText {
+               text-align:center;
+}
+.infoWrapper {
+       left: 15px;
+       /*width: 900px;*/
+}
+.descriptionElement {
+       position: relative;
+       top: 80px;
+}
+.versionElement {
+       position: relative;
+       top: 100px;
+}
+.detailDescription {
+       position: relative;
+       top: 3px;
+       width: 600px;
+}
+.versionTitle {
+       position: relative;
+       display: inline-block;
+
+}
+.versionNumber {
+       position: relative;
+       display: inline-block;
+}
+.imagesElement {
+       position: relative;
+       top: 120px;
+       left: 0;
+
+}
+
+.imageElement {
+       width: 180px;
+       height: 400px;
+       float: left;
+       overflow: hidden;
+       margin-top: 10px;
+       margin-left: 5px;
+       background-repeat:no-repeat;
+}
+
+.textPanel {
+       position: relative;
+       width: 405px;
+       top: 50px;
+       display: none;
+}
+
+.installText {
+       text-align: left;
+}
+
+.progressBar {
+       position: absolute;
+       top: 40px;
+       left: 0;
+       width: 325px;
+       height: 10px;
+       border-style: solid;
+       border-width: 0 0 4px 0;
+}
+
+.appDetail {
+       height: 200px;
+}
diff --git a/icon.png b/icon.png
new file mode 100644 (file)
index 0000000..fe38f7e
Binary files /dev/null and b/icon.png differ
diff --git a/index.html b/index.html
new file mode 100644 (file)
index 0000000..82b03b9
--- /dev/null
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8" />
+<meta name="viewport" content="width=720, height=1280, user-scalable=no" />
+<meta name="description"
+       content="A single-page template generated by Tizen Web IDE" />
+
+<title>Store</title>
+
+<script type="text/javascript" src="./css/car/components/jQuery/jquery-1.8.2.js"></script>
+<script type="text/javascript" src="./css/car/components/knockout/knockout.js"></script>
+
+<!-- jsRender Library Import -->
+<script type="text/javascript" src="./css/car/components/jsViews/jsrender.js"></script>
+<script type="text/javascript" src="./css/car/components/jsViews/template.js"></script>
+<script type="text/javascript" src="./css/car/components/carousel/jquery.carouFredSel-6.2.1-packed.js"></script>
+<script type="text/javascript" src="./css/car/components/carousel/jquery.touchSwipe.min.js"></script>
+
+<script type="text/javascript" src="./js/main.js"></script>
+<script type="text/javascript" src="./js/popularController.js"></script>
+<script type="text/javascript" src="./js/store_library.js"></script>
+<script type="text/javascript" src='./js/packagerepository.js'></script>
+
+<!-- CarouselView -->
+
+<link rel="stylesheet" href="./css/carouselview.css" />
+<link rel="stylesheet" href="./css/style.css" />
+<link rel="stylesheet" href="./css/store_library.css" />
+<link rel="stylesheet" href="./css/popularApps.css" />
+<link rel="stylesheet" href="./css/car/components/incomingCall/incomingCall.css" />
+
+<link rel="stylesheet" href="./css/car/car.css">
+<link rel="stylesheet" href="./css/car/car.css" />
+<script type="text/javascript" src='./css/car/car.js'></script>
+<script type='text/javascript' src='./js/services/bootstrap.js'></script>
+
+<script type='text/javascript' src='./css/car/components/boxCaption/boxCaption.js'></script>
+<link rel="stylesheet" href="./css/car/components/boxCaption/boxCaption.css" />
+
+<script type="text/javascript" src='./css/car/components/alphabetBookmark/alphabetBookmark.js'></script>
+<link rel="stylesheet" href="./css/car/components/alphabetBookmark/alphabetBookmark.css" />
+
+<script type="text/javascript" src='./css/car/components/library/library.js'></script>
+<link rel="stylesheet" href="./css/car/components/library/library.css" />
+
+<script type='text/javascript' src='./css/car/components/topBarIcons/topBarIcons.js'></script>
+<link rel="stylesheet" href="./css/car/components/topBarIcons/topBarIcons.css" />
+
+<script type="text/javascript" src="./css/car/components/bottomPanel/bottomPanel.js"></script>
+
+<script type='text/javascript' src='./css/car/components/dateTime/dateTime.js'></script>
+<link rel="stylesheet" href="./css/car/components/dateTime/dateTime.css" />
+</head>
+
+<body>
+       <div id="backgroundStore" class="storeBackground">
+               <div id="clockElement"></div>
+       <div id="carouselObject" class="carousel">
+               <ul id="carousel_wrap" class="appsCarousel"></ul>
+       </div>
+
+               <div onClick="openStoreLibrary();"
+                       class="button libraryButton fontSizeSmaller fontWeightBold fontColorNormal">MORE
+                       APPS</div>
+
+               <div class="divider borderColorDark boxShadow1"></div>
+
+               <div id="appDetailWraper"></div>
+
+               <div id="topBarIcons"></div>
+               <div id="bottomPanel" class="bottomPanel bottomPanelImg"></div>
+
+               <div id="storeLibrary" class="library pageBgColorNormalTransparent"></div>
+       </div>
+</body>
+</html>
diff --git a/js/main.js b/js/main.js
new file mode 100644 (file)
index 0000000..d9b175b
--- /dev/null
@@ -0,0 +1,399 @@
+/*global Bootstrap, StoreLibrary, PackageRepository, packageRepository, template, Speech, AppModel, ThemeKeyColor, _applicationDetail, _categories, popularAppsModel, popularController */
+
+/**
+ * Store application provides access to [remote package server](../../package_server/index.html) with installable WGT packages. Packages are grouped
+ * into package categories like *System*, *Utilities* or *Media*. Package server takes following information from WGT
+ * package `config.xml` file:
+ *
+ * * application icon
+ * * application name
+ * * application version
+ *
+ * Package server provides additional metadata processed by Store application:
+ *
+ * * application rating
+ * * category
+ * * application description
+ * * price for application
+ * * application screenshots
+ * * flag assigning application into Promoted and/or Popular groups
+ *
+ * Store application uses {{#crossLink "PackageRepository"}}{{/crossLink}} class to download, install and uninstall applications.
+ *
+ * Package server address and credentials can be configured by updating {{#crossLink "Store/Config:property"}}{{/crossLink}} property.
+ * Please refer to [Package server documenation](../../package_server/index.html) for more details.
+ *
+ * Hover and click on elements in images below to navigate to components of Store application.
+ *
+ * <img id="Image-Maps_1201312180420487" src="../assets/img/store.png" usemap="#Image-Maps_1201312180420487" border="0" width="649" height="1152" alt="" />
+ *   <map id="_Image-Maps_1201312180420487" name="Image-Maps_1201312180420487">
+ *     <area shape="rect" coords="0,0,573,78" href="../classes/TopBarIcons.html" alt="top bar icons" title="Top bar icons" />
+ *     <area shape="rect" coords="0,77,644,132" href="../classes/Clock.html" alt="clock" title="Clock"    />
+ *     <area shape="rect" coords="0,994,644,1147" href="../classes/BottomPanel.html" alt="bottom panel" title="Bottom panel" />
+ *     <area shape="rect" coords="573,1,644,76" href="../modules/Settings.html" alt="Settings" title="Settings" />
+ *     <area  shape="rect" coords="497,135,648,178" alt="Store Library" title="Store Library" target="_self" href="../classes/StoreLibrary.html"     >
+ *     <area  shape="rect" coords="0,476,648,1001" alt="Popular applications" title="Popular applications" target="_self" href="../classes/popularController.html"     >
+ *     <area  shape="rect" coords="1,188,648,457" alt="Promoted applications" title="Promoted applications" target="_self" href="../classes/Store.html#property_promotedApplicationsModel"     >
+ *   </map>
+ *
+ * @module StoreApplication
+ * @main StoreApplication
+ * @class Store
+ **/
+
+var moved = false;
+
+/**
+ * Configuration object holding url and authentication access to remote store server
+ * @property Config
+ * @static
+ **/
+var Config = {
+       httpPrefix: "http://localhost:80",
+       username: "intel",
+       pwd: "TiZ3N456!",
+       defaultIcon: "css/car/images/default_icon.png"
+};
+
+/**
+ * Reference to instance of object holding data about promoted applications
+ * @property promotedApplicationsModel {Object}
+ */
+var promotedApplicationsModel;
+
+/**
+ * Object handling speech commands to install or uninstall application
+ * @property speechObj {Object}
+ */
+var speechObj;
+
+/**
+ * Object holding data about apps installed on the device
+ * @property installedApps {Object}
+ */
+var installedApps;
+
+var bootstrap;
+
+/**
+ * Method fills Promoted Applications carousel with data and rendering
+ * @method setupCarousel
+ * @static
+ **/
+function setupCarousel() {
+       "use strict";
+       template.compile(promotedApplicationsModel, "templates/carouselDelegate.html", "#carousel_wrap", function() {
+               $('#carousel_wrap').carouFredSel({
+                       auto: false,
+                       width: 720,
+                       items: {
+                               visible: 3
+                       },
+                       swipe: {
+                               onMouse: true,
+                               onTouch: true
+                       },
+                       scroll: {
+                               items: 1
+                       }
+               });
+
+               $('.carouselItem').on("touchstart", function (event) {
+                       moved = false;
+               });
+
+               $('.carouselItem').on("touchmove", function (event) {
+                       moved = true;
+               });
+       });
+}
+
+/**
+ * Function invoked after `touchend` event on the carousel item
+ * @method triggerTouchEnd
+ * @param cat {String} Category
+ * @param app {String} Application
+ * @static
+ **/
+function triggerTouchEnd(cat, app) {
+       "use strict";
+       if (moved === false) {
+               StoreLibrary.setAppDetailAndCategory(cat, app);
+       }
+}
+
+/**
+ * Adds http prefix to application icons' urls for apps from the store
+ * @method enhanceModelUrls
+ * @static
+ **/
+function enhanceModelUrls(model) {
+       "use strict";
+       $.each(model, function (itemIndex, item) {
+               if (item.iconUrl.indexOf(Config.httpPrefix) < 0) {
+                       item.iconUrl = Config.httpPrefix + item.iconUrl;
+               }
+       });
+}
+
+/**
+ * Looks for application icon file and provides a path to default one if not found
+ * @method getAppIcon
+ * @static
+ **/
+function getAppIcon(appIconPath, callback) {
+       "use strict";
+       try {
+               tizen.filesystem.resolve(appIconPath, function (iconFile) {
+                       callback(iconFile.fullPath);
+               }, function (error) {
+                       callback(Config.defaultIcon);
+               });
+       } catch(ex) {
+               console.log("EXCEPTION when trying to find icon file: " + ex.message);
+       }
+}
+
+/**
+ * Applies selected theme to application icons
+ * @method setThemeImageColor
+ * @static
+ **/
+function setThemeImageColor() {
+       "use strict";
+       var imageSource;
+       $('body').find('img').each(function() {
+               var self = this;
+               imageSource = $(this).attr('src');
+
+               if (typeof(imageSource) !== 'undefined' && $(this.parentElement).hasClass('themeImage') === false &&
+                       (imageSource.indexOf(Config.httpPrefix) >= 0 || imageSource.indexOf('base64') >= 0)) {
+                       var img = new Image();
+                       var ctx = document.createElement('canvas').getContext('2d');
+                       img.onload = function () {
+                               var w = ctx.canvas.width = img.width;
+                               var h = ctx.canvas.height = img.height;
+                               ctx.fillStyle = ThemeKeyColor;
+                               ctx.fillRect(0, 0, w, h);
+                               ctx.globalCompositeOperation = 'destination-in';
+                               ctx.drawImage(img, 0, 0);
+
+                               $(self).attr('src', ctx.canvas.toDataURL());
+                               $(self).hide(0, function() { $(self).show();});
+                       };
+
+                       img.src = imageSource;
+               }
+       });
+}
+
+/**
+ * Sets up voice recognition listeners for un/installing applications
+ * @method setupSpeechRecognition
+ * @static
+ **/
+function setupSpeechRecognition() {
+       "use strict";
+       console.log("Store setupSpeechRecognition");
+       Speech.addVoiceRecognitionListener({
+               onapplicationinstall : function() {
+                       console.log("Speech application install invoked");
+                       if (_applicationDetail.id !== undefined && $('#storeLibrary').library('isVisible') &&
+                               (!_applicationDetail.installed || _applicationDetail.installed === false)) {
+                               StoreLibrary.installApp(_applicationDetail.id);
+                       }
+               },
+               onapplicationuninstall : function() {
+                       console.log("Speech application uninstall invoked");
+                       if (_applicationDetail.id !== undefined && $('#storeLibrary').library('isVisible') && _applicationDetail.installed === true) {
+                               StoreLibrary.uninstallApp(_applicationDetail.id);
+                       }
+               }
+
+       });
+}
+
+/**
+ * Applies Base64 conversion to icon urls in the model
+ * @method setThemeIconColorBeforeRender
+ * @static
+ **/
+function setThemeIconColorBeforeRender(model) {
+       "use strict";
+       if (!!model) {
+               $.each(model, function (itemIndex, item) {
+                       if (item.iconUrl.indexOf(Config.httpPrefix) >= 0 || item.iconUrl.indexOf('base64') >= 0 || item.iconUrl.indexOf('intelPoc') >= 0) {
+                               var img = new Image();
+                               var aIcon = item.iconUrl;
+                               var ctx = document.createElement('canvas').getContext('2d');
+                               img.onload = function () {
+                                       var w = ctx.canvas.width = img.width;
+                                       var h = ctx.canvas.height = img.height;
+                                       ctx.fillStyle = ThemeKeyColor;
+                                       ctx.fillRect(0, 0, w, h);
+                                       ctx.globalCompositeOperation = 'destination-in';
+                                       ctx.drawImage(img, 0, 0);
+                                       item.iconUrl = ctx.canvas.toDataURL();
+                               };
+
+                               img.src = item.iconUrl;
+                       }
+               });
+       }
+}
+
+/**
+ * Loads store data and builds the page based on the data
+ * @method loadUi
+ * @static
+ **/
+function loadUi() {
+       "use strict";
+       var self;
+       packageRepository = new PackageRepository();
+       packageRepository.availableApplications(function (appData) {
+               AppModel = appData;
+               enhanceModelUrls(AppModel);
+               setThemeIconColorBeforeRender(AppModel);
+
+               promotedApplicationsModel = packageRepository.getPromotedApplications();
+               setTimeout(function() {
+                       setupCarousel();
+
+                       packageRepository.getAppsInfo(function (appsInfo) {
+                               installedApps = appsInfo;
+                               var appsNotInStore = [];
+                               var foundInStore = false;
+                               var appsLength = appsInfo.length;
+                               var appModelLength = AppModel.length;
+
+                               var processApplication = function(i) {
+                                       for (var j = 0; j < appModelLength; j++) {
+                                               if (appsInfo[i].name === AppModel[j].name) {
+                                                       foundInStore = true;
+                                                       AppModel[j].installed = true;
+
+                                                       break;
+                                               } else if (!AppModel[j].installed) {
+                                                       AppModel[j].installed = false;
+                                               }
+                                       }
+                                       if (foundInStore === false &&
+                                               (appsInfo[i].name.toLowerCase() !== "store" && appsInfo[i].name.toLowerCase() !== "homescreen" && appsInfo[i].name.toLowerCase() !== "home screen")) {
+                                               var appNotInStore = {};
+                                               appNotInStore.id = appsInfo[i].id;
+                                               appNotInStore.name = appsInfo[i].name;
+                                               appNotInStore.version = 0;
+                                               appNotInStore.silentInstall = false;
+                                               /* jshint camelcase: false */
+                                               appNotInStore.category_id = "system";
+                                               /* jshint camelcase: true */
+                                               appNotInStore.price = "0";
+                                               appNotInStore.rating = "0";
+                                               appNotInStore.description = "";
+                                               appNotInStore.isPromoted = false;
+                                               appNotInStore.isPopular = false;
+                                               appNotInStore.screenshots = [];
+                                               appNotInStore.downloadUrl = "";
+                                               getAppIcon(appsInfo[i].iconPath, function(resolvedPath) {
+                                                       appNotInStore.iconUrl = resolvedPath;
+                                               });
+                                               appNotInStore.installed = true;
+                                               AppModel.push(appNotInStore);
+                                       }
+                                       foundInStore = false;
+                               };
+
+                               for (var i = 0; i < appsLength; i++) {
+                                       processApplication(i);
+                               }
+                               popularAppsModel = packageRepository.getPopularApplications();
+                               popularController.addHeader();
+                               popularController.fillView(popularAppsModel);
+                       });
+
+               },500);
+       }, function() {
+                       packageRepository.getAppsInfo(function (appsInfo) {
+                               installedApps = appsInfo;
+                               var appsNotInStore = [];
+                               var appsLength = appsInfo.length;
+
+                               var processApplication = function(i) {
+                                       if (appsInfo[i].name.toLowerCase() !== "store" && appsInfo[i].name.toLowerCase() !== "homescreen" && appsInfo[i].name.toLowerCase() !== "home screen") {
+                                               var appNotInStore = {};
+                                               appNotInStore.id = appsInfo[i].id;
+                                               appNotInStore.name = appsInfo[i].name;
+                                               appNotInStore.version = 0;
+                                               appNotInStore.silentInstall = false;
+                                               /* jshint camelcase: false */
+                                               appNotInStore.category_id = "system";
+                                               /* jshint camelcase: true */
+                                               appNotInStore.price = "0";
+                                               appNotInStore.rating = "0";
+                                               appNotInStore.description = "";
+                                               appNotInStore.isPromoted = false;
+                                               appNotInStore.isPopular = false;
+                                               appNotInStore.screenshots = [];
+                                               appNotInStore.downloadUrl = "";
+                                               getAppIcon(appsInfo[i].iconPath, function(resolvedPath) {
+                                                       appNotInStore.iconUrl = resolvedPath;
+                                               });
+                                               appNotInStore.installed = true;
+                                               AppModel.push(appNotInStore);
+                                       }
+                               };
+
+                               for (var i = 0; i < appsLength; i++) {
+                                       processApplication(i);
+                               }
+                       });
+       });
+       packageRepository.getCategories(function (catData) {
+               _categories = catData;
+       });
+
+}
+
+/**
+ * Initialize plugins and register events for Store app.
+ * @method init
+ * @static
+ **/
+var init = function () {
+       "use strict";
+       bootstrap = new Bootstrap(function (status) {
+               $("#topBarIcons").topBarIconsPlugin('init', 'store');
+               $("#clockElement").ClockPlugin('init', 5);
+               $("#clockElement").ClockPlugin('startTimer');
+               $('#bottomPanel').bottomPanel('init');
+
+               loadUi();
+               if (tizen.speech) {
+                       setupSpeechRecognition();
+               } else {
+                       console.log("Store: Speech Recognition not running, voice control will be unavailable");
+               }
+
+               bootstrap.themeEngine.addStatusListener(function (eData) {
+                       setThemeImageColor();
+               });
+       });
+};
+
+$(document).ready(init);
+
+/**
+ * Opens store library after it's initialization or initialize library if it's not.
+ * @method openStoreLibrary
+ * @static
+ **/
+function openStoreLibrary() {
+       "use strict";
+       if (!StoreLibrary.initialized) {
+               StoreLibrary.init();
+       } else {
+               StoreLibrary.show();
+       }
+       setThemeIconColorBeforeRender(AppModel);
+}
\ No newline at end of file
diff --git a/js/packagerepository.js b/js/packagerepository.js
new file mode 100644 (file)
index 0000000..b35846d
--- /dev/null
@@ -0,0 +1,333 @@
+/*global Config, StoreLibrary, _applicationDetail, installedApps */
+
+/**
+ * Provides Javascript wrapper around AJAX-based requests to package server providing categories, lists of applications,
+ * download (using [tizen.download API](https://developer.tizen.org/dev-guide/2.2.1/org.tizen.web.device.apireference/tizen/download.html))
+ * and allows installation or uninstallation of downloaded packages through
+ * [tizen.package API](https://developer.tizen.org/dev-guide/2.2.1/org.tizen.web.device.apireference/tizen/package.html).
+ *
+ * @class PackageRepository
+ * @module StoreApplication
+ **/
+
+/**
+ * object holding info about applications available on the server as well as apps installed in the system
+ * @property AppModel
+ * @static
+ **/
+var AppModel = [];
+
+var PackageRepository = (function() {
+    "use strict";
+    function PackageRepository() {
+        console.info("Starting up PackageRepository");
+    }
+
+    PackageRepository.prototype = function() {};
+
+    PackageRepository.prototype._storage = "downloads";
+
+    /**
+     * Gets only promoted applications from list of available apps
+     * @method getPromotedApplications
+     * @param callback {Function(results)} Callback function providing array of promoted applications.
+     **/
+       PackageRepository.prototype.getPromotedApplications = function (callback) {
+        if (AppModel.length === 0) {
+            this.availableApplications(function () {
+                var result = AppModel.filter(function (app) {
+                    return app.isPromoted === true;
+                });
+                if (callback) {
+                    callback(result);
+                } else {
+                    return result;
+                }
+            });
+        } else {
+            var result = AppModel.filter(function (app) {
+                return app.isPromoted === true;
+            });
+            if (callback) {
+                callback(result);
+            } else {
+                return result;
+            }
+        }
+       };
+
+    /**
+     * Gets only popular applications from list of available apps
+     * @method getPopularApplications
+     * @param callback {Function(results)} Callback function providing array of popular applications.
+     **/
+       PackageRepository.prototype.getPopularApplications = function (callback) {
+               var result = AppModel.filter(function (app) {
+            return app.isPopular === true;
+        });
+               if (callback) {
+                       callback(result);
+               } else {
+                       return result;
+               }
+       };
+
+    /**
+     * Gets list of available categories from package server.
+     * @method getCategories
+     * @param callback {Function(results)} Callback function providing array of categories.
+     * @param errorCallback {Function(error)} Callback function providing error in case if any issue was detected.
+     **/
+       PackageRepository.prototype.getCategories = function (callback, errorCallback) {
+        $.ajax({
+            type: 'GET',
+            url: Config.httpPrefix + '/packages/categories',
+            dataType: 'json',
+            async: true,
+            username: Config.username,
+            password: Config.pwd,
+            data:'{}'
+            }).done(function(resCategories) {
+                console.log('categories: ' + JSON.stringify(resCategories));
+                if (callback) {
+                    callback(resCategories);
+                } else {
+                    return resCategories;
+                }
+        }).fail(function (jqXHR, textStatus) {
+            console.log('getCategories fail: ' + textStatus);
+            if (errorCallback) {
+                errorCallback();
+            }
+        });
+
+       };
+
+    /**
+     * Gets only applications beloging to specified category from list of available apps
+     * @method getCategoryApplications
+     * @param catId {String} Category identifier.
+     * @param callback {Function(results)} Callback function providing array of popular applications.
+     **/
+       PackageRepository.prototype.getCategoryApplications = function (catId, callback) {
+               var result = AppModel.filter(function (app) {
+            /* jshint camelcase: false */
+            var res = app.category_id === catId;
+            /* jshint camelcase: true */
+            return res;
+        });
+               if (callback) {
+                       callback(result);
+               } else {
+                       return result;
+               }
+       };
+
+    /**
+     * Gets all application data for specified application.
+     * @method getApplicationDetail
+     * @param appId {String} Application identifier.
+     * @param callback {Function(result)} Callback function providing array of popular applications.
+     **/
+       PackageRepository.prototype.getApplicationDetail = function (appId, callback) {
+               var result = AppModel.filter(function (app) {
+             return app.id === appId;
+        });
+               if (callback) {
+                       callback(result);
+               } else {
+                       return result;
+               }
+       };
+
+    /**
+     * Gets list of available applications from package server.
+     * @method availableApplications
+     * @param callback {Function(results)} Callback function providing array of applications.
+     * @param errorCallback {Function(error)} Callback function providing error in case if any issue was detected.
+     **/
+    PackageRepository.prototype.availableApplications = function (callback, errorCallback) {
+        $.ajax({
+            type: 'GET',
+            url: Config.httpPrefix + '/packages/available',
+            dataType: 'json',
+            async: true,
+            username: Config.username,
+            password: Config.pwd,
+            data:'{}'
+        }).done(function(resp) {
+                if (callback) {
+                    callback(resp);
+                }
+        }).fail(function (jqXHR, textStatus) {
+                console.log('availableApplications fail: ' + textStatus);
+                if (errorCallback) {
+                    errorCallback();
+                }
+        });
+    };
+
+
+    /**
+     * Starts package download identified by applidation identifier via [tizen.download API]()
+     * @method downloadApplication
+     * @param appId {String} Application Id
+     * @param callback {Function(error, appId, packageUri)} Callback function providing information about status about download.
+     **/
+    PackageRepository.prototype.downloadApplication = function (appId, callback) {
+        var listener = {
+            onprogress: function(id, receivedSize, totalSize) {
+                console.log('Received with id: ' + id + ', ' + receivedSize + '/' + totalSize);
+            },
+            onpaused: function(id) {
+                console.log('Paused with id: ' + id);
+            },
+            oncanceled: function(id) {
+                console.log('Canceled with id: ' + id);
+            },
+            oncompleted: function(id, fullPath) {
+                console.log('Completed with id: ' + id + ', full path: ' + fullPath);
+                tizen.filesystem.resolve(fullPath, function (file) {
+                    callback(null, id, file.toURI());
+                });
+            },
+            onfailed: function(id, error) {
+                console.log('Failed with id: ' + id + ', error name: ' + error.name);
+            }
+        };
+
+        // Starts downloading of the file from the Web with the corresponding callbacks.
+        var downloadRequest = new tizen.DownloadRequest("http://"+Config.username+":"+Config.pwd+"@localhost:80" + _applicationDetail.downloadUrl, "downloads", appId.split("/").pop() + ".wgt");
+
+        var downloadId = tizen.download.start(downloadRequest, listener);
+    };
+
+    /**
+     * Provides list of installed application using [tizen application API]().
+     * @method getAppsInfo
+     * @param callback {Function(results)} Callback function providing array of installed applications.
+     **/
+    PackageRepository.prototype.getAppsInfo = function (callback) {
+        try {
+            tizen.application.getAppsInfo(function (installedAppData) {
+                callback(installedAppData);
+            }, function(err) {
+                console.log('Failed to get installed apps info.');
+            });
+        } catch (exc) {
+            console.error(exc.message);
+        }
+    };
+
+    /**
+     * Method performs installation of specified application ID using [tizen package API]() by following process:
+     *
+     * * download package
+     * * install package
+     * * cleanup of downloaded package
+     *
+     * @method install
+     * @param appId application Id
+     * @param callback {Function(error)} Callback function invoked after installation is finished or error occurs.
+     **/
+    PackageRepository.prototype.install = function (appId, callback) {
+        var installationFile;
+        var self = this;
+        callback = callback || function() {};
+
+        var cleanup = function(err) {
+            console.log("Removing installation file " + installationFile);
+            tizen.filesystem.resolve(self._storage, function(directory) {
+                directory.deleteFile(installationFile,
+                    function() {
+                        self.getAppsInfo(function (appsInfo) {
+                            installedApps = appsInfo;
+                            callback(err);
+                        });
+                    },
+                    function(error) { callback(err || error); }
+                );
+            });
+        };
+
+        var onInstallation = {
+            onprogress: function(packageId, percentage) {
+                console.log("On installation(" + packageId + ") : progress(" + percentage + ")");
+                StoreLibrary.displayInstallProgress(true, percentage);
+            },
+            oncomplete: function(packageId) {
+                console.log("Installation(" + packageId + ") Complete");
+                cleanup();
+                this.getAppsInfo(function (appsInfo) {
+                    installedApps = appsInfo;
+                    callback();
+                });
+            }
+        };
+
+        var onError = function (err) {
+            console.error("Error occurred on installation : " + err.name);
+            callback(err);
+        };
+
+        this.downloadApplication(appId, function(error, fileName, fullPath) {
+            if (error) {
+                this.cleanup(error);
+            } else {
+                installationFile = fullPath;
+                tizen.package.install(fullPath, onInstallation, onError);
+            }
+        });
+    };
+
+    /**
+     * Method performs uninstallation of specified application ID using [tizen package API]()
+     *
+     * @method uninstall
+     * @param appId application Id
+     * @param callback {Function(error)} Callback function invoked after installation is finished or error occurs.
+     **/
+    PackageRepository.prototype.uninstall = function (appId, callback) {
+        var onInstallation = {
+            onprogress: function(packageId, percentage) {
+                console.log("On uninstallation(" + packageId + ") : progress(" + percentage + ")");
+                StoreLibrary.displayInstallProgress(false, percentage);
+            },
+            oncomplete: function(packageId) {
+                console.log("Uninstallation(" + packageId + ") Complete");
+                if (callback) {
+                    callback(true);
+                }
+            }
+        };
+
+        var onError = function (err) {
+            console.log("Error occurred on uninstallation : " + err.name);
+            if (callback) {
+                callback(false);
+            }
+        };
+        var uninstPackageName = this.getPackageId(_applicationDetail.name);
+        console.log("Trying to uninstall "+ _applicationDetail.name);
+        if (uninstPackageName === undefined) {
+            console.log("Package name not available.");
+        } else {
+            tizen.package.uninstall(uninstPackageName, onInstallation, onError);
+        }
+    };
+
+    /**
+     * Function returns package id for specified application name.
+     * @method getPackageId
+     * @param appName {String} Application name
+     **/
+    PackageRepository.prototype.getPackageId = function (appName) {
+        for (var i in installedApps) {
+            if (installedApps[i].name === appName) {
+                return installedApps[i].packageId;
+            }
+        }
+    };
+
+       return PackageRepository;
+}());
diff --git a/js/popularController.js b/js/popularController.js
new file mode 100644 (file)
index 0000000..0179d89
--- /dev/null
@@ -0,0 +1,53 @@
+/*global template, setThemeImageColor*/
+
+/**
+ * Provides controller for popular applications list.
+ * @class popularController
+ * @module StoreApplication
+ * @static
+ **/
+
+/**
+ * Hols popular apps model.
+ * @property popularAppsModel
+ * @type object
+ * @default null
+ * @static
+ **/
+var popularAppsModel = null;
+/**
+ * Holds popular apps model length.
+ * @property popularAppsModelLenght
+ * @type int
+ * @default null
+ * @static
+ **/
+var popularAppsModelLenght;
+var popularController = {
+               /**
+                * Adds header bar to store app.
+                * @method addHeader
+                **/
+               addHeader: function () {
+                       "use strict";
+                       $('#appDetailWraper').append('<div class="popularHeader fontSizeXLarge fontWeightBold fontColorDark">MOST POPULAR</div>');
+                       $('#appDetailWraper').append('<div id="popularApps" class="popularAppsContainer"></div>');
+               },
+               /**
+                * Creates store view based on model parameter.
+                * @method fillView
+                * @param model {array} Contains array of objects which holds popular apps informations.
+                **/
+               fillView: function (model) {
+                       "use strict";
+                       popularAppsModelLenght = model.length;
+                       console.log("filling popular view with " + popularAppsModelLenght + " items");
+                       var i;
+                       for (i = 0; i < popularAppsModelLenght; i++) {
+                               model[i].index = i;
+                       }
+                       template.compile(model, "templates/popularAppsContainer.html", "#popularApps", function () {
+                               setThemeImageColor();
+                       });
+               }
+       };
\ No newline at end of file
diff --git a/js/store_library.js b/js/store_library.js
new file mode 100644 (file)
index 0000000..4150953
--- /dev/null
@@ -0,0 +1,487 @@
+/*global PackageRepository, setThemeImageColor, GRID_TAB, LIST_TAB, Config, AppModel, popularAppsModel, popularController */
+
+/**
+ * Provides implementation of {{#crossLink "Library"}}{{/crossLink}} object for Store application. Applications are displayed in
+ * following hierarchy:
+ *
+ * * List of application categories
+ *   * List of applications for one category
+ *      * Application detail
+ *
+ *
+ * @class StoreLibrary
+ * @module StoreApplication
+ * @static
+ **/
+
+/**
+ * Holds array of apps categories.
+ * @property _categories
+ * @type array
+ * @default empty
+ * @static
+ **/
+var _categories = [];
+
+/**
+ * Holds object of selected apps category.
+ * @property _selectedCategory
+ * @type object
+ * @default empty
+ * @static
+ **/
+var _selectedCategory = {};
+
+/**
+ * Hols array of apps in selected category.
+ * @property _categoryApplications
+ * @type array
+ * @default empty
+ * @static
+ **/
+var _categoryApplications = [];
+
+/**
+ * Hols object of selected app detailed informations.
+ * @property _selectedCategory
+ * @type object
+ * @default empty
+ * @static
+ **/
+var _applicationDetail = {};
+
+/**
+ * Hols object of instalation timer.
+ * @property _progress
+ * @type timer
+ * @default null
+ * @static
+ **/
+var _progress;
+
+/**
+ * Hols object of uninstalation timer.
+ * @property _unProgress
+ * @type timer
+ * @default null
+ * @static
+ **/
+var _unProgress;
+
+/**
+ * Hols object of package repository.
+ * @property packageRepository
+ * @type PackageRepository
+ * @default null
+ * @static
+ **/
+var packageRepository;
+
+var StoreLibrary = {
+               /**
+                * Indicates if store library is initialized.
+                * @property initialized
+                * @type bool
+                * @default false
+                **/
+               initialized: false,
+               /**
+                * Provides initialization of store library.
+                * @method init
+                * @param showApps {bool} If true shows apps in store library ordered by category ID.
+                **/
+               init: function (showApps) {
+                       "use strict";
+                       $('#storeLibrary').library("setSectionTitle", "APP STORE");
+                       $('#storeLibrary').library("init");
+
+                       if (_categories.length > 0 ) {
+                               StoreLibrary.showStoreLibrary(showApps);
+                       } else {
+                               if (typeof PackageRepository !== 'undefined') {
+                                       packageRepository = new PackageRepository();
+                                       packageRepository.getCategories(function (jsonObject) {
+                                               if ((typeof jsonObject).toLowerCase() === "string") {
+                                                       try {
+                                                               _categories = JSON.parse(jsonObject);
+                                                       } catch (error) {
+                                                               console.log("Unable to parse categories: " + error.message);
+                                                       }
+                                               } else {
+                                                       _categories = jsonObject;
+                                               }
+                                               StoreLibrary.showStoreLibrary();
+                                       }, function(error) {
+                                               _categories.length = 0;
+                                               _categories.push({"id": "system", "description": "", "name": "System", "url": "/packageRepository/category?id=system"});
+                                               StoreLibrary.showStoreLibrary();
+                                       });
+                               } else {
+                                       console.warn("packageRepository is not available.");
+                               }
+                       }
+               },
+
+               /**
+                * Shows library of apps in Store application.
+                * @method show
+                **/
+               show: function () {
+                       "use strict";
+                       $('#storeLibrary').library("showPage");
+               },
+
+               /**
+                * Builds and displays the Store library view
+                * @method showStoreLibrary
+                * @param showApps {bool} indicator
+                **/
+               showStoreLibrary: function (showApps) {
+                       "use strict";
+                       var i = 0;
+                       for (i = 0; i < _categories.length; ++i) {
+                               if (i === 0) {
+                                       _categories[i].selected = true;
+                                       _selectedCategory = _categories[i];
+                                       if (showApps === true || showApps === undefined) {
+                                               StoreLibrary.showAppsByCategoryId(_selectedCategory.id);
+                                       }
+                               }
+                               _categories[i].text = _categories[i].name;
+                               _categories[i].action = "StoreLibrary.showAppsByCategoryId('" + _categories[i].id + "');";
+                       }
+
+                       var tabMenuModel = {
+                                       Tabs: _categories
+                               };
+
+                       $('#storeLibrary').library("tabMenuTemplateCompile", tabMenuModel, function() {
+                               setThemeImageColor();
+                       });
+
+                       $('#storeLibrary').bind('eventClick_GridViewBtn', function () {
+                               $('#storeLibrary').library('closeSubpanel');
+                               StoreLibrary.showAppsByCategoryId(_categories[$('#storeLibrary').library('getSelectetTopTabIndex')].id);
+                       });
+
+                       $('#storeLibrary').bind('eventClick_ListViewBtn', function () {
+                               $('#storeLibrary').library('closeSubpanel');
+                               StoreLibrary.showAppsByCategoryId(_categories[$('#storeLibrary').library('getSelectetTopTabIndex')].id);
+                       });
+
+                       $('#storeLibrary').bind('eventClick_SearchViewBtn', function () {
+
+                       });
+
+                       $('#storeLibrary').bind('eventClick_menuItemBtn', function (e, data) {
+                               $('#storeLibrary').library('closeSubpanel');
+                               StoreLibrary.showAppsByCategoryId(_categories[$('#storeLibrary').library('getSelectetTopTabIndex')].id);
+                       });
+
+                       $('#storeLibrary').bind('eventClick_closeSubpanel', function () {
+                               StoreLibrary.showAppsByCategoryId(_categories[$('#storeLibrary').library('getSelectetTopTabIndex')].id);
+                       });
+
+                       var heightWithoutScrollbar = $('#libraryTabsID').scrollHeight;
+                       $('#libraryTopPanel').height($('#libraryTopPanel').height() - heightWithoutScrollbar);
+                       StoreLibrary.initialized = true;
+                       StoreLibrary.show();
+               },
+
+               /**
+                * Sets category and detail of application.
+                * @method setAppDetailAndCategory
+                * @param categoryID {int} Contains ID of category to set.
+                * @param applicationID {int} Contains ID of app to show details.
+                **/
+               setAppDetailAndCategory: function (categoryID, applicationID) {
+                       "use strict";
+                       var tabID = 0, i = 0;
+                       for (i = 0; i < _categories.length; i++) {
+                               if (_categories[i].id === categoryID) {
+                                       tabID = i;
+                                       break;
+                               }
+                       }
+                       $('#storeLibrary').library('setTopTabIndex', tabID);
+                       if (!StoreLibrary.initialized) {
+                               StoreLibrary.init(false);
+                       }
+                       StoreLibrary.openAppDetail(applicationID);
+                       setThemeImageColor();
+                       StoreLibrary.show();
+               },
+
+               /**
+                * Shows apps sorted by specific categry.
+                * @method showAppsByCategoryId
+                * @param categoryID {int} Contains ID of category.
+                **/
+               showAppsByCategoryId: function (categoryID) {
+                       "use strict";
+                       packageRepository.getCategoryApplications(categoryID, function (jsonObject) {
+                               if ((typeof jsonObject).toLowerCase() === "string") {
+                                       try {
+                                               _categoryApplications = JSON.parse(jsonObject);
+                                       } catch (error) {
+                                               console.log("Unable to parse category applications: " + error.message);
+                                       }
+                               } else {
+                                       _categoryApplications = jsonObject;
+                               }
+
+                               switch ($('#storeLibrary').library('getSelectetLeftTabIndex')) {
+                               case GRID_TAB:
+                                       StoreLibrary.renderAppsGridView(_categoryApplications);
+                                       break;
+                               case LIST_TAB:
+                                       StoreLibrary.renderAppsListView(_categoryApplications);
+                                       break;
+                               default:
+                                       break;
+                               }
+                       });
+               },
+
+               /**
+                * Shows apps in grid view.
+                * @method renderAppsGridView
+                * @param model {object} Contains model of applications.
+                **/
+               renderAppsGridView: function (model) {
+                       "use strict";
+                       $('#storeLibrary').library("setContentDelegate", "templates/storeLibraryAppsDelegate.html");
+                       $('#storeLibrary').library("contentTemplateCompile", model, "storeLibraryContentGrid", function() {
+                               setThemeImageColor();
+                       });
+               },
+
+               /**
+                * Shows apps in list view.
+                * @method renderAppsGridView
+                * @param model {object} Contains model of applications.
+                **/
+               renderAppsListView: function (model) {
+                       "use strict";
+                       $('#storeLibrary').library("setContentDelegate", "templates/storeLibraryAppsDelegate.html");
+                       $('#storeLibrary').library("contentTemplateCompile", model, "storeLibraryContentList", function() {
+                               setThemeImageColor();
+                       });
+               },
+
+               /**
+                * If model of an app dosen't contain screenshot, function set default one to model.
+                * @method enhanceModelsUrls
+                * @param appDetail {array} Contains array of objects which holds promotedapps informations.
+                * @return appDetail {array} Returns enhanced model of promoted apps.
+                **/
+               enhanceModelUrls: function (appDetail) {
+                       "use strict";
+                       appDetail.imageObjects = [];
+                       if (!!appDetail.screenshots) {
+                               $.each(appDetail.screenshots, function (imageIndex, urlobject) {
+                                       appDetail.imageObjects.push({
+                                               url: Config.httpPrefix + urlobject
+                                       });
+                               });
+                       }
+                       return appDetail;
+               },
+
+               /**
+                * Opens app detail view.
+                * @method openAppDetail
+                * @param appID {string} Contains ID of app to show detail of it.
+                **/
+               openAppDetail: function (appID) {
+                       "use strict";
+                       packageRepository.getApplicationDetail(appID, function (jsonObject) {
+                               // _applicationDetail = jsonObject;
+                               _applicationDetail = StoreLibrary.enhanceModelUrls(jsonObject[0]);
+                               StoreLibrary.renderAppDetailView(_applicationDetail);
+                       });
+               },
+
+               /**
+                * Creates detail view of app.
+                * @method renderAppDetailView
+                * @param app {object} Contains object with app data.
+                **/
+               renderAppDetailView: function (app) {
+                       "use strict";
+                       var subpanelModel = {
+                                       /* jshint camelcase: false */
+                                       textTitle: StoreLibrary.getCategoryTitleById(app.category_id),
+                                       /* jshint camelcase: true */
+                                       textSubtitle: app.name || "-"
+                               };
+                       $('#storeLibrary').library("subpanelContentTemplateCompile", subpanelModel, function () {
+                               $("#libraryTopSubPanelTitle").boxCaptionPlugin('initSmall', subpanelModel.textTitle);
+                       });
+                       $('#storeLibrary').library('showSubpanel');
+                       $('#storeLibrary').library("setContentDelegate", "templates/detailApplicationContainer.html");
+                       $('#storeLibrary').library("contentTemplateCompile", app, "", function () {
+                               setThemeImageColor();
+
+                               var height = $('#storeLibrary').height();
+                               if ($("#libraryTopPanel").is(":visible")) {
+                                       height = height - $("#libraryTopPanel").outerHeight();
+                               }
+                               if ($("#libraryTopSubPanel").is(":visible")) {
+                                       height = height - $("#libraryTopSubPanel").outerHeight();
+                               }
+                               height = height - $('.appDetail').outerHeight();
+                               $('.infoWrapper').height(height);
+                       });
+               },
+
+               /**
+                * Creates search view in store.
+                * @method renderSearchView
+                **/
+               renderSearchView: function () {
+                       "use strict";
+                       $('#storeLibrary').library("clearContent");
+               },
+
+               /**
+                * Returns title of a category based on category ID.
+                * @method getCategoryTitleById
+                * @param categoryID {string} Contains object with app data.
+                * @return {string} Title of category.
+                **/
+               getCategoryTitleById: function (categoryID) {
+                       "use strict";
+                       var i = 0;
+                       for (i = 0; i < _categories.length; i++) {
+                               if (_categories[i].id === categoryID) {
+                                       return _categories[i].name;
+                               }
+                       }
+                       return "-";
+               },
+
+               /**
+                * Install a new app based on app id.
+                * @method installApp
+                * @param id {string} Contains app id.
+                **/
+               installApp: function (id) {
+                       "use strict";
+                       console.log('INSTALL APP... ' + id);
+
+                       StoreLibrary.displayInstallProgress(true, 0);
+                       packageRepository.install(id, function (instError) {
+                               packageRepository.getApplicationDetail(id, function (appDetail) {
+                                       if (instError) {
+                                               appDetail[0].installed = false;
+                                               StoreLibrary.installResult(instError, true, appDetail[0]);
+                                       } else {
+                                               appDetail[0].installed = true;
+                                               StoreLibrary.installResult(null, true, appDetail[0]);
+                                       }
+                               });
+                       });
+               },
+
+               /**
+                * Uninstall a new app based on app id.
+                * @method uninstallApp
+                * @param id {string} Contains app id.
+                **/
+               uninstallApp: function (id) {
+                       "use strict";
+                       console.log('UNINSTALL APP... ' + id);
+                       StoreLibrary.displayInstallProgress(false, 0);
+                       packageRepository.uninstall(id, function (jsonObject) {
+                               var instError = jsonObject.error;
+                               if (!!instError) {
+                                       packageRepository.getApplicationDetail(id, function (appDetail) {
+                                               appDetail[0].installed = true;
+                                               StoreLibrary.installResult(instError, false, appDetail[0]);
+                                       });
+                               } else {
+                                       packageRepository.getApplicationDetail(id, function (appDetail) {
+                                               appDetail[0].installed = false;
+                                               StoreLibrary.installResult(instError, false, appDetail[0]);
+                                       });
+                               }
+                       });
+               },
+
+               /**
+                * Called as callback after installing or uninstalling application.
+                * @method installResult
+                * @param error {bool} Error indicator.
+                * @param install {bool} Indicates if app was installed (true) or uninstalled (false).
+                * @param app {object} Object of app which was installed/uninstalled.
+                **/
+               installResult: function (error, install, app) {
+                       "use strict";
+                       var instLabel1 = 'INSTALLATION';
+                       var instLabel2 = 'INSTALLED';
+                       if (install === false) {
+                               instLabel1 = 'UNINSTALLATION';
+                               instLabel2 = 'UNINSTALLED';
+                       }
+                       if (!!error) {
+                               $('#installText').html(instLabel1 + ' FAILED');
+                       } else {
+                               $('#installText').html(instLabel2 + ' SUCCESSFULLY');
+                               $('#installBar').css({
+                                       width: '100%'
+                               });
+                       }
+                       setTimeout(function () {
+                               /* jshint camelcase: false */
+                               if (app.category_id === "system") {
+                               /* jshint camelcase: true */
+                                       var appToRemoveIndex = AppModel.indexOf(app);
+                                       if (appToRemoveIndex >= 0) {
+                                               AppModel.splice(appToRemoveIndex, 1);
+                                       }
+                                       /* jshint camelcase: false */
+                                       StoreLibrary.showAppsByCategoryId(app.category_id);
+                                       /* jshint camelcase: true */
+                                       $('#storeLibrary').library('closeSubpanel');
+                               } else {
+                                       StoreLibrary.renderAppDetailView(app);
+                                       StoreLibrary.refreshPopularApps(app);
+                               }
+                       }, 3000);
+               },
+
+               /**
+                * Displays progress of installation or uninstallation.
+                * @method displayInstallProgress
+                * @param install {bool} Indicates if app was installed (true) or uninstalled (false).
+                **/
+               displayInstallProgress: function (install, percent) {
+                       "use strict";
+                       if (install === false) {
+                               $('#installText').html('UNINSTALLING...');
+                       }
+                       $('.textPanel').css('display', 'inline-block');
+                       $('.installButtons').css('display', 'none');
+                       $('#installBar').css({
+                               width: percent + '%'
+                       });
+
+               },
+
+               /**
+                * Updates the model object and rerenders popular apps view
+                * @method refreshPopularApps
+                * @param app updated application object
+                **/
+               refreshPopularApps: function (app) {
+                       "use strict";
+                       for (var i in popularAppsModel) {
+                               if (popularAppsModel[i].id === app.id) {
+                                       popularAppsModel[i].installed = app.installed;
+                                       popularController.fillView(popularAppsModel);
+                                       break;
+                               }
+                       }
+               }
+       };
\ No newline at end of file
diff --git a/packaging/html5-ui-appmanager.changes b/packaging/html5-ui-appmanager.changes
new file mode 100644 (file)
index 0000000..81132a1
--- /dev/null
@@ -0,0 +1,4 @@
+* Thu Mar 06 2014 brianjjones <brian.j.jones@intel.com> c8620ac
+- Initial commit of the Appmanager app
+
+
diff --git a/packaging/html5-ui-appmanager.spec b/packaging/html5-ui-appmanager.spec
new file mode 100644 (file)
index 0000000..d23ea34
--- /dev/null
@@ -0,0 +1,36 @@
+Name:       html5_UI_Appmanager
+Summary:    A proof of concept pure html5 UI
+Version:    0.0.1
+Release:    1
+Group:      Applications/System
+License:    Apache 2.0
+URL:        http://www.tizen.org
+Source0:    %{name}-%{version}.tar.bz2
+BuildRequires:  zip
+BuildRequires:  html5_UI_Common
+Requires:   wrt-installer
+Requires:   wrt-plugins-ivi
+
+%description
+A proof of concept pure html5 UI
+
+%prep
+%setup -q -n %{name}-%{version}
+
+%build
+
+make wgtPkg
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+%post
+    wrt-installer -i /opt/usr/apps/.preinstallWidgets/html5UIAppmanager.wgt;
+
+%postun
+    wrt-installer -un html5POC03.Appmanager
+
+%files
+%defattr(-,root,root,-)
+/opt/usr/apps/.preinstallWidgets/html5UIAppmanager.wgt
diff --git a/templates/carouselDelegate.html b/templates/carouselDelegate.html
new file mode 100644 (file)
index 0000000..5e7caf9
--- /dev/null
@@ -0,0 +1,12 @@
+<li>
+<!-- <li> -->
+       <div id="item_{{:index}}" class="carouselItem" ontouchend="triggerTouchEnd('{{:category_id}}','{{:id}}');">
+               <img class="carouselImage" src='{{:iconUrl}}' alt="">
+               <div class="albumCarouselDescription">
+                       <div
+                               class="albumCarouselDescriptionText fontColorNormal fontSizeLarge fontWeightBold">{{:name}}
+                       </div>
+               </div>
+       </div>
+</li>
+
diff --git a/templates/detailApplicationContainer.html b/templates/detailApplicationContainer.html
new file mode 100644 (file)
index 0000000..9ec59b4
--- /dev/null
@@ -0,0 +1,68 @@
+<div class="appDetail">
+       <div class="iconElement">
+               <div class="detailIcon">
+                       <img src="{{:iconUrl}}"
+                               style="width: 100%; height: 100%;">
+               </div>
+               <div class="ratingTableDetail">
+                       <div
+                               class="ratingIcons {{if rating>0}}iconStarActive{{else}}iconStarInActive{{/if}}"></div>
+                       <div
+                               class="ratingIcons {{if rating>1}}iconStarActive{{else}}iconStarInActive{{/if}}"></div>
+                       <div
+                               class="ratingIcons {{if rating>2}}iconStarActive{{else}}iconStarInActive{{/if}}"></div>
+                       <div
+                               class="ratingIcons {{if rating>3}}iconStarActive{{else}}iconStarInActive{{/if}}"></div>
+                       <div
+                               class="ratingIcons {{if rating>4}}iconStarActive{{else}}iconStarInActive{{/if}}"></div>
+               </div>
+       </div>
+       <div class="priceElement">
+
+               <div class="priceTitle fontSizeLarge fontColorNormal fontWeightBold">PRICE:</div>
+               <div class="priceAmount  fontSizeLarge fontWeightBold fontColorTheme">{{if
+                       price ==0 }}FREE{{else}}{{:price}} EUR{{/if}}</div>
+                       <div id="installInfo" class="textPanel">
+                               <div id="installText" class="installText fontColorNormal fontSizeLarge fontWeightBold">INSTALLING...</div>
+                               <div id="installBar" class="installBarClass progressBar borderColorTheme"></div>
+                       </div>
+                       {{if category_id != "user_theme" && category_id != "system" && name.toLowerCase() != "store" && name.toLowerCase() != "home screen"}}
+                       <div class="installButtons borderColorDark bgColorDarkTransparent">
+                               {{if installed !=true}}
+
+                               <div onclick='StoreLibrary.installApp("{{:id}}");'>
+                                       <div class="btnText fontColorNormal fontSizeLarge fontWeightBold">INSTALL</div>
+                               </div>
+
+                               {{/if}}
+                               {{if installed ==true}}
+                               <div onclick='StoreLibrary.uninstallApp("{{:id}}");'>
+                                       <div class="btnText fontColorNormal fontSizeLarge fontWeightBold">UNINSTALL</div>
+                               </div>
+                               {{/if}}
+                       </div>
+                       {{/if}}
+               </div>
+
+       </div>
+       <div class="infoWrapper">
+               <div class="descriptionElement">
+                       <div class="fontSizeLarge fontColorNormal fontWeightBold">DESCRIPTION:</div>
+                       <div class="detailDescription fontSizeSmall fontColorDimmed fontWeightBold ">{{:description}}</div>
+               </div>
+               <div class="versionElement">
+                       <div class="versionTitle fontSizeLarge fontColorNormal fontWeightBold">VERSION:</div>
+                       <div class="versionNumber fontSizeLarge fontColorDimmed fontWeightBold">{{:version}}</div>
+               </div>
+
+               <div class="imagesElement">
+                       <div class="fontSizeLarge fontColorNormal fontWeightBold">SCREENSHOTS:</div>
+
+                       {{foreach imageObjects}}
+                               <div class="imageElement" style="background: url('{{:url}}'); background-repeat:no-repeat; color: white; ">
+                               </div>
+                               {{/foreach}}
+
+               </div>
+       </div>
+</div>
\ No newline at end of file
diff --git a/templates/popularAppsContainer.html b/templates/popularAppsContainer.html
new file mode 100644 (file)
index 0000000..b3c0c9b
--- /dev/null
@@ -0,0 +1,33 @@
+<div id="{{:path}}"
+       class="popularItem fontSizeMedium fontWeightBold settingsItemBorder"
+       onClick="StoreLibrary.setAppDetailAndCategory('{{:category_id}}','{{:id}}')">
+       <div class="detailPopIcon storeAppInfoImage">
+               <img src="{{:iconUrl}}"
+                       style="width: 100%; height: 100%;">
+       </div>
+
+       <div class="storePopAppInfo">
+               <div
+                       class="storePopAppTitle fontSizeMedium fontWeightBold fontColorNormal">
+                       {{:name}}</div>
+               <div
+                       class="storePopAppMoreInfo fontSizeXSmall fontWeightBold fontColorDark">{{if
+                       installed==true}}Installed{{else if price ==0
+                       }}Free{{else}}{{:price}} Eur{{/if}}</div>
+               <div class="storePopAppMoreInfo">
+                       <div class="ratingPopTable">
+                               <div
+                                       class="ratingIcons {{if rating>0}}iconStarActive{{else}}iconStarInActive{{/if}}"></div>
+                               <div
+                                       class="ratingIcons {{if rating>1}}iconStarActive{{else}}iconStarInActive{{/if}}"></div>
+                               <div
+                                       class="ratingIcons {{if rating>2}}iconStarActive{{else}}iconStarInActive{{/if}}"></div>
+                               <div
+                                       class="ratingIcons {{if rating>3}}iconStarActive{{else}}iconStarInActive{{/if}}"></div>
+                               <div
+                                       class="ratingIcons {{if rating>4}}iconStarActive{{else}}iconStarInActive{{/if}}"></div>
+                       </div>
+               </div>
+       </div>
+       <div class="transparent"></div>
+</div>
diff --git a/templates/storeLibraryAppsDelegate.html b/templates/storeLibraryAppsDelegate.html
new file mode 100644 (file)
index 0000000..9357063
--- /dev/null
@@ -0,0 +1,24 @@
+<div class="appElement boxShadow4 borderColorTheme"
+       onClick='StoreLibrary.openAppDetail("{{:id}}");'>
+       <div class="appImage">
+               <img src="{{:iconUrl}}" />
+       </div>
+       <div class="appInfoBox textBgColorNormalTransparent">
+               <div class="appTitle fontSizeLarge fontWeightBold fontColorNormal">{{:name}}</div>
+               <div class="appSubtitle fontSizeXSmall fontWeightBold fontColorTheme">{{if
+                       installed==true}}Installed{{else if price ==0
+                       }}Free{{else}}{{:price}} Eur{{/if}}</div>
+               <div class="appRating">
+                       <div
+                               class="ratingIcons {{if rating>0}}iconStarActive{{else}}iconStarInActive{{/if}}"></div>
+                       <div
+                               class="ratingIcons {{if rating>1}}iconStarActive{{else}}iconStarInActive{{/if}}"></div>
+                       <div
+                               class="ratingIcons {{if rating>2}}iconStarActive{{else}}iconStarInActive{{/if}}"></div>
+                       <div
+                               class="ratingIcons {{if rating>3}}iconStarActive{{else}}iconStarInActive{{/if}}"></div>
+                       <div
+                               class="ratingIcons {{if rating>4}}iconStarActive{{else}}iconStarInActive{{/if}}"></div>
+               </div>
+       </div>
+</div>
\ No newline at end of file