<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>W-Shadow.com » Blog</title>
	
	<link>http://w-shadow.com</link>
	<description>Slightly Advanced Computer Stuff (and some magic)</description>
	<lastBuildDate>Fri, 03 Sep 2010 08:17:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/wshadowcom" /><feedburner:info uri="wshadowcom" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>wshadowcom</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Automatic Updates For Private And Commercial Plugins</title>
		<link>http://feedproxy.google.com/~r/wshadowcom/~3/J-jq6bbyP1Y/</link>
		<comments>http://w-shadow.com/blog/2010/09/02/automatic-updates-for-any-plugin/#comments</comments>
		<pubDate>Thu, 02 Sep 2010 11:04:00 +0000</pubDate>
		<dc:creator>White Shadow</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[automatic updates]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[update notifications]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress plugins]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=2045</guid>
		<description><![CDATA[Since time immemorial, only plugins hosted in the official WordPress.org plugin directory have supported automatic updates. Now, I&#8217;ve written a PHP library that you can use to add automatic update capabilities to any plugin. Public, private and commercial plugins alike &#8211; all can now enjoy the benefits of automatic update notifications and one-click upgrades. The [...]]]></description>
			<content:encoded><![CDATA[<p>Since <abbr title="December 10th, 2008 - WordPress 2.7">time immemorial</abbr>, only plugins hosted in the official WordPress.org plugin directory have supported automatic updates. Now, I&#8217;ve written a PHP library that you can use to add automatic update capabilities to any plugin. Public, private and commercial plugins alike &#8211; all can now enjoy the benefits of automatic update notifications and one-click upgrades.</p>
<p>The custom update checker integrates closely with the upgrade system already built into WordPress, producing a seamless user experience. Observe : </p>
<div id="attachment_2064" class="wp-caption aligncenter" style="width: 500px;  border: 1px solid #dddddd; background-color: #f3f3f3; padding-top: 4px; margin: 10px; text-align:center; display: block; margin-right: auto; margin-left: auto;"><a href="http://w-shadow.com/wp-content/uploads/2010/09/external-upgrade-notice.png"><img src="http://w-shadow.com/wp-content/uploads/2010/09/external-upgrade-notice-490x56.png" alt="" title="Upgrade notice generated by an external plugin update" width="490" height="56" class="size-large wp-image-2064" /></a><p style=' padding: 0 4px 5px; margin: 0;'  class="wp-caption-text">An upgrade notice for a privately hosted plugin.</p></div>
<div id="attachment_2065" class="wp-caption aligncenter" style="width: 500px;  border: 1px solid #dddddd; background-color: #f3f3f3; padding-top: 4px; margin: 10px; text-align:center; display: block; margin-right: auto; margin-left: auto;"><a href="http://w-shadow.com/wp-content/uploads/2010/09/external-update-plugin-information.png"><img src="http://w-shadow.com/wp-content/uploads/2010/09/external-update-plugin-information-490x290.png" alt="" title="The &quot;Plugin Information&quot; window with placeholder data" width="490" height="290" class="size-large wp-image-2065" /></a><p style=' padding: 0 4px 5px; margin: 0;'  class="wp-caption-text">The 'Plugin Information' window with placeholder data.</p></div>
<p><em>(Excuse my marketing-speak. It&#8217;s a thing. On with the practicalities of the matter.)</em></p>
<h3>Download</h3>
<ul>
<li><strong><a href="http://w-shadow.com/files/plugin-updates.zip">Client library</a></strong> (requires PHP5 and WP 2.8 or later)</li>
<li><strong><a href="http://w-shadow.com/files/external-update-example/external-update-example.zip">Example plugin</a></strong></li>
<li><strong><a href="http://w-shadow.com/files/external-update-example/info.json">Example metadata file</a></strong></li>
</ul>
<h3>Quick-start Guide</h3>
<p>This section describes the quickest way to get automatic updates working for your plugin. Here&#8217;s what you&#8217;ll need to do: create a metadata file for your plugin, host it somewhere publicly accessible, and tell the update checker where to find it.</p>
<p>Lets start with the metadata. Copy the <a href="http://www.json.org/">JSON</a> code below into a new file and replace the placeholder values with your plugin&#8217;s info.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#123;</span>
    <span style="color: #3366CC;">&quot;name&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;My Cool Plugin&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;slug&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;my-cool-plugin&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;download_url&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;http://example.com/plugins/my-cool-plugin.zip&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;version&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;2.0&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;author&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;John Smith&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;sections&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #3366CC;">&quot;description&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Plugin description here. Basic HTML allowed.&quot;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>(This is the <em>minimal</em> amount data required to make automatic updates work. In most cases, you will probably want to add a couple more fields. See the metadata docs below for details.)</p>
<p>Most of the fields should be pretty self-explanatory, with one possible exception &#8211; the &#8220;slug&#8221;. WordPress expects all plugins that support automatic updates to have a unique textual identifier called the &#8220;slug&#8221;. Normally, slugs are assigned by the official plugin directory. For a private/commercial plugin that&#8217;s hosted elsewhere you&#8217;ll have to make something up. If unsure, just use the plugin&#8217;s file name without the &#8220;.php&#8221; extension (my-cool-plugin/my-cool-plugin.php becomes my-cool-plugin).</p>
<p>Upload the metadata file you just created to your web server. It doesn&#8217;t matter where exactly you put the file or how you name it. The important thing is for its URL to be accessible from wherever someone might install your plugin.</p>
<p>Next, copy the &#8220;update-checker&#8221; directory from the <a href="http://w-shadow.com/files/plugin-updates.zip">client library archive</a> to your plugin&#8217;s directory. Then fire up your favourite code editor and add the following lines to the top of your plugin file:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">require</span> <span style="color: #0000ff;">'plugin-updates/plugin-update-checker.php'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$MyUpdateChecker</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> PluginUpdateChecker<span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">'http://example.com/path/to/metadata.json'</span><span style="color: #339933;">,</span>
    <span style="color: #009900; font-weight: bold;">__FILE__</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'your-chosen-slug'</span>
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>(If you followed my advice and used the plugin&#8217;s file name as the slug, you can omit the third parameter of the PluginUpdateChecker constructor.)</p>
<p>And that, believe it or not, is it. </p>
<p>The PluginUpdateChecker class will handle the rest. It&#8217;ll check the metadata file every 12 hours and, if it discovers that a new version has been released, twiddle the right bits in the undocumented WP API to make it show up as a standard upgrade notification in the &#8220;Plugins&#8221; tab. Assuming you&#8217;ve set up the download_url correctly, users will be able to install the update with a single click.</p>
<p>The rest of this post will be devoted to a more in-depth discussion of the update checker class and the metadata format.</p>
<h3>The PluginUpdateChecker class</h3>
<p>This class is the core of the update checker. It&#8217;s also the only part of the updater that you should need to deal with unless you decide to  extend the library yourself.</p>
<p><strong>Class constructor</strong></p>
<p>All configuration settings should be specified by passing them to the PluginUpdateChecker constructor. It takes the following parameters :</p>
<ul>
<li><code>$metadataUrl</code> &#8211; The full URL of the plugin&#8217;s metadata file.</li>
<li><code>$pluginFile</code> &#8211; The path to the plugin&#8217;s file. In most cases you can simply use the __FILE__ constant here. Alternatively, you can also specify the path relative to the &#8220;plugins&#8221; directory, e.g. &#8220;my-cool-plugin/my-cool-plugin.php&#8221;.</li>
<li><code>$slug</code> &#8211; The plugin&#8217;s &#8216;slug&#8217;. If not specified, the filename part of $pluginFile (sans &#8220;.php&#8221;) will be used as the slug.</li>
<li><code>$checkPeriod</code> &#8211; How often to check for updates (in hours). Defaults to checking every 12 hours. Set to zero to disable automatic update checks.</li>
<li><code>$optionName</code> &#8211; Where to store book-keeping info about updates. Defaults to &#8220;external_updates-$slug&#8221;.</li>
</ul>
<p><strong>checkForUpdates()</strong></p>
<p>Manually trigger an update check. This is especially useful when you&#8217;ve disabled automatic checks by setting $checkPeriod (above) to zero. This method takes no parameters and returns nothing.</p>
<p><strong>addQueryArgFilter($callback)</strong></p>
<p>Register a callback for filtering query arguments. Whenever the update checker needs to retrieve the metadata file, it will first run each filter callback and attach the query arguments that they return to the metadata URL. This lets you pass arbitrary data to the server hosting the metadata. For example, commercial plugins could use it to implement some kind of authorization scheme where only users that have the right &#8220;key&#8221; get automatic updates.</p>
<p>The callback function will be passed an associative array of query arguments and should return a modified array. By default, the update checker will add these arguments to the metadata URL:</p>
<ul>
<li><code>installed_version</code> &#8211; set to the currently installed version of the plugin.</li>
<li><code>checking_for_updates</code> &#8211; set to 1 if checking for updates, absent otherwise (i.e. when loading data for the &#8220;Plugin Information&#8221; box).</li>
</ul>
<p>This method takes one parameter &#8211; the callback function.</p>
<p><strong>addHttpRequestArgFilter($callback)</strong></p>
<p>Register a callback for filtering the various options passed to the built-in helper function <a href="http://codex.wordpress.org/HTTP_API#Helper_Functions">wp_remote_get</a> that the update checker uses to periodically download plugin metadata. The callback function should take one argument &#8211; an associative array of arguments &#8211; and return a modified array or arguments. See the WP documentation on wp_remote_get for details about what arguments are available and how they work.</p>
<p>This method takes one parameter &#8211; the callback function.</p>
<p><strong>addResultFilter($callback)</strong></p>
<p>Register a callback for filtering plugin info retrieved from the metadata URL.</p>
<p>The callback function should take two arguments. If the metadata was retrieved successfully, the first argument passed will be an instance of  PluginInfo (see the source for a description of this class). Otherwise, it will be NULL. The second argument will be the corresponding return value of wp_remote_get (see WP docs for details). The callback function should return a new or modified instance of PluginInfo or NULL.</p>
<p>This method takes one parameter &#8211; the callback function.</p>
<h3>Metadata format</h3>
<p>The automatic update system uses a JSON-based file format to describe plugins.  Essentially, the entire file is one big JSON-encoded object (<em>AKA</em> hash-table or associative array). Each field &#8211; or array key &#8211; represents a piece of information about the latest version of the plugin. <a href="https://spreadsheets.google.com/pub?key=0AqP80E74YcUWdEdETXZLcXhjd2w0cHMwX2U1eDlWTHc&amp;authkey=CK7h9toK&amp;hl=en&amp;single=true&amp;gid=0&amp;output=html">The full description of all available fields is here.</a></p>
<p>For the sake of simplicity, both general metadata and update-related information are stored in the same file. If this is undesirable, you can replace the plain JSON file with a script that checks for the presence of the the &#8220;checking_for_updates&#8221; query parameter and emits just the update-related fields if its set to &#8220;1&#8243;.</p>
<hr/>Copyright &copy; 2010 <strong><a href="http://w-shadow.com">W-Shadow.com</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement.<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/wshadowcom?a=J-jq6bbyP1Y:VG8jMLkSCeM:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/wshadowcom?i=J-jq6bbyP1Y:VG8jMLkSCeM:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=J-jq6bbyP1Y:VG8jMLkSCeM:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=J-jq6bbyP1Y:VG8jMLkSCeM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/wshadowcom/~4/J-jq6bbyP1Y" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2010/09/02/automatic-updates-for-any-plugin/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://w-shadow.com/blog/2010/09/02/automatic-updates-for-any-plugin/</feedburner:origLink></item>
		<item>
		<title>Fixing “Memory Exhausted” Errors In WP-DBManager</title>
		<link>http://feedproxy.google.com/~r/wshadowcom/~3/ODVpdialVNk/</link>
		<comments>http://w-shadow.com/blog/2010/08/25/fix-memory-exhausted-error-wp-dbmanager/#comments</comments>
		<pubDate>Wed, 25 Aug 2010 13:30:27 +0000</pubDate>
		<dc:creator>White Shadow</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[hacks]]></category>
		<category><![CDATA[patch]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress plugins]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=2036</guid>
		<description><![CDATA[WP-DBManager is a handy plugin that can, among other things, make periodic database backups and send them to a specified email address. I installed it on this blog months ago and up until a week ago everything was working perfectly. Then one day the backup emails simply stopped coming. What Went Wrong? A quick check [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://wordpress.org/extend/plugins/wp-dbmanager/">WP-DBManager</a> is a handy plugin that can, among other things, make periodic database backups and send them to a specified email address. I installed it on this blog months ago and up until a week ago everything was working perfectly. Then one day the backup emails simply stopped coming.</p>
<h3>What Went Wrong?</h3>
<p>A quick check of the server&#8217;s error_log revealed the problem: the plugin was running out of memory.</p>

<div class="wp_syntax"><div class="code"><pre class="log" style="font-family:monospace;">[19-Aug-2010 15:47:44] PHP Fatal error:  Allowed memory size of 33554432 bytes exhausted (tried to allocate 11145167 bytes) in /home/foo/public_html/wp-content/plugins/wp-dbmanager/wp-dbmanager.php on line 101
[20-Aug-2010 15:47:49] PHP Fatal error:  Allowed memory size of 33554432 bytes exhausted (tried to allocate 10929395 bytes) in /home/foo/public_html/wp-content/plugins/wp-dbmanager/wp-dbmanager.php on line 101
[21-Aug-2010 15:47:38] PHP Fatal error:  Allowed memory size of 33554432 bytes exhausted (tried to allocate 10693507 bytes) in /home/foo/public_html/wp-content/plugins/wp-dbmanager/wp-dbmanager.php on line 101</pre></div></div>

<p>Alas, this was not all that surprising. Due to the way the mail() function works in PHP, WP-DBManager must read the entire backup file into memory before emailing it. Since the database gets bigger and bigger with each new post and comment, it will one day inevitably exceed the maximum amount of memory that PHP scripts are allowed to use and thus crash the plugin.</p>
<p>There are many ways to fix this problem, but most of them will only buy you some time. Increasing PHP memory limit will work in the short-term, but eventually the WP database will grow large enough to exceed the new limit. Similarly, cleaning up the DB &#8211; e.g. by removing old post revisions &#8211; can make it small enough that the backup file fits in the available memory. But that, too, is only a temporary solution.</p>
<h3>The Fix</h3>
<p>Ideally, the plugin shouldn&#8217;t even need to read the entire file into memory. It&#8217;s just the &#8220;convenient&#8221; design of the built-in mail() function that demands this. To solve the &#8220;allowed memory size of XXX bytes exhausted&#8221; problem once and for all, we need to replace mail() with something more flexible.</p>
<p>So, after an hour or two of hacking, I managed to rig WP-DBManager to use the free <a href="http://swiftmailer.org/">Swift Mailer library</a> instead. Among the library&#8217;s many features is the ability to send file attachments of virtually any size without worrying about memory limits. Thus enhanced, the plugin should be able to handle large backups without a hitch.</p>
<p>You can download the fixed version below. I&#8217;ve successfully installed it on my site and the periodic backup emails are rolling in again (yay!). Note, however, that due to the inclusion of the Swift Mailer library the plugin now requires PHP 5.2 or later. Make sure your server has that before trying to install the modified version.</p>
<p><a href="http://w-shadow.com/files/wp-dbmanager-modified.zip"><strong>wp-dbmanager-modified.zip</strong></a><strong> </strong>(190 KB)</p>
<hr/>Copyright &copy; 2010 <strong><a href="http://w-shadow.com">W-Shadow.com</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement.<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/wshadowcom?a=ODVpdialVNk:QFhiyX-DQOA:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/wshadowcom?i=ODVpdialVNk:QFhiyX-DQOA:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=ODVpdialVNk:QFhiyX-DQOA:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=ODVpdialVNk:QFhiyX-DQOA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/wshadowcom/~4/ODVpdialVNk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2010/08/25/fix-memory-exhausted-error-wp-dbmanager/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://w-shadow.com/blog/2010/08/25/fix-memory-exhausted-error-wp-dbmanager/</feedburner:origLink></item>
		<item>
		<title>AdSense Experiment: The Final Summary</title>
		<link>http://feedproxy.google.com/~r/wshadowcom/~3/sWAsBtEOvE8/</link>
		<comments>http://w-shadow.com/blog/2010/08/24/adsense-experiment-summary/#comments</comments>
		<pubDate>Tue, 24 Aug 2010 13:06:58 +0000</pubDate>
		<dc:creator>White Shadow</dc:creator>
				<category><![CDATA[Making Money]]></category>
		<category><![CDATA[adsense]]></category>
		<category><![CDATA[AdSense optimization]]></category>
		<category><![CDATA[charts]]></category>
		<category><![CDATA[search engine traffic]]></category>
		<category><![CDATA[summary]]></category>
		<category><![CDATA[visitor segmentation]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=2020</guid>
		<description><![CDATA[As you may remember, I&#8217;ve been running a little AdSense experiment on this site. Here&#8217;s a brief summary for new readers: The core motivation for the experiment was to test the prevalent assumption that people coming from search engines are the ones most likely to click on ads. To this end, I used a little [...]]]></description>
			<content:encoded><![CDATA[<p>As you may remember, I&#8217;ve been running a little AdSense experiment on this site. Here&#8217;s a brief summary for new readers:</p>
<blockquote><p>The core motivation for the experiment was to test the prevalent assumption that people coming from search engines are the ones most likely to click on ads. To this end, I used a little piece of JS that would present different ads to people based on how they arrived on this site – either directly, from a search engine, from another kind of external site, or from a different page on the same site. All the ads were visually identical but were tracked separately.</p>
<p><em>(See <a href="http://w-shadow.com/blog/2010/03/09/showing-different-ads-to-different-visitors/">the original announcement</a> and <a href="http://w-shadow.com/blog/2010/03/18/adsense-experiment-results/">the first summary</a> for more details.)</em></p></blockquote>
<p>The visitor segmentation script has been running uninterrupted for more than five months, allowing me to collect CTR and CPM data on more than 10 000 AdSense clicks. Overall, the trends look stable enough that running it for a while longer probably wouldn&#8217;t change the results. So now is a good time to post one final summary and declare the experiment concluded.</p>
<h3>Internal Traffic Wins</h3>
<p>At least on paper, it does. Out of all possible traffic sources, internal traffic &#8211; i.e. people who browse more than one page into the site &#8211; has the highest click-through rate and the highest eCPM. However, it also accounts for the least number of ad impressions. In a nutshell, internal traffic is valuable but rare.</p>
<p>Conversely, search engine traffic comes third in terms of CTR and eCPM, but brings the most money due to a high number of impressions.</p>
<p>The full results are below. To comply with AdSense ToS which prevent me from displaying the actual numbers, the results have been normalized to display the <em>relative</em> CTR and eCPM of various traffic sources.</p>
<p><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2023" title="CTR by Traffic Source (normalized so that the smallest value is 100%)" src="http://w-shadow.com/wp-content/uploads/2010/08/Summary-CTR-by-Traffic-Source.png" alt="" width="485" height="445" /></p>
<p><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2022" title="eCPM by Traffic Source (normalized so that the smallest value is 100%)" src="http://w-shadow.com/wp-content/uploads/2010/08/Summary-eCPM-by-Traffic-Source.png" alt="" width="485" height="445" /></p>
<h3><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2027" title="Earnings by Traffic Source (percentages)" src="http://w-shadow.com/wp-content/uploads/2010/08/Earnings-by-Traffic-Source.png" alt="" width="492" height="445" /></h3>
<h3>Source Data</h3>
<p>The above results are based on:</p>
<ul>
<li>&gt; 18 000 clicks.</li>
<li>&gt; 400 000 impressions (73% search engine traffic).</li>
</ul>
<p>All data was collected during an uninterrupted 168 day period (2010.03.09 &#8211; 2010.08.24) on this very same site. Results may be different for other sites.</p>
<hr/>Copyright &copy; 2010 <strong><a href="http://w-shadow.com">W-Shadow.com</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement.<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/wshadowcom?a=sWAsBtEOvE8:L1UoaYnWpgc:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/wshadowcom?i=sWAsBtEOvE8:L1UoaYnWpgc:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=sWAsBtEOvE8:L1UoaYnWpgc:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=sWAsBtEOvE8:L1UoaYnWpgc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/wshadowcom/~4/sWAsBtEOvE8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2010/08/24/adsense-experiment-summary/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://w-shadow.com/blog/2010/08/24/adsense-experiment-summary/</feedburner:origLink></item>
		<item>
		<title>micro-tweet – The Twitter Client That Fits In a Tweet</title>
		<link>http://feedproxy.google.com/~r/wshadowcom/~3/PVnzQNBbxR0/</link>
		<comments>http://w-shadow.com/blog/2010/08/10/micro-tweet/#comments</comments>
		<pubDate>Tue, 10 Aug 2010 10:55:23 +0000</pubDate>
		<dc:creator>White Shadow</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[command line]]></category>
		<category><![CDATA[fun]]></category>
		<category><![CDATA[minimalist]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tweet]]></category>
		<category><![CDATA[twitter client]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=1973</guid>
		<description><![CDATA[micro-tweet is an ultra-minimalist Twitter client that fits in a tweet. It can only do two things &#8211; display your friends tweets (one at a time) and post new tweets. It&#8217;s written in Python and works entirely from the command line. Source Code The source code of micro-tweet is exactly 137 characters, which is short [...]]]></description>
			<content:encoded><![CDATA[<p><em>micro-tweet</em> is an ultra-minimalist Twitter client that fits in a tweet. It can only do two things &#8211; display your friends tweets (one at a time) and post new tweets. It&#8217;s written in Python and works entirely from the command line.</p>
<h3>Source Code</h3>
<p>The source code of <em>micro-tweet</em> is exactly 137 characters, which is short enough to fit in a single tweet :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>,twitter <span style="color: #ff7700;font-weight:bold;">as</span> t<span style="color: #66cc66;">;</span>p=<span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: #66cc66;">;</span>a=t.<span style="color: black;">Api</span><span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span>p<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">;</span>m=a.<span style="color: black;">GetFriendsTimeline</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">;</span>print m.<span style="color: #dc143c;">user</span>.<span style="color: black;">name</span>+<span style="color: #483d8b;">':'</span>,m.<span style="color: black;">text</span><span style="color: #66cc66;">;</span>p<span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span>:<span style="color: black;">&#93;</span> <span style="color: #ff7700;font-weight:bold;">and</span> a.<span style="color: black;">PostUpdate</span><span style="color: black;">&#40;</span>p<span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></div></div>

<h3>Installation</h3>
<ol>
<li><a href="http://www.python.org/">Install Python</a>.</li>
<li>Install the <a href="http://cheeseshop.python.org/pypi/simplejson">simplejson</a> library.</li>
<li>Install the <a href="http://code.google.com/p/python-twitter/">python-twitter</a> library.</li>
<li>Copy the client source code (above) and paste it into a new file. Save it as &#8220;micro-tweet.py&#8221;.</li>
</ol>
<h3>Usage</h3>
<p>To run the client, execute micro-tweet.py using the Python interpreter and pass your Twitter username and password as the script arguments. This will output the latest tweet from your friends time line:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">python micro-tweet.py username password</pre></div></div>

<p>To post a status update, pass the tweet text as the third script argument. The following example will again output the latest tweet from your friends time line <em>and</em> post &#8220;Your tweet here!&#8221; (sans quotes) to Twitter:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">python micro-tweet.py username password &quot;Your tweet here!&quot;</pre></div></div>

<p>Note that the tweet text needs to be enclosed in quotes for it to be posted properly. Use "double quotes" on Windows and 'single quotes' on *nix-like systems. You will not receive any confirmation as to whether your tweet was posted successfully or not. To check, visit twitter.com or fire up a different Twitter client.</p>
<h3>Why micro-tweet?</h3>
<p>Just for fun <img src='http://w-shadow.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>micro-tweet was a little project I did over the weekend. The goal was to see if I could squeeze the essential features of a &#8220;real&#8221; Twitter client &#8211; reading and posting tweets &#8211; into less than 140 characters. It also served as a nice work-out for my rusty Python skills. </p>
<p>And yes, I&#8217;m aware that using a pre-existing library to interface with the Twitter API might be considered &#8220;cheating&#8221;, but it would be downright impossible to fit the script into the size constraints without it. The API endpoint URLs alone would probably be long enough to push the script over the limit.</p>
<hr/>Copyright &copy; 2010 <strong><a href="http://w-shadow.com">W-Shadow.com</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement.<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/wshadowcom?a=PVnzQNBbxR0:AS-b47AGl4k:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/wshadowcom?i=PVnzQNBbxR0:AS-b47AGl4k:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=PVnzQNBbxR0:AS-b47AGl4k:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=PVnzQNBbxR0:AS-b47AGl4k:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/wshadowcom/~4/PVnzQNBbxR0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2010/08/10/micro-tweet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://w-shadow.com/blog/2010/08/10/micro-tweet/</feedburner:origLink></item>
		<item>
		<title>Towards a Better dbDelta</title>
		<link>http://feedproxy.google.com/~r/wshadowcom/~3/NXS-XkuA4l4/</link>
		<comments>http://w-shadow.com/blog/2010/07/29/towards-a-better-dbdelta/#comments</comments>
		<pubDate>Thu, 29 Jul 2010 14:17:27 +0000</pubDate>
		<dc:creator>White Shadow</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[database schema]]></category>
		<category><![CDATA[dbDelta]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[php classes]]></category>
		<category><![CDATA[table diff]]></category>
		<category><![CDATA[update tables]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=1954</guid>
		<description><![CDATA[When it comes to creating and updating database tables, WordPress has what appears to be a very handy utility function &#8211; dbDelta. In theory, this function can take one or more CREATE TABLE queries, compare them to the tables already in the database and automatically figure out how to bring them up to date, adding [...]]]></description>
			<content:encoded><![CDATA[<p>When it comes to creating and updating database tables, WordPress has what appears to be a very handy utility function &#8211; <a href="http://codex.wordpress.org/Creating_Tables_with_Plugins#Creating_or_Updating_the_Table">dbDelta</a>. In theory, this function can take one or more CREATE TABLE queries, compare them to the tables already in the database and automatically figure out how to bring them up to date, adding or modifying columns and indexes as necessary.</p>
<p>In practice, <code>dbDelta</code> is fragile, undocumented and prone to fail silently when something goes wrong. It can only parse queries tailored to its idiosyncratic requirements, doesn&#8217;t know how to drop obsolete columns, isn&#8217;t aware of character sets and collation, chokes on extra whitespace&#8230; Nasty, but evidently <em>Good Enough™ </em> for most plugins, even for WordPress itself. It&#8217;s still better than doing schema updates manually, and in most cases you can work around the limitations.</p>
<p>Then again, sometimes you can&#8217;t. Just a few days ago I ran into a situation that <code>dbDelta</code> just couldn&#8217;t handle (due to the aforementioned lack of collation awareness). This prompted me to refactor dbDelta into something more flexible. The result was the <code>blcTableDelta</code> class &#8211; still somewhat finicky with regards to query syntax, but much more flexible otherwise. </p>
<p>In the remainder of this post discuss how my version compares to the built-in dbDelta function, explain how to use it, and provide the source code.</p>
<h3>Advantages</h3>
<p>My version of dbDelta is by no means perfect &#8211; or, for that matter, even particularly <em>good</em>. That would require implementing a full-blown SQL parser, which is clearly overkill for a utility function that gets called only once or twice per install. Instead, it&#8217;s just <em>Better Enough<em>™</em></em>. Here&#8217;s how blcTableDelta fares when compared to dbDelta :</p>
<ul>
<li>More lenient with whitespace &#8211; no more ridiculous requirements like &#8220;there must be exactly two spaces between the words PRIMARY KEY and the definition of your primary key&#8221;.</li>
<li>Detects changes not just in column data type, but also in collation settings and NULL/NOT NULL/AUTO INCREMENT flags.</li>
<li>Can optionally remove obsolete columns and indexes.</li>
<li>Returns a complete query log, including execution status and any MySQL error messages.</li>
<li>Doesn&#8217;t choke on &#8220;IF NOT EXISTS&#8221;.</li>
<li>Has slightly better documentation.</li>
</ul>
<p>The downside is that this class isn&#8217;t nearly as battle-tested as the native dbDelta function. It also doesn&#8217;t support INSERT queries.</p>
<h3>Usage</h3>
<p>Here&#8217;s a simple example of how to use the <code>blcTableDelta</code> class :</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//Define the table structure you want to achieve.</span>
<span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000cc; font-style: italic;">&lt;&lt;&lt;EOM
prefix}example_table` (
	`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
	`name` varchar(100) NOT NULL DEFAULT '',
	`another_field` text  COLLATE latin1_general_cs    not null,
&nbsp;
	PRIMARY    KEY   ( `id` ),
	INDEX named_index(name)
);
EOM</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Call the static delta() method</span>
<span style="color: #990000;">list</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$messages</span><span style="color: #339933;">,</span> <span style="color: #000088;">$query_log</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> blcTableDelta<span style="color: #339933;">::</span><span style="color: #004000;">delta</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Output the execution log</span>
<span style="color: #990000;">print_r</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$messages</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">print_r</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$query_log</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>The static delta() method can take up to four arguments :</p>
<ul>
<li><strong>$queries </strong>- a string containing one or more CREATE TABLE queries, separated by semicolons.</li>
<li><strong>$execute</strong> &#8211; whether to apply the required schema changes (True) or just return the generated queries (False). Defaults to executing the queries right away.</li>
<li><strong>$drop_columns</strong> &#8211; whether to remove columns that are present in the current table but not in the corresponding CREATE TABLE query (True), or leave them alone (False). Defaults to removing the columns.</li>
<li><strong>$drop_indexes</strong> &#8211; same as the previous argument, except for indexes.</li>
</ul>
<p>The function returns an array with two elements. The first element is a list of human-readable messages explaining what schema changes would need to be performed to update the database. The second returned value is the query log. Each item of the query log array is also an array, with up to three keys :</p>
<ul>
<li><strong>&#8220;query&#8221;</strong> &#8211; the generated SQL query.</li>
<li><strong>&#8220;success&#8221;</strong> &#8211; a True/False flag indicating whether the query was executed successfully. Present only if the $execute argument was set to True.</li>
<li><strong>&#8220;error_message&#8221; </strong> &#8211; the MySQL error that occurred when executing the query. Only meaningful when &#8220;success&#8221; = False.</li>
</ul>
<h3>Source Code</h3>
<p>The source code is too long to include in the post, so I&#8217;ve placed it in a separate .zip archive. <a href="http://w-shadow.com/files/db-upgrade.zip">Download it here.</a> Just place the .php file found therein somewhere inside your plugin&#8217;s directory and <code>include</code> it before calling <code>blcTableDelta::delta</code>.</p>
<hr/>Copyright &copy; 2010 <strong><a href="http://w-shadow.com">W-Shadow.com</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement.<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/wshadowcom?a=NXS-XkuA4l4:1nJH2oFeTE0:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/wshadowcom?i=NXS-XkuA4l4:1nJH2oFeTE0:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=NXS-XkuA4l4:1nJH2oFeTE0:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=NXS-XkuA4l4:1nJH2oFeTE0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/wshadowcom/~4/NXS-XkuA4l4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2010/07/29/towards-a-better-dbdelta/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://w-shadow.com/blog/2010/07/29/towards-a-better-dbdelta/</feedburner:origLink></item>
		<item>
		<title>Broken Link Checker 0.9.5 Alpha</title>
		<link>http://feedproxy.google.com/~r/wshadowcom/~3/JODoRKkmLfM/</link>
		<comments>http://w-shadow.com/blog/2010/07/28/broken-link-checker-095-alpha/#comments</comments>
		<pubDate>Wed, 28 Jul 2010 10:13:42 +0000</pubDate>
		<dc:creator>White Shadow</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[News and Rants]]></category>
		<category><![CDATA[broken link checker]]></category>
		<category><![CDATA[new features]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[public alpha]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress plugins]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=1944</guid>
		<description><![CDATA[There&#8217;s a wicked thunderstorm coming this way, so I&#8217;ll keep this short. The next major release of the Broken Link Checker plugin is nearing completion. Some of the highest voted ideas have been implemented, the user interface has been re-worked and many bugs have been fixed. Interested? Play with the alpha version, check out new [...]]]></description>
			<content:encoded><![CDATA[<p><em>There&#8217;s a wicked thunderstorm coming this way, so I&#8217;ll keep this short.</em></p>
<p>The next major release of the Broken Link Checker plugin is nearing completion. Some of the <a href="http://feedback.w-shadow.com/forums/58400-broken-link-checker">highest voted ideas</a> have been implemented, the user interface has been re-worked and many bugs have been fixed. Interested? <a href="http://downloads.wordpress.org/plugin/broken-link-checker.zip">Play with the alpha version</a>, check out new features before anyone else, submit last-minute feedback. I&#8217;m especially interested in your thoughts about the new interface &#8211; layout, colours, wording.</p>
<h3>What&#8217;s New</h3>
<p>Implemented and available right now :</p>
<ul>
<li>Individually pick the types of content to check for links.</li>
<li>Check drafts, scheduled and private posts.</li>
<li>Colour-coded &#8220;Status&#8221; column in the link table.</li>
<li>Show/hide columns selectively.</li>
<li>&#8220;Compact&#8221; table view &#8211; each row becomes exactly two lines, no text wrapping. Slick.</li>
<li>Select how many links per page to display.</li>
<li>New URL editor.</li>
<li>Tabbed interface for the settings page.</li>
</ul>
<p>Implemented, but not yet public. Probably reserved for a &#8220;Pro&#8221; version :</p>
<ul>
<li>Check embedded YouTube, DailyMotion and Vimeo videos.</li>
<li>Specialized checker algorithms for RapidShare, Mediafire and MegaUpload links.</li>
<li>Custom post type support.</li>
<li>Check plaintext URLs.</li>
</ul>
<h3>Screenshots</h3>
<p>The new &#8220;Broken Links&#8221; page (click to enlarge) :</p>
<p><a href="http://w-shadow.com/wp-content/uploads/2010/07/blc-new-version-screenshot.png"></a><a href="http://w-shadow.com/wp-content/uploads/2010/07/blc-new-version-screenshot1.png"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-large wp-image-1950" title="Broken Link Checker - new &quot;Broken Links&quot; table" src="http://w-shadow.com/wp-content/uploads/2010/07/blc-new-version-screenshot1-490x301.png" alt="" width="490" height="301" /></a></p>
<p>The new settings page :</p>
<p><a href="http://w-shadow.com/wp-content/uploads/2010/07/blc-new-settings-page.png"></a><a href="http://w-shadow.com/wp-content/uploads/2010/07/blc-new-settings-page1.png"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-large wp-image-1951" title="Broken Link Checker - tabbed &quot;Settings&quot; page" src="http://w-shadow.com/wp-content/uploads/2010/07/blc-new-settings-page1-490x216.png" alt="" width="490" height="216" /></a></p>
<p>Thoughts?</p>
<hr/>Copyright &copy; 2010 <strong><a href="http://w-shadow.com">W-Shadow.com</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement.<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/wshadowcom?a=JODoRKkmLfM:I1-CXTq8s-0:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/wshadowcom?i=JODoRKkmLfM:I1-CXTq8s-0:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=JODoRKkmLfM:I1-CXTq8s-0:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=JODoRKkmLfM:I1-CXTq8s-0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/wshadowcom/~4/JODoRKkmLfM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2010/07/28/broken-link-checker-095-alpha/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://w-shadow.com/blog/2010/07/28/broken-link-checker-095-alpha/</feedburner:origLink></item>
		<item>
		<title>Don’t Worry About Free Will</title>
		<link>http://feedproxy.google.com/~r/wshadowcom/~3/m-SPLglcWMA/</link>
		<comments>http://w-shadow.com/blog/2010/07/06/dont-worry-about-free-will/#comments</comments>
		<pubDate>Tue, 06 Jul 2010 08:29:44 +0000</pubDate>
		<dc:creator>White Shadow</dc:creator>
				<category><![CDATA[Thoughts]]></category>
		<category><![CDATA[choice]]></category>
		<category><![CDATA[determinism]]></category>
		<category><![CDATA[free will]]></category>
		<category><![CDATA[indeterminism]]></category>
		<category><![CDATA[quantum physics]]></category>
		<category><![CDATA[rants]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=1924</guid>
		<description><![CDATA[A recent pop-sci piece Think You&#8217;re Operating on Free Will? Think Again caught my eye. The article is well-written, but it focuses mostly on examples of priming and doesn&#8217;t even come close to debunking free will. However, it inspired me to write up my own thoughts on the topic. Here they are. Whether we have [...]]]></description>
			<content:encoded><![CDATA[<p>A recent pop-sci piece <a href="http://www.time.com/time/health/article/0,8599,2000994,00.html"><em>Think You&#8217;re Operating on Free Will? Think Again</em></a> caught my eye. The article is well-written, but it focuses mostly on examples of <a href="http://en.wikipedia.org/wiki/Priming_(psychology)">priming</a> and doesn&#8217;t even come close to debunking free will. However, it inspired me to write up my own thoughts on the topic. Here they are.</p>
<p>Whether we have free will is not a question of science. Nor is it a question of religion. And, despite the protestations of many, it is also not a question of philosophy.</p>
<p>Free will is mostly a matter of terminology.</p>
<p>Most people treat &#8220;free will&#8221; as something obvious, but it can be surprisingly hard to nail down the specific meaning of those two words. If you go and ask a random passer-by what they think free will is, they&#8217;ll probably say it&#8217;s something like &#8220;having a choice&#8221; or &#8220;your actions not being predetermined&#8221;. Answers like that are typical, but they don&#8217;t really stand up to scrutiny.</p>
<h3>Choice</h3>
<p>Lets consider choice first. If &#8220;free will&#8221; stands for &#8220;free choice&#8221;, then what choice is &#8220;free&#8221;? Computers can make choices &#8211; often incredibly complex and important ones &#8211; but no-one considers them to have free will. This is because a computer&#8217;s choice is deterministic: the same inputs will always produce the same outputs. No matter how complex the algorithm it runs, a computer&#8217;s behaviour is ultimately predetermined. Therefore, it does not have free will.</p>
<p>But then, how is a human different? Sure, our minds are much more complex than any computer program ever written. And certainly, our choices are influenced by a multitude of factors that would be meaningless to a machine &#8211; goals and aspirations, genetics, upbringing, unconscious urges, societal pressure, and so on. And maybe even the goals and aspirations of our mystical souls and the almighty god(s), assuming such entities exist.</p>
<p>And yet, that is still just a list of (very many) inputs. If that&#8217;s all that goes into making a choice, we are as deterministic as computers. Given the same set of goals, preferences, societal pressures, mystical influences and so on, we would make the same choice every time. The very notion of <em>making a choice</em> implies that you select one of the alternatives based on some sort of criteria (AKA inputs and algorithms); implies some amount of determinism. If it didn&#8217;t, you could just as well flip a coin.</p>
<h3>Chance</h3>
<p>Sadly, that is exactly what many explanations of &#8220;free will&#8221; end up with. Chance. Randomness. Quantum physics! Anything to escape the dread of a predetermined destiny.</p>
<p>Alas, that turn of the free will argument just leaves me confused. Am I to understand that &#8220;free will&#8221; means behaving randomly? How is that <em>better</em>? After all, if your choice is random then it wasn&#8217;t really <em>your</em> choice. This stands in stark contrast with the common assumption that having free will means being able to make your own choices.</p>
<p>Since neither deterministic nor random choice are suitable for explaining free will, <a href="http://en.wikipedia.org/wiki/Standard_argument_against_free_will#Flaw_in_the_Standard_Argument">some have argued</a> that it&#8217;s actually an amalgam of the two. Personally, this &#8220;Free Will cake mix&#8221; leaves me unimpressed. And it&#8217;s certainly not what the majority of people mean when they say &#8220;I have free will&#8221;.</p>
<div id="attachment_1931" class="wp-caption aligncenter" style="width: 310px;  border: 1px solid #dddddd; background-color: #f3f3f3; padding-top: 4px; margin: 10px; text-align:center; display: block; margin-right: auto; margin-left: auto;"><img class="size-full wp-image-1931" title="Mmm, free will." src="http://w-shadow.com/wp-content/uploads/2010/07/546579_cake2.jpg" alt="A cake" width="300" height="247" /><p style=' padding: 0 4px 5px; margin: 0;'  class="wp-caption-text">Mmm, free will.</p></div>
<h3>Conclusion</h3>
<p>As far as I can tell, free will is a confusion, a meaningless phrase. NB : I&#8217;m not saying that free will is an illusion. What I really mean is that to say &#8220;free will&#8221; is the same as to say &#8220;colourless green ideas sleep furiously&#8221;. Instead of asking whether something has free will, we should instead ask <em>specific</em> questions, e.g. &#8220;what factors guide its decisions?&#8221; and &#8220;is its behaviour deterministic or random/semi-random?&#8221;.</p>
<p>Coincidentally, the arguments used in this post are very similar to the <a href="http://en.wikipedia.org/wiki/Standard_argument_against_free_will">standard argument against free will</a>. Fancy that.</p>
<p><em>Image credit : <a href="http://www.sxc.hu/photo/546579">kefir @ sxc.hu</a></em></p>
<hr/>Copyright &copy; 2010 <strong><a href="http://w-shadow.com">W-Shadow.com</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement.<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/wshadowcom?a=m-SPLglcWMA:oe-QbtgFQhA:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/wshadowcom?i=m-SPLglcWMA:oe-QbtgFQhA:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=m-SPLglcWMA:oe-QbtgFQhA:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=m-SPLglcWMA:oe-QbtgFQhA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/wshadowcom/~4/m-SPLglcWMA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2010/07/06/dont-worry-about-free-will/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://w-shadow.com/blog/2010/07/06/dont-worry-about-free-will/</feedburner:origLink></item>
		<item>
		<title>Add New Buttons Alongside “Screen Options” And “Help”</title>
		<link>http://feedproxy.google.com/~r/wshadowcom/~3/aWEpjdM8rDU/</link>
		<comments>http://w-shadow.com/blog/2010/06/30/add-new-buttons-alongside-screen-options-and-help/#comments</comments>
		<pubDate>Wed, 30 Jun 2010 09:31:46 +0000</pubDate>
		<dc:creator>White Shadow</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[screen meta]]></category>
		<category><![CDATA[screen options]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress plugins]]></category>
		<category><![CDATA[wp]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=1911</guid>
		<description><![CDATA[Continuing from yesterday&#8217;s post about adding custom settings to the &#8220;Screen Options&#8221; panel in WP, I will now show you how to add your own buttons alongside &#8220;Screen Options&#8221; and &#8220;Help&#8221;. But first, here are a few screenshots &#8211; to whet your appetite, so to speak. Want those neat buttons in your plugin? Read on. [...]]]></description>
			<content:encoded><![CDATA[<p>Continuing from <a href="http://w-shadow.com/blog/2010/06/29/adding-stuff-to-wordpress-screen-options/">yesterday&#8217;s post</a> about adding custom settings to the &#8220;Screen Options&#8221; panel in WP, I will now show you how to add your own buttons alongside &#8220;Screen Options&#8221; and &#8220;Help&#8221;.</p>
<p>But first, here are a few screenshots &#8211; to whet your appetite, so to speak.</p>
<p><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-1914" title="An example link" src="http://w-shadow.com/wp-content/uploads/2010/06/example-meta-link-1.png" alt="" width="352" height="87" /><br />
<img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-1915" title="Meta buttons can be styled with CSS" src="http://w-shadow.com/wp-content/uploads/2010/06/more-colourful-meta-links-2.png" alt="" width="254" height="47" /><br />
<img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-1913" title="Multiple custom links on one page" src="http://w-shadow.com/wp-content/uploads/2010/06/colourful-meta-links-3.png" alt="" width="361" height="50" /></p>
<p>Want those neat buttons in your plugin? Read on.</p>
<h3>Hackety-Hack</h3>
<p>The area that holds the &#8220;Screen Options&#8221; and &#8220;Help&#8221; links is internally known as &#8220;screen meta links&#8221;. There is no official API for adding new links to this area. Fortunately, the DOM structure that represents the buttons is relatively simple, so we can attach an extra button with just a few lines of JavaScript.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#screen-meta-links'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">append</span><span style="color: #009900;">&#40;</span>
		<span style="color: #3366CC;">'&lt;div id=&quot;my-screen-meta-link-wrap&quot; class=&quot;hide-if-no-js screen-meta-toggle&quot;&gt;'</span> <span style="color: #339933;">+</span>
			<span style="color: #3366CC;">'&lt;a href=&quot;http://example.com/&quot; id=&quot;my-screen-meta-link&quot; class=&quot;show-settings&quot;&gt;Foo&lt;/a&gt;'</span> <span style="color: #339933;">+</span>
		<span style="color: #3366CC;">'&lt;/div&gt;'</span>
	<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span>jQuery<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span></pre></div></div>

<p>You&#8217;ll also need to add some extra CSS to the page to make the new button show up correctly :</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;">&lt;style type<span style="color: #00AA00;">=</span><span style="color: #ff0000;">&quot;text/css&quot;</span><span style="color: #00AA00;">&gt;</span>
<span style="color: #cc00cc;">#my-screen-meta-link-wrap</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">float</span><span style="color: #00AA00;">:</span> <span style="color: #000000; font-weight: bold;">right</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">height</span><span style="color: #00AA00;">:</span> <span style="color: #933;">22px</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">margin</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span> <span style="color: #933;">6px</span> <span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">font-family</span><span style="color: #00AA00;">:</span> <span style="color: #ff0000;">&quot;Lucida Grande&quot;</span><span style="color: #00AA00;">,</span> Verdana<span style="color: #00AA00;">,</span> Arial<span style="color: #00AA00;">,</span> <span style="color: #ff0000;">&quot;Bitstream Vera Sans&quot;</span><span style="color: #00AA00;">,</span> <span style="color: #993333;">sans-serif</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">background</span><span style="color: #00AA00;">:</span> <span style="color: #cc00cc;">#e3e3e3</span><span style="color: #00AA00;">;</span>
&nbsp;
	border-bottom-left-radius<span style="color: #00AA00;">:</span> <span style="color: #933;">3px</span><span style="color: #00AA00;">;</span>
	border-bottom-right-radius<span style="color: #00AA00;">:</span> <span style="color: #933;">3px</span><span style="color: #00AA00;">;</span>
	-moz-border-radius-bottomleft<span style="color: #00AA00;">:</span> <span style="color: #933;">3px</span><span style="color: #00AA00;">;</span>
	-moz-border-radius-bottomright<span style="color: #00AA00;">:</span> <span style="color: #933;">3px</span><span style="color: #00AA00;">;</span>
	-webkit-border-bottom-left-radius<span style="color: #00AA00;">:</span> <span style="color: #933;">3px</span><span style="color: #00AA00;">;</span>
	-webkit-border-bottom-right-radius<span style="color: #00AA00;">:</span> <span style="color: #933;">3px</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #cc00cc;">#my-screen-meta-link-wrap</span> a<span style="color: #6666ff;">.show-settings</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">background-image</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">none</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span><span style="color: #cc66cc;">0</span> <span style="color: #933;">6px</span> <span style="color: #cc66cc;">0</span> <span style="color: #933;">6px</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&lt;/style<span style="color: #00AA00;">&gt;</span></pre></div></div>

<p>These style will make your button look just like the default ones &#8211; light-grey background and dark-grey text. You can easily modify the CSS to change your button&#8217;s appearance. For example, the green &#8220;Upgrade&#8221; link pictured in one of the above screenshots has the equivalent of these extra styles applied :</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #cc00cc;">#my-screen-meta-link-wrap</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">background-color</span><span style="color: #00AA00;">:</span> <span style="color: #cc00cc;">#00C31F</span><span style="color: #00AA00;">;</span> 
<span style="color: #00AA00;">&#125;</span>
<span style="color: #cc00cc;">#my-screen-meta-link-wrap</span> a<span style="color: #6666ff;">.show-settings</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">font-weight</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">bold</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">color</span><span style="color: #00AA00;">:</span> <span style="color: #cc00cc;">#DEFFD8</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">text-shadow</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">none</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
<span style="color: #cc00cc;">#my-screen-meta-link-wrap</span> a<span style="color: #6666ff;">.show-settings</span><span style="color: #3333ff;">:hover </span><span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">color</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">white</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<h3>No API? Make one.</h3>
<p>Even such a simple hack can get cumbersome if you need to use it more than once or twice. After using it in several plugins, I went ahead and wrote a wrapper script that hides all the JS/CSS machinations behind a simple PHP interface. Here&#8217;s an example plugin that employs my custom API :</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #666666; font-style: italic;">/*
Plugin Name: Screen Meta Links Demo
Plugin URI: http://w-shadow.com/
Description: Demonstrates how to add new links alongside the &quot;Screen Options&quot; and &quot;Help&quot; links on Dashboard pages.
Version: 1.0
Author: Janis Elsts
Author URI: http://w-shadow.com/blog/
*/</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Load the custom button API</span>
<span style="color: #b1b100;">include</span> <span style="color: #0000ff;">'screen-meta-links.php'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Simple example. Adds a screen meta link to example.com </span>
<span style="color: #666666; font-style: italic;">//to the main Dashboard page.</span>
add_screen_meta_link<span style="color: #009900;">&#40;</span>
	<span style="color: #0000ff;">'meta-link-example2'</span><span style="color: #339933;">,</span>  <span style="color: #666666; font-style: italic;">//Link ID. Should be unique.  </span>
	<span style="color: #0000ff;">'Example Link'</span><span style="color: #339933;">,</span>        <span style="color: #666666; font-style: italic;">//Link text.</span>
	<span style="color: #0000ff;">'http://example.com/'</span><span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">//URL</span>
	<span style="color: #0000ff;">'index.php'</span>            <span style="color: #666666; font-style: italic;">//Where to show the link. </span>
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Advanced example. Demonstrates how to add one link to </span>
<span style="color: #666666; font-style: italic;">//several different pages and how to set link attributes.</span>
add_screen_meta_link<span style="color: #009900;">&#40;</span>
	<span style="color: #0000ff;">'meta-link-example2'</span><span style="color: #339933;">,</span> 
	<span style="color: #0000ff;">'Advanced Link'</span><span style="color: #339933;">,</span> 
	<span style="color: #0000ff;">'http://example.com/'</span><span style="color: #339933;">,</span> 
	<span style="color: #666666; font-style: italic;">//An array of page/screen IDs specifying where to display the link. </span>
	<span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
		<span style="color: #0000ff;">'options-general.php'</span><span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">//Settings -&gt; General	</span>
		<span style="color: #0000ff;">'post'</span><span style="color: #339933;">,</span>                <span style="color: #666666; font-style: italic;">//The post editor</span>
		<span style="color: #0000ff;">'page'</span><span style="color: #339933;">,</span>                <span style="color: #666666; font-style: italic;">//The page editor</span>
	<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> 
	<span style="color: #666666; font-style: italic;">//Additional attributes for the link tag.</span>
	<span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
		<span style="color: #0000ff;">'target'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'_blank'</span><span style="color: #339933;">,</span>
		<span style="color: #0000ff;">'title'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Open &quot;http://example.com/&quot; in a new window'</span>
	<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>You can <a href="http://w-shadow.com/files/screen-meta-links-demo.zip">download a working example here</a>. The <code>screen-meta-links.php</code> file is included in the archive. Feel free to use it in your own plugins.</p>
<hr/>Copyright &copy; 2010 <strong><a href="http://w-shadow.com">W-Shadow.com</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement.<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/wshadowcom?a=aWEpjdM8rDU:CykrBjKk7pM:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/wshadowcom?i=aWEpjdM8rDU:CykrBjKk7pM:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=aWEpjdM8rDU:CykrBjKk7pM:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=aWEpjdM8rDU:CykrBjKk7pM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/wshadowcom/~4/aWEpjdM8rDU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2010/06/30/add-new-buttons-alongside-screen-options-and-help/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://w-shadow.com/blog/2010/06/30/add-new-buttons-alongside-screen-options-and-help/</feedburner:origLink></item>
		<item>
		<title>Adding Stuff To WordPress “Screen Options”</title>
		<link>http://feedproxy.google.com/~r/wshadowcom/~3/pT_c18X7DzQ/</link>
		<comments>http://w-shadow.com/blog/2010/06/29/adding-stuff-to-wordpress-screen-options/#comments</comments>
		<pubDate>Tue, 29 Jun 2010 11:33:48 +0000</pubDate>
		<dc:creator>White Shadow</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[filters]]></category>
		<category><![CDATA[hooks]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[screen options]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress plugins]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=1893</guid>
		<description><![CDATA[The Screen Options pull-down is the perfect place for those &#8220;rarely used but nice to have&#8221; settings. It&#8217;s unobtrusive and saves screen space. Some plugins could even put all of their settings in this panel and avoid cluttering the Dashboard menu with yet another &#8220;Settings&#8221; page. While Screen Options were already present in older WP [...]]]></description>
			<content:encoded><![CDATA[<p><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  src="http://w-shadow.com/wp-content/uploads/2010/06/screen-options-button1.png" alt="" title="The &quot;Screen Options&quot; button" width="210" height="85" class="alignright size-full wp-image-1903" />The <em>Screen Options</em> pull-down is the perfect place for those &#8220;rarely used but nice to have&#8221; settings. It&#8217;s unobtrusive and saves screen space. Some plugins could even put all of their settings in this panel and avoid cluttering the Dashboard menu with yet another &#8220;Settings&#8221; page.</p>
<p>While <em>Screen Options</em> were already present in older WP versions, only the latest 3.0 release finally introduced a sane way to add your own content to this panel &#8211; the <code>screen_settings</code> filter. This filter is completely undocumented, so I thought it would be helpful to create a short tutorial on how to use it. Hence this post.</p>
<h3>The screen_settings Filter</h3>
<p>This <code>screen_settings</code> filter is applied to the additional HTML code that is to be appended to the <em>Screen Options</em> box. The callback function attached to this filter will receive two arguments: the current HTML code and an undocumented &#8220;screen object&#8221;. This object represents the current Dashboard screen. It has an &#8220;id&#8221; property which can be used to figure out which page/screen you&#8217;re on and only attach your extra HTML to specific pages.</p>
<p>Note that a &#8220;screen&#8221; is not the same thing as a page or a menu. For example, both the &#8220;Add Post&#8221; and &#8220;Edit Post&#8221; pages are considered to be the same screen. Luckily, in most cases you can (ab)use the <code>convert_to_screen</code> function to convert the page slug to a screen object. You can then compare the converted object&#8217;s and the current screen&#8217;s &#8220;id&#8221; attributes to check what page your script is executing on.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">add_filter<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'screen_settings'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'screen_options_demo'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">10</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">function</span> screen_options_demo<span style="color: #009900;">&#40;</span><span style="color: #000088;">$current</span><span style="color: #339933;">,</span> <span style="color: #000088;">$screen</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$desired_screen</span> <span style="color: #339933;">=</span> convert_to_screen<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'plugins.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$screen</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">id</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$desired_screen</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">id</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$current</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;Hello WordPress!&quot;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$current</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The above code will append the line &#8220;Hello WordPress!&#8221; to the <em>Screen Options</em> box on the <em>Plugins</em> page.</p>
<p><a href="http://w-shadow.com/wp-content/uploads/2010/06/screen_settings-filter-example1.png"><img style=' display: block; margin-right: auto; margin-left: auto;'  src="http://w-shadow.com/wp-content/uploads/2010/06/screen_settings-filter-example1-490x123.png" alt="" title="screen_settings filter example" width="490" height="123" class="aligncenter size-large wp-image-1904" /></a></p>
<p>For some pages &#8211; e.g. the main Dashboard page and post/page editor &#8211; you&#8217;ll need to figure out the corresponding screen ID by yourself. See the <code>set_current_screen</code> function in <code>/wp-includes/template.php</code> for clues.</p>
<p>If you specify a page that doesn&#8217;t have its own screen options, the <em>Screen Options</em> box will be added automatically and its contents will be set to the HTML code returned by your callback function. You can also compare the screen id against the hook name returned by <code>add_submenu_page</code> and its ilk to display custom screen options on plugin pages. </p>
<h3>A More Convenient Form</h3>
<p>Personally, I think the screen_settings filter is too low-level for most situations. Do you really want your callback to be executed on each and every admin page, and worry about converting between &#8220;pages&#8221; and the undocumented &#8220;screens&#8221;? And then duplicate that code (<em>boo!</em>) in each new plugin where you want to use this WP feature? Also, the extra settings fields added via this filter lack the tasty AJAX autosave feature used by the native screen options fields, which means you&#8217;d have to reimplement that as well.</p>
<p>With that in mind, I wrote a wrapper script that handles all that for you. The script has one public function named <code>add_screen_options_panel</code> which makes adding extra screen options panels as easy as adding extra menus. The function takes these arguments :</p>
<ul>
<li><strong>id</strong> &#8211; the string to use in the &#8216;id&#8217; attribute of the settings panel. Should be unique.</li>
<li><strong>title</strong> &#8211; Title of your new settings panel. Set to an empty string to omit title.</li>
<li><strong>callback</strong> &#8211; Function that fills the panel with the desired content. Should return a string of HTML.</li>
<li><strong>page</strong> &#8211; The page(s) on which to show the panel.  This can be either a string specifying a single page file name (e.g. &#8220;plugins.php&#8221;) or the hook name returned by add_submenu_page (e.g. &#8220;settings_page_my_plugin&#8221;), or an array of page filenames/hook names.</li>
<li><strong>save_callback</strong> &#8211; Optional. The name of the function that will save the settings contained in the panel.</li>
<li><strong>autosave</strong> &#8211; Optional. If set to true, panel contents will be automatically submitted (via AJAX) when the value of any field in the panel changes, and the specified save_callback function will be called with the field values. Defaults to false.</li>
</ul>
<p>Here&#8217;s an example of how this function is used in the latest version of <a href="http://wordpress.org/extend/plugins/raw-html/">my Raw HTML plugin</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">include</span> <span style="color: #0000ff;">'screen-options/screen-options.php'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Add our panel to the &quot;Screen Options&quot; box</span>
add_screen_options_panel<span style="color: #009900;">&#40;</span>
	<span style="color: #0000ff;">'rawhtml-default-settings'</span><span style="color: #339933;">,</span>       <span style="color: #666666; font-style: italic;">//Panel ID</span>
	<span style="color: #0000ff;">'Raw HTML defaults'</span><span style="color: #339933;">,</span>              <span style="color: #666666; font-style: italic;">//Panel title. </span>
	<span style="color: #0000ff;">'rawhtml_default_settings_panel'</span><span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">//The function that generates panel contents.</span>
	<span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'post'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'page'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>            <span style="color: #666666; font-style: italic;">//Pages/screens where the panel is displayed. </span>
	<span style="color: #0000ff;">'rawhtml_save_new_defaults'</span><span style="color: #339933;">,</span>      <span style="color: #666666; font-style: italic;">//The function that gets triggered when settings are submitted/saved.</span>
	<span style="color: #009900; font-weight: bold;">true</span>                              <span style="color: #666666; font-style: italic;">//Auto-submit settings (via AJAX) when they change. </span>
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">/* ...more code here...  */</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * Generate the &quot;Raw HTML defaults&quot; panel for Screen Options.
 * 
 * @return string
 */</span>
<span style="color: #000000; font-weight: bold;">function</span> rawhtml_default_settings_panel<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$defaults</span> <span style="color: #339933;">=</span> rawhtml_get_default_settings<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">//Output checkboxes </span>
	<span style="color: #000088;">$fields</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
		<span style="color: #0000ff;">'disable_wptexturize'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Disable wptexturize'</span><span style="color: #339933;">,</span>
		<span style="color: #0000ff;">'disable_wpautop'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Disable automatic paragraphs'</span><span style="color: #339933;">,</span>
		<span style="color: #0000ff;">'disable_convert_chars'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Disable convert_chars'</span><span style="color: #339933;">,</span>
		<span style="color: #0000ff;">'disable_convert_smilies'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Disable smilies'</span><span style="color: #339933;">,</span>
	 <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
 	<span style="color: #000088;">$output</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fields</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$field</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$legend</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$esc_field</span> <span style="color: #339933;">=</span> esc_attr<span style="color: #009900;">&#40;</span><span style="color: #000088;">$field</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$output</span> <span style="color: #339933;">.=</span> <span style="color: #990000;">sprintf</span><span style="color: #009900;">&#40;</span>
			<span style="color: #0000ff;">'&lt;label for=&quot;rawhtml_default-%s&quot; style=&quot;line-height: 20px;&quot;&gt;
				&lt;input type=&quot;checkbox&quot; name=&quot;rawhtml_default-%s&quot; id=&quot;rawhtml_default-%s&quot;%s&gt;
				%s
			&lt;/label&gt;&lt;br&gt;'</span><span style="color: #339933;">,</span>
			<span style="color: #000088;">$esc_field</span><span style="color: #339933;">,</span>
			<span style="color: #000088;">$esc_field</span><span style="color: #339933;">,</span>
			<span style="color: #000088;">$esc_field</span><span style="color: #339933;">,</span>
			<span style="color: #009900;">&#40;</span><span style="color: #000088;">$defaults</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$field</span><span style="color: #009900;">&#93;</span>?<span style="color: #0000ff;">' checked=&quot;checked&quot;'</span><span style="color: #339933;">:</span><span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
			<span style="color: #000088;">$legend</span>
		<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$output</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * Process the &quot;Raw HTML defaults&quot; form fields and save new settings
 * 
 * @param array $params
 * @return void
 */</span>
<span style="color: #000000; font-weight: bold;">function</span> rawhtml_save_new_defaults<span style="color: #009900;">&#40;</span><span style="color: #000088;">$params</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #666666; font-style: italic;">//Get current defaults</span>
	<span style="color: #000088;">$defaults</span> <span style="color: #339933;">=</span> rawhtml_get_default_settings<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">//Read new values from the submitted form</span>
	<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$defaults</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$field</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$old_value</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'rawhtml_default-'</span><span style="color: #339933;">.</span><span style="color: #000088;">$field</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'rawhtml_default-'</span><span style="color: #339933;">.</span><span style="color: #000088;">$field</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'on'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$defaults</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$field</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$defaults</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$field</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">//Store the new defaults</span>
	rawhtml_set_default_settings<span style="color: #009900;">&#40;</span><span style="color: #000088;">$defaults</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>And here&#8217;s the result :</p>
<p><a href="http://w-shadow.com/wp-content/uploads/2010/06/Raw-HTML-screen-options2.png"><img style=' display: block; margin-right: auto; margin-left: auto;'  src="http://w-shadow.com/wp-content/uploads/2010/06/Raw-HTML-screen-options2-490x239.png" alt="" title="RawHTML screen options" width="490" height="239" class="aligncenter size-large wp-image-1905" /></a></p>
<p>You can <a href="http://w-shadow.com/files/screen-options.zip">download the wrapper script here</a>. To use it in your plugin, just drop the &#8220;screen-options&#8221; folder into your plugin&#8217;s directory and <code>include</code> the screen-options.php file. Then call the <code>add_screen_options_panel</code> function as described above. </p>
<p>Bonus: the file is structured in a way that lets multiple plugins execute it without causing conflicts <img src='http://w-shadow.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<hr/>Copyright &copy; 2010 <strong><a href="http://w-shadow.com">W-Shadow.com</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement.<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/wshadowcom?a=pT_c18X7DzQ:VNbmRbK9oac:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/wshadowcom?i=pT_c18X7DzQ:VNbmRbK9oac:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=pT_c18X7DzQ:VNbmRbK9oac:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=pT_c18X7DzQ:VNbmRbK9oac:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/wshadowcom/~4/pT_c18X7DzQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2010/06/29/adding-stuff-to-wordpress-screen-options/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://w-shadow.com/blog/2010/06/29/adding-stuff-to-wordpress-screen-options/</feedburner:origLink></item>
		<item>
		<title>Pure CSS Perversion</title>
		<link>http://feedproxy.google.com/~r/wshadowcom/~3/Mn0k9Wqiy8Q/</link>
		<comments>http://w-shadow.com/blog/2010/06/16/pure-css-perversion/#comments</comments>
		<pubDate>Wed, 16 Jun 2010 16:47:44 +0000</pubDate>
		<dc:creator>White Shadow</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[CSS hack]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[image converter]]></category>
		<category><![CDATA[image handling]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[pure CSS image]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=1876</guid>
		<description><![CDATA[Sometimes it seems that not a month goes by without another &#8220;Pure CSS Something&#8221; project. Most recently, it was the Pure CSS Twitter &#8220;Fail Whale&#8221; page that has been making the rounds on Twitter and social news sites for the last few days. Before that, we had the Opera logo made in CSS, and many, [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes it seems that not a month goes by without another <em>&#8220;Pure CSS Something&#8221;</em> project. Most recently, it was the <a href="http://www.subcide.com/experiments/fail-whale/">Pure CSS Twitter &#8220;Fail Whale&#8221;</a> page that has been making the rounds on Twitter and social news sites for the last few days. Before that, we had the <a href="http://desandro.com/articles/opera-logo-css/">Opera logo made in CSS</a>, and many, many others.</p>
<p>It got me wondering &#8211; could one write a program that converts <em>any</em> image into pure CSS &amp; HTML?</p>
<p>As it turns out, <a href="http://elliottback.com/wp/convert-image-to-css/">that&#8217;s already been done</a>. However, I was pretty sure it could be done <em>better</em> &#8211; despite limiting the maximum output resolution to 100&#215;100, the CSS/HTML code produced by the aforementioned converter was truly humongous. Surely I could improve on that. Thus I went ahead and wrote my own image to CSS converter anyway.</p>
<p>The result, lovingly code-named &#8220;Pure CSS Perversion&#8221;, produces remarkably space-efficient* HTML and CSS code for a wide range of input images. You can <a href="http://w-shadow.com/css-anything/">try it out here</a>. </p>
<p><em>*Only in the context of image-to-CSS conversion. It&#8217;s laughably inefficient when compared to most image file formats.</em></p>
<h3>Awesome Features</h3>
<ul>
<li><strong>Highly perverse HTML/CSS coding</strong><br />
Almost as space-efficient as storing your images in uncompressed bitmaps!</li>
<li><strong>Glorious 256 color palette<br />
</strong>Evokes fond memories of DOS and VGA.<strong><br />
</strong></li>
<li><strong>Dithering support<br />
</strong>Greatly improves image quality with only an enormous increase in file size.<strong><br />
</strong></li>
<li><strong>Cross-browser compatibility</strong><br />
Tested in Firefox 3.6, Opera 10.53, Chrome 6.0, and even Internet Explorer 8.</li>
<li><strong>Supports JPG, PNG and GIF<br />
</strong>Also supports PCX, ARJ and ponies. Okay, not really.</li>
</ul>
<h3>Examples</h3>
<p>Click a screenshot to go to the corresponding converter results page.</p>
<p><a href="http://w-shadow.com/css-anything/process.php?url=http%3A%2F%2Fw-shadow.com%2Fcss-anything%2Fexamples%2FMona_Lisa.jpg&amp;submit=Go&amp;max_width=300&amp;max_height=270&amp;max_colors=256&amp;box_size=1&amp;rle=50"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-1880" title="Pure CSS Mona Lisa" src="http://w-shadow.com/wp-content/uploads/2010/06/converted-image-2.png" alt="" width="298" height="425" /></a></p>
<h3><a href="http://w-shadow.com/css-anything/process.php?url=http%3A%2F%2Fw-shadow.com%2Fcss-anything%2Fexamples%2F%2527Recycle%25202%2527%2520by%2520jaylopez%2520%2528sxc.hu%2529.jpg&amp;submit=Go&amp;max_width=300&amp;max_height=250&amp;max_colors=256&amp;box_size=1&amp;rle=50&amp;dither=on"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-1879" title="Pure CSS &quot;Recycle&quot; tag" src="http://w-shadow.com/wp-content/uploads/2010/06/converted-image-1.png" alt="" width="319" height="375" /></a></h3>
<h3><a href="http://w-shadow.com/css-anything/process.php?url=http%3A%2F%2Fw-shadow.com%2Fcss-anything%2Fexamples%2FCornell_box.png&amp;max_width=300&amp;max_height=300&amp;max_colors=256&amp;box_size=auto&amp;rle=50&amp;dither=0"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-1878" title="Some boxes?... But hey, it's pure CSS and HTML!" src="http://w-shadow.com/wp-content/uploads/2010/06/converted-image-3.png" alt="" width="326" height="455" /></a></h3>
<p>You can find more examples on the <a href="http://w-shadow.com/css-anything/">converter&#8217;s homepage</a>.</p>
<h3>Descent Into Optimization</h3>
<p>For those interested in such things, here is a detailed explanation of how the converter works, including a tedious step-by-step account of how I arrived to the current algorithm. You can also <a href="http://w-shadow.com/files/css-anything.rar">download the source code</a>.</p>
<p><strong>1. Starting Simple</strong><br />
The simplest way to encode an image as HTML/CSS is to convert each image pixel to a separate &lt;div&gt; element 1&#215;1 pixels in size and use an inline style attribute set the div&#8217;s background color to that of the pixel. Example :</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;css-image&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;row&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">style</span>=<span style="color: #ff0000;">&quot;background: #abcdef; width: 1px; height: 1px;&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">style</span>=<span style="color: #ff0000;">&quot;background: #abcdef; width: 1px; height: 1px;&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #808080; font-style: italic;">&lt;!-- more pixels --&gt;</span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;row&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">style</span>=<span style="color: #ff0000;">&quot;background: #abcdef; width: 1px; height: 1px;&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">style</span>=<span style="color: #ff0000;">&quot;background: #abcdef; width: 1px; height: 1px;&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #808080; font-style: italic;">&lt;!-- more pixels --&gt;</span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #808080; font-style: italic;">&lt;!-- more rows/scanlines --&gt;</span></pre></div></div>

<p>This produces good-looking results, but the amount of HTML code quickly balloons out of control. Even a modest 200&#215;200 picture would result take up over 1 MB when encoded in this way, which is wasteful and can even crash some browsers.</p>
<p><strong>2. Palletise and Cassify</strong><br />
The easiest way to reduce the file size of the &#8220;pure CSS&#8221; image is to convert it to a palette-based format and create a new CSS class for each palette color. This is what my first version of the image-to-CSS converter did.</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;style<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
div { width: 1px; height: 1px; float: left; }
.color1 { background: #abcdef; }
.color2 { background: #f00000; }
/*....*/
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/style<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
...
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;color1&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;color2&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>As you can see, I&#8217;ve also moved the rules that apply to all DIVs to a separate CSS block.</p>
<p><strong>3. Run-Length Encoding</strong><br />
To further reduce the code size, we can detect continuous runs of the same color and encode each of them using only a single, wider &lt;div&gt;. To avoid explicitly writing out the width of each element, lets generate CSS classes for widths :</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;style<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
.width2 { width: 2px; }
.width3 { width: 3px; }
.width4 { width: 4px; }
.width5 { width: 5px; }
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/style<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
...
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;color1 width3&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>All &lt;div&gt;&#8217;s have a 1-pixel width by default, so we don&#8217;t need a &#8220;width1&#8243; class.</p>
<p><strong>4. Shorter Class Names</strong><br />
All those &#8220;colorA&#8221; and &#8220;widthB&#8221; class names are wastefully long. Lets shorten them to a single-letter prefix and a hex-encoded index.</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;style<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
.c1 { background: #abcdef; }
.c2 { background: #f00000; }
/* ... */
.w9 { width: 9px; }
.wa { width: 10px; }
.wb { width: 11px; }
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/style<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;c2a wf&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;c2 wa2&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>...</pre></div></div>

<p><strong>5. Default Colors</strong><br />
We can squeeze out a few more bytes by determining the color that&#8217;s most frequently used in a given row and adding it as the background color to the container element. Then we can omit the color class from those elements that match the most common color.</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;c2&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;c1&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><span style="color: #808080; font-style: italic;">&lt;!-- matches the row's background color --&gt;</span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;c3&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p><strong>6. Perversion Begins</strong><br />
Hmm, look at all those byte-hogging &lt;div&gt; elements &#8211; each eating up 3 bytes on tag name alone. Plus, we&#8217;re forced to waste another 6 bytes on the completely useless closing tag! That will not do. </p>
<p>Luckily, the closing tags are optional for &lt;p&gt; and &lt;li&gt; elements. We can rework our HTML structure to make use of this.</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;css-image&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;ul<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;li<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;p</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;c1 w2&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;p</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;c3&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;p</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;cba w5&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #808080; font-style: italic;">&lt;!-- more pixels --&gt;</span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;li<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;p</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;c1 w2&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;p</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;c3&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;p</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;cba w5&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #808080; font-style: italic;">&lt;!-- more pixels --&gt;</span>
&nbsp;
   <span style="color: #808080; font-style: italic;">&lt;!-- more rows --&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ul<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p><strong>7. Going Classless</strong><br />
We&#8217;re also wasting 5 bytes/div on the &#8220;class&#8221; attribute, so lets get rid of it and use custom attributes instead.</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;style<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
p[c=&quot;1&quot;],li[c=&quot;1&quot;]{ background: #abcdef; }
p[c=&quot;2&quot;],li[c=&quot;2&quot;]{ background: #f00000; }
/*...*/
p[w=&quot;9&quot;]{ width: 9px; }
p[w=&quot;a&quot;]{ width: 10px; }
p[w=&quot;b&quot;]{ width: 11px; }
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/stlye<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #808080; font-style: italic;">&lt;!-- ... --&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;p</span> <span style="color: #000066;">c</span>=<span style="color: #ff0000;">&quot;1&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;p</span> <span style="color: #000066;">c</span>=<span style="color: #ff0000;">&quot;16&quot;</span> <span style="color: #000066;">w</span>=<span style="color: #ff0000;">&quot;5&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;p</span> <span style="color: #000066;">c</span>=<span style="color: #ff0000;">&quot;ab&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span></pre></div></div>

<p>It may not validate, but it works. Who cares about validation anyway? <img src='http://w-shadow.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><strong>8. Even More Perversion</strong><br />
Well, that&#8217;s probably the limit of size optimization. We need to specify the background color and width <em>somehow</em>, so we can&#8217;t completely eliminate the attributes. We could remove the quotes from attribute values and format our output like &#8220;&lt;p c=1 w=ab&gt;&#8221;, but that&#8217;s it. Right?</p>
<p>Actually, there <em>is</em> a way to compress the output even more. We can use the attribute name itself to specify pixel color and width. Observe :</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;style<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
p[c1],li[c1]{ background: #abcdef; }
p[c2],li[c2]{ background: #f00000; }
/*...*/
p[w9]{ width: 9px; }
p[wa]{ width: 10px; }
p[wb]{ width: 11px; }
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/stlye<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #808080; font-style: italic;">&lt;!-- ... --&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;p</span> c1<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;p</span> c16 w5<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;p</span> cab<span style="color: #000000; font-weight: bold;">&gt;</span></span></pre></div></div>

<p>Yes, that actually works. It even works in Internet Explorer 8 (when in standards mode).</p>
<p><strong>9. Huffman And Friends</strong><br />
In any given image, some colors are more common than others. For example, a picture of a lush countryside might have a lot of greens, whereas a beach photo would be predominantly blue and yellow. Our current algorithm is not aware of that &#8211; it simply enumerates all colors in sequential order, assigning attribute names as it goes. There&#8217;s no relation between the color and the codename it gets.</p>
<p>We can reduce output size by assigning shorter attribute names to more common colors. This is known as <a href="http://en.wikipedia.org/wiki/Huffman_coding">Huffman coding</a>, and is one of the simplest algorithms used for lossless data compression.</p>
<p>The general idea is thus : </p>
<ul>
<li>Iterate over the image and record how many times each color is seen.</li>
<li>Sort the list of colors by their frequency.</li>
<li>Assign shorter names to more common colors, longer ones to rare ones.</li>
</ul>
<p>In fact, we can use this idea to eliminate the color vs. width attribute distinction completely. Lets look at our HTML stucture again :</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;p</span> c1<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;p</span> c16 w5<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;p</span> cab<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;p</span> ce2<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;p</span> c1 w12<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #808080; font-style: italic;">&lt;!-- ... --&gt;</span></pre></div></div>

<p>If we forget the &#8220;&lt;p &#8230;&gt;&#8221; wrappers for a moment&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">c1 c16 w5 cab ce2 c1 w12</pre></div></div>

<p>&#8230;it&#8217;s just a string of codes! Some more common, some less. We don&#8217;t need to know what each of them means to assign a optimally short and unique name to each one.</p>
<p>The actual implementation is somewhat complicated, but the HTML/CSS it produces is very space-efficient. This is what the output of my final algorithm looks like (line breaks inserted for clarity) :</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;style<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
p[a]{width:6px;}
p[b],li[b]{background:#dfdbda;}
p[c]{width:9px;}
p[d],li[d]{background:#dfe3e8;}
p[e],li[e]{background:#d4d5dc;}
/*...*/
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/style<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #808080; font-style: italic;">&lt;!-- ... --&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;css-image&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;ul<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;li</span> y<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;p</span> d f<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;p</span> b c<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;p</span> d a<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;p</span> b xb<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;p</span> o<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;p</span> b _g<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;p</span> e<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;p</span> b l<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #808080; font-style: italic;">&lt;!-- etc --&gt;</span></pre></div></div>

<h3>Improve On <em>That</em></h3>
<p>Unbelievable though it may seem, this is <em>still</em> not the limit of size optimization for &#8220;pure CSS&#8221; images. For example, you could use variable-width right and left borders on the &lt;p&gt; element to encode additional pixels in a single element. This would decrease the HTML size at least by another 20%. You could also replace the primitive RLE algorithm I used in my converter with something more advanced. There might also be some interesting HTML hacks I haven&#8217;t even thought about.</p>
<p>I&#8217;ll leave that as an exercise to the reader <img src='http://w-shadow.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<hr/>Copyright &copy; 2010 <strong><a href="http://w-shadow.com">W-Shadow.com</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement.<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/wshadowcom?a=Mn0k9Wqiy8Q:59lM3xqFfME:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/wshadowcom?i=Mn0k9Wqiy8Q:59lM3xqFfME:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=Mn0k9Wqiy8Q:59lM3xqFfME:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=Mn0k9Wqiy8Q:59lM3xqFfME:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/wshadowcom/~4/Mn0k9Wqiy8Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2010/06/16/pure-css-perversion/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		<feedburner:origLink>http://w-shadow.com/blog/2010/06/16/pure-css-perversion/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 2.982 seconds. --><!-- Cached page generated by WP-Super-Cache on 2010-09-08 09:13:03 -->
