Uploading image to the web service in WinJS application

Published November 27, 2013 1:07 pm

It is very likely that you need to have functionality to pick single or multiple image(s) and upload to your web service in your winjs windows store application. First, we will go through single image case. I have seen image pick & upload experience very often in facebook and google plus web client. Both of the web clients have ‘native’ experience for picking & uploading image(s). What I mean by native is that they have custom built experience that fits into their overall user experience. You will need to build a custom image select control that will do some or all of these:

  1. Launch picker – On click, launch windows file picker initialized to pick image file.
  2. Display preview – of the selected image. If no image is selected, display a placeholder image.
  3. Store file object – keep the file object picked by the user until it is submitted to the web service.
  4. View – you may need to show the preview of the image that already exists at the web service.
  5. delete command – context menu or other way to let user delete the uploaded image.
  6. download progress – related to (4), show progress while the image is downloading from the web service.
  7. show error – related to (4), show error if the image download fails.
  8. send command to service – to delete or upload the image
  9. show progress of command sent to the service
  10. reduce the size of the picked image before upload to the service.

The above is top down view of all the things related to uploading image in your winjs client. Building a custom control in winjs is a good topic on its own. We will not go over it in this post. This msdn blog post is a good start for building custom winjs control in your project.

Let’s get started.
html:

<img class="select-image" src="images/placeholder.png" />

