Archives pour la catégorie JavaScript

Windows Metro – Clouder! (5) – Créer un objet SoundCloudService pour structurer son code

Dans le dernier tutorial, on a donné un peu de style à notre application Windows 8 Metro en passant par Microsoft Blend for Visual Studio:

Windows Metro – Clouder! (4) – Donner du style avec Microsoft Blend

Pour l’instant, on a tout codé dans la fonction « ready », notre appel XHR au service SoundCloud et la manipulation de notre vue. Bien sûr, ce ne sera pas le dernier appel au service SoundCloud que l’on va réaliser, on va devoir récupérer des titres selon certains critères (prévus dans l’API SoundCloud), des commentaires, des informations utilisateur, …

Pour éviter de se retrouver avec trop de code / logique dans chaque « page », on va centraliser ces appels XHR dans un objet « SoundCloudService » qui servira uniquement à créer des appels XHR vers SoundCloud.

Création d’objets, de namespaces, notions de « classes »

Pour créer un objet SoundCloudService, vous avez pas mal d’options. Vous avez tout d’abord les méthodes WinJS.Namespace.define et WinJS.Class.define:

Windows Metro – Les fonctions WinJS.Namespace.define et WinJS.Class.define

En gros, WinJS.Namespace.define vous permet de garnir un Namespace avec des propriétés (hors prototype). WinJS.Class.define vous rappellera un peu le système de classe en programmation orientée objet (JavaScript n’a pas de notion de « classes » mais simplement des objets, toujours dynamiques). Vous pouvez créer des « classes » en ajoutant des fonctions (méthodes) et des variables (propriétés) au prototype de l’objet.

Ces méthodes sont simplement des raccourcis vers un fonctionnel JavaScript « classique » du web. A noter une petite spécificité, si vous utilisez ces méthodes, WinJS va marquer toutes les fonctions comme « supportedForProcessing », plus d’informations ici:

Windows Metro – Marker des fonctions comme « supportedForProcessing » pour pouvoir les utiliser dans le markup HTML (data-win-*)

Il y a aussi une autre technique que vous verrez dans de nombreux exemples de chez Microsoft. La technique est d’isoler votre code dans une « self executing anonymous function » qui se définit comme ceci:

(function () {
    "use strict";
	// vars ...
	// fonctions ...
})();

Tout le code qui se trouve dans cette fonction ne sera pas visible de l’extérieur, et c’est le but. Sauf qu’un objet complètement opaque depuis l’extérieur, cela ne sert pas à grand chose. Vous allez donc pouvoir lui déclarer une « API publique », c’est-à-dire des fonctions qui seront visibles depuis l’extérieur de cette fonction.

Cela se fait par un appel à WinJS.Namespace.define, par exemple:

(function () {
    "use strict";
	function someProtectedFunction(){
		// whatnot
	};
	function someNotExposedFunction(){
		// can't see me
	};
	WinJS.Namespace.define("SomeNamespace", {
        somePublicAPIFunction: someProtectedFunction
    });
})();

Vous pourrez ensuite accéder à la fonction par SomeNamespace.somePublicAPIFunction, qui sera une sorte de lien symbolique vers someProtectedFunction. Vous ne pourrez en revanche pas accéder à « someNotExposedFunction depuis l’extérieur car son scope est celui de la fonction.

Si vous n’avez pas tout compris, je vous conseille tout de même de réviser un peu votre JavaScript, cela vous aidera à comprendre les exemples en ligne:

http://bonsaiden.github.com/JavaScript-Garden/

Création de l’objet SoundCloudService

Maintenant que j’ai présenté plusieurs technique, laquelle va-t-on utiliser? Et bien aucune de celles-là, on va la faire « à l’ancienne ». Même si cela parait plus verbeux, on va créer un objet SoundCloudService en définissant son prototype et l’instancier puis on va assigner l’instance dans un namespace applicatif.

La raison de ce choix est assez personnelle, même si les approches proposées par WinJS (ou pas d’autres librairies) semblent plus sexy, au final j’arrive plus à lire un code simple basé sur prototype. Libre à vous de faire différemment (la version originale de Clouder est par exemple créée à partir de la technique des self-executing functions, expliquée plus haut.

Lire la suite

Windows Metro – Retour d’expérience sur la création de l’application Clouder! pour Windows 8 (stack HTML5)

Si vous suivez mon compte twitter @fnicollet, vous avez pu voir que ces dernières semaines, je travaillais sur une application Windows 8 perso. L’application est à présent terminée, prête à être mise sur le Windows 8 Store. Comme il y a encore peu de développeurs qui créent des applications Windows 8, je vais faire un point sur le développement de mon application, les bonnes et les mauvaises surprises.

Windows 8 ne sortira que fin Octobre 2012, vous avez donc le temps de vous y frotter ;).

