Imagine the following use case: a user copy a file from its Windows desktop (so it’s sent to the clipboard) and he want to be able to perform a paste in your Windows Store application to retrieve the image. This is not a common scenario but after all, it could be helpful for your users.

So here is a way to do it. First, we need to get access to the clipboard, using the Clipboard.getContent method:

var dataPackageView = Windows.ApplicationModel.DataTransfer.Clipboard.getContent();

Then, we are going to check if the clipboard contains some StorageItems and retrieve them (here, StorageItem represent a file that has been copied in the clipboard)

if (dataPackageView.contains(Windows.ApplicationModel.DataTransfer.StandardDataFormats.storageItems)) {
    dataPackageView.getStorageItemsAsync().then(function (items) {
        // TODO
    }
}

Now, we’ll get the properties of the first item and we’ll open it to access to a stream that will allow us to load that stream in a bit array and convert that bit array to a base64 string:

items[0].properties.getImagePropertiesAsync().then(function (imgProps) {
    var height = imgProps.height;
    var width = imgProps.width;

    items[0].openReadAsync().then(function (stream) {
        var inputStream = stream.getInputStreamAt(0);
        var reader = new Windows.Storage.Streams.DataReader(inputStream);
        reader.loadAsync(stream.size).then(function(actualSize) {
            var array = new Array(actualSize);
            reader.readBytes(array);
            reader.close();

            var base64Data = Base64.encode(array);

            // TODO
            }, function(error) {
                console.log(error);
            });
        });
    }, function(error) {
        console.log(error);
});

Here is the code for the Base64.encode method:

var Base64 = {
    encode: function(data) {
        var str = "";
        for (var i = 0; i < data.length; i++)
            str += String.fromCharCode(data[i]);

        return btoa(str).split(/(.{75})/).join("\n").replace(/\n+/g, "\n").trim();
    }
}

You may wonder why I have chosen to use a bit array/base64 string. In fact, this is because the next part of the code will be to load an image using the base64 string

var canvasImage = document.createElement('img');
canvasImage.onerror = function (error) {
    console.log(error);
};

canvasImage.onload = function () {
    // TODO
};

canvasImage.src = "data:" + items[0].contentType + ";base64," + base64Data;

When the image is loaded, we’ll access our HTML5 canvas and draw the image within:

canvasImage.onload = function () {
    var canvas = document.getElementById("canvas");
    canvas.width = width;
    canvas.height = height;

    var ctx = canvas.getContext("2d");
    ctx.drawImage(this, 0, 0, width, height);

    canvasImage = undefined;
};

And voila ! Of course, there are other possibilities (like setting the source of an image that’s already added to the DOM instead of using a Canvas). And even if I’ve used JavaScript code here, we could have easily perform the same thing using C# because, if you are able to access to the file stream, you’re able to perform what you want with it (load it in a BitmapImage for example).

Happy coding!

The “tilt effect” was introduced in Windows Phone and give to developers the possibility to provide visual feedback to users by performing a small scale when the pointer is down on the control (and restoring the control to its original scale’s value when the pointer is up).

Here is a quick (but useful !) tip if you want to add this “tilt effect” to your controls:

(function () {
    "use strict";

    function addTiltEffect(control) {
        control.addEventListener('MSPointerDown', function () {
            WinJS.UI.Animation.pointerDown(control);
        }, false);

        control.addEventListener('MSPointerUp', function () {
            WinJS.UI.Animation.pointerUp(control);
        }, false);

        control.addEventListener('MSPointerOut', function () {
            WinJS.UI.Animation.pointerUp(control);
        }, false);
    }

    WinJS.Namespace.define("UiHelpers", {
        AddTiltEffect: addTiltEffect
    });
})();

As you can see, we just add handlers to the PointerDown, PointerUp and PointerOut events and we call the function pointerDown and pointerUp provided by the WinJS Framework !

 

Have fun and happy coding!

Sometimes, it’s useful/needed to take screenshots of a video that is played by your application. Here is a simple (but working) technique to perform this task:

<section class="section">
    <p>
        <button id="btnVideoSelect">Select Video</button>
    </p>
    <p>
        <video id="videoPreview" width="350" height="250"></video>
    </p>
</section>

<section class="section2">
    <div id="outputListView" class="output" data-win-control="WinJS.UI.ListView"></div>
</section>
var screenshots = new WinJS.Binding.List();

var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
openPicker.viewMode = Windows.Storage.Pickers.PickerViewMode.list;
openPicker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.musicLibrary;
openPicker.fileTypeFilter.replaceAll([".mp4", ".mpeg", ".avi"]);
openPicker.pickSingleFileAsync().done(function(file) {
if (file) {
    var videoPreview = document.getElementById("videoPreview");
    if(videoPreview) {
        var fileLocation = window.URL.createObjectURL(file);

        videoPreview.src = fileLocation;
        videoPreview.setAttribute("controls", "true");

        var createScreenshots = false;

        videoPreview.addEventListener("ended", function() {
            createScreenshots = false;
        });

        videoPreview.addEventListener("play", function () {

            createScreenshots = true;

            setInterval(function () {
                if (createScreenshots) {
                    var canvas = document.createElement("canvas");
                    if (canvas) {

                         canvas.width = videoPreview.videoWidth;
                         canvas.height = videoPreview.videoHeight;

                         var ctx = canvas.getContext("2d");
                         ctx.drawImage(videoPreview, 0, 0, videoPreview.videoWidth, videoPreview.videoHeight);

                         var imageUrl = canvas.toDataURL();

                         screenshots.push({ url: imageUrl, width: 150, height: 50 });
                     }
                 }
             }, 500);
         });

            videoPreview.play();
        }
    }
});

Let’s take a look at the code now ! First, we use a FileOpenPicker to allow users to select the video to use. Once a video is selected, we set it a the source of the Video element. Then, as soon as the video starts to play, we create a Canvas element and access to the 2D context, that will allow us to call the drawImage method. This method accept, as a parameter, the video element that we use to play the video!

Finally, once the screenshot is generated, we use the method toDataURL to get its content encoded in Base64 and put it in a Binding list, which allows the ListView to be notified when new items are added !

As a result, take a look at this image!

image

This is just a prototype (code could be better) but you get the main idea! Of course, you could also use this code to get the screenshot at a particular time of the video (like if you wanted to extract a particular frame from the video).

 

Happy coding!

In .NET application, to retrieve the user’s current culture is pretty simple using the CultureInfo class. But performing the same thing, in particular using Javascript, is a bit more complex.

So here is a quick code sample to perform this task:

image

As you can see, we just need to access to the languages property of the GlobalizationPreferences class. This property is an array containing all the cultures installed and used on the machine.

Here is the results of the previous call:

image

Simple but very useful ! To see more content about localization, check here: http://msdn.microsoft.com/en-us/library/windows/apps/hh465006.aspx

 

Happy coding!

On my spare time, I’ve started a few weeks ago to work on a small Windows 8 application that allow users to look for YouTube videos and play them directly in the application.

I’m proud to announce that the application is now live on the Microsoft Store and any Windows 8 Release Preview users can download it and play with it !

For now, there are some issues with some videos that cannot be played directly in the app but I’ll try to improve this part (and add more features) in the next version !

Here are some screenshots:

Capture d’écran 1

Capture d’écran 2

Capture d’écran 3

Capture d’écran 4

I hope you’ll enjoy it !

In one of his blog post (here or here, for the French version), the Windows 8 Development Master David Catuhe explained how to generate and to rescale a new picture for a tile (secondary or not).

This is very useful if you’re not able to modify the service delivering the images to rescale them automatically. Its technique need you to use an Image HTML element and, unfortunately, you’re not allowed to use graphical components in a Windows 8 background task.

So here is the version I propose, which is quite different. First, I use a Promise when David’s version use an callback parameter. Then, I don’t use an Image element but I take advantage of the BitmapTransform class to perform a transformation (scale, rotation, etc.) on the image, accessed using the BitmapDecoder:

function rescaleImage2(src, destinationWidth, destinationHeight, localfilename) {

    return new WinJS.Promise(function (complete, error, progress) {

        var Imaging = Windows.Graphics.Imaging;

 

        WinJS.xhr({ url: src, responseType: “blob” }).then(function (request) {

            var imageStream = request.response;

 

            var fileName = new Date().getTime() + “_” + parseUri(src).file

 

            Windows.Storage.ApplicationData.current.localFolder.createFileAsync(fileName, Windows.Storage.CreationCollisionOption.replaceExisting).then(function (rootFile) {

                rootFile.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream) {

                    Windows.Storage.Streams.RandomAccessStream.copyAsync(imageStream.msDetachStream(), stream).then(function () {

                        stream.flushAsync().then(function () {

                            stream.close();

                                     Windows.Storage.ApplicationData.current.localFolder.getFileAsync(fileName).then(function(file){

                            file.openReadAsync().then(function (stream) {

                                Imaging.BitmapDecoder.createAsync(stream).then(function (bd) {

                                    var transform = new Windows.Graphics.Imaging.BitmapTransform();

                                    transform.scaledHeight = destinationHeight;

                                    transform.scaledWidth = destinationWidth;

 

                                    bd.getPixelDataAsync(Imaging.BitmapPixelFormat.rgba8, Imaging.BitmapAlphaMode.straight, transform, Imaging.ExifOrientationMode.respectExifOrientation, Imaging.ColorManagementMode.doNotColorManage).then(function (pdp) {

                                        var pixelData = pdp.detachPixelData();

                                       Windows.Storage.ApplicationData.current.localFolder.createFileAsync(localfilename, Windows.Storage.CreationCollisionOption.replaceExisting).then(function (file) {

           file.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream){

                                                                 Imaging.BitmapEncoder.createAsync(Imaging.BitmapEncoder.pngEncoderId, stream).then(function (encoder) {

               encoder.setPixelData(Imaging.BitmapPixelFormat.rgba8, Imaging.BitmapAlphaMode.straight, destinationWidth, destinationHeight, 96, 96, pixelData);

 

               encoder.flushAsync().then(function () {

                   stream.flushAsync().then(function () {

                       stream.close();

                       rootFile.deleteAsync().done(function () {

                           if (complete)

                               complete(“ms-appdata:///local/” + localfilename.replace(“\\”, “/”));

                                                            });

                                                        });

                                                    });

                                                });

                                             });

                                         });

                                      });

                                  });

                              });

                          });

                      });

                  });

              });

          });

      });

    });

}

