<?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>Thu, 26 Apr 2012 04:04:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>5 years later: print CSS still sucks</title>
		<link>http://www.phpied.com/5-years-later-print-css-still-sucks/</link>
		<comments>http://www.phpied.com/5-years-later-print-css-still-sucks/#comments</comments>
		<pubDate>Wed, 25 Apr 2012 18:44:36 +0000</pubDate>
		<dc:creator>Stoyan</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.phpied.com/?p=1599</guid>
		<description><![CDATA[This tweet had me revise a 5 year old experiment on how print CSS affects page loading, especially in the light of mobile browsers. So I tweaked the test ever so slightly to print out timing info in the document.title and after the page is done. The test is essentially how does a slow print [...]]]></description>
			<content:encoded><![CDATA[<p>This <a href="https://twitter.com/WagnerMarkus/status/194908115387424770" title="Twitter Q">tweet</a> had me revise <a href="http://www.phpied.com/delay-loading-your-print-css/" title="Experiment print css">a 5 year old experiment</a> on how print CSS affects page loading, especially in the light of mobile browsers.</p>
<p>So I tweaked the test ever so slightly to print out timing info in the <code>document.title</code> and after the page is done. </p>
<p>The test is essentially how does a slow <em>print</em> stylesheet affect the rendering of the page on the <em>screen</em>.</p>
<div class="hl-main">
<pre><span class="hl-brackets">&lt;</span><span class="hl-reserved">link</span><span class="hl-code"> </span><span class="hl-var">rel</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">stylesheet</span><span class="hl-quotes">&quot;</span><span class="hl-code"> </span><span class="hl-var">href</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">screen.css</span><span class="hl-quotes">&quot;</span><span class="hl-code"> </span><b><span class="hl-var">media</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">screen</span><span class="hl-quotes">&quot;</span></b><span class="hl-brackets">&gt;</span><span class="hl-code">
</span><span class="hl-brackets">&lt;</span><span class="hl-reserved">link</span><span class="hl-code"> </span><span class="hl-var">rel</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">stylesheet</span><span class="hl-quotes">&quot;</span><span class="hl-code"> </span><span class="hl-var">href</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">print.css</span><span class="hl-quotes">&quot;</span><span class="hl-code">  </span><b><span class="hl-var">media</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">print</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;</span></b></pre>
</div>
<p>In the experiment I have <code>screen.css</code> delayed with 5 seconds and <code>print.css</code> delayed 10 seconds.</p>
<h3>Results 5 years ago</h3>
<p>Browsers blocked rendering waiting for print.css. Some took 10 seconds (downloading print.css and screen.css in parallel), some took 15. Why, oh why? It's a <em>print</em> CSS, you don't need this sh...eet.</p>
<h3>Results today</h3>
<p>Good guy <strong>Opera</strong>, doesn't even wait for screen.css. After some timeout, O renders unstyled page and restyles after screen.css arrives. Yes, brave O takes rendering risks this way, all others wait for the screeen.css before styling anything. Still, onload fires in ~10s, so this is bad. All your onload JS code is blocked on a useless print.css</p>
<p><strong>FF</strong> blocks rendering on the print.css. Boo! Nothing renders for 10 seconds. And it fires onload after ~10s. Boo-boo! At least it loads both stylesheets in parallel. Galaxy (<b>Android</b>) <a href="http://www.blaze.io/mobile/result/?testid=120425_7P_9SW&#038;vidid=120425_9f6ff6d731f1d4e38b95440cb71dbbfc2ab52b61&#038;src=wpt">waits for print.css too</a>. How often do you print from a mobile device? Same in <a href="http://www.webpagetest.org/result/120425_J3_54501b9db91af17b60af7fb260cb3501/1/screen_shot/"><b>IE8</b></a> and <a href="http://www.webpagetest.org/result/120425_4S_1119f7d95e264d264baae1dc1d327c77/1/screen_shot/"><b>IE9</b></a>. Even more retarded in IE is <code>DOMContentLoaded</code> event also waiting for 10 seconds. speech=less. </p>
<p><strong>Safari, Chrome, Mobile Safari</strong> - render after 5 seconds, meaning only after screen.css. There is hope for the humanity. However the onload fires in 15 seconds. So the two CSS files are downloaded sequentially. Kinda makes sense, print.css is low priority and should give way to everything else. Still could start earlier if there are no other downloads competing for precious resources.</p>
<p>So on the wall of shame - IE worst, FF yuck, Webkit bad, O least bad.</p>
<h3>Recommendation</h3>
<p>Ditch <code>media="print"</code> if you have one! (Hey why isn't this a yslow/pagespeed rule?). Ditch it because in the best case scenario it will only block onload. In the worst case it will block initial paint, onload and DOMContentLoaded. Sitting in front of a white page with no feedback is the worst possible user experience.</p>
<p>Put all (should be minimal anyway) print rules inline in your normal screen stylesheet.</p>
<div class="hl-main">
<pre><span class="hl-var">@media</span><span class="hl-code"> </span><span class="hl-identifier">print</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code">
  </span><span class="hl-identifier">body</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-reserved">font:</span><span class="hl-code"> </span><span class="hl-code">fit-to-print</span><span class="hl-reserved"></span><span class="hl-brackets">}</span><span class="hl-code">
  </span><span class="hl-identifier">.big-ads</span><span class="hl-code">, </span><span class="hl-identifier">.sidebar</span><span class="hl-code">, </span><span class="hl-identifier">.menu</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-reserved">display:</span><span class="hl-code"> </span><span class="hl-string">none</span><span class="hl-reserved"></span><span class="hl-brackets">}</span><span class="hl-code">
</span><span class="hl-brackets">}</span></pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.phpied.com/5-years-later-print-css-still-sucks/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Simple music player</title>
		<link>http://www.phpied.com/simple-music-player/</link>
		<comments>http://www.phpied.com/simple-music-player/#comments</comments>
		<pubDate>Wed, 18 Apr 2012 09:12:43 +0000</pubDate>
		<dc:creator>Stoyan</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Music]]></category>

		<guid isPermaLink="false">http://www.phpied.com/?p=1597</guid>
		<description><![CDATA[I put up a few MP3s on http://anacondalimousine.com, in simple a hrefs. While modern browsers will let you click and display some sort of player in a new page, why not play them in-page without a refresh? Simple enough. Plus we have HTML5 audio. Problem is, old IEs don't support HTML5 audio and you need [...]]]></description>
			<content:encoded><![CDATA[<p>I put up a few MP3s on <a href="http://anacondalimousine.com" title="LA's hottest band, serisously">http://anacondalimousine.com</a>, in simple <code>a href</code>s. While modern browsers will let you click and display some sort of player in a new page, why not play them in-page without a refresh? Simple enough. Plus we have HTML5 audio. Problem is, old IEs don't support HTML5 audio and you need flash or, god forbid, a Java applet to play them.</p>
<p>What's a webmaster to do? All I need is a simple PLAY button next to each link</p>
<p>While I was aware of <a href="http://www.schillmania.com/projects/soundmanager2/" title="SoundManager">SoundManager</a>, I accidentally stumbled across <a href="soundjs.com" title="SoundJS">sound.js</a> yesterday and thought I should give it a chance. Tiny (3K), it should give me an easy way to do x-browser playing with the help of some SWF for IE, I assume. Dropped the JS from their CDN (nice), but then what? "Online documentation" points to <a href="http://createjs.com/Docs/SoundJS_docs-0.2.0/" title="soundjs docs">API docs</a> which I don't feel like reading. Demos don't give you the code. Next.</p>
<p>Sound manager has a nice <a href="http://www.schillmania.com/projects/soundmanager2/demo/template/" title="sound manager basic template">"basic template"</a>. Awesome. Replace the sound.js js with SoundManager's. Load in FF. It's looking for an swf. In FF. Why? Because FF doesn't play mp3. Well, I'd rather convert the MP3 than have the user load SWF. But anyway, I drop the swf. For whatever reason (like you need a reason!) I've disabled flash in FF and forgot about it. So no sound in FF. And maybe I'm not the one. Requiring SWF in FF feels unnecessary, although I'm sure Sound Manager probably has way around it. I'm sure. I've met <a href="https://twitter.com/schill" title="Scott Schiller">the author</a>, he's brilliant. But... I still need to write some JS to initialize the playing. And if I'm to write code, might as well go solo. </p>
<p>Here's what I came up with, hope it helps.</p>
<p>Disclaimer: I haven't tested in IE, and I mean at all. <a href="http://caniuse.com/audio">Should</a> probably work in newer IEs</p>
<h3>Demo</h3>
<p><a href="http://anacondalimousine.com" title="LA's hottest band, most positively">http://anacondalimousine.com</a></p>
<h3>Codez, how they work</h3>
<p>Everything in an immediate function. Unobtrusive. Bail if (IE) browser doesn't know about <code>Audio</code>.</p>
<div class="hl-main">
<pre><span class="hl-brackets">(</span><span class="hl-reserved">function</span><span class="hl-code"> </span><span class="hl-brackets">(</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-code">!</span><span class="hl-identifier">Audio</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-reserved">return</span><span class="hl-code">;

  </span><span class="hl-comment">//</span><span class="hl-comment"> ...</span><span class="hl-comment"></span><span class="hl-code">

</span><span class="hl-brackets">}</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-brackets">)</span><span class="hl-code">;</span></pre>
</div>
<p>Codes for play and stop:</p>
<div class="hl-main">
<pre><span class="hl-reserved">var</span><span class="hl-code"> </span><span class="hl-identifier">playsym</span><span class="hl-code"> = </span><span class="hl-quotes">&quot;</span><span class="hl-string">&amp;#9654;</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">stopsym</span><span class="hl-code"> = </span><span class="hl-quotes">&quot;</span><span class="hl-string">&amp;#9632;</span><span class="hl-quotes">&quot;</span><span class="hl-code">;</span></pre>
</div>
<p>Some browsers play mp3, some OGG, so let's just change the extension and have both .mp3 and .ogg on the server</p>
<div class="hl-main">
<pre><span class="hl-reserved">var</span><span class="hl-code"> </span><span class="hl-identifier">extension</span><span class="hl-code"> = </span><span class="hl-reserved">new</span><span class="hl-code"> </span><span class="hl-identifier">Audio</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">.</span><span class="hl-identifier">canPlayType</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">audio/mpeg</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code"> === </span><span class="hl-quotes">'</span><span class="hl-quotes">'</span><span class="hl-code"> ? </span><span class="hl-quotes">'</span><span class="hl-string">ogg</span><span class="hl-quotes">'</span><span class="hl-code"> : </span><span class="hl-quotes">'</span><span class="hl-string">mp3</span><span class="hl-quotes">'</span><span class="hl-code">;</span></pre>
</div>
<p>Loop though all links on the page, find the ones that point to .mp3</p>
<div class="hl-main">
<pre><span class="hl-reserved">var</span><span class="hl-code"> </span><span class="hl-identifier">dl</span><span class="hl-code"> = </span><span class="hl-builtin">document</span><span class="hl-code">.</span><span class="hl-identifier">links</span><span class="hl-code">;
</span><span class="hl-reserved">for</span><span class="hl-code"> </span><span class="hl-brackets">(</span><span class="hl-reserved">var</span><span class="hl-code"> </span><span class="hl-identifier">i</span><span class="hl-code"> = </span><span class="hl-number">0</span><span class="hl-code">; </span><span class="hl-identifier">i</span><span class="hl-code"> &lt; </span><span class="hl-identifier">dl</span><span class="hl-code">.</span><span class="hl-identifier">length</span><span class="hl-code">; </span><span class="hl-identifier">i</span><span class="hl-code">++</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">dl</span><span class="hl-brackets">[</span><span class="hl-identifier">i</span><span class="hl-brackets">]</span><span class="hl-code">.</span><span class="hl-identifier">href</span><span class="hl-code">.</span><span class="hl-identifier">split</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">.</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">.</span><span class="hl-identifier">slice</span><span class="hl-brackets">(</span><span class="hl-code">-</span><span class="hl-number">1</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-quotes">&quot;</span><span class="hl-string">mp3</span><span class="hl-quotes">&quot;</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">continue</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">p</span><span class="hl-code"> = </span><span class="hl-builtin">document</span><span class="hl-code">.</span><span class="hl-identifier">createElement</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">button</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">;
  </span><span class="hl-identifier">p</span><span class="hl-code">.</span><span class="hl-identifier">innerHTML</span><span class="hl-code"> = </span><span class="hl-identifier">playsym</span><span class="hl-code">;
  </span><span class="hl-identifier">p</span><span class="hl-code">.</span><span class="hl-identifier">onclick</span><span class="hl-code"> = </span><span class="hl-identifier">play</span><span class="hl-code">;
  </span><span class="hl-identifier">dl</span><span class="hl-brackets">[</span><span class="hl-identifier">i</span><span class="hl-brackets">]</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">p</span><span class="hl-code">, </span><span class="hl-identifier">dl</span><span class="hl-brackets">[</span><span class="hl-identifier">i</span><span class="hl-brackets">]</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-brackets">}</span></pre>
</div>
<p>Forgot to mention, my markup is as simple as it gets:</p>
<div class="hl-main">
<pre><span class="hl-code">  </span><span class="hl-brackets">&lt;</span><span class="hl-reserved">p</span><span class="hl-brackets">&gt;</span><span class="hl-brackets">&lt;</span><span class="hl-reserved">a</span><span class="hl-code"> </span><span class="hl-var">href</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">virus.mp3</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;</span><span class="hl-code">Virus</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">a</span><span class="hl-brackets">&gt;</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">p</span><span class="hl-brackets">&gt;</span><span class="hl-code">
  </span><span class="hl-brackets">&lt;</span><span class="hl-reserved">p</span><span class="hl-brackets">&gt;</span><span class="hl-brackets">&lt;</span><span class="hl-reserved">a</span><span class="hl-code"> </span><span class="hl-var">href</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">yesterday.mp3</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;</span><span class="hl-code">Yesterday</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">a</span><span class="hl-brackets">&gt;</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">p</span><span class="hl-brackets">&gt;</span><span class="hl-code">
  </span><span class="hl-brackets">&lt;</span><span class="hl-reserved">p</span><span class="hl-brackets">&gt;</span><span class="hl-brackets">&lt;</span><span class="hl-reserved">a</span><span class="hl-code"> </span><span class="hl-var">href</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">parting.mp3</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;</span><span class="hl-code">Parting</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">a</span><span class="hl-brackets">&gt;</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">p</span><span class="hl-brackets">&gt;</span><span class="hl-code">
  </span><span class="hl-brackets">&lt;</span><span class="hl-reserved">p</span><span class="hl-brackets">&gt;</span><span class="hl-brackets">&lt;</span><span class="hl-reserved">a</span><span class="hl-code"> </span><span class="hl-var">href</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">faultline.mp3</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">&gt;</span><span class="hl-code">Faultline</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">a</span><span class="hl-brackets">&gt;</span><span class="hl-brackets">&lt;/</span><span class="hl-reserved">p</span><span class="hl-brackets">&gt;</span></pre>
</div>
<p>So all I'm doing is insert a PLAY button right before the link. Onclick it should play.</p>
<p>The play() function initializes Audio with the appropriate extension, based on what the browser supports:</p>
<div class="hl-main">
<pre><span class="hl-code">  </span><span class="hl-reserved">function</span><span class="hl-code"> </span><span class="hl-identifier">play</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-reserved">var</span><span class="hl-code"> </span><span class="hl-identifier">button</span><span class="hl-code"> = </span><span class="hl-identifier">e</span><span class="hl-code"> ? </span><span class="hl-identifier">e</span><span class="hl-code">.</span><span class="hl-identifier">target</span><span class="hl-code"> : </span><span class="hl-builtin">window</span><span class="hl-code">.</span><span class="hl-identifier">event</span><span class="hl-code">.</span><span class="hl-identifier">srcElement</span><span class="hl-code">;
    </span><span class="hl-identifier">button</span><span class="hl-code">.</span><span class="hl-identifier">innerHTML</span><span class="hl-code"> = </span><span class="hl-identifier">stopsym</span><span class="hl-code">;
    </span><span class="hl-reserved">var</span><span class="hl-code"> </span><span class="hl-identifier">a</span><span class="hl-code"> = </span><span class="hl-reserved">new</span><span class="hl-code"> </span><span class="hl-identifier">Audio</span><span class="hl-brackets">(</span><span class="hl-identifier">button</span><span class="hl-code">.</span><span class="hl-identifier">nextSibling</span><span class="hl-code">.</span><span class="hl-identifier">href</span><span class="hl-code">.</span><span class="hl-identifier">replace</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">mp3</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">extension</span><span class="hl-brackets">)</span><span class="hl-brackets">)</span><span class="hl-code">;
    </span><span class="hl-identifier">a</span><span class="hl-code">.</span><span class="hl-identifier">play</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">;</span></pre>
</div>
<p>And if you click the same button as the music plays, you stop it and reset the button click handler:</p>
<div class="hl-main">
<pre><span class="hl-code">    </span><span class="hl-identifier">button</span><span class="hl-code">.</span><span class="hl-identifier">onclick</span><span class="hl-code"> = </span><span class="hl-reserved">function</span><span class="hl-brackets">(</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">a</span><span class="hl-code">.</span><span class="hl-identifier">pause</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">;
      </span><span class="hl-identifier">button</span><span class="hl-code">.</span><span class="hl-identifier">innerHTML</span><span class="hl-code"> = </span><span class="hl-identifier">playsym</span><span class="hl-code">;
      </span><span class="hl-identifier">button</span><span class="hl-code">.</span><span class="hl-identifier">onclick</span><span class="hl-code"> = </span><span class="hl-identifier">play</span><span class="hl-code">;
    </span><span class="hl-brackets">}</span><span class="hl-code">;
  }</span></pre>
</div>
<h3>That's it</h3>
<p>So simple and tiny, it's all inline, no extra requests, not a SWF in sight. Support for <a href="http://caniuse.com/audio">72.3% of all browsers</a>. The other 30% can still download the file and play it with a separate program.</p>
<p>SoundManager and, I assume, sound.js have more features, events and other shiny, but for my simple purpose I'm so happy with the result I'll even blog about it <img src='http://www.phpied.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>For full source - view source at <a href="http://anacondalimousine.com" title="LA's hottest band, really, really">http://anacondalimousine.com</a></p>
<p>Moarr info:</p>
<ul>
<li><a href="http://dev.opera.com/articles/view/everything-you-need-to-know-about-html5-video-and-audio/" title="Opera">Article on Opera.com</a></li>
<li><a href="https://developer.mozilla.org/En/HTML/Element/Audio" title="mozilla">MDN</a></li>
</ul>
<p><b>p.s.</b> about the mp3 to ogg conversion... ffmpeg ftw:</p>
<pre>$ ffmpeg -i in.mp3 -acodec vorbis -aq 60 -strict experimental out.ogg</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.phpied.com/simple-music-player/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>The Truth about semicolons in JavaScript</title>
		<link>http://www.phpied.com/the-truth-about-semicolons-in-javascript/</link>
		<comments>http://www.phpied.com/the-truth-about-semicolons-in-javascript/#comments</comments>
		<pubDate>Tue, 17 Apr 2012 03:50:37 +0000</pubDate>
		<dc:creator>Stoyan</dc:creator>
				<category><![CDATA[Fun]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.phpied.com/?p=1594</guid>
		<description><![CDATA[jk jsdrama.com is live though. Enjoy and feel free to add more next time. (image from wikipedia)]]></description>
			<content:encoded><![CDATA[<p>jk</p>
<p><a href="http://jsdrama.com">jsdrama.com</a> is live though. Enjoy and feel <a href="https://github.com/stoyan/jsdrama">free to add</a> more next time.</p>
<p><img src="http://www.phpied.com/wp-content/uploads/2012/04/200px-Drama-icon.png" alt="" title="200px-Drama-icon" width="200" height="150" class="alignnone size-full wp-image-1595" /></p>
<p>(image from wikipedia)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.phpied.com/the-truth-about-semicolons-in-javascript/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<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>8</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>3</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>6</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>30</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>15</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>13</slash:comments>
		</item>
	</channel>
</rss>

