Developer. Creative Geek. Composer.

In this third tutorial, we will use the WinJS FlipView control to navigate between our live preview UI and the various photos & videos taken during the life of the application. For that, we will need a specific template for each case: camera live preview, photo & video. To do that, you need to use a JS function as a template renderer that will return the appropriate piece of HTML for each case. We will also see that the FlipView is doing some virtualization by default which could lead to unexpected behavior if you’re not prepared for that.

In our case, we need 3 different templates for our FlipView control: a live preview, a photo and a video template.

As the first element of the list bind to the FlipView will be the live preview control, let’s start by this one. We just need to take the HTML built in the 2 previous tutorials and turn it into a WinJS Template. For that, we just have to copy/paste it into a new div marked with the data-win-control="WinJS.Binding.Template" attribute.

Note: But to make a good template, it’s normally better to avoid using IDs the inner HTML as this block of HTML will be repeated by the templating engine. In our case, this template will be only instantiated once as we’ve got only 1 live preview control. So, we won’t run into issues in our very specific case.

Let’s now review the 2 templates that will be used (and repeated) for the photos and videos you’ll recorded:

The imageTemplate is more or less the same template we’ve used for the slide effect in the previous tutorial. The videoTemplate one is just using the video tag instead of the image one and add a layer on top of it with a play button. This play button is using the code xE102 of the Segoe UI Symbol font. Both templates use the binding engine of WinJS for their source properties.

Now that we’ve got our templates ready to use, let’s insert the FlipView control itself:

<div id="flip-view" data-win-control="WinJS.UI.FlipView">
</div>

Finally, insert this new piece of CSS to style our various containers:

You should now be comfortable with this CSS. We’re using again CSS Grid to center our elements.

If you’re running the application now, you will simply have a black screen as we don’t have written the JavaScript code to handle our FlipView yet.

Step 2: inserting the live preview control as the first element bind to the FlipView

We need to instantiate a new binding list that will serve our FlipView control. This binding list will have 3 types of objects inside. Based on this type, our rendering function will choose the proper template to render and launch the appropriate code to initialize the various events handling and so on.

We’re pushing a dummy JS object with just the type property set to “application” into the binding list. This is just to help us knowing that associated to this object, we should render the live preview control. Then, we’re setting the FlipView’s options programmatically (data source and item template renderer) thanks to the setOptions functions. We now need the JS function acting as the item renderer:

This function will be called on each object inserted into the binding list. The first thing we’re doing is accessing to the type property of the current object bind for the currently processed item. We’re then selecting the associated template (applicationTemplate, imageTemplate or videoTemplate). We’re rendering and injecting them into the DOM by the renderItem function. Once this asynchronous operation is finished, we can associate some code to this new HTML generated. In the “application” case, we’re simply doing the same logic done in the previous tutorials: getting the video tag and rendering the live preview feed of the camera into it.

If you’re now pressing F5, you should visually obtain the exact result as the second tutorial. But we’re now living into a FlipView control! That’s a big difference. Aren’t you amazed? Ok, not yet I guess… But you’ll soon see the difference.

Step 3: inserting the photos & videos recorded into the FlipView

Like demonstrated in the video at the beginning at this article, if we slide from left to right, a new element will be displayed in the flipview. We then need to add items in the list bind to the control.

It adds a new JS object to the list with the path to the URL of the photo or video just recorded, the value type (image or video) to help the renderer function choosing the right template and the URL to a thumbnail (for the video in fact). We add them at the beginning of the list with the unshift function. Use the push function to add the new element at the end of the list.

We now need to call this function instead of calling the previewSlide() directly into takePhoto() and stopRecording(). We also need to tune a little bit the stopRecording function to add a call to createObjectURL() to map the video stream recorded to an URL.

This function simply binds some code to the play button displayed in front of the video. You’ll notice that we’re using this time the WinJS.UI.Animation framework to handle the fade in/fade out effects. We could have used also some pure CSS3 transitions or animations code for that. But the WinJS framework provides some easy & cool effects to code & use. It generates some CSS3 on the fly for you.

Press F5 to play with the application. It starts to be really cool to play with! But maybe you’ll face some issues because we haven’t handled the virtualization of the WinJS list controls properly yet. Let’s talk about that in the next step.

Step 4: handling properly the virtualization of the WinJS controls

To reproduce the problem, launch the application, take for instance 2 photos, 1 video then 3 photos again. Navigate to the first element of the list sliding from left to right a couple of times and navigate back to the video element. You should normally see the play button but no more thumbnail image, just a black screen.

So, what happened? It happened that the WinJS list controls (ListView & FlipView) are very well written and are using a virtualization mechanism by default for performance and memory reasons. Usually, it then loads and renders the elements by bunch of 3. This means also that it finishes by unloading some element once the view window is greater than 3.

In our case case, we’ve created the URL bind to the template controls using the oneTimeOnly boolean set to true. This means that once the template control is unloaded by the virtualization mechanism, the memory area dedicated to this blob URL could be garbage collected.

There is then 2 ways to fix this problem:

1 – change to boolean to false to keep our blob URL in memory and avoid then garbage collecting. This is an easy fix but not a good practice for memory usage if your application does a lot of calls to createObjectURL.

2 – call the createObjectURL only when the template control is rendered in the flipViewItemTemplateRendererFunction() function.

The second option means that you will have to read the stream back from the disk to pass it the createObjectURL function every time the virtualization process will instantiate the template control. This is more memory efficient but generate more I/O. The first option is more I/O efficient but cost more memory. This is the usual balance we’re used to as developers my friends!

In our case, our sample application is not meant to generate thousand of videos and if we’re killing and re-launching it, we’re starting every time from scratch. We’re not reloading previous videos/photos taken. Using the first option should be fine for this tutorial.

In conclusion, change all calls to the createObjectURL to set the boolean to false. Re-launch the application with F5 and check that this boolean modification has solved our problems.

Ok, let’s now fix some other potential problems. While navigating into the flipview, the camera live preview video stream could be paused by the system. So when you’ll navigate back to the camera template, the video could appear as frozen. To fix that, in the startCamera() function, add this line of code:

Only updates needed for it to work as 8.1 application (pre-beta) is swapping the deprecated MediaControl logic for muting with the systemMediaTransportControls. So the code would look something like this:

var systemMediaTransportControls;

then in app.onactivated(), replace MediaControl and event handler with the Windows.Media.SystemMediaTransportControl like this:

Also, like in the previous tutorial, you need to add the click handler to overlay instead of livePreview since at least with the pre-beta bits, the click event isn't getting pushed down. So this change needed:

function flipViewItemTemplateRendererFunction(itemPromise)

{

…

// livePreview.addEventListener("click", capture);

var overlay = elem.querySelector("#overlay");

overlay.addEventListener("click", capture);

And that should do it. Jumping into the final lesson next. Great job, David! Love your teaching style.