Applications modernes

Maîtrise des contrôles et des paramètres dans les applications du Windows Store créées avec JavaScript

Rachel Appel

Rachel AppelLes expériences utilisateur exceptionnelles présentent les données aux utilisateurs de façon naturelle et intuitive quel que soit le facteur de forme. Pour créer des expériences modernes, des API actualisées sont nécessaires à la présentation des données et des contenus. Dans les applications du Windows Store, la quantité de code requise et la complexité des contrôles dépendent du type d'application créé, qu'il s'agisse d'un jeu, d'une application sociale, financière ou de productivité. Les contrôles de la Bibliothèque Windows pour JavaScript (WinJS) sont simples à maîtriser pour les développeurs qui créent des applications du Windows Store avec JavaScript et ils font l'objet de cet article.

Windows 8 apporte un nouveau paradigme et de nouveaux contrôles d'interface utilisateur

Les applications du Windows Store ont une apparence et un comportement extrêmement différents de ceux des programmes exécutés dans les versions précédentes de Windows. Windows a connu de nombreuses améliorations, à commencer par la nouvelle page de démarrage remplie de vignettes dynamiques qui constitue votre première interaction avec les applications. Parmi les autres modifications évidentes, citons nomment l'exécution des applications du Windows Store en mode plein écran ou en vue ancrée, le placement du contenu à l'avant et au centre, tandis que les commandes et les menus restent mis de côté jusqu'à ce que l'utilisateur les demande.

Les éléments de l'interface utilisateur Windows tels que les boutons de réduction, d'agrandissement et de fermeture qui étaient partout auparavant n'existent plus dans les applications du Windows Store dans la mesure où les balayages tactiles et les mouvements de souris les ont rendus inutiles. Pour fermer une application, vous devez uniquement balayer ou garder le bouton de la souris appuyé du haut de l'écran vers le bas. Même les menus ne sont plus un élément essentiel situé en haut de chaque écran. Dans les applications du Windows Store, les menus restent mis de côté jusqu'à ce qu'un balayage tactile ou un geste de souris ne les révèle dans une barre de l'application située en bas, comme illustré à la figure 1 qui présente une petite application de compte à rebours à titre d'exemple.

The AppBar at the Bottom of the App
Figure 1 La barre de l'application située en bas de l'application

Comme vous pouvez le constater à la figure 1, les menus sont absents et les éléments de menus apparaissent essentiellement sous forme de graphiques avec un peu de texte, à l'inverse des menus traditionnels qui étaient essentiellement constitués de texte et comportaient parfois des graphiques. Ces éléments ont aussi très exactement la taille d'un doigt. Si vous avez besoin de plus d'espace pour les options et que le bas de l'écran ne suffit pas, vous pouvez placer une barre de navigation qui est une simple barre de l'application située en haut de la page.

La navigation dans les menus Windows traditionnels peut parfois être extrêmement pénible. Nous avons tous eu un mouvement de recul face à un programme avec un menu en cascade comportant jusqu'à 13 niveaux qui vous font même oublier ce que vous recherchiez initialement. Dans les applications du Windows Store, la navigation s'intègre au contenu car les gestes tactiles et des souris sur les éléments ListView appellent d'autres pages. Les gestes de pincement et la touche Ctrl + la roue de la souris activent le zoom sémantique (bit.ly/16IDtdi), qui est à la fois un contrôle et un paradigme de navigation dans les applications du Windows Store. SemanticZoom fait partie de la liste complète des contrôles WinJS (bit.ly/w1jLM5).

Utilisation des éléments HTML et des contrôles WinJS

Il existe deux types de contrôles principaux dans les applications du Windows Store qui utilisent JavaScript : les éléments HTML standard et les contrôles WinJS. Les contrôles WinJS sont du HTML combiné à du JavaScript précréé qui étend la façon dont les éléments HTML se présentent ou se comportent. Dans la mesure où il s'agit de HTML, vous pouvez donner un style aux contrôles WinJS à l'aide de CSS. La figure 2 présente un contrôle WinJS de base, DatePicker, un contrôle composé de plusieurs contrôles DropDown représentant le jour, le mois et l'année. Vous voyez s'afficher la sortie par défaut du code ci-après :

<span id="eventDate" data-win-control="WinJS.UI.DatePicker" />

