Damien ALEXANDRE

Aller au contenu | Aller au menu | Aller à la recherche

DevBlog

Programmation, parce que oui un peu de sérieux ne fait pas de mal.

Fil des billets - Fil des commentaires

vendredi, juillet 2 2010

Utiliser des fontes SVG avec Raphael.js

Raphael.js est une librairie javascript permettant de dessiner du SVG très simplement, et ce sur tous les navigateurs actuels, IE6 compris (en passant par VML).

Bref ça rox du poulet et je suis actuellement en train de jouer avec. Les limitations imposé par cette compatibilité sont assumées : il n'y a pas de méthode permettant d'utiliser tous les filters SVG comme feGaussianBlur ou feOffset (qui servent à dessiner une ombre portée) par exemple - tout simplement parce que ce n'est pas reproductible sous IE.

Heureusement il est possible d'étendre Raphael pour y ajouter nos propres méthodes et ainsi exploiter pleinement l'intégralité des spécifications SVG (à condition de faire fi de la compatibilité IE, mais on est là pour s'amuser non ?).

Mon besoin était de mettre en place une police personnalisée. Il y a plusieurs solutions :

  • utiliser des police "web safe" (dont le verdana, arial, helvetica...)
  • utiliser @font-face pour déclarer une nouvelle police en CSS
  • utiliser une fonte définie en SVG via la balise <font>

C'est ce dernier cas qui me paraissait le plus fun. J'ai donc trouvé une police libre, et j'ai convertie les glyphes qui m'intéressait en SVG grâce à l'excellent http://www.fontsquirrel.com/ !

 Par contre, l'API de Raphael ne propose pas de méthode pour embedder une fonte externe. Voici ma solution, j'espère qu'elle vous sera utile ;-)

Raphael.fn.registerSvgFont = function (name, path)
{
var fontface = document.createElementNS("http://www.w3.org/2000/svg", "font-face");
fontface.setAttribute('font-family', name);
var fontfacesrc = document.createElementNS("http://www.w3.org/2000/svg", "font-face-src");
var fontfaceuri = document.createElementNS("http://www.w3.org/2000/svg", "font-face-uri");
fontfaceuri.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path);
var fontfaceformat = document.createElementNS("http://www.w3.org/2000/svg", "font-face-format");
fontfaceformat.setAttribute('string', 'svg');
fontfaceuri.appendChild(fontfaceformat)
fontfacesrc.appendChild(fontfaceuri);
fontface.appendChild(fontfacesrc);
return this.defs.appendChild(fontface);
};

A utiliser de la façon suivante dans votre code :

paper.registerSvgFont('pixelsplitter', '../fonts/pixelsplitter-bold-webfont.svg');

createElementNS n'est pas compatible IE6 attention.

mercredi, juin 16 2010

Installer XHProf sous Ubuntu 9.10 et PHP5.3 (dotdeb)

Si comme moi vous utilisez les dépôts dotdeb sur votre Ubuntu / Debian, l'installation de l'extension XHProf peut s'avérer fastidieuse...

Voici la procédure normale :

wget http://pecl.php.net/get/xhprof-0.9.2.tgz
tar xvfz xhprof-0.9.2.tgz
cd xhprof-0.9.2/extension
phpize
./configure
make
sudo make install
sudo make test

On télécharge, on compile, on installe et on test. Si vous n'avez aucun soucis jusque là, GOOD FOR YOU. Vous pouvez modifier votre php.ini et jouer avec XHProf :

[xhprof]
extension=xhprof.so
;
; directory used by default implementation of the iXHProfRuns
; interface (namely, the XHProfRuns_Default class) for storing
; XHProf runs.
;
xhprof.output_dir=(A REMPLIR)

Maintenant si vous êtes comme moi, vous obtiendrez surement une erreur du style :

PHP Warning:  PHP Startup: xhprof: Unable to initialize module
Module compiled with module API=20060613
PHP    compiled with module API=20090626
These options need to match

Normal ! Vous venez de compiler le module avec la mauvaise version de php5-dev (et donc de phpize). Pour vérifier votre version, faite un phpize -v, si vous êtes en PHP 5.3 ça devrait être 20090626.
Un petit tour dans apt-get nous apprend que php5-dev ne peux pas être mis à jour :

libtool (>= 2.2) mais 2.2.6a-4 devra être installé

