In this post I’m going to talk about WinJS.xhr that makes an XMLHttpRequest as a Promise, and how to save and load images and from your local storage.
What is a Promise?
Promise is a way for Asynchronous Programming in JavaScript, Avoiding synchronous execution in single-threaded languages like JavaScript is necessary in order to create apps that are responsive and high performing. Windows Library for JavaScript provides a consistent and predictable mechanism called a Promise that simplifies asynchronous programming.
A promise implements a method for registering callbacks for state change notifications, named then.
Instead of writing a single get action that force your code to wait for response.
var result = myWebService.get(http://www.contoso.com);
Or if you think about writing more code like this:
myWebService.addEventListener('completed', function(result)
{ /* do something */});
myWebService.get(http://www.contoso.com);
You should use WinJS Promise to create Asynchronous action using then method.
myWebService.get("http://www.contoso.com")
.then(
function (result) { /* do something */ },
function (error) { /* handle error */ },
function (progress) { /* report progress */ }
);
For this post I wrote a simple JavaScript Metro App that downloads web images and saves them to local storage and a gallery that display all images under App local storage.

Download Demo Project
Step 1: Create a new Windows 8 JavaScript Metro App
First create empty JavaScript project and add new js file called - imgDownloader
We will use this file to download and locate the local images.
Step 2: Asynchronous Image Download
We need to download the image asynchronously, then save the stream we get to a local file.
The first thing is the folder location, Each application has three available folders under - Windows.Storage.ApplicationData.current - to save user data:
Now using WinJS.xhr we enter the image url and define the response type as “Blob”, again this is an Asynchronous method and we can use THEN in order to register a callback that will called when the request is finished.
Once we get the result from Xhr we use the folder object to create new file with the name the user passed, again once the new file was created we open this file for editing and get the stream.
Code Flow:
- Using Ajax get the image = WinJS.xhr({ url: imgUrl, responseType: "blob" }).then
- After we received the image we create a new file = folder.createFileAsync(imgName,..).then
- Open our file for edit = file.openAsync(Windows.Storage.FileAccessMode.readWrite).then
- Copy the image content = copyAsync(blob.msDetachStream(), stream).then
- Close stream = stream.flushAsync().then
function download(imgUrl, imgName) {
return WinJS.xhr({ url: imgUrl, responseType: "blob" }).then(function
(result) {
var blob = result.response;
return folder.createFileAsync(imgName, Windows.Storage.
CreationCollisionOption.replaceExisting).then(function (file){
// Open the returned file in order to copy the data
return file.openAsync(Windows.Storage.FileAccessMode.readWrite).
then(function (stream) {
return Windows.Storage.Streams.RandomAccessStream.copyAsync
(blob.msDetachStream(), stream).then(function () {
// Copy the stream from the blob to the File stream
return stream.flushAsync().then(function () {
stream.close();
});
});
});
});
}, function (e) {
var msg = new Windows.UI.Popups.MessageDialog(e.message);
msg.showAsync();
});
}
Step 3: Locate Local File
After the download has completed we want to locate the local file we just saved and return the file object, using the file object we can get the file type ,creation date and more.
Using Windows.Storage.ApplicationData.current.local.getFileAsync (or Temp, Roaming") , we can search for a specific file under that folder, if the file is found in the local folder we return the file, else return null. (File Not Found)
function fileExists(fileName) {
return folder.getFileAsync(fileName).then(function (file) {
return file;
}, function (err) {
return null;
});
}
Step 4: Add imgDownloader Namespace
In order to call these methods from Default.js we need to add the namespace using the following methods:
WinJS.Namespace.define('imgDownloader', {
download: download,
fileExists: fileExists
});
Step 5: Add page functionality
Now, when the user writes the image Uri and clicks the “Get Image” button we’ll call the getImage function.
app.onactivated = function (eventObject) {
if (eventObject.detail.kind === Windows.ApplicationModel.Activation.
ActivationKind.launch) {
// TODO: Initialize your application here.
WinJS.UI.processAll();
document.querySelector("#btnDownloadImg").addEventListener("click"
, function () {
getImage();
});
};
using querySelector we’ll take the Uri and File Name values, using the imgDownloader namespace and call Download function using the user supplied values. Because the download function has a callback value we can use the then method.
After the download operation has completed we call the fileExists function to get the local file object.
After getting the Image we demonstrate two options for displaying the image:
- ms-appdata:// protocol – Path To Local Folder
- URL.createObjectURL – Converting the file to blob, you can choose to create permanent blob so you can use it again.
function getImage() {
var imgUrl = document.querySelector("#txtUrl").value;
var fileName = document.querySelector("#txtFileName").value;
imgDownloader.download(imgUrl,
fileName).then(function () {
imgDownloader.fileExists(fileName).then(function (file) {
document.querySelector("#mainImg").src =
URL.createObjectURL(file, false);
// using the ms-appdata:// protocol.
document.querySelector("#mainImg2").src =
"ms-appdata:///Local/" + fileName;
document.querySelector("#filePath").textContent =
"Path: " + file.path;
document.querySelector("#fileType").textContent =
"Display Type: " + file.displayType;
document.querySelector("#dateCreated").textContent =
"Date Created: " + file.dateCreated;
drawGallery();
}, function (err) {
var msg = new Windows.UI.Popups.MessageDialog
("Picture Not Found");
msg.showAsync();
});
});
}
The last thing I want to do is locate all files under my local folder and display all image files.
Again we’ll use Windows.Storage.ApplicationData.current.localFolder but now let’s call “getItemsAsync” to get all files, then forEach over these items and make sure to handle only images, convert each file to a blob using createObjectURL and add the image to our gallery div.
function drawGallery() {
Windows.Storage.ApplicationData.current.localFolder.getItemsAsync().
then(function (items) {
var div = document.querySelector("#existingFiles");
div.textContent = "";
items.forEach(function (storageItem) {
if (storageItem.fileType === ".png" ||
storageItem.fileType === ".jpg" ||
storageItem.fileType === ".jpeg") {
var image = document.createElement("img");
image.style.width = "100px";
image.style.height = "100px";
image.src = URL.createObjectURL(storageItem);
image.alt = image.src;
div.appendChild(image);
}
}, function (e) {
var msg = new Windows.UI.Popups.MessageDialog(e);
msg.showAsync();
});
});
}
Download Demo Project
The feature I’m going to show you now isn’t part of JavaScript Metro app and you need to write some code and use Metro Touch Event called – MSPointerMove.
The feature I’m going to simulate is Pinch -
Download Demo Project
In this post I’ve created a Pinch functionality to increase and decrease zoom on specific item.
Step 1: Create JavaScript Metro Project
In the default.html page I’ve added a image (for our demo) and div element called output to display the touch output.
<body>
<div id="output"></div>
<div style="text-align: center; vertical-align: middle">
<img id="image" src="images/SelaLogo.png" style="zoom: 1;
width: 10%; height: 10%" />
</div>
</body>
Step 2: Register to Pointer Move Event
In the application activated event we get the image object from the UI and register to MSPointerMove event, this event will allow to receive Multi-touch pointers for more than one finger on the screen.
var img;
app.onactivated = function (eventObject) {
if (eventObject.detail.kind === Windows.ApplicationModel.Activation.
ActivationKind.launch) {
WinJS.UI.processAll();
img = document.querySelector("#image");
document.addEventListener("MSPointerMove", pointerMoveListener,
false);
}
};
Step 3: Distance Calculation Helpers
Now, before start handling the touch event I created a point class to obtain x, y, and the point id.
beside that a simple math calculation to get the distance between two points.
Distance Formula: Given the two points (x1, y1) and (x2, y2), the distance between these points is given by the formula:

function point(x, y, id) {
this.id = id;
this.x = x;
this.y = y;
}
var distance;
var basePoint1, basePoint2;
var outID;
function calcDistance(point1, point2) {
var x = Math.pow((point2.x - point1.x), 2);
var y = Math.pow((point2.y - point1.y), 2);
return Math.ceil(Math.sqrt(x + y));
}
Step 4: Calculate Distance Between Points
Now we ready to talk about the pointerMoveListener that gets the output from the MSPointerMove event, first we’ll use the getPointerList function to receive all recognize points on the screen, in my demo I want to handle only two points no less and no more.
If basePoint1,2 are undefined we define those objects for the current output and calculate the current distance between those points.
Once the event will raise again we call the cangeRatio method that will calculate the new distance between the points.
function pointerMoveListener(event) {
var pointerList = event.getPointerList(event.pointerId);
if (pointerList.length !== 2) return;
clearTimeout(outID);
outID = setTimeout(function () {
basePoint1 = basePoint2 = distance = undefined;
}, 100);
var currentPoint1 = new point(pointerList[0].clientX,
pointerList[0].clientY, pointerList[0].pointerId);
var currentPoint2 = new point(pointerList[1].clientX,
pointerList[1].clientY, pointerList[1].pointerId);
if (basePoint1 === undefined || basePoint2 === undefined ||
distance === undefined) {
basePoint1 = currentPoint1;
basePoint2 = currentPoint2;
distance = calcDistance(basePoint1, basePoint2);
}
else if (basePoint1.id === currentPoint1.id && basePoint2.id
=== currentPoint2.id ||
basePoint1.id === currentPoint2.id && basePoint2.id
=== currentPoint1.id) {
changeRatio(currentPoint1, currentPoint2);
}
}
Step 5: Change Ratio
Finally we have two distances, we just need to subtract both to find the delta between the first and the seconds, using this value I’ll increase or decrease the zoom attribute of the picture.
function changeRatio(p1, p2) {
var delta = 0;
var Seconddistance = calcDistance(p1, p2);
delta = (Seconddistance - distance) / 10;
document.querySelector("#output").textContent = "Point 1 - x: " + p1.x
+ " y: " + p1.y + " - " + "Point 2 - x: " + p2.x + " y: "
+ p2.y + " Delta: " + delta;
if (delta < 0) return;
if (delta > 10)
document.querySelector("#image").style.zoom = 10;
else
document.querySelector("#image").style.zoom = delta;
}
Download Demo Project
When creating an Win 8 Metro App you define splash screen with a single image, what if you want to do more… For example show some animations, load your resources before the application loads and more.
In this post I’ll show you how to create custom Splash Screen and control the load event so you know when the loading is over and your user can start using the application.
In my demo I’ll display some canvas animation and a timer (from 10s) until going to the main page.
Download Demo Project
Step 1: Create Navigation Metro App (JavaScript)
Add the following files:
- css\splash.css
- html\splash.html
- js\splash.js
- js\shadebob.js
Step 2: Define Startup Page
When you start your application the first thing the user will see is this:

There are two ways to remove it before we can set our custom splash screen:

- Because you can’t remove the splash image (it’s required), you can replace the image with your own empty image.
- The second option is to define the background color to white – this will show an white page with not clock.
After we remove the default splash image we want to define our Splash.html page as startup page as follow:

Step 3: Splash.html
Our splash page will contain a screen div and holder div.
The Screen div will contain a canvas that will display the animations.
The holder will contain the timer div that will display the remaining seconds from the timer.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Splash</title>
<!-- WinJS references -->
<link href="//Microsoft.WinJS.0.6/css/ui-dark.css" rel="stylesheet">
<script src="//Microsoft.WinJS.0.6/js/base.js"></script>
<script src="//Microsoft.WinJS.0.6/js/ui.js"></script>
<link href="/css/default.css" rel="stylesheet">
<link href="/css/splash.css" rel="stylesheet">
<script src="/js/splash.js"></script>
<script src="/js/shadebob.js"></script>
</head>
<body onload="resize()">
<div id="screen" style="display: none">
<canvas id="shadebob"></canvas>
</div>
<div id="holder">
This is my Custom Splash...
<h1 id="timer"></h1>
</div>
</body>
</html>
Step 4: Splash.css
The first thing we want is to place our custom splash in the center of the screen, so I’ve defined our holder div to absolute position, I’ve also centered the timer div.
#body {
position: absolute;
top: 0%;
left: 0%;
height: 100%;
width: 100%;
margin: 0px;
padding: 0px;
}
#holder {
position: absolute;
}
h1 {
font-size: 180px;
font-weight: 600;
}
#timer {
text-align: center;
}
Step 5: Splash.js
Because we changed the startup page we now need to set the splash.js to start the application, this allows us to hook the onactivated event from he application.
You can see the onactivated is fired you get the eventObject that has the splashScreen object inside detail.
From the splash object we take the imageLocation to get the x,y width and height of the original splash screen, the reason for doing that is to set our canvas and timer display in the center exactly where the splash should be, you don’t have to do that you can also calculate based on the document width and height.
After we obtain those values we set our holder div at the same position and size as the original splash screen, and we start the timer by calling setInterval to call countDown function.
The countDown function reduce 1 from the waitFor object until is reached to 0 and then he will redirect the page to homePage.
Now to the important part the dismissed event, as you can see I’ve register to the dismissed event from the splash screen so I can know when the splash has dismissed, in my demo this event is not relevant because my splash is dismissed the second I place the image on the screen but for you it can be loading event are something else.
(function () {
"use strict";
var waitFor = 10;
var app = WinJS.Application;
// This function responds to all application activations.
app.onactivated = function (eventObject) {
if (eventObject.detail.kind === Windows.ApplicationModel.Activation.
ActivationKind.launch) {
// Retrieve splash screen object
var splash = eventObject.detail.splashScreen;
// Retrieve the window coordinates of the splash screen image.
var coordinates = splash.imageLocation;
// Position the extended splash screen image in the same location
// as the splash screen image.
var holder = document.querySelector("#holder");
holder.style.left = coordinates.x + "px";
holder.style.top = coordinates.y + "px";
holder.style.height = coordinates.height + "px";
holder.style.width = coordinates.width + "px";
countDown();
setInterval(countDown, 1000);
// Register an event handler to be executed when the splash screen
// has been dismissed.
splash.addEventListener("dismissed", onSplashScreenDismissed,
false);
WinJS.UI.processAll();
}
};
app.start();
function countDown() {
waitFor = waitFor - 1;
if (waitFor <= 0) {
location.href = "/html/homePage.html";
}
else
document.querySelector("#timer").innerHTML = waitFor;
}
function onSplashScreenDismissed() {
// Include code to be executed when the system has transitioned
// from the splash screen to the application's first view.
}
})();
Download Demo Project
In my previous post I talked about App Settings, and now it’s time to talk about on of the most important things – Message Dialog. 
Download Demo Project
I’ve already saw people who wrote overlay div to show messages, just because they didn’t find how to add more buttons for the Message Dialog, so let me show you how-
Using the WinRT you can use the MessageDialog to popup a message to the user:
var msg = new Windows.UI.Popups.MessageDialog("Message Content",
"Your Message Title");
msg.showAsync();

For more complex dialog message that contains more then one button and can perform a different action based on user choice, you need to append new UICommand inside the MessageDialog object.
var msg = new Windows.UI.Popups.MessageDialog("Message Content",
"Your Message Title");
//Add buttons and set their callback functions
msg.commands.append(new Windows.UI.Popups.UICommand("OK",
function (command) {
writeMsg("You Clicked Ok");
}));
msg.commands.append(new Windows.UI.Popups.UICommand("Cancel",
function (command) {
writeMsg("You Clicked Cancel");
}));
msg.showAsync();
Now, there are some options for the message box, such as what should happened when the user click “ESC” or what should by the focus button?
beside that you probably want to create a function that will handle the user action instead of writing the function inside the button (the example above).
function showMsg()
{
var msg = new Windows.UI.Popups.MessageDialog("Message Content",
"Your Message Title");
//Add buttons and set their callback functions
msg.commands.append(new Windows.UI.Popups.UICommand("OK",
actionHandler, 0));
msg.commands.append(new Windows.UI.Popups.UICommand("Cancel",
actionHandler, 1));
msg.commands.append(new Windows.UI.Popups.UICommand("Ignore",
actionHandler, 2));
//Set the command to be invoked when a user presses ESC
msg.cancelCommandIndex = 1;
//Set the command that will be invoked by default
msg.defaultCommandIndex = 1;
msg.showAsync();
}
function actionHandler(command) {
writeMsg(command.label);
//Create action for each button.
switch (command.id) {
case 0:
break;
case 1:
break;
case 2:
break;
}
}

Download Demo Project
In my previous post I talked about Windows 8 JavaScript Metro App Basics, and some getting started with the new Metro Apps.
In order to help you get inside Windows 8 Metro Apps I’ll start writing on specific features in Metro Apps, starting from Settings.
As you build your Metro App you probably need to let the user to change some settings in the application, you don’t need to write any things special for that because Win8 comes with integrated Settings Pane allow you to add your own settings.
Download Demo Project
This is a very simple task, just define your settings as Pages, for example:
- Help Page
- About
- Dummy 1
- etc…
(Remember – Each page should have it’s own CSS and JS file, don’t be lazy!)
before we can get started you need to build new JavaScript application, the second part is getting inside the default.js file and register to onsettings event:
app.onactivated = function (eventObject) {
if (eventObject.detail.kind === Windows.ApplicationModel.
Activation.ActivationKind.launch) {
WinJS.UI.processAll();
// app.addEventListener("settings", function (e) { Load Settings });
// OR
app.onsettings = loadSettings;
}
};
I’ve created a new folder in my project called – “Settings”, inside I’ve create 2 pages – Help and About.

Now, you need to register those pages to the application onsettings event, and make sure to use the flyout control to populate those setting.
function loadSettings(e) {
e.detail.applicationcommands =
{
"Help":
{
title: "Help",
href: "/Settings/Help.html"
},
"About":
{
title: "About Me",
href: "/Settings/About.html"
}
};
WinJS.UI.SettingsFlyout.populateSettings(e);
}
Now, how can I see my settings? There are three ways to see them:
- User perform a proper gesture to open the setting page.
- Call the Setting Pane using SettingsPane
Windows.UI.ApplicationSettings.SettingsPane.show();
- Call specific page using SettingsFlyout (using id and path)
WinJS.UI.SettingsFlyout.showSettings("Help", "/Settings/Help.html");
document.querySelector("#btnShowSettings").addEventListener
("click", function (e) {
Windows.UI.ApplicationSettings.SettingsPane.show();
});
document.querySelector("#btnHelp").addEventListener("click", function () {
WinJS.UI.SettingsFlyout.showSettings("Help", "/Settings/Help.html");
});
document.querySelector("#btnAbout").addEventListener("click", function () {
WinJS.UI.SettingsFlyout.showSettings("About", "/Settings/About.html");
});

Download Demo Project