The WinJS DatePicker Control
Figure 2 Contrôle WinJS DatePicker

Il est évident que le contrôle DatePicker de la figure 2 n'a aucun style à l'exception des styles WinJS par défaut, mais vous pouvez modifier cet aspect en remplaçant également les sélecteurs CSS WinJS .win-datepicker-date, .win-datepicker-month et .win-datepicker-year. .win-datepicker vous permet de donner un style à tout le contrôle.

Le fonctionnement de DatePicker (ou tout contrôle WinJS) est lié aux attributs data-* HTML5, à savoir à l'attribut data-win-control. Ce dernier définit quel type de contrôle sera rendu par WinJS. C'est la raison pour laquelle, lorsque vous définissez la valeur de l'attribut data-win-control sur WinJS.UI.DatePicker, le contrôle rend les listes déroulantes présentées à la figure 2. L'attribut data-win-options vous permet de définir des propriétés supplémentaires sur les contrôles. Par exemple, sur DatePicker, vous pouvez définir data-win-options pour la date affichée par défaut et les plages de date maximum et minimum. Bien qu'il se nomme DatePicker, vous pouvez modifier ce contrôle de façon à capturer le temps, par exemple les heures, les minutes et les secondes.

Dans la mesure où WinJS crée et rend la sortie de contrôle finale, le HTML au moment de la conception et celui au moment de l'exécution ont une apparence relativement différente. La figure 3 présente le HTML injecté par WinJS dans l'élément hôte lors de l'exécution. Vous pouvez visualiser ce code dans l'Explorateur DOM (Déboguer | Windows | Explorateur DOM).

Figure 3 DatePicker rend trois listes déroulantes comportant des options de date, mois et année

<span class="win-datepicker" id="eventDate" role="group"
   lang="en-US" dir="ltr" data-win-control="WinJS.UI.DatePicker">
<select tabindex="0" class="win-datepicker-month win-order0"
   aria-label="Select Month">
<option value="January">January</option>
<option value="February">February</option>
<option value="March">March</option>
<option value="April">April</option>
<!-- more <options> that show the other months -->
</select>
<select tabindex="0" class="win-datepicker-date win-order1"
   aria-label="Select Day">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<!-- more <options> that  show day numbers -->
</select>
<select tabindex="0" class="win-datepicker-year win-order2"
   aria-label="Select Year">
<option value="1913">1913</option>
<option value="1914">1914</option>
<option value="1915">1915</option>
<option value="1916">1916</option>
<!—more <options> that show years -->
<option value="2112">2112</option>
<option value="2113">2113</option>
</select>

Le code qui accompagne les contrôles WinJS tels que DatePicker se trouve dans un fichier situé dans <RacineProjet>\References\Windows Library for JavaScript 1.0\js\ui.js, avec quelques amis WinJS de base. Vous remarquerez qu'il s'agit de la même référence <script> que celle requise dans l'élément <head> des pages de l'application du Windows Store, à savoir :

<script src="//Microsoft.WinJS.1.0/js/ui.js"></script>

Si vous modifiez ces fichiers, c'est à vos risques et périls car ils sont composés de code WinJS principal.

Tous les contrôles WinJS, y compris DatePicker, sont accessibles lors de l'exécution par l'intermédiaire d'une propriété nommée winControl. Lors de l'exécution, WinJS ajoute à la propriété winControl des propriétés enfants propres au type de contrôle WinJS. Par exemple, ListView contient sa liste d'éléments ou bien vous pouvez demander à un contrôle WinJS.UI.Ratings le classement sélectionné par l'utilisateur. Vous pouvez accéder à la propriété winControl de l'élément de la façon suivante :

var control = document.getElementById("WinJSElementId").winControl

Les boutons, les cases à cocher, les cases d'option, les listes déroulantes, les zones de texte, etc. fonctionnent tous de la même façon que dans une page HTML traditionnelle. Toutefois, l'espace de noms WinJS.UI est rempli de contrôles d'interface utilisateur pour de nombreux scénarios complexes, dont les contrôles de liste qui jouent un rôle très important.

Contrôles de grille et de liste

