creating windows store java script apps
DESCRIPTION
TRANSCRIPT
![Page 2: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/2.jpg)
PROTOTYPE
Check official UX guidlines
![Page 3: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/3.jpg)
APP FLOWDo not forget about:
Form factorsApp contractsAll type of the tilesToast notificationsTouch firstAnimations
![Page 4: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/4.jpg)
ASYNC PATTERNSYou should understand how:
to compose asynchronous codeto use promisesto chain and group promisesto code promise chains to avoid nestingto wrap non-promise values in a promiseto handle errors in a promise
![Page 5: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/5.jpg)
PROMISESA promise is an object that represent a value that will be
available later.
Most API's are wraped to the promises.
All based on two methods .then and .done.
![Page 6: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/6.jpg)
PROMISESA promise is an object that represent a value that will be
available later.Hilo\Hilo\imageQueryBuilder.js
if (this.settings.bindable) {// Create Hilo.Picture objects instead of returning StorageFile objects queryPromise = queryPromise.then(this._createViewModels);}
![Page 7: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/7.jpg)
PROMISE CHAINvar whenImagesForTileRetrieved = queryBuilder.build(picturesLibrary).execute();whenImagesForTileRetrieved .then(Hilo.Tiles.createTileFriendlyImages) .then(this.getLocalImagePaths) .then(Hilo.Tiles.createTileUpdates) .then(queueTileUpdates);
![Page 8: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/8.jpg)
PROMISE CHAIN
![Page 9: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/9.jpg)
BIND FUNCTIONDefine funtion environment with .bind
Hilo\Hilo\Tiles\TileUpdater.js
var queueTileUpdates = this.queueTileUpdates.bind(this);
queueTileUpdates: function (notifications) { var self = this; notifications.forEach(function (notification) { self.tileUpdater.update(notification); });},
![Page 10: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/10.jpg)
BIND FUNCTIONBind can receive additional parameters.
Hilo\Hilo\Tiles\createTileFriendlyImages.js
function createTileFriendlyImages(files) { var localFolder = applicationData.current.localFolder;
var copyThumbnailsToFolder = copyFilesToFolder.bind(null, files);
var whenFolderCreated = localFolder.createFolderAsync(thumbnailFolderName, creationCollisionOption.replaceExisting);
return whenFolderCreated .then(copyThumbnailsToFolder);}
![Page 11: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/11.jpg)
GROUPING A PROMISEWhen you have non-sequential, asynchronous operations
that must all complete before you can continue a task, you canuse the WinJS.Promise.join
var whenFileIsOpen = targetFile.openAsync(fileAccessMode.readWrite);var whenThumbailIsReady = sourceFile.getThumbnailAsync(thumbnailMode.singleItem);var whenEverythingIsReady = WinJS.Promise.join({ opened: whenFileIsOpen, ready: whenThumbailIsReady });
![Page 12: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/12.jpg)
HANDLING ERRORSUse .done at the end of method chain.
It doesn't return another promise and throw unhandledexpetions.
![Page 13: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/13.jpg)
HANDLING ERRORSHilo\Hilo\crop\croppedImageWriter.js
var decoderPromise = getOrientation.then(function (retrievedProps) { exifOrientation = (retrievedProps.size !== 0) ? retrievedProps["System.Photo.Orientation"] : photoOrientation.normal;
}, function (error) { switch (error.number) { case Hilo.ImageWriter.WINCODEC_ERR_UNSUPPORTEDOPERATION: case Hilo.ImageWriter.WINCODEC_ERR_PROPERTYNOTSUPPORTED: exifOrientation = photoOrientation.normal; break; default: throw error; }});
![Page 14: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/14.jpg)
MVPThe model represents the state and operations of businessobjects that your app manipulatesThe view (HTML and CSS) defines the structure, layout, andappearance of what the user sees on the screen. The viewmanages the controls on the page and forwards user eventsto a presenter classThe presenter contains the logic to respond to events,update the model and, in turn, manipulate the state of theview
![Page 15: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/15.jpg)
MVP - VIEWHilo\Hilo\hub\hub.html
<div id="hub-image-template" data-win-control="WinJS.Binding.Template"> <div data-win-bind="style.backgroundImage: url.backgroundUrl; alt: name; className: className" class="thumbnail"> </div></div>
![Page 16: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/16.jpg)
MVP - PRESENTER TESTHilo\Hilo.Specfications\specs\hub\ListViewPresenter.spec.js
describe("when snapped", function () { var el;
beforeEach(function () { var appView = {}; el = new Specs.WinControlStub(); el.winControl.addEventListener = function () { };
var listviewPresenter = new Hilo.Hub.ListViewPresenter(el, appView); listviewPresenter.setViewState(Windows.UI.ViewManagement.ApplicationViewState.snapped); });
it("the ListView should use a ListLayout", function () { expect(el.winControl.layout instanceof WinJS.UI.ListLayout).equal(true); });
});
![Page 17: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/17.jpg)
PRESENTERSEach presenter is responsible for a specific part of the page (a
control)
One page-specific presenter (the mediator) coordinates theother presenters (control-specific) and receives forwarded
events
![Page 18: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/18.jpg)
PRESENTERSHilo\Hilo\detail\detail.js
ready: function (element, options) {
var query = options.query; var queryDate = query.settings.monthAndYear; var pageTitle = Hilo.dateFormatter.getMonthFrom(queryDate) + " " + Hilo.dateFormatter.getYearFrom(queryDate); this.bindPageTitle(pageTitle);
var hiloAppBarEl = document.querySelector("#appbar"); var hiloAppBar = new Hilo.Controls.HiloAppBar.HiloAppBarPresenter(hiloAppBarEl, WinJS.Navigation, query);
var filmstripEl = document.querySelector("#filmstrip"); var flipviewEl = document.querySelector("#flipview");
var flipviewPresenter = new Hilo.Detail.FlipviewPresenter(flipviewEl); var filmstripPresenter = new Hilo.Detail.FilmstripPresenter(filmstripEl);
var detailPresenter = new Hilo.Detail.DetailPresenter(filmstripPresenter, flipviewPresenter, hiloAppBar, WinJS.Navigation); detailPresenter.addEventListener("pageSelected", function (args) { var itemIndex = args.detail.itemIndex; options.itemIndex = itemIndex; });
detailPresenter .start(options)
![Page 19: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/19.jpg)
SEPARATING RESPONSIBILITIESHilo\Hilo\hub\hub.html
Hilo\Hilo\controls\HiloAppBar\hiloAppBar.html
<section id="image-nav" data-win-control="WinJS.UI.HtmlControl" data-win-options="{uri: '/Hilo/controls/HiloAppBar/hiloAppBar.html'}"></section>
<div id="appbar" data-win-control="WinJS.UI.AppBar" data-win-options="{sticky: false}"> <button data-win-control="WinJS.UI.AppBarCommand" data-win-options="{id:'rotate', icon:'rotate', section: 'selection', disabled: true}" data-win-bind="{disabled: isCorrupt}" data-win-res="{winControl: {label:'RotateAppBarButton.Name'}}"> </button> <button data-win-control="WinJS.UI.AppBarCommand" data-win-options="{id:'crop', icon:'crop', section: 'selection', disabled: true}" data-win-bind="{disabled: isCorrupt}" data-win-res="{winControl: {label:'CropAppBarButton.Name'}}"> </button></div>
![Page 20: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/20.jpg)
UPDATING TILESHilo\default.js
if (currentState.kind === activation.ActivationKind.launch) {
if (currentState.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
// When the app is started, we want to update its tile // on the start screen. Since this API is not accessible // inside of Blend, we only invoke it when we are not in // design mode. if (!Windows.ApplicationModel.DesignMode.designModeEnabled) { var tileUpdater = new Hilo.Tiles.TileUpdater(); tileUpdater.update(); }}
![Page 21: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/21.jpg)
UPDATING TILESHilo\Hilo\Tiles\TileUpdater.js
update: function () { // Bind the function to a context, so that this will be resolved // when it is invoked in the promise. var queueTileUpdates = this.queueTileUpdates.bind(this);
// Build a query to get the number of images needed for the tiles. var queryBuilder = new Hilo.ImageQueryBuilder(); queryBuilder.count(numberOfImagesToRetrieve);
var whenImagesForTileRetrieved = queryBuilder.build(picturesLibrary).execute(); whenImagesForTileRetrieved .then(Hilo.Tiles.createTileFriendlyImages) .then(this.getLocalImagePaths) .then(Hilo.Tiles.createTileUpdates) .then(queueTileUpdates);}
![Page 22: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/22.jpg)
UPDATING TILESThe XML for a typical tile notification
<tile> <visual> <binding template="TileWideImageCollection"> <image id="1" src="ms-appdata:///local/thumbnails/thumbImage_0.jpg"/> <image id="2" src="ms-appdata:///local/thumbnails/thumbImage_1.jpg"/> <image id="3" src="ms-appdata:///local/thumbnails/thumbImage_2.jpg"/> <image id="4" src="ms-appdata:///local/thumbnails/thumbImage_3.jpg"/> <image id="5" src="ms-appdata:///local/thumbnails/thumbImage_4.jpg"/> </binding> <binding template="TileSquareImage"> <image id="1" src="ms-appdata:///local/thumbnails/thumbImage_0.jpg"/> </binding> </visual></tile>
![Page 23: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/23.jpg)
PAGE NAVIGATIONHilo\Default.html
Hilo\Hilo\hub\hubPresenter.js
<div id="contenthost" data-win-control="Hilo.PageControlNavigator" data-win-options="{home: '/Hilo/hub/hub.html'}"></div>
itemClicked: function (args) {
// Get the Hilo.Picture item that was bound to the invoked image, // and the item index from the list view control. var picture = args.detail.item.data;
// Build the query that can find this picture within it's month group. var options = this.buildQueryForPicture(picture);
// Navigate to the detail view, specifying the month query to // show, and the index of the individual item that was invoked. this.nav.navigate("/Hilo/detail/detail.html", options);},
![Page 24: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/24.jpg)
CREATING PAGESHilo\Hilo\hub\hub.js
Hilo.controls.pages.define("hub", {
ready: function (element, options) {
// Handle the app bar button clicks for showing and hiding the app bar. var appBarEl = document.querySelector("#appbar"); var hiloAppBar = new Hilo.Controls.HiloAppBar.HiloAppBarPresenter(appBarEl, WinJS.Navigation);
// Handle selecting and invoking (clicking) images. var listViewEl = document.querySelector("#picturesLibrary"); this.listViewPresenter = new Hilo.Hub.ListViewPresenter(listViewEl, Windows.UI.ViewManagement.ApplicationView);
// Coordinate the parts of the hub page. this.hubViewPresenter = new Hilo.Hub.HubViewPresenter( WinJS.Navigation, hiloAppBar, this.listViewPresenter, new Hilo.ImageQueryBuilder() );
this.hubViewPresenter .start(knownFolders.picturesLibrary) .then(function () { WinJS.Application.addEventListener("Hilo:ContentsChanged", Hilo.navigator.reload); });
![Page 25: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/25.jpg)
SUPPORTING DIFFERENT LAYOUTSHilo\Hilo\PageControlNavigator.js
function PageControlNavigator(element, options) {
// . . .
window.onresize = this._resized.bind(this);
// . . . }, _resized: function (args) { if (this.pageControl && this.pageControl.updateLayout) { this.pageControl.updateLayout.call(this.pageControl, this.pageElement, appView.value, this._lastViewstate); } this._lastViewstate = appView.value;},
![Page 26: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/26.jpg)
SUPPORTING DIFFERENT LAYOUTSHilo\Hilo\hub\hub.js
Hilo\Hilo\hub\listViewPresenter.js
updateLayout: function (element, viewState, lastViewState) { this.listViewPresenter.setViewState(viewState, lastViewState);},
setViewState: function (viewState) { this.lv.layout = this.selectLayout(viewState);},
selectLayout: function (viewState, lastViewState) {
if (lastViewState === viewState) { return; }
if (viewState === appViewState.snapped) { return new WinJS.UI.ListLayout(); } else { var layout = new WinJS.UI.GridLayout(); layout.groupInfo = function () { return listViewLayoutSettings; }; layout.maxRows = 3; return layout; }},
![Page 27: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/27.jpg)
DATA BINDINGTemplates for group items and group headers in the normal
view.Hilo\Hilo\month\month.html
<div id="monthItemTemplate" data-win-control="WinJS.Binding.Template"> <div data-win-bind="style.backgroundImage: url.backgroundUrl; className: className"></div></div>
<div id="monthGroupHeaderTemplate" data-win-control="WinJS.Binding.Template"> <a class="monthLink" href="#"><span data-win-bind="innerHTML: title"></span> (<span data-win-bind="innerText: count"></span>)</a></div>
<div id="monthSnappedTemplate" data-win-control="WinJS.Binding.Template"> <span data-win-bind="innerHTML: title"></span> (<span data-win-bind="innerText: count"></span>) <div data-win-bind="style.backgroundImage: backgroundUrl;" class="thumbnail"></div></div>
![Page 28: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/28.jpg)
DATA SOURCE TYPESWinJS.Binding.List - synchronous data source, in-memorydata source (an array), all its data must be available fordisplayStorageDataSource - built-in support for the Windows filesystemVirtualizedDataSource - custom implementation
![Page 29: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/29.jpg)
UXYou should provide both pointer and touch experience to your
user.
The pointer is an old school, touch control requires some skillsfrom developer.
![Page 30: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/30.jpg)
OBJECT ROTATIONHilo\Hilo\rotate\TouchProvider.js
function TouchProviderConstructor(inputElement) {
var recognizer = new Windows.UI.Input.GestureRecognizer(); recognizer.gestureSettings = Windows.UI.Input.GestureSettings.manipulationRotate; inputElement.addEventListener("MSPointerDown", function (evt) { var pp = evt.currentPoint; if (pp.pointerDevice.pointerDeviceType === pointerDeviceType.touch) { recognizer.processDownEvent(pp); } }, false);
inputElement.addEventListener("MSPointerMove", function (evt) { var pps = evt.intermediatePoints; if (pps[0] && pps[0].pointerDevice.pointerDeviceType === pointerDeviceType.touch) { recognizer.processMoveEvents(pps); } }, false);
inputElement.addEventListener("MSPointerUp", function (evt) { var pp = evt.currentPoint; if (pp.pointerDevice.pointerDeviceType === pointerDeviceType.touch) { recognizer.processUpEvent(pp); } }, false);
![Page 31: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/31.jpg)
PERFORMANCE TIPSLimit the start timeEmphasize responsivenessUse thumbnails for quick renderingRetrieve thumbnails when accessing itemsRelease media and stream resources when they're nolonger neededOptimize ListView performanceKeep DOM interactions to a minimumOptimize property accessUse independent animationsManage layout efficientlyStore state efficientlyKeep your app’s memory usage low when it's suspendedMinimize the amount of resources that your app uses
![Page 32: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/32.jpg)
IN DEPTH is a technique in which the system creates
bytecode for each JavaScript file once, rather than re-creatingthe bytecode each time it starts the app (30% improvment in
large apps).
Avoid synchronous API calls. Break proccessing operationsinto series of smaller operations.
Bytecode caching
![Page 33: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/33.jpg)
IN DEPTHUse Windows Runtime thumbnail APIs to cache and show
thumbnails.
Use DOM objects only to store information that directlyaffects how the DOM lays out or draws elements.
Certain types of animations are offloaded from the UI threadto GPU-accelerated system thread.
![Page 34: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/34.jpg)
IN DEPTHCombine API calls to reduce the number of layout passes.
Store session data in the sessionState in-memory object.
When your app begins the suspension process, it should freeany large objects that can be easily rebuilt when it resumes.
![Page 35: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/35.jpg)
WAYS TO TEST YOUR APPUnit testingIntegration testingUX testingSecurity testingLocalization testingAccessibility testingPerformance testingDevice testing
![Page 36: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/36.jpg)
MOCHAHilo.Specifications\specs\queries\imageQueryBuilder.spec.js
describe("Image Query Builder", function () {
var queryBuilder, storageFolder;
beforeEach(function (done) { queryBuilder = new Hilo.ImageQueryBuilder();
var whenFolder = Windows.Storage.ApplicationData.current.localFolder.getFolderAsync("Indexed"); whenFolder.then(function (folder) { storageFolder = folder; done(); }); });
![Page 37: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/37.jpg)
ASYNC TESTSHilo.Specifications\specs\queries\imageQueryBuilder.spec.js
describe("when executing a query that specifies the number of images to load", function () { var queryResult;
beforeEach(function () { queryResult = queryBuilder .count(1) .build(storageFolder) .execute(); });
it("should load the specified number of images", function (done) { queryResult.then(function (images) { expect(images.length).equals(1); done(); }).done(null, done); });});
![Page 38: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/38.jpg)
HANDLING EXCEPTIONSMocha test runner should intercepts this exception and
reports it as a test failure.
But WinJS is intercepting all promises errors.
.done function is never called, test will go into a wait state andMocha will time out (2 seconds), omitting the fail message.
![Page 39: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/39.jpg)
TEST APP STATES
Debug Location toolbar
![Page 40: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/40.jpg)
OTHER TESTS versions
methodology for threat modeling, Performance
Monitor :)Visual Studio
Pseudo-localizedSTRIDEPerformance Analyzer for HTML5 Apps
profilerWindows App Certification Kit
![Page 41: Creating windows store java script apps](https://reader034.vdocuments.net/reader034/viewer/2022050815/54852538b4af9f730d8b4d8a/html5/thumbnails/41.jpg)
DETAILS
source -
app docs -
http://bit.ly/win8js
http://bit.ly/pphilojs
@2j2e