Cette erreur ne veux pas dire grand chose, je ne l'ai toujours pas compris, mais il existe une solution ! Downgrader à la main libtool et réinstaller le tout (car php5-dev est bien disponible chez dotdeb dans la version qui va bien) :

cd /tmp
wget http://fr.archive.ubuntu.com/ubuntu/pool/main/libt/libtool/libtool_1.5.26-1ubuntu1_i386.deb
sudo apt-get remove libtool
sudo dpkg -i libtool_1.5.26-1ubuntu1_i386.deb
sudo apt-get install php5-dev

Maintenant que vous avez la bonne version de php5-dev tout devrait rouler (vous pouvez recommencer depuis le début de ce post :P), et là j'ai eu le problème avec XHProf mais j'aurais pu avoir le même sur n'importe quel compilation de module.

dimanche, novembre 1 2009

Convertir une fonte TrueType ou OpenType en EOT Embedded OpenType sous Ubuntu Linux

Un titre à ralonge pour un petit tuto rapide qui va vous permettre de convertir vos polices de caractères OpenType (.otf) ou TrueType (.ttf) en Embedded OpenType (.eot), un format propre à Microsoft, utilisé dans Internet Explorer depuis Ubuntu Linux (je dis Ubuntu mais ça devrait fonctionner sur n'importe quel unix).

EOT est le seul format de police accepté par Internet Explorer, il va donc falloir convertir les polices que je souhaite utiliser avec @font-face pour assurer la compatibilité. Microsoft propose un outil pour faire ça (WEFT), mais il est mal fichu et ne tourne pas sous Wine (testé avec Wine 1.0.1 sous Ubuntu 9.10). On va donc se débrouiller autrement !

Let me introduce ttf2eot !

Il s'agit simplement d'un utilitaire en ligne de commande pour OpenTypeUtilities.cpp (une classe qui à la base vient de Chromium, le projet Open Source dont Google Chrome est issu). On télécharge donc les sources, et on fait un petit "make" dans le répertoire :

~/Bureau/ttf2eot-0.0.2-2$ make

Si tout se passe bien le binaire ttf2eot à été compilé (si ça foire, posez vous la question : est-ce que g++ est installé sur mon système ?).

Comme son nom l'indique, on a plus qu'a lui passer un ttf pour qu'il nous génére le eot correspondant :

~/Bureau/ttf2eot-0.0.2-2$ ./ttf2eot < ../delicious-123/Delicious-Roman.ttf > ../delicious-123/Delicious-Roman.eot

Deux paramètre : le fichier d'entrée, et de destination :
$ ./ttf2eot < input.ttf > output.eot
That's all !

Convertir un fichier OpenType

C'est bien beau mais si notre police de caractère n'est pas en TrueType, ttf2eot ne sert à rien. Il n'existe pas d'équivalent pour OpenType, mais il est possible de convertir une fonte OpenType en TrueType. Voici la marche à suivre. On va avoir besoin de fontforge :

$ sudo apt-get install fontforge

Ensuite on écrit un petit script shell qui nous évitera de passer par l'affreuse interface de fontforge (à sauver en otf2ttf.sh par exemple) :

#!/usr/local/bin/fontforge
# Quick and dirty hack: converts a font to truetype (.ttf)
Print("Opening "+$1);
Open($1);
Print("Saving "+$1:r+".ttf");
Generate($1:r+".ttf");
Quit(0);

(Petit script récupéré ici, merci :-))

On s'en sert donc pour convertir notre fichier otf en ttf (et ensuite, on utilise ttf2eot pour enfin obtenir le fichier eot !) :

$ fontforge -script otf2ttf.sh ../delicious-123/Delicious-Roman.otf

Utilisation de @font-face

Si vous vous intéressez à eot c'est que vous allez utiliser @font-face (grillé !), mais savez-vous comment l'utiliser proprement ?

@font-face {
font-family:'Delicious';
src: url('Delicious-Roman.eot');
src: local('Delicious Roman'), local('Delicious'),
url('Delicious-Roman.otf') format('opentype');
}

Pour les explications, veuillez vous référer au billet de Paul Irish, qui est à l'origine de cette solution (qui en gros permet en une seule fois de déclarer une police pour tous les navigateur, sans requête HTTP superflue).