De nombreux types d'application doivent présenter les données dans une grille ou dans une liste. Il existe donc un contrôle ListView pour ces scénarios. Ce contrôle peut se rendre sous forme de grille ou de liste, avec des regroupements et des tailles d'éléments variables. Le contrôle ListView est non seulement extrêmement flexible, mais il fonctionne parfaitement dans la nouvelle expérience Windows. Il s'ajuste automatiquement à l'écran et place les éléments de la liste dans des lignes et des colonnes de diverses tailles selon la résolution et la taille de l'affichage de l'appareil.

Alors que la plupart des autres contrôles WinJS sont autonomes, les ListView fonctionnent en collaboration avec le HTML correspondant sous forme de modèle. Cela signifie que vous devez configurer le HTML du modèle et le conteneur du contrôle lui-même, comme présenté à la figure 4. Remarquez que les attributs data-win-control du modèle et data-win-options de ListView contiennent des paramètres qui lient ListView et son modèle.

Figure 4 HTML nécessaire à la création de ListView WinJS

<div id="maincontent">     
  <div id="listViewTemplate"
         data-win-control="WinJS.Binding.Template" >
    <div data-win-bind="style.background: color" class="win-item">
      <h1 data-win-bind=" innerText: daysToGo"></h1>
      <h2 class="subtitle" 
             data-win-bind="innerText: eventTitle"></h2><br />
      <h2 class="subtitle-bottom" 
             data-win-bind=" innerText: eventDate"></h2>
    </div>
  </div>
  <div id="listView" data-win-control="WinJS.UI.ListView"
    class="win-listview"
    data-win-options=
    "{ itemDataSource: Data.items.dataSource,
    itemTemplate: select('#listViewTemplate'),
    selectionMode: 'single'}">
  </div>
</div>

La figure 4 contient deux éléments <div>, un premier pour le modèle avec un identificateur de listViewTemplate et ListView lui-même, nommé listView. L'élément listViewTemplate contient des éléments enfants qui représentent différents champs pour chaque élément de la liste ou de la grille, par exemple eventTitle ou eventDate. Si vous observez ListView dans la figure 4, vous constaterez que la propriété itemDataSource est définie sur Data.items.dataSource, ce qui signifie que Data est un espace de noms et que items est un objet WinJS.Binding.List rempli de données. Dans la mesure où JavaScript a recours à des données largement typées, il vous suffit de remplir un tableau d'objets dans le constructeur List qui est ensuite prêt à être lié aux contrôles ListView, de la façon suivante :

var items = [
  { eventTitle: "Rachel's Birthday", 
    eventDate: new Date(2014, 1, 13) },
  { eventTitle: "Rachel's BFF's Birthday", 
    eventDate: new Date(2013, 5, 29) }
];
var list = new WinJS.UI.list(events);

Vous pouvez également avoir recours à la méthode push afin de pousser les éléments dans l'objet List au lieu de passer un tableau au constructeur de List. La meilleure façon de gérer les données dans ListView consiste à exposer les options pertinentes (ajouter, supprimer, etc.) par l'intermédiaire d'un contrôle AppBar.

Barres d'application et commandes

Privilégier le contenu plutôt que l'apparence est un principe de conception important des produits Microsoft. Les barres d'application font partie intégrante de ce principe de conception puisqu'elles ne sont pas visibles et attendent de présenter leurs options lorsque vous en avez besoin. Dans le code, la barre de l'application est simplement un élément <div> qui contient un ou plusieurs éléments <button>, nommés « commandes de la barre de l'application », avec leurs attributs data-win-control définis sur WinJS.UI.AppBarCommand. Comme vous l'aviez probablement deviné, l'attribut data-win-options est ce qui différencie chaque commande AppBar.

Si vous examinez les data-win-options de la figure 5 pour chaque commande AppBar, vous distinguerez l'identificateur, l'étiquette, l'icône et la section de chaque commande. Vous pouvez attribuer des boutons AppBar à la section globale de l'AppBar (qui s'affiche dans la partie inférieure droite de l'écran de l'application) ou définir l'option de section sur « selection » (pour l'afficher dans la partie inférieure gauche). Si vous définissez l'option de section des commandes AppBar sur « selection », vous les rendrez contextuelles, c'est-à-dire disponibles pour une utilisation lorsqu'un utilisateur sélectionne un élément de ListView en balayant ou en cliquant.

Figure 5 Création d'une AppBar

<!-- HTML -->
<div id="appbar" class="win-appbar" 
       data-win-control="WinJS.UI.AppBar">
<button data-win-control="WinJS.UI.AppBarCommand"
   data-win-options="{id:'deleteButton', 
    label:'Delete',
    icon:'delete', section:'selection'}" 
    type="button"></button>
<button data-win-control="WinJS.UI.AppBarCommand"
   data-win-options="{id:'addButton', 
    label:'Add', icon:'add',
    section:'global'}" 
    type="button"></button>
