AngularJS et ngOptions : binder une valeur primitive à un tableau d’objet dans un select

La directive select d’AngularJS combinée à l’attribut ngOptions permet de générer une liste d’options pour le tag HTML select à partir d’un tableau ou d’un objet. La valeur sélectionnée étant attachée (bindé) au modèle spécifié par l’attribut ngModel.

<select ng-options="category for category in categories" ng-model="book.category"></select>

Dans cet exemple, la syntaxe utilisée est la suivante : « label for item in array ». « label » est la valeur affichée dans les éléments HTML option, « item » représente un élément du tableau et « array » le tableau de valeurs. Etant donné qu’un tableau JavaScript ne contient pas de clés, le label doit ici avoir le même nom que la valeur. Dans le cas d’un tableau d’objets, ça peut-être n’importe quelle propriété des objets.

Une fois la tableau de valeurs transformé en tableau d’objets, l’écriture est la suivante :

<select ng-options="category.name for category in categories" ng-model="book.category"></select>

L’utilisation basique du ngOptions ne pose pas de problèmes mais ça se complique dès qu’il faut associer le select à une valeur existante. A partir de l’exemple précédent, imaginons que nous récupérons notre livre d’une base de données et que celui-ci ait déjà sa catégorie de précisée. Dans ce cas le select doit ajouter l’attribut « selected » à l’option correspondant à la catégorie du livre.

En gardant exactement la même notation pour le ngOptions et en précisant la catégory du livre, aucune option n’est sélectionnée :

$scope.book.category = 'SF';

Si aucune n’option n’est sélectionnée c’est parce que AngularJS ne sait pas à quel objet la catégory ‘SF’ correspond. Pour lui indiquer sur quelle valeur nous voulons lier la propriété du modèle il faut ajouter la notation « select as ».

<select ng-options="category.name as category.name for category in categories" ng-model="book.category"></select>

De cette façon category.name devient le modèle. Sans le « select as » la comparaison est faite sur l’objet entier.

GruntJS, le script d’automatisation pour le web

Une des bonnes pratiques web consiste à minifier tous les scripts JavaScript et CSS puis à les concaténer afin de ne servir que deux fichiers lorsque le site est en production. Ce a des fins de performances.

Il existe déjà des outils le permettant, tels que Capistrano, Ant, ou le traditionnel script Bash. Depuis début 2012 on entend parler de GruntJS, plus encore ces derniers mois.

GruntJS reprend le même principe qu’Ant, à savoir exécuter des tâches définies par l’utilisateur. Il est basé sur NodeJS et est actuellement disponible en 0.3.9.

L’article qui suit est un tutorial expliquant pas à pas comment installer et configurer GruntJS pour minifier et concaténer les fichiers JavaScript et CSS.

Lire le reste de cet article »

Des bordures CSS sur des tableaux et des images dans Outlook 2007/10/13

Ayant récemment dû intégrer une newsletter HTML, je me suis heurté à un soucis de bordures de tableaux et d’images sous Outlook 2007, Outlook 2010 et Outlook 2013.

Des bordures CSS sur les tableaux HTML dans Outlook

Lorsque l’on style un email HTML, le peu de propriétés CSS supportées doivent être présentes dans l’attribut « style » de l’élément à styler.
Voici le code original utilisé pour créer un tableau avec une bordure. Ce code fonctionne parfaitement sous Gmail, Thunderbird, Yahoo! et bien d’autres, excepté sur les différentes versions d’Outlook citées plus haut :

<table cellpadding="0" cellspacing="0" bgcolor="#dbd7d4" border="0" style="border:2px solid #816d5b;" width="550" align="center">

Après quelques essais il s’avère que l’attribut « border » prend le pas sur la déclaration CSS inline lorsque sa valeur est à 0. Pour remédier à ce problème il suffit simplement d’enlever cet attribut :

<table cellpadding="0" cellspacing="0" bgcolor="#dbd7d4" style="border:2px solid #816d5b;" width="550" align="center">

Cela semble logique. Après tout si l’élément voit son attribut « border » égal à 0 alors il ne semblerait pas normal qu’une bordure CSS s’ajoute à cet élément.
Seulement voilà, il n’y a que Outlook 2007/2010/2013 qui se comportent de cette façon, tous les autres clients affichent correctement la bordure définie en CSS même si l’attribut « border » de l’élément est égal à 0.
En étudiant d’un peu plus près les spécifications CSS, voici ce que l’on trouve, au premier paragraphe de la dernière section des spécifications sur la cascade CSS :

The UA may choose to honor presentational attributes in an HTML source document. If so, these attributes are translated to the corresponding CSS rules with specificity equal to 0, and are treated as if they were inserted at the start of the author style sheet. They may therefore be overridden by subsequent style sheet rules. In a transition phase, this policy will make it easier for stylistic attributes to coexist with style sheets.

Ce paragraphe explique que s’il existe des attributs permettant de styler des éléments (tels que « border  » ou « bordercolor »), ces attributs sont convertis en CSS puis sont traités comme si ils étaient ajoutés au début de la CSS de la page. Ces attributs se font donc écraser par n’importe quel style et sont donc censés être écrasés par un style inline qui a la priorité la plus élevée (si l’on omet le « !important »).

Comme on pouvait ici s’en douter, c’est Outlook qui interprète mal le code.

Des bordures CSS sur les images dans Outlook

Lorsqu’il s’agit d’appliquer dans un email HTML une règle CSS à un élément, la première chose à vérifier est la compatibilité de cette règle avec les principaux clients mails. Une des référence en la matière est le guide de compatibilité CSS de Campaign Monitor qui nous indique que la propriété « border » est compatible avec tous les clients listés, dont Outlook 2007/10/13.

Le code HTML est tout simple :

<img src="#" style="display: block; border: 1px solid black">

Cependant, rien ne s’affiche.

Un petit coup d’oeil à la documentation officielle d’Outlook qui indique également le support complet de cette propriété pour la balise « img ».

Une recherche rapide me conforte dans mon idée. Bien que le support de la propriété CSS « border » sur les balises « img » dans Outlook 2007/10/13 est annoncé sur la doc officielle et dans d’autres tableaux de compatibilité des emails HTML (qui doivent en fait reprendre la documentation), celle-ci ne l’est pas.

La parade pour contourner cette limitation est d’englober l’image dans un tableau :

<table cellpadding="0" cellspacing="0" style="border:1px solid #b53b32;" bgcolor="#f6f6f6" width="217" align="center">
  <tr>
    <td width="217">
      <img src="#" alt="" width="215" border="0" style="display:block" />  
    </td>
  </tr>
</table>

Il faut additionner à la largeur de la cellule et du tableau le nombre de pixels supplémentaires de la bordure.
La seule contrainte de cette méthode étant la taille fixe sur la largeur de l’image.

Plugin jQuery validation : vérifier l’unicité d’un champ

Le plugin de validation jQuery propose une fonction de validation « à distance » en AJAX, utile par exemple pour vérifier l’unicité d’un login (cf. documentation).

Dans le cas d’un login pouvant être modifié par l’utilisateur il est nécessaire de n’appliquer la règle de validation que si celui-ci change. Imaginez un formulaire d’édition des informations d’un utilisateur enregistré en base où l’on peut modifier le login et le mot de passe. Dans le cas où le login ne change pas le formulaire ne passe pas la validation car le login est déjà pris… par la personne qui modifie ses informations.

Pour contourner ce problème j’utilise l’option « depends » qui permet de déclencher une règle de validation uniquement si la dépendance est correcte.

$('#myInput').rules('add', {
	required: true,
	remote: {
		param: {
			url: 'http://url/vers/ma/fonction/de/verification',
			type: 'POST'
		},
		depends: function(el) {
			return $(el).val() != loginValue;
		}
	}
}

« loginValue » est une variable contenant le login actuel, login qui provient du champ texte et qui est stocké à l’initialisation de la page. Si le login actuel est différent du login présent dans l’input lorsque la validation s’effectue, « depends » renvoie « true » et la vérification AJAX s’effectue.

Notez que contrairement à la documentation les paramètres sont passé dans un objet « param ». Après le contournement du bug des classes multiples c’est ici un nouveau bug. Si vous utilisez « depends » dans « remote » les paramètres de l’appel AJAX ne sont pas pris en compte, à moins de passer un nouvel objet « param ».

Sélectionner ou désélectionner toutes les checkboxes avec jQuery

On trouve de nombreux bouts de code permettant, à partir d'une checkbox maître, de sélectionner ou désélectionner toutes ses checkbox enfant, mais beaucoup d'entre eux contiennent de trop nombreuses lignes inutiles.
Voici ce que j'utilise :
$('#checkAll').click(function(){
	$(':checkbox').attr('checked', $(this).attr('checked'));
});

Il vous suffit juste d'adapter les sélecteurs a vos besoins.