The code is also available, in a more readable format, here (thanks http://codepaste.net !)

As always, feel free to use it, comment, it, etc.

 

Happy coding!

Some people ask me if there are some helpers available to perform various tasks such manipulating settings, local storage, etc.

There are no built-in helpers but for the current Windows 8 application I’m working, I’ve developed some of them and I wanted to share them with the community (note that this helpers are available in Javascript but it should not be hard to translate them in C#):

ResourcesHelper:

(function () {

    “use strict”;

 

    var appView = Windows.UI.ViewManagement.ApplicationView;

    var displayProps = Windows.Graphics.Display.DisplayProperties;

    var nav = WinJS.Navigation;

    var ui = WinJS.UI;

    var utils = WinJS.Utilities;

 

    WinJS.Namespace.define(“ResourcesHelper”, {

        ResourcesManager: WinJS.Class.define(

        // Define the constructor function for the ResourcesManager.

            function (resourceFile) {

                this.resourceLoader = null;

 

                if (resourceFile) {

                    this.resourceLoader = new Windows.ApplicationModel.Resources.ResourceLoader(resourceFile);

                }

                else {

                    this.resourceLoader = new Windows.ApplicationModel.Resources.ResourceLoader();

                }

            }, {

                // Instance methods

                ResourceLoader: {

                    get: function () { return this.resourceLoader; }

                },

 

                GetString: function (key) {

                    return this.ResourceLoader.getString(key);

                }

            }, {

                // Static methods               

            }

        )

    });

})();

 

SettingsHelper:

(function () {

    “use strict”;

 

    var applicationData = Windows.Storage.ApplicationData.current;

 

    function hasSetting(key) {

        return new WinJS.Promise(function (complete, error, progress) {

            var result = applicationData.roamingSettings.values.hasKey(key);

 

            complete(result);

        });

    }

 

    function getSetting(key) {

        return new WinJS.Promise(function (complete, error, progress) {

            hasSetting(key).then(function (found) {

                if (found) {

                    var result = applicationData.roamingSettings.values[key];

 

                    complete(result);

                }

                else {

                    complete(false);

                }

            });

        });

    }

 

    function addSetting(key, value) {

        return new WinJS.Promise(function (complete, error, progress) {

            var result = applicationData.roamingSettings.values.insert(key, value);

 

            complete(result);

        });

    }

 

    function removeSetting(key) {

        return new WinJS.Promise(function (complete, error, progress) {

            applicationData.roamingSettings.values.remove(key);

 

            complete();

        });

    }

 

    function updateSetting(key, value) {

        return new WinJS.Promise(function (complete, error, progress) {

            hasSetting(key).then(function (result) {

                if (result) {

                    removeSetting(key).then(function () {

                        addSetting(key, value).then(function (addResult) {

                            complete(addResult);

                        });

                    });

                }

                else {

                    addSetting(key, value).then(function (result) {

                        complete(result);

                    });

                }

            });

        });

    }

 

    function clearSettings() {

        return new WinJS.Promise(function (complete, error, progress) {

            applicationData.roamingSettings.values.clear();

 

            complete();

        });

    }

 

    WinJS.Namespace.define(“SettingsHelper”, {

        HasSetting: hasSetting,

        GetSetting: getSetting,

        AddSetting: addSetting,

        RemoveSetting: removeSetting,

        UpdateSetting: updateSetting,

        ClearSettings: clearSettings

    });

})();

 

StorageHelper:

(function () {

    “use strict”;

 

    var applicationData = Windows.Storage.ApplicationData.current;

    var localFolder = applicationData.localFolder;

 

    function hasSavedContent(file) {

        return new WinJS.Promise(function (complete, error, progress) {

            localFolder.getFileAsync(file).then(function (file) {

                complete(true);

            }, function () {

                complete(false);

            });

        });

    }

 

    function saveToCache(file, content) {

        return new WinJS.Promise(function (complete, error, progress) {

            localFolder.createFileAsync(file, Windows.Storage.CreationCollisionOption.replaceExisting)

                .then(function (file) {

                    file.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream) {

                        var writer = new Windows.Storage.Streams.DataWriter(stream.getOutputStreamAt(0));

                        writer.writeString(content);

                        writer.storeAsync().then(function () {

                            writer.flushAsync().then(function () {

                                complete();

                            });

                        });

                    });

                });

        });

    }

 

    function getFromCache(file) {

        return new WinJS.Promise(function (complete, error, progress) {

            hasSavedContent().then(function (exists) {

                if (exists) {

                    localFolder.getFileAsync(file).then(function (file) {

                        file.openReadAsync().then(function (stream) {

                            var reader = new Windows.Storage.Streams.DataReader(stream.getInputStreamAt(0));

                            reader.loadAsync(stream.size).then(function (fileLength) {

                                var jsonContentAsString = reader.readString(fileLength);

 

                                complete(jsonContentAsString);

                            });

                        });

                    });

                }

                else {

                    complete();

                }

            });

        });

    }

 

    function deleteCache(file) {

        return new WinJS.Promise(function (complete, error, progress) {

            hasSavedContent().then(function (exists) {

                if (exists) {

                    localFolder.getFileAsync(file).then(function (file) {

                        if (file) {

                            file.deleteAsync().then(function () {

                                complete();

                            });

                        }

                        else {

                            complete();

                        }

                    })

                }

                else {

                    complete();

                }

            });

        });

    }

 

    WinJS.Namespace.define(“StorageHelper”, {

        HasSavedContent: hasSavedContent,

        SaveToCache: saveToCache,

        GetFromCache: getFromCache,

        DeleteCache: deleteCache

    });

})();

 

