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

<channel>
	<title>W-Shadow.com &#187; Programming</title>
	<atom:link href="http://w-shadow.com/blog/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://w-shadow.com</link>
	<description>Slightly Advanced Computer Stuff (and some magic)</description>
	<lastBuildDate>Fri, 12 Mar 2010 19:43:46 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Showing Different Ads To Different Visitors</title>
		<link>http://w-shadow.com/blog/2010/03/09/showing-different-ads-to-different-visitors/</link>
		<comments>http://w-shadow.com/blog/2010/03/09/showing-different-ads-to-different-visitors/#comments</comments>
		<pubDate>Tue, 09 Mar 2010 16:38:42 +0000</pubDate>
		<dc:creator>White Shadow</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[a/b testing]]></category>
		<category><![CDATA[adsense]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Making Money]]></category>
		<category><![CDATA[online advertising]]></category>
		<category><![CDATA[referrer]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=1740</guid>
		<description><![CDATA[Just today, I decided to run an impromptu experiment to test if visitors who come from search engines are really more likely to click on ads. It&#8217;s considered  &#8221;common knowledge&#8221; by many bloggers who advise everyone to only show ads to search engine visitors (as a quick Google search will illustrate), but my own AdSense [...]]]></description>
			<content:encoded><![CDATA[<p>Just today, I decided to run an impromptu experiment to test if visitors who come from search engines are really more likely to click on ads. It&#8217;s considered  &#8221;common knowledge&#8221; by many bloggers who advise everyone to only show ads to search engine visitors (as a <a href="http://www.google.com/search?q=show+ads+search+engine+visitors">quick Google search</a> will illustrate), but my own AdSense stats made me doubt that particular piece of advice. Hence the experiment.</p>
<p>So how does one show different ads to different visitors? Normally you could use the excellent <a href="http://planetozh.com/blog/my-projects/wordpress-plugin-who-sees-ads-control-adsense-display/">Who Sees Ads</a> plugin, but that doesn&#8217;t work for my site. I&#8217;m using the <a href="http://wordpress.org/extend/plugins/wp-super-cache/">WP-SuperCache</a> caching plugin which is incompatible with Who Sees Ads.</p>
<p>Instead, I wrote a JavaScript function that can analyse the HTTP referrer to distinguish between four types of visitors :</p>
<ul>
<li>People who accessed your page directly, e.g. by typing in the URL (no referrer).</li>
<li>People who clicked an internal link to access the page (referrer from the same domain).</li>
<li>Search engine visitors; people who arrived via Google or Yahoo! (referrer matches one of the most popular search engines).</li>
<li>External visitors. This is basically a catch-all category for everyone who found your link on a third-party site that&#8217;s not a search engine. For example, this would include external forums and web directories.</li>
</ul>
<p>Here&#8217;s the script :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> get_referrer_type<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> ref <span style="color: #339933;">=</span> document.<span style="color: #660066;">referrer</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> ref.<span style="color: #660066;">length</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">'none'</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #003366; font-weight: bold;">function</span> getHostname<span style="color: #009900;">&#40;</span>str<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #003366; font-weight: bold;">var</span> re <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/^(?:f|ht)tp(?:s)?\:\/\/([^\/]+)/im</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> matches <span style="color: #339933;">=</span> str.<span style="color: #660066;">match</span><span style="color: #009900;">&#40;</span> re <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> matches <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000066; font-weight: bold;">return</span> matches<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> getHostname<span style="color: #009900;">&#40;</span>ref<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> document.<span style="color: #660066;">location</span>.<span style="color: #660066;">host</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">'internal'</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #003366; font-weight: bold;">var</span> SE <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'/search?'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'.google.'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'web.info.com'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'search.'</span><span style="color: #339933;">,</span> 
		<span style="color: #3366CC;">'del.icio.us/search'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'soso.com'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'/search/'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'.yahoo.'</span><span style="color: #339933;">,</span>
		<span style="color: #3366CC;">'.ask.'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">var</span> source <span style="color: #000066; font-weight: bold;">in</span> SE<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>ref.<span style="color: #660066;">indexOf</span><span style="color: #009900;">&#40;</span>SE<span style="color: #009900;">&#91;</span>source<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=-</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">'search'</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">'external'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The function <code>get_referrer_type()</code> returns one of &#8220;none&#8221;, &#8220;internal&#8221;, &#8220;search&#8221; or &#8220;external&#8221; based on the referrer info.</p>
<p>And here&#8217;s the script that I used to show different  AdSense ads to different people :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> get_top_adsense_ad<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> default_slot <span style="color: #339933;">=</span> <span style="color: #3366CC;">'1111111111'</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> code <span style="color: #339933;">=</span> <span style="color: #3366CC;">'&lt;'</span><span style="color: #339933;">+</span><span style="color: #3366CC;">'script type=&quot;text/javascript&quot;&gt;&lt;!--<span style="color: #000099; font-weight: bold;">\n</span>google_ad_client = &quot;pub-0000000000000000&quot;;google_ad_slot = &quot;%ad_slot%&quot;;google_ad_width = 336;google_ad_height = 280;<span style="color: #000099; font-weight: bold;">\n</span>//--&gt;&lt;'</span><span style="color: #339933;">+</span><span style="color: #3366CC;">'/script&gt;&lt;'</span><span style="color: #339933;">+</span><span style="color: #3366CC;">'script type=&quot;text/javascript&quot; src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;&lt;/'</span><span style="color: #339933;">+</span><span style="color: #3366CC;">'script&gt;'</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> slots <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #3366CC;">'none'</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">'2222222222'</span><span style="color: #339933;">,</span>
		<span style="color: #3366CC;">'internal'</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">'3333333333'</span><span style="color: #339933;">,</span>
		<span style="color: #3366CC;">'external'</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">'4444444444'</span><span style="color: #339933;">,</span>
		<span style="color: #3366CC;">'search'</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">'5555555555'</span><span style="color: #339933;">,</span>
	<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #003366; font-weight: bold;">var</span> ref_type <span style="color: #339933;">=</span> get_referrer_type<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000066; font-weight: bold;">typeof</span><span style="color: #009900;">&#40;</span>slots<span style="color: #009900;">&#91;</span>ref_type<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #3366CC;">'undefined'</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		code <span style="color: #339933;">=</span> code.<span style="color: #660066;">replace</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'%ad_slot%'</span><span style="color: #339933;">,</span> slots<span style="color: #009900;">&#91;</span>ref_type<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
		code <span style="color: #339933;">=</span> code.<span style="color: #660066;">replace</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'%ad_slot%'</span><span style="color: #339933;">,</span> default_slot<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000066; font-weight: bold;">return</span> code<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
document.<span style="color: #000066; font-weight: bold;">write</span><span style="color: #009900;">&#40;</span>get_top_adsense_ad<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Unlike <code>get_referrer_type()</code>, this script is optimized for my site/AdSense account. Don&#8217;t try using it without modification <img src='http://w-shadow.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  If you want to use it, replace &#8220;pub-XXXXXXXX&#8221;, the ad slot IDs and ad width/height settings with your own values (you can find them in your AdSense ad code).</p>
<p>As for the experiment, I&#8217;ll post the results sometime next week.</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. Please contact legal@w-shadow.com so we can take legal action immediately.]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2010/03/09/showing-different-ads-to-different-visitors/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>12 Invisible But Invaluable jQuery Plugins</title>
		<link>http://w-shadow.com/blog/2010/03/05/12-invisible-but-invaluable-jquery-plugins/</link>
		<comments>http://w-shadow.com/blog/2010/03/05/12-invisible-but-invaluable-jquery-plugins/#comments</comments>
		<pubDate>Fri, 05 Mar 2010 20:28:02 +0000</pubDate>
		<dc:creator>White Shadow</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[cookies]]></category>
		<category><![CDATA[DOM]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[jQuery plugins]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[keyboard shortcuts]]></category>
		<category><![CDATA[lists]]></category>
		<category><![CDATA[mouse wheel]]></category>
		<category><![CDATA[utilities]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=1729</guid>
		<description><![CDATA[Not all jQuery plugins are about UI and eye-candy. There&#8217;s also a class of plugins that aim to make web development itself easier, either by acting as convenient wrappers around hard-to-use JavaScript functionality, simplifying cross-browser compatibility, or providing small but useful utilities and APIs.
Below you&#8217;ll find a list of 12 great utility-style jQuery plugins. While [...]]]></description>
			<content:encoded><![CDATA[<p>Not all jQuery plugins are about UI and eye-candy. There&#8217;s also a class of plugins that aim to make web development itself easier, either by acting as convenient wrappers around hard-to-use JavaScript functionality, simplifying cross-browser compatibility, or providing small but useful utilities and APIs.</p>
<p><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-1734" title="JQuery logo" src="http://w-shadow.com/wp-content/uploads/2010/03/JQuery_logo_color_onwhite-200.png" alt="" width="200" height="49" />Below you&#8217;ll find a list of 12 great utility-style jQuery plugins. While invisible to the user, they can be invaluable to the developer.</p>
<h3>1. <a href="http://code.google.com/p/js-hotkeys/">Hotkeys</a></h3>
<p>The <a href="http://code.google.com/p/js-hotkeys/">HotKeys plugin</a> makes it very easy to hook almost any key or key combination. Great for adding keyboard shortcuts to your web-app.</p>
<h3>2. <a href="http://brandonaaron.net/code/mousewheel/docs">Mouse Wheel</a></h3>
<p>Detect when the user scrolls the <a href="http://brandonaaron.net/code/mousewheel/docs">mouse wheel</a>. Note : In theory, the plugin supports all major browsers. However, the current version may report inconsistent scroll deltas in different browsers.</p>
<h3>3. <a href="http://www.fyneworks.com/jquery/xml-to-json/">XML to JSON</a></h3>
<p><a href="http://www.fyneworks.com/jquery/xml-to-json/">XML to JSON</a> lets you convert XML documents to JSON. Handy if you find plain JS objects easier to use than the XML DOM, or if you&#8217;re building a mashup with heterogeneous data coming in from a bunch of APIs and you want to convert it all to JSON for simplicity.</p>
<h3>4. <a href="http://projects.allmarkedup.com/jquery_url_parser/">URL Parser</a></h3>
<p><a href="http://projects.allmarkedup.com/jquery_url_parser/">jQuery URL parser</a> processes URLs and provides you with easy access to info about their components &#8211; the protocol, host, path, query string, and so on. On top of that, it also has some neat extra features, like the ability access query parameter values by parameter name.</p>
<h3>5. <a href="http://www.malsup.com/jquery/taconite/">Taconite</a></h3>
<p>With <a href="http://www.malsup.com/jquery/taconite/">Taconite</a>, you can update multiple DOM elements with a single AJAX request. This can considerably simplify your client-side code and helps cut down on bandwidth use.</p>
<h3>6. <a href="http://www.protofunc.com/scripts/jquery/ajaxManager3/">AJAX Manager</a></h3>
<p>Queue, order, abort, block, cache and otherwise manipulate your AJAX requests with the <a href="http://www.protofunc.com/scripts/jquery/ajaxManager3/">AJAX manager</a> plugin.</p>
<h3>7. <a href="http://www.pengoworks.com/workshop/jquery/calculation/calculation.plugin.htm">Calculation</a></h3>
<p>The <a href="http://www.pengoworks.com/workshop/jquery/calculation/calculation.plugin.htm">jQuery Calculation Plugin</a> lets you extract numeric data from HTML elements and apply a number of common mathematical operations to the results. It includes typical aggregation functions like sum(), avg(), min() and max() and also lets you define your own equations.</p>
<h3>8. <a href="http://stackoverflow.com/questions/1809275/suppress-jquery-event-handling-temporarily/1810532#1810532">Freeze/Unfreeze Events</a></h3>
<p><a href="http://stackoverflow.com/questions/1809275/suppress-jquery-event-handling-temporarily/1810532#1810532">This mini-plugin</a> can be used to temporarily stop all jQuery events assigned to a specific element (or a group of elements) from firing.</p>
<h3>9. <a href="http://plugins.jquery.com/project/cookie">Cookie </a><a href="http://code.google.com/p/cookies/">Handling</a></h3>
<p>When it comes to cookies, there are <em>two</em> jQuery plugins that stand out :</p>
<ul>
<li><a href="http://plugins.jquery.com/project/cookie">Cookie</a> is simple and light-weight. Just the bare essentials  &#8211; you can read/write/delete cookies, and that&#8217;s it.</li>
<li><a href="http://code.google.com/p/cookies/">Cookies</a> is the advanced option. It can filter cookies using regexps, test if the browser is set to accept cookies, bind DOM element contents to cookies, and do automatic JSON serialization.</li>
</ul>
<h3>10. <a href="http://plugins.jquery.com/project/metadata">Metadata</a></h3>
<p>The <a href="http://plugins.jquery.com/project/metadata">Metadata</a> plugin provides a unified way to extract different formats of metadata from the DOM. It can extract metadata from classes, attributes, child elements or HTML5 data- attributes.</p>
<h3>11. <a href="http://www.asual.com/jquery/address/">Navigation History For AJAX Pages</a></h3>
<p>Add the coveted back-button support to your AJAX apps with the powerful <a href="http://www.asual.com/jquery/address/">Address</a> plugin. There&#8217;s a number of other plugins that deal with #anchor-based navigation, but <a href="http://www.asual.com/jquery/address/">Address</a> is a clear winner &#8211; it has the cleanest API and the best documentation.</p>
<h3>12. <a href="http://plugins.jquery.com/project/timers">Timers</a></h3>
<p><a href="http://plugins.jquery.com/project/timers">jQuery Timers</a> provides a more elegant, jQuery-flavoured way to deal with setTimetout() and setInterval(). You can apply timers to DOM elements, set the number of times a given timer will execute, create named timers, and more.</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. Please contact legal@w-shadow.com so we can take legal action immediately.]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2010/03/05/12-invisible-but-invaluable-jquery-plugins/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Making The Web More Readable For Everyone</title>
		<link>http://w-shadow.com/blog/2010/01/18/making-the-web-more-readable-for-everyone/</link>
		<comments>http://w-shadow.com/blog/2010/01/18/making-the-web-more-readable-for-everyone/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 17:59:19 +0000</pubDate>
		<dc:creator>White Shadow</dc:creator>
				<category><![CDATA[News and Rants]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[bookmarklet]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[readability]]></category>
		<category><![CDATA[reddit]]></category>
		<category><![CDATA[web page layout]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=1612</guid>
		<description><![CDATA[In a recent Reddit thread, one commenter made a casual remark :
There needs to be a way to link to a page on Reddit and automatically apply Readability.
That seemed like an excellent idea to me. In case you haven&#8217;t heard about it yet, Readability is a bookmarklet that can take an article or blog post [...]]]></description>
			<content:encoded><![CDATA[<p>In a recent Reddit thread, one commenter made a casual remark :</p>
<blockquote><p>There needs to be a way to link to a page on Reddit and automatically apply <a href="http://lab.arc90.com/experiments/readability/">Readability</a>.</p></blockquote>
<p>That seemed like an excellent idea to me. In case you haven&#8217;t heard about it yet, <a href="http://lab.arc90.com/experiments/readability/">Readability</a> is a bookmarklet that can take an article or blog post with even the most cluttered, ad-infested and eye-bleedingly ugly design and turn it into a clean and readable work of art. As a side-effect, it also removes most kinds of ads.</p>
<p>Of course, you could just install the bookmarklet for your own use and have that be the end of it. But if you regularly share links to interesting articles with friends, or post them to social bookmarking sites, it would sure be handy to have a way give others the benefit of Readability without forcing them to install anything.</p>
<p>So I went ahead and created a website that lets you do just that &#8211; <a href="http://makereadable.com/">MakeReadable.com</a>. Go <a href="http://makereadable.com/">check it out</a>.</p>
<p>Here&#8217;s how to use it :</p>
<ol>
<li>Enter a URL of the page  that you want to make more readable. Pages with lots of text &#8211; like news articles or blog posts &#8211; work best.</li>
<li>Click the &#8220;Make Readable&#8221; button (or press Enter).</li>
<li>Wait a few seconds while the server processes the page and redirects you to a new URL that already has Readability applied.</li>
<li>Share the URL of the new page with your friends, etc.</li>
</ol>
<p>An even easier way to use this service is to simply append the URL of the page you want processed after <code>http://makereadable.com/</code>, like this :</p>
<p><code>http://makereadable.com/example.com/someblog/article-123.htm</code></p>
<p>Behind the scenes, <a href="http://makereadable.com/">MakeReadable.com</a> also performs several other optimizations, like normalizing the HTML and stripping out all other scripts and most CSS. Since Readability completely restyles the page anyway, this post-processing makes the resulting page smaller and faster-loading (in theory) without hurting its looks.</p>
<p>Thoughts? Feature suggestions? Leave a comment below.</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. Please contact legal@w-shadow.com so we can take legal action immediately.]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2010/01/18/making-the-web-more-readable-for-everyone/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>15+ Useful Firefox Addons For Web Developers</title>
		<link>http://w-shadow.com/blog/2009/11/27/15-useful-firefox-addons-for-web-developers/</link>
		<comments>http://w-shadow.com/blog/2009/11/27/15-useful-firefox-addons-for-web-developers/#comments</comments>
		<pubDate>Fri, 27 Nov 2009 17:08:07 +0000</pubDate>
		<dc:creator>White Shadow</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[firefox addon]]></category>
		<category><![CDATA[firefox extension]]></category>
		<category><![CDATA[lists]]></category>
		<category><![CDATA[web development]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=1479</guid>
		<description><![CDATA[Everyone already knows and loves Firebug and Web Developer. So instead of another redundant &#8220;Top 10&#8243; list, here&#8217;s a collection of 15+ great add-ons that you might not have heard about yet.
Dust-Me Selectors

Dust-Me Selectors helps you find unused CSS selectors. You can use it to test an individual page, or let it spider your entire [...]]]></description>
			<content:encoded><![CDATA[<p>Everyone already knows and loves <a href="http://getfirebug.com/">Firebug</a> and <a href="https://addons.mozilla.org/en-US/firefox/addon/60">Web Developer</a>. So instead of another redundant &#8220;Top 10&#8243; list, here&#8217;s a collection of 15+ great add-ons that you might not have heard about yet.</p>
<h3><a href="https://addons.mozilla.org/en-US/firefox/addon/5392">Dust-Me Selectors</a></h3>
<p><a href="https://addons.mozilla.org/en-US/firefox/addon/5392"><img class="size-full wp-image-1496 alignnone" title="Dust-Me Selectors" src="http://w-shadow.com/wp-content/uploads/2009/11/Dust-Me-Selectors.png" alt="Dust-Me Selectors" width="401" height="211" /></a></p>
<p>Dust-Me Selectors helps you find unused CSS selectors. You can use it to test an individual page, or let it spider your entire site. Results are presented in a nice color-coded report and can be exported as CSV.</p>
<p><em>Alternative</em> :  <a href="https://addons.mozilla.org/en-US/firefox/addon/10704">CSS Usage</a></p>
<h3><a href="https://addons.mozilla.org/en-US/firefox/addon/9641">Inline Code Finder for Firebug</a></h3>
<p><a href="https://addons.mozilla.org/en-US/firefox/addon/9641"><img class="size-full wp-image-1498 alignnone" title="Inline Code Finder" src="http://w-shadow.com/wp-content/uploads/2009/11/Inline-Code-Finder2.jpg" alt="Inline Code Finder" width="500" height="200" /></a></p>
<p>Finds and highlights HTML elements with suspicious hacks like inline JavaScript events, inline styles and javascript: links. It also presents a summary report and calculates an overall score based on how many such elements were encountered on the page.</p>
<h3><a href="https://addons.mozilla.org/en-US/firefox/addon/1985">Window Resizer</a></h3>
<p><a href="https://addons.mozilla.org/en-US/firefox/addon/1985"><img class="alignnone size-full wp-image-1508" title="Window Resizer" src="http://w-shadow.com/wp-content/uploads/2009/11/Window-Resizer-ready.png" alt="Window Resizer" width="517" height="197" /></a></p>
<p>Lets you quickly resize your browser window to a number of common screen sizes so that you can see how you page would look at a different display resolution.</p>
<p><em>Alternative</em> : <a href="https://addons.mozilla.org/en-US/firefox/addon/5792">FireSizer</a></p>
<h3><a href="https://addons.mozilla.org/en-US/firefox/addon/9780">RESTClient</a></h3>
<p><a href="https://addons.mozilla.org/en-US/firefox/addon/9780"><img class="alignnone size-full wp-image-1507" title="RESTClient" src="http://w-shadow.com/wp-content/uploads/2009/11/RESTClient-ready.png" alt="RESTClient" width="400" height="293" /></a></p>
<p>RESTClient is a very handy tool for web service developers, allowing you to directly test and analyze RESTful APIs. It also includes partial support for the WebDAV protocol.</p>
<h3><a href="https://addons.mozilla.org/en-US/firefox/addon/10869">JSONView</a></h3>
<p><a href="https://addons.mozilla.org/en-US/firefox/addon/10869"><img class="alignnone size-full wp-image-1506" title="JSONView" src="http://w-shadow.com/wp-content/uploads/2009/11/JSONView-ready.png" alt="JSONView-ready" width="290" height="278" /></a></p>
<p>Lets you view JSON data directly in the browser and supports syntax highlighting and code folding. Overall, it&#8217;s another simple yet useful extension for developers working with WEB APIs.</p>
<h3><a href="https://addons.mozilla.org/en-US/firefox/addon/1595">Remove Cookie(s) for Site</a></h3>
<p><a href="https://addons.mozilla.org/en-US/firefox/addon/1595"><img class="alignnone size-full wp-image-1482" title="Remove Cookie(s)" src="http://w-shadow.com/wp-content/uploads/2009/11/Remove-Cookies.png" alt="Remove Cookie(s)" width="320" height="280" /></a></p>
<p>Remove all cookies from the current site with a single click. If you need something more advanced, check out the alternatives below.</p>
<p><em>Alternatives</em> : <a href="https://addons.mozilla.org/en-US/firefox/addon/573">Add N Edit Cookies</a>, <a href="https://addons.mozilla.org/en-US/firefox/addon/6683">FireCookie</a></p>
<h3><a href="https://addons.mozilla.org/en-US/firefox/addon/3255">CookieSwap</a></h3>
<p><a href="https://addons.mozilla.org/en-US/firefox/addon/3255"><img class="alignnone size-full wp-image-1501" title="CookieSwap" src="http://w-shadow.com/wp-content/uploads/2009/11/CookieSwap-ready.png" alt="CookieSwap" width="276" height="192" /></a></p>
<p>Lets you quickly swap all your cookies so that you can easily switch between different user accounts without logging in/out all the time. While this add-on is primarily advertised as a way to manage multiple webmail/Amazon/Google accounts, it can also be useful to web developers &#8211; e.g. for testing how your site behaves from the point of view of normal visitors vs. logged-in users, or users with different privilege levels.</p>
<h3><a href="https://addons.mozilla.org/en-US/firefox/addon/966">TamperData</a></h3>
<p><a href="https://addons.mozilla.org/en-US/firefox/addon/966"><img class="alignnone size-full wp-image-1483" title="TamperData" src="http://w-shadow.com/wp-content/uploads/2009/11/TamperData.png" alt="TamperData" width="500" height="220" /></a></p>
<p>With TamperData, you can intercept HTTP(S) requests made by Firefox and view/modify their headers and POST data. All requests are logged and can also be exported as XML or displayed on a graph. Handy for security testing and catching certain breeds of elusive server-side bugs.</p>
<p><em>Alternatives</em> : <a href="https://addons.mozilla.org/en-US/firefox/addon/967">Modify Header</a>, <a href="https://addons.mozilla.org/en-US/firefox/addon/1290">UrlParams</a></p>
<h3><a href="https://addons.mozilla.org/en-US/firefox/addon/2214">View Dependencies</a></h3>
<p><a href="https://addons.mozilla.org/en-US/firefox/addon/2214"><img class="alignnone size-full wp-image-1502" title="View Dependencies" src="http://w-shadow.com/wp-content/uploads/2009/11/View-Dependencies-ready-2.png" alt="View Dependencies" width="538" height="323" /></a></p>
<p>Essentially a simpler alternative to <a href="https://addons.mozilla.org/firefox/addon/5369">YSlow</a>, View Dependencies adds a new tab to the <em>Page Info</em> window, listing all the files that were loaded to display the current page.</p>
<h3><a href="https://addons.mozilla.org/en-US/firefox/addon/3899">HackBar</a></h3>
<p><a href="https://addons.mozilla.org/en-US/firefox/addon/3899"><img class="alignnone size-full wp-image-1504" title="HackBar" src="http://w-shadow.com/wp-content/uploads/2009/11/HackBar-screenshot-ready.png" alt="HackBar" width="490" height="228" /></a></p>
<p>HackBar is a large collection of simple penetration testing tools, useful for security-auditing your site and testing it for common vulnerabilities. You can convert strings to hex and back, encrypt text with SHA-1, SHA-256 or ROT13 (if only just for fun), try a number of typical SQL injection/XSS tricks, manipulate POST data, spoof the referer, and much more.</p>
<p><em>Related</em> : <a href="https://addons.mozilla.org/en-US/firefox/addon/7595">Access Me</a>, <a href="https://addons.mozilla.org/en-US/firefox/addon/7598">XSS Me</a></p>
<h3><a href="https://addons.mozilla.org/en-US/firefox/addon/3863">iMacros for Firefox</a></h3>
<p><a href="https://addons.mozilla.org/en-US/firefox/addon/3863"><img class="alignnone size-full wp-image-1486" title="iMacros" src="http://w-shadow.com/wp-content/uploads/2009/11/iMacros.png" alt="iMacros" width="519" height="211" /></a></p>
<p>&#8220;Whatever you do with Firefox, iMacros can automate it.&#8221; It can automatically fill forms, download &amp; upload files, scrape web pages, memorize passwords, and so on. iMacros really makes tasks like web application testing, data mining and mashup creation much easier.</p>
<h3><a href="https://addons.mozilla.org/en-US/firefox/addon/2637">TableTools</a></h3>
<p><a href="https://addons.mozilla.org/en-US/firefox/addon/2637"><img class="alignnone size-full wp-image-1487" title="TableTools" src="http://w-shadow.com/wp-content/uploads/2009/11/TableTools.png" alt="TableTools" width="487" height="161" /></a></p>
<p>Sort, filter or copy any HTML table. You can filter each column either by selecting a value from a drop-down menu or by searching for a specific keyword (regular expressions are also supported). TableTools will automatically recognize frequently used data types like numbers, timestamps and IP addresses, and sort/filter them intelligently.</p>
<h3><a href="https://addons.mozilla.org/en-US/firefox/addon/5817">SQLite Manager</a></h3>
<p><a href="https://addons.mozilla.org/en-US/firefox/addon/5817"><img class="alignnone size-full wp-image-1489" title="SQLite Manager" src="http://w-shadow.com/wp-content/uploads/2009/11/SQLite-Manager.png" alt="SQLite Manager" width="400" height="232" /></a></p>
<p>Manage any SQLite database on your computer. This add-on has all the features you would expect from a full-featured DB manager &#8211; you can view the database structure, create, modify and search tables and views, manage indexes, export and import data, and manipulate pretty much any other aspect of the database.</p>
<h3><a href="https://addons.mozilla.org/en-US/firefox/addon/8487">Pencil</a></h3>
<p><a href="https://addons.mozilla.org/en-US/firefox/addon/8487"><img class="alignnone size-full wp-image-1490" title="Pencil" src="http://w-shadow.com/wp-content/uploads/2009/11/Pencil.jpg" alt="Pencil" width="329" height="250" /></a></p>
<p>Make diagrams, build GUI prototypes and sketch website mockups with this awesome Firefox add-on!</p>
<h3><a href="https://addons.mozilla.org/en-US/firefox/addon/14465">Flashbug</a></h3>
<p><a href="https://addons.mozilla.org/en-US/firefox/addon/14465"><img class="alignnone size-full wp-image-1493" title="Flashbug" src="http://w-shadow.com/wp-content/uploads/2009/11/Flashbug-ready-2.png" alt="Flashbug" width="489" height="205" /></a></p>
<p>A Firebug extension that logs all the SWF trace output to the Firebug console. Can be invaluable for debugging Flash-based applications and games.</p>
<h3><a href="https://addons.mozilla.org/en-US/firefox/addon/11090">FireLogger</a></h3>
<p><a href="https://addons.mozilla.org/en-US/firefox/addon/11090"><img class="alignnone size-full wp-image-1494" title="FireLogger" src="http://w-shadow.com/wp-content/uploads/2009/11/FireLogger-ready-1.png" alt="FireLogger" width="500" height="198" /></a></p>
<p>Debug your server-side Python and PHP code from within the browser. After installing this Firebug extension and the appropriate Python/PHP library, you will be able to send logging information from your server-side scripts directly to the FireBug console.</p>
<p><em>Alternative</em> : <a href="https://addons.mozilla.org/en-US/firefox/addon/6149">FirePHP</a></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. Please contact legal@w-shadow.com so we can take legal action immediately.]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2009/11/27/15-useful-firefox-addons-for-web-developers/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>How To Extract HTML Tags And Their Attributes With PHP</title>
		<link>http://w-shadow.com/blog/2009/10/20/how-to-extract-html-tags-and-their-attributes-with-php/</link>
		<comments>http://w-shadow.com/blog/2009/10/20/how-to-extract-html-tags-and-their-attributes-with-php/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 14:35:03 +0000</pubDate>
		<dc:creator>White Shadow</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[data mining]]></category>
		<category><![CDATA[DOM]]></category>
		<category><![CDATA[extract attributes]]></category>
		<category><![CDATA[extract tags]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHP script]]></category>
		<category><![CDATA[regular expressions]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=1375</guid>
		<description><![CDATA[There are several ways to extract specific tags from an HTML document. The one that most people will think of first is probably regular expressions. However, this is not always &#8211; or, as some would insist, ever &#8211; the best approach. Regular expressions can be handy for small hacks, but using a real HTML parser [...]]]></description>
			<content:encoded><![CDATA[<p>There are several ways to extract specific tags from an HTML document. The one that most people will think of first is probably regular expressions. However, this is not always &#8211; or, as some would insist, <em>ever</em> &#8211; the best approach. Regular expressions can be handy for small hacks, but using a real HTML parser will usually lead to simpler and more robust code. Complex queries, like &#8220;find all rows with the class .foo of the second table of this document and return all links contained in those rows&#8221;, can also be done much easier with a decent parser.</p>
<p>There are <em>some</em> (though very few they may be) edge case where regular expressions might work better, so I will discuss both approaches in this post.</p>
<h3>Extracting Tags With DOM</h3>
<p>PHP 5 comes with a usable <a href="http://php.net/manual/en/book.dom.php">DOM API</a> built-in that you can use to parse and manipulate (X)HTML documents. For example, here&#8217;s how you could use it to extract all link URLs from a HTML file :</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//Load the HTML page</span>
<span style="color: #000088;">$html</span> <span style="color: #339933;">=</span> <span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'page.htm'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//Create a new DOM document</span>
<span style="color: #000088;">$dom</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> DOMDocument<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Parse the HTML. The @ is used to suppress any parsing errors</span>
<span style="color: #666666; font-style: italic;">//that will be thrown if the $html string isn't valid XHTML.</span>
<span style="color: #339933;">@</span><span style="color: #000088;">$dom</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">loadHTML</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$html</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Get all links. You could also use any other tag name here,</span>
<span style="color: #666666; font-style: italic;">//like 'img' or 'table', to extract other tags.</span>
<span style="color: #000088;">$links</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$dom</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getElementsByTagName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'a'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Iterate over the extracted links and display their URLs</span>
<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$links</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$link</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #666666; font-style: italic;">//Extract and show the &quot;href&quot; attribute. </span>
	<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$link</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'href'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'&lt;br&gt;'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>In addition to <code>getElementsByTagName()</code> you can also use <code>$dom-&gt;getElementById()</code> to find tags with a specific id. For more complex tasks, like extracting deeply nested tags, <a href="http://www.php.net/manual/en/class.domxpath.php">XPath</a> is probably the way to go. For example, to find all list items with the class &#8220;foo&#8221; containing links with the class &#8220;bar&#8221; and display the link URLs :</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//Load the HTML page</span>
<span style="color: #000088;">$html</span> <span style="color: #339933;">=</span> <span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'page.htm'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//Parse it. Here we use loadHTML as a static method</span>
<span style="color: #666666; font-style: italic;">//to parse the HTML and create the DOM object in one go.</span>
<span style="color: #339933;">@</span><span style="color: #000088;">$dom</span> <span style="color: #339933;">=</span> DOMDocument<span style="color: #339933;">::</span><span style="color: #004000;">loadHTML</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$html</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Init the XPath object</span>
<span style="color: #000088;">$xpath</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> DOMXpath<span style="color: #009900;">&#40;</span><span style="color: #000088;">$dom</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Query the DOM</span>
<span style="color: #000088;">$links</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$xpath</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'//li[contains(@class, &quot;foo&quot;)]//a[@class = &quot;bar&quot;]'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Display the results as in the previous example</span>
<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$links</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$link</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$link</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'href'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'&lt;br&gt;'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>For more information about DOM and XPath see these resources : </p>
<ul>
<li><a href="http://www.php.net/manual/en/book.dom.php">DOM API documentation</a></li>
<li><a href="http://www.w3schools.com/Xpath/">W3Schools XPath tutorial</a></li>
<li><a href="http://www.w3.org/TR/xpath">XPath language specification</a></li>
</ul>
<p>Honourable mention : <a href="http://simplehtmldom.sourceforge.net/">Simple HTML DOM Parser</a> is a popular alternative HTML parser for PHP 5 that lets you manipulate HTML pages with jQuery-like ease. However, I personally wouldn&#8217;t recommend using it if you care about your script&#8217;s performance, as in my tests Simple HTML DOM was about 30 times slower than DOMDocument.</p>
<h3>Extracting Tags &#038; Attributes With Regular Expressions</h3>
<p>There are only two advantages to processing HTML with regular expressions &#8211; availability and edge-case performance. While most parsers require PHP 5 or later, regular expressions are available pretty much anywhere. Also, they are a little bit faster than real parsers when you need to extract something from a <em>very</em> large document (on the order of 400 KB or more). Still, in most cases you&#8217;re better off using the PHP DOM extension or even Simple HTML DOM, not messing with convoluted regexps.</p>
<p>That said, here&#8217;s a PHP function that can extract any HTML tags and their attributes from a given string :</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * extract_tags()
 * Extract specific HTML tags and their attributes from a string.
 *
 * You can either specify one tag, an array of tag names, or a regular expression that matches the tag name(s). 
 * If multiple tags are specified you must also set the $selfclosing parameter and it must be the same for 
 * all specified tags (so you can't extract both normal and self-closing tags in one go).
 * 
 * The function returns a numerically indexed array of extracted tags. Each entry is an associative array
 * with these keys :
 * 	tag_name	- the name of the extracted tag, e.g. &quot;a&quot; or &quot;img&quot;.
 *	offset		- the numberic offset of the first character of the tag within the HTML source.
 *	contents	- the inner HTML of the tag. This is always empty for self-closing tags.
 *	attributes	- a name -&gt; value array of the tag's attributes, or an empty array if the tag has none.
 *	full_tag	- the entire matched tag, e.g. '&lt;a href=&quot;http://example.com&quot;&gt;example.com&lt;/a&gt;'. This key 
 *		          will only be present if you set $return_the_entire_tag to true.	   
 *
 * @param string $html The HTML code to search for tags.
 * @param string|array $tag The tag(s) to extract.							 
 * @param bool $selfclosing	Whether the tag is self-closing or not. Setting it to null will force the script to try and make an educated guess. 
 * @param bool $return_the_entire_tag Return the entire matched tag in 'full_tag' key of the results array.  
 * @param string $charset The character set of the HTML code. Defaults to ISO-8859-1.
 *
 * @return array An array of extracted tags, or an empty array if no matching tags were found. 
 */</span>
<span style="color: #000000; font-weight: bold;">function</span> extract_tags<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$html</span><span style="color: #339933;">,</span> <span style="color: #000088;">$tag</span><span style="color: #339933;">,</span> <span style="color: #000088;">$selfclosing</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$return_the_entire_tag</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #000088;">$charset</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'ISO-8859-1'</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #990000;">is_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$tag</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$tag</span> <span style="color: #339933;">=</span> <span style="color: #990000;">implode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'|'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$tag</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">//If the user didn't specify if $tag is a self-closing tag we try to auto-detect it</span>
	<span style="color: #666666; font-style: italic;">//by checking against a list of known self-closing tags.</span>
	<span style="color: #000088;">$selfclosing_tags</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'area'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'base'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'basefont'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'br'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'hr'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'input'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'img'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'link'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'meta'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'col'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'param'</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: #990000;">is_null</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$selfclosing</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$selfclosing</span> <span style="color: #339933;">=</span> <span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$tag</span><span style="color: #339933;">,</span> <span style="color: #000088;">$selfclosing_tags</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">//The regexp is different for normal and self-closing tags because I can't figure out </span>
	<span style="color: #666666; font-style: italic;">//how to make a sufficiently robust unified one.</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$selfclosing</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$tag_pattern</span> <span style="color: #339933;">=</span> 
			<span style="color: #0000ff;">'@&lt;(?P&lt;tag&gt;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$tag</span><span style="color: #339933;">.</span><span style="color: #0000ff;">')			# &lt;tag
			(?P&lt;attributes&gt;\s[^&gt;]+)?		# attributes, if any
			\s*/?&gt;					# /&gt; or just &gt;, being lenient here 
			@xsi'</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;">$tag_pattern</span> <span style="color: #339933;">=</span> 
			<span style="color: #0000ff;">'@&lt;(?P&lt;tag&gt;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$tag</span><span style="color: #339933;">.</span><span style="color: #0000ff;">')			# &lt;tag
			(?P&lt;attributes&gt;\s[^&gt;]+)?		# attributes, if any
			\s*&gt;					# &gt;
			(?P&lt;contents&gt;.*?)			# tag contents
			&lt;/(?P=tag)&gt;				# the closing &lt;/tag&gt;
			@xsi'</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000088;">$attribute_pattern</span> <span style="color: #339933;">=</span> 
		<span style="color: #0000ff;">'@
		(?P&lt;name&gt;\w+)							# attribute name
		\s*=\s*
		(
			(?P&lt;quote&gt;[\&quot;\'])(?P&lt;value_quoted&gt;.*?)(?P=quote)	# a quoted value
			|							# or
			(?P&lt;value_unquoted&gt;[^\s&quot;\']+?)(?:\s+|$)			# an unquoted value (terminated by whitespace or EOF) 
		)
		@xsi'</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">//Find all tags </span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #990000;">preg_match_all</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$tag_pattern</span><span style="color: #339933;">,</span> <span style="color: #000088;">$html</span><span style="color: #339933;">,</span> <span style="color: #000088;">$matches</span><span style="color: #339933;">,</span> PREG_SET_ORDER <span style="color: #339933;">|</span> PREG_OFFSET_CAPTURE <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">//Return an empty array if we didn't find anything</span>
		<span style="color: #b1b100;">return</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000088;">$tags</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$matches</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$match</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">//Parse tag attributes, if any</span>
		<span style="color: #000088;">$attributes</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</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: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$match</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'attributes'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> 
&nbsp;
			<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #990000;">preg_match_all</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$attribute_pattern</span><span style="color: #339933;">,</span> <span style="color: #000088;">$match</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'attributes'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$attribute_data</span><span style="color: #339933;">,</span> PREG_SET_ORDER <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
				<span style="color: #666666; font-style: italic;">//Turn the attribute data into a name-&gt;value array</span>
				<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$attribute_data</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$attr</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: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$attr</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'value_quoted'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
						<span style="color: #000088;">$value</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$attr</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'value_quoted'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
					<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$attr</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'value_unquoted'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
						<span style="color: #000088;">$value</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$attr</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'value_unquoted'</span><span style="color: #009900;">&#93;</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;">$value</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
					<span style="color: #009900;">&#125;</span>
&nbsp;
					<span style="color: #666666; font-style: italic;">//Passing the value through html_entity_decode is handy when you want</span>
					<span style="color: #666666; font-style: italic;">//to extract link URLs or something like that. You might want to remove</span>
					<span style="color: #666666; font-style: italic;">//or modify this call if it doesn't fit your situation.</span>
					<span style="color: #000088;">$value</span> <span style="color: #339933;">=</span> <span style="color: #990000;">html_entity_decode</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">ENT_QUOTES</span><span style="color: #339933;">,</span> <span style="color: #000088;">$charset</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
					<span style="color: #000088;">$attributes</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$attr</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$value</span><span style="color: #339933;">;</span>
				<span style="color: #009900;">&#125;</span>
			<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #000088;">$tag</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
			<span style="color: #0000ff;">'tag_name'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$match</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'tag'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
			<span style="color: #0000ff;">'offset'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$match</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> 
			<span style="color: #0000ff;">'contents'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$match</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'contents'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>?<span style="color: #000088;">$match</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'contents'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">:</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">//empty for self-closing tags</span>
			<span style="color: #0000ff;">'attributes'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$attributes</span><span style="color: #339933;">,</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;">$return_the_entire_tag</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$tag</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'full_tag'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$match</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> 			
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #000088;">$tags</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$tag</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$tags</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p><strong>Usage examples</strong></p>
<p>Extract all links and output their URLs :</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$html</span> <span style="color: #339933;">=</span> <span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'example.html'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$nodes</span> <span style="color: #339933;">=</span> extract_tags<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$html</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'a'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$nodes</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$link</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$link</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'attributes'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'href'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">,</span> <span style="color: #0000ff;">'&lt;br&gt;'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Extract all heading tags and output their text :</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$nodes</span> <span style="color: #339933;">=</span> extract_tags<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$html</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'h\d+'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$nodes</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$node</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">echo</span> <span style="color: #990000;">strip_tags</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$link</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'contents'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">,</span> <span style="color: #0000ff;">'&lt;br&gt;'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Extract meta tags :</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$nodes</span> <span style="color: #339933;">=</span> extract_tags<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$html</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'meta'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Extract bold and italicised text fragments :</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$nodes</span> <span style="color: #339933;">=</span> extract_tags<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$html</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'b'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'strong'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'em'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'i'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$nodes</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$node</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">echo</span> <span style="color: #990000;">strip_tags</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$node</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'contents'</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'&lt;br&gt;'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The function is pretty well documented, so check the source if anything is unclear. Of course, you can also leave a comment if you have any further questions or feedback.</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. Please contact legal@w-shadow.com so we can take legal action immediately.]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2009/10/20/how-to-extract-html-tags-and-their-attributes-with-php/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>How To Make a &#8220;Falling Sand&#8221; Style Water Simulation</title>
		<link>http://w-shadow.com/blog/2009/09/29/falling-sand-style-water-simulation/</link>
		<comments>http://w-shadow.com/blog/2009/09/29/falling-sand-style-water-simulation/#comments</comments>
		<pubDate>Tue, 29 Sep 2009 14:14:43 +0000</pubDate>
		<dc:creator>White Shadow</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[cellular automata]]></category>
		<category><![CDATA[falling sand game]]></category>
		<category><![CDATA[fluid simulation]]></category>
		<category><![CDATA[game design]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Processing]]></category>
		<category><![CDATA[simulation]]></category>
		<category><![CDATA[water simulation]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=1295</guid>
		<description><![CDATA[Have you ever wondered how all those &#8220;falling sand&#8221; games work under the hood? If so, read on. Today I will discuss one of the possible ways how you could implement the &#8220;falling&#8221; part of the game &#8211; sand particles falling under the effects of gravity, water (or other liquids) flowing down a hillside, and [...]]]></description>
			<content:encoded><![CDATA[<p>Have you ever wondered how all those <a href="http://chir.ag/stuff/sand/">&#8220;falling sand&#8221; games</a> work under the hood? If so, read on. Today I will discuss one of the possible ways how you could implement the &#8220;falling&#8221; part of the game &#8211; sand particles falling under the effects of gravity, water (or other liquids) flowing down a hillside, and so on. <a href="http://w-shadow.com/files/FallingWater.zip">Source code</a> and a <a href="http://w-shadow.com/files/FallingSandWater/">live demo</a> are also available. This tutorial is along the same vein as my previous <a href="http://w-shadow.com/blog/2009/09/01/simple-fluid-simulation/">fluid simulation post</a> that dealt with pseudo-compressible fluids and pressure, but the specific algorithm is much simpler (and probably quite a bit faster, too).<em> </em></p>
<p><em>Side-note : No, I haven&#8217;t been completely consumed by an inexorable desire to build fun graphical toys instead of practically useful software, why do you ask? <img src='http://w-shadow.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  In fact, there&#8217;ll be some WordPress-related announcements later this week&#8230;</em></p>
<h3>Learning To <del datetime="2009-09-28T14:15:43+00:00">Fly</del> Fall</h3>
<p><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-1299" title="Falling water movement" src="http://w-shadow.com/wp-content/uploads/2009/09/gravity-simulation-rules.png" alt="Falling water movement" width="120" height="236" />While I can&#8217;t claim intimate familiarity with the algorithms the aforementioned games use to simulate fire or explosions, it&#8217;s pretty easy to come up with a way to implement falling sand/flowing water. First, you need to figure out under what conditions something can fall/flow downwards. For a basic simulation this could be just a small set of very simple rules :</p>
<ul>
<li>For each entity that is affected by gravity
<ul>
<li>If there&#8217;s an empty space <strong>below</strong> it, move it <strong>down</strong>.</li>
<li>If there&#8217;s an empty space <strong>down and to the left</strong>, move it <strong>down and to the left</strong>.</li>
<li>If there&#8217;s an empty space <strong>down and to the right</strong>, move it <strong>down and to the right</strong>.</li>
</ul>
</li>
</ul>
<p>Next, you need to decide how to represent the simulation world and all the objects (like immovable walls, moving water particles <em>et cetera</em>) that it contains. One of the most common solutions is to use a two-dimensional array where each array element is an numeric ID of the material contained in that map tile. For example, 0 = air (or an empty square), 1 = wall, 2 = water, and so on.</p>
<p style="text-align: center;"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="size-full wp-image-1300 aligncenter" title="Map array" src="http://w-shadow.com/wp-content/uploads/2009/09/map-representation.png" alt="Map array" width="481" height="306" /></p>
<p>In most falling sand games each array element would correspond to a single pixel on the game&#8217;s screen. However, in my example application I used 20&#215;20 pixel tiles instead to make the underlying simulation behaviour easier to see.</p>
<p>If possible, use <em>byte</em> or <em>char</em> as the array element datatype. Using <em>int&#8217;s</em> might seem more straightforward, but it would also take up at least four times more memory and hurt performance. It&#8217;s also a good idea to make the array just a bit bigger than the actual map dimensions and create a single-tile &#8220;buffer zone&#8221; around the map so that you can avoid checking for boundary conditions during the simulation.</p>
<p>Finally, during the simulation step we just loop over the entire array and apply the simple rules I mentioned above to each tile that contains material that should be affected by gravity.</p>
<h3>Getting It Right</h3>
<p><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-1301" title="Now that's just silly." src="http://w-shadow.com/wp-content/uploads/2009/09/whee.png" alt="Now that's just silly." width="78" height="211" />If you go ahead and implement the above algorithm as written, you will get a simulation that <em>kind-of</em> works, but quickly grinds to a halt on big maps and sometimes behaves in unexpected ways. For example, you might see sand tiles that seem to &#8220;teleport&#8221; to the bottom of the map instead of falling gradually and water that always flows <em>left</em> after hitting a free-standing ground tile (even though there&#8217;s a perfectly suitable channel available on the right side). Lets see what we can do about that.</p>
<p><strong>Keeping track of updated tiles</strong></p>
<p>The &#8220;teleportation&#8221; behaviour can happen if our simulation algorithm doesn&#8217;t keep track of which tiles it has already moved around during the current simulation step. For example, first it loops over the top row of the map, finds a water tile A and moves it downwards one row. Then it loops over the second row, finds the tile A, moves it again, goes to the third row, moves the same water tile <em>again</em>&#8230; and so on, until the water tile A hits a solid tile or falls off the map.</p>
<p>To prevent this bug we need to somehow remember which tiles have been updated already. Since I wanted to keep the memory use low, I used the most-significant bit of each map array element to indicate whether that tile was last updated on an even-numbered simulation step (0) or an odd-numbered step (1). Then, at the start of each step, the algorithm calculates what the flag should be for tiles updated in that step :</p>
<pre>update_mask = byte ( ( simulationFrameCount &amp; (long)1 ) &lt;&lt; 7 );
//this basically takes the modulo of frame-count / 2 and shifts the result 7 places to the left</pre>
<p>&#8230;then sets the msb of each tile it updates to that value and automatically skips tiles that have it already set to that value.</p>
<p><strong>Pseudo-random movement</strong></p>
<p>When a falling particle hits a free-standing fixed tile on a 2D map it has two choices &#8211; it can either move down and left, or down and right. In the naive algorithm I discussed above it will always try to move left first, leading to weirdness. Obviously we want it to choose at random, but on a big map generating a new random number for each tile would be slow. Instead, lets use the same approach as for the &#8220;teleportation&#8221; problem and move it either diagonally left if the current simulation step is even-numbered and or diagonally right if it&#8217;s odd-numbered. This can still introduce some artifacts in the simulation behaviour, but they&#8217;re rarer and and significantly less noticeable.</p>
<h3>Optimization</h3>
<p>Speaking of optimization, we don&#8217;t really need to update each gravity-enabled tile every time. Many of them will eventually end up in a situation where they can&#8217;t move anywhere (e.g. water at the bottom of a puddle or sand resting on a flat surface), so it would be nice if we could quickly skip them and not waste our time trying to apply the simulation rules to these static tiles. This would help performance quite a bit.</p>
<p>The way I implemented is with the help with another bit-flag. If the simulation algorithm discovers that it can&#8217;t move a tile in any direction, it will set the tile&#8217;s &#8220;static&#8221; bit-flag. It will also skip any tiles that have the &#8220;static&#8221; bit-flag set.</p>
<p>There&#8217;s some additional book-keeping we need to do to make this work as intended. When an empty space is created somewhere in the map (e.g. by a water tile moving down) we need to re-activate any gravity-enabled tiles that are directly above the newly created hole, so that they can fall/flow down into that space.</p>
<h3>Possible Improvements</h3>
<p>The result is a pretty basic and plain simulation that is useful to explain the basic principle, but it wouldn&#8217;t really qualify as a full game. Here are some ideas you could use to improve it :</p>
<ul>
<li>Make water flow horizontally if there&#8217;s another water tile on top of it. Consider adding a simple pressure model [link to my prev. article].</li>
<li>Implement fluid density. This one is easy &#8211; if the current tile is more dense than the tile below it, swap them.</li>
<li>Add tile generators, e.g. a faucet that creates a water tile below itself on each simulation step (included in my demo application).</li>
<li>To improve performance, use a <a href="http://en.wikipedia.org/wiki/Quadtree">quadtree</a> to keep track of which regions of the map have interacting tiles and quickly skip inactive regions.</li>
<li>Explore the source code of existing games and look for interesting ideas. Some open-source examples : <a href="http://www.piettes.com/fallingsandgame/download.html">wxSand</a>, <a href="http://sourceforge.net/projects/sdlsand/">SDL Sand</a>.</li>
</ul>
<h3>Live Demo &amp; Source</h3>
<p>Like my previous <a href="http://w-shadow.com/blog/2009/09/01/simple-fluid-simulation/">fluid simulation app</a>, this one was also written in <a href="http://processing.org/">Processing</a>. In addition to a working implementation of the algorithm discussed above it also lets you draw and erase water/ground/faucet tiles using your mouse, pan around the map with the WASD keys, zoom in/out with the mouse wheel and more. However, be warned that the map rendering code is not very optimized so the simulation <em>will</em> degenerate into a slideshow if you zoom all the way out, regardless of how fast your system is.</p>
<ul>
<li><a href="http://w-shadow.com/files/FallingSandWater/">Live demo  (requires Java)</a></li>
<li><a href="http://w-shadow.com/files/FallingWater.zip">Source code</a></li>
</ul>
<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. Please contact legal@w-shadow.com so we can take legal action immediately.]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2009/09/29/falling-sand-style-water-simulation/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Simple Fluid Simulation With Cellular Automata</title>
		<link>http://w-shadow.com/blog/2009/09/01/simple-fluid-simulation/</link>
		<comments>http://w-shadow.com/blog/2009/09/01/simple-fluid-simulation/#comments</comments>
		<pubDate>Tue, 01 Sep 2009 19:48:33 +0000</pubDate>
		<dc:creator>White Shadow</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[cellular automata]]></category>
		<category><![CDATA[fluid dynamics]]></category>
		<category><![CDATA[fluid simulation]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Processing]]></category>
		<category><![CDATA[water dynamics]]></category>
		<category><![CDATA[water simulation]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=1285</guid>
		<description><![CDATA[Last week I couldn&#8217;t use my regular dev. machine (broken graphics card), so all my WordPress-related plans were on hold. To pass the time, I built a simple water simulation in Processing. Today I&#8217;m going to show you this little application and explain how it works. Online demo and source code are included.
Big Words, or [...]]]></description>
			<content:encoded><![CDATA[<p>Last week I couldn&#8217;t use my regular dev. machine (broken graphics card), so all my WordPress-related plans were on hold. To pass the time, I built a simple water simulation in <a href="http://processing.org/">Processing</a>. Today I&#8217;m going to show you this little application and explain how it works. Online demo and source code are included.</p>
<h3>Big Words, or The Theoretical Part</h3>
<p>Fluid dynamics is a complex topic. If you so much as <a rel="nofollow" href="http://en.wikipedia.org/wiki/Computational_fluid_dynamics">look it up in Wikipedia</a>, you will be immediately assaulted by integrals, differentials  and other agents of mathematical insanity. To accurately model a fluid you would need a quite an in-depth understanding of physics and calculus. And while that&#8217;s certainly not something one couldn&#8217;t figure out given enough time, &#8220;proper&#8221; fluid simulation is still extremely rare in non-academic applications and games because it&#8217;s <strong>slow</strong>.</p>
<p>One way to create a faster (though less accurate) simulation is by using <a rel="nofollow" href="http://en.wikipedia.org/wiki/Cellular_automata">cellular automata</a> to represent the water. A cellular automaton is basically a grid where each cell can be in one of a finite number of states, plus a set of rules that determine how a cell can change from one state to another. The rules are typically local &#8211; that is, they consider only the current cell and it&#8217;s direct neighbours when determining the new state. During each step of the simulation, you simply loop through the entire grid and apply the rules to each cell.</p>
<p>When simulating water or other fluids it can more appropriate to store a continuous value (e.g. water mass) in each cell, instead of using discrete states.</p>
<h3>CA-Based Water Simulation</h3>
<p>Before we go into details, lets take a look at the promised online demo. It will give you a good idea about what you can achieve with this approach :</p>
<p><a href="http://w-shadow.com/files/water_sim/"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-large wp-image-1291" title="Click to run the simulation" src="http://w-shadow.com/wp-content/uploads/2009/09/Water-Simulation1-490x513.png" alt="Click to run the simulation" width="490" height="513" /></a> <em>(klicken Sie auf das Bild; Java required)</em></p>
<p>Alright, on to the code stuff. Lets try simulating the most common fluid &#8211; water.</p>
<p><strong>The basic data structure</strong></p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//Map dimensions</span>
<span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span> map_width <span style="color: #339933;">=</span> <span style="color: #cc66cc;">16</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span> map_height <span style="color: #339933;">=</span> <span style="color: #cc66cc;">16</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Block types</span>
<span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span> AIR <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span> GROUND <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span> WATER <span style="color: #339933;">=</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Data structures</span>
<span style="color: #000066; font-weight: bold;">int</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> blocks <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #000066; font-weight: bold;">int</span><span style="color: #009900;">&#91;</span>map_width<span style="color: #339933;">+</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>map_height<span style="color: #339933;">+</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">float</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> mass <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #000066; font-weight: bold;">float</span><span style="color: #009900;">&#91;</span>map_width<span style="color: #339933;">+</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>map_height<span style="color: #339933;">+</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span>,
          new_mass <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #000066; font-weight: bold;">float</span><span style="color: #009900;">&#91;</span>map_width<span style="color: #339933;">+</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>map_height<span style="color: #339933;">+</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span></pre></div></div>

<p>I use two two-dimensional arrays to represent the simulation world. The <code>blocks</code> array defines a basic &#8220;map&#8221; where each cell can contain ground (solid, stops water flow), air (an empty cell, water can flow in) or water. Each water cell also has a corresponding entry in the <code>mass</code> array that defines how much water it contains. All water cells/blocks start out with one unit of water.</p>
<p>There&#8217;s also a third array &#8211; <code>new_mass</code> that is used to store intermediate mass values when running the simulation. Operating directly on the <code>mass</code> array is unadvisable because you would get various sideffects like water spreading at different speeds depending on the order in which you update the cells.</p>
<p><strong>Overall algorithm</strong></p>
<p>The main idea is to treat water as a slightly compressible liquid, as described in <a href="http://home.comcast.net/~tom_forsyth/papers/cellular_automata_for_physical_modelling.html">this article</a>. In terms of implementation, this means that if there are two or more water cells stacked vertically, the bottom cells will be able to hold slightly more water than normal. This way we don&#8217;t need to explicitly track pressure to make the water level equalize in communicating vessels &#8211; we can just look at how much excess water a cell has, and move it upwards if required.</p>
<p>Lets set up the exact fluid properties as constants :</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//Water properties</span>
<span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">float</span> MaxMass <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1.0</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//The normal, un-pressurized mass of a full water cell</span>
<span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">float</span> MaxCompress <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0.02</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//How much excess water a cell can store, compared to the cell above it</span>
<span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">float</span> MinMass <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0.0001</span><span style="color: #339933;">;</span>  <span style="color: #666666; font-style: italic;">//Ignore cells that are almost dry</span></pre></div></div>

<p>For example, if one cell contains 1.0 units of water, the cell below it should contain up to 1.02 units, the cell below that one should contain 1.04, the next one 1.06, and so on. There is one however special case that we need to consider to get a plausible simulation &#8211; what if the if the top cell contains less than <code>MaxMass</code> units of water? In my implementation the bottom cell will contain a proportionally smaller excess amount, not the usual <code>mass_of_the_cell_above + MaxCompression</code> units.</p>
<p>Based on the above, we can simulate water movement by looping over the <code>mass</code> array and applying these cellular automaton rules to each cell :</p>
<ol>
<li>Take the mass of the current cell and the cell <strong>below</strong> it and figure out how much water the bottom cell should contain. If it has less than that, remove the corresponding amount from the current cell and add it to the bottom cell.</li>
<li>Check the cell to the <strong>left</strong> of this one. If it has less water, move over enough water to make both cells contain the same amount.</li>
<li>Do the same thing for the <strong>right</strong> neighbour.</li>
<li>Do the same thing as in step 1., but for the cell <strong>above</strong> the current one.</li>
</ol>
<p>While doing this you also need to keep track of how much water the current cell still has remaining, or you could end up with negative-mass water blocks.</p>
<p>After the new mass of each cell has been calculated, you can safely copy over the new values to the <code>mass</code> array. You also need to update the <code>blocks</code> array so that cells that are now dry get marked as empty and vice versa.</p>
<p>Here&#8217;s the simulation code :</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">void</span> simulate_compression<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">float</span> Flow <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">float</span> remaining_mass<span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">//Calculate and apply flow for each block</span>
  <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> x <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span> x <span style="color: #339933;">&lt;=</span> map_width<span style="color: #339933;">;</span> x<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
     <span style="color: #000000; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> y <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span> y <span style="color: #339933;">&lt;=</span> map_height<span style="color: #339933;">;</span> y<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
       <span style="color: #666666; font-style: italic;">//Skip inert ground blocks</span>
       <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> blocks<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> GROUND<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">continue</span><span style="color: #339933;">;</span>
&nbsp;
       <span style="color: #666666; font-style: italic;">//Custom push-only flow</span>
       Flow <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
       remaining_mass <span style="color: #339933;">=</span> mass<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
       <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> remaining_mass <span style="color: #339933;">&lt;=</span> <span style="color: #cc66cc;">0</span> <span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">continue</span><span style="color: #339933;">;</span>
&nbsp;
       <span style="color: #666666; font-style: italic;">//The block below this one</span>
       <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span>blocks<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">!=</span> GROUND<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
         Flow <span style="color: #339933;">=</span> get_stable_state_b<span style="color: #009900;">&#40;</span> remaining_mass <span style="color: #339933;">+</span> mass<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> mass<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
         <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> Flow <span style="color: #339933;">&gt;</span> MinFlow <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
           Flow <span style="color: #339933;">*=</span> <span style="color: #cc66cc;">0.5</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//leads to smoother flow</span>
         <span style="color: #009900;">&#125;</span>
         Flow <span style="color: #339933;">=</span> constrain<span style="color: #009900;">&#40;</span> Flow, <span style="color: #cc66cc;">0</span>, min<span style="color: #009900;">&#40;</span>MaxSpeed, remaining_mass<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
         new_mass<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span> <span style="color: #339933;">-=</span> Flow<span style="color: #339933;">;</span>
         new_mass<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">+=</span> Flow<span style="color: #339933;">;</span>   
         remaining_mass <span style="color: #339933;">-=</span> Flow<span style="color: #339933;">;</span>
       <span style="color: #009900;">&#125;</span>
&nbsp;
       <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> remaining_mass <span style="color: #339933;">&lt;=</span> <span style="color: #cc66cc;">0</span> <span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">continue</span><span style="color: #339933;">;</span>
&nbsp;
       <span style="color: #666666; font-style: italic;">//Left</span>
       <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> blocks<span style="color: #009900;">&#91;</span>x<span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span> <span style="color: #339933;">!=</span> GROUND <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
         <span style="color: #666666; font-style: italic;">//Equalize the amount of water in this block and it's neighbour</span>
         Flow <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>mass<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span> <span style="color: #339933;">-</span> mass<span style="color: #009900;">&#91;</span>x<span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">/</span><span style="color: #cc66cc;">4</span><span style="color: #339933;">;</span>
         <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> Flow <span style="color: #339933;">&gt;</span> MinFlow <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> Flow <span style="color: #339933;">*=</span> <span style="color: #cc66cc;">0.5</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
         Flow <span style="color: #339933;">=</span> constrain<span style="color: #009900;">&#40;</span>Flow, <span style="color: #cc66cc;">0</span>, remaining_mass<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
         new_mass<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span> <span style="color: #339933;">-=</span> Flow<span style="color: #339933;">;</span>
         new_mass<span style="color: #009900;">&#91;</span>x<span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span> <span style="color: #339933;">+=</span> Flow<span style="color: #339933;">;</span>
         remaining_mass <span style="color: #339933;">-=</span> Flow<span style="color: #339933;">;</span>
       <span style="color: #009900;">&#125;</span>
&nbsp;
       <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> remaining_mass <span style="color: #339933;">&lt;=</span> <span style="color: #cc66cc;">0</span> <span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">continue</span><span style="color: #339933;">;</span>
&nbsp;
       <span style="color: #666666; font-style: italic;">//Right</span>
       <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> blocks<span style="color: #009900;">&#91;</span>x<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span> <span style="color: #339933;">!=</span> GROUND <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
         <span style="color: #666666; font-style: italic;">//Equalize the amount of water in this block and it's neighbour</span>
         Flow <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>mass<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span> <span style="color: #339933;">-</span> mass<span style="color: #009900;">&#91;</span>x<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">/</span><span style="color: #cc66cc;">4</span><span style="color: #339933;">;</span>
         <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> Flow <span style="color: #339933;">&gt;</span> MinFlow <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> Flow <span style="color: #339933;">*=</span> <span style="color: #cc66cc;">0.5</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
         Flow <span style="color: #339933;">=</span> constrain<span style="color: #009900;">&#40;</span>Flow, <span style="color: #cc66cc;">0</span>, remaining_mass<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
         new_mass<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span> <span style="color: #339933;">-=</span> Flow<span style="color: #339933;">;</span>
         new_mass<span style="color: #009900;">&#91;</span>x<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span> <span style="color: #339933;">+=</span> Flow<span style="color: #339933;">;</span>
         remaining_mass <span style="color: #339933;">-=</span> Flow<span style="color: #339933;">;</span>
       <span style="color: #009900;">&#125;</span>
&nbsp;
       <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> remaining_mass <span style="color: #339933;">&lt;=</span> <span style="color: #cc66cc;">0</span> <span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">continue</span><span style="color: #339933;">;</span>
&nbsp;
       <span style="color: #666666; font-style: italic;">//Up. Only compressed water flows upwards.</span>
       <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> blocks<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">!=</span> GROUND <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
         Flow <span style="color: #339933;">=</span> remaining_mass <span style="color: #339933;">-</span> get_stable_state_b<span style="color: #009900;">&#40;</span> remaining_mass <span style="color: #339933;">+</span> mass<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
         <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> Flow <span style="color: #339933;">&gt;</span> MinFlow <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> Flow <span style="color: #339933;">*=</span> <span style="color: #cc66cc;">0.5</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
         Flow <span style="color: #339933;">=</span> constrain<span style="color: #009900;">&#40;</span> Flow, <span style="color: #cc66cc;">0</span>, min<span style="color: #009900;">&#40;</span>MaxSpeed, remaining_mass<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
         new_mass<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span> <span style="color: #339933;">-=</span> Flow<span style="color: #339933;">;</span>
         new_mass<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">+=</span> Flow<span style="color: #339933;">;</span>   
         remaining_mass <span style="color: #339933;">-=</span> Flow<span style="color: #339933;">;</span>
       <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
     <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">//Copy the new mass values to the mass array</span>
  <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> x <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> x <span style="color: #339933;">&lt;</span> map_width <span style="color: #339933;">+</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">;</span> x<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> y <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> y <span style="color: #339933;">&lt;</span> map_height <span style="color: #339933;">+</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">;</span> y<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
      mass<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> new_mass<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> x <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span> x <span style="color: #339933;">&lt;=</span> map_width<span style="color: #339933;">;</span> x<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
     <span style="color: #000000; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> y <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span> y <span style="color: #339933;">&lt;=</span> map_height<span style="color: #339933;">;</span> y<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
       <span style="color: #666666; font-style: italic;">//Skip ground blocks</span>
       <span style="color: #000000; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>blocks<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> GROUND<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">continue</span><span style="color: #339933;">;</span>
       <span style="color: #666666; font-style: italic;">//Flag/unflag water blocks</span>
       <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>mass<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span> <span style="color: #339933;">&gt;</span> MinMass<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
         blocks<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> WATER<span style="color: #339933;">;</span>
       <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
         blocks<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> AIR<span style="color: #339933;">;</span>
       <span style="color: #009900;">&#125;</span>
     <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">//Remove any water that has left the map</span>
  <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> x <span style="color: #339933;">=</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> x <span style="color: #339933;">&lt;</span> map_width<span style="color: #339933;">+</span><span style="color: #cc66cc;">2</span><span style="color: #339933;">;</span> x<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    mass<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    mass<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>map_height<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
  <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> y <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span> y <span style="color: #339933;">&lt;</span> map_height<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span> y<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    mass<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    mass<span style="color: #009900;">&#91;</span>map_width<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>y<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>And here&#8217;s the function that calculates how to distribute a given amount of water between two vertically adjacent cells :</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//Returns the amount of water that should be in the bottom cell.</span>
<span style="color: #000066; font-weight: bold;">float</span> get_stable_state_b <span style="color: #009900;">&#40;</span> <span style="color: #000066; font-weight: bold;">float</span> total_mass <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> total_mass <span style="color: #339933;">&lt;=</span> <span style="color: #cc66cc;">1</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> total_mass <span style="color: #339933;">&lt;</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">*</span>MaxMass <span style="color: #339933;">+</span> MaxCompress <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #009900;">&#40;</span>MaxMass<span style="color: #339933;">*</span>MaxMass <span style="color: #339933;">+</span> total_mass<span style="color: #339933;">*</span>MaxCompress<span style="color: #009900;">&#41;</span><span style="color: #339933;">/</span><span style="color: #009900;">&#40;</span>MaxMass <span style="color: #339933;">+</span> MaxCompress<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #009900;">&#40;</span>total_mass <span style="color: #339933;">+</span> MaxCompress<span style="color: #009900;">&#41;</span><span style="color: #339933;">/</span><span style="color: #cc66cc;">2</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p><strong>Full source code</strong></p>
<ul>
<li><a href="http://w-shadow.com/files/water_sim.zip"><strong>Download the source</strong></a> (23 KB)</li>
<li>You will need the Java-based <a href="http://processing.org/">Processing programming language</a> to run the code.</li>
</ul>
<p>I didn&#8217;t discuss how to render the water, or how to handle user interaction, but the source code also includes a simplistic implementation of those things.</p>
<h3>Conclusion</h3>
<p>CA-based algorithms have both advantages and disadvantages. On the one hand, they&#8217;re relatively fast and the simulation quality is often good enough for games and software toys. On the other, they can produce behaviour that is very unrealistic &#8211; for example, water falling into a basin will form a little &#8220;hill&#8221; and spread out slowly, instead of near-instantly as real water would. Whether this is an acceptable downside depends on your application.</p>
<p>For a different take on simulating fluid dynamics with cellular automata, check out this <a href="http://www.gamasutra.com/view/feature/3549/interview_the_making_of_dwarf_.php?page=9">interview with the author of Dwarf Fortress</a>.</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. Please contact legal@w-shadow.com so we can take legal action immediately.]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2009/09/01/simple-fluid-simulation/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Changelog Generator For WordPress Plugins</title>
		<link>http://w-shadow.com/blog/2009/08/20/changelog-generator-for-wordpress-plugins/</link>
		<comments>http://w-shadow.com/blog/2009/08/20/changelog-generator-for-wordpress-plugins/#comments</comments>
		<pubDate>Thu, 20 Aug 2009 19:25:55 +0000</pubDate>
		<dc:creator>White Shadow</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[Blogging]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[changelog]]></category>
		<category><![CDATA[PHP script]]></category>
		<category><![CDATA[plugin directory]]></category>
		<category><![CDATA[repository]]></category>
		<category><![CDATA[SVN]]></category>
		<category><![CDATA[Trac]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress plugins]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=1276</guid>
		<description><![CDATA[A few months ago, WordPress.org introduced a new feature available to plugins hosted in the Plugin Directory &#8211; changelogs. Having an easily accessible changelog is certainly a usability plus, but I felt it created unnecessary work for plugin developers. Personally, I usually provide meaningful log messages (example) when uploading a new version of a plugin [...]]]></description>
			<content:encoded><![CDATA[<p>A few months ago, WordPress.org introduced a new feature available to plugins hosted in the Plugin Directory &#8211; <a href="http://westi.wordpress.com/2009/06/20/changelogs-changelogs-changelogs/">changelogs</a><span>. Having an easily accessible changelog is certainly a usability plus, but I felt it created unnecessary work for plugin developers. Personally, I usually provide meaningful log messages (</span><a href="http://plugins.trac.wordpress.org/log/broken-link-checker">example</a><span>) when uploading a new version of a plugin to the repository, so updating the changelog with pretty much the same information seems redundant.</span></p>
<p><span>This gave me the idea to write a PHP script that can generate a wordpress.org-compatible changelog from the revision log. It works for any plugin hosted in the official plugins directory and <span class="hiddenGrammarError">can be</span> a handy starting point for adding a changelog to plugins that don&#8217;t have it yet :</span></p>
<ul>
<li><strong><a href="http://w-shadow.com/wpchangelog/"><span>Run the changelog generator</span></a></strong></li>
<li><a href="http://w-shadow.com/files/wpchangelog.zip">Download the source code</a> (97 KB, requires PHP 5)</li>
</ul>
<p>For those too lazy to click one of the above links, here&#8217;s a screenshot :</p>
<p><a href="http://w-shadow.com/wpchangelog/"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-1278" title="Changelog generator for WordPress plugins" src="http://w-shadow.com/wp-content/uploads/2009/08/Changelog-Generator.png" alt="Changelog generator for WordPress plugins" width="490" height="205" /></a></p>
<p>And I really do need to stop making these small hacks <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. Please contact legal@w-shadow.com so we can take legal action immediately.]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2009/08/20/changelog-generator-for-wordpress-plugins/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>How To Speed Up Your JavaScript (Video)</title>
		<link>http://w-shadow.com/blog/2009/08/10/how-to-speed-up-your-javascript-video/</link>
		<comments>http://w-shadow.com/blog/2009/08/10/how-to-speed-up-your-javascript-video/#comments</comments>
		<pubDate>Mon, 10 Aug 2009 15:52:51 +0000</pubDate>
		<dc:creator>White Shadow</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Google TechTalks]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[web apps]]></category>
		<category><![CDATA[youtube videos]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=1251</guid>
		<description><![CDATA[JavaScript has become an integral part of the modern Web. Some would praise it as the miracle stuff that ties together diverse web technologies and creates more responsive user interfaces, the stuff that makes glorious mashups and truly interactive web apps possible. Some would rather liken it to a sticky sludge that attaches itself to [...]]]></description>
			<content:encoded><![CDATA[<p>JavaScript has become an integral part of the modern Web. Some would praise it as the miracle stuff that ties together diverse web technologies and creates more responsive user interfaces, the stuff that makes glorious mashups and truly interactive web apps possible. Some would rather liken it to a sticky sludge that attaches itself to a perfectly good (X)HTML site and transmogrifies it into a hulking mass of slowness.</p>
<p>Here&#8217;s a <a href="http://www.youtube.com/watch?v=mHtdZgou0qU">very interesting video</a> from <a href="http://www.youtube.com/user/googletechtalks">Google TechTalks</a> that discusses a number of advanced JS optimization techniques that will help your site avoid that horrible fate :</p>
<p><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/mHtdZgou0qU&#038;hl=en&#038;fs=1&#038;"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/mHtdZgou0qU&#038;hl=en&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></p>
<p><strong>Bonus :</strong> If you&#8217;re a WordPress dev and intend to use the bundled jQuery library, check out these <a href="http://www.tvidesign.co.uk/blog/improve-your-jquery-25-excellent-tips.aspx">25 tips for improving your jQuery usage</a>. This is one of the most comprehensive jQuery tip sheets I&#8217;ve seen.</p>
<p><strong>Also :</strong> <a href="http://www.nihilogic.dk/labs/wolf/">Wolfenstein 3D implemented in JavaScript</a> <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. Please contact legal@w-shadow.com so we can take legal action immediately.]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2009/08/10/how-to-speed-up-your-javascript-video/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Calculating Readability Metrics In PHP</title>
		<link>http://w-shadow.com/blog/2009/04/28/calculating-readability-metrics-in-php/</link>
		<comments>http://w-shadow.com/blog/2009/04/28/calculating-readability-metrics-in-php/#comments</comments>
		<pubDate>Tue, 28 Apr 2009 17:40:34 +0000</pubDate>
		<dc:creator>White Shadow</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[english language]]></category>
		<category><![CDATA[flesch kincaid grade level]]></category>
		<category><![CDATA[gunning fog index]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[readability]]></category>
		<category><![CDATA[readability formulas]]></category>
		<category><![CDATA[readability metrics]]></category>
		<category><![CDATA[readability tests]]></category>
		<category><![CDATA[smog index]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=1081</guid>
		<description><![CDATA[Readability metrics, also known as readability formulas, are a set of algorithms that estimate the readability of text. Most tests are fairly primitive as they only take into account things like sentence length and the average number of syllables per word, but ignore deeper factors like sentence structure and semantics.
Still, readability metrics can be useful [...]]]></description>
			<content:encoded><![CDATA[<p><img style=' float: left; padding: 4px; margin: 0 7px 2px 0;'  src="http://w-shadow.com/wp-content/uploads/2009/04/lorem-ipsum.png" alt="Lorem Ipsum" title="Too much XKCD" width="190" height="156" class="alignleft size-full wp-image-1086" />Readability metrics, also known as readability formulas, are a set of algorithms that estimate the readability of text. Most tests are fairly primitive as they only take into account things like sentence length and the average number of syllables per word, but ignore deeper factors like sentence structure and semantics.</p>
<p>Still, readability metrics can be useful as a rough indicator of how understandable your writing is. Other possible uses include detecting smart-ass comments and even catching spam (obviously, most spam messages would score very low on a readability test).</p>
<p>If you want to do something like that in your own PHP application(s), take a look at <a href="http://code.google.com/p/php-text-statistics/">PHP Text Statistics</a>. It&#8217;s a PHP class that implements a number of readability tests, including : </p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Flesch-Kincaid_Readability_Test" rel="nofollow">Flesch-Kincaid Reading Ease</a> (probably the most popular metric)</li>
<li><a href="http://en.wikipedia.org/wiki/Flesch-Kincaid_Readability_Test#Flesch.E2.80.93Kincaid_Grade_Level" rel="nofollow">Flesch-Kincaid Grade Level</a></li>
<li><a href="http://en.wikipedia.org/wiki/Gunning-Fog_Index" rel="nofollow">Gunning-Fog Index</a></li>
<li><a href="http://en.wikipedia.org/wiki/Coleman-Liau_Index" rel="nofollow">Coleman-Liau Index</a></li>
<li><a href="http://en.wikipedia.org/wiki/SMOG_(Simple_Measure_Of_Gobbledygook)" rel="nofollow">SMOG index</a></li>
<li><a href="http://en.wikipedia.org/wiki/Automated_Readability_Index" rel="nofollow">Automated Reability Index</a></li>
</ul>
<p>It can also calculate other metrics like sentence count, syllable count, average words per sentence, and so on. </p>
<p>The class is very easy to use &#8211; just <code>include</code> one file, create an instance, and call one of the suggestively named methods. There&#8217;s not much &#8220;official&#8221; documentation but the source code is well-commented and easy to understand. </p>
<p>The only flaw that stuck out to me was how inefficient the script can be. You probably won&#8217;t notice it unless you need to analyze huge volumes of text, but it could really use some optimization. In fact, I managed to improve the performance by ~30% simply by eliminating a few redundant function calls (you can <a href="http://w-shadow.com/files/TextStatistics.rar">download the modified version here</a> if you&#8217;re interested).</p>
<p>Ah well, it&#8217;s a useful class overall. I&#8217;m sure it will come in handy the occasional NLP exploit or <a href="http://twanalyst.com/">mashup</a>. </p>
<p><em>Hmm, this gives me an idea for a WordPress plugin&#8230;.</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. Please contact legal@w-shadow.com so we can take legal action immediately.]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2009/04/28/calculating-readability-metrics-in-php/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
