I. Description

Wink est un framework JavaScript mobile Open Source et un projet de la fondation Dojo. Il cible avant tout les navigateurs WebKit (que l'on retrouve sur la majorité des smartphones et tablettes du moment) et annonce sa compatibilité avec iOS (iPod touch, iPhone, iPad), Android ou encore BlackBerry. Il a été pensé et construit pour s'adapter aux contraintes et aux spécificités des environnements Web mobile : c'est un framework qui reste ultra-léger (6 ko une fois minimisé et gzippé) et qui fournit, par exemple, toute une couche de gestion des événements "touch" et "gesture". Bien entendu, on y retrouve les fonctions HTML5 comme la géolocalisation ou le stockage local. Toutes les animations (2D et 3D) sont quant à elles réalisées en CSS3.

Wink présente un grand nombre d'éléments graphiques innovants (nuages de tags 3D en HTML, mises en pages originales, composants multitouch...) et se démarque ainsi de ses concurrents directs comme Sencha ou jQuery mobile.

Enfin, Wink se veut être un framework simple d'utilisation, c'est ce que nous allons voir au travers des différents exemples présentés dans cet article.

Ci-dessous, un exemple de composant innovant que l'on retrouvera dans le toolkit:


Cliquez pour lire la vidéo



II. Présentation des packages

Wink a été divisé en huit packages

Wink Core, qui constitue la base du framework, offre toutes les fonctions de base dont un développeur à besoin. Des requêtes XHR à la manipulation du DOM, en passant par la publication d'événements ou la gestion des transformations CSS. C'est aussi dans ce package que l'on retrouve tout ce qui concerne la gestion des événements de toucher.

Wink "ui" rassemble tous les composants graphiques. Certains sont familiers, comme le "date picker" ou le "carousel" alors que d'autres sont plus inattendus comme le nuage de tags HTML en 3D ou le composant "flippage" permettant de naviguer à la manière d'un e-book. C'est dans ce package que l'on retrouve aussi les layouts les plus populaires : sliding panels, scrollers... De quoi donner à sa webapp un Look and Feel d'application native.

Quelques vidéos des composants en action

C'est dans Wink "ux" que l'on retrouve tous les composants d'interaction. Bien sûr, les éléments "touch" et "multitouch" mais aussi des briques comme le gestionnaire de Drag and Drop ou encore l'adaptation du moteur de reconnaissance de forme "$1". Des utilitaires permettant de facilement gérer les changements d'orientation du terminal, ou encore l'historique de navigation du browser sont également présents.

Quelques vidéos des composants en action

Wink "net" inclut un certain nombre de "loaders". Le "JsLoader" peut être utilisé pour charger des ressources JavaScript externes à la volée, ce qui devient vite utile dans un environnement mobile dans lequel on voudra éviter de charger toutes les ressources au démarrage. Ce composant est parfaitement adapté pour le JSONP. Le préchargement d'images et de CSS fait aussi partie de ce package. Comme on le verra plus amplement par la suite, l'instanciation des composants reste simple et suit toujours le même pattern.

Voilà un premier exemple d'instanciation du JsLoader utilisé pour effectuer une requête JSONP
Sélectionnez

jsLoader = new wink.net.JsLoader();
jsLoader.load('http://server2.example.com/getjson?jsonp=parseResponse');
			

Wink "fx" regroupe toutes les librairies CSS permettant de gérer les transformations 2D, 3D ainsi que les animations. Wink "api" fournit des couches d'abstraction aux API HTML5 comme la géolocalisation ou le stockage local et le tout nouveau Wink "mm" (multimédia) contient désormais des players audio et vidéo.

Un tout nouveau composant "Easy Caching" vient compléter le tout. Le but : répliquer le fonctionnement du cache grâce au stockage local et ainsi améliorer jusqu'à dix fois les temps de chargement des WebApps tout en s'affranchissant des problèmes de compatibilité entre les différents OS mobiles.

III. Téléchargement et utilisation

L'intégralité du framework est disponible sur winktoolkit.orgWink. Deux choix s'offrent alors à vous. Soit télécharger la version "code source", soit la version optimisée. Le plus simple est de télécharger cette dernière car elle comprend le core déjà minimisé. Dans cet article, nous utiliserons le version 1.2 optimisée que vous pourrez retrouver içiwink 1.2.

IV. Ma première WebApp

Nous allons maintenant développer notre première WebApp en se basant en partie sur les composants Wink. Le but est d'obtenir une WebApp "classique" contenant un header et un footer fixes, une zone de contenu intermédiaire dans laquelle l'utilisateur pourra scroller. Enfin, un bouton dans le header permettra l'ouverture d'un menu en overlay dans la page.

Au final, nous devrions obtenir un résultat équivalent aux deux captures ci-après :

Image non disponible Image non disponible

Dans un premier temps, nous allons créer un répertoire test qui contiendra notre WebApp. Le fichier principal de notre application sera index.html (situé dans le répertoire test). Pour simplifier, le répertoire wink est recopié directement dans le répertoire test, afin que notre page HTML accède facilement aux ressources.

IV-A. Première étape : positionnement des metas

Nous allons définir deux directives meta dans cette page. La première spécifie que sur iOS, la WebApp va pouvoir s'afficher en mode "WebApp" (plus d'informations sur le mode "WebApp"mode webapp). La seconde va permettre d'adapter la page HTML à la taille de l'écran.