TilesHelper:

(function () {

    “use strict”;

 

    function updateMainTile() {

        return new WinJS.Promise(function (complete, error, progress) {

            complete();

        });

    }

 

    function addSecondTile(tileId, name, image) {

        return new WinJS.Promise(function (complete, error, progress) {

            var tile = new Windows.UI.StartScreen.SecondaryTile(tileId);

            tile.shortName = name;

            tile.displayName = name;

            tile.arguments = tileId;

            tile.tileOptions = Windows.UI.StartScreen.TileOptions.showNameOnWideLogo;

 

            //var uri = parseUri(image);

            //var imageLocalUri = tileId + “_” + uri.file;

 

            var imageLocalUri = tileId + “.jpg”;

 

            rescaleImage2(image, 150, 150, imageLocalUri.replace(“.jpg”, “_uri.jpg”), false).then(function (uriLogo) {

                rescaleImage2(image, 310, 150, imageLocalUri.replace(“.jpg”, “_wide.jpg”), false).then(function (wideLogo) {

                    tile.logo = new Windows.Foundation.Uri(uriLogo);

                    tile.wideLogo = new Windows.Foundation.Uri(wideLogo);

 

                    tile.requestCreateAsync().then(function (isPinned) {

                        if (isPinned) {

                            _updateSecondaryTile(tileId, name, uriLogo, wideLogo);

                        }

 

                        complete(isPinned);

                    });

                });

            });

        });

    }

 

    function updateSecondaryTile(tileId, name, image) {

        return new WinJS.Promise(function (complete, error, progress) {

            isPinned(tileId).then(function (isPinned) {

                if (isPinned) {

                    var tileToUpdate = new Windows.UI.StartScreen.SecondaryTile(tileId);

                    tileToUpdate.shortName = name;

                    tileToUpdate.displayName = name;

                    tileToUpdate.arguments = tileId;

                    tileToUpdate.tileOptions = Windows.UI.StartScreen.TileOptions.showNameOnWideLogo;

 

                    //var uri = parseUri(image);

                    //var imageLocalUri = tileId + “_” + uri.file;

 

                    var imageLocalUri = tileId + “.jpg”;

 

                    rescaleImage2(image, 150, 150, imageLocalUri.replace(“.jpg”, “_uri.jpg”), false).then(function (uriLogo) {

                        rescaleImage2(image, 310, 150, imageLocalUri.replace(“.jpg”, “_wide.jpg”), false).then(function (wideLogo) {

                            tileToUpdate.logo = new Windows.Foundation.Uri(uriLogo);

                            tileToUpdate.wideLogo = new Windows.Foundation.Uri(wideLogo);

 

                            _updateSecondaryTile(tileId, name, uriLogo, wideLogo);

 

                            complete();

                        });

                    });

                }

                else {

                    complete();

                }

            });

        });

    }

 

    function _updateSecondaryTile(tileId, name, uriLogo, wideLogo) {

        // Square tile

        var tileXml = Windows.UI.Notifications.TileUpdateManager.getTemplateContent(Windows.UI.Notifications.TileTemplateType.tileSquarePeekImageAndText04);

        var imageXml = tileXml.getElementsByTagName(“image”);

        imageXml.item(0).attributes.getNamedItem(“src”).innerText = uriLogo;

 

        var textXml = tileXml.getElementsByTagName(“text”);

        textXml.item(0).innerText = name;

 

        // Wide tile

        var wideTileXml = Windows.UI.Notifications.TileUpdateManager.getTemplateContent(Windows.UI.Notifications.TileTemplateType.tileWidePeekImage03);

        imageXml = wideTileXml.getElementsByTagName(“image”);

        imageXml.item(0).attributes.getNamedItem(“src”).innerText = wideLogo;

 

        textXml = wideTileXml.getElementsByTagName(“text”);

        textXml.item(0).innerText = name;

 

        // Merge both xml to get one tile

        var mergedNode = tileXml.importNode(wideTileXml.getElementsByTagName(“binding”).item(0), true);

        tileXml.getElementsByTagName(“visual”).item(0).appendChild(mergedNode);

 

        var notificationUpdater = Windows.UI.Notifications.TileUpdateManager.createTileUpdaterForSecondaryTile(tileId);

        notificationUpdater.clear();

        notificationUpdater.enableNotificationQueue(true);

 

        var tileNotification = Windows.UI.Notifications.TileNotification(tileXml);

        tileNotification.tag = tileId;

 

        notificationUpdater.update(tileNotification);

    }

 

    function removeSecondTile(tileId) {

        return new WinJS.Promise(function (complete, error, progress) {

            isPinned(tileId).then(function (isPinned) {

                if (isPinned) {

                    var tileToDelete = new Windows.UI.StartScreen.SecondaryTile(tileId);

                    tileToDelete.requestDeleteAsync().then(function (isUnPinned) {

                        complete(isUnPinned);

                    });

                }

                else {

                    complete();

                }

            });

        });

    }

 

    function isPinned(tileId) {

        return new WinJS.Promise(function (complete, error, progress) {

            var isPinned = Windows.UI.StartScreen.SecondaryTile.exists(tileId);

 

            complete(isPinned);

        });

    }

 

    function rescaleImage2(src, destinationWidth, destinationHeight, localfilename) {

        return new WinJS.Promise(function (complete, error, progress) {

            var Imaging = Windows.Graphics.Imaging;

 

            WinJS.xhr({ url: src, responseType: “blob” }).then(function (request) {

                var imageStream = request.response;

 

                var fileName = new Date().getTime() + “_” + parseUri(src).file

 

                Windows.Storage.ApplicationData.current.localFolder.createFileAsync(fileName, Windows.Storage.CreationCollisionOption.replaceExisting).then(function (rootFile) {

                         rootFile.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream) {

                             Windows.Storage.Streams.RandomAccessStream.copyAsync(imageStream.msDetachStream(), stream).then(function () {

                                 stream.flushAsync().then(function () {

                                     stream.close();

                                     Windows.Storage.ApplicationData.current.localFolder.getFileAsync(fileName).then(function(file){

                                         file.openReadAsync().then(function (stream) {

                                             Imaging.BitmapDecoder.createAsync(stream).then(function (bd) {

                                                 var transform = new Windows.Graphics.Imaging.BitmapTransform();

                                                 transform.scaledHeight = destinationHeight;

                                                 transform.scaledWidth = destinationWidth;

 

                                                 bd.getPixelDataAsync(Imaging.BitmapPixelFormat.rgba8, Imaging.BitmapAlphaMode.straight, transform, Imaging.ExifOrientationMode.respectExifOrientation, Imaging.ColorManagementMode.doNotColorManage).then(function (pdp) {

                                                     var pixelData = pdp.detachPixelData();

 

                                                     Windows.Storage.ApplicationData.current.localFolder.createFileAsync(localfilename,

                                                         Windows.Storage.CreationCollisionOption.replaceExisting).then(function (file) {

                                                             file.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream) {

                                                                 Imaging.BitmapEncoder.createAsync(Imaging.BitmapEncoder.pngEncoderId, stream).then(function (encoder) {

                                                                     encoder.setPixelData(Imaging.BitmapPixelFormat.rgba8, Imaging.BitmapAlphaMode.straight, destinationWidth, destinationHeight, 96, 96, pixelData);

 

                                                                     encoder.flushAsync().then(function () {

                                                                         stream.flushAsync().then(function () {

                                                                             stream.close();

 

                                                                             rootFile.deleteAsync().done(function () {

                                                                                 if (complete)

                                                                                     complete(“ms-appdata:///local/” + localfilename.replace(“\\”, “/”));

                                                                             });

                                                                         });

                                                                     });

                                                                 });

                                                             });

                                                         });

                                                 });

                                             });

                                         });

                                     });

                                 });

                             });

                         });

                     });

            });

        });

    }

 

    // parseUri 1.2.2

    // (c) Steven Levithan <stevenlevithan.com>

    // MIT License

    function parseUri (str) {

        var    o   = parseUri.options,

        m   = o.parser[o.strictMode ? "strict" : "loose"].exec(str),

        uri = {},

        i   = 14;

 

        while (i–) uri[o.key[i]] = m[i] || “”;

 

        uri[o.q.name] = {};

        uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {

            if ($1) uri[o.q.name][$1] = $2;

        });

 

        return uri;

    }

    parseUri.options = {

        strictMode: false,

        key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],

        q:   {

            name:   “queryKey”,

            parser: /(?:^|&)([^&=]*)=?([^&]*)/g

        },

        parser: {

            strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,

            loose:  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/

        }

    };

 

    WinJS.Namespace.define(“TilesManager”, {

        UpdateMainTile: updateMainTile,

        AddSecondTile: addSecondTile,

        UpdateSecondaryTile: updateSecondaryTile,

        RemoveSecondTile: removeSecondTile,

        IsPinned: isPinned,

        RescaleImage: rescaleImage2

    });

})();