<button 
   data-win-control="WinJS.UI.AppBarCommand"
   data-win-options="{id:'refreshButton',
   label:'Refresh',
   icon:'refresh', 
   section:'global'}" 
   type="button"></button>
</div>
// JavaScript
document.getElementById("addButton").addEventListener(
  "click", this.addButtonClick);
document.getElementById("deleteButton").addEventListener(
  "click", this.deleteButtonClick);
document.getElementById("refreshButton").addEventListener(
  "click", this.refreshButtonClick);

Dans le fichier JavaScript associé de la page HTML, ajoutez les détecteurs d'événements aux boutons AppBar comme vous le feriez pour tout autre élément HTML. Vous n'avez besoin d'aucun détecteur pour que l'AppBar apparaisse puisque celle-ci s'affiche et disparaît automatiquement en réponse aux commandes de l'utilisateur, bien que vous puissiez l'appeler par programme. L'exemple de la figure 5 présente une AppBar complète avec des boutons permettant d'ajouter, de supprimer et d'actualiser des données.

Vous pouvez écrire du code de façon à afficher, masquer, activer et désactiver des boutons de l'AppBar, comme nécessaire dans le cadre de votre scénario. 

Dans la mesure où l'écran tactile est ce qui se fait de mieux, vous avez probablement remarqué que lorsque les éléments d'interface utilisateur et les boîtes de dialogue apparaissent, vous pouvez facilement les faire disparaître en touchant simplement n'importe quelle partie de l'écran, autre que la boîte de dialogue elle-même, ou en cliquant n'importe où. Cette notion de fermeture implicite de la boîte de dialogue est qualifiée de « disparition rapide » et il s'agit du comportement par défaut des boîtes de dialogue et des menus contextuels dans Windows 8 dans la mesure où il est bien plus simple de travailler ainsi pour l'utilisateur que de se servir des boutons de fermeture.

À l'instar des contrôles précédents, Flyout a recours à l'attribut data-win-control pour indiquer qu'il s'agit effectivement d'un contrôle WinJS.UI.Flyout. Les enfants de l'élément <div> Flyout sont rendus dans le menu volant. Par exemple, vous pouvez intégrer un formulaire HTML à un menu volant afin que l'utilisateur puisse indiquer un titre et une date pour l'événement à venir, comme présenté à la figure 6, ce qui vous donne le résultat de la figure 7.  

Figure 6 Menu volant à disparition rapide pour recueillir des informations avec les contrôles WinJS

<!-- HTML  -->
<div id="eventFlyoutPanel" data-win-control="WinJS.UI.Flyout">
  <table width="100%" height="100%">    
    <tr><td>Event Title:</td><td><input type="text"
 id="eventTitle"/></td></tr>
    <tr><td>Event Date:</td><td id="eventDate"
       data-win-control="WinJS.UI.DatePicker"></td></tr>        
    <tr><td> </td><td align="right">
    <input type="button" id="confirmButton" value="Submit" /></td></tr>
    </table>
</div>
// JavaScript
addButtonClick: function () {
  document.getElementById("eventFlyoutPanel").winControl.show(
  "addButton", "top");
}

A Flyout to Collect Information
Figure 7 Menu volant permettant de recueillir des informations

Remarquez que le menu volant de la figure 7 est un simple formulaire HTML. Lorsque l'utilisateur appuie ou clique sur la commande d'ajout de la barre de l'application, le menu volant s'affiche, comme indiqué dans la fonction addButtonClick de la figure 6. Les menus volants apparaissent à l'écran par rapport aux autres contrôles. Ainsi, lorsque vous appelez la méthode winControl.show, vous passez le nom de l'élément de point d'ancrage du contrôle ainsi que l'endroit où le contrôle doit être placé, c'est-à-dire près du bord supérieur ou inférieur du contrôle de point d'ancrage.