js:

 
    var page = WinJS.UI.Pages.define('/pages/page1/page.html', 
    {
        ready: function onready(element, options)
        {
             ...
             var img = element.querySelector('.select-image');
             img.addEventListener('click', this.onclick.bind(this));
        }),
        onclick: function onclick()
        {
            var self = this;
            var img = this.element.querySelector('.select-image');
            this.pickSingleImage().then(function onpicksinglefile(file)
            {
                if (!file)
                    return;

                // set the blob to img.src for preview
                var imageUrl = URL.createObjectURL(file, { oneTimeOnly: true });
                img.src = imageUrl;
                // keep file object for upload later
                self.selectedFile = file;
            });
        },
        // launches file open picker initialized to pick an image
        pickSingleImage: function pickSingleImage()
        {
            // Verify that we are currently not snapped, or that we can unsnap to open the picker
            var currentState = Windows.UI.ViewManagement.ApplicationView.value;
            if (currentState === Windows.UI.ViewManagement.ApplicationViewState.snapped &&
                !Windows.UI.ViewManagement.ApplicationView.tryUnsnap())
            {
                // Fail silently if we can't unsnap
                return WinJS.Promise.timeout();
            }

            // Create the picker object and set options
            var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
            openPicker.viewMode = Windows.Storage.Pickers.PickerViewMode.thumbnail;
            openPicker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.picturesLibrary;
            // Users expect to have a filtered view of their folders depending on the scenario.
            // show file types that are accepted by your service 
            openPicker.fileTypeFilter.replaceAll([".gif", ".jpg", ".jpeg"]);

            // Open the picker for the user to pick a file
            return openPicker.pickSingleFileAsync();
        },
        // returns a promise that completes on upload of the file to the url.
        uploadBlob: function uploadBlob(url, file)
        {
            var data = MSApp.createFileFromStorageFile(file);
            var xhrOptions = {
                type: 'put', // this may be post if your web service expects http post
                url: url,    // url for the web service
                headers: {
                    'Content-Type': 'image/jpeg',
                    'Content-Length': data.size,
                    // TODO - add any other headers that service may expect
                },
                data: data,
            };

            return WinJS.xhr(xhrOptions);
        },

The code above is more or less self explanatory. Few notes:

  1. uploadBlob needs to be invoked by other function when image is to be uploaded.
  2. For uploading image to azure blob, upload code will look similar. you can refer this post.

There we are. Current code will allow to pick, preview and upload an image file to your web service.

It does not cover all the 1-10 things listed above yet. Did your app need it?

Backup and recovery of the azure table storage of the service

Published November 23, 2013 4:12 pm

It is very likely that you come across the problem – How do I ensure safety of my azure service from data-loss? Our service development is in progress. Before we onboard any customer for trial, we need to ensure that his data can’t be lost. In that context, I started with the problem definition as how do I backup & recover azure table storage? The service has maximum data in the table storage.

Very soon, I realized that data reliability of azure table storage is very high. It makes multiple local copies and if geo-rep is enabled, additional copies in another data center. it must be order of 99.9%. I tried to find documented link in msdn for this. Documented SLA of 99.9% is only for availability. Hence, do we need to do nothing for data loss? Actually, we need to handle the data loss protection in following cases:

  1. No data loss during service administration and maintenance. For example: do not execute delete table api in any administration task. This can only be done through very tight control and strict guidelines for the production environment.
  2. Data loss caused by end user in the application. Take for example: email application. user can accidentally delete a mail or folder.

After striking out (1) by following strict documented guidelines – problem can be redefined as – Backup and recovery of the application data of the service. This is typically very specific for the application. For example: email application has very rich experience built into the client application . End user can help himself/herself for any loss of data by recovery the item from ‘deleted items’ folder. He needs to approach the service administrator only if whole mailbox is lost, deleted items folder is deleted, etc. rarely. In our service case, accidental deletions will be rare and can be handled by user raising a request to the service administrator. Hence, service client (app) will not have rich recovery experience built in like it is required in an email client.

How do we backup application data in table storage? It will likely very specific for each service. In our case, current thinking is – to backup each user data separately – to a set of excel (xls) files – providing daily backup. Why excel?

  1. Excel not only provides excellent data access and manipulation, it is de facto standard.
  2. If user wishes to do manual recovery – it can be shared as is with user.
  3. The service needs to be seeded with user existing data. For that also, recovery flow can be used.

Regarding backing each user data separately, it partitions the problem of backing up table storage that will grow in size with number of service users.

Backup format is specific for the service. It is not likely relevant for other services. I need to think about building incremental daily backup yet. Design needs to be implemented. It may likely go through changes as I implement – as in regular cycle of software development.

How do you handle backup and recovery of your application data in service?

Saving and restoring page state in a WinJS application

Published November 15, 2013 1:39 pm

When building a winjs application with multiple pages, there is high chance that you need to save and restore page state of some of the page(s).

First – what is page state and why it needs to be saved & restored? Let’s take few example cases.

  1. User inputs some data provided in a form page. When the form page is navigated back, form page needs to be filled with the same data; not lose data.
  2. Page contains a list view with multiple items; user scrolls to reach an item and clicks it to traverse to the item detail page. When user navigates back, list view’s scroll position should not be reset.
  3. Add another case for case (2). application is suspended when on the item detail page, restored during next activation and start on item details page. In such case also, the listview scroll position should not be lost when navigating back to the list view page.

How to handle this?

In a WinJS application, each page is re-initialized when navigated back. ready event handler is called each time a page is navigated. Hence, to keep the page in the same state – it’s state needs to be saved and restored. WinJS library provides WinJS.Application.SessionState object. It is serialized and de-serialized across application suspension by the library. The page state needs to be saved and restored to/from session state object.

What the code looks like? Let take the case (2).
Initializing, and restoring the scrollPosition state on the list view

 
    var sessionState = WinJS.Application.sessionState;
    ready: function onready(element, options)
    {
        ...
        if (!sessionState.itemList)
            sessionState.itemList = {};
        else if (sessionState.itemList.scrollPosition)
        {
            WinJS.Promise.timeout().then(function ()
            {
                listView.winControl.scrollPosition = sessionState.itemList.scrollPosition;
            });
        }
    },

Saving the scrollPosition state when navigating to the item detail page. The code below is doing that in the iteminvoked handler.

 
    listView.winControl.addEventListener('iteminvoked', function (event)
    {
        var item = this.viewModel.items.getAt(event.detail.itemIndex);
        sessionState.itemList.scrollPosition = textListView.winControl.scrollPosition;
        WinJS.Navigation.navigate('/pages/itemDetail/page.html', { item: item });
    }.bind(this));

That’s it. Few comments before closing.

  1. It will be good practice to keep separation between the state for each page. Hence, the code above saves the scrollPosition state for the itemList page under itemList property in session state object.
  2. The state is restored typically in the ready handler.
  3. The state needs to be saved prior to the navigation to the next page.
  4. scrollPosition is restored under a setImmediate call. otherwise, it does not get restored.

HTH.

WinJS 101

Published September 25, 2013 1:47 pm

Last couple of months has been heads down into our next app; The app is more involved app with authentication, backend service etc. I have not been able to find time to write blog. Today, I thought of resurrecting again. Here is what we are going to do. We will go over WinJS over next set of posts – as a winjs 101 for developer.

WinJS 101 for developer will be as close to code as possible. It is not meant to be executive summary. It is meant to be developer summary; a dev to dev talk/share – to help you jump start on this. If you are developer, who is starting because a) your current project needs it b) you want to remain updated of windows app development c) you want to get on to html/css/javascript since they are open and skill will be valuable on other platforms. It is likely that the post might help you. At the very least, it is an attempt with that intent. Let’s get started.

