1 /*global Bootstrap, StoreLibrary, PackageRepository, packageRepository, template, Speech, AppModel, ThemeKeyColor, _applicationDetail, _categories, popularAppsModel, popularController */
4 * Store application provides access to [remote package server](../../package_server/index.html) with installable WGT packages. Packages are grouped
5 * into package categories like *System*, *Utilities* or *Media*. Package server takes following information from WGT
6 * package `config.xml` file:
10 * * application version
12 * Package server provides additional metadata processed by Store application:
14 * * application rating
16 * * application description
17 * * price for application
18 * * application screenshots
19 * * flag assigning application into Promoted and/or Popular groups
21 * Store application uses {{#crossLink "PackageRepository"}}{{/crossLink}} class to download, install and uninstall applications.
23 * Package server address and credentials can be configured by updating {{#crossLink "Store/Config:property"}}{{/crossLink}} property.
24 * Please refer to [Package server documenation](../../package_server/index.html) for more details.
26 * Hover and click on elements in images below to navigate to components of Store application.
28 * <img id="Image-Maps_1201312180420487" src="../assets/img/store.png" usemap="#Image-Maps_1201312180420487" border="0" width="649" height="1152" alt="" />
29 * <map id="_Image-Maps_1201312180420487" name="Image-Maps_1201312180420487">
30 * <area shape="rect" coords="0,0,573,78" href="../classes/TopBarIcons.html" alt="top bar icons" title="Top bar icons" />
31 * <area shape="rect" coords="0,77,644,132" href="../classes/Clock.html" alt="clock" title="Clock" />
32 * <area shape="rect" coords="0,994,644,1147" href="../classes/BottomPanel.html" alt="bottom panel" title="Bottom panel" />
33 * <area shape="rect" coords="573,1,644,76" href="../modules/Settings.html" alt="Settings" title="Settings" />
34 * <area shape="rect" coords="497,135,648,178" alt="Store Library" title="Store Library" target="_self" href="../classes/StoreLibrary.html" >
35 * <area shape="rect" coords="0,476,648,1001" alt="Popular applications" title="Popular applications" target="_self" href="../classes/popularController.html" >
36 * <area shape="rect" coords="1,188,648,457" alt="Promoted applications" title="Promoted applications" target="_self" href="../classes/Store.html#property_promotedApplicationsModel" >
39 * @module StoreApplication
40 * @main StoreApplication
47 * Configuration object holding url and authentication access to remote store server
52 httpPrefix: "http://localhost:80",
55 defaultIcon: "css/car/images/default_icon.png"
59 * Reference to instance of object holding data about promoted applications
60 * @property promotedApplicationsModel {Object}
62 var promotedApplicationsModel;
65 * Object handling speech commands to install or uninstall application
66 * @property speechObj {Object}
71 * Object holding data about apps installed on the device
72 * @property installedApps {Object}
79 * Method fills Promoted Applications carousel with data and rendering
80 * @method setupCarousel
83 function setupCarousel() {
85 template.compile(promotedApplicationsModel, "templates/carouselDelegate.html", "#carousel_wrap", function() {
86 $('#carousel_wrap').carouFredSel({
101 $('.carouselItem').on("touchstart", function (event) {
105 $('.carouselItem').on("touchmove", function (event) {
112 * Function invoked after `touchend` event on the carousel item
113 * @method triggerTouchEnd
114 * @param cat {String} Category
115 * @param app {String} Application
118 function triggerTouchEnd(cat, app) {
120 if (moved === false) {
121 StoreLibrary.setAppDetailAndCategory(cat, app);
126 * Adds http prefix to application icons' urls for apps from the store
127 * @method enhanceModelUrls
130 function enhanceModelUrls(model) {
132 $.each(model, function (itemIndex, item) {
133 if (item.iconUrl.indexOf(Config.httpPrefix) < 0) {
134 item.iconUrl = Config.httpPrefix + item.iconUrl;
140 * Looks for application icon file and provides a path to default one if not found
144 function getAppIcon(appIconPath, callback) {
147 tizen.filesystem.resolve(appIconPath, function (iconFile) {
148 callback(iconFile.fullPath);
149 }, function (error) {
150 callback(Config.defaultIcon);
153 console.log("EXCEPTION when trying to find icon file: " + ex.message);
158 * Applies selected theme to application icons
159 * @method setThemeImageColor
162 function setThemeImageColor() {
165 $('body').find('img').each(function() {
167 imageSource = $(this).attr('src');
169 if (typeof(imageSource) !== 'undefined' && $(this.parentElement).hasClass('themeImage') === false &&
170 (imageSource.indexOf(Config.httpPrefix) >= 0 || imageSource.indexOf('base64') >= 0)) {
171 var img = new Image();
172 var ctx = document.createElement('canvas').getContext('2d');
173 img.onload = function () {
174 var w = ctx.canvas.width = img.width;
175 var h = ctx.canvas.height = img.height;
176 ctx.fillStyle = ThemeKeyColor;
177 ctx.fillRect(0, 0, w, h);
178 ctx.globalCompositeOperation = 'destination-in';
179 ctx.drawImage(img, 0, 0);
181 $(self).attr('src', ctx.canvas.toDataURL());
182 $(self).hide(0, function() { $(self).show();});
185 img.src = imageSource;
191 * Sets up voice recognition listeners for un/installing applications
192 * @method setupSpeechRecognition
195 function setupSpeechRecognition() {
197 console.log("Store setupSpeechRecognition");
198 Speech.addVoiceRecognitionListener({
199 onapplicationinstall : function() {
200 console.log("Speech application install invoked");
201 if (_applicationDetail.id !== undefined && $('#storeLibrary').library('isVisible') &&
202 (!_applicationDetail.installed || _applicationDetail.installed === false)) {
203 StoreLibrary.installApp(_applicationDetail.id);
206 onapplicationuninstall : function() {
207 console.log("Speech application uninstall invoked");
208 if (_applicationDetail.id !== undefined && $('#storeLibrary').library('isVisible') && _applicationDetail.installed === true) {
209 StoreLibrary.uninstallApp(_applicationDetail.id);
217 * Applies Base64 conversion to icon urls in the model
218 * @method setThemeIconColorBeforeRender
221 function setThemeIconColorBeforeRender(model) {
224 $.each(model, function (itemIndex, item) {
225 if (item.iconUrl.indexOf(Config.httpPrefix) >= 0 || item.iconUrl.indexOf('base64') >= 0 || item.iconUrl.indexOf('intelPoc') >= 0) {
226 var img = new Image();
227 var aIcon = item.iconUrl;
228 var ctx = document.createElement('canvas').getContext('2d');
229 img.onload = function () {
230 var w = ctx.canvas.width = img.width;
231 var h = ctx.canvas.height = img.height;
232 ctx.fillStyle = ThemeKeyColor;
233 ctx.fillRect(0, 0, w, h);
234 ctx.globalCompositeOperation = 'destination-in';
235 ctx.drawImage(img, 0, 0);
236 item.iconUrl = ctx.canvas.toDataURL();
239 img.src = item.iconUrl;
246 * Loads store data and builds the page based on the data
253 packageRepository = new PackageRepository();
254 packageRepository.availableApplications(function (appData) {
256 enhanceModelUrls(AppModel);
257 setThemeIconColorBeforeRender(AppModel);
259 promotedApplicationsModel = packageRepository.getPromotedApplications();
260 setTimeout(function() {
263 packageRepository.getAppsInfo(function (appsInfo) {
264 installedApps = appsInfo;
265 var appsNotInStore = [];
266 var foundInStore = false;
267 var appsLength = appsInfo.length;
268 var appModelLength = AppModel.length;
270 var processApplication = function(i) {
271 for (var j = 0; j < appModelLength; j++) {
272 if (appsInfo[i].name === AppModel[j].name) {
274 AppModel[j].installed = true;
277 } else if (!AppModel[j].installed) {
278 AppModel[j].installed = false;
281 if (foundInStore === false &&
282 (appsInfo[i].name.toLowerCase() !== "store" && appsInfo[i].name.toLowerCase() !== "homescreen" && appsInfo[i].name.toLowerCase() !== "home screen")) {
283 var appNotInStore = {};
284 appNotInStore.id = appsInfo[i].id;
285 appNotInStore.name = appsInfo[i].name;
286 appNotInStore.version = 0;
287 appNotInStore.silentInstall = false;
288 /* jshint camelcase: false */
289 appNotInStore.category_id = "system";
290 /* jshint camelcase: true */
291 appNotInStore.price = "0";
292 appNotInStore.rating = "0";
293 appNotInStore.description = "";
294 appNotInStore.isPromoted = false;
295 appNotInStore.isPopular = false;
296 appNotInStore.screenshots = [];
297 appNotInStore.downloadUrl = "";
298 getAppIcon(appsInfo[i].iconPath, function(resolvedPath) {
299 appNotInStore.iconUrl = resolvedPath;
301 appNotInStore.installed = true;
302 AppModel.push(appNotInStore);
304 foundInStore = false;
307 for (var i = 0; i < appsLength; i++) {
308 processApplication(i);
310 popularAppsModel = packageRepository.getPopularApplications();
311 popularController.addHeader();
312 popularController.fillView(popularAppsModel);
317 packageRepository.getAppsInfo(function (appsInfo) {
318 installedApps = appsInfo;
319 var appsNotInStore = [];
320 var appsLength = appsInfo.length;
322 var processApplication = function(i) {
323 if (appsInfo[i].name.toLowerCase() !== "store" && appsInfo[i].name.toLowerCase() !== "homescreen" && appsInfo[i].name.toLowerCase() !== "home screen") {
324 var appNotInStore = {};
325 appNotInStore.id = appsInfo[i].id;
326 appNotInStore.name = appsInfo[i].name;
327 appNotInStore.version = 0;
328 appNotInStore.silentInstall = false;
329 /* jshint camelcase: false */
330 appNotInStore.category_id = "system";
331 /* jshint camelcase: true */
332 appNotInStore.price = "0";
333 appNotInStore.rating = "0";
334 appNotInStore.description = "";
335 appNotInStore.isPromoted = false;
336 appNotInStore.isPopular = false;
337 appNotInStore.screenshots = [];
338 appNotInStore.downloadUrl = "";
339 getAppIcon(appsInfo[i].iconPath, function(resolvedPath) {
340 appNotInStore.iconUrl = resolvedPath;
342 appNotInStore.installed = true;
343 AppModel.push(appNotInStore);
347 for (var i = 0; i < appsLength; i++) {
348 processApplication(i);
352 packageRepository.getCategories(function (catData) {
353 _categories = catData;
359 * Initialize plugins and register events for Store app.
363 var init = function () {
365 bootstrap = new Bootstrap(function (status) {
366 $("#topBarIcons").topBarIconsPlugin('init', 'store');
367 $("#clockElement").ClockPlugin('init', 5);
368 $("#clockElement").ClockPlugin('startTimer');
369 $('#bottomPanel').bottomPanel('init');
373 setupSpeechRecognition();
375 console.log("Store: Speech Recognition not running, voice control will be unavailable");
378 bootstrap.themeEngine.addStatusListener(function (eData) {
379 setThemeImageColor();
384 $(document).ready(init);
387 * Opens store library after it's initialization or initialize library if it's not.
388 * @method openStoreLibrary
391 function openStoreLibrary() {
393 if (!StoreLibrary.initialized) {
398 setThemeIconColorBeforeRender(AppModel);