Archives mensuelles : juillet 2012

Outils CSS3 – HTML5 – JavaScript : Episode 3

Cet article fait suite aux 2 précendents articles su le même sujet :

J’ai un temps pensé appeler cet article Outils CSS3 – HTML5 – JavaScript : la suite de la suite mais je me suis dis qu’au fur et à mesure des articles ça commencerai à être long …

Chargeur de fichier JS/CSS/…

Le chargement de fichier JavaScript par le tag script est bloquant. Quand un fichier de script est chargé, votre page est mise en attente du chargement et de l’exécution de votre fichier. Cela est vrai pour chaque script de votre page. Afin de contourner ce problème, des librairies de chargement de scripts asynchrones ont vu le jour comme :

  • RequireJS : un gestionnaire de fichier qui permet de définir les fichiers à charger via un système de dépendance
  • YepNope.js : Librairie très utilisée pour le chargement de polyfills (mis en avant par Modernizr). Cette librairie permet de charger des fichiers suivant un test booléen (ex : Modernizr.geolocation). Un petit lien vers mon article sur cette librairie
  • HeadJS : loader de script mais pas que (détection de fonctionnalités, détection de navigateur, détection de taille d’écran, …)

Sammy.js

Sammy.js est une librairie JavaScript implémentant REST.
Il permet de créer des applications web avec une gestion de l’historique, des événements personnalisé, des plugins, etc.

Tester son code JS

TypedJS est un outil de tests automatique de vos fonctions JavaScript. Il suffit d’annoter vos fonctions avec les types attendus, TypedJS se charge de tester vos fonctions pour vous afin de vérifier que le type retourné est correct. Attention, il ne s’agit pas d’une librairie permettant de faire des tests unitaires automatisés comme QUnit par exemple.

Framework MVC

J’ai évoqué dans mon article de présentation de knockout des framework MVC comme BackoneJS ou EmberJS. AngularJS, un framework MVC développé par Google, fait pas mal parler de lui en ce moment.

JQuery

Jquery ++ : collection de nouvelles fonctionnalités DOM et d’événements bien pratiques pour jQuery

BootStraps / Initializr

Il s’agit ici de boite à outils/template/Framework pour HTML/CSS/Javascript permettant de démarrer un projet rapidement. De nombreux outils sont inclus par défaut pour vous faciliter la vie (classes CSS, jQuery, page html de base, …).

SpritePad

Une des pratiques permettant un gain de vitesse de chargement d’une page web est la mise en place de sprite. Un Sprite est un fichier composé de plusieurs icônes/images. Le CSS se chargera d’afficher qu’une zone de l’image correspondant à la partie à afficher. Ainsi un seul fichier est chargé. SpritePad permet la génération de Sprite CSS en drag’n drop et génère pour vous le CSS.

Mobilité

Les technologies HTML5/CSS3/JavaScript ont beaucoup de succès notamment du fait de leur compatibilité sur terminaux mobiles (smartphone, tablette). Le debuggage sur ce type de terminaux n’est pas évident. Voici quelques outils pour le faire :

CSS3 Generator

CSS3 Generator : Un générateur de règles CSS très complet (Border-Radius, Gradient, Box-Shadow, Transform, Text-Shadow, …).

Partage de code

Je vous avez parlé de JSFiddle dans un précédent article, un outil de partage de code HTML/CSS/JavaScript. JSBin permet également la même chose.

Guide des bonnes pratiques HTML/CSS par Google

Google a misà disposition un ensemble de bonnes pratiques concernant HTML / CSS et JavaScript. A lire !!

Librairies graphiques

datavisualization.ch est un site qui recense les librairies graphiques pour le web et qui aidera à trouver la librairie qui correspond le mieux à vos attentes.
Highcharts : LA librairie pour faire des graphes en SVG avec un fallback en VML pour IE8 et inférieurs.

Animations CSS

Animate.css : Jeu d’animation en CSS déjà coté à réutiliser et à adapter pour vos projets. Possibilité de créer un fichier ne comportant que les animations dont vous avez besoins.

Javscript : Divers

BankersBox

BankersBox est une librairie facilitant la sauvegarde de donnée coté client.