winjs-lib-002What is WinJS – well, it is windows javascript library. Like you have underscore.js, backbone.js – various javascript libraries, it is a javascript library meant for developing windows modern (aka metro) applications. When you open a new winjs based windows store application project in VS express 2012, you will find reference to winjs lib in solution explorer – like you used to find default reference to few net assemblies e.g. system in your .net projects. Your curiosity will certainly expand the node and you will find couple of these files there.

ui-dark.css/ui-light.css : css provides the way to declaratively style a html web page. css is available to style winjs applications. This file contains the default style rules for the windows controls. MSDN documentation of the WinJS controls will document the css classes that can be used to style them. For example – refer styling of listview control here. Typical web developer will not need introduction to css. If you are not a typical web developer, css introduction here helped me in past. Do not try to go through this file at beginning, it might be intimidating. It is like seeing disassembly of a .net assembly. Ctrl+f in this file will be of most help during first few days when documentation does not help getting to css classes for a winjs control.

base.js: In simply terms, this is the non-ui part of the winjs lib. Winjs library provides basic functions like WinJS.Class.define/derive: to define a class (using javascript prototype underneath), WinJS.Namespace.define: to organize code in namespaces (using simply dynamic javascript  object underneath) albeit there is no native thing called namespace in javascript, WinJS.Binding.List: one of the first class that you will get exposed; it is used as dataSource for winjs controls like ListView and FlipView, WinJS.Application namespace: apis/events for app start/suspend, session and setting mgmt. you will see reference to this mostly in default.js in your project. Note: that winrt apis* are natively accessible to winjs application and not part of the winjs lib. WinJS library provides added functionality to support winjs based application development. For winrt apis example: refer Windows.Storage.FileIO: it provides apis to read/write files. For all windows(aka winrt) api for all windows store apps – refer here. These can be used in windows store app written in javascript or any other supported language like c#, c++ etc.

*winrt api: winrt apis are referred as windows apis that are available to a windows store app, written any language of choice – c#, javascript, c++ etc. It is not a new/latest version of .net frameworks. It is a new framework altogether meant for windows store (modern) app development. This is a one line intro to winrt which is a longer  discussion otherwise.

ui.js: this is the ui part of the wijs lib. All html 5 controls (rather all documented to be supported by IE) can be used in winjs app. There are subtle differences in support when used in native modern app vs IE. At meta level, you can think of using html/DOM to build UI without getting into details at the onset. If you are web developer, you get to leverage all your knowledge of native html controls; listing of all controls here will make you happy.

ui.js provides additional ui controls apart from native html – like ListView, FlipView and more. There controls are rendered below a html div, written in javascript and styled using css. Not sure what that means – use debug->windows->DOM Explorer->select element in VS, and explore the html/css below a list view in your application. you will find that WinJS ListView control renders itself by spitting html in the DOM.

There is lot more under WinJS.UI namespace. Many of the controls like HubControl, SearchBox are coming windows 8.1. ListView, DatePicker, TimePicker, Flyout, AppBar has been the frequently used controls in my case. Again, like in case of base.js – this is not all. All other windows (aka winrt) controls – like Windows.UI.Popups.MessageDialog – are available to javascript and other languages like c#, c++.

Going back to our winjs lib node in picture above, you will find string resource files below en-us node. ui-dark and ui-light.css provides different style for light and dark theme. your application will use only one of them.

