<?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>phpied.com</title>
	<atom:link href="http://www.phpied.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.phpied.com</link>
	<description>Stoyan&#039;s blog about &#60;a href=&#34;/category/xhtml&#34; class=&#34;tag-minor&#34;&#62;(x)html(5)&#60;/a&#62;, &#60;a href=&#34;/category/ajax&#34; class=&#34;tag-major&#34;&#62;ajax&#60;/a&#62;, &#60;a href=&#34;/category/bookmarklets&#34; class=&#34;tag-major&#34;&#62;bookmarklets&#60;/a&#62;, &#60;a href=&#34;/category/browsers&#34; class=&#34;tag-minor&#34;&#62;browsers&#60;/a&#62;, &#60;a href=&#34;/category/css&#34; class=&#34;tag-normal&#34;&#62;css&#60;/a&#62;, &#60;a href=&#34;/category/firebug&#34; class=&#34;tag-minor&#34;&#62;firebug&#60;/a&#62;, &#60;a href=&#34;/category/javascript&#34; class=&#34;tag-numero-uno&#34;&#62;javascript&#60;/a&#62;, &#60;a href=&#34;/category/json&#34; class=&#34;tag-normal&#34;&#62;json&#60;/a&#62;, &#60;a href=&#34;/category/mdb2&#34; class=&#34;tag-minor&#34;&#62;mdb2&#60;/a&#62;, &#60;a href=&#34;/category/mysql&#34; class=&#34;tag-normal&#34;&#62;mysql&#60;/a&#62;, &#60;a href=&#34;/category/pear&#34; class=&#34;tag-numero-uno&#34;&#62;pear&#60;/a&#62;, &#60;a href=&#34;/category/performance&#34; class=&#34;tag-major&#34;&#62;performance&#60;/a&#62;, &#60;a href=&#34;/category/php&#34; class=&#34;tag-numero-uno&#34;&#62;php&#60;/a&#62;, &#60;a href=&#34;/category/phpbb&#34; class=&#34;tag-major&#34;&#62;phpbb&#60;/a&#62;, &#60;a href=&#34;/category/tools&#34; class=&#34;tag-normal&#34;&#62;tools&#60;/a&#62;, &#60;a href=&#34;/category/yslow&#34; class=&#34;tag-minor&#34;&#62;yslow&#60;/a&#62;, &#60;a href=&#34;/category/yui&#34; class=&#34;tag-normal&#34;&#62;yui&#60;/a&#62;, &#60;a href=&#34;/category/writing&#34; class=&#34;tag-minor&#34;&#62;writing&#60;/a&#62;, &#60;a href=&#34;/category/music&#34; class=&#34;tag-major&#34;&#62;music&#60;/a&#62;,... &#60;a href=&#34;/category/life-and-everything&#34; class=&#34;tag-normal&#34;&#62;life and everything&#60;/a&#62;.</description>
	<lastBuildDate>Fri, 20 Jan 2012 22:24:11 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>Wish You a Merry Christmas 2011</title>
		<link>http://www.phpied.com/wish-you-a-merry-christmas-2011/</link>
		<comments>http://www.phpied.com/wish-you-a-merry-christmas-2011/#comments</comments>
		<pubDate>Sat, 24 Dec 2011 11:31:08 +0000</pubDate>
		<dc:creator>Stoyan</dc:creator>
				<category><![CDATA[Music]]></category>

		<guid isPermaLink="false">http://www.phpied.com/?p=1591</guid>
		<description><![CDATA[Here's a cover of We Wish You a Merry Christmas I just did. It's in a Bulgarian (and other Balkan countries) style in 7/8 tempo (and 9/8th at one place). This is me channeling my inner Goran Bregovich We Wish You a Merry Christmas (7/8th and 9/8th) Continuing the tradition (why did I skip last [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.phpied.com/wp-content/uploads/2011/12/tele.jpg" alt="" title="tele" width="637" height="478" class="alignnone size-full wp-image-1593" /></p>
<p>Here's a cover of We Wish You a Merry Christmas I just did. It's in a Bulgarian (and other Balkan countries) style in 7/8 tempo (and 9/8th at one place). This is me channeling my inner Goran Bregovich <img src='http://www.phpied.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a href="/files/music/we-wish-7:8:9:8.mp3">We Wish You a Merry Christmas (7/8th and 9/8th)</a></p>
<p>Continuing the tradition (why did I skip last year?! oh I know, because 7/8 is damn confusing and I failed last year), here are the others:</p>
<ul>
<li><a href="/files/music/feliz-navidad.mp3">Feliz Navidad 2009</a>
</li>
<li><a href="/files/music/jingle-bell.mp3">Jingle Bells 2008</a>
</li>
</ul>
<p>It's amazing to look back over the years and see how little I have grown as a musician and recording technician <img src='http://www.phpied.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /><br />
<script src="http://mediaplayer.yahoo.com/js"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.phpied.com/wish-you-a-merry-christmas-2011/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Imagine</title>
		<link>http://www.phpied.com/imagine/</link>
		<comments>http://www.phpied.com/imagine/#comments</comments>
		<pubDate>Mon, 12 Dec 2011 22:59:31 +0000</pubDate>
		<dc:creator>Stoyan</dc:creator>
				<category><![CDATA[Fun]]></category>

		<guid isPermaLink="false">http://www.phpied.com/?p=1590</guid>
		<description><![CDATA[Challenged by Marcel and inspired by another idea by Nicholas (upcoming, stay tuned!) here's the beginning. Imagine there's no quirksmode It's easy if IE6 dies No Trident below us And all the data URIs Imagine all the web devs coding for today You may say I'm a dreamer But I'm not the only one I [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://calendar.perfplanet.com/2011/pure-css3-images-hmm-maybe-later/">Challenged by Marcel</a> and inspired by another idea by <a href="http://www.nczonline.net/">Nicholas</a> (upcoming, stay tuned!) here's the beginning.</p>
<pre>
Imagine there's no quirksmode
It's easy if IE6 dies
No Trident below us
And all the data URIs

Imagine all the web devs coding for today

You may say I'm a dreamer
But I'm not the only one
I hope some day you will upgrade
And the world will browse as one
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.phpied.com/imagine/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Velocity Europe discount</title>
		<link>http://www.phpied.com/velocity-europe-discount/</link>
		<comments>http://www.phpied.com/velocity-europe-discount/#comments</comments>
		<pubDate>Tue, 01 Nov 2011 22:52:55 +0000</pubDate>
		<dc:creator>Stoyan</dc:creator>
				<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.phpied.com/?p=1587</guid>
		<description><![CDATA[The web performance and operations conference, Velocity Europe, is just around the corner. This always sold-out event is making its EU debut this year in Berlin. Get your ticket now (with 20% discount no less) or punish your users and clients with slow user experiences Info: url: http://velocityconf.com/velocityeu/ cost: €600 after 20% discount (ow €749) [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.phpied.com/wp-content/uploads/2011/11/veloeu.jpg" alt="" title="veloeu" width="650" height="153" class="alignnone size-full wp-image-1588" /></p>
<p>The web performance and operations conference, Velocity Europe, is just around the corner. This always sold-out event is making its EU debut this year in Berlin. </p>
<p>Get your ticket now (with 20% discount no less) or punish your users and clients with slow user experiences <img src='http://www.phpied.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Info:</p>
<ul>
<li>    url: <a href="http://velocityconf.com/velocityeu/">http://velocityconf.com/velocityeu/</a></li>
<li>    cost: €600 after 20% discount (ow €749)</li>
<li>    discount code: <strong>veu11sts</strong></li>
<li>    when: Nov 8-9</li>
<li>    where: Berlin</li>
<li>    hashtag: #<a href="http://twitter.com/#!/search/%23VelocityConf">VelocityConf</a></li>
</ul>
<p>Some highlights from the program:</p>
<ul>
<li>Jon Jenkins will be talking about Amazon Silk.</li>
<li>Browser sessions from Chrome, Firefox, and Opera.</li>
<li>David Mandelin talking on JavaScript engines.</li>
<li>Jeff Veen talking about Designing for Disaster.</li>
<li>Estelle Weyl on Mobile UI Performance.</li>
</ul>
<p>Full list of speakers <a href="http://velocityconf.com/velocityeu/public/schedule/speakers">here</a></p>
<p>Full disclosure: I'm in the program committee for the US event</p>
]]></content:encoded>
			<wfw:commentRss>http://www.phpied.com/velocity-europe-discount/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Imagemagick crop and center</title>
		<link>http://www.phpied.com/imagmagick-crop-and-center/</link>
		<comments>http://www.phpied.com/imagmagick-crop-and-center/#comments</comments>
		<pubDate>Thu, 13 Oct 2011 03:09:02 +0000</pubDate>
		<dc:creator>Stoyan</dc:creator>
				<category><![CDATA[images]]></category>

		<guid isPermaLink="false">http://www.phpied.com/?p=1580</guid>
		<description><![CDATA[Say you get a sprite created no matter how but the original images are long gone or for whatever reason not available. With imagemagick it's easy to crop them back. And I think it's easier and more precise than with a graphic UI, e.g. photoshop. Let's see how. Task: get me a 16x16 favicon for [...]]]></description>
			<content:encoded><![CDATA[<p>Say you get a sprite created no matter how but the original images are long gone or for whatever reason not available. With imagemagick it's easy to crop them back. And I think it's easier and more precise than with a graphic UI, e.g. photoshop. Let's see how.</p>
<p><strong>Task: get me a 16x16 favicon for yahoo when all you have is the <a href="http://search.yahoo.com/">Yahoo search</a> page</strong></p>
<ol>
<li>goto yahoo search, right click the icon, Inspect<br />
<a href="http://www.phpied.com/wp-content/uploads/2011/10/ys.png"><img src="http://www.phpied.com/wp-content/uploads/2011/10/ys.png" alt="" title="ys" width="650" class="alignnone size-full wp-image-1581" /></a>
</li>
<li>Download the sprite:
<pre>
$ curl http://a.l.yimg.com/pv/i/us/sch/gr5/metro_sprite_20110907.png > ys.png
</pre>
<p>here it is:<br />
<img src="http://a.l.yimg.com/pv/i/us/sch/gr5/metro_sprite_20110907.png"/></li>
<li>While inspecting the CSS you noticed
<pre>
width: 16px;
height: 12px;
background-position: -117px -95px;
</pre>
<p>This helps us cut precisely as opposed to guess the coordinates
</li>
<li>Crop it:
<pre>
$ convert ys.png -crop 16x12+117+95 yfavicon.png
</pre>
<p>The result is a 16x12 image:<br />
<a href="http://www.phpied.com/wp-content/uploads/2011/10/yfavicon.png"><img src="http://www.phpied.com/wp-content/uploads/2011/10/yfavicon.png" alt="" title="yfavicon" width="16" height="12" class="alignnone size-full wp-image-1582" /></a>
</li>
<li>And because we have this arbitrary requirement that we want all favicons to be 16x16 because our design says so, let's resize it to fit a 16x16 box and center it inside the box
<pre>
$ convert yfavicon.png -background transparent -gravity center -extent 16x16 y.png
</pre>
<p>Here:<br />
<img src="http://www.phpied.com/wp-content/uploads/2011/10/y.png" alt="" title="y" width="16" height="16" class="alignnone size-full wp-image-1583" />
</li>
<li>And just because, let's make it 160x160 with colored background to make sure the command works
<pre>
$ convert yfavicon.png -background orange -gravity center -extent 160x160 yorange.png
</pre>
<p><img src="http://www.phpied.com/wp-content/uploads/2011/10/yorange.png" alt="" title="yorange" width="160" height="160" class="alignnone size-full wp-image-1584" />
</li>
<li>Enjoy the rest of your day having saved some time by doing things on the command line instead of dealing with UI that gets in the way <img src='http://www.phpied.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.phpied.com/imagmagick-crop-and-center/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Social button BFFs</title>
		<link>http://www.phpied.com/social-button-bffs/</link>
		<comments>http://www.phpied.com/social-button-bffs/#comments</comments>
		<pubDate>Wed, 28 Sep 2011 02:31:47 +0000</pubDate>
		<dc:creator>Stoyan</dc:creator>
				<category><![CDATA[facebook]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.phpied.com/?p=1579</guid>
		<description><![CDATA[TL;DR: Loading JavaScript asynchronously is critical for the performance of your web app. Below is an idea how to do it for the most common social buttons out there so you can make sure these don't interfere with the loading of the rest of your content. After all people need to see your content first, [...]]]></description>
			<content:encoded><![CDATA[<p><em>TL;DR: Loading JavaScript asynchronously is critical for the performance of your web app. Below is an idea how to do it for the most common social buttons out there so you can make sure these don't interfere with the loading of the rest of your content. After all people need to see <strong>your content first</strong>, then decide if it's share-worthy.</em></p>
<p>Facebook now offers a new asynchronous snippet to load the JavaScript SDK, which lets you load social plugins (e.g. Like button) among doing other <a href="https://developers.facebook.com/docs/reference/javascript/">more powerful</a> things.</p>
<p>It has always been possible to load the JS SDK asynchronously but since recently it's the default. The code looks pretty damn nice (I know, right!), here's how it looks like (<a href="https://developers.facebook.com/docs/reference/plugins/like/">taken from here</a>):</p>
<div class="hl-main">
<pre><span class="hl-brackets">(</span><span class="hl-reserved">function</span><span class="hl-brackets">(</span><span class="hl-identifier">d</span><span class="hl-code">, </span><span class="hl-identifier">s</span><span class="hl-code">, </span><span class="hl-identifier">id</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code">
  </span><span class="hl-reserved">var</span><span class="hl-code"> </span><span class="hl-identifier">js</span><span class="hl-code">, </span><span class="hl-identifier">fjs</span><span class="hl-code"> = </span><span class="hl-identifier">d</span><span class="hl-code">.</span><span class="hl-identifier">getElementsByTagName</span><span class="hl-brackets">(</span><span class="hl-identifier">s</span><span class="hl-brackets">)</span><span class="hl-brackets">[</span><span class="hl-number">0</span><span class="hl-brackets">]</span><span class="hl-code">;
  </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-brackets">(</span><span class="hl-identifier">d</span><span class="hl-code">.</span><span class="hl-identifier">getElementById</span><span class="hl-brackets">(</span><span class="hl-identifier">id</span><span class="hl-brackets">)</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-reserved">return</span><span class="hl-code">;</span><span class="hl-brackets">}</span><span class="hl-code">
  </span><span class="hl-identifier">js</span><span class="hl-code"> = </span><span class="hl-identifier">d</span><span class="hl-code">.</span><span class="hl-identifier">createElement</span><span class="hl-brackets">(</span><span class="hl-identifier">s</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-identifier">js</span><span class="hl-code">.</span><span class="hl-identifier">id</span><span class="hl-code"> = </span><span class="hl-identifier">id</span><span class="hl-code">;
  </span><span class="hl-identifier">js</span><span class="hl-code">.</span><span class="hl-identifier">src</span><span class="hl-code"> = </span><span class="hl-quotes">&quot;</span><span class="hl-string">//connect.facebook.net/en_US/all.js#xfbml=1</span><span class="hl-quotes">&quot;</span><span class="hl-code">;
  </span><span class="hl-identifier">fjs</span><span class="hl-code">.</span><span class="hl-identifier">parentNode</span><span class="hl-code">.</span><span class="hl-identifier">insertBefore</span><span class="hl-brackets">(</span><span class="hl-identifier">js</span><span class="hl-code">, </span><span class="hl-identifier">fjs</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-brackets">}</span><span class="hl-brackets">(</span><span class="hl-builtin">document</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">script</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">facebook-jssdk</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-brackets">)</span><span class="hl-code">;</span></pre>
</div>
<p>Some nice steal-me <a href="http://jspatterns.com">JS patterns</a> here:</p>
<ul>
<li>immediate (self-invoking) function so not to bleed vars into global namespace</li>
<li>pass oft-used objects (<code>document</code>) and strings ("script", "facebook-jssdk") to the immediate function. Sort of rudimentary manual minification, while keeping the code readable</li>
<li>append script node by using the first available <code>script</code> element. That's 99.99% guaranteed to work unless all your code is in <code>body onload="..."</code> or img onload or something similar (insanity, I know, but let's allow generous 0.01% for it)</li>
<li>assign an ID to the node you append so you don't append it twice by mistake (e.g. like button in the header, footer and article)</li>
</ul>
<h3>All buttons' JS files</h3>
<p>Other buttons exist, most notably the <a href="http://twitter.com/goodies/tweetbutton">Twitter</a> and <a href="http://www.google.com/intl/en/webmasters/+1/button/index.html">Google+1</a> buttons. Both of these can be loaded with async JavaScript whether or not this is the default in their respective configurators.</p>
<p>So why not make them all get along and shelter them under the same facebook immediate function? We'll save some bytes and extra script tags in the HTML. For G+/T buttons all we need is a new script node. Google+'s snippet has some additional attribs such as <code>type</code> and <code>async</code>, but these are not really needed. Because <code>type</code> is always <code>text/javascript</code> and <code>async</code> is always <code>true</code>. Plus we kinda take care of the async part anyways.</p>
<p>The end result:</p>
<div class="hl-main">
<pre>
  <span class="hl-brackets">&lt;</span><span class="hl-reserved">div</span><span class="hl-code"> </span><span class="hl-var">id</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">fb-root</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">div</span><span class="hl-brackets">&gt;</span>
<span class="hl-code">  &lt;</span><span class="hl-identifier">script</span><span class="hl-code">&gt;</span><span class="hl-brackets">(</span><span class="hl-reserved">function</span><span class="hl-brackets">(</span><span class="hl-identifier">d</span><span class="hl-code">, </span><span class="hl-identifier">s</span><span class="hl-code">, </span><span class="hl-identifier">id</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code">
    </span><span class="hl-comment">//</span><span class="hl-comment"> fb + common</span><span class="hl-comment"></span><span class="hl-code">
    </span><span class="hl-reserved">var</span><span class="hl-code"> </span><span class="hl-identifier">js</span><span class="hl-code">, </span><span class="hl-identifier">fjs</span><span class="hl-code"> = </span><span class="hl-identifier">d</span><span class="hl-code">.</span><span class="hl-identifier">getElementsByTagName</span><span class="hl-brackets">(</span><span class="hl-identifier">s</span><span class="hl-brackets">)</span><span class="hl-brackets">[</span><span class="hl-number">0</span><span class="hl-brackets">]</span><span class="hl-code">;
    </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-brackets">(</span><span class="hl-identifier">d</span><span class="hl-code">.</span><span class="hl-identifier">getElementById</span><span class="hl-brackets">(</span><span class="hl-identifier">id</span><span class="hl-brackets">)</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-reserved">return</span><span class="hl-code">;</span><span class="hl-brackets">}</span><span class="hl-code">
    </span><span class="hl-identifier">js</span><span class="hl-code"> = </span><span class="hl-identifier">d</span><span class="hl-code">.</span><span class="hl-identifier">createElement</span><span class="hl-brackets">(</span><span class="hl-identifier">s</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-identifier">js</span><span class="hl-code">.</span><span class="hl-identifier">id</span><span class="hl-code"> = </span><span class="hl-identifier">id</span><span class="hl-code">;
    </span><span class="hl-identifier">js</span><span class="hl-code">.</span><span class="hl-identifier">src</span><span class="hl-code"> = </span><span class="hl-quotes">&quot;</span><span class="hl-string">//connect.facebook.net/en_US/all.js#xfbml=1</span><span class="hl-quotes">&quot;</span><span class="hl-code">;
    </span><span class="hl-identifier">fjs</span><span class="hl-code">.</span><span class="hl-identifier">parentNode</span><span class="hl-code">.</span><span class="hl-identifier">insertBefore</span><span class="hl-brackets">(</span><span class="hl-identifier">js</span><span class="hl-code">, </span><span class="hl-identifier">fjs</span><span class="hl-brackets">)</span><span class="hl-code">;
    </span><span class="hl-comment">//</span><span class="hl-comment"> +1</span><span class="hl-comment"></span><span class="hl-code">
    </span><span class="hl-identifier">js</span><span class="hl-code"> = </span><span class="hl-identifier">d</span><span class="hl-code">.</span><span class="hl-identifier">createElement</span><span class="hl-brackets">(</span><span class="hl-identifier">s</span><span class="hl-brackets">)</span><span class="hl-code">;
    </span><span class="hl-identifier">js</span><span class="hl-code">.</span><span class="hl-identifier">src</span><span class="hl-code"> = </span><span class="hl-quotes">'</span><span class="hl-string">https://apis.google.com/js/plusone.js</span><span class="hl-quotes">'</span><span class="hl-code">;
    </span><span class="hl-identifier">fjs</span><span class="hl-code">.</span><span class="hl-identifier">parentNode</span><span class="hl-code">.</span><span class="hl-identifier">insertBefore</span><span class="hl-brackets">(</span><span class="hl-identifier">js</span><span class="hl-code">, </span><span class="hl-identifier">fjs</span><span class="hl-brackets">)</span><span class="hl-code">;
    </span><span class="hl-comment">//</span><span class="hl-comment"> tweet</span><span class="hl-comment"></span><span class="hl-code">
    </span><span class="hl-identifier">js</span><span class="hl-code"> = </span><span class="hl-identifier">d</span><span class="hl-code">.</span><span class="hl-identifier">createElement</span><span class="hl-brackets">(</span><span class="hl-identifier">s</span><span class="hl-brackets">)</span><span class="hl-code">;
    </span><span class="hl-identifier">js</span><span class="hl-code">.</span><span class="hl-identifier">src</span><span class="hl-code"> = </span><span class="hl-quotes">'</span><span class="hl-string">//platform.twitter.com/widgets.js</span><span class="hl-quotes">'</span><span class="hl-code">;
    </span><span class="hl-identifier">fjs</span><span class="hl-code">.</span><span class="hl-identifier">parentNode</span><span class="hl-code">.</span><span class="hl-identifier">insertBefore</span><span class="hl-brackets">(</span><span class="hl-identifier">js</span><span class="hl-code">, </span><span class="hl-identifier">fjs</span><span class="hl-brackets">)</span><span class="hl-code">;
  </span><span class="hl-brackets">}</span><span class="hl-brackets">(</span><span class="hl-builtin">document</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">script</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">facebook-jssdk</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-brackets">)</span><span class="hl-code">;&lt;/</span><span class="hl-identifier">script</span><span class="hl-code">&gt;</span></pre>
</div>
<p>So this thing loads all three JS files required by the three buttons/plugins. </p>
<p>Additionally we can wrap the node creation/appending part into a function. So all the code is tighter. Here's the final snippet:</p>
<div class="hl-main">
<pre>
<span class="hl-brackets">&lt;</span><span class="hl-reserved">div</span><span class="hl-code"> </span><span class="hl-var">id</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">fb-root</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">div</span><span class="hl-brackets">&gt;</span><span class="hl-comment">&lt;!--</span><span class="hl-comment"> fb needs this </span><span class="hl-comment">--&gt;</span>
<span class="hl-code">&lt;</span><span class="hl-identifier">script</span><span class="hl-code">&gt;</span><span class="hl-brackets">(</span><span class="hl-reserved">function</span><span class="hl-brackets">(</span><span class="hl-identifier">d</span><span class="hl-code">, </span><span class="hl-identifier">s</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code">
  </span><span class="hl-reserved">var</span><span class="hl-code"> </span><span class="hl-identifier">js</span><span class="hl-code">, </span><span class="hl-identifier">fjs</span><span class="hl-code"> = </span><span class="hl-identifier">d</span><span class="hl-code">.</span><span class="hl-identifier">getElementsByTagName</span><span class="hl-brackets">(</span><span class="hl-identifier">s</span><span class="hl-brackets">)</span><span class="hl-brackets">[</span><span class="hl-number">0</span><span class="hl-brackets">]</span><span class="hl-code">, </span><span class="hl-identifier">load</span><span class="hl-code"> = </span><span class="hl-reserved">function</span><span class="hl-brackets">(</span><span class="hl-identifier">url</span><span class="hl-code">, </span><span class="hl-identifier">id</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code">
    </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-brackets">(</span><span class="hl-identifier">d</span><span class="hl-code">.</span><span class="hl-identifier">getElementById</span><span class="hl-brackets">(</span><span class="hl-identifier">id</span><span class="hl-brackets">)</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-reserved">return</span><span class="hl-code">;</span><span class="hl-brackets">}</span><span class="hl-code">
    </span><span class="hl-identifier">js</span><span class="hl-code"> = </span><span class="hl-identifier">d</span><span class="hl-code">.</span><span class="hl-identifier">createElement</span><span class="hl-brackets">(</span><span class="hl-identifier">s</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-identifier">js</span><span class="hl-code">.</span><span class="hl-identifier">src</span><span class="hl-code"> = </span><span class="hl-identifier">url</span><span class="hl-code">; </span><span class="hl-identifier">js</span><span class="hl-code">.</span><span class="hl-identifier">id</span><span class="hl-code"> = </span><span class="hl-identifier">id</span><span class="hl-code">;
    </span><span class="hl-identifier">fjs</span><span class="hl-code">.</span><span class="hl-identifier">parentNode</span><span class="hl-code">.</span><span class="hl-identifier">insertBefore</span><span class="hl-brackets">(</span><span class="hl-identifier">js</span><span class="hl-code">, </span><span class="hl-identifier">fjs</span><span class="hl-brackets">)</span><span class="hl-code">;
  </span><span class="hl-brackets">}</span><span class="hl-code">;
  </span><span class="hl-identifier">load</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">//connect.facebook.net/en_US/all.js#xfbml=1</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">fbjssdk</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">;
  </span><span class="hl-identifier">load</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">https://apis.google.com/js/plusone.js</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">gplus1js</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">;
  </span><span class="hl-identifier">load</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">//platform.twitter.com/widgets.js</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">tweetjs</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-brackets">}</span><span class="hl-brackets">(</span><span class="hl-builtin">document</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">script</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-brackets">)</span><span class="hl-code">;&lt;/</span><span class="hl-identifier">script</span><span class="hl-code">&gt;</span></pre>
</div>
<h3>All buttons' markup</h3>
<p>Next is actually advising the scripts where the widgets should be rendered. Facebook offers XFBML syntax, with tags such as <code>&lt;fb:like&gt;</code>, but it also offers pure HTML(5) with data-* attributes. Luckily, so do all others.</p>
<p>Here's an example:</p>
<div class="hl-main">
<pre><span class="hl-comment">&lt;!--</span><span class="hl-comment"> facebook like </span><span class="hl-comment">--&gt;</span><span class="hl-code">
</span><span class="hl-brackets">&lt;</span><span class="hl-reserved">div</span><span class="hl-code"> </span><span class="hl-var">class</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">fb-like</span><span class="hl-quotes">&quot;</span><span class="hl-code"> </span><span class="hl-var">data-send</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">false</span><span class="hl-quotes">&quot;</span><span class="hl-code"> </span><span class="hl-var">data-width</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">280</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">div</span><span class="hl-brackets">&gt;</span><span class="hl-code">
</span><span class="hl-comment">&lt;!--</span><span class="hl-comment"> twitter </span><span class="hl-comment">--&gt;</span><span class="hl-code">
</span><span class="hl-brackets">&lt;</span><span class="hl-reserved">a</span><span class="hl-code"> </span><span class="hl-var">class</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">twitter-share-button</span><span class="hl-quotes">&quot;</span><span class="hl-code"> </span><span class="hl-var">data-count</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">horizontal</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;</span><span class="hl-code">Tweet</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">a</span><span class="hl-brackets">&gt;</span><span class="hl-code">
</span><span class="hl-comment">&lt;!--</span><span class="hl-comment"> g+ </span><span class="hl-comment">--&gt;</span><span class="hl-code">
</span><span class="hl-brackets">&lt;</span><span class="hl-reserved">div</span><span class="hl-code"> </span><span class="hl-var">class</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">g-plusone</span><span class="hl-quotes">&quot;</span><span class="hl-code"> </span><span class="hl-var">data-size</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">medium</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">div</span><span class="hl-brackets">&gt;</span></pre>
</div>
<p>G+ requires a <code>div</code> element (with <code>g-plusone</code> class name), Twitter requires an <code>a</code> (with a <code>twitter-share-button</code> class name). Facebook will take any element you like with a <code>fb-like</code> class name (or <code>fb-comments</code> or <code>fb-recommendations</code> or <a href="https://developers.facebook.com/docs/plugins/">any other social plugin</a> you may need)</p>
<p>Also very important to note that you can (and should) load the JS files once and then render as many different buttons as you need. In Facebook's case these can be any type of plugin, not just like buttons. Economy of scale - on JS file, many plugins.</p>
<h3>All together now</h3>
<p>So here's the overall strategy for loading all those buttons. </p>
<ol>
<li>Copy the JS above at the bottom of the page right before <code>/body</code> just to be safe (G+ failed to load when the markup is after the JS). This will also help you make sure there should be only one place to load the JS files, although the snippet takes cares of dedupe-ing.</li>
<li>sprinkle plugins and buttons any way you like anywhere on your pages using the appropriate configurator to help you deal with the data-* attributes (<a href="https://developers.facebook.com/docs/plugins/">FB</a>, <a href="http://www.google.com/intl/en/webmasters/+1/button/index.html">G+</a>, <a href="http://twitter.com/goodies/tweetbutton">Tw</a>)</li>
<li>Enjoy all the social traffic you deserve!</li>
</ol>
<p>To see it all in action - go to my abandoned <a href="http://phonydev.com">phonydev.com</a> blog. Yep, those buttons play nice in mobile too.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.phpied.com/social-button-bffs/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>x-webkit-speech input and textareas</title>
		<link>http://www.phpied.com/x-webkit-speech-input-and-textareas/</link>
		<comments>http://www.phpied.com/x-webkit-speech-input-and-textareas/#comments</comments>
		<pubDate>Sat, 06 Aug 2011 09:11:58 +0000</pubDate>
		<dc:creator>Stoyan</dc:creator>
				<category><![CDATA[(x)HTML(5)]]></category>

		<guid isPermaLink="false">http://www.phpied.com/?p=1571</guid>
		<description><![CDATA[New hotness, speech input. (The demo, the demo) You get an input: &#60;input&#62; You add an x-webkit-speech attribute &#60;input x-webkit-speech&#62; And voila! Or if you don't have a recent Chrome version, here's what these who have a recent Chrome version see: Nice. Textareas Speech inputs - gotta love them. But in textareas - you can't [...]]]></description>
			<content:encoded><![CDATA[<p>New hotness, speech input. (<a href="/files/speech-input/speech.html">The demo, the demo</a>) </p>
<p>You get an input:</p>
<p><code>&lt;input&gt;</code></p>
<p>You add an <code>x-webkit-speech</code> attribute</p>
<p><code>&lt;input x-webkit-speech&gt;</code></p>
<p>And voila!</p>
<input x-webkit-speech/>
<p>Or if you don't have a recent Chrome version, here's what these who have a recent Chrome version see:</p>
<p><img src="http://www.phpied.com/wp-content/uploads/2011/08/speak-now.png" alt="" title="speak-now" width="227" height="145" class="alignnone size-full wp-image-1572" /></p>
<p>Nice.</p>
<h3>Textareas</h3>
<p>Speech inputs - gotta love them. But in textareas - you can't have them. So you can put an input and a textarea and copy over the content.</p>
<p>html:</p>
<div class="hl-main">
<pre><span class="hl-brackets">&lt;</span><span class="hl-reserved">textarea</span><span class="hl-code"> </span><span class="hl-var">id</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">txt</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">textarea</span><span class="hl-brackets">&gt;</span><span class="hl-code">
</span><span class="hl-brackets">&lt;</span><span class="hl-reserved">input</span><span class="hl-code"> </span><span class="hl-var">x-webkit-speech</span><span class="hl-code"> </span><span class="hl-var">id</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">mike</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">/&gt;</span></pre>
</div>
<p>With some CSS you can remove the border, add pointy cursor, etc make it look like not an input.</p>
<div class="hl-main">
<pre><span class="hl-identifier">#mike</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code">
    </span><span class="hl-reserved">font-size:</span><span class="hl-code"> </span><span class="hl-number">25</span><span class="hl-string">px</span><span class="hl-reserved"></span><span class="hl-code">;
    </span><span class="hl-reserved">width:</span><span class="hl-code"> </span><span class="hl-number">25</span><span class="hl-string">px</span><span class="hl-reserved"></span><span class="hl-code">;
    </span><span class="hl-reserved">height:</span><span class="hl-code"> </span><span class="hl-number">25</span><span class="hl-string">px</span><span class="hl-reserved"></span><span class="hl-code">;
    </span><span class="hl-reserved">cursor:</span><span class="hl-string">pointer</span><span class="hl-reserved"></span><span class="hl-code">;
    </span><span class="hl-reserved">border:</span><span class="hl-code"> </span><span class="hl-string">none</span><span class="hl-reserved"></span><span class="hl-code">;
    </span><span class="hl-reserved">position:</span><span class="hl-code"> </span><span class="hl-string">absolute</span><span class="hl-reserved"></span><span class="hl-code">;
    </span><span class="hl-reserved">margin-left:</span><span class="hl-code"> </span><span class="hl-number">5</span><span class="hl-string">px</span><span class="hl-reserved"></span><span class="hl-code">;
    </span><span class="hl-reserved">outline:</span><span class="hl-code"> </span><span class="hl-string">none</span><span class="hl-reserved"></span><span class="hl-code">;
    </span><span class="hl-reserved">background:</span><span class="hl-code"> </span><span class="hl-string">transparent</span><span class="hl-reserved"></span><span class="hl-code">;
</span><span class="hl-brackets">}</span><span class="hl-code">
</span><span class="hl-identifier">#txt</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code">
    </span><span class="hl-reserved">height:</span><span class="hl-code"> </span><span class="hl-number">150</span><span class="hl-string">px</span><span class="hl-reserved"></span><span class="hl-code">;
    </span><span class="hl-reserved">width:</span><span class="hl-code"> </span><span class="hl-number">150</span><span class="hl-string">px</span><span class="hl-reserved"></span><span class="hl-code">;
</span><span class="hl-brackets">}</span></pre>
</div>
<p>Finally a little JavaScript to a/ unfocus the input and b/ carry over the content from the input to the textarea</p>
<div class="hl-main">
<pre><span class="hl-reserved">var</span><span class="hl-code"> </span><span class="hl-identifier">mike</span><span class="hl-code"> = </span><span class="hl-builtin">document</span><span class="hl-code">.</span><span class="hl-identifier">getElementById</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">mike</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-identifier">mike</span><span class="hl-code">.</span><span class="hl-identifier">onfocus</span><span class="hl-code"> = </span><span class="hl-identifier">mike</span><span class="hl-code">.</span><span class="hl-identifier">blur</span><span class="hl-code">;
</span><span class="hl-identifier">mike</span><span class="hl-code">.</span><span class="hl-identifier">onwebkitspeechchange</span><span class="hl-code"> = </span><span class="hl-reserved">function</span><span class="hl-brackets">(</span><span class="hl-identifier">e</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code">
    </span><span class="hl-comment">//</span><span class="hl-comment">console.log(e); // SpeechInputEvent</span><span class="hl-comment"></span><span class="hl-code">
    </span><span class="hl-builtin">document</span><span class="hl-code">.</span><span class="hl-identifier">getElementById</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">txt</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">.</span><span class="hl-identifier">value</span><span class="hl-code"> = </span><span class="hl-identifier">mike</span><span class="hl-code">.</span><span class="hl-identifier">value</span><span class="hl-code">;
</span><span class="hl-brackets">}</span><span class="hl-code">;</span></pre>
</div>
<p>That's all there is. <a href="/files/speech-input/speech.html">Click over to the demo.</a></p>
<p>Here's what you should see in Chrome:</p>
<p><img src="http://www.phpied.com/wp-content/uploads/2011/08/speak-now-txt.png" alt="" title="speak-now-txt" width="373" height="208" class="alignnone size-full wp-image-1573" /></p>
<p>You can see that <code>console.log()</code> there - it's definitelly worth exploring. The thing is a <code>SpeechInputEvent</code> type of object is passed to the handler of the <code>onwebkitspeechchange</code> event. This object has some interesting properties, such as the array <code>results[]</code> which is number of guesses what you've said and confidence (0 to 1 it seems) in the guess.</p>
<p>Enjoy and go ahead and add these all over the place! <img src='http://www.phpied.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.phpied.com/x-webkit-speech-input-and-textareas/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Overlooked Optimizations: Images</title>
		<link>http://www.phpied.com/overlooked-optimizations-images/</link>
		<comments>http://www.phpied.com/overlooked-optimizations-images/#comments</comments>
		<pubDate>Tue, 14 Jun 2011 07:16:53 +0000</pubDate>
		<dc:creator>Stoyan</dc:creator>
				<category><![CDATA[images]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.phpied.com/?p=1566</guid>
		<description><![CDATA[#1 This guest post from Billy Hoffman is the last post in the Velocity countdown series. Velocity starts first thing tomorrow! Hope you enjoyed the ride and please welcome Billy Hoffman! Billy Hoffman (@zoompf) is the founder and CEO of Zoompf, a web performance startup whose scanning technology helps website owners find and fix performance [...]]]></description>
			<content:encoded><![CDATA[<p style="margin-top: 5px;" class="alt"><span style="font-size: 2em; color: #464646">#1</span> This guest post from Billy Hoffman is the last post in the <a href="http://www.phpied.com/velocity-countdown/">Velocity countdown</a> series. Velocity starts first thing tomorrow! Hope you enjoyed the ride and please welcome Billy Hoffman!</p>
<div class="alt" style="padding-bottom: 0; margin-top: 20px"><img align="right" src="http://assets.en.oreilly.com/1/eventprovider/1/_@user_75913.jpg" alt="Billy Hoffman" title="Billy Hoffman" style="padding-left:15px"/><a href="http://zoompf.com">Billy Hoffman</a> (<a href="http://twitter.com/zoompf">@zoompf</a>) is the founder and CEO of <a href="http://zoompf.com">Zoompf</a>, a web performance startup whose scanning technology helps website owners find and fix performance issues which are slowing down their sites. Previously Billy was a web security researcher at SPI Dynamics and managed a research team at HP. He can open a Coke can without using his hands.
</div>
<p>(tl;dr: <i>Images make up the majority of the Internet, yet we consistently fail to apply the most basic of optimizations. Even big sites like Twitter are completely screwing this up. Furthermore, there are huge unexplored areas when it comes to image optimization which would provide significant savings. We should stop worrying about esoteric performance optimizations when there is so much other low hanging fruit.</i>)</p>
<p>
Images constitute the bulk of content on the Internet, both in terms of content size and number of resources. Using data from the wonderful <a href="http://httparchive.org/">HTTP Archive</a> we see that 60% of the bytes that make up an Alexa Top 1000 website are images. The average webpage references 81 external resources, and 64% of these are images. And the dominance of images is growing. In the last 6 months, total page content size increased by 70 kB. 75% of that increase (52 kB) came from images.
</p>
<p><img src="http://www.phpied.com/wp-content/uploads/2011/06/bytes-per-type.png" /></p>
<p><img src="http://www.phpied.com/wp-content/uploads/2011/06/total-size.png"/></p>
<p><img src="http://www.phpied.com/wp-content/uploads/2011/06/image-size.png" /></p>
<p>
We know that lossless image optimization tools reduce content size anywhere from 5-20%. Occasionally you will see 70% savings or more, but that only happens when the image contains an embedded thumbnail. That level of savings doesn't sound all that impressive. After all HTTP compression can save 60-70% on real world text resources like HTML, JavaScript, or CSS. However text resources only make up on average 188 kB, or 24% of total content size. Saving 66% on 24% of content saves about as much as 5-20% savings on 60% of the content. In fact, if you could reduce images by 25%, that would have more of an effect on reducing total content size than using HTTP compression!
</p>
<p>
If you work in front-end performance, none of this should be a surprise. Obviously any front-end performance strategy needs to include image optimizations. Image optimization is an old topic. Shouldn't we instead be focusing on more esoteric optimizations, like refactoring CSS rules so that external fonts render faster on Blackberry Webkit? No, we shouldn't, because sadly we collectively suck at optimizing images.
</p>
<h3>Give PNG a Chance? Nope.</h3>
<p>
One of <b>the most basic</b> image optimizations that you can make is converting GIFs to PNGs. PNGs can do everything that GIFs can do and more, and the browser issues with PNGs are larger a problem of the past. Even <b>without applying additional lossless optimization tools</b> on the PNG, converting a GIF file will almost without exception create a smaller PNG. This is because the fundamental way graphics data is compressed in a file PNG, using the DEFLATE algorithm, is more efficient than GIF's LZW compression scheme. Once you apply lossless tools on the converted PNG they get even smaller. Animated GIFs are the exception here, as PNGs are not animated and alternatives for simple animations (MNG, Flash) are either not widely supported or result in larger files. So what is the break down of image formats on the web today?
</p>
<p><img src="http://www.phpied.com/wp-content/uploads/2011/06/image-formats.png" /></p>
<p>
37% of images on the Alexa Top 1000 websites are GIFs. That makes no sense given what we know about PNGs over GIFs. 37% of the images on the Internet are not animated "Under construction" icons or Ajax status thumper animations. People are not being intelligent about file formats they use for images.
</p>
<h3>The Internet, now with more bloat!</h3>
<p>
Applying lossless image optimization tools is one of the simplest optimizations to do. Take an image, run a program, get an optimized image. Stoyan and I love optimizations like this because they are so easy to automate. Just add a step to the website build process or to your staging-to-production publishing process that automatically optimizes images. It should be transparent, something you setup once and forget about. So how are we doing?<br />
82% of Alexa Top 1000 websites contain images which were not losslessly optimized. Apply lossless optimizations across all the images from the Alexa top 1000 would <b>reduce file size by an additional 15%</b>.
</p>
<p>
Surely there are just a few number of smaller sites which aren't properly optimizing images which are pulling down the statistics right? Sadly no. Twitter, the ninth largest website in the world by traffic, <a href="http://zoompf.com/blog/2011/05/how-fast-is-twitter">doesn't losslessly optimize any of their images</a>. 33% of total page load bytes could be eliminated solely by applying lossless image optimization. Let me phrase that a different way: <b>1 byte of our every 3 bytes Twitter sends you is unnecessary!</b> This is an incredible waste.
</p>
<h3>Unplowed Fields</h3>
<p>
It's clear we are not applying the image optimizations we already know about. However there is much more work to be done with images. This is a largly unresearched or unadvocated area which needs more attention.
</p>
<p>
Consider choosing the correct image format. Are people saving images as a PNG when they should be saved as a JPEG? Indeed they are. <a href="http://assets.tumblr.com/images/register_login/light6.png">Tumblr's background image</a> is a 76 kB PNG image and it would be 33 kB (55% smaller) if it was a JPEG. This is better than their <a href="http://assets.tumblr.com/images/register_login/light4.png">old 827 kB PNG background image</a>, which would be 47 kB (94% smaller) if it was a JPEG. Unfortunately I know of no other tool besides <a href="http://zoompf.com/free">Zoompf's free performance scan</a> which identifies PNG candidate images for conversion to JPEG.
</p>
<p>
What about JPEGs saved with a high quality setting? This is a large enough topic for its own blog post. To quickly summarize, JPEG "quality" is an arbitrary, non-linear scale, quality is not a percentage of anything, and "quality of 80" does not mean "discard 20% of graphics data." Thought leaders like Adobe recommend a quality setting of 70-80 for JPEGs published on the web. Zoompf found that 36% of Alexa Top 1000 images have a quality setting over 80, and reducing them to quality 70 would on average reduce image size by 48%! While all of these images might not be able to be reduced in quality, surely some of them can. Again, this is an area that needs more attention, more best practices and guidance, and more tools to help validate.
</p>
<h3>Not "Instead of" but "In addition too"</h3>
<p>I am not saying other performance optimizations are not important. Zoompf checks for over 380 performance issues and we are adding more all the time. Many of them are esoteric and low impact. We flag things like <a href="http://zoompf.com/blog/2010/03/duplicate-cookies">duplicate cookies</a>, unnecessary HTTP headers, and even when your &lt;META&gt; contains duplicate keywords. However these checks are for when you have handled all the other important checks. Image optimizations, and research into new image optimization techniques should be not done instead of other work, but in addition to it. Just remeber to prioritize what you are working on so that it will affect the most number of people in  the largest possible way.
</p>
<h3>Conclusions</h3>
<p>
Images are a huge component of the web and modern web performance. This importance is only growing. Sadly, there are only one or two widely recognized image optimizations techniques. Unfortunately, these most basic optimizations are ignored, forgotten, and not uniformly applied by even the largest of websites today. Additionally, there are a lot of unexplored areas of image optimization, including lossy image optimization, with no clear recommendations or best practices and virtually no tool support. Some areas for further research include:
</p>
<ul>
<li>Lossy image optimizations</li>
<li>Comparison of JPEG encoders</li>
<li>PNG-to-JPEG and GIF-to-JPEG best practices, recommendations, and processes</li>
<li>Image quality for Desktop vs. mobile browsing experiences</li>
<li>Better <a href="http://zoompf.com/blog/2010/02/choosing-png8-candidate-images">PNG24 to PNG8 conversion guidelines</a>. (I converted all the figures in this blog post from PNG24 to PNG8 and reduced file size by 52%)</li>
<li><a href="http://zoompfchangelog.tumblr.com/post/4916052161/scanner-features-bug-fixes-new-checks-check-fixes">Viablility of WebP</a> and automated delivery to supported browsers</li>
</ul>
<p>
I will be discussing many of these topics this week during my presentation <a href="http://velocityconf.com/velocity2011/public/schedule/detail/18229"><i>Take it all Off! Lossy Image Optimization</i></a> at Velocity 2011 on Wednesday. I hope you all can make it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.phpied.com/overlooked-optimizations-images/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Sultans of Speed</title>
		<link>http://www.phpied.com/sultans-of-speed/</link>
		<comments>http://www.phpied.com/sultans-of-speed/#comments</comments>
		<pubDate>Mon, 13 Jun 2011 10:13:59 +0000</pubDate>
		<dc:creator>Stoyan</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.phpied.com/?p=1565</guid>
		<description><![CDATA[#2 This post is part of the Velocity countdown series. Stay tuned for the last one tomorrow. With only 2 days to Velocity, it's time to drop in the quality of these posts (but the one tomorrow will be great, I promise) with today's announcement of the immediate availability of the project called http://sultansofspeed.com. I [...]]]></description>
			<content:encoded><![CDATA[<p style="margin-top: 5px;" class="alt"><span style="font-size: 2em; color: #464646">#2</span> This post is part of the <a href="http://www.phpied.com/velocity-countdown/">Velocity countdown</a> series. <a href="http://phpied.com/feed/">Stay</a> <a href="http://twitter.com/stoyanstefanov">tuned</a> for the last one tomorrow.</p>
<p><img src="http://calendar.perfplanet.com/wp-content/themes/wpc/wpclogo.png"/></p>
<p>With only 2 days to Velocity, it's time to drop in the quality of these posts (but the one tomorrow will be great, I promise) with today's announcement of the immediate availability of the project called <a href="http://sultansofspeed.com">http://sultansofspeed.com</a>.</p>
<p>I think we've had enough of experts, gurus, ninjas, jedis, pirates and overloards. Time for the sultans to step in!</p>
<p>So there: a slideshow of bios and photos of a number of Web Performance Sultans.</p>
<p>The background music is my heavy metal cover (sorry!) of "Sultans of Swing" by Dire Straits.</p>
<p>The Sultans you see there are the people who have written for the <a href="http://calendar.perfplanet.com">Perfplanet Calendar</a>. But this is just the initial seed. (And because these are the bios/photos I have easy access to.)</p>
<p>Are you a sultan? Add/delete/edit your bio in the <a href="https://github.com/stoyan/Sultans-of-Speed">Github repo</a> in the <a href="https://github.com/stoyan/Sultans-of-Speed/blob/master/sultans.js">sultans.js</a> file.</p>
<p>Want to change something - better slideshow maybe? Yes, <a href="https://github.com/stoyan/Sultans-of-Speed">the repository is still there</a>.</p>
<p>In the immortal words of Mark Knopfler:</p>
<blockquote><p>And he makes it <em>fast</em> with one more thing:<br />
"We are the sultans, yeah the <a href="http://www.sultansofspeed.com/">sultans of speed</a>"
</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.phpied.com/sultans-of-speed/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Book of Speed</title>
		<link>http://www.phpied.com/book-of-speed/</link>
		<comments>http://www.phpied.com/book-of-speed/#comments</comments>
		<pubDate>Sun, 12 Jun 2011 11:40:43 +0000</pubDate>
		<dc:creator>Stoyan</dc:creator>
				<category><![CDATA[book]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.phpied.com/?p=1560</guid>
		<description><![CDATA[#3 This post is part of the Velocity countdown series. Stay tuned for the articles to come. Without further ado, please point your browser to the newborn bookofspeed.com. It's a free (public domain), online, open-source, not yet finished, book about web performance. Contributions welcome The source files are on Github - https://github.com/stoyan/Book-of-Speed. I'll be glad [...]]]></description>
			<content:encoded><![CDATA[<p style="margin-top: 5px;" class="alt"><span style="font-size: 2em; color: #464646">#3</span> This post is part of the <a href="http://www.phpied.com/velocity-countdown/">Velocity countdown</a> series. <a href="http://phpied.com/feed/">Stay</a> <a href="http://twitter.com/stoyanstefanov">tuned</a> for the articles to come.</p>
<p>Without further ado, please point your browser to the newborn <a href="http://bookofspeed.com">bookofspeed.com</a>.</p>
<p>It's a free (public domain), online, open-source, not yet finished, book about web performance.</p>
<h3>Contributions welcome</h3>
<p>The source files are on Github - <a href="https://github.com/stoyan/Book-of-Speed">https://github.com/stoyan/Book-of-Speed</a>. I'll be glad to receive any errata, technical mistakes, requests, grammar checks, anything really. Just edit the stuff in <code>/src</code> and send a patch. /src is the text for the chapters alone, then what you see on the site and in the main directory - <a href="https://github.com/stoyan/Book-of-Speed/blob/master/index.html">TOC</a> and chapters - are generated by <a href="https://github.com/stoyan/Book-of-Speed/blob/master/builder/builder.js">a build script</a> (of course a javascript).</p>
<h3>How did we end up here</h3>
<p>Year and half ago I did this <a href="http://www.phpied.com/performance-advent-calendar-2009/">Performance advent calendar experiment</a> (since moved to a <a href="http://calendar.perfplanet.com/">new home</a>), writing an article a day for 24 days (sounds vaguely familiar?). PeachPit press approached me about publishing a book based on those. PeachPit publishes mostly web design books (like Designing with Web Standards) and I thought designers should know about performance. Also business folks, product managers. So why not write something more accessible and less technical?</p>
<p><a href="http://www.amazon.com/Speed-Matters-psychology-technology-high-performance/dp/0321715209">"Speed Matters" was the title</a>.</p>
<p><img src="http://www.phpied.com/wp-content/uploads/2011/06/speed-matters.jpg" alt="" title="speed-matters" width="300" height="300" class="alignnone size-full wp-image-1561" /></p>
<p>Fast forward... I kept missing deadlines (a favorite thing, <a href="http://www.goodreads.com/quotes/show/1398">ask Douglas Adams</a>) until eventually after 5 and a half chapters out of 9, the publisher decided to cancel the project. Fair enough. Wasn't meant to be. We're grown ups, no hard feelings. (Well, I did try to save the project by suggesting Marcel Duran who now works on YSlow to finish it, to which PeachPit expressed interest initially but then didn't bother to follow up with a comment or explanation)</p>
<p>So instead of letting PeachPit keep the content and maybe publish it on their site, I decided to keep the chapters and return them the money for the royalty advance they have given me. After all, I did wanted to try self-publishing for some time .</p>
<p>Fast forward again... I didn't do anything further. Changing computers, failing disks and non-existing backups convinced me I should let this content free sooner. "Information wants to be free". So I managed to restore from emails (but not the images, had to copy images from Word) and thought the <a href="http://www.phpied.com/velocity-countdown/">Velocity countdown</a> is a good excuse to release this thing.</p>
<p>I mentioned to my good friend and designer <a href="http://twitter.com/jvatchkov">Yavor</a> about the project two days ago, he had a few free cycles and sent me a mock. Awesome! the only "brief" I gave him was "it's to be a free online book, like <a href="http://diveintohtml5.com">diveintohtml5.com</a> and <a href="http://eloquentjavascript.net">eloquentjavascript.net</a>". And here's what he came up with, how cool is that! (oh and I gave him a turtle drawing, see below)</p>
<p><img src="http://www.phpied.com/wp-content/uploads/2011/06/ddd1.jpg" alt="" title="ddd" width="600" height="1250" class="alignnone size-full wp-image-1563" /></p>
<p>(As you can see, he's so humble he doesn't want any credit on the site. But this is my blog and I can give credit as much as want now, can't I? <img src='http://www.phpied.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  )</p>
<p>So last night between writing last night's post and today, I turned this mock into HTML (not fully complete, missing ego-header and pagination) and converted the 5 chapters I have so far from word docs to HTML.</p>
<h3>Audience</h3>
<p>If you follow my blog there isn't much new for you. Like I said, the audience was to be less technical. But there are a few new never-before seen bits and pieces.</p>
<p>Assuming the html-writing part of the PeachPit audience will be still very attached to XHTML, I decided to do what I generally tend to avoid - closing tags, using type="text/javascript" etc. Further edits should convert these to more compact html5-allowed syntax.</p>
<p>In the markup for the site though, in the rush to convert everything I started not closing P and LI to save time <img src='http://www.phpied.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Feel free to send a patch.</p>
<h3>No credits</h3>
<p>I was planning on having one round of credit-giving either as footnotes or appendix once the book is done. But the books is not done, so forgive me if I havent given you credit where it was due.</p>
<h3>No links</h3>
<p>It's silly to have no links in an online publication, but given the rush, I didn't edit the content at all to add them. Again I was planning on appendix, or actually a companion site. Will do. Will accept a patch <img src='http://www.phpied.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>On editing</h3>
<p>My editor from PeachPit sent me notes and edits. These are not in the online edition. Partly because I don't think it's fair (what's in it for them?) and partly because, trivially, I didn't have the time.</p>
<h3>On reviewing</h3>
<p>I got technical reviews from Marcel Duran and Sergey Chikuyonok while working on the book. I haven't incorporated their feedback. Will do <img src='http://www.phpied.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  (Sergey said my chapter on image optimization was too basic <img src='http://www.phpied.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  It is, especially compared with his articles on smashing magazine and his blog )</p>
<p>But Annie Sullivan from Google went way above and beyond any review I have seen. She actually read the chapter with her husband (not technical) and explained to him what's going on. So I had very eye-opening observations and I'm grateful and indebted for this.</p>
<p>(As you guessed, the feedback is not yet reflected in the text)</p>
<h3>PageSpeed</h3>
<p>PageSpeed runs on <a href="http://www.dreamhost.com/r.cgi?447675">Dreamhost</a> where the site is. So I though I should check the "use pagespeed" check in DH's panel. Not bad, not bad at all. Having your images and other stuff taken care of for you automagically. I have 99/100 Page Speed score and 94/100 YSlow. </p>
<p>I do minify CSS myself though and inline it, because it's small</p>
<h3>Turtle</h3>
<p>I couldn't use the turtle (nor the title) from Speed Matters. But my kid drew a turtle in drawing class so I thought I should use it. Here's what it looked like before the my designer friend took over:</p>
<p><img src="http://www.phpied.com/wp-content/uploads/2011/06/spped2.png" alt="" title="spped2" width="581" height="362" class="alignnone size-full wp-image-1564" /></p>
<h3>Happy reading!</h3>
<p>Like I metioned, regulars on this blog won't find much new information, but feel free to send your junior team members to learn from the free source.</p>
<p>And don't forget to send patches - book editing via GitHub sounds pretty nice to me.</p>
<p>Once again - here's <a href="http://bookofspeed.com">the book of speed</a> and here are <a href="https://github.com/stoyan/Book-of-Speed/">its source files</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.phpied.com/book-of-speed/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>YSlow 2.0: the first sketches</title>
		<link>http://www.phpied.com/yslow-2-0-the-first-sketches/</link>
		<comments>http://www.phpied.com/yslow-2-0-the-first-sketches/#comments</comments>
		<pubDate>Sat, 11 Jun 2011 08:15:12 +0000</pubDate>
		<dc:creator>Stoyan</dc:creator>
				<category><![CDATA[performance]]></category>
		<category><![CDATA[yahoo]]></category>
		<category><![CDATA[ydn]]></category>
		<category><![CDATA[yslow]]></category>

		<guid isPermaLink="false">http://www.phpied.com/?p=1554</guid>
		<description><![CDATA[#4 This post is part of the Velocity countdown series. Stay tuned for the articles to come. I'm working on tomorrow's kind of big thing, so will take it easy today, with a stroll down memory lane. I was clearing up my space at home few days ago and came across this oldish notepad. In [...]]]></description>
			<content:encoded><![CDATA[<p style="margin-top: 5px;" class="alt"><span style="font-size: 2em; color: #464646">#4</span> This post is part of the <a href="http://www.phpied.com/velocity-countdown/">Velocity countdown</a> series. <a href="http://phpied.com/feed/">Stay</a> <a href="http://twitter.com/stoyanstefanov">tuned</a> for the articles to come.</p>
<p>I'm working on tomorrow's kind of big thing, so will take it easy today, with a stroll down memory lane.</p>
<p>I was clearing up my space at home few days ago and came across this oldish notepad. In there (among the usual amount of lists of todos and ideas in the spirit of i-wanna-do-this-tool/site/experiment!) I found these early sketches of what has since become YSlow 2.0. These are all still pretty relevant, so why not take a minute to review them and get acquainted with the YSlow internals.</p>
<p>Back at the time Steve Souders and I had <a href="http://ajaxian.com/archives/yslow-09-release-grokking-xhr-and-more">just released YSlow 0.9</a> and Steve had moved to Google. It was the right time to have a quick bugfix-or-two release of YSlow 1.0 and in parallel get cranking on a complete YSlow 2.0 rewrite. </p>
<p>The motivation behind the total rewrite was (aside from the usual "I didn't make this mess" ego-driven desire to start fresh and do a better job the second time around) was that we were getting a lot of "meh, these are <a href="http://www.codinghorror.com/blog/2007/08/yslow-yahoos-problems-are-not-your-problems.html">Yahoo's problems/rules, not yours</a>". For example a normal mere mortal blog with no CDN budget should still try to get an A in most other checks. Another, somewhat forward thinking, as opposed to reactive reason was that I was a big fan of letting others contribute rules and checks of their own. The idea was to make YSlow your own tool, not only Yahoo's. For example if you want to set a rule that there should be no more than 5 images on a page, you should be able to codify this into a rule. And share the rule with the rest of team or the world. (<a href="http://www.phpied.com/wtf/">Here's an example</a>). Another thing was also to decouple the tool from Firebug. Make it work without Firebug and even without Firefox. Go back to having a bookmarklet version (Steve's original very first version) and versions for other browsers. (Thanks to Marcel Duran this is also becoming <a href="https://chrome.google.com/webstore/detail/ninejjcohidippngpapiilnmkgllmakh">a reality now</a>)</p>
<p>So the new architecture (a big name for a bunch of objects) was conceived on these sketches while en route a red-eye flight to Bulgaria. My little kids were asleep taking over my seat as well, so here I was standing up in the aisle on the plane or sitting on the seat's handrail, scribbling these notes. </p>
<p>The main idea was divide and conquer. Split this monolithic piece of code into smaller components. </p>
<p>When you run YSlow, it starts by "peeling off" the page, extracting all possible information. Hence the <code>Peeler</code> singleton.</p>
<p><img src="http://www.phpied.com/wp-content/uploads/2011/06/1.jpg" alt=""  /></p>
<p><code>Peeler</code> has methods such as <code>getJavaScript()</code> and <code>getDocuments()</code> (as in <code>document</code> + any frames). This can work most anywhere (bookmarklet too). Then if YSlow is running inside Firebug and has access to Net Panel (or any other browser or environment that lets you access stuff happening on the network, not only DOM crawling), it can also find things such as XHR requests or image beacons, which are not part of the DOM, using a <code>NetMonitor</code> listener object of some sorts.</p>
<p>Whatever <code>Peeler</code> finds, it sticks into a <code>ComponentSet</code> which is just an array of components along with some convenience methods such as <code>getComponentsByType('css')</code>.</p>
<p>Moving on, the <code>ComponentSet</code> contains <code>Component</code> objects which have all the data, like headers, type, content, URL, the whole thing.</p>
<p><img src="http://www.phpied.com/wp-content/uploads/2011/06/2.jpg" alt=""  /></p>
<p>K, now we have a bunch of components waiting and willing to be inspected. To make this inspection as lego-like as possible, there's no big-ass inspector, but there are many little <code>Rule</code> objects. Each <code>Rule</code> object has a bunch of properties like <code>name</code>, <code>URL</code> with more info, etc, but the main thing is - it needs to implement a <code>lint()</code> method. The <code>lint()</code> method takes a reference to the <code>ComponentSet</code> and then returns a <code>Result</code> object.</p>
<p>The <code>Result</code> objects are fairly simple - they have a grade/score, message and optionally a list of offending components (e.g. images without <code>Expires</code> header). A bunch of result objects make a <code>ResultSet</code> which has methods to get the final total score.</p>
<p><img src="http://www.phpied.com/wp-content/uploads/2011/06/3.jpg" alt=""  /></p>
<p>A bunch of <code>Rule</code> objects go into a <code>RuleSet</code>. The idea is to mash those up as you wish. So a <code>Rule</code> object is for example "Use CDN". (it's also configurable, e.g. how many score points to take away for each offender). Also within a <code>RuleSet</code> you can define what is the relative weight of each <code>Rule</code>. E.g. is F on "Expires" rule as bad as F on "CSS expressions". You can create your own <code>RuleSet</code>s (e.g. "Small blog") including an configuring any of the existing rules you like and also add more custom <code>Rules</code>. It's one big happy pool of Rules to pick from and configure. In fact YSlow 2.0 shipped with three rulesets - the new one with more rules, the old yslow1 and a "small site or blog"</p>
<p>At the end there is one central <code>lint()</code> method which takes a <code>RuleSet</code>, loops over the <code>Rule</code>s in it, calls each <code>Rule</code>'s <code>lint()</code> and collects the results into a <code>ResultSet</code>.</p>
<p><img src="http://www.phpied.com/wp-content/uploads/2011/06/4.jpg" alt=""  /></p>
<p>From there it's a question of rendering the <code>ResultSet</code>, grades, offenders, etc. Additionally there are tools that can run on the <code>ComponentSet</code> (e.g. JSLint) and stats. In addition to the YSlow UI, you should be able to render these results in any way you like, including exporting a JSON or whathaveyou.</p>
<p><img src="http://www.phpied.com/wp-content/uploads/2011/06/5.jpg" alt=""  /></p>
<h3>Whew!</h3>
<p>I may have missed some details but that's about all there is to the core of YSlow 2.0</p>
<p>Here's also a presentation that talks about these things and offers some diagrams that hopefully clarify even further</p>
<div style="width:425px" id="__ss_839679"> <strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/stoyan/yslow-20-presentation" title="YSlow 2.0">YSlow 2.0</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/839679" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
<div style="padding:5px 0 12px"> View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/stoyan">Stoyan Stefanov</a> </div>
</p></div>
<h3>Thanks for reading!</h3>
<p>That was it for today, only 4 days to go to Velocity. Hope you learned something you can use and you're ready to start coding your own rules and create rulesets to customize what YSlow can do for you.</p>
<p>To stay connected, there's now <a href="http://facebook.com/getyslow">a Facebook page for YSlow</a> and there's always the YDN (Yahoo! Developer Network) section <a href="http://developer.yahoo.com/yslow/">about YSlow</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.phpied.com/yslow-2-0-the-first-sketches/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