Si vous l’avez raté, vous pouvez lire mon article résumé sur le développement d’applications « HTML5 » pour Windows 8:

Introduction au développement HTML / JavaScript / CSS pour Windows 8

Clouder! pour SoundCloud

L’application se nomme donc « Clouder! » (merci @iammichiel pour la suggestion) et permet de parcourir les milliers de sons du site soundcloud.com.

Pour présenter l’application, j’ai fait un screencast, plus sympa que des screenshots. Désolé pour le bruit de fond, c’est celui de mon ventilateur qui n’apprécie pas vraiment les VM.

Quelques screenshots quand même:

Pourquoi SoundCloud? Car j’y passe pas mal de temps et qu’ils disposent d’une bonne API, bien documentée permettant de jouer / rechercher les morceaux :

http://developers.soundcloud.com/docs/api/reference

Voici en vrac les fonctionnalités de l’application:

  • écran d’accueil
  • Derniers morceaux joués par l’application (6 max)
  • « Hottest tracks », les tracks les plus populaires de SoundCloud des 3 derniers jours
  • La sélection du développeur :)
  • écran d’une track / playlist
    • Jaquette et information sur le morceau
    • Lecture automatique du titre
    • Accès au profil de l’artiste
    • Possibilité de partager / télécharger le morceau
    • Affichage des commentaires liés au morceaux (clic sur un commentaire = accès à la page de l’utilisateur qui a commenté)
  • écran d’un utilisateur
    • Affichage avatar + location
    • Affichage de ses morceaux partagés sur SoundCloud
    • Affichage de ses morceaux marqués comme « favoris » sur SC
    • Affichage de ses playlists
    • Affichage de ses followings / followers
  • écran des résultats de recherche
    • Affichage des suggestions intégré au système Windows 8
    • Affichage des résulats avec accès à chaque titre
  • bonus
    • Le lecteur audio est présent en permanence dans l’application, il se trouve dans l’AppBar qui peut être affichée / masquée par un click droit (souris) ou par un swipe vers le haut (tablette). Le son n’est pas coupé lors des changements de page dans l’application
    • « Tuile » de l’écran de démarrage Windows Metro dynamique, avec affichage des derniers titres et de leur jaquette
    • Fonctionnalité de partage complètement intégrée à Windows 8

    Durant le développement de cette application, il y a eu du bon et du moins bon. Mon point de vue est celui d’un débutant dans le dév d’application Windows 8 Metro mais ce sera le cas de beaucoup de monde ;).

    Pour le développement de Clouder!, j’ai utilisé la stack « HTML5 » proposée par Microsoft. A noter qu’il est aussi possible de le faire avec les autres langages de la plateforme MS (C# & co).

    La documentation et les samples Microsoft

    Sûrement ce qui est le plus important quand on développe sa première application. La documentation fournie par Microsoft (en ligne) est excellente. Les exemples sont concrets, avec du code dans les différents langages (C#, JS, …), des « QuickStart » bien pratiques et complets. J’ai beaucoup copié de code venant directement de la documentation et cela a souvent fonctionné du premier coup. Les exemples sont nombreux et très fournis  avec beaucoup de scénarios expliqués et implémentés. Et pour ceux qui ne veulent vraiment pas se mettre à l’anglais, une grosse partie de la documentation est même disponible en Français. Les traductions sont un peu douteuses mais elles sont là.

    Bon exemple: ajouter une liste (QuickStart détaillé):

    http://msdn.microsoft.com/en-us/library/windows/apps/hh465496.aspx

    Il est parfois un peu difficile de trouver de l’information car on va tomber sur des sites / blogs qui donnent des exemples en C# alors que l’on développe sur la stack HTML5. Mais les APIs étant sensiblement les mêmes, cela reste une bonne aide. A noter aussi ce ebook gratuit (en cours d’écriture) de très bonne qualité:

    Free ebook: Programming Windows 8 Apps with HTML, CSS, and JavaScript (First Preview)

    Sur ce point, bravo Microsoft.

    Installation de l’environnement de développement

    J’avais fait un billet sur l’installation de la Consumer Preview (qui est maintenant une Release Preview) et son installation dans VMWare:

    Installation de Windows 8 Consumer Preview sur VMware Workstation 8

    Ce n’est pas évident la première fois mais au final pas très laborieux. Le SDK Windows 8 permet d’installer MS Visual Studio Express 2012 RC pour Windows 8 ainsi que Microsoft Blend et les kits de certifications. Pas vraiment de reproches à faire sur ce point, c’est très guidé et cela fonctionne plutôt bien.

    Lire la suite

    Windows Metro – Afficher une liste simple avec le composant WinJS.UI.ListView

    Les derniers articles sur le dev Windows 8 Metro étaient plutôt descriptifs. Pour celui-là, on commence enfin à coder avec le framework WinJS. On va commencer doucement avec l’affichage d’une simple liste. Pour faire encore plus simple, on la peupler avec des données bidons. Plus tard, on verra comment la peupler à partir d’un appel serveur (XHR), ce qui revient au final au même.

    La donnée

    La donnée est une liste de musées, que j’ai emprunté depuis un tutorial jQuery de @nicolasgans. Une simple liste au format JSON, avec quelques informations pour chaque musée:

    {
    	"musees" : [
    		{
    			"id" : "0",
    			"nom" : "Musée d'art moderne de la Ville de Paris",
    			"adresse" : "11, avenue du Président Wilson - Paris 16e",
    			"site" : "mam.paris.fr",
    			"image" : "art_moderne.jpg",
    			"texte" : "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce felis nibh, aliquam in semper quis, accumsan vitae est. Nunc sed urna nunc. Donec congue justo sed purus molestie dignissim. Cras posuere tempor sem quis sodales. Vestibulum varius fringilla accumsan. Suspendisse commodo lectus id justo viverra ultrices. Nullam non orci arcu, vel tincidunt velit. Suspendisse semper suscipit magna. Nullam tempor turpis at justo pulvinar venenatis ut eu elit. Phasellus lacus justo, venenatis id vestibulum at, commodo vehicula arcu. Morbi non ipsum neque."
    		},
    		{
    			"id" : "1",
    			"nom" : "Musée Bourdelle",
    			"adresse" : "16, rue Antoine-Bourdelle - Paris 15e",
    			"site" : "bourdelle.paris.fr",
    			"image" : "bourdelle.jpg",
    			"texte" : "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce felis nibh, aliquam in semper quis, accumsan vitae est. Nunc sed urna nunc. Donec congue justo sed purus molestie dignissim. Cras posuere tempor sem quis sodales. Vestibulum varius fringilla accumsan. Suspendisse commodo lectus id justo viverra ultrices. Nullam non orci arcu, vel tincidunt velit. Suspendisse semper suscipit magna. Nullam tempor turpis at justo pulvinar venenatis ut eu elit. Phasellus lacus justo, venenatis id vestibulum at, commodo vehicula arcu. Morbi non ipsum neque."
    		},

    Création d’un projet Windows 8 Metro

    Ce tutorial assume bien sûr que vous avez une VM avec Windows 8 d’installé ainsi que le SDK + Visual Studio 2011 Express Beta:

    Installation de Windows 8 Consumer Preview sur VMware Workstation 8

    Introduction au développement HTML / JavaScript / CSS pour Windows 8

    C’est parti, File > New Project > JavaScript > Windows Metro style. Choisissez le template « Blank Application »:

    Un petit récap sur les différents templates à votre disposition:

    Windows Metro – Les templates pour application JavaScript (Grid, Navigation, Split, …)

    Patientez un peu et votre projet est créé. Vous devriez avoir le contenu du fichier « default.js » sous les yeux. Lancez donc l’application pour vous assurer du bon fonctionnement avec le bouton « Play » réglé sur Local Machine pour avoir directement le rendu dans Windows Metro.

    Votre application va se lancer et afficher « Content goes here » sur fond noir.

    Ajout d’un composant ListView

    Sortez donc de l’application qui vient de se lancer (Alt-Tab pour switcher rapidement entre le dev et l’application) et revenez dans Visual Studio. Depuis l’arbre « Solution Explorer » à droite, ouvrez le fichier « default.html ». Voici son contenu:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>SimpleList</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>
    
        <!-- SimpleList references -->
        <link href="/css/default.css" rel="stylesheet">
        <script src="/js/default.js"></script>
    </head>
    <body>
        <p>Content goes here</p>
    </body>
    </html>

    On va remplacer le « Content goes here » par notre liste. Contrairement au HMTL « classique », les listes sous Windows 8 de sont pas de simples UL / LI. Au lieu de cela, on va créer un conteneur, un div:

    <body>
        <div></div>
    </body>

    A ce conteneur, on va associer le composant ListView qui va venir « décorer » le div et lui donner son comportement liste. Pour cela, on va référencer le nom complet du composant ListView : WinJS.UI.ListView. On va indiquer ce décorateur dans l’attribut « data-win-control »:

    Voilà, vous avez votre composant ListView. Donnez lui un id « simpleList » pour pouvoir le référencer plus tard:

    <div id="simpleList" data-win-control="WinJS.UI.ListView"></div>

    On va maintenant l’alimenter avec des données.

    Lier une ListView avec des données grâce à WinJS.Binding.List

    Notre donnée est de base dans un tableau JSON. Cependant, on va faire passer ce tableau JSON dans un objet du framework WinJS qui se nomme « WinJS.Binding.List ». Celui-ci va encapsuler la donnée et vous donnez des méthodes d’accès plus pratiques (insérer un élément à un index, supprimer un élément, etc.).

    Le gros avantage de cette manipulation et que vous allez pouvoir créer une liaison dynamique entre votre composant graphique (WinJS.UI.ListView) et votre donnée (WinJS.Binding.List). Ainsi, si la List est modifiée (ajout / suppression d’élément), le composant graphique sera automatiquement mis à jour. Du vrai MVC comme dirait l’autre :).

    Lire la suite

    Windows Metro – Cycle de vie d’une application

    Comme je l’avais dit en introduction, une application Windows 8 style Metro diffère de votre application web classique. Vous devrez notamment jouer avec les APIs offertes par le framework WinJS qui permet de communiquer entre le système est votre application.

    Une application « vit » de son lancement à sa fermeture. Tout ce qui se passe entre représente le cycle de vie de l’application. Notez que comme sur les systèmes mobiles, les applications Metro peuvent être fermées à tout moment si le système à besoin de ressources. Il est donc important de bien gérer la vie et la mort de l’application.

    Code commun à tous les templates applicatifs

    Dans l’article précédent, on a vu les différents templates applicatifs proposés par Visual Studio:

    Windows Metro – Les templates pour application JavaScript (Grid, Navigation, Split, …)

    Tous ces templates contiennent une page (écran) par défaut, nommée « default.html »:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>BlankApp</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>
    
        <!-- BlankApp references -->
        <link href="/css/default.css" rel="stylesheet">
        <script src="/js/default.js"></script>
    </head>
    <body>
        <p>Content goes here</p>
    </body>
    </html>

    Celle-ci référence plusieurs fichiers JavaScript « default.js », notamment ceux du framework WinJS. Elle référence aussi un fichier JavaScript qui va contenir le comportement dynamique de la page. De base, voici ce que contient ce fichier:

    (function () {
        "use strict";
    
        var app = WinJS.Application;
    
        app.onactivated = function (eventObject) {
            if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {
                if (eventObject.detail.previousExecutionState !== Windows.ApplicationModel.Activation.ApplicationExecutionState.terminated) {
                    // TODO: This application has been newly launched. Initialize
                    // your application here.
                } else {
                    // TODO: This application has been reactivated from suspension.
                    // Restore application state here.
                }
                WinJS.UI.processAll();
            }
        };
    
        app.oncheckpoint = function (eventObject) {
            // TODO: This application is about to be suspended. Save any state
            // that needs to persist across suspensions here. You might use the
            // WinJS.Application.sessionState object, which is automatically
            // saved and restored across suspension. If you need to complete an
            // asynchronous operation before your application is suspended, call
            // eventObject.setPromise().
        };
    
        app.start();
    })();

    On a donc une fonction auto-exécutée, pour permettre de « fermer » le scope du bloc de code à l’intérieur. Grâce à cette fonction, les méthodes déclarées à l’intérieur ne sont pas visibles de l’extérieur, une sorte de « private » en JavaScript.

    Petite remarque personnelle, je ne comprend pas vraiment pourquoi Microsoft isole son code comme cela dans tous les exemples. L’utilisation de leur namespace Windows / WinJS suffit à compartimenter le code pour éviter les collisions. Cela rend le code difficile à manipuler par la suite. Bref, j’aurai sûrement pas fait comme cela mais ce n’est pas grave.

    La fonction WinJS.Application.start

    La méthode WinJS.Application.start est appelée dans tous les templates. C’est elle qui va démarrer un processus important dans le cycle de vie (livecycle) de l’application, celui des évènements qui transitent par l’objet WinJS.Application. Parmi ces évènements, on a les évènements provenant du système comme les évènements de lancement nommés « checkpoint » dans le jargon Win Metro.

    La fonction WinJS.Application.oncheckpoint

    Dans le code de base, on définit la fonction WinJS.Application.oncheckpoint. Celle-ci sera appelée par le système quand l’application juste avant sa mise en arrière-plan, pendant la bascule vers une autre application par exemple.

    C’est à ce moment que vous devrez sauvegarder l’état de l’application (navigation / choix utilisateur). En effet, une fois en arrière plan, votre application peut être « tuée » par le système à n’importe quel moment. Si l’utilisateur relance votre application, vous voudrez le renvoyer là où il était auparavant, vous devrez donc sauvegarder les informations importantes pour les recharger plus tard.

    Si vous êtes développeur Flex /AIR, c’est l’équivalent d’un évènement Event.DEACTIVATE propagé sur l’application principale.

    La fonction WinJS.Application.onactivated

    La fonction onactivate est invoquée par le système au lancement de l’application. A celle-ci, l’application passe un objet qui contient des détails sur le contexte de ce lancement. Vous pourrez notamment savoir si c’est le premier lancement de l’application ou si l’utilisateur est simplement repassé sur votre application alors qu’elle était en arrière-plan.

    Pour les devs AIR, c’est l’équivalent de l’évènement flash.events.InvokeEvent.

    La fonction WinJS.UI.processAll

    A la fin de l’appel à onactivated, vous pouvez remarquer que l’on fait appel à WinJS.UI.processAll. Cette méthode est une des pierres angulaires du framework WinJS. En effet, c’est elle qui indique au framework que tous les composants graphiques doivent être rendus / interprétés.

    Comme vous le verrez pas la suite, tout l’interface graphique se fait de manière déclarative par des attributs « data-win-* » sur des éléments HTML. Ces éléments non-standards doivent être interprétés par WinJS qui va les transformer en composants « natifs ».

    Quelques mots sur le fonctionnement de WinJS.UI.processAll

    A l’appel de processAll, WinJS va donc parcourir tout le DOM à le recherche de ces attributs « data-win-* ». Le processus se fait en fait en 2 passes:

    1. WinJS recherche tous les tags ayant un attribut « data-win-control ». On le verra plus tard, dans ces attributs, on définit un « décorateur » au sens Design Pattern du terme. C’est-à-dire que l’on définit une classe qui va venir gérer notre composant, son comportement interne et ses interactions. A chaque attribut « data-win-control », WinJS va instancier ce décorateur et l’associer au composant.
    2. WinJS recherche tous les tags ayant un attribut « data-win-options ». Celui-ci contient les options passées au décorateur instancié en 1/. WinJS va ainsi évaluer toutes les propriétés dynamiques et les setter sur l’instance du décorateur.

    Une fois instancié, le décorateur créé à l’étape 1 est accessible par la propriété « winControl » de l’élément HTML.

    Mon avis personnel sur ce fonctionnement

    Ce fonctionnement est assez atypique et on ne le retrouve pas ce système de décorateur dans le HTML « classique ». Ce système de décorateur est en fait mis en place pour contourner une grosse faiblesse du langage HTML. Le problème avec HTML est que l’on ne peut pas créer de composant ayant son propre contexte d’exécution. Vous ne pouvez pas créer un composant qui contient du JavaScript en interne, propre au composant et ayant pour scope le composant.

    Si vous regardez du côté du framework Flex, vous verrez que l’on peut créer ce genre de composant indépendant, dans un fichier à part. Ayant mangé plusieurs années de développement Flex au quotidien, je peux vous assurer que cela vous facilite la tâche lorsque vous voulez créer des composants réutilisables, en encapsulant son aspect graphique et son comportement (code).

    Si vous lisez ce draft W3C sur les « Web Components », vous verrez que c’est le genre de chose qu’ils essaient de reproduire avec ce qu’ils appelent les « Custom Elements« :

    Introduction to Web Components

    Cela permet aussi de s’échanger facilement des composants / librairies et de les intégrer à un projet. Bref, vous l’avez compris, j’ai adoré le système de composant lorsque je faisais du développement Flex et si ce système avait été adopté dans le monde HTML dès le départ, je pense que le développement web ressemblerait moins à un champ de bataille de librairies :).

    Alors pourquoi Windows y est allé de ses propres attributs? Et bien en fait, ils n’avaient pas vraiment le choix, étant dans un contexte « web », il leur a fallu « broder » avec des propriétés dynamiques qui peuvent être résolues à la volée. Ça parait assez moche au départ mais c’est plutôt malin, car le contexte d’exécution du composant est cloisonné dans la propriété « winControl » de l’élément DOM.

    Voilà, ça en est fini pour mon analyse personnelle, vous pouvez bien sûr utiliser les commentaires pour donner votre avis!