Hammer

Hammer.js est une librairie pour gérer les « gestures ».

Gestion de raccourcis clavier

MouseTrap : une librairie pour gérer des raccourcis clavier et les binder sur des fonctions

Utilisation de Template JavaScript avec JsRender

L’utilisation de plus en plus grande du JavaScript coté client a fait émerger des « moteurs » de templating. Le principe de ces librairies est de faciliter la génération de code HTML en JavaScript en utilisant des modèles. Cela s’avère très pratique notamment dans le cas de mise à jour d’une page avec le résultat d’un appel AJAX. Le site template-chooser permet de choisir parmi une liste de librairies suivant certains critères. Pour cet article j’utiliserai la librairie JsRender, librairie développée par Boris Moore, un des développeurs de JQuery UI.

Pour notre exemple nous allons récupérer les tweets d’un utilisateur de twitter (user_timeline) que l’on récupérera via une requête AJAX. L’utilisateur est renseigné via une textbox (documentation sur l’API de twitter). Le résultat nous est retourné sous la forme d’un tableau au format JSON.

Installation

Il suffit d’inclure JsRender via la ligne suivante

<script src="include/jsrender.js"></script>

Contexte

Voici ci dessous le code HTML de la page de démo que nous allons utiliser :

<!-- Le formulaire de recherche -->
<form action="#" id="searchForm">
	<label for="twittername">Utilisateur twitter :</label><input type="text" placeholder="username" id="twittername" />
	afficher les RT : <input type="checkbox" checked="checked" id="includeRT" />
	<input type="submit" id="search" value="Rechercher" />
</form>

<!-- Le conteneur -->
<div id="tweets"></div>

Déclaration d’un template

Sans l’utilisation de template, nous sommes obliger de créer nos code HTML soit en créer des élements HTML (createElement) soit en faisant de la concaténation de string.

// sans template
var i = 1;
$(mytweets).each(function () {
  var tweet = this;
  $("#tweets").append("<div class=tweet>" tweet.user.screen_name + "</br>" + tweet.text + "</div>");
});

Par terrible, non ?

Voyons comment utiliser les templates via JsRender.

Il existe plusieurs façon de déclarer un template (modèle) :

  • en JavaScript
  • en pseudo HTML en le spécifiant comme un script de type text/x-jsrender

Voici la déclaration en JavaScript pur :

//Déclaration de notre template
$.templates({ tweetsTemplate : "<div class="tweet">{{>user.screen_name}} </br> {{>text}}</div>" });

En Pseudo HTML :

<script id="tweetsTemplate" type="text/x-jsrender">
<div class="tweet">
		{{:user.screen_name}}  </br>
		{{:text}}</div>
</script>

On peut voir que la description et la maintenance des templates est plus aisée en pseudo HTML, surtout dans le cas de template complexe. Je vous conseille d’utiliser cette méthode de déclaration que nous utiliserons dans la suite de l’article.

Comme vu précédemment, la déclaration d’un template JsRender se fait en HTML avec l’utilisation de tags JSRender se trouvant entre {{ et }}.

Voici les principaux tags :

  • {{:name }} : Rendu sans encodage d’une propriété (name dans notre exemple)
  • {{>name }} : Rendu avec encodage HTML d’une propriété
  • {{for entities.hashtags}} : Parcours d’un tableau (hastags dans notre exemple)
  • {{if test}} … {{else}} {{/if}} : Conditions

Une fois le template défini, celui-ci peut être utilisé pour effectuer le rendu de vos données.

Génération du HTML via le template

Le rendu de données via un template se fait par l’appel à la méthode render.
Nous avons besoin de 3 choses :

  • un template
  • des données
  • un conteneur dans lequel les données vont être rendues
$("#tweets").html($("#tweetsTemplate").render(data));