we have not yet finished talking about the other files in the a typical winjs project. There will be other things like data-win-control, data-win-options in html that won’t look like html attributes; a typical page in winjs app will be a Winjs PageControl defined using WinJS.UI.Pages.define(); javascript for the page needs to be organized little differently than its done for typical web pages. We will talk about these next time.

Before we close on this: Why WinJS? You will the right person to make the choice for your project. I will share few of my observations:

  1.  Are you a web developer that have sound html/css/js skills and need to code a windows store app? WinJS based application development will surely help to leverage your skills. At the same time, do not think you can get around without  any additional learning curve. There are windows specific nuances. but again, you will certainly have better jumpstart here than in going with c# and xaml.
  2. Are you are developer that have sound c#, xaml skills? yes – then certainly, windows provides default path of using xaml & c#. That will align well and give you good jumpstart. Should you think even once of learning html/js/css way of building the windows store app? Ask yourself do you want to get exposed to html/js/css. These skills are likely more transferable to other web/mobile development platforms. They might help you in the long run and good to have these skills in your arsenal even if you are a old timer solid dev. At the same time, do expect a learning curve of 6 month even if you are a Pro in c#, xaml, ms technologies; this is assuming that you have no exposure to css/html/js.
  3. If you already have sound html/css/js knowledge – using this library do help for windows store app dev.
  4. html/css/js skills are transferable to other web/mobile platforms. This will also come with disclaimer that winjs apis or windows api knowledge development will be key and require investment of time. This knowledge won’t be directly transferable to other platforms.
  5. if you are building application that falls in integration category – what I mean, the application falls in category of building a native windows experience for one or more web services. json/ajax- provide a loose / lightweight way to interact with services; winjs might help.
  6. does your application have lot of algorithmic, complex logic implementation? javascript is a dynamic language and not strongly typed. The benefits of compiler catching your common coding mistakes will not be there. For example – even if you invoke a method without passing required number of arguments, code will not give error until executed. Now, think of complex product code base, making changes and handling regression. This is flip side of js that I have experienced. but decided to live with it. The power of language needs to be used with caution.
  7. for a specific project, you may want to pilot to verify that framework suffices your needs. There is certainly difference in controls available in xaml vs winjs.
  8. winjs won’t provide two way binding by default. I wrote a naïve two way binding impl. sufficient enough for our current needs.
  9. in sum total, I would say staying with html/css/js stack was the biggest motivator to stay with winjs.

Adding context menu for a WinJS custom control

Published August 12, 2013 1:18 pm

Recently, we were adding a WinJS custom control for image selection. It needs to handle things like – show progress ring during image load; show load error if image failed to load; allow user to select a new image; etc. The custom control also needs to display a context menu.

Windows.UI.Menu provides the way to show context menu as flyout and quite straight forward. Need to define the menu in the html, and show the flyout in an event handler on user gesture. Example html:

<div id="imageSelectControlMenu" data-win-control="WinJS.UI.Menu">
    <button data-win-control="WinJS.UI.MenuCommand" 
      data-win-options="{ extraClass: 'delete', label: 'Delete' }"></button>
    <button data-win-control="WinJS.UI.MenuCommand" 
      data-win-options="{ extraClass: 'undo-delete', label: 'Undo Delete' }"></button>
    <button data-win-control="WinJS.UI.MenuCommand" 
      data-win-options="{ extraClass: 'clear-new-selection', label: 'Clear New Selection' }"></button>
</div>

Example js:

 
_initializeEventHandlers: function initializeEventHandlers()
{
    this.element.addEventListener('contextmenu', this._oncontextmenu.bind(this));
},
_oncontextmenu: function oncontextmenu(event)
{
    var menu = document.querySelector('#imageSelectControlMenu');
    menu.winControl.show(this.element, 'right', 'center');
},

so far so good. This is where I hit the issue of context menu showing and hiding immediately. Context menu will show up and hide immediately in less than a sec. In process to get to the root cause of the issue, I tried GestureRecognizer which exposes high level gesture events when passed the mouse events for an element. There is a good sample available for it. It takes few minutes to digest what Gesture Recognizer provides. Few notes from my usage:

  1. Typically, it will come handy for a custom control where you want to control how to raise gesture events for mspointer events.
  2. I only used it to get ‘tapped’, ‘righttapped’ events. I did not use it for manipulation events or custom gesture events. DOM ‘click’ and ‘contextmenu’ events give the same functionality as ‘tapped’ and ‘righttapped’ events respectively.
  3. Sample code gives feel how to pass it mouse pointer events.