L'utilisateur peut appuyer ou cliquer n'importe où hors du menu volant pour faire disparaître celui-ci puisqu'il s'agit d'un contrôle à disparition rapide. Vous remarquerez l'absence manifeste de boîtes de dialogue modales dans les applications du Windows Store, une autre partie intégrante de la philosophie de conception mise en œuvre par Microsoft. Les concepteurs désapprouvent les boîtes de dialogue modales à juste titre : tout ce qui gêne un utilisateur ou limite sa liberté de mouvement est considéré comme un mauvais élément conceptuel.

SettingsFlyout est un autre type de menu volant et constitue un changement considérable par rapport à la façon dont les applications des versions antérieures de Windows géraient les préférences utilisateur.

Paramètres de l'application

Les utilisateurs de Windows connaissent déjà les options de menu Outils | Options ou Aide | À propos de qui lancent des boîtes de dialogue avec tout un labyrinthe de paramètres. Fort heureusement, ces boîtes de dialogue ont été remplacées par quelque chose de plus intuitif pour l'utilisateur dans les applications du Windows Store. Les pages de paramètres et d'informations sont désormais de grands contrôles verticaux de menus volants qui sont appelés lorsque l'utilisateur sélectionne l'icône de paramètres dans les icônes Windows (bit.ly/146cniM).

Les paramètres fonctionnent toujours de la même façon dans les applications du Windows Store. Lorsque l'utilisateur appelle l'icône Paramètres, le même menu volant de paramètres apparaît à droite quelle que soit l'application exécutée. Les liens vers la politique de confidentialité, les préférences utilisateur, l'aide, etc. doivent se trouver dans SettingsFlyout. La création de liens vers vos pages de confidentialité ou d'options ne prend que quelques lignes de code dans l'événement app.onactivated généralement situé dans /js/default.js :

// In default.js, app.onactivated

WinJS.Application.onsettings = function (e) {

  e.detail.applicationcommands =
   { "privacypolicy": { title: "Privacy Policy",
 href: "privacy.html" } };

    WinJS.UI.SettingsFlyout.populateSettings(e);

};