On peut noter que nous utilisons ici JQuery pour mettre à jour le contenu de notre conteneur (#tweets) mais JsRender est indépendant de JQuery.

Le code complet :

//Abonnement au click du bouton rechercher
$('#search').click(function() {
    //Définition de l'URL du service
    var url='http://api.twitter.com/1/statuses/user_timeline.json?callback=?&amp;include_entities=1&amp;count=10&amp;screen_name=' + $('#twittername').val();
    //Inclusion des retweets
    if ($('#includeRT').is(':checked') ) {
        url += '&amp;include_rts=1';
    }
    //Appel du service REST et affichage des données
    $.getJSON(url, function(data) {
        $("#tweets").html(
            $("#tweetsTemplate").render( data )
        );
    });
});

Aller plus loin avec JsRender

view path

Un objet est rarement plat. Il peut contenir des objets enfants. JsRender permet de parcourir ses objets. On a pu voir dans les exemples précédent que l’accès à une propriété se fait par l’utilisation du point ({{:user.screen_name}}). JsRender fournit également des mots clés spéciaux facilitant l’accès à ces données.
#view fournit un accès à la vue courante, #data un accès au context courant de la vue, #parent permet d’accéder à l’objet parent et #index renvoi la position dans la liste.

Dans l’exemple suivant, nous affichons le numéro du tweet via le mot clé index. On peut également constater que les opérations basiques sont fonctionnelles (addition, soustraction, multiplication, division, comparaison, égalité, …)

<script id="tweetsTemplate" type="text/x-jsrender">
	<div class="tweet">
		<p class="tweetInfo">
			<img src="{{:user.profile_image_url}}" title="{{:user.description}}" />
			{{:#index+1}} : <span class="twitterName">{{:user.screen_name}}</span> ({{:user.name}})</b>
			</p>
		<p class="tweetMessage">{{:text}}</p>
	</div>
</script>

boucles

Il est possible d’itérer sur les collections de nos objets. Dans notre exemple, nous récupérer les hashtags de nos tweets. Nous allons les parcourir afin de les afficher. Nous utilisons la « balise » for :

{{for entities.hashtags }} &nbsp#{{>text}} {{/for}}

sous templates

Il est également possible de définir des templates qui seront appelés par des templates parents. Ainsi nous allons en déclarer un pour les hashtags et l’appeler dans la balise for. Le code en devient donc beaucoup plus simple, lisible et maintenable.

la définition du template

<script id="hashtagsTemplate" type="text/x-jsrender">
    &nbsp#{{>text}}
</script>

L’appel du template se fait via l’attribut tmpl …

hashtags : {{for entities.hashtags tmpl="#hashtagsTemplate" /}}

Conditions (if)

JsRender supporte les conditions if/else. Voici un exemple qui teste si le tweet est un retweet et ajoute la classe retweet à notre élément p.

<p class="tweetMessage {{if retweeted_status}} retweet{{/if}}">{{:text}}</br>

externalisation

Dans le cadre d’un site complexe, vos templates pourront être utilisés dans plusieurs pages. Il devient alors nécessaire d’externaliser vos scripts afin de ne déclarer qu’une seule fois ceux ci et de les charger dans les pages correspondantes.

Je vais reprendre ici une fonction issus d’un article de John Papa qui permet de charger des templates, présenté dans un article (cf Liens). Ceux-ci doivent se trouver dans le fichier /templates. de votre site, commencer par un underscore et avoir l’extension .tmpl.html.

my.utils = (function () {
      var
        formatTemplatePath = function (name) {
          return "/templates/_" + name + ".tmpl.html";
        },
        renderTemplate = function (tmplName, targetSelector, data) {
          var file = formatTemplatePath(tmplName);
          $.get(file, null, function (template) {
            var tmpl = $.templates(template);
            var htmlString = tmpl.render(data);
            if (targetSelector) {
              $(targetSelector).html(htmlString);
            }
            return htmlString;
              });
            };
        return {
          formatTemplatePath: formatTemplatePath,
            renderExternalTemplate: renderTemplate
        };
    })()

//Utilisation
my.utils.renderExternalTemplate("tweetTemplate", "#tweets", my.vm);

Voici le page de démo avec un style inspiré de l’interface Métro de Windows 8.

Conclusion

JsRender est un moteur de template très puissant et extensible. Il permet également la compilation de template, un mode permettant l’autorisation de code JavaScript dans les templates, helpers, converters. De plus il permet une séparation entre la présentation de vos données et la gestion de celles ci.