<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Code-It &#187; Tips</title>
	<atom:link href="http://lois.di-qual.net/blog/category/tips/feed/" rel="self" type="application/rss+xml" />
	<link>http://lois.di-qual.net/blog</link>
	<description></description>
	<lastBuildDate>Tue, 30 Oct 2012 19:19:29 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Bloquer ou monitorer AJAX à partir d&#8217;un script GreaseMonkey (ou Userscript)</title>
		<link>http://lois.di-qual.net/blog/bloquer-ou-monitorer-ajax-a-partir-dun-script-greasemonkey-ou-userscript/</link>
		<comments>http://lois.di-qual.net/blog/bloquer-ou-monitorer-ajax-a-partir-dun-script-greasemonkey-ou-userscript/#comments</comments>
		<pubDate>Fri, 01 Jun 2012 00:13:05 +0000</pubDate>
		<dc:creator>Loïs Di Qual</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[greasemonkey]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[userscript]]></category>

		<guid isPermaLink="false">http://lois.di-qual.net/blog/?p=60</guid>
		<description><![CDATA[Facebook a récemment ajouté une fonctionnalité qui m&#8217;est très désagréable: la notification de la lecture des messages à l&#8217;expéditeur. Impossible dès lors d&#8217;ignorer un message instantané sans que la personne le sache, or c&#8217;est un droit immuable qui devrait être inscrit au burin dans la roche des droits de l&#8217;homme. Modification de XMLHttpRequest Pour empêcher [...]]]></description>
				<content:encoded><![CDATA[<p>Facebook a récemment ajouté une fonctionnalité qui m&#8217;est très désagréable: la notification de la lecture des messages à l&#8217;expéditeur. Impossible dès lors d&#8217;ignorer un message instantané sans que la personne le sache, or c&#8217;est un droit immuable qui devrait être inscrit au burin dans la roche des droits de l&#8217;homme.</p>
<h2>Modification de XMLHttpRequest</h2>
<p>Pour empêcher ces notifications, il faut empêcher l&#8217;envoi de données vers <code class="codecolorer text default"><span class="text">http(s)://www.facebook.com/ajax/mercury/change_read_status.php</span></code> à partir d&#8217;un script Greasemonkey. Le principe du blocage consiste en la modification de l&#8217;objet <code class="codecolorer text default"><span class="text">XMLHttpRequest</span></code> pour que la méthode <code class="codecolorer text default"><span class="text">open</span></code> n&#8217;autorise pas l&#8217;ouverture du socket vers la page en question:</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// On sauvegarde la méthode open originale</span><br />
window.<span style="color: #660066;">XMLHttpRequest</span>.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">trueOpen</span> <span style="color: #339933;">=</span> window.<span style="color: #660066;">XMLHttpRequest</span>.<span style="color: #660066;">prototype</span>.<span style="color: #000066;">open</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// On modifie la méthode open avec la notre</span><br />
window.<span style="color: #660066;">XMLHttpRequest</span>.<span style="color: #660066;">prototype</span>.<span style="color: #000066;">open</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <br />
&nbsp; <span style="color: #006600; font-style: italic;">// Du code pour bloquer ou logger ce qui se passe</span><br />
&nbsp; <span style="color: #006600; font-style: italic;">// On peut notamment regarder ce qu'il y a dans arguments</span><br />
&nbsp; <span style="color: #006600; font-style: italic;">// pour bloquer: return;</span><br />
<br />
&nbsp; <span style="color: #006600; font-style: italic;">// Si on ne souhaite pas bloquer l'ouverture du socket,</span><br />
&nbsp; <span style="color: #006600; font-style: italic;">// on fait appel à la méthode originale</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">trueOpen</span>.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> arguments<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Vous pouvez ainsi intercepter chaque appel aux méthodes de <code class="codecolorer text default"><span class="text">XMLHttpRequest</span></code>, et les bloquer ou les rerouter à votre guise. Pour la liste complète des méthodes en question, je vous invite à consulter <a href="http://www.w3.org/TR/XMLHttpRequest">sa documentation W3C</a>.</p>
<p>Dans le cas d&#8217;un blocage (pas d&#8217;appel à <code class="codecolorer text default"><span class="text">trueOpen</span></code>), voici ce qu&#8217;il va se passer du côté de la page monitorée:</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// Instanciation normale de notre objet</span><br />
<span style="color: #003366; font-weight: bold;">var</span> xhr <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> XMLHttpRequest<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #006600; font-style: italic;">// Rien ne se passe, l'instance de xhr n'est pas modifiée et le socket n'est pas ouvert</span><br />
xhr.<span style="color: #000066;">open</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;get&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;page_bloquee.html?param=1&quot;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #006600; font-style: italic;">// Le send échoue car le socket n'est pas ouvert</span><br />
xhr.<span style="color: #660066;">send</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span></div></td></tr></tbody></table></div>
<p>L&#8217;appel à <code class="codecolorer text default"><span class="text">xhr.send</span></code> ne provoque aucune erreur, du moins sous Chrome.</p>
<h2>Le script Greasemonkey</h2>
<p>Le script abordé précédemment suppose que vous soyez dans le scope de la page dont vous souhaitez monitorer les appels AJAX. Ce n&#8217;est pas le cas pour les scripts GreaseMonkey. Comme expliqué très judicieusement <a href="http://stackoverflow.com/a/10828021/646960">dans ce post sur StackOverflow</a>, Firefox et Chrome exécutent ces scripts dans une sandbox qui ne permet pas d&#8217;accéder à l&#8217;environnement javascript de la page concernée.</p>
<p>Néanmoins, il existe une méthode assez simple pour sortir de cette sandbox: injecter un élément <code class="codecolorer text default"><span class="text">script</span></code> dans la page en question qui exécutera le code de notre choix.</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">function</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #006600; font-style: italic;">// Notre code précédent</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// On crée un élément &lt;script&gt;&lt;/script&gt; et on l'injecte dans la page à contrôler</span><br />
<span style="color: #006600; font-style: italic;">// Dans cet élément, on copie la fonction main afin qu'elle soit exécutée</span><br />
<span style="color: #003366; font-weight: bold;">var</span> script <span style="color: #339933;">=</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;script&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
script.<span style="color: #660066;">textContent</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;(&quot;</span> <span style="color: #339933;">+</span> main.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;)();&quot;</span><span style="color: #339933;">;</span><br />
document.<span style="color: #660066;">body</span>.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span>script<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<h2>Le code final</h2>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">function</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; window.<span style="color: #660066;">XMLHttpRequest</span>.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">trueOpen</span> <span style="color: #339933;">=</span> window.<span style="color: #660066;">XMLHttpRequest</span>.<span style="color: #660066;">prototype</span>.<span style="color: #000066;">open</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; window.<span style="color: #660066;">XMLHttpRequest</span>.<span style="color: #660066;">prototype</span>.<span style="color: #000066;">open</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// ...</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// this.trueOpen.apply(this, arguments);</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> script <span style="color: #339933;">=</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;script&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
script.<span style="color: #660066;">textContent</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;(&quot;</span> <span style="color: #339933;">+</span> main.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;)();&quot;</span><span style="color: #339933;">;</span><br />
document.<span style="color: #660066;">body</span>.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span>script<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>En ce qui concerne le blocage de la notification facebook, voici <a href="https://github.com/ldiqual/facebook-read-status-disabler">facebook-read-status-disabler</a>. Il est également à noter que ce monitoring ne fonctionnera pas avec Internet Explorer car celui-ci utilise un autre objet pour les requêtes AJAX. Un script plus complet est disponible sur github: <a href="https://github.com/creotiv/AJAX-calls-intercepter">AJAX Calls Intercepter</a>, avec notamment la prise en compte d&#8217;Internet Explorer.</p>
]]></content:encoded>
			<wfw:commentRss>http://lois.di-qual.net/blog/bloquer-ou-monitorer-ajax-a-partir-dun-script-greasemonkey-ou-userscript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Un PDF à l&#8217;image de votre CV en ligne avec wkpdf</title>
		<link>http://lois.di-qual.net/blog/un-pdf-a-limage-de-votre-cv-en-ligne/</link>
		<comments>http://lois.di-qual.net/blog/un-pdf-a-limage-de-votre-cv-en-ligne/#comments</comments>
		<pubDate>Thu, 31 May 2012 22:32:46 +0000</pubDate>
		<dc:creator>Loïs Di Qual</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[astuce]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[CV]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[wkpdf]]></category>

		<guid isPermaLink="false">http://127.0.0.1/ldiqual/blog/?p=14</guid>
		<description><![CDATA[Tout comme il est intéressant pour un employeur d&#8217;avoir accès au CV en ligne d&#8217;une potentielle nouvelle recrue, il est également pratique de pouvoir imprimer ce CV dans un format qui convient. La génération automatique d&#8217;un PDF associé au contenu de votre site présente plusieurs avantages: Le PDF est constamment à jour du contenu de [...]]]></description>
				<content:encoded><![CDATA[<p>Tout comme il est intéressant pour un employeur d&#8217;avoir accès au CV en ligne d&#8217;une potentielle nouvelle recrue, il est également pratique de pouvoir imprimer ce CV dans un format qui convient.</p>
<p>La génération automatique d&#8217;un PDF associé au contenu de votre site présente plusieurs avantages:</p>
<ul>
<li>Le PDF est constamment à jour du contenu de votre site</li>
<li>Le PDF adopte le design de votre site</li>
<li>C&#8217;est totalement la classe</li>
</ul>
<p>Voici donc un petit aperçu hautement égocentré de ce que vous pourrez faire:</p>
<p><a href="http://lois.di-qual.net/blog/wp-content/uploads/2012/05/cv_online.png"><img class="alignnone size-medium wp-image-55" title="CV - version en ligne" src="http://lois.di-qual.net/blog/wp-content/uploads/2012/05/cv_online-280x300.png" alt="" width="280" height="300" /></a>       <a href="http://lois.di-qual.net/blog/wp-content/uploads/2012/05/cv_pdf.png"><img class="alignnone size-medium wp-image-56" title="CV - Version PDF" src="http://lois.di-qual.net/blog/wp-content/uploads/2012/05/cv_pdf-300x290.png" alt="" width="300" height="290" /></a></p>
<p>Comme vous l&#8217;aurez remarqué, divers détails graphiques comme l&#8217;arrière-plan gris ou le ruban bleu ont été effacés afin de proposer une version épurée prête à l&#8217;impression.</p>
<p>Pour parvenir à ce résultat, nous allons utiliser un petit logiciel nommé wkpdf associé à une feuille de style spéciale.</p>
<h2>La feuille de style</h2>
<p>Depuis la <a href="http://www.w3.org/TR/html4/present/styles.html#h-14.2.4">version 4 de la norme HTML</a>, il est possible d&#8217;inclure une feuille de style en précisant le type de périphérique auquel elle est adressée. On peut ainsi inclure une une feuille de style spécifique aux télévisions:</p>
<div class="codecolorer-container html4strict twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/link.html"><span style="color: #000000; font-weight: bold;">link</span></a> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;stylesheet&quot;</span> <span style="color: #000066;">media</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;tv&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;css/tv.css&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span></div></td></tr></tbody></table></div>
<p>Il est même possible depuis la version 2 de la norme CSS de déclarer des règles spécifiques à un media directement dans votre feuille de style principale:</p>
<div class="codecolorer-container css twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="css codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">/* Avec @import */</span><br />
<span style="color: #a1a100;">@import url(&quot;tv.css&quot;) tv;</span><br />
<br />
<span style="color: #808080; font-style: italic;">/* Ou avec @media */</span><br />
<span style="color: #a1a100;">@media print {</span><br />
&nbsp; <span style="color: #808080; font-style: italic;">/* Règles spécifiques */</span><br />
<span style="color: #00AA00;">&#125;</span></div></td></tr></tbody></table></div>
<p>Voici la <a href="http://www.w3.org/TR/CSS2/media.html">liste des valeurs</a> de l&#8217;attribut media:</p>
<pre>

<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">all &nbsp; &nbsp; &nbsp; &nbsp; Suitable for all devices.<br />
braille &nbsp; &nbsp; Intended for braille tactile feedback devices.<br />
embossed &nbsp; &nbsp;Intended for paged braille printers.<br />
handheld &nbsp; &nbsp;Intended for handheld devices (typically small screen, limited bandwidth).<br />
print &nbsp; &nbsp; &nbsp; Intended for paged material and for documents viewed on screen in print preview mode.<br />
projection &nbsp;Intended for projected presentations, for example projectors.<br />
screen &nbsp; &nbsp; &nbsp;Intended primarily for color computer screens.<br />
speech &nbsp; &nbsp; &nbsp;Intended for speech synthesizers.<br />
tty &nbsp; &nbsp; &nbsp; &nbsp; Intended for media using a fixed-pitch character grid (such as teletypes, terminals, or portable devices with limited display capabilities). <br />
tv &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Intended for television-type devices (low resolution, color, limited-scrollability screens, sound available).</div></td></tr></tbody></table></div>

</pre>
<p>Il est à noter que si vous ne précisez pas de media, la valeur de l&#8217;attribut est &#8220;all&#8221; (pour tous les périphériques).<br />
Nous voyons ici que la valeur &#8220;print&#8221; permet de personnaliser un document destiné à être imprimé, c&#8217;est donc celui-ci que nous allons utiliser:</p>
<div class="codecolorer-container html4strict twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/link.html"><span style="color: #000000; font-weight: bold;">link</span></a> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;stylesheet&quot;</span> <span style="color: #000066;">media</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;print&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;css/print.css&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span></div></td></tr></tbody></table></div>
<p>Dans cette feuille de style, supprimons tout ce qui n&#8217;est plus nécessaire, par exemple:</p>
<div class="codecolorer-container css twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="css codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">/* Suppression d'un élément inutile */</span><br />
<span style="color: #6666ff;">.classe-de-l-element</span> <span style="color: #00AA00;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">display</span><span style="color: #00AA00;">:</span><span style="color: #993333;">none</span><span style="color: #00AA00;">;</span><br />
<span style="color: #00AA00;">&#125;</span><br />
<br />
<span style="color: #808080; font-style: italic;">/* Suppression de l'arrière plan */</span><br />
body <span style="color: #00AA00;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">background</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">none</span><span style="color: #00AA00;">;</span><br />
<span style="color: #00AA00;">&#125;</span></div></td></tr></tbody></table></div>
<p>Vous pouvez tester ces nouvelles règles en modifiant temporairement l&#8217;attribut media de &#8220;print&#8221; à &#8220;all&#8221;.</p>
<h2>Génération du PDF</h2>
<p>Nous allons utiliser <a href="http://plessl.github.com/wkpdf/">wkpdf</a> pour générer notre fichier. Malheureusement ce dernier n&#8217;est disponible que sur Mac, mais il existe une alternative multiplateforme, <a href="http://code.google.com/p/wkhtmltopdf/">wkhtmltopdf</a>, qui semble fonctionner sur le même principe.</p>
<p>Ces logiciel a un énorme avantage: au lieu de posséder son propre moteur d&#8217;interprétation de la structure HTML, il utilise le fameux Webkit (le moteur de rendu de Chrome et Safari, notamment). Le rendu sera donc fidèle à ce que vous pourrez voir dans un navigateur web conventionnel.</p>
<p>Il vous suffit donc d&#8217;exécuter wkpdf en ligne de commande:</p>
<pre>

<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ wkpdf --source http://monsite.com/ --output cv.pdf --margins 0 --stylesheet-media print --print-background</div></td></tr></tbody></table></div>

</pre>
<p>De plus, si votre site met en place des éléments graphiques à l&#8217;aide de Javascript, ajoutez les arguments suivants:</p>
<pre>

<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--enable-javascript --save-delay [temps_avant_capture_en_secondes]</div></td></tr></tbody></table></div>

</pre>
<p>Vous devriez ainsi obtenir un beau PDF prêt à l&#8217;emploi. Il vous faudra sûrement adapter certaines règles CSS pour que tout tienne sur une page, etc&#8230;</p>
<h2>Bonus: impression directe à partir du site</h2>
<p>La feuille de style &#8220;media=print&#8221; sert également à votre navigateur lors de l&#8217;impression d&#8217;une page. Néanmoins, certaines limitations sont mises en place par la plupart des navigateurs:</p>
<ul>
<li>Les arrières-plans ne sont pas pris en compte. <code class="codecolorer text default"><span class="text">background-color</span></code> et <code class="codecolorer text default"><span class="text">background-image</span></code> ne fonctionneront donc pas.</li>
<li>Le Javascript n&#8217;est pas pris en charge, aucune modification ne pourra être faite dynamiquement avant l&#8217;impression.</li>
</ul>
<blockquote><p>
Note concernant le comportement des navigateurs lors de l&#8217;impression:</p>
<ul>
<li>Aucune référence ou documentation n&#8217;est disponible à ce sujet, du moins pour le moment</li>
<li>Dans certaines versions de Firefox, et sous certains systèmes d&#8217;exploitation, il est possible d&#8217;activer la prise en charge des arrière-plans (couleur et image) ainsi que le Javascript. Là encore, aucune documentation.</li>
<li>Internet Explorer propose un event <code class="codecolorer text default"><span class="text">onbeforeprint</span></code> permettant de modifier le DOM lorsque le navigateur s&#8217;apprête à imprimer. Plus d&#8217;informations <a href="http://msdn.microsoft.com/en-us/library/ie/ms536906(v=vs.85).aspx">par ici</a>.</li>
</ul>
<p>Si vous avez des renseignements supplémentaires concernant les différents comportements adoptés par les navigateurs, n&#8217;hésitez pas à m&#8217;en informer !
</p></blockquote>
<p>Toute l&#8217;astuce consistera donc à remplacer les arrières plans par des images (qui elles seront affichées), ou de tenter de mettre en place une sorte de &#8220;graceful degradation&#8221; afin de simuler certains éléments graphiques. Par exemple, les barres de compétences mises en place sur mon CV ne sont pas pleines lors de leur impression, j&#8217;ai donc dû ajouter un <code class="codecolorer text default"><span class="text">border-color</span></code> pour symboliser les limites de ces dernières.</p>
<h2>Et après ?</h2>
<p>On peut maintenant aisément imaginer un système qui génèrerait automatiquement votre PDF à chaque modification du site web. Si vous utilisez un système de versioning, aucun soucis. Je vous invite à chercher du côté de <code class="codecolorer text default"><span class="text">pre-commit</span></code> si vous gérez tout ça avec svn ou git. Il vous suffira de modifier ces hooks en insérant la commande de génération, et d&#8217;ajouter au commit le fichier PDF ainsi généré.</p>
]]></content:encoded>
			<wfw:commentRss>http://lois.di-qual.net/blog/un-pdf-a-limage-de-votre-cv-en-ligne/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