index.html : metas
Sélectionnez

<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=no;" />
				

IV-B. Deuxième étape : création des header et footer

Pour accéder aux fonctionnalités du toolkit, il va tout d'abord falloir rajouter un lien vers le core de Wink (fichier wink.min.js) dans la section "head" de notre WebApp.

index.html : layout
Sélectionnez

<script type="text/javascript" src="../js/wink.min.js"></script>
				

Nous allons maintenant créer le layout de la page. À savoir : un header, une zone de contenu et un footer.

index.html : layout
Sélectionnez

<body>
	<div id="header">My WebApp</div>
	<div id="content">
		Lorem ipsum dolor sit amet...
	</div>
	<div id="footer"> 
	</div>
</body>
				

Enfin, appliquons les styles sur les différents éléments HTML de la page.

index.html : styles
Sélectionnez

#header, #footer {
	position: relative;
	z-index: 0;
	width: 100%;
								
	text-align: center;
	font-size: 1.4em;
	line-height: 2em;
	font-family: Verdana, Helvetica, sans-serif;
}
				
#header {
	background-color: #444755;
	background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(0, #d4d4d4), 
					color-stop(0.05, #c1cbff), color-stop(0.95, #444755), color-stop(1, #23273b));
	color: #fff;
	text-shadow: 0 -0.05em 0 rgba(0, 0, 0, 0.5);
}

#footer {
	background-color: #444755;
	background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(0, #d4d4d4), 
					color-stop(0.05, #c1cbff), color-stop(0.95, #444755), color-stop(1, #23273b));
	color: #fff;
}
							
#content {
	position: relative;
	width: 100%;
	min-height: 300px;
	-webkit-box-sizing: border-box;
	padding: 1em;
	font-size: 1.1em;
	text-align: justify;
	background-color: #fff;
	color: #000;
}

				

IV-C. Troisième étape : ajout du menu

Nous allons maintenant devoir nous servir du composant Popup de Wink (situé dans le répertoire ui/xy/popup). Pour cela, il va donc falloir rajouter dans la section "head" de la WebApp un lien vers le fichier JavaScript du composant Popup et un lien vers la feuille de style qui lui est associée.

index.html : intégration du composant Popup
Sélectionnez

<link rel="stylesheet" href="../../../wink/ui/xy/popup/css/styles.css" type="text/css">
<script type="text/javascript" src="../../../wink/ui/xy/popup/js/popup.js"></script>
				

Une fois cette étape effectuée, il va falloir rajouter un bouton dans le header. C'est sur ce bouton qu'il faudra cliquer pour voir le menu apparaitre. Nous allons donc modifier la structure HTML. Vous remarquerez que nous avons rajouté dans la balise body un handler sur l'événement load qui va permettre, une fois que la page sera chargée, de déclencher l'appel à la fonction "webapp.init" qui sera détaillée ci-après.

index.html
Sélectionnez

<body onload="setTimeout(webapp.init, 1);">
	<div id="header">
		<div class="title"><span>My WebApp</span></div>
		<div id="menuBtn" class="button"><span>menu</span></div>
	</div>
	<div id="content">
		Lorem ipsum dolor sit amet...
	</div>
	<div id="footer"> </div>
</body>
				

Intégrons le style du bouton dans la balise style précédemment créée.

index.html : styles
Sélectionnez

.title {
	display: inline-block;
}
				
.button {
	color: #fff;
	display: inline-block;
	padding: 0em 0.5em;
	height: 2em;
	line-height: 2em;
	font-size: 0.8em;
	background-image: -webkit-gradient(linear, left top, left bottom, from(#7d828c), 
					color-stop(0.5, #303749), color-stop(0.5, #121a2e), to(#121a2e));
	border: solid 0.1em rgba(240, 240, 240, 0.75);
	-webkit-user-select: none;
	-webkit-border-radius: 0.5em;
}
				
#header .button {
	position: absolute;
	top: 0.2em;
	right: 0.2em;
}
				

Reste à instancier et à initialiser le composant Popup, et à gérer les clics sur notre bouton.

Instanciation du composant Popup et gestion des clics sur le bouton contenu dans le header
Sélectionnez

var webapp = 
{
	popup: null,
		
	init: function()
	{
		window.scrollTo(0,0);
		webapp.initPopup();
	},
	
	initPopup: function() 
	{
		webapp.popup = new wink.ui.xy.Popup()
		document.body.appendChild(webapp.popup.getDomNode());
		
		$('menuBtn').onclick = function() {
			var menu = "";
			menu += "<div class='menu'>";
			menu += "Cras vulputate turpis id lorem scelerisque et scelerisque ipsum commodo.";
			menu += "Cras sit amet nibh lacus, sed blandit nunc. Pellentesque aliquet mollis diam, non ultricies metus";
			menu += "laoreet elementum.";
			menu += "</div>";
							
			webapp.popup.popup({
				content: menu,
				top: ($('header').offsetHeight + 20) + "px"
			});
		};
	}
};
				

IV-D. Quatrième étape : les sliding panels

Si vous voulez donner à votre site Web des airs d'application native, vous allez sans doute vouloir que la navigation entre les différentes pages de votre WebApp se fasse en "slidant". Pour cela, Wink offre un composant adapté qui permet de choisir parmi trois types de slides différents ("normal", "cover" et "reveal") tout en spécifiant la durée de l'effet.

Nous allons maintenant devoir utiliser le composant SlidingPanels de Wink (situé dans le répertoire ui/layout/slidingpanels). Encore une fois, il va falloir rajouter dans la section "head" de la WebApp un lien vers le fichier JavaScript du composant ainsi qu'un lien vers la feuille de style qui lui est associée.

index.html : intégration du composant SlidingPanels
Sélectionnez

<link rel="stylesheet" href="../../../wink/ui/layout/slidingpanels/css/styles.css" type="text/css">
<script type="text/javascript" src="../../../wink/ui/layout/slidingpanels/js/slidingpanels.js"></script>
				

Le corps du document HTML doit aussi être modifié en fonction pour intégrer la notion de page. On pensera à bien séparer les pages identifiées par une 'div' (page1, page2) de leur contenu via une autre div (content1, content2) ; ceci afin de pouvoir associer le style souhaité au contenu sans modifier le style des pages qui est propre au fonctionnement du composant. Il nous faut aussi des boutons pour pouvoir naviguer à travers les pages. Nous allons intégrer cette fonctionnalité dans le footer de la WebApp.

index.html
Sélectionnez

<body onload="setTimeout(webapp.init, 1);">
	<div id="header">
		<div class="title"><span>My WebApp</span></div>
		<div id="menuBtn" class="button"><span>menu</span></div>
	</div>
	<div id="content">
		<div id="page1">
			<div id="content1" class="pageContent">
				Lorem ipsum dolor sit amet ...
			</div>
		</div>
		<div id="page2">
			<div id="content2" class="pageContent">
				Aliquam vehicula scelerisque ...
			</div>
		</div>
	</div>
	<div id="footer">
		<div id="previousBtn" class="button hidden"><span>previous</span></div>
		<div id="nextBtn" class="button"><span>next</span></div>
	</div>
</body>
				

Intégrons ensuite les styles de nos pages

index.html : styles
Sélectionnez

.pageContent {
	min-height: 300px;
	
	padding: 1em;
	font-size: 1.1em;
	text-align: justify;
	
	-webkit-box-sizing: border-box;
}

#content1 {
	background-color: #fff;
	color: #000;
}

#content2 {
	background-color: #000;
	color: #fff;
}
				

Reste à déclencher la création du composant SlidingPanels, en JavaScript, au démarrage de l'application. Reste aussi à gérer les boutons "suivant" et "précédent" qui permettront de naviguer dans la webapp. Pour cela nous allons rajouter plusieurs méthodes et modifier la fonction "init".

Instanciation du composant SlidingPanels et gestion des clics sur les boutons suivant/précédent
Sélectionnez

var webapp = 
{
	popup: null,
		
	init: function()
	{
		window.scrollTo(0,0);
		webapp.initSize();
		webapp.initPopup();
		webapp.initPanels();
						
		$('nextBtn').onclick = webapp.next;
		$('previousBtn').onclick = webapp.previous;
	},
	
	initPopup: function() 
	{
		webapp.popup = new wink.ui.xy.Popup()
		document.body.appendChild(webapp.popup.getDomNode());
		
		$('menuBtn').onclick = function() {
			var menu = "";
			menu += "<div class='menu'>";
			menu += "Cras vulputate turpis id lorem scelerisque et scelerisque ipsum commodo.";
			menu += "Cras sit amet nibh lacus, sed blandit nunc. Pellentesque aliquet mollis diam, non ultricies metus";
			menu += "laoreet elementum.";
			menu += "</div>";
							
			webapp.popup.popup({
				content: menu,
				top: ($('header').offsetHeight + 20) + "px"
			});
		};
	},
	
	initPanels: function()
	{
		webapp.slidingPanels = new wink.ui.layout.SlidingPanels(
		{
			'duration': 500,
			'pages': [ 'page1', 'page2' ]
		});
		
		$('content').appendChild(webapp.slidingPanels.getDomNode());
	},
	
	next: function() 
	{
		wink.addClass($('nextBtn'), "hidden");
		wink.removeClass($('previousBtn'), "hidden");
	
		webapp.slidingPanels.slideTo('page2');
	},
	
	previous: function() 
	{
		wink.removeClass($('nextBtn'), "hidden");
		wink.addClass($('previousBtn'), "hidden");
	
		webapp.slidingPanels.slideBack();
	},
	
	initSize: function() 
	{
		$('content').style.height = page1.offsetHeight + "px";
	}
};
				

IV-E. Cinquième étape : le scroller (header et footer fixes)

Pour terminer la WebApp et lui permettre d'avoir un comportement proche de celui d'une application native, nous allons utiliser le composant Scroller. Il va nous permettre de garder les header et footer fixes tout en pouvant naviguer dans nos deux pages.

index.html : intégration du composant Slider
Sélectionnez

<script type="text/javascript" src="../../../wink/ux/window/js/window.js"></script>
<script type="text/javascript" src="../../../wink/ux/movementtracker/js/movementtracker.js"></script>
<script type="text/javascript" src="../../../wink/ux/inertia/js/inertia.js"></script>
<script type="text/javascript" src="../../../wink/ui/layout/scroller/js/scroller.js"></script>
				

Pour utiliser ce composant, il va simplement falloir rajouter son instanciation à l'initialisation de la WebApp.

Instanciation du composant Scroller
Sélectionnez

var webapp = 
{
	popup: null,
		
	init: function()
	{
		window.scrollTo(0,0);
		webapp.initSize();
		webapp.initScroller();
		webapp.initPopup();
		webapp.initPanels();
						
		$('nextBtn').onclick = webapp.next;
		$('previousBtn').onclick = webapp.previous;
	},
	
	initPopup: function() 
	{
		webapp.popup = new wink.ui.xy.Popup()
		document.body.appendChild(webapp.popup.getDomNode());
		
		$('menuBtn').onclick = function() {
			var menu = "";
			menu += "<div class='menu'>";
			menu += "Cras vulputate turpis id lorem scelerisque et scelerisque ipsum commodo.";
			menu += "Cras sit amet nibh lacus, sed blandit nunc. Pellentesque aliquet mollis diam, non ultricies metus";
			menu += "laoreet elementum.";
			menu += "</div>";
							
			webapp.popup.popup({
				content: menu,
				top: ($('header').offsetHeight + 20) + "px"
			});
		};
	},
	
	initPanels: function()
	{
		webapp.slidingPanels = new wink.ui.layout.SlidingPanels(
		{
			'duration': 500,
			'pages': [ 'page1', 'page2' ]
		});
		
		$('content').appendChild(webapp.slidingPanels.getDomNode());
	},
	
	initScroller: function() 
	{
		webapp.scroller1 = new wink.ui.layout.Scroller(
		{
			target: "content1",
			direction: "y"
		});
		
		webapp.scroller2 = new wink.ui.layout.Scroller(
		{
			target: "content2",
			direction: "y",
			scrollbars: {
				backgroundColor: 'rgba(255, 255, 255, 0.8)',
				borderColor: 'rgba(255, 255, 255, 0.9)'
			}
		});
	},
	
	next: function() 
	{
		wink.addClass($('nextBtn'), "hidden");
		wink.removeClass($('previousBtn'), "hidden");
	
		webapp.slidingPanels.slideTo('page2');
	},
	
	previous: function() 
	{
		wink.removeClass($('nextBtn'), "hidden");
		wink.addClass($('previousBtn'), "hidden");
	
		webapp.slidingPanels.slideBack();
	},
	
	initSize: function() 
	{
		$('content').style.height = page1.offsetHeight + "px";
	}
};
				

V. Pour aller un peu plus loin

D'autres exemples de code sont à retrouver dans la section "tutorialstutoriaux wink" du site de Wink, ainsi que des conseils sur le développement Web mobile.

Un forum de discussion est aussi là pour aider les développeurs à résoudre les problèmes rencontrés avec l'outil.

Enfin, si vous êtes intéressés pour contribuer au projet Wink, n'hésitez pas à contacterget involved ses créateurs.

VI. Remerciements

Merci à Rodrigue Hunel ainsi que eusebe19, Mahefasoa et jacques_jean pour leur relecture.