(this last one is probably the one you’ll want to modify a bit, depending to the kind of tile you’ll want to use in your application)

Be aware that there might be some bugs or issues with the code so feel free to let me a comment if you have a fix !

 

Happing coding!

In my day to day job, I have the chance to work on some Windows 8 apps thus, I wanted to share with you some code I’ve found/used and which could be, I hope, useful for you too !

Access files located in installation folder:

const string file = @”Images\Logo.jpg”;

 

var installFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;

var logoFile = await installFolder.GetFileAsync(file);

if(logoFile != null)

{

    //

}

Detect Design Mode:

var isInDesignMode = Windows.ApplicationModel.DesignMode.DesignModeEnabled;

 

Get license information (expiration date, trial mode, etc.):

LicenseInformation licenseInfo = null;

 

#if DEBUG

    // CurrentAppSimulator is use to simulate an object allowing to access to the data

    licenseInfo = Windows.ApplicationModel.Store.CurrentAppSimulator.LicenseInformation;

#else

    licenseInfo = Windows.ApplicationModel.Store.CurrentApp.LicenseInformation;

#endif

    var expirationDate = licenseInfo.ExpirationDate;

    var isTrial = licenseInfo.IsTrial;

Convert HTML text to simple text:

string text = Windows.Data.Html.HtmlUtilities.ConvertToText(

“<div class=\”siteLogo\”><a href=\”/en-us/windows/apps\” title=\”Dev Center -  Metro style apps\”><img src=\”http://i.msdn.microsoft.com/Hash/6b67f1378af22a94e4336f5bfdd136bd.png\” alt=\”Dev Center -  Metro style apps\” title=\”Dev Center -  Metro style apps\” /><span>Dev Center -  Metro style apps</span></a></div>”);

Get all connected devices information:

var deviceWatcher = Windows.Devices.Enumeration.DeviceInformation.CreateWatcher();

deviceWatcher.Added += async (watcher, deviceInformation) =>

{

    var glyphThumbnail = await deviceInformation.GetGlyphThumbnailAsync();

    if(glyphThumbnail.Size > 0)

    {

        // Access to the glyph thumbnail

    }

 

    var thumbnail = await deviceInformation.GetThumbnailAsync();

    if(thumbnail.Size > 0)

    {

        // Access to the thumbnail

    }

};

deviceWatcher.Removed += (watcher, deviceInformation) =>

{};

deviceWatcher.Start();

Detect if keyboard, mouse or touch device is available:

// 1: Present

// 0: Not Present

var isKeyboardPresent = new Windows.Devices.Input.KeyboardCapabilities().KeyboardPresent;

var isMousePresent = new Windows.Devices.Input.MouseCapabilities().MousePresent;

var isTouchPresent = new Windows.Devices.Input.TouchCapabilities().TouchPresent;

Change image used in LockScreen:

var filePicker = new Windows.Storage.Pickers.FileOpenPicker();

filePicker.FileTypeFilter.Add(“.png”);

var selectedFile = await filePicker.PickSingleFileAsync();

 

if(selectedFile != null)

{

    var authPicker = Windows.System.UserProfile.LockScreen.SetImageFileAsync(selectedFile);

}

Get information about connected user (and, optionally, set its pictures):

var userInformation = Windows.System.UserProfile.UserInformation.DisplayName;

Update badge on tile:

var badgeUpdate = Windows.UI.Notifications.BadgeUpdateManager.CreateBadgeUpdaterForApplication();

var template = Windows.UI.Notifications.BadgeUpdateManager.GetTemplateContent(BadgeTemplateType.BadgeNumber);

var textNode = template.SelectSingleNode(“/badge”);

textNode.Attributes[0].NodeValue = “99″;

var badge = new BadgeNotification(template);

 

badgeUpdate.Update(badge);

 

Happy coding!

In HTML 5, it’s possible to use the attribute required attribute of an input field to specify that this field need to be fill otherwise, a validation error is raised:

<label>Username:<sup>*</sup><input name="username" type="text" placeholder="Username" required="true" autofocus="true"/></label>

image

While this is useful and done automatically, you might prefer to customize the message that is displayed. To do that; you can use the setCustomValidity method:

$(document).ready(function () {
    var intputElements = document.getElementsByTagName("INPUT");
    for (var i = 0; i < intputElements.length; i++) {
        intputElements[i].oninvalid = function (e) {
            e.target.setCustomValidity("");
            if (!e.target.validity.valid) {
                if (e.target.name == "username") {
                    e.target.setCustomValidity("The field 'Username' cannot be left blank");
                }
                else {
                    e.target.setCustomValidity("The field 'Password' cannot be left blank");
                }
            }
        };
    }
})

Now, if an error is raised, the previous JQuery code will check the name of the field and display the correct error message:

image image

Again, a simple tip but very useful if you plan to use HTML 5 forms.

 

Happy coding!