After using the GR, I found that the issue did not go away. After few minutes of debugging, root cause was found. It was missed ‘preventDefault()’ call in the handler for ‘contextmenu’ event.

 
_oncontextmenu: function oncontextmenu(event)
{
    var menu = document.querySelector('#imageSelectControlMenu');
    menu.winControl.show(this.element, 'right', 'center');
    event.preventDefault();
},

I need to this css to fix the layout of the context menu.

.my-custom-control .win-menu
{
    width: 10em;
    padding-left: 1em;
}

Reading a file into ArrayBuffer in WinJS application

Published August 8, 2013 11:02 am

Many a times when you are using an external javascript library into your winjs application, you come across apis that expect a parameter as ArrayBuffer. Windows storage apis like FileIO.readBufferAsync return IBuffer. In such case, How do one read the contents of a file into ArrayBuffer?

There are multiple solutions for this. One of the solution that I have come across is to read the DOM ‘File’ object using WinJS.xhr.

        var storage = Windows.Storage;
        storage.StorageFile.getFileFromApplicationUriAsync(new Windows.Foundation.Uri('ms-appx:///images/logo.png')).then(function ongetfile(file)
        {
            var blob = MSApp.createFileFromStorageFile(file);
            var url = URL.createObjectURL(blob, { oneTimeOnly: true });
            return WinJS.xhr({ url: url, responseType: 'arraybuffer' });
        }).then(function onreadbuffer(req)
        {
            var arrayBuffer = req.response;
        }).then(null, function onerror(error)
        {
            // TODO: handle error
        });

Responding to feedback for Hymn World

Published August 2, 2013 11:20 am

There was a recent feedback on the Hymn World through windows store rating. Thanks for sending feedback.

StorePromo-414x180
A very good App with a few flaws
I highly recommend this app. I like the fact that the sheet music is included with each hymn incase you want to play it on the piano. I just have a few problems (pretty minor) with the app. When playing the hymn, there is only a pause button.  It would be good if a rewind and fast forward option was included. Also, an option to resize the text on the hymn and its sheet music would also be great. All in all a great app. I give it 4 stars, but if these issues were fixed I would gladly give it 5.

 

Let me respond in parts.

  1. Yes, rewind & fast-forward options are good to have. but they do not look straight forward to implement. We are currently busy with the next application. We will add them to the feature requests.
  2. Regards zoom in and out, it was earlier request by other users and already exists. you can use touch ‘pinch’ action or (ctrl key + mouse wheel) to zoom in/out.

Thanks for your valuable feedback; share it with your friends and happy playing your favorite hymns.

Css selector and its style rules are not picked up

Published July 23, 2013 11:38 am

When building a WinJS based windows store, many a times I run into the issue – css rule is not getting picked. then, begins the debugging to figure out what is going wrong. Sometimes, it has been quick and get to the solution; sometimes end up pulling hairs and decide to take it up some other day; sometime eliminate the problem by removing it thinking about ROI; sometimes strike a reasonable workaround.

Here is the listing of things that have come handy some time or the other:

  1. Seriously checking that css file is included in the html file; The path of the css file is indeed correct and does not have any typo. For example: today, I hit a case where I missed one directory in the folder path of the css file in a big size project.
  2. class names or the id name in the css selector does not match with what is mentioned in the html file. Following a naming convention reduces the probability of this cause over a period of time. For example – I happen to use some of these rules a) use camel casing for id b) use ‘-‘ as word separators in class names c) try to keep class names to 2-3 words d) pick class names that are intuitively represent the element
  3. Use VS->Debug->windows-> DOM Explorer -> select element and look through the styles and trace style for the desired element.
  4. Keeping the common css rules across projects into default.css.
  5. Prefixing the css selector long enough that it does not conflict with rules in other pages. For example – I happen to use a convention to give a unique class name for each page in the fragment element and use '.mypage.fragment' prefix in the css rules for the page.
  6. Layout rules have been most challenging at least in the beginning when using display: -ms-grid or display: -ms-flexbox . Over a period of time, there is understanding of how it works. Debugging issues here require a separate post though.
  7. Using WinJS builtin styles whenever possible since they are well tested and work for multiple layouts of the page. For example: .win-type-ellipsis to auto-ellipse the text if it is too long for the space. win-ring win-medium for a medium size progress ring. msdn pages for each control and skimming though the ui-light.css gives access to such classes.
  8. There can be many more items. but need to get back to work. Today I found this nice article that explains how a multiple rules fight over a given css selector in the section “cascading order”.

More later.

Adding asserts to WinJS application

Published July 8, 2013 2:49 pm

I have been coding without asserts Windows store application in javascript (WinJS based). Amidst making progress on frameworks for the next application, looking into this was at the back burner. One day, it pinched enough to look around for the solution.

I had been using chai.js for the assertions in the nodejs server code. It is expected to work in browser. hence, gave it a try to use it in WinJS application. It works; the library has right set of apis for the assertions in javascript.

What needs to be done:

  1. download chai.js for browser from here.
  2. Add the file to the vs project
  3. Add script entry into default.html
  4. Add a global variable – assert – in default.js
  5. Use the assert apis in code.

default.html:

<!-- WinJS references -->     
<link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" />     
<script src="//Microsoft.WinJS.1.0/js/base.js"></script>     
<script src="//Microsoft.WinJS.1.0/js/ui.js"></script>

<!-- external js libs -->     
<script src="/js/chai.js"></script>

<script src="/js/default.js"></script>

default.js:

 
(function()
{
    ...
    assert = chai.assert;
})();
var assert;

Examples:

 
    assert.isObject(this.options);

    assert.isString(this.options.parameter1);

    assert.deepEqual({ tea: 'tea' }, { tea: 'tea' });
    //  for more examples - refer http://chaijs.com/api/assert/

Azure Table Rest API errors with WinJS application

Published June 7, 2013 11:10 am

If you are using azure SDK to code to its REST API – there are lot of API nuance that is taken care by the SDK. For example – if you are coding nodejs server, or windows store application using c# that uses Azure, nodejs and .net sdk is available. For WinJS, there isn’t azure sdk.

But it shouldn’t be big deal to code directly to the REST API if the basic http lib is available. `WinJS.xhr()` is available to mimics closely what XmlHttpRequest does in the browser. Well, this holds true if the API returns meaningful errors with sufficient contextual details for the error. If that isn’t true, lot of developer(your) time is wasted debugging the error cases. Keep binging to see if other community developer hit similar issue, or parse the http packets sent — for a successful rest api call made by other tool or application – using fiddler or network monitor.

I recently saw two such errors when invoking azure table rest api to query using javascript in WinJS application.

  1. AuthenticationFailed
    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
      <code>AuthenticationFailed</code>
      <message xml:lang="en-US">Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.</message>
    </error>
  2. InvalidHeaderValue
     
    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
      <code>InvalidHeaderValue</code>
      <message xml:lang="en-US">The value for one of the HTTP headers is not in the correct format.</message>
    </error>

AuthenticationFailed was hit when the x-ms-date header was formatted incorrectly. Expected value – Thu, 06 Jun 2013 08:09:50 GMT . Value computed in the code – Thu, 6 Jun 2013 08:20:34 GMT. Note: the difference in ‘0’ prefix for the date. Because of this, the computed stringToSign for the authorization header was incorrect. For details, you can refer here.

InvalidHeaderValue was hit because MaxDataServiceVersion: '2.0;NetFx' header value was missing.

In the first case, if the REST API returned the expected and found ‘stringToSign’ parameter value in the returned error – it would help developer save order of .5 to 1day worth of debugging time. In the second case, if the returned error mentioned the missing header in the error details, again it will save 1-2 hours of debugging time.

Well, you might hit here and cause & solution of the error code for the same api might be different than this – do drop a comment with the cause & solution. If you are a developer coding REST API, do send error codes with sufficient details to save hours of developer time. Thanks for reading so far.