Une fois que l'utilisateur a appuyé ou cliqué sur l'un des liens de paramètres, le menu volant correspondant s'affiche. La figure 8 contient le HTML d'un SettingsFlyout comportant des informations de politique de confidentialité (il est nécessaire d'avoir une politique de confidentialité claire et concise pour publier une application dans le Windows Store).

Figure 8 HTML d'un menu volant de paramètres comportant des informations de politique de confidentialité

<div id="settingsFlyout" 
  data-win-control="WinJS.UI.SettingsFlyout"
  data-win-options="{settingsCommandId:'privacypolicy', width:'narrow'}">
  <div class="win-header" style="background-color:#312e2e">
    <button type="button" onclick="WinJS.UI.SettingsFlyout.show()"
       class="win-backbutton"></button>
    <div class="win-label">Privacy Policy</div>
  </div>
  <div class="win-content">
    <div class="win-settings-section">
      <p>This application does not collect any personal information.</p>
      <p>Internet access is only used to retrieve data from the web,<div id="settingsFlyout" 
  data-win-control="WinJS.UI.SettingsFlyout"
  data-win-options="{settingsCommandId:'privacypolicy', width:'narrow'}">
  <div class="win-header" style="background-color:#312e2e">
    <button type="button" onclick="WinJS.UI.SettingsFlyout.show()"
       class="win-backbutton"></button>
    <div class="win-label">Privacy Policy</div>
  </div>
  <div class="win-content">
    <div class="win-settings-section">
      <p>This application does not collect any personal information.</p>
      <p>Internet access is only used to retrieve data from the web,
         or to allow you to contact the developer:</p>
          <p>
            <a href="mailto:rachel@rachelappel.com">Email Rachel Appel </a>
 <br />
            <a href="http://rachelappel.com/privacy-policy"
             target="_blank">View privacy statement online</a>
          </p>
      </div>
  </div>
</div>

         or to allow you to contact the developer:</p>
          <p>
            <a href="mailto:rachel@rachelappel.com">Email Rachel Appel </a>
 <br />
            <a href="http://rachelappel.com/privacy-policy"
             target="_blank">View privacy statement online</a>
          </p>
      </div>
  </div>
</div>

N'oubliez pas de nommer le fichier des paramètres de politique de confidentialité comme l'argument href utilisé pour enregistrer le menu volant (voir la figure 8).

Les politiques de confidentialité ne sont pas les seuls éléments ajoutés dans les paramètres. Les contrôles SettingsFlyouts peuvent contenir tout HTML valide et ils sont souvent l'hôte des boutons bascule, des cases à cocher et des listes déroulantes. Ils fonctionnent comme les boîtes de dialogue Outils | Options à l'heure actuelle. Toutefois, comme nous l'avons déjà mentionné, il s'agit de contrôles qui, à l'inverse des boîtes de dialogue modales, disparaissent rapidement dès que vous appuyez simplement ailleurs. Le contrôle SemanticZoom est un nouveau paradigme simple du développement d'applications du Windows Store. Il facilite la navigation.

Zoom sémantique

Certaines applications comportent beaucoup de données. Il peut être relativement difficile de les parcourir, notamment lorsqu'elles gèrent un grand nombre de données. Dans ces cas de figure, le zoom sémantique peut être très utile. Il vous permet en effet d'avoir recours à deux modes de visualisation des données : zooms avant et arrière. Le mode de zoom avant, la valeur par défaut, affiche toutes les données disponibles et l'utilisateur doit les parcourir ou les faire défiler pour trouver ce qu'il cherche. Le mode de zoom arrière propose généralement une représentation groupée des données qui permet à l'utilisateur d'accéder à une zone de données, puis d'effectuer un zoom avant sur un élément de donnée spécifique.

SemanticZoom se compose de trois contrôles : le contrôle hôte et les deux contrôles zoomés, comme présenté à la figure 9. Les contrôles enfants doivent implémenter IZoomable pour participer au zoom sémantique. ListView est donc le seul qui fonctionnera pour les applications WinJS.

Figure 9 Code du contrôle SemanticZoom

<div id="semanticZoomDiv" data-win-control="WinJS.UI.SemanticZoom">            
  <!-- The zoomed-in view. -->   
  <div id="zoomedInListView"
    data-win-control="WinJS.UI.ListView"
    data-win-options="{ itemDataSource:
      myData.groupedItemsList.dataSource,
     itemTemplate: select('#mediumListIconTextTemplate'),
     groupHeaderTemplate: select('#headerTemplate'),
     groupDataSource: myData.groupedItemsList.groups.dataSource,
     selectionMode: 'none',
     tapBehavior: 'none',
     swipeBehavior: 'none' }">  </div>
  <!-- The zoomed-out view. -->
  <div id="zoomedOutListView"
    data-win-control="WinJS.UI.ListView"
    data-win-options="{ itemDataSource:
     myData.groupedItemsList.groups.dataSource, itemTemplate:
     select('#semanticZoomTemplate'), selectionMode: 'none',
     tapBehavior: 'invoke', swipeBehavior: 'none' }">
  </div>
</div>

Comme vous pouvez le constater, le zoom sémantique bascule entre deux ListView, ce qui est très pratique pour les utilisateurs et très facile à implémenter pour les développeurs.

Contrôles supplémentaires

Il existe d'autres contrôles (par exemple, la barre de progression, FlipView, les menus contextuels, MessageDialog et Rating) qui font tous partie de la nouvelle expérience Windows, mais je n'aurai pas assez de place pour les aborder ici. Les normes ouvertes telles que HTML5 et ECMAScript 5 (ES5) sont à la base de tout ce qui constitue WinJS. Par conséquent, les basiques du Web, les points d'ancrage et les entrées audio et vidéo HTML5 fonctionnent tous bien dans le cadre de la plateforme de développement des applications du Windows Store.

Rachel Appel est consultante, auteure, mentor et a travaillé pour Microsoft. Elle dispose de plus de 20 ans d'expérience dans le secteur informatique. Elle participe aux conférences majeures du domaine, par exemple Visual Studio Live!, DevConnections, MIX, etc. Elle est experte en développement de solutions répondant aux exigences professionnelles et technologiques, et se concentre sur la pile de développement Microsoft et le Web ouvert. Pour plus d'informations sur Rachel Appel, consultez son site Web à l'adresse rachelappel.com.

 Merci à l'expert technique suivant d'avoir relu cet article : Keith Boyd (Microsoft)