Quelques liens :

  • compatibilité de @font-face (on y voit que Google Chrome n'active pas Web Font par défaut)
  • la police pour laquelle je me suis penché sur le sujet, Delicious (ces conditions d'utilisations autorise @font-face)

dimanche, août 2 2009

jQuery, éviter la soumission multiple d'un formulaire

Le morceau de code qui suit permet d'éviter la soumission multiple d'un formulaire en désactivant l'event submit d'un formulaire et en mettant les input submit en disabled dès la première soumission effectuée.

J'ai été incapable de trouver quelque chose de correct, il existe même des plugins jQuery pour faire ça mais ils sont mauvais et inefficace (oui, on peux soumettre un formulaire autrement que par un click! sur un input:submit...). Donc voilà je publie mon code, il sera peut être utile à toi, visiteur de l'internet mondial :

$(document).ready(function() {
$('form').submit(function() {
if(typeof jQuery.data(this, "disabledOnSubmit") == 'undefined') {
jQuery.data(this, "disabledOnSubmit", { submited: true });
$('input[type=submit], input[type=button]', this).each(function() {
$(this).attr("disabled", "disabled");
});
return true;
}
else
{
return false;
}
});
});

Il s'agit en même temps d'un bon exemple d'utilisation de jQuery.data :)

PS : peux poser des problèmes avec les solution d'autocomplete pour jquery :/

PPS : non ce blog n'est pas mort, il survit.

dimanche, novembre 30 2008

Perspectives de mise en page css avec des tables

Billet initialement publié sur le blog de Clever AgePerspectives de mise en page css avec des tables.

Derrière ce titre accrocheur se cache une propriété CSS qui fait beaucoup parler d’elle ces derniers temps, et pour cause, on va bientôt pouvoir l’utiliser pour de vrai : display:table;.

Historique de la mise en page

Il y a encore de cela quelques années, la grande majorité des sites web qui sortaient des agences étaient mis en pages avec des <table>. Cette balise HTML a l’avantage de grandement faciliter la conception de site en plusieurs colonnes, plusieurs parties, et ont des propriétés difficiles à reproduire avec des div flottantes.

On faisait des sites, ils fonctionnaient bien. Mais cette solution avait quand même ses défauts :

  • même pour un design simple, il était souvent nécessaire d’imbriquer plusieurs tableaux
  • le code devenait vite illisible, au vu du nombre de balises html nécessaires(des <table>, <tr>, <td>, ou encore <thead>, <th>...)
  • beaucoup de code signifie aussi beaucoup de bande passante

Mais le vrai problème, ce sont les standards et la sémantique. Un beau jour on s’est rendu compte qu’une table, ça ne servait pas à mettre en page, mais à présenter des données tabulaires. On s’est alors démené pour changer nos habitudes, et concevoir des sites accessibles, standards et à la sémantique cohérente [1].

La solution la plus souvent utilisée (ici même par exemple) pour concevoir un site en colonne (un menu, un contenu et un autre menu optionnel) se nomment le float et son ami le clear.

Layout classique en 3 colonnes, nov 2008

Technique éprouvée, mais franchement pas idéale, elle montre ses limites en de nombreuses circonstances : qui ne connait pas le Three Pixel Text Jog [2] ou le Doubled Float Margin [3] ? (Des combos uniquement disponibles sous IE)

Cette technique nous oblige aussi à ruser pour avoir visuellement des colonnes de même hauteur. En réalité, les colonnes de ce type site ne sont pas aussi longue que le contenu, on a mis une image en fond pour vous le faire croire [4] !

Elle a aussi la fâcheuse tendance à ne pas être à toute épreuve (si un contenu venait à être plus large que son conteneur, bonjour les dégâts).
Citons aussi la technique "position:absolute", moins problématique mais beaucoup moins souple (il y a aussi cette technique mais je ne la conseille pas :P).

Bref, avec les tables, c’était mieux et c’est là que display:table; intervient.

La propriété display:table;

Apparu dans la première version de CSS2 [5] (c’était il y a 10 ans au moins !), avec tous ces petits amis (inline-table, table-row-group, table-header-group, table-footer-group, table-row, table-column-group, table-column, table-cell, table-caption, mais on ne les verra pas en détails ici), l’implémentation de cette propriété dans les navigateurs web s’est faite très tard, et le couple IE6/IE7 ne la supporte pas [6] (46% de part de marché en octobre 2008 [7], on ne peux pas passer outre).

La bonne nouvelle, c’est le support complet de cette propriété dans IE8 beta 2 (en mode IE8). Si si bonne nouvelle, parce que d’ici trois ans on pourra peut-être enfin l’utiliser à tout va :D

En attendant, petit rappel du fonctionnement global de la propriété.

On va prendre l’exemple le plus utile, un layout en 3 colonnes avec un footer.

La solution à base de flottant est simple et rapide à coder, cependant si je veux que mes colonnes aillent toucher le footer, je suis obligé de tricher (image de fond à la place du fond gris clair) ou d’utiliser du Javascript.

float.html

Alors qu’en reprenant exactement le même code HTML, et en changeant juste un peu de CSS (on remplace les float:left; par des display:table-cell;) on est bon !

table.html

Pour visualiser ces pages web, cliquez sur les images (et utilisez un navigateur respectueux des standards).

Ce qui est magique avec ces propriétés c’est que nous ne somme pas obligés d’utiliser le display:table; et le display:row; avant d’avoir un display:table-cell;, en effet un tableau "anonyme" se place en parent des table-cell automatiquement. Ce dernier se charge d’englober les cellules qui se suivent dans la même ligne, les lignes qui se suivent dans le même tableau.

On pourrait trouver encore de nombreuses applications, les tableaux ont des propriétés vraiment intéressante (le vertical-align qui permet d’aligner n’importe quoi verticalement par exemple).

Est-ce vraiment utile et pouvons-nous l’utiliser ?

Comme je le disais en introduction, ces propriétés ne fonctionnent pas sous IE<8, bien sûr il existe des alternatives à base de hack mais elles sont complexes et difficiles à mettre en place, KISS [8].

Utiliser la magie des propriétés de table est techniquement envisageable (on peut tout à fait imaginer utiliser les floats pour IE, et garder les display:table; pour les navigateurs récents, mon code HTML est strictement le même pour les deux cas), mais cela relève plus d’un exercice de style pour site personnel que d’un choix pertinent. Utiliser cette technique à l’heure actuelle sur un site professionnel serait une perte de temps (et d’argent). En effet, le gain de temps acquis grâce à la souplesse de cette solution serait aussitôt perdu dans les tentatives de compatibilité avec IE en versions inférieures à la version 8.

En attendant la mort complète et définitive d’IE6 et d’IE7, ne changez pas vos habitudes : la mise en page reste un casse tête :D et la solution à base de floats (ou d’absolute, selon les gouts) a encore de beaux jours devant elle.

La vraie révolution de la mise en page en CSS pointera le bout de son nez avec CSS3, et permettra de définir nos layouts en ASCII !

[1] Pas convaincu ? shouldiusetablesforlayout

[2] Le bug du Three Pixel Text Jog

[3] Le bug du Doubled Float Margin

[4] Technique du Faux Columns

[5] La spécification W3C

[6] Détails de la compatibilité

[7] Les statistiques de W3schools

[8] Qu’est-ce que le KISS ?

dimanche, octobre 26 2008

Cellule de table qui s'élargie en fonction du contenu

J'ai eu affaire récemment à un cas plutôt rare dans la longue liste des bugs de rendu sous IE.
Un input text de largeur exprimé en %, dans une cellule de tableau : si on lui met un contenu long, et sans espace (un email par exemple), la cellule du tableau est poussé en fonction de la longueur du texte de l'input.

Vous avez alors beau vous battre avec tous les overflow, width et autres display le problème est insolvable : les cellules d'un tableau sont prévus pour s'adapter à leur contenu, et IE décide d'agrandir l'input si celui-ci contient une longue chaîne.

La solution c'est la propriété table-layout ! C'est elle qui dit comment le navigateur est censé calculer la largeur des cellules du tableau, elle a 3 valeurs possibles :

  • auto : valeur par défaut, le contenu fait sa place et les width appliqué au tableau ne sont que des valeurs minimale
  • inherit : comme son nom l'indique, c'est papa qui décide
  • fixed : la valeur qui m'a sauvé ! Avec elle, toutes les cellules prennent la même largeur sans se soucier du contenu, et si on spécifie une width, elle est appliqué et respecté.

C'est (je pense) une propriété CSS assez méconnu et c'est pour ça que j'en parle :) (et ça me sert de mémo pour plus tard aussi ;) ), cela dit ça n'explique pas le problème de l'input qui prend la largeur de son contenu.

Les sources de test : sans layout:fixed/avec layout:fixed.

- page 1 de 12