<?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>Terry Dunham is a graphic artist, web designer and illustrator for hire &#187; Nettuts</title>
	<atom:link href="http://terrytoledo.com/category/nettuts/feed/" rel="self" type="application/rss+xml" />
	<link>http://terrytoledo.com</link>
	<description>Free Estimates for Illustrations, Graphic Art and Web Design</description>
	<lastBuildDate>Thu, 09 Sep 2010 04:00:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>CodeIgniter from Scratch: Displaying &amp; Sorting Tabular Data</title>
		<link>http://terrytoledo.com/2010/09/codeigniter-from-scratch-displaying-sorting-tabular-data-2/</link>
		<comments>http://terrytoledo.com/2010/09/codeigniter-from-scratch-displaying-sorting-tabular-data-2/#comments</comments>
		<pubDate>Thu, 09 Sep 2010 04:00:07 +0000</pubDate>
		<dc:creator>Nettuts</dc:creator>
				<category><![CDATA[Nettuts]]></category>

		<guid isPermaLink="false">http://terrytoledo.com/2010/09/codeigniter-from-scratch-displaying-sorting-tabular-data-2/</guid>
		<description><![CDATA[In today&#8217;s video tutorial, we are going to use CodeIgniter to pull information from a database and display it in a sortable table structure. This is a quite common task, especially inside admin areas, for displaying database records. We&#8217;ll be utilizing a few different utilities, such as the active records library and pagination. Catch Up [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://feedads.g.doubleclick.net/~a/V-uE38GFn68ykJc6XW57afyVyzY/0/da"><img src="http://feedads.g.doubleclick.net/~a/V-uE38GFn68ykJc6XW57afyVyzY/0/di" border="0"></img></a><br />
<a href="http://feedads.g.doubleclick.net/~a/V-uE38GFn68ykJc6XW57afyVyzY/1/da"><img src="http://feedads.g.doubleclick.net/~a/V-uE38GFn68ykJc6XW57afyVyzY/1/di" border="0"></img></a></p>
<p>
In today&#8217;s video tutorial, we are going to use CodeIgniter to pull information from a database and display it in a sortable table structure. This is a quite common task, especially inside admin areas, for displaying database records. We&#8217;ll be utilizing a few different utilities, such as the active records library and pagination. </p>
<p><span></span></p>
<hr />
<h2>Catch Up</h2>
<ul>
<li><a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-day-1/">Day 1: Getting Started With the Framework</a></li>
<li><a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-day-2/">Day 2: Database Selecting Methods</a></li>
<li><a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-day-3/">Day 3: Sending Emails</a></li>
<li><a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-day-4-newsletter-signup/">Day 4: Newsletter Signup</a></li>
<li><a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-day-5-crud/">Day 5: CRUD</a></li>
<li><a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-day-6-login/">Day 6: Login</a></li>
<li><a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-day-7-pagination/">Day 7: Pagination</a></li>
<li><a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-day-8-ajax/">Day 8: AJAX</a></li>
<li><a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-file-uploading-and-image-manipulation/">Day 9: File Uploading and Image Manipulation</a></li>
<li><a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-the-calendar-library/">Day 10: The Calendar Library</a></li>
<li><a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-file-operations/">Day 11: File and Directory Operations</a></li>
<li><a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-shopping-cart/">Day 12: Shopping Cart</a></li>
<li><a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-extending-the-framework/">Day 13: Extending the Framework</a></li>
<li><a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-security/">Day 14: Security</a></li>
<li><a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-profiling-benchmarking-hooks/">Day 15: Profiling, Benchmarking &#038; Hooks</a></li>
<li> <a href="http://net.tutsplus.com"> Day 16: Displaying &#038; Sorting Tabular Data </a></li>
</ul>
<hr />
<h2> <span>Day 16: </span>Displaying &#038; Sorting Tabular Data </h2>
<div>
</div>
<div>
<img src="http://nettuts.s3.amazonaws.com/786_ci/ss.png" alt="Day 16: Displaying &amp; Sorting Tabular Data" />
</div>
<hr />
<p>Thanks for watching! Any questions/thoughts? </p>
<div>
<a href="http://feeds.feedburner.com/~ff/nettuts?a=sVPpZKIisvM:rSVsiBVXtRs:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=sVPpZKIisvM:rSVsiBVXtRs:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nettuts?i=sVPpZKIisvM:rSVsiBVXtRs:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=sVPpZKIisvM:rSVsiBVXtRs:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nettuts?i=sVPpZKIisvM:rSVsiBVXtRs:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=sVPpZKIisvM:rSVsiBVXtRs:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/nettuts?i=sVPpZKIisvM:rSVsiBVXtRs:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=sVPpZKIisvM:rSVsiBVXtRs:TzevzKxY174"><img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"></img></a>
</div>
<p><img src="http://feeds.feedburner.com/~r/nettuts/~4/sVPpZKIisvM" height="1" width="1" /></p>
]]></content:encoded>
			<wfw:commentRss>http://terrytoledo.com/2010/09/codeigniter-from-scratch-displaying-sorting-tabular-data-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Theme Tumblr Like a Pro: Upcoming Rockable Book</title>
		<link>http://terrytoledo.com/2010/09/theme-tumblr-like-a-pro-upcoming-rockable-book/</link>
		<comments>http://terrytoledo.com/2010/09/theme-tumblr-like-a-pro-upcoming-rockable-book/#comments</comments>
		<pubDate>Thu, 09 Sep 2010 04:00:07 +0000</pubDate>
		<dc:creator>Nettuts</dc:creator>
				<category><![CDATA[Nettuts]]></category>

		<guid isPermaLink="false">http://terrytoledo.com/2010/09/theme-tumblr-like-a-pro-upcoming-rockable-book/</guid>
		<description><![CDATA[I&#8217;m pleased to announce the upcoming release of the book I&#8217;ve been sporadically referencing on Twitter for the last month or so: &#8220;Theme Tumblr Like a Pro.&#8221; There&#8217;s a reason why Tumblr&#8217;s popularity has sky-rocketed in the last few years: it&#8217;s amazingly intuitive, and allows you to rapidly build dynamic websites in a matter of [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://feedads.g.doubleclick.net/~a/QPZ7BVSh0TX5DpEoCwXEl4pDDDA/0/da"><img src="http://feedads.g.doubleclick.net/~a/QPZ7BVSh0TX5DpEoCwXEl4pDDDA/0/di" border="0"></img></a><br />
<a href="http://feedads.g.doubleclick.net/~a/QPZ7BVSh0TX5DpEoCwXEl4pDDDA/1/da"><img src="http://feedads.g.doubleclick.net/~a/QPZ7BVSh0TX5DpEoCwXEl4pDDDA/1/di" border="0"></img></a></p>
<p>
I&#8217;m pleased to announce the upcoming release of the book I&#8217;ve been sporadically referencing on <a href="http://www.twitter.com">Twitter</a> for the last month or so: &#8220;Theme Tumblr Like a Pro.&#8221;  There&#8217;s a reason why Tumblr&#8217;s popularity has sky-rocketed in the last few years: it&#8217;s amazingly intuitive, and allows you to rapidly build dynamic websites in a matter of hours.
</p>
<p>
As with <a href="http://rockablepress.com/books/photoshop-to-html/">my previous book,</a> I&#8217;ve included companion screencasts with each chapter. This means that, whether you prefer the written word or screencasts, we have you covered.
</p>
<p><span></span></p>
<div><img src="http://cdn.net.tutsplus.com/788_tumblr/tumblrCover.jpg" alt="Theme Tumblr Like a Pro: Upcoming Rockable Book" />
</div>
<hr />
<h2> What&#8217;s in it for you? </h2>
<p>Focusing on the fundamentals, this book takes you from front to back. You&#8217;ll learn about:</p>
<ul>
<li> The fundamentals: template tags, basic structure </li>
<li> Blocks </li>
<li> The various post types and variables </li>
<li> Build a theme </li>
<li> Working with the Tumblr API </li>
<li> Passing Tumblr-specific values to your JavaScript </li>
<li> Adding enhanced functionality with JavaScript and the API </li>
<li> A plethora of miscellaneous recipes </li>
<li> Working with custom meta types to create an options panel, which then provides maximum flexibility for the user of the theme </li>
<li> And plenty more&#8230; </li>
</ul>
<div><img src="http://cdn.net.tutsplus.com/788_tumblr/promo.jpg" alt="Promo" /></div>
<hr />
<h2> Save $9 and get a Free Book </h2>
<p>
The book <strong>won&#8217;t be out for one more week</strong>, however, as always, those who are on the <a href="http://rockablepress.com/the-rockin-list/">Rockin&#8217; List</a> (takes five seconds to sign up) will receive a voucher for $9 dollars off the cost of the book. </p>
<blockquote>
<p>
&#8220;The Rockin’ List is our irregular mailout about new books and products, discounts and offers and Rockable news. Signing up to the mailing list will get you a free copy of the <a href="http://rockablepress.com/minibooks/rockstar-personal-branding/">Rockstar Personal Branding</a> minibook by <a href="http://skelliewag.org">Skellie</a>.&#8221;</p>
</blockquote>
<hr />
<p>I&#8217;ll obnoxiously keep everyone posted on when the book officially comes out. Strangely, there simply aren&#8217;t many Tumblr resources and screencasts available around the web for those looking to switch over from a framework, like WordPress. Hopefully, this will help! Bye!</p>
<div>
<a href="http://feeds.feedburner.com/~ff/nettuts?a=6lf5th4zPv0:zKnF9_VqbCk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=6lf5th4zPv0:zKnF9_VqbCk:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nettuts?i=6lf5th4zPv0:zKnF9_VqbCk:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=6lf5th4zPv0:zKnF9_VqbCk:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nettuts?i=6lf5th4zPv0:zKnF9_VqbCk:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=6lf5th4zPv0:zKnF9_VqbCk:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/nettuts?i=6lf5th4zPv0:zKnF9_VqbCk:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=6lf5th4zPv0:zKnF9_VqbCk:TzevzKxY174"><img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"></img></a>
</div>
<p><img src="http://feeds.feedburner.com/~r/nettuts/~4/6lf5th4zPv0" height="1" width="1" /></p>
]]></content:encoded>
			<wfw:commentRss>http://terrytoledo.com/2010/09/theme-tumblr-like-a-pro-upcoming-rockable-book/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Understanding and Applying Polymorphism in PHP</title>
		<link>http://terrytoledo.com/2010/09/understanding-and-applying-polymorphism-in-php/</link>
		<comments>http://terrytoledo.com/2010/09/understanding-and-applying-polymorphism-in-php/#comments</comments>
		<pubDate>Wed, 08 Sep 2010 23:08:32 +0000</pubDate>
		<dc:creator>Nettuts</dc:creator>
				<category><![CDATA[Nettuts]]></category>

		<guid isPermaLink="false">http://terrytoledo.com/2010/09/understanding-and-applying-polymorphism-in-php/</guid>
		<description><![CDATA[In object oriented programming, polymorphism is a powerful and fundamental tool. It can be used to create a more organic flow in your application. This tutorial will describe the general concept of polymorphism, and how it can easily be deployed in PHP. What is Polymorphism? Polymorphism is a long word for a very simple concept. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://feedads.g.doubleclick.net/~a/P1uXh59eMddl6zrJ_Ur0C_e7mrA/0/da"><img src="http://feedads.g.doubleclick.net/~a/P1uXh59eMddl6zrJ_Ur0C_e7mrA/0/di" border="0"></img></a><br />
<a href="http://feedads.g.doubleclick.net/~a/P1uXh59eMddl6zrJ_Ur0C_e7mrA/1/da"><img src="http://feedads.g.doubleclick.net/~a/P1uXh59eMddl6zrJ_Ur0C_e7mrA/1/di" border="0"></img></a></p>
<p>In object oriented programming, polymorphism is a powerful and fundamental tool. It can be used to create a more organic flow in your application. This tutorial will describe the general concept of polymorphism, and how it can easily be deployed in PHP.</p>
<p><span></span></p>
<hr />
<h2>What is Polymorphism?</h2>
<p>Polymorphism is a long word for a very simple concept. </p>
<blockquote><p>
Polymorphism describes a pattern in object oriented programming in which classes have different functionality while sharing a common interface.
</p>
</blockquote>
<p> The beauty of polymorphism is that the code working with the different classes does not need to know which class it is using since they&#8217;re all used the same way.</p>
<p>A real world analogy for polymorphism is a button. Everyone knows how to use a button: you simply apply pressure to it. What a button &#8220;does,&#8221; however, depends on what it is connected to and the context in which it is used &#8212; but the result does not affect how it is used. If your boss tells you to press a button, you already have all the information needed to perform the task.</p>
<p>In the programming world, polymorphism is used to make applications more modular and extensible. Instead of messy conditional statements describing different courses of action, you create interchangeable objects that you select based on your needs. That is the basic goal of polymorphism.</p>
<hr />
<h2>Interfaces</h2>
<p>An integral part of polymorphism is the common interface. There are two ways to define an interface in PHP: <strong>interfaces</strong> and <strong>abstract classes</strong>. Both have their uses, and you can mix and match them as you see fit in your class hierarchy.</p>
<h3>Using an Interface</h3>
<p>An interface is similar to a class, except that it cannot contain code. It can define method names and arguments, but not the contents of the methods. Any classes implementing an interface <strong>must</strong> implement all methods defined by the interface. A class can implement multiple interfaces.</p>
<p>An interface is declared using the &#8216;<code>interface</code>&#8216; keyword:</p>
<pre>interface MyInterface {
    // methods
}</pre>
<p>and is attached to a class using the &#8216;<code>implements</code>&#8216; keyword:</p>
<pre>class MyClass implements MyInterface {
    // methods
}</pre>
<p>Methods can be defined in the interface just like in a class, except without the body (the part between the braces):</p>
<pre>interface MyInterface {
    public function doThis();
    private function doThat();
    public function setName($name);
}</pre>
<p>All methods defined here will need to be included in any implementing classes exactly as described. (Note the code comments below.)</p>
<pre>// VALID
class MyClass implements MyInterface {
    protected $name;
    public function doThis() {
        // code that does this
    }
    private function doThat() {
        // code that does that
    }
    public function setName($name) {
        $this-&gt;name = $name;
    }
}

// INVALID
class MyClass implements MyInterface {
    // missing doThis()!
    public function doThat() {
        // this should be private!
    }
    public function setName() {
        // missing the name argument!
    }
}</pre>
<h3>Using an Abstract Class</h3>
<p>An abstract class is a mix between an interface and a class. It can define functionality as well as interface (in the form of abstract methods). Classes extending an abstract class <strong>must</strong> implement all of the abstract methods defined in the abstract class.</p>
<p>An abstract class is declared the same way as classes with the addition of the &#8216;<code>abstract</code>&#8216; keyword:</p>
<pre>abstract class MyAbstract {
    // methods
}</pre>
<p>and is attached to a class using the &#8216;<code>extends</code>&#8216; keyword:</p>
<pre>class MyClass extends MyAbstract {
    // class methods
}</pre>
<p>Regular methods can be defined in an abstract class just like in a regular class, as well as any abstract methods (using the &#8216;<code>abstract</code>&#8216; keyword). Abstract methods behave just like methods defined in an interface, and must be implemented exactly as defined by extending classes.</p>
<pre>abstract class MyAbstract {
    protected $name;
    public function doThis() {
        // do this
    }
    abstract private function doThat();
    abstract public function setName($name);
}</pre>
<hr />
<h2> <span>Step 1:</span> Identify The Problem</h2>
<p>Let&#8217;s imagine that you have an <code>Article</code> class that is responsible for managing articles on your website. It contains information about an article, including the title, author, date, and category. Here&#8217;s what it looks like:</p>
<pre>class poly_base_Article {
    public $title;
    public $author;
    public $date;
    public $category;

    public function  __construct($title, $author, $date, $category = 0) {
        $this-&gt;title = $title;
        $this-&gt;author = $author;
        $this-&gt;date = $date;
        $this-&gt;category = $category;
    }
}</pre>
<p><strong>Note:</strong> The example classes in this tutorial use the naming convention of &#8220;package_component_Class.&#8221; This is a common way to separate classes into virtual namespaces to avoid name collisions.</p>
<p>Now you want to add a method to output the information into different formats, such as XML and JSON. You might be tempted to do something like this:</p>
<pre>class poly_base_Article {
    //...
    public function write($type) {
        $ret = '';
        switch($type) {
            case 'XML':
                $ret = '&lt;article&gt;';
                $ret .= '&lt;title&gt;' . $obj-&gt;title . '&lt;/title&gt;';
                $ret .= '&lt;author&gt;' . $obj-&gt;author . '&lt;/author&gt;';
                $ret .= '&lt;date&gt;' . $obj-&gt;date . '&lt;/date&gt;';
                $ret .= '&lt;category&gt;' . $obj-&gt;category . '&lt;/category&gt;';
                $ret .= '&lt;/article&gt;';
                break;
            case 'JSON':
                $array = array('article' =&gt; $obj);
                $ret = json_encode($array);
                break;
        }
        return $ret;
    }
}</pre>
<p>This is kind of an ugly solution, but it works &#8212; for now. Ask yourself what happens in the future, though, when we want to add more formats? You can keep editing the class, adding more and more cases, but now you&#8217;re only diluting your class.</p>
<blockquote>
<p>One important principle of OOP is that a class should do one thing, and it should do it well. </p>
</blockquote>
<p>With this in mind, conditional statements should be a red flag indicating that your class is trying to do too many different things. This is where polymorphism comes in.</p>
<p>In our example, it is clear that there are two tasks presented: managing articles and formatting their data. In this tutorial, we will refactor our formatting code into a new set of classes and discover how easy it is use polymorphism.</p>
<hr />
<h2> <span>Step 2:</span> Define Your Interface</h2>
<p>The first thing we should do is define the interface. It is important to think hard about your interface, because any changes to it may require changes to calling code. In our example, we&#8217;ll be using a simple interface to define our one method:</p>
<pre>interface poly_writer_Writer {
    public function write(poly_base_Article $obj);
}</pre>
<p>It&#8217;s that simple; we have defined a public <code>write()</code> method that accepts an Article object as an argument. Any classes implementing the Writer interface will be sure to have this method.</p>
<p><strong>Tip:</strong> If you want to restrict the type of arguments that can be passed to your functions and methods, you can use type hints, as we&#8217;ve done in the <code>write()</code> method; it only accepts objects of type <code>poly_base_Article</code>. Unfortunately, return type hinting is not supported in current versions of PHP, so it is up to you to take care of return values.</p>
<hr />
<h2> <span>Step 3:</span> Create Your Implementation</h2>
<p>With your interface defined, it is time to create the classes that actually do stuff. In our example, we have two formats that we want to output. Thus we have two Writer classes: XMLWriter and JSONWriter. It&#8217;s up to these to extract the data from the passed Article object and format the information.</p>
<p>Here&#8217;s what XMLWriter looks like:</p>
<pre>class poly_writer_XMLWriter implements poly_writer_Writer {
    public function write(poly_base_Article $obj) {
        $ret = '&lt;article&gt;';
        $ret .= '&lt;title&gt;' . $obj-&gt;title . '&lt;/title&gt;';
        $ret .= '&lt;author&gt;' . $obj-&gt;author . '&lt;/author&gt;';
        $ret .= '&lt;date&gt;' . $obj-&gt;date . '&lt;/date&gt;';
        $ret .= '&lt;category&gt;' . $obj-&gt;category . '&lt;/category&gt;';
        $ret .= '&lt;/article&gt;';
        return $ret;
    }
}</pre>
<p>As you can see from the class declaration, we use the <code>implements</code> keyword to implement our interface. The <code>write()</code> method contains functionality specific to formatting XML.</p>
<p>Now here&#8217;s our JSONWriter class:</p>
<pre>class poly_writer_JSONWriter implements poly_writer_Writer {
    public function write(poly_base_Article $obj) {
        $array = array('article' =&gt; $obj);
        return json_encode($array);
    }
}</pre>
<p>All of our code specific to each format is now contained within individual classes. These classes each have the sole responsibility of handling a specific format, and nothing else. No other part of your application needs to care about how these work in order to use it, thanks to our interface.</p>
<hr />
<h2> <span>Step 4:</span> Use Your Implementation</h2>
<p>With our new classes defined, it&#8217;s time to revisit our Article class. All the code that lived in the original <code>write()</code> method has been factored out into our new set of classes. All our method has to do now is to use the new classes, like this:</p>
<pre>class poly_base_Article {
    //...
    public function write(poly_writer_Writer $writer) {
        return $writer-&gt;write($this);
    }
}</pre>
<p>All this method does now is accept an object of the Writer class (that is any class implementing the Writer interface), call its <code>write()</code> method, passing itself (<code>$this</code>) as the argument, then forward its return value straight to the client code. It no longer needs to worry about the details of formatting data, and it can focus on its main task.</p>
<h3>Obtaining A Writer</h3>
<p>You may be wondering where you get a Writer object to begin with, since you need to pass one to this method. That&#8217;s up to you, and there are many strategies. For example, you might use a factory class to grab request data and create an object:</p>
<pre>class poly_base_Factory {
    public static function getWriter() {
        // grab request variable
        $format = $_REQUEST['format'];
        // construct our class name and check its existence
        $class = 'poly_writer_' . $format . 'Writer';
        if(class_exists($class)) {
            // return a new Writer object
            return new $class();
        }
        // otherwise we fail
        throw new Exception('Unsupported format');
    }
}</pre>
<p>Like I said, there are many other strategies to use depending on your requirements. In this example, a request variable chooses which format to use. It constructs a class name from the request variable, checks if it exists, then returns a new Writer object. If none exists under that name, an exception is thrown to let client code figure out what to do.</p>
<hr />
<h2> <span>Step 5:</span> Put It All Together</h2>
<p>With everything in place, here is how our client code would put it all together:</p>
<pre>$article = new poly_base_Article('Polymorphism', 'Steve', time(), 0);

try {
    $writer = poly_base_Factory::getWriter();
}
catch (Exception $e) {
    $writer = new poly_writer_XMLWriter();
}

echo $article-&gt;write($writer);</pre>
<p>First we created an example Article object to work with. Then we try to get a Writer object from the Factory, falling back to a default (XMLWriter) if an exception is thrown. Finally, we pass the Writer object to our Article&#8217;s <code>write()</code> method, printing the result.</p>
<hr />
<h2>Conclusion</h2>
<p>In this tutorial, I&#8217;ve provided you with an introduction to polymorphism and an explanation of interfaces in PHP. I hope you realize that I&#8217;ve only shown you one potential use case for polymorphism. There are many, many more applications. Polymorphism is an elegant way to escape from ugly conditional statements in your OOP code. It follows the principle of keeping your components separate, and is an integral part of many design patterns. If you have any questions, don&#8217;t hesitate to ask in the comments!</p>
<div>
<a href="http://feeds.feedburner.com/~ff/nettuts?a=_FzY2lAmDjU:1ADGucxm2bw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=_FzY2lAmDjU:1ADGucxm2bw:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nettuts?i=_FzY2lAmDjU:1ADGucxm2bw:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=_FzY2lAmDjU:1ADGucxm2bw:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nettuts?i=_FzY2lAmDjU:1ADGucxm2bw:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=_FzY2lAmDjU:1ADGucxm2bw:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/nettuts?i=_FzY2lAmDjU:1ADGucxm2bw:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=_FzY2lAmDjU:1ADGucxm2bw:TzevzKxY174"><img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"></img></a>
</div>
<p><img src="http://feeds.feedburner.com/~r/nettuts/~4/_FzY2lAmDjU" height="1" width="1" /></p>
]]></content:encoded>
			<wfw:commentRss>http://terrytoledo.com/2010/09/understanding-and-applying-polymorphism-in-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CodeIgniter from Scratch: Displaying &amp; Sorting Tabular Data</title>
		<link>http://terrytoledo.com/2010/09/codeigniter-from-scratch-displaying-sorting-tabular-data/</link>
		<comments>http://terrytoledo.com/2010/09/codeigniter-from-scratch-displaying-sorting-tabular-data/#comments</comments>
		<pubDate>Wed, 08 Sep 2010 04:00:08 +0000</pubDate>
		<dc:creator>Nettuts</dc:creator>
				<category><![CDATA[Nettuts]]></category>

		<guid isPermaLink="false">http://terrytoledo.com/2010/09/codeigniter-from-scratch-displaying-sorting-tabular-data/</guid>
		<description><![CDATA[In today&#8217;s video tutorial, we are going to use CodeIgniter to pull information from a database and display it in a sortable table structure. This is a quite common task, especially inside admin areas, for displaying database records. We&#8217;ll be utilizing a few different utilities, such as the active records library and pagination. Catch Up [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://feedads.g.doubleclick.net/~a/gZKK9wOkqg7hL5OLHftR5BM4a5Y/0/da"><img src="http://feedads.g.doubleclick.net/~a/gZKK9wOkqg7hL5OLHftR5BM4a5Y/0/di" border="0"></img></a><br />
<a href="http://feedads.g.doubleclick.net/~a/gZKK9wOkqg7hL5OLHftR5BM4a5Y/1/da"><img src="http://feedads.g.doubleclick.net/~a/gZKK9wOkqg7hL5OLHftR5BM4a5Y/1/di" border="0"></img></a></p>
<p>
In today&#8217;s video tutorial, we are going to use CodeIgniter to pull information from a database and display it in a sortable table structure. This is a quite common task, especially inside admin areas, for displaying database records. We&#8217;ll be utilizing a few different utilities, such as the active records library and pagination. </p>
<p><span></span></p>
<hr />
<h2>Catch Up</h2>
<ul>
<li><a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-day-1/">Day 1: Getting Started With the Framework</a></li>
<li><a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-day-2/">Day 2: Database Selecting Methods</a></li>
<li><a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-day-3/">Day 3: Sending Emails</a></li>
<li><a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-day-4-newsletter-signup/">Day 4: Newsletter Signup</a></li>
<li><a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-day-5-crud/">Day 5: CRUD</a></li>
<li><a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-day-6-login/">Day 6: Login</a></li>
<li><a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-day-7-pagination/">Day 7: Pagination</a></li>
<li><a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-day-8-ajax/">Day 8: AJAX</a></li>
<li><a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-file-uploading-and-image-manipulation/">Day 9: File Uploading and Image Manipulation</a></li>
<li><a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-the-calendar-library/">Day 10: The Calendar Library</a></li>
<li><a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-file-operations/">Day 11: File and Directory Operations</a></li>
<li><a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-shopping-cart/">Day 12: Shopping Cart</a></li>
<li><a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-extending-the-framework/">Day 13: Extending the Framework</a></li>
<li><a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-security/">Day 14: Security</a></li>
<li><a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-profiling-benchmarking-hooks/">Day 15: Profiling, Benchmarking &#038; Hooks</a></li>
<li> <a href="http://net.tutsplus.com"> Day 16: Displaying &#038; Sorting Tabular Data </a></li>
</ul>
<hr />
<h2> <span>Day 16: </span>Displaying &#038; Sorting Tabular Data </h2>
<div>
</div>
<div>
<img src="http://nettuts.s3.amazonaws.com/786_ci/ss.png" alt="Day 16: Displaying &amp; Sorting Tabular Data" />
</div>
<hr />
<p>Thanks for watching! Any questions/thoughts? </p>
<div>
<a href="http://feeds.feedburner.com/~ff/nettuts?a=Y4J2vl5WxWI:rSVsiBVXtRs:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=Y4J2vl5WxWI:rSVsiBVXtRs:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nettuts?i=Y4J2vl5WxWI:rSVsiBVXtRs:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=Y4J2vl5WxWI:rSVsiBVXtRs:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nettuts?i=Y4J2vl5WxWI:rSVsiBVXtRs:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=Y4J2vl5WxWI:rSVsiBVXtRs:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/nettuts?i=Y4J2vl5WxWI:rSVsiBVXtRs:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=Y4J2vl5WxWI:rSVsiBVXtRs:TzevzKxY174"><img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"></img></a>
</div>
<p><img src="http://feeds.feedburner.com/~r/nettuts/~4/Y4J2vl5WxWI" height="1" width="1" /></p>
]]></content:encoded>
			<wfw:commentRss>http://terrytoledo.com/2010/09/codeigniter-from-scratch-displaying-sorting-tabular-data/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>10 Terminal Commands That Will Boost Your Productivity</title>
		<link>http://terrytoledo.com/2010/09/10-terminal-commands-that-will-boost-your-productivity/</link>
		<comments>http://terrytoledo.com/2010/09/10-terminal-commands-that-will-boost-your-productivity/#comments</comments>
		<pubDate>Tue, 07 Sep 2010 04:00:06 +0000</pubDate>
		<dc:creator>Nettuts</dc:creator>
				<category><![CDATA[Nettuts]]></category>

		<guid isPermaLink="false">http://terrytoledo.com/2010/09/10-terminal-commands-that-will-boost-your-productivity/</guid>
		<description><![CDATA[Back in May, Nettuts+ ran a great article entitled &#8221;7 Simple and Useful Command-Line Tips&#8221;; this was a great article for getting started with using the command line. But there&#8217;s a lot more you can learn about using a shell, and I&#8217;ll take you to the next level in this tutorial! Getting Started If you&#8217;re [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://feedads.g.doubleclick.net/~a/63TYaSEnM8G4OErD5Y6c1mzdL2A/0/da"><img src="http://feedads.g.doubleclick.net/~a/63TYaSEnM8G4OErD5Y6c1mzdL2A/0/di" border="0"></img></a><br />
<a href="http://feedads.g.doubleclick.net/~a/63TYaSEnM8G4OErD5Y6c1mzdL2A/1/da"><img src="http://feedads.g.doubleclick.net/~a/63TYaSEnM8G4OErD5Y6c1mzdL2A/1/di" border="0"></img></a></p>
<p>Back in May, Nettuts+ ran a great article entitled &#8221;<a href="http://net.tutsplus.com/tutorials/other/7-simple-and-useful-command-line-tips/">7 Simple and Useful Command-Line Tips</a>&#8221;; this was a great article for getting started with using the command line. But there&#8217;s a lot more you can learn about using a shell, and I&#8217;ll take you to the next level in this tutorial!</p>
<p><span></span></p>
<hr />
<h2>Getting Started</h2>
<p>If you&#8217;re running Mac OS X, or your favourite flavour Linux, you&#8217;re all set. Just fire up the terminal, and keep going. If you&#8217;re on Windows, well, the default command set isn&#8217;t quite what a bash shell is. If you want some power, check out <a href="http://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx">Microsoft PowerShell</a>; however, the commands below won&#8217;t necessarily work there. You <em>can</em> get a bash shell on Windows, though:</p>
<ul>
<li>Install <a href="http://www.cygwin.com/">Cygwim</a>, a Linux-like environment for Windows.</li>
<li>Install <a href="http://code.google.com/p/msysgit/">msysgit</a>; depending on the options you choose when installing, you&#8217;ll get a Git Bash that should work will all these commands.</li>
<li>Try Windows&#8217; <a href="http://technet.microsoft.com/en-us/library/cc779522(WS.10).aspx">subsystem for Unix-based applications</a>. Although I haven&#8217;t tried it myself, I understand you can get a Unix shell with it.</li>
</ul>
<p>All right, let&#8217;s hop in!</p>
<hr />
<h2><span>1.</span> Touch</h2>
<div><img alt="touch" src="http://cdn.net.tutsplus.com/779_terminalTips/touch.jpg" /></div>
<p>As a developer, one of your most common tasks is creating files. If you&#8217;re working from the command line, most of the time you&#8217;ll just pass the name of the file you want to create to your editor:</p>
<pre>$ mate index.html
$ mvim default.css</pre>
<p>However, occasionally you&#8217;ll just want to create one or more files, without editing it. In this case, you&#8217;ll use the <code>touch</code> command:</p>
<pre>$ touch index.html
$ touch one.txt two.txt three.txt</pre>
<p>It&#8217;s that easy. Actually, the <code>touch</code> command is for updating the access / modified date of a file; it&#8217;s just a nice side-effect that if the file doesn&#8217;t exist, it will create it.</p>
<hr />
<h2><span>2.</span> Cat and Less</h2>
<div><img alt="cat and less" src="http://cdn.net.tutsplus.com/779_terminalTips/catLess.jpg" /></div>
<p>Well, since it&#8217;s all about files, there&#8217;s a good change you&#8217;ll want to see the contents of a file from the terminal sooner or later. There&#8217;s a few commands that will do this for you. First is <code>cat</code>; <code>cat</code> is short for &#8220;concatenate&#8221;, and this command does more than output file contents; however, that&#8217;s what we&#8217;ll look at here. It&#8217;s as simple as passing the command a file:</p>
<pre>$ cat shoppingList.txt</pre>
<p>However, if the file is large, the contents will all scroll past you and you&#8217;ll be left at the bottom. Granted, you can scroll back up, but that&#8217;s lame. How about using <code>less</code>?</p>
<pre>$ less shoppingList.txt</pre>
<p>Less is a much better way to inspect large files on the command line. You&#8217;ll get a screen-full of text at a time, but no more. You can move a line up or a line down with the <code>k</code> and <code>j</code> respectively, and move a window up or down with <code>b</code> and <code>f</code>. You can search for a pattern by typing <code>/pattern</code>. When you&#8217;re done, hit <code>q</code> to exit the <code>less</code> viewer.</p>
<hr />
<h2><span>3.</span> Curl</h2>
<div><img alt="curl" src="http://cdn.net.tutsplus.com/779_terminalTips/curl.jpg" /></div>
<p>Since you probably work with your fair share of frameworks libraries, you&#8217;ll often find yourself downloading these files as you work. Oh, I know: you can just download it from the web, navigate to the folder, uncompress it, and copy the pieces to your project, but doesn&#8217;t that sound like so much work? It&#8217;s much simpler to use the command line. To download files, you can use <code>curl</code>; proceed as follows:</p>
<pre>$ curl -O http://www.domain.com/path/to/download.tar.gz</pre>
<p>The <code>-O</code> flag tells <code>curl</code> to write the downloaded content to a file with the same name as the remote file. If you don&#8217;t supply this parameter, curl will probably just display the file in the commmand line (assuming it&#8217;s text).</p>
<p>Curl is a pretty extensive tool, so check out the man page (see below) if you think you&#8217;ll be using it a lot. Here&#8217;s a neat tip that uses the shell&#8217;s bracket expansion:</p>
<pre>$ curl -0 http://www.domain.com/{one,two,three}.txt</pre>
<p>Yeah, it&#8217;s that easy to download multiple files from one place at once. (Note that this isn&#8217;t curl functionality; it&#8217;s part of the shell, so you can use this notation in other commands; <a href="http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html">check this link</a> out for more)</p>
<hr />
<h2><span>4.</span> Tar and Gzip</h2>
<div><img alt="tar and gzip" src="http://cdn.net.tutsplus.com/779_terminalTips/tarGzip.jpg" /></div>
<p>So, now you&#8217;re rocking command line downloads; however, there&#8217;s a really good chance that most of the things you download will be archived and gzipped, having an extension of .tar.gz (or, alternately, .tgz). So, what do you do with that? Let&#8217;s take a step back for a second and understand what exactly &#8220;archived and gzipped&#8221; means. You&#8217;re probably familiar with archives. You&#8217;ve seen .zip files; they&#8217;re one incarnation of archives. Basically, an archive is just a single file that wraps more than one file together. Often archives compress the files, so that the final file is smaller than the original ones together. However, you can still get a bit smaller by compressing the archive &#8230; and that&#8217;s where gzipping comes in. Gzipping is a form of compression.</p>
<p>So, back to that download. It&#8217;s been tarred (archived) and gzipped. You could unzip it and then un-tar it, but we&#8217;re all about fewer keystrokes here, right? Here&#8217;s what you&#8217;d do:</p>
<pre>$ tar xvzf download.tar.gz</pre>
<p>Wait, what? Here&#8217;s the breakdown: <code>tar</code> is the command we&#8217;re running; <code>xvzf</code> are the flags we&#8217;re using (usually, you&#8217;d have a dash in front, but that&#8217;s optional here). The flags are as follows:</p>
<ul>
<li><code>x</code> let&#8217;s <code>tar</code> know we&#8217;re e<strong>x</strong>tracting, not archiving.</li>
<li><code>v</code> let&#8217;s <code>tar</code> know we want it to be <strong>v</strong>erbose (give us some output about the action it&#8217;s performing).</li>
<li><code>z</code> let&#8217;s <code>tar</code> know that the file we&#8217;re working with has been gzipped (so it unzips the file).</li>
<li><code>f</code> let&#8217;s <code>tar</code> know we&#8217;re going to pass it the name of the archive file.</li>
</ul>
<p>If you want to create one of these gzipped archives, it&#8217;s as simple as replacing the <code>x</code> flag with a <code>c</code> (to <strong>c</strong>reate an archive). The <code>v</code> and <code>z</code> flags are options: do you want output? how about gzipping? Of course, leave <code>f</code>; you&#8217;ll have to give the file name for the new archive (otherwise, it will all be output to the command line). After that, you&#8217;ll pass the command all the files you want to put in the archive:</p>
<pre>$ tar cvzf archive.tar.gz index.html css js auth.php
$ tar cvzf archive.tar.gx *.txt</pre>
<p>Just for completeness, I&#8217;ll mention that you can gzip archives (or other files) individually; when you do so, gzip replaces the original file with the gzipped version. To un-gzip, add the <code>-d</code> flag (think <strong>d</strong>ecompress.</p>
<pre>$ gzip something.txt
$ gzip -d something.txt.gz</pre>
<hr />
<h2><span>5.</span> Chmod</h2>
<div><img alt="chmod" src="http://cdn.net.tutsplus.com/779_terminalTips/chmod.jpg" /></div>
<p>Another thing you&#8217;ll do often as a web developer is change file permissions. There are three permissions you can set, and there are three classes that can receive those permissions. The permissions are <em>read</em>, <em>write</em>, and <em>execute</em>; the classes are <em>user</em>, <em>group</em>, and <em>others</em>. The user usually the owner of the file, the user that created the file. It&#8217;s possible to have groups of users, and the group class determines the permissions for the users in the group that can access the file. Predictably, the others class includes everyone else. Only the user (owner of the file) and the super user can change file permissions. Oh, and everything you&#8217;ve just read goes for directories as well.</p>
<p>So, how can we set these permissions? The command here <code>chmod</code> (<strong>ch</strong>ange <strong>mod</strong>e). There are two ways to do it. First, you can do it with octal notation; this is a bit cryptic, but once you figure it out, it&#8217;s faster. Basically, execute gets 1 &#8216;point&#8217;, write gets 2, and read gets 4. You can add these up to give multiple permissions: read+write = 6, read+write+execute = 7, etc. So for each class, you&#8217;ll get this number, and line them up to get a three digit number for User, Group, and Others. For example, 764 will give user all permissions, give group read and write ability, and give others permission to read. For a better explanation, check out <a href="http://en.wikipedia.org/wiki/File_system_permissions#Octal_notation">the Wikipedia article</a>.</p>
<p>If you have a hard time remembering the octal notation, you might find symbolic notation easier (although it takes a few more keystrokes). In this case, you&#8217;ll use the initial &#8216;u&#8217;, &#8216;g&#8217;, and &#8216;o&#8217; for user, group, and others respectively (and &#8216;a&#8217; for all classes). Then, you&#8217;ll use &#8216;r&#8217;, &#8216;w&#8217;, and &#8216;x&#8217; for read, write, and execute. Finally, you&#8217;ll use the operators &#8217;+&#8217;, &#8216;-&#8216;, and &#8217;=&#8217; to add, subtract, and absolutely set permissions. Here&#8217;s how you&#8217;ll use these symbols: class, operator, permissions. For example, <code>u+rwx</code> adds all permissions to the user class; <code>go-x</code> removes executable permission from group and others; <code>a=rw</code> sets all classes to read and write only.</p>
<p>To use all this theory on the command line, you&#8217;ll start with the command (<code>chmod</code>), followed by the permissions, followed by the files or directories:</p>
<pre>$ chmod 760 someScript.sh
$ chmod u=rwx g+r o-x dataFolder</pre>
<hr />
<h2><span>6.</span> Diff and Patch</h2>
<div><img alt="diff and patch" src="http://cdn.net.tutsplus.com/779_terminalTips/diffPatch.jpg" /></div>
<p>If you&#8217;ve used version control like Git or Subversion, you know how helpful such a system is when you want to share a project with other developers, or just keep track of versions. But what if you want to send a friend some updates to a single file? Or what if another developer has emailed you the new version of a file that you&#8217;ve edited since you received the last copy? Sometimes, full-blown version control is too much, but you still need something small. Well, the command line has you covered. You&#8217;ll want to use the <code>diff</code> command. Before you make changes to a file, copy the file so you have the original. After you update, run <code>diff</code>; if you don&#8217;t send the output to a file, it will just be output to the command line, so include a <code>&gt;</code> with the name for your patch file:</p>
<pre>$ cp originalFile newFile
$ vim newFile #edit newFile
$ diff originalFile newFile
1c1
&lt; This is a sentence.
---
&gt; This is a short sentence.
$ diff originalFile newFile &gt; changes.patch</pre>
<p>As you can see, the <code>diff</code> is just a simple text file that uses a syntax the <code>diff</code> and <code>patch</code> command will understand. <code>Patch</code>? Well, that&#8217;s the command that goes hand in hand with <code>diff</code>. If you&#8217;ve received a patch file, you&#8217;ll update the original as follows:</p>
<pre>patch originalFile2 changes.patch</pre>
<p>And now you&#8217;re all updated.</p>
<hr />
<h2><span>7.</span> Sudo</h2>
<div><img alt="sudo" src="http://cdn.net.tutsplus.com/779_terminalTips/sudo.jpg" /></div>
<p><code>Sudo</code> isn&#8217;t really a command like the others, but it&#8217;s one you&#8217;ll find a need for as you venture deeper into the command line world. Here&#8217;s the scenario: there are some things that regular users just shouldn&#8217;t be able to do on the command line; it&#8217;s not hard to do irrevocable damage. The only user who has the right to do anything he or she wants is the super user, or root user. However, it&#8217;s not really safe to be logged in as the super user, because of all that power. Instead, you can use the <code>sudo</code> (<strong>s</strong>uper <strong>u</strong>ser <strong>do</strong>) command to give you root permissions for a single command. You&#8217;ll be asked for you user account password, and when you&#8217;re provided that, the system will execute the command.</p>
<p>For example, installing a ruby gem requires super user permissions:</p>
<pre>$ gem install heroku
ERROR:  While executing gem ... (Errno::EACCES)
    Permission denied - /Users/andrew/.gem/ruby/1.9.1/cache/heroku-1.9.13.gem
$ sudo gem install heroku
Password:
Successfully installed heroku-1.9.13</pre>
<hr />
<h2><span>8.</span> Man</h2>
<div><img alt="man" src="http://cdn.net.tutsplus.com/779_terminalTips/man.jpg" /></div>
<p>Most of the commands you&#8217;ll use in a bash shell are pretty flexible, and have a lot of hidden talents. If you suspect a command might do what you want, or you just want to see some general instruction on using a command, it&#8217;s time to hit the manuals, or man pages, as they&#8217;re called. Just type <code>man</code> followed by the command you&#8217;re curious about.</p>
<pre>$ man ln</pre>
<p>You&#8217;ll notice that the man pages are opened in <code>less</code>.</p>
<hr />
<h2><span>9.</span> Shutdown</h2>
<div><img alt="shutdown" src="http://cdn.net.tutsplus.com/779_terminalTips/shutdown.jpg" /></div>
<p>When you&#8217;re done for the day, you can even turn your computer off from the command line. The command in the spotlight is <code>shutdown</code>, and you&#8217;ll need to use <code>sudo</code> to execute it. You&#8217;ll have to give the command a flag or two; the most common ones are <code>-h</code> to halt the system (shut it down), <code>-r</code> to reboot, and <code>-s</code> to put it to sleep. Next, you&#8217;ll pass the time it should happen, either as <code>now</code>, <code>+numberOfminutes</code>, or <code>yymmddhhmm</code>. Finally, you can pass a message to be shown to users when the deed is about to be done. If I wanted to put my computer to sleep in half-an-hour, I&#8217;d run this:</p>
<pre>$ sudo shutdown -s +30</pre>
<hr />
<h2><span>10.</span> History, !!, and !$</h2>
<div><img alt="history" src="http://cdn.net.tutsplus.com/779_terminalTips/history.jpg" /></div>
<p>Since the command line is all about efficiency, it&#8217;s supposed to be easy to repeat commands. There are a few ways to do this. First, you can use the <code>history</code> command to get a numbered list of many of your recent commands. Then, to execute one of them, just type an exclamation mark and the history number.</p>
<pre>$ history
...
563  chmod 777 one.txt
564  ls -l
565  ls
566  cat one.txt
...
$ !565</pre>
<p>Granted, this is a terrible example, because I&#8217;m typing more characters to use the history than it would take to re-type the command. But once you&#8217;re combining commands to create long strings, this will be faster.</p>
<p>It&#8217;s even quicker to access the last command and last argument you used. For the latest command, use <code>!!</code>; the usual use case given for this is adding sudo to the front of a command. For the latest argument, use <code>!$</code>; with this, moving into a new folder is probably the common example. In both these cases, the shell will print out the full command so you can see what you&#8217;re really executing.</p>
<pre>$ gem install datamapper
ERROR:  While executing gem ... (Errno::EACCES)
    Permission denied - /Users/andrew/.gem/ruby/1.9.1/cache/datamapper-1.0.0.gem
$ sudo !!
sudo gem install datamapper
Password:
Successfully installed datamapper-1.0.0

$ mkdir lib
$ cd !$
cd lib</pre>
<hr />
<h2>Conclusion</h2>
<p>If you&#8217;re as passionate about productivity as I am, the idea of using the command line as much as possible should resonate with you. What I&#8217;ve shown you here is just a sampling of the built in commands &#8230; then, there are many more than you can install yourself (look at something like <a href="http://mxcl.github.com/homebrew/">the homebrew package manager</a>, for example). But maybe you&#8217;re already proficient on the command line; if so, can you share another great command with the rest of us? Hit the comments!</p>
<div>
<a href="http://feeds.feedburner.com/~ff/nettuts?a=F4wvnDMBVmI:adMmI25oNBE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=F4wvnDMBVmI:adMmI25oNBE:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nettuts?i=F4wvnDMBVmI:adMmI25oNBE:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=F4wvnDMBVmI:adMmI25oNBE:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nettuts?i=F4wvnDMBVmI:adMmI25oNBE:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=F4wvnDMBVmI:adMmI25oNBE:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/nettuts?i=F4wvnDMBVmI:adMmI25oNBE:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=F4wvnDMBVmI:adMmI25oNBE:TzevzKxY174"><img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"></img></a>
</div>
<p><img src="http://feeds.feedburner.com/~r/nettuts/~4/F4wvnDMBVmI" height="1" width="1" /></p>
]]></content:encoded>
			<wfw:commentRss>http://terrytoledo.com/2010/09/10-terminal-commands-that-will-boost-your-productivity/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>An Analysis of Typography on the Web</title>
		<link>http://terrytoledo.com/2010/09/an-analysis-of-typography-on-the-web/</link>
		<comments>http://terrytoledo.com/2010/09/an-analysis-of-typography-on-the-web/#comments</comments>
		<pubDate>Sat, 04 Sep 2010 04:00:08 +0000</pubDate>
		<dc:creator>Nettuts</dc:creator>
				<category><![CDATA[Nettuts]]></category>

		<guid isPermaLink="false">http://terrytoledo.com/2010/09/an-analysis-of-typography-on-the-web/</guid>
		<description><![CDATA[Typography is one of the most&#8212;if not the most&#8212;important aspects of web design. Some would argue that it takes up to 95% of web design, so why do we often neglect its importance? The readers who come to your site will often decide whether or not to stay according to your typographic choices. After all, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://feedads.g.doubleclick.net/~a/t8SZSp-7qe-6MgbTU08VJCsr8B0/0/da"><img src="http://feedads.g.doubleclick.net/~a/t8SZSp-7qe-6MgbTU08VJCsr8B0/0/di" border="0"></img></a><br />
<a href="http://feedads.g.doubleclick.net/~a/t8SZSp-7qe-6MgbTU08VJCsr8B0/1/da"><img src="http://feedads.g.doubleclick.net/~a/t8SZSp-7qe-6MgbTU08VJCsr8B0/1/di" border="0"></img></a></p>
<p>Typography is one of the most&mdash;if not the most&mdash;important aspects of web design. Some would argue that it takes up to <a href="http://informationarchitects.jp/the-web-is-all-about-typography-period/" title="Information Architects, 'Web Design is 95% Typography'">95% of web design,</a> so why do we often neglect its importance? The readers who come to your site will often decide whether or not to stay according to your typographic choices. After all, they came here to <i>read</i> in the first place. Think about it for a second: if content really is king, logically typography should be treated as the queen.</p>
<p><span></span></p>
<p>In fact, even some font names suggest that classification; Futura, Optima, Times New Roman (OK, that&#8217;s probably a dude), Verdana, Lucida, Georgia, Helvetica&hellip; There&#8217;s no question about it, Typography is the queen. Therefore, she also needs to be dressed up properly before going out: she should put on some kerning and tracking, maybe a different font-variant, and already she&#8217;s looking like a real lady.</p>
<p>Not sure what I&#8217;m talking about? Well, read on.</p>
<hr />
<h2>Knowing Your (sans) Serifs</h2>
<p>Before proceeding with this article, and especially if you don&#8217;t have much contact with typography, I suggest you fill the gaps of your Typographic knowledge from <a href="http://www.typedia.com" title="Typeda, a user-powered Website on Typography">Typedia</a>, taking special note of <a href="http://typedia.com/learn/only/typeface-classifications/">Typeface classifications</a> and <a href="http://typedia.com/learn/only/anatomy-of-a-typeface/">the anatomy of a typeface</a>, which will serve you well when making your own font-stacks and pairing fonts.</p>
<p>After you finish reading the two articles on Typedia, come back here so we can tighten your newly-founded Typographic knowledge and prepare it for the next few chapters of this article.</p>
<h3><span>Tightening Wisdom #1:</span> Typefaces Relate</h3>
<p>Typefaces have dynamic relationships and can look good or bad together, depending on who they&#8217;re mixed with and their differences. If we&#8217;d like to get technical, there are in fact three ways in which typefaces can relate:</p>
<ol>
<li>
<h4>Concord</h4>
<p>A concordant relationship is the one with no thrills, where two typefaces are very similar in characteristics. It can also be a single typeface in multiple styles and/or sizes.</p>
</li>
<li>
<h4>Contrast</h4>
<p>When typefaces are fairly different from each other, contrast appears. It&#8217;s usually good to aim for contrast, for instance, between a serif and sans-serif typeface.</p>
</li>
<li>
<h4>Conflict</h4>
<p>Two (or more) typefaces who have different characteristics that are still similar enough to create distress on a page are in conflict. You should usually avoid this type of relationship.</p>
</li>
</ol>
<div>
<img src="http://nettuts.s3.amazonaws.com/781_typography/relationships.png" alt="Contrasting, conflicting and concording relationship between fonts." />
</div>
<h3><span>Tightening Wisdom #2:</span> Typefaces Differ</h3>
<p>Typefaces can vary. Whether it is weight, height, width, or anything else, every single typeface has some characteristic that makes it stand out. You should learn to spot these subtleties and adapt to their influence. And don&#8217;t think it doesn&#8217;t matter, since even various iterations of the same typefaces can be <a href="http://barneycarroll.com/garamond.htm" title="Comparing different Garamond iterations">significantly unequal</a> at times.</p>
<p>This specifically relates to the Web, where the art of creating and applying font stacks is very important. You do not have to pick exactly the same-looking typefaces for a fallback, but it&#8217;s only fair to say that an oldstyle font like Garamond should be backed up by another oldstyle typeface with sensibly similar characteristics (Caslon, Baskerville, Times, for instance).</p>
<div>
<img src="http://nettuts.s3.amazonaws.com/781_typography/letter-comparison.png" alt="Adobe Garamond Pro, Garamond Premier Pro and Georgia side-by-side" /></p>
<p>Although they&#8217;re all serifs, Georgia, Garamond and Adobe Garamond Pro (200 point size in example above) look very different.
</p></div>
<h3><span>Tightening Wisdom #3:</span> Not Every Typeface is Suitable For All Situations</h3>
<p>A modern font, such as Bodoni Condensed or <a href="http://danielmall.com" title="Daniel Mall uses Bodoni Bold for his blog headlines with beautiful results">Bodoni Bold</a> is an excellent choice for headlines, whereas it would likely be a bad typeface for extensive lines of body copy, where it would only distract the reader from the content. An oldstyle like <a href="http://en.wikipedia.org/wiki/Garamond" title="Wikipedia on the legendary typeface">Garamond</a> (I &hearts; Garamond) is a much better choice for these situations.</p>
<p>Non-designers often make poor decisions when choosing typefaces for different occasions, and&mdash;although I&#8217;m going to skip the Comic Sans lecture&mdash;you should be aware of the fact that it&#8217;s not always suitable to use, say, Georgia for body copy. It&#8217;s also not always bad to use Arial as your preferred typeface; but do consider what message you are trying to convey, via your typography.</p>
<hr />
<h2>Learning From The Best</h2>
<p>This article is not primarily a showcase, yet it&#8217;s always interesting to observe what other talented designers have done to make their (client&#8217;s) websites a delight to look at. We&#8217;re going to see what can be done with careful consideration for font decoration, as well as solid font-stacks and smart typographic choices.</p>
<p>(P.S. If you&#8217;d like to see other examples of nice Typography on line, browse through <a href="http://typesites.com/archives/">Typesites&#8217; archives</a>. There&#8217;s not too much content there, but they&#8217;ve covered some very good sites.)</p>
<h3><span>Websafe Fonts:</span> A List Apart</h3>
<div>
<a href="http://alistapart.com"><img src="http://nettuts.s3.amazonaws.com/781_typography/ala.jpg" alt="A List Apart, careful consideration to Webfonts" /></a><br />
<i>A List Apart</i> shows how Websafe fonts can look good indeed when given enough thought.
</div>
<p>Is Verdana the most boring typeface you can use? Not if you ask Jason Santa Maria. He was smart in using Verdana&#8217;s strength (X-height) to make body copy rather small in size for a dignified, elegant look that <i>A List Apart</i> deserves. The small size also makes it pleasant to read in the long run.</p>
<p>Georgia is mostly used for emphasis on certain page elements, and as a display typeface. From other noticeable design decisions, uppercase letters are small in size and positive letter-spaced for easier readability and better looks.</p>
<h3><span>Font Stacks:</span> Jon Tan</h3>
<div>
<a href="http://jontangerine.com"><img src="http://nettuts.s3.amazonaws.com/781_typography/attention-to-detail.jpg" alt="JonTangerine.com, typographic excellence" /></a><br />
Jon Tan, attention to detail brings Typographic perfection.
</div>
<p>Jon Tan, like <a href="http://www.subtraction.com/" title="Subtraction">Khoi Vin</a> and <a href="http://www.danielmall.com/">Daniel Mall</a>, also follows the cult of black <span>&amp;</span> white minimalist design with carefully placed splashes of orange. Although there&#8217;s a lack of excitement in color choice, you could say that Jon makes up for it by taking extra care of his typographic choices. The CSS file of Jontangerine.com contains more than 250 different declarations for all micro-typography!</p>
<p>The main body copy is set in lovely Georgia, while centered headings appear in a Times-based font stack with Baskerville and Palatino:</p>
<pre>font-family: baskerville, 'palatino linotype', 'times new roman', serif;</pre>
<p>In other areas, typographic &#8220;color&#8221; is achieved using different font-variants, various shades of black and excellent font styling. Definitely one of the best typography-centered sites out there!</p>
<h3><span>@font-face Embedding:</span> Information Highwayman</h3>
<div>
<a href="http://informationhighwayman.com"><img src="http://nettuts.s3.amazonaws.com/781_typography/info-highway.jpg" alt="Information Highwayman" /></a><br />
Information Highwayman is embedding <a href="http://www.dafont.com/justus.font">Justus</a>, a free font.
</div>
<p>You have probably heard a lot about <a href="http://net.tutsplus.com/tutorials/design-tutorials/quick-tip-how-to-work-with-font-face/" title="Nettuts quick tip: 'How to work with @font-face'">@font-face embedding</a> with CSS during the past few months. Although Internet Explorer has had a similar technique ever since its fourth iteration (we&#8217;re ashamed to admit this), only in 2009&mdash;when all of the five big browsers implemented @font-face (the right way)&mdash;did we start talking intensively about using non-core webfonts online.</p>
<p>There are, as you might know, a few considerable drawbacks to this technique (primarily copyright issues), but if you find a suitable font for your needs, you have every chance of improving the way readers experience your site. D. Bnonn Tennant (Information Highwayman) decided to use Justus for body copy, which contrasts quite well against the sans-serif background element (the &#8220;compelling magnum&#8221;) and helps in achieving the &#8220;worn-out&#8221; effect on the site.</p>
<h3><span>Typekit:</span> Elliot Jay Stocks</h3>
<div>
<a href="http://elliotjaystocks.com"><img src="http://nettuts.s3.amazonaws.com/781_typography/elliotjay.jpg" alt="FF Tisa Web Pro on ElliotJayStocks.com" /></a><br />
The slabby FF Tisa goes perfect with Elliot&#8217;s website.
</div>
<p>Elliot likes to use Slab-Serif typefaces, which is exemplified in both his excellent <a href="http://8faces.com/"><i>8 faces</i></a> magazine on Typography (highly recommend it), with <a href="http://www.fontshop.com/fonts/downloads/fontfont/ff_unit_slab_ot_collection/" title="FF Unit Slab in Fontshop">FF Unit Slab</a>, and his own <a href="http://elliotjaystocks.com">Website</a>, where <a href="http://www.behance.net/gallery/FF-Tisa-a-A-Perfect-Typeface-for-Magazines/170268" title="Find out more about FF Tisa">FF Tisa Web Pro</a> is embedded using <a href="http://typekit.com/fonts/ff-tisa-web-pro">Typekit&#8217;s font embedding service</a>.</p>
<p>There isn&#8217;t as much typographic styling on the site as, for instance, Jon Tan has; however, he&#8217;s done a great job with alignment and color, which also never should be overlooked and are important ingredients in good typography.</p>
<h3><span>Image Replacement and sIFR:</span> Squared Eye</h3>
<div>
<a href="http://squaredeye.com"><img src="http://nettuts.s3.amazonaws.com/781_typography/squaredeye.png" alt="Squared Eye, sIFR typography" /></a><br />
Squared Eye uses <a href="http://www.mikeindustries.com/blog/sifr" title="Find out more about sIFR">sIFR</a> Flash text replacement.
</div>
<p>Although they&#8217;re rapidly becoming &#8220;old&#8221; replacement techniques, Flash and image-replaced text (both <a href="http://cufon.shoqolate.com/generate/" title="Find out more about Cufon">Cuf&oacute;n</a> and manually inserted images) instead of ordinary text are important for cross-browser compatibility in sites whose visitors aren&#8217;t predominantly using modern browsers, as well as in cases where the particular font isn&#8217;t available due to one or the other reason (e.g., copyright issues).</p>
<p>Squared Eye places emphasis on different levels of headings with sIFR, as well as with manually inserted images. He&#8217;s using a beautiful slab-serif <a href="http://typography.com/fonts/font_styles.php?productLineID=100033">Archer</a> in harmony with a Lucida-based font stack for a modern, yet still elegant look.</p>
<hr />
<h2>Putting Our Knowledge to Good Use</h2>
<p>Although I&#8217;m going to provide a few font-stacks you can use in your designs, consider the following more as a &#8220;training&#8221; for making your own font stacks. There are already plenty of <a href="http://www.codestyle.org/css/font-family/" title="Code style offers some pretty extensive tips on font stacks">other sites</a> out there which offer a lot of readymade solutions for both display and body copy text.</p>
<p>As the saying goes, &#8220;Give a man a fish and you feed him for a day. Teach a man to fish and you feed him for a lifetime.&#8221;</p>
<h3><span>Gripping the Bases:</span> Your Readers</h3>
<p>Before beginning to build font stacks, you should become acquainted with your primary audience and determine what software and Operating Systems they use. That way, you can predict which fonts they might have installed, and how much typographic flexibility that provides you.</p>
<p>For instance; Matthew Smith (Squared Eye) probably (rightfully) predicted that most of his audience will not have a font like Archer installed on their computers and decided to embed it using Flash font replacement (comparing to Archer, &#126;97% of users have Flash installed).</p>
<blockquote><p>Always design with core Webfonts first, and then gradually improve with font stacks)</p>
</blockquote>
<p>For more information on fonts shipped with different software, browse through 24 Ways&#8217; <a href="http://media.24ways.org/2007/17/fontmatrix.html">Font Matrix</a>, <a href="http://fluidwebtype.info/web-safe-fonts/" title="Comparing the likelihood of a font being installed on Win/Mac">Fluid Web Type</a> and <a href="http://www.apaddedcell.com/web-fonts" title="'Complete Guide to Pre-Installed Fonts in Linux, Mac, and Windows'">Apaddedcell</a>. You might also find Microsoft&#8217;s <a href="http://support.microsoft.com/kb/837463/">extensive documentation</a> on fonts that come with their products, as well as insight into their <a href="http://www.microsoft.com/typography/default.mspx">Typographic department</a>, a useful read.</p>
<h3>Notice The Small Things</h3>
<p>When it comes to building font stacks, you&#8217;ll need to consider a few variables, when determining what make fonts different from one other (remember the Georgia-Garamond-Garamond comparison above?). This, again, comes down to your experience and familiarity with different font categories. You&#8217;ll need to learn to notice not only the way serifs are presented (are they slanted, or straight? Or do they not exist?), but also the small(er) differences between two similar typefaces.</p>
<p>Consider how they communicate with each other, their x-heights and readability on small sizes, as well as their form and direction. Even if this sounds, perhaps, intimidating right now, remember how practice makes perfect.</p>
<p><b>Example:</b> <a href="http://new.myfonts.com/fonts/fontbureau/ibis-display/">Ibis Display</a> and <a href="http://typography.com/fonts/font_styles.php?productLineID=100033" title="Visit H&amp;FJ For more info on Archer">Archer</a>, although both slab-serifs by category, probably wouldn&#8217;t make a good pair due to the significant difference in the way their serifs are presented and the noticeable thick/thin transitions on Ibis versus a monoweight Archer.</p>
<h3>Writing a Sample Font Stack</h3>
<p>I&#8217;ve already mentioned I like Garamond. So I&#8217;m going to base a font stack off of Times New Roman, which is the Web-safe font closest in appearance to the aforementioned oldstyle typeface.</p>
<p>I would like to mention that Garamond, due to its low X-height, likely isn&#8217;t the best choice when designing for excellent readability on screen (after all, it wasn&#8217;t made for screen presentation primarily), but it is fine if used on high enough font sizes (in my opinion, 16-17 pixel/1em Garamond is optimal).</p>
<blockquote><p>In optical scaling, as it is called, smaller text sizes typically have larger x-heights, wider stem widths, and less typographic stem contrast and larger display sizes have smaller x-heights with more variation in stem widths. <br />
&ndash; <a href="http://blogs.msdn.com/b/fontblog/archive/2010/06/25/the-art-and-tradition-of-typography.aspx" title="The art and tradition of Typography">MSDN Blogs</a></p>
</blockquote>
<div>
<img src="http://nettuts.s3.amazonaws.com/781_typography/font-stacks.png" alt="Font degrading in our font-stack" /><br />
How our font family will degrade in case Garamond isn&#8217;t available (Garamond colored blue in examples).
</div>
<p>According to 24 Ways&#8217; Font Matrix, Garamond is shipped with Office Word 2007 for Windows, and Word 2004 for Mac, which means that it&#8217;s available to a huge percentage of visitors. For those who don&#8217;t have it installed, I&#8217;ve provided a backup in the form of Adobe&#8217;s Caslon, Garamond and Minion Pro typefaces which come shipped with the Creative Suite (notice, however, that all of these fonts are also available for individual download; I&#8217;m mentioning the programs they ship with because I suppose a lot of you bought them with Adobe&#8217;s software).</p>
<p>I&#8217;ve also decided to use Crimson text from Google&#8217;s <a href="http://code.google.com/webfonts">Webfont repository</a> to provide a decent fallback before Times. The final font stack looks like this:</p>
<pre>font-family: Garamond, Adobe Garamond Pro, Minion Pro, Adobe Caslon Pro, Crimson Text, Times, serif;</pre>
<p>This font stack should be used exclusively on higher font sizes, especially because Windows is notorious for poor font rendering.</p>
<div>
<img src="http://nettuts.s3.amazonaws.com/781_typography/font-rendering.png" alt="Font rendering in Safari vs. Chrome" /></p>
<p>Chrome with default settings (left) and Safari with font smoothing set to Medium (right). May look subtle at first, but it makes a big impact on readability in smaller sizes.
</p></div>
<p>If you were looking for extremely good on-screen readability, the high-x-height-blessed Georgia and Verdana (both fonts are from the nineties, made specifically for screen rendering) will provide more pleasing results in font-stacks.</p>
<p>For instance, we could take advantage of the similarity between the Lucida serifs (Fax and Bright, which also come with MS Word) and Droid serif from the Google Webfont repository to make a highly readable font-stack with a large x-height:</p>
<pre>font-family: Lucida Bright, Lucida Fax, Droid serif, Georgia, Serif;</pre>
<p>Once again Google&#8217;s webfonts come to action before a generic solution, mostly because Droid serif is much closer in appearance to Lucida than Georgia and Times, respectively.</p>
<p>A very similar Verdana-based stack would also contain the three almost equal Lucida sans-serifs (Grande &#8211; ships with Mac, Sans, Sans Unicode):</p>
<pre>font-family: Lucida Sans, Lucida Sans Unicode, Lucida Grande, Verdana, Sans-serif;</pre>
<p>Notice how the replacement fonts have similar characteristics, particularly how the <em>g</em> letter is virtually the same across typefaces, and how the <em>o</em> resembles a circle rather than an ellipse. As with most sans-serifs, they&#8217;re monoweight and don&#8217;t have any thick/thin transitions (<a href="http://new.myfonts.com/fonts/adobe/optima/">Optima</a>, for instance, isn&#8217;t monoweight &mdash;that&#8217;s what makes it more difficult to pair with other fonts).</p>
<div><img src="http://nettuts.s3.amazonaws.com/781_typography/sans-serif-stack.png" alt="Lucida-based Sans-serif font stack" /></div>
<hr />
<h2>Being Picky</h2>
<p>While creating sensible font stacks is important, in order to provide excellent typography, you&#8217;re going to have to do the &#8220;extra ten percent&#8221; and provide typographical contrast using different font variants, weights, direction and nurturing care to all <a href="http://en.wikipedia.org/wiki/Microtypography" title="Wikipedia on micro typography, a short but useful read">micro typographic</a> methods.</p>
<div><img src="http://nettuts.s3.amazonaws.com/781_typography/jontan-post-title.png" alt="Jon Tan, attention to micro typography" /></p>
<p>Jon Tan tackles micro typography with extra care.</p></div>
<p>Jon Tan, for instance, uses some CSS3 selectors to create great visual impact.</p>
<pre>.entry-content p:first-line,
.entry-content img + p:first-line {
	font-variant: small-caps;
	font-weight: 900;
	text-indent: 0px;
}
</pre>
<p>He&#8217;s using centered and italicized headings within a blog post in a Times-based font stack. This, when combined with justified text and his minimalistic design, makes for a very pleasant reading experience. Remember: small things do matter.</p>
<div><img src="http://nettuts.s3.amazonaws.com/781_typography/jontan-heading.png" alt="Absolutely astonishing headings on jontangerine.com" /></div>
<p>Mixing things up with a bold typeface, uppercase titles and positive letter spacing for smaller headings will many times provide a far better experience and contrast, as well as clearer separation to the body copy, than just a different typeface. Samantha Warren <a href="http://badassideas.com/typographic-hierarchy/" title="'Typographic hierarchy', the elementary principles of design">has covered</a> Typographic hierarchy very well, and I suggest you read her article for a broader understanding of the topic.</p>
<div><img src="http://nettuts.s3.amazonaws.com/781_typography/headings.png" alt="Lucida and Garamond, contrasting and conflicting" /><br />Contrast improves separation. Can you even notice the second heading?</div>
<p>A seventeen pixel Garamond for body copy and 15px Lucida Sans for subheading level 4 (h4) do look quite different in the upper two situations, only due to a few small changes in our CSS:</p>
<pre>
body {
	font: 17px/1.4 Garamond, Adobe Garamond Pro, /* ... (look at the Garamond-based stack above) */ serif;
	color: #333;
	text-align: justify;
} 

h4#uppercase {
	text-transform: uppercase;
	font: bold 14px/1 Lucida Grande, Lucida Sans, Verdana, sans-serif;
	margin-top: 15px; letter-spacing: 1px;
}

h4#normalcase {
	text-transform: none;
	font-weight: normal;
	letter-spacing:0;
}
</pre>
<p>The italicized ampersands are another one of those techniques that prove how &#8220;small things matter&#8221; (notice, however, that not all fonts have &#8220;special&#8221; ampersands):</p>
<pre>
.amp {
	font-family:Adobe Caslon Pro,Garamond, Palatino Linotype, Bell MT, Minion Pro, Garamond, Constantia, Goudy Old Style, High Tower text, serif;

	/* The font-stack above contains some font-families that
	have nice ampersands. You should pick a couple that suit your
	needs on a particular website, rather than use all.
	For instance, Caslon, Palatino and Baskerville do a nice job
		most of the time. */

	font-style: italic;
	line-height: 0;
}
</pre>
<p>If you would like to automate the use of fancy ampersands (enclosing them to proper classes, as well as having some advanced typographic help), I suggest looking up the <a href="http://wordpress.org/extend/plugins/wp-typography/" title="Download WP-Typography for free">WP-Typography</a> plugin for WordPress.</p>
<hr />
<h2>Additional JavaScript Enhancement</h2>
<p>We could further improve our user&#8217;s experience by enhancing the site with some simple JavaScript to test whether she has a particular font installed on her system. Then, it&#8217;s simply a matter of picking a suitable fallback font, if the font isn&#8217;t available (i.e., increase font size to make another font more readable, use image replacement, load additional fonts, etc.).</p>
<blockquote>
<p>Note that you should still consider the fact that a small percentage of users browse the web with JavaScript turned off. </p>
</blockquote>
<p> You could, perhaps, <a href="http://screenr.com/ya7" title="From a previous NetTuts competition, 'Using jQuery to set up noscript styles'">add a noscript class</a> to the body if JavaScript is disabled and prepare some sensible typography for it, accordingly.</p>
<p>That said, there are a few, essentially equal, techniques for discovering if a particular font is installed on the user&#8217;s system. I&#8217;m going to use a slightly modified version of <a href="http://lucassmith.name/2009/05/test-if-a-font-is-installed-via-javascript.html" title="'How to test if a font is installed via Javascript', explanation of the code.">Lucas Smith&#8217;s</a> code:</p>
<pre>
function testFont(name) {
    name = name.replace(/['"]/g,'');

    var	body  = document.body,
		test  = document.createElement('div'),
		installed = false,
		template =
			'&lt;b style="display:inline !important; width:auto !important; font:normal 80px/1 \'X\',sans-serif !important"&gt;mmmmmwwwww&lt;/b&gt;'+
			'&lt;b style="display:inline !important; width:auto !important; font:normal 80px/1 \'X\',monospace !important"&gt;mmmmmwwwww&lt;/b&gt;',
		ab;

    if (name) {
        test.innerHTML = template.replace(/X/g, name);

        test.style.cssText = 'position: absolute; visibility: hidden; display: block !important';

        body.insertBefore(test, body.firstChild);

        ab = test.getElementsByTagName('b');

        installed = ab[0].offsetWidth === ab[1].offsetWidth;

        body.removeChild(test);
    }

    return installed;
}</pre>
<p>Upon pasting the code into your JavaScript file, you can simply test whether a particular font is installed on the users&#8217; computer by using conditional statements:</p>
<pre>
if (testFont("FontName"))
	// Do stuff if the font is installed
else
	// Do stuff if the font isn't installed, i.e. load Cuf&oacute;n replacement
</pre>
<p>One of the more interesting uses of this technique would possibly be linking to a font-loading file (@font-face, Google Webfonts&hellip;), in the case our preferred fonts aren&#8217;t available on the user&#8217;s system. That way, we improve performance, and don&#8217;t force the user to download extra &#126;30kb for no reason:</p>
<pre>
if (!testFont("Lucida Fax") &#038;&#038; !testFont("Lucida Bright") &#038;&#038; !testFont("Droid serif")) {

  var head = document.getElementsByTagName("head")[0];
  var webfontLink = document.createElement('link');
  webfontLink.rel = 'stylesheet';
  webfontLink.href = 'http://fonts.googleapis.com/css?family=Droid+serif';
	// now we have &lt;link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Droid+serif"&gt;
  head.appendChild(webfontLink);

}
</pre>
<h2>Further Reading and Resources</h2>
<ul>
<li><a href="http://flippingtypical.com/">Flipping typical</a> loads local fonts and displays them in your preferred text. Can be a bit intensive on the computer.</li>
<li><a href="http://unitinteractive.com/blog/2008/06/26/better-css-font-stacks/">Better CSS Font stacks</a>, from Unit Interactive. An oldie but goodie providing sample font-stacks suitable for both headlines and body copy.</li>
<li><a href="http://webfontspecimen.com/">Web font specimen</a> is a great tool for testing different fonts locally. You should also read the <a href="http://www.alistapart.com/articles/real-web-type-in-real-web-context/">supporting <i>A list apart</i> article</a>.</li>
<li><a href="http://www.smashingmagazine.com/2010/05/06/50-helpful-typography-tools-and-resources/">50 helpful Typography tools and resources</a> from Smashing Magazine</li>
<li><a href="http://www.amazon.com/dp/0321534042/?tag=kukurin-20" title="Buy on Amazon (affiliate link)"><i>The non-designer&#8217;s design book</i></a>, which covers basic Typographic and design principles for visual novices, a simple and quick read. You might find it useful that all fonts in the book are clearly named, so expect to find out how to differentiate them by type and category rather quickly.</li>
<li>Already know your basics? Try <a href="http://www.amazon.com/dp/0881792055/?tag=kukurin-20" title="Buy on Amazon (affiliate link)"><i>The Elements of Typographic Style</i></a>, an essential and excellent read for all designers, recommended by some of the best designers.</li>
</ul>
<p>&clubs; &spades; &clubs; &spades; &clubs; &clubs; &spades; &clubs;</p>
<p>I hope that you now have a better understanding of typography on the web. There&#8217;s definitely more to the matter, and I&#8217;ll enjoy hearing what you have to say about it in the comments!</p>
<div>
<a href="http://feeds.feedburner.com/~ff/nettuts?a=k34yKE64ong:IniMgBqRY4I:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=k34yKE64ong:IniMgBqRY4I:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nettuts?i=k34yKE64ong:IniMgBqRY4I:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=k34yKE64ong:IniMgBqRY4I:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nettuts?i=k34yKE64ong:IniMgBqRY4I:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=k34yKE64ong:IniMgBqRY4I:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/nettuts?i=k34yKE64ong:IniMgBqRY4I:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=k34yKE64ong:IniMgBqRY4I:TzevzKxY174"><img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"></img></a>
</div>
<p><img src="http://feeds.feedburner.com/~r/nettuts/~4/k34yKE64ong" height="1" width="1" /></p>
]]></content:encoded>
			<wfw:commentRss>http://terrytoledo.com/2010/09/an-analysis-of-typography-on-the-web/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Build a Custom HTML5 Video Player: Free Premium Tutorial</title>
		<link>http://terrytoledo.com/2010/09/build-a-custom-html5-video-player-free-premium-tutorial/</link>
		<comments>http://terrytoledo.com/2010/09/build-a-custom-html5-video-player-free-premium-tutorial/#comments</comments>
		<pubDate>Sat, 04 Sep 2010 02:32:39 +0000</pubDate>
		<dc:creator>Nettuts</dc:creator>
				<category><![CDATA[Nettuts]]></category>

		<guid isPermaLink="false">http://terrytoledo.com/2010/09/build-a-custom-html5-video-player-free-premium-tutorial/</guid>
		<description><![CDATA[Much like the other various Envato marketplaces, our newly launched Tuts+ marketplace will offer a free file each month. For September, that free file/tutorial just so happens to mine! I&#8217;ll show you how to build a custom HTML5 video player with Flash fallback support. Be sure to grab this one for free for the entire [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://feedads.g.doubleclick.net/~a/pq9dvBgzpBby3GCJFegqZge9J7k/0/da"><img src="http://feedads.g.doubleclick.net/~a/pq9dvBgzpBby3GCJFegqZge9J7k/0/di" border="0"></img></a><br />
<a href="http://feedads.g.doubleclick.net/~a/pq9dvBgzpBby3GCJFegqZge9J7k/1/da"><img src="http://feedads.g.doubleclick.net/~a/pq9dvBgzpBby3GCJFegqZge9J7k/1/di" border="0"></img></a></p>
<p>
Much like the other various Envato <a href="http://codecanyon.net">marketplaces</a>, our newly launched <a href="http://marketplace.tutsplus.com">Tuts+ marketplace</a> will offer a free file each month. For September, that <a href="http://marketplace.tutsplus.com/item/how-to-code-a-custom-html5-video-player/122026">free file/tutorial</a> just so happens to mine! I&#8217;ll show you how to build a custom HTML5 video player with Flash fallback support.
</p>
<p> Be sure to <a href="http://marketplace.tutsplus.com/item/how-to-code-a-custom-html5-video-player/122026">grab this one</a> for free for the entire month of September. Next month, it&#8217;ll return to its original price.  </p>
<p><span></span></p>
<div><a href="http://marketplace.tutsplus.com/item/how-to-code-a-custom-html5-video-player/122026"><img src="http://s3.envato.com/files/1123983/1_itemScreenshot.jpg" alt="Build a Custom HTML5 Video Player" /></a></div>
<blockquote><p>Though the idea of a video-specific HTML element was suggested well over a decade ago, we’re only just beginning to see this come to fruition! Forget all of that “HTML5 2012” mumbo-jumbo; the truth is that you can use the video element in your projects right now! The only problem is that the video players are inconsistent from browser to browser, and full-screen support is, at the time of this writing, only available in certain browsers, via a right-click. Further, what if we want to brand our video player? Unfortunately, there isn’t an easy way to do so by default. The solution is to create a custom player that remedies all of these issues.
</p>
</blockquote>
<p>While we&#8217;re using a great deal of our Premium catalog to populate the new marketplace, it will quickly become dominated by unique tutorials, screencasts, and eBooks! Be sure to <a href="http://marketplace.tutsplus.com">check it out</a> if you haven&#8217;t already. </p>
<div>
<a href="http://feeds.feedburner.com/~ff/nettuts?a=w__eY_v1t5M:E1_Dva7sosI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=w__eY_v1t5M:E1_Dva7sosI:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nettuts?i=w__eY_v1t5M:E1_Dva7sosI:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=w__eY_v1t5M:E1_Dva7sosI:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nettuts?i=w__eY_v1t5M:E1_Dva7sosI:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=w__eY_v1t5M:E1_Dva7sosI:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/nettuts?i=w__eY_v1t5M:E1_Dva7sosI:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=w__eY_v1t5M:E1_Dva7sosI:TzevzKxY174"><img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"></img></a>
</div>
<p><img src="http://feeds.feedburner.com/~r/nettuts/~4/w__eY_v1t5M" height="1" width="1" /></p>
]]></content:encoded>
			<wfw:commentRss>http://terrytoledo.com/2010/09/build-a-custom-html5-video-player-free-premium-tutorial/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Creating a Web Poll with PHP</title>
		<link>http://terrytoledo.com/2010/09/creating-a-web-poll-with-php/</link>
		<comments>http://terrytoledo.com/2010/09/creating-a-web-poll-with-php/#comments</comments>
		<pubDate>Fri, 03 Sep 2010 04:00:06 +0000</pubDate>
		<dc:creator>Nettuts</dc:creator>
				<category><![CDATA[Nettuts]]></category>

		<guid isPermaLink="false">http://terrytoledo.com/2010/09/creating-a-web-poll-with-php/</guid>
		<description><![CDATA[Polls are nearly ubiquitous on the web today, and there are plenty of services that will provide a drop-in poll for you. But what if you want to write one yourself? This tutorial will take you through the steps to create a simple PHP-based poll, including database setup, vote processing, and displaying the poll. Step [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://feedads.g.doubleclick.net/~a/N3zAXz_uU_QGUvY6qOTUr1Pig3g/0/da"><img src="http://feedads.g.doubleclick.net/~a/N3zAXz_uU_QGUvY6qOTUr1Pig3g/0/di" border="0"></img></a><br />
<a href="http://feedads.g.doubleclick.net/~a/N3zAXz_uU_QGUvY6qOTUr1Pig3g/1/da"><img src="http://feedads.g.doubleclick.net/~a/N3zAXz_uU_QGUvY6qOTUr1Pig3g/1/di" border="0"></img></a></p>
<p>Polls are nearly ubiquitous on the web today, and there are plenty of services that will provide a drop-in poll for you. But what if you want to write one yourself? This tutorial will take you through the steps to create a simple PHP-based poll, including database setup, vote processing, and displaying the poll.</p>
<p><span></span></p>
<hr />
<h2><span>Step 1: </span> Plan &amp; Create the Database</h2>
<p>In order to store poll results, we&#8217;re going to store three pieces of information:</p>
<ul>
<li>A question identifier</li>
<li>An answer identifier</li>
<li>The number of votes a question/answer pair has gotten</li>
</ul>
<p>For this tutorial, we&#8217;ll be using PDO and SQLite. If you&#8217;re working with SQLite3, you can create a new database via the command line tool; if you&#8217;re using an older version, a quick PHP script will do the trick. Here&#8217;s the one used for this tutorial:</p>
<pre>&lt;?php
echo "creating database\n";
try {
    $dbh = new PDO('sqlite:voting.db');
    $dbh-&gt;setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
    $dbh-&gt;exec('
        CREATE TABLE tally (
        QID varchar(32) NOT NULL,
        AID integer NOT NULL,
        votes integer NOT NULL,
        PRIMARY KEY (QID,AID))
    ');
}
catch(PDOException $e) {
    echo "ERROR!!: $e";
    exit;
}
echo "db created successfully.";
?&gt;
</pre>
<div><img src="http://nettuts.s3.amazonaws.com/783_PHPPoll/one.png" alt="Voting Database Structure" height="244" width="600"></div>
<p>This simple script will create a SQLite database in the directory you run it. Unlike mySQL, the database here is a flat file. If you&#8217;re familiar with SQL, the <code>create</code> should make sense to you, although the last line may be new to some people:</p>
<pre>PRIMARY KEY (QID,AID)
</pre>
<p>This creates a <strong>composite key</strong> for the database. Entries in either column do not have to be unique to that column, but the combination of the two must be unique.</p>
<hr />
<h2><span>Step 2: </span> Design Your Poll&#8217;s HTML</h2>
<p>Before you start writing any PHP, you need to decide how to create your poll in terms of markup. We&#8217;re going to try to keep the markup as semantic and simple as possible. Your poll will have two looks:</p>
<ul>
<li>Question waiting to be answered</li>
<li>Current Results of the poll</li>
</ul>
<p>In writing this HTML, some classes will be included to help with the CSS later.</p>
<h3>Poll View</h3>
<p>Because a poll is primarily a list of answers, we&#8217;re going to incorporate an unordered list to contain those answers. For the question itself, we&#8217;re going to use a heading tag.</p>
<pre>&lt;form class="webPoll" method="post" action="test.php"&gt;
    &lt;h4&gt;What question would you like to ask?&lt;/h4&gt;
    &lt;ul&gt;
        &lt;li&gt;Answer Here&lt;/li&gt;
        &lt;li&gt;Another Answer Here&lt;/li&gt;
    &lt;/ul&gt;
&lt;/form&gt;
</pre>
<p>That&#8217;s pretty basic, but doesn&#8217;t include any form elements. Radio buttons are the most appropriate since we&#8217;re only allowing one answer per poll. Also, we&#8217;re going to use the label tag to associate answers with the proper radio button. Now our form HTML looks more like this:</p>
<pre>&lt;form class="webPoll" method="post" action="test.php"&gt;
    &lt;h4&gt;What question would you like to ask?&lt;/h4&gt;
    &lt;ul&gt;
        &lt;li&gt;
            &lt;label class='poll_active'&gt;
            &lt;input type='radio' name='AID' value='0'&gt;
            First Answer Here
            &lt;/label&gt;
        &lt;/li&gt;
    &lt;/ul&gt;
&lt;/form&gt;
</pre>
<p>That&#8217;s a little more complex, but not too bad. Still a bit more to add. We&#8217;re going to include a fieldset tag to open up some styling options, and of course we need a submit button!</p>
<pre>&lt;form class="webPoll" method="post" action="/poll/test.php"&gt;
    &lt;h4&gt;What question would you like to ask?&lt;/h4&gt;
    &lt;fieldset&gt;
    &lt;ul&gt;
        &lt;li&gt;
            &lt;label class='poll_active'&gt;
            &lt;input type='radio' name='AID' value='0'&gt;
            First Answer Here
            &lt;/label&gt;
        &lt;/li&gt;
    &lt;/ul&gt;
    &lt;/fieldset&gt;
    &lt;p class="buttons"&gt;
        &lt;button type="submit" class="vote"&gt;Vote!&lt;/button&gt;
    &lt;/p&gt;
&lt;/form&gt;
</pre>
<p>For each answer, a new LI tag is added and the value of the radio button incremented. That will eventually be done by our PHP. The extra HTML is the fieldset tag, and the paragraph wrapped around the button &#8211; both of which will be used by our CSS.</p>
<h3>Answer View</h3>
<p>The HTML is going to be nearly identical for the answer view. The line-item tags won&#8217;t contain a form element and we&#8217;ll be adding a div which can be used to show the percentage of votes that answer received. Here&#8217;s how that will look:</p>
<pre>&lt;li&gt;
    &lt;div class='result' style='width:20px;'&gt;&amp;nbsp;&lt;/div&gt;
    &lt;label class='poll_results'&gt;
        10%: First Answer Here
    &lt;/label&gt;
&lt;/li&gt;
</pre>
<p>Yes, that&#8217;s an inline style you see there. That style will be generated by our PHP based on the current percentage of each individual answer. Here&#8217;s what we have so far:</p>
<div><img src="http://nettuts.s3.amazonaws.com/783_PHPPoll/two.png" alt="Unstyled Poll" height="182" width="600"></div>
<hr />
<h2><span>Step 3: </span> Style the Form</h2>
<p>The HTML we created in the last step was not very attractive. Let&#8217;s see if we can fix that up a bit. We&#8217;re going to use the wonderful <a href="http://css3pie.com/">CSS3 PIE</a> (progressive Internet Explorer) library so we can obtain a similar look across all browsers. To make this library work properly, there are numerous cases where you must apply a relative position to elements. You can read all the details on the library website.</p>
<h3>Style the Form Tag</h3>
<p>We&#8217;re going to use the form tag as our container. It&#8217;s going to have nice, rounded corners, and a bit of a drop shadow. The styles below also specify a width, and padding.</p>
<pre>form.webPoll {
    background:#ededed;
    behavior:url(PIE.php);
    border:1px solid #bebebe;
    -moz-border-radius:8px;
    -webkit-border-radius:8px;
    border-radius:8px;
    -moz-box-shadow:#666 0 2px 3px;
    -webkit-box-shadow:#666 0 2px 3px;
    box-shadow:#666 0 2px 3px;
    margin:10px 0 10px 8px;
    padding:6px;
    position:relative;
    width:246px;
}
</pre>
<p>The key line here is the behavior attribute. This will be ignored by non-IE browsers and will add the CSS3 functionality to IE6-8.</p>
<div><img src="http://nettuts.s3.amazonaws.com/783_PHPPoll/three.png" alt="Basic styling" height="300" width="600"></div>
<p>Still ugly, but a noticeable improvement.</p>
<h3>Box the Answers</h3>
<p>Next, we&#8217;re going to create a nice box around the answers and use a bit of illusion to make the border look inset by a pixel. This is done by coloring the outer-most border (the fieldset) the same color as the interior, and then using the unordered-list tag as our real border. Here&#8217;s the CSS:</p>
<pre>form.webPoll fieldset {
    background:#FCFAFC;
    behavior:url(PIE.php);
    border:1px solid #FCFAFC;
    -moz-border-radius:10px;
    -webkit-border-radius:10px;
    border-radius:10px;
    margin:0;
    padding:0;
    position:relative;
}
form.webPoll ul {
    behavior:url(PIE.php);
    border:2px #bebebe solid;
    -moz-border-radius:10px;
    -webkit-border-radius:10px;
    border-radius:10px;
    font-family:verdana;
    font-size:10px;
    list-style-type:none;
    margin:0;
    padding:10px 0;
    position:relative;
}
</pre>
<div><img src="http://nettuts.s3.amazonaws.com/783_PHPPoll/four.png" alt="Basic styling" height="256" width="600"></div>
<h3>Style the Answers</h3>
<p>Next we need to add a little CSS to make our options look better.</p>
<pre>form.webPoll li {
    margin:0 16px;
    overflow:auto;
    padding:4px 0 6px;
    position: relative;
}
form.webPoll input {
    position: absolute;
    top: 4px;
    *top: 0;
    left: 0;
    margin: 0;
    padding:0;
}
label.poll_active {
    float:right;
    width:90%;
}
</pre>
<p>You might ask why we&#8217;re using absolute positioning on the inputs and floating the label. The reason is simple: multi-line answers. If an answer to your poll question is long, you want the radio button to look like a bullet on an unordered list &#8211; hanging. This will keep the text from wrapping around it if it&#8217;s multiple lines.</p>
<p>There&#8217;s also a style targeting IE specifically with the * hack to cause the buttons to line up properly in IE6-8.</p>
<p>We also need to style the bar used to show results. We&#8217;ll add that now:</p>
<pre>form.webPoll .result {
    background: #d81b21;
    background: -webkit-gradient(linear, left top, left bottom, from(#ff8080), to(#aa1317));
    background: -moz-linear-gradient(top,  #ff8080,  #aa1317);
    -pie-background: linear-gradient(#ff8080, #aa1317);
    border:1px red solid;
    -moz-border-radius:3px;
    -webkit-border-radius:3px;
    border-radius:3px;
    clear:both;
    color:#EFEFEF;
    padding-left:2px;
    behavior: url('PIE.php');
}
</pre>
<p>There&#8217;s another new attribute here: -pie-background, which allows us to, in conjunction with the PIE library, use gradient backgrounds in IE. There&#8217;s still a few touches to add.</p>
<h3>Question and Button</h3>
<p>A default H4 may not be what you&#8217;re looking for, so let&#8217;s add some styling to that.</p>
<pre>form.webPoll h4 {
    color:#444;
    font-family:Georgia, serif;
    font-size:19px;
    font-weight:400;
    line-height:1.4em;
    margin:6px 4px 12px;
    padding:0;
}
</pre>
<p>And I&#8217;m not a big fan of default buttons, so we&#8217;re going to use a CSS sprite to liven it up a bit.</p>
<pre>.buttons {
    margin:8px 0 1px;
    padding:0;
    text-align:right;
    width:122px;
}
.vote {
    background:url(res/vote.png) repeat scroll 0 0 transparent;
    border:medium none;
    height:40px;
    text-indent:-9999em;
    width:122px;
}
.vote:hover {
    background-position:0 -41px;
    cursor:pointer;
}
</pre>
<p>What about IE6? It doesn&#8217;t support the hover psudo-class! We can either leave those users out in the cold (they&#8217;ll still see the button default state) or we can use another lovely little GPL licensed library, <a href="http://www.xs4all.nl/~peterned/">Whatever:hover</a>.</p>
<div><img src="http://nettuts.s3.amazonaws.com/783_PHPPoll/five.png" alt="Final Poll CSS" height="400" width="600"></div>
<h3>Last Bits</h3>
<p>In order to accommodate some IE6 quirks, certain elements need to have something called &#8220;HasLayout&#8221; triggered. The easiest way to do this is to set a property of zoom for these elements. The property is ignored by non-IE browsers.</p>
<pre>form.webPoll ul,li { /*// Make IE6 happy //*/
    zoom:1;
}
</pre>
<p>You&#8217;ll also notice there are borders between each question. This was done with an additional class on the LI tags specifying a border. The class will be assigned to all but the last item by the PHP script.</p>
<p>The completed CSS file is contained in the download.</p>
<hr />
<h2><span>Step 4: </span> Create a PHP Class — Decide on the Interface</h2>
<p>Now it&#8217;s time to create the PHP to generate polls, show results, and handle votes. I&#8217;d like to keep using the script as simple as possible, so I&#8217;m planning the usage ahead of time. To create a poll in a particular place in a page, you&#8217;ll just use the following PHP:</p>
<pre>$a = new webPoll(array(
        'What subjects would you like to learn more about?',
        'HTML &amp; CSS',
        'JavaScript',
        'JS Frameworks (jQuery, etc)',
        'Ruby/Ruby on Rails',
        'PHP',
        'mySQL'));
</pre>
<p>That&#8217;s it. You&#8217;ll pass an array to the constructor which contains the question followed by the answers. In order to track the questions in the database, we&#8217;ll create an MD5 hash of the question to use as an identifier.</p>
<hr />
<h2><span>Step 5: </span> Decide on the Class Properties</h2>
<p>There&#8217;s certain data that&#8217;s going to be needed by each poll; we&#8217;re going to store some of this in class properties. We&#8217;ll need to store the question and the answers, the basic HTML, the question identifier, and some information on how to draw the results bars. Here&#8217;s the start:</p>
<pre>class webPoll {

    # makes some things more readable later
    const POLL = true;
    const VOTES = false;

    # number of pixels for 1% on display bars
    public $scale = 2;

    # the poll itself
    public $question = '';
    public $answers = array();

    # the HTML
    private $header = '&lt;form class="webPoll" method="post" action="%src%"&gt;
                       &lt;input type="hidden" name="QID" value="%qid%" /&gt;
                       &lt;h4&gt;%question%&lt;/h4&gt;
                       &lt;fieldset&gt;&lt;ul&gt;';
    private $center = '';
    private $footer = "\n&lt;/ul&gt;&lt;/fieldset&gt;%button%\n&lt;/form&gt;\n";
    private $button = '&lt;p class="buttons"&gt;&lt;button type="submit" class="vote"&gt;Vote!&lt;/button&gt;&lt;/p&gt;';

    # question identifier
    private $md5 = '';
</pre>
<p>The initial constants will be used in one of the methods to make it more readable so it&#8217;s easier to know whats going on.</p>
<p>Take note of the hidden input that&#8217;s been added here. This is the question identifier used to store information in the database. All the values in the HTML surrounded by percent signs will be replaced.</p>
<hr />
<h2><span>Step 6: </span> Create the HTML Poll or Answers</h2>
<p>Since it&#8217;s already been decided the poll will be made by creating an object, let&#8217;s examine the __construct method.</p>
<pre>public function __construct($params) {
    $this-&gt;question = array_shift($params);
    $this-&gt;answers = $params;
    $this-&gt;md5 = md5($this-&gt;question);  

    $this-&gt;header = str_replace('%src%', $_SERVER['SCRIPT_NAME'], $this-&gt;header);
    $this-&gt;header = str_replace('%qid%', $this-&gt;md5, $this-&gt;header);
    $this-&gt;header = str_replace('%question%', $this-&gt;question, $this-&gt;header);

    # has the user voted yet?
    isset($_COOKIE[$this-&gt;md5]) ? $this-&gt;poll(self::VOTES) : $this-&gt;poll(self::POLL);
}
</pre>
<p>In the first line, we peel the question off the array stack with array_shift, and store it in a property. We also store the questions, leaving them as an array. We also create the question identifier here, by making an md5 hash of the question itself. </p>
<p>The next three lines perform some replacements on the HTML. The first sets our form action to point at the page the poll is one. The second puts our question identifier in a hidden form field. The third puts our question into the HTML.</p>
<p>In the final line of the constructor we check if the user has voted on this particular poll, and if he has, we show the votes. If he hasn&#8217;t, we show the poll.</p>
<hr />
<h2><span>Step 7: </span> Generate the Poll</h2>
<p>Both generating the poll and generating the results are very similar operations. In order to keep our code <a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY</a> we break the creation into three methods. The main one is &#8220;poll&#8221;.</p>
<div><img src="http://nettuts.s3.amazonaws.com/783_PHPPoll/six.png" alt="DRY: Don't Repeat Yourself" height="160" width="600"></div>
<pre>private function poll($show_poll) {
    $replace = $show_poll ? $this-&gt;button : '';
    $this-&gt;footer = str_replace('%button%', $replace, $this-&gt;footer);

    # static function doesn't have access to instance variable
    if(!$show_poll) {
        $results = webPoll::getData($this-&gt;md5);
        $votes = array_sum($results);
    }

    for( $x=0; $x&lt;count($this-&gt;answers); $x++ ) {
        $this-&gt;center .= $show_poll ? $this-&gt;pollLine($x) : $this-&gt;voteLine($this-&gt;answers[$x],$results[$x],$votes);
    }

    echo $this-&gt;header, $this-&gt;center, $this-&gt;footer;
}
</pre>
<p>Here&#8217;s the breakdown of what&#8217;s going on in this function:</p>
<p><strong>lines 2 &amp; 3:</strong> We only need a vote button if the user hasn&#8217;t voted. Here we determine if we&#8217;re going to use the button HTML or not, and then either insert the HTML, or replace the %button% placeholder with an empty string.</p>
<p><strong>lines 6 &#8211; 8:</strong> If we&#8217;re not showing the poll, we obviously need the results, so here we go fetch them. We also calculate the total votes cast for use later in determining percentages.</p>
<p><strong>lines 11 &#8211; 12:</strong> This generates the LI tags in our HTML. Depending on if we&#8217;re showing the poll or the results, we generate different HTML. This HTML generation is handed off to two functions:</p>
<ul>
<li>pollLine</li>
<li>voteLine</li>
</ul>
<p><strong>line 15:</strong> Simply dumps out the data to the page.</p>
<hr />
<h2><span>Step 8: </span> The pollLine() Method</h2>
<p>This is a very simple method, which takes the current index of the answer as an argument.</p>
<pre>private function pollLine($x) {
    isset($this-&gt;answers[$x+1]) ? $class = 'bordered' : $class = '';
    return "
    &lt;li class='$class'&gt;
            &lt;label class='poll_active'&gt;
            &lt;input type='radio' name='AID' value='$x' /&gt;
                {$this-&gt;answers[$x]}
            &lt;/label&gt;
    &lt;/li&gt;
";
}
</pre>
<p>It checks if there&#8217;s an answer after the current one on its first line, and if there is, applies a class of bordered to that LI tag. The very last answer won&#8217;t get this class, allowing us to achieve the visual effect intended.</p>
<hr />
<h2><span>Step 9: </span> The voteLine() Method</h2>
<p>This method is getting 3 parameters passed into it:</p>
<ul>
<li>$answer : The question answer for this line</li>
<li>$result : The number of votes this option has gotten</li>
<li>$votes : The total number of votes cast in this poll</li>
</ul>
<p>With that information, the LI tags for the voting results can be produced.</p>
<pre>private function voteLine($answer,$result,$votes) {
    $result = isset($result) ? $result : 0;
    $percent = round(($result/$votes)*100);
    $width = $percent * $this-&gt;scale;
    return "
    &lt;li&gt;
            &lt;div class='result' style='width:{$width}px;'&gt;&amp;nbsp;&lt;/div&gt;{$percent}%
            &lt;label class='poll_results'&gt;
                $answer
            &lt;/label&gt;
    &lt;/li&gt;
";
}
</pre>
<p>Since it&#8217;s possible for there to be no votes for an option, it will effectively leave $result unset. If we detect this we&#8217;ll give it a default value of 0 votes.</p>
<p>Next, we determine what percent of the votes the option got and finally use the scale property to determine the width, in pixels, that the results bar should be. Then we finally return the HTML containing all that information.</p>
<hr />
<h2><span>Step 10: </span> Write the getData() Method</h2>
<p>If you look back up a bit, you&#8217;ll see we call the getData() method which is defined as a static method in the class. Why static? Because if we decide to enhance this poll later by making it AJAX based, we&#8217;ll want access to that method without object creation. Here&#8217;s the method:</p>
<pre>static function getData($question_id) {
    try {
        $dbh = new PDO('sqlite:voting.db');
        $dbh-&gt;setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

        $STH = $dbh-&gt;prepare('SELECT AID, votes FROM tally WHERE QID = ?');
        $STH-&gt;execute(array($question_id));
    }
    catch(PDOException $e) {
        # Error getting data, just send empty data set
        return array(0);
    }

    while($row = $STH-&gt;fetch()) {
        $results[$row['AID']] = $row['votes'];
    }

    return $results;
}
</pre>
<p>The question ID is passed into the method and it will return an array containing the answer ID&#8217;s and the number of votes that answer has. If an answer has no votes, it won&#8217;t have an entry in the array, which we&#8217;ve already dealt with in the voteLine() method.</p>
<p>Since database errors in web polls are particularly tragic, we&#8217;re simply going to return an empty array if one occurs. The user will get 0 votes for each result. In a production environment you might want to log this error to a file, or send the admin an email.</p>
<hr />
<h2><span>Step 11: </span> Handling a Vote</h2>
<p>We&#8217;re going to add a second static method to the class, and this one will handle incoming votes. Votes will only be counted if the user hasn&#8217;t voted before (as determined by a cookie) and once the user has voted we&#8217;ll set a cookie indicating this.</p>
<p>In this type of web application, it&#8217;s nearly impossible to stop multiple votes without excluding some legitimate users. Setting a cookie is just a basic precaution.</p>
<p>This is one of the more complex methods in our webPoll class, and we&#8217;re going to look at it in three parts.</p>
<pre>static function vote() {
    if(!isset($_POST['QID']) ||
       !isset($_POST['AID']) ||
       isset($_COOKIE[$_POST['QID']])) {
        return;
    }
</pre>
<p>A call to the vote() method will be at the top of our PHP page, so the first thing we want to do is decide if there&#8217;s a vote to process or not. The above statement is how we determine this. Here&#8217;s what it says:</p>
<ul>
<li>If there&#8217;s no Question Identifier in our POST data (OR!!)</li>
<li>If there&#8217;s no Answer Identifier in our POST data (OR!!)</li>
<li>If a cookie has been set already matching the Question Identifier</li>
</ul>
<p>If any of those are true, we don&#8217;t have to process a vote, and we leave the method.</p>
<pre>$dbh = new PDO('sqlite:voting.db');
$dbh-&gt;setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

try {
    $sth = $dbh-&gt;prepare( "INSERT INTO tally (QID,AID,votes) values (:QID, :AID, 1)" );
    $sth-&gt;execute(array($_POST['QID'],$_POST['AID']));
}
catch(PDOException $e) {
    # 23000 error code means the key already exists, so UPDATE!
    if($e-&gt;getCode() == 23000) {
        try {
            $sth = $dbh-&gt;prepare( "UPDATE tally SET votes = votes+1 WHERE QID=:QID AND AID=:AID");
            $sth-&gt;execute(array($_POST['QID'],$_POST['AID']));
        }
        catch(PDOException $e) {
            $this-&gt;db_error($e-&gt;getMessage());
        }
    }
    else {
        $this-&gt;db_error($e-&gt;getMessage());
    }
}
</pre>
<p>This looks a lot more complicated then it really is. What happens here is we check if a particular answer has gotten a vote before. If it hasn&#8217;t we create a new record for that answer, and give it one vote. If it has, we update the existing record. So how&#8217;s it decide which to do?</p>
<p>PDO exception magic.</p>
<p>Remember at the very beginning we created our multi-column primary key? When we try to insert a record into the table which matches an existing QID/AID pair, an exception is thrown, and in particular the exception code is 23000 (duplicate key).</p>
<p>If the insert throws an exception, we&#8217;re going to check the exception code, and if it matches 23000, we&#8217;ll try to update the record instead. Of course if the insert fails for a different reason, or the update fails as well, we&#8217;re going to just issue a call to a method called db_error() which just echos a generic error message. Like before, a production environment would log this error and/or notify the admin.</p>
<div><img src="http://nettuts.s3.amazonaws.com/783_PHPPoll/seven.png" alt="Using PDO Exceptions" height="185" width="600"></div>
<p>Finally, the end of the method:</p>
<pre>    # entry in $_COOKIE to signify the user has voted, if he has
    if($sth-&gt;rowCount() == 1) {
        setcookie($_POST['QID'], 1, time()+60*60*24*365);
        $_COOKIE[$_POST['QID']] = 1;
    }
}
</pre>
<p>By using rowCount() we can verify that we&#8217;ve either updated or inserted a vote. If a vote has been successfully registered we set a cookie indicating as much, using the question identifier as the cookie name.</p>
<p>In addition to setting the cookie, we populate the super-global $_COOKIE, so when the poll displays, it shows answers rather then presenting the poll again.</p>
<hr />
<h2><span>Step 12: </span> Put It All Into Action</h2>
<p>We&#8217;ve written the PHP, set up the CSS and HTML, now it&#8217;s time to put it all into use. In this example, we&#8217;re just going to drop everything into a page that&#8217;s otherwise blank. At the very top of the page, insert the following:</p>
<pre>&lt;?php
    include('webPoll.class.php');
    webPoll::vote();
?&gt;
</pre>
<p>It&#8217;s important that this be the very top of the page, before any HTML. Why? Because if there&#8217;s a vote to process, a cookie may be written, and you can&#8217;t write cookies after anything else has been sent. The call to the static method vote() returns if there&#8217;s not the proper POST data to process.</p>
<p>Next, we&#8217;ll include all the styles we wrote as a seperate stylesheet. Also, we&#8217;re going to include a particular style just for IE that was mentioned earlier to enable the :hover psudo-class.</p>
<pre>&lt;link rel="stylesheet" href="poll.css" type="text/css" /&gt;
&lt;!--[if IE]&gt;
&lt;style&gt; body { behavior: url("res/hover.htc"); } &lt;/style&gt;
&lt;![endif]--&gt;
</pre>
<p>In the BODY of your HTML page, you&#8217;ll drop in the following PHP to insert the polls:</p>
<pre>$a = new webPoll(array(
        'What subjects would you like to learn more about?',
        'HTML &amp; CSS',
        'JavaScript',
        'JS Frameworks (jQuery, etc)',
        'Ruby/Ruby on Rails',
        'PHP',
        'mySQL'));

$b = new webPoll(array(
        'What is your question?',
        'Don\'t have one',
        'Why?',
        'When?',
        'Where?'));
</pre>
<p>That&#8217;s it! Thanks for reading. Any thoughts, questions, or suggestions?</p>
<div>
<a href="http://feeds.feedburner.com/~ff/nettuts?a=ru5UZ0Za-HE:dHndae25fy8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=ru5UZ0Za-HE:dHndae25fy8:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nettuts?i=ru5UZ0Za-HE:dHndae25fy8:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=ru5UZ0Za-HE:dHndae25fy8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nettuts?i=ru5UZ0Za-HE:dHndae25fy8:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=ru5UZ0Za-HE:dHndae25fy8:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/nettuts?i=ru5UZ0Za-HE:dHndae25fy8:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=ru5UZ0Za-HE:dHndae25fy8:TzevzKxY174"><img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"></img></a>
</div>
<p><img src="http://feeds.feedburner.com/~r/nettuts/~4/ru5UZ0Za-HE" height="1" width="1" /></p>
]]></content:encoded>
			<wfw:commentRss>http://terrytoledo.com/2010/09/creating-a-web-poll-with-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to Create a Web-Based Drawing Application Using Canvas: New Premium Tutorial</title>
		<link>http://terrytoledo.com/2010/09/how-to-create-a-web-based-drawing-application-using-canvas-new-premium-tutorial/</link>
		<comments>http://terrytoledo.com/2010/09/how-to-create-a-web-based-drawing-application-using-canvas-new-premium-tutorial/#comments</comments>
		<pubDate>Fri, 03 Sep 2010 01:51:10 +0000</pubDate>
		<dc:creator>Nettuts</dc:creator>
				<category><![CDATA[Nettuts]]></category>

		<guid isPermaLink="false">http://terrytoledo.com/2010/09/how-to-create-a-web-based-drawing-application-using-canvas-new-premium-tutorial/</guid>
		<description><![CDATA[Combining HTML with the all new &#60;canvas&#62; feature, you can make some pretty awesome web apps! In this Premium exclusive tutorial, we will create a neat interactive drawing application using HTML and JavaScript. Along the way, we’ll also learn the basic concepts of the all new &#60;canvas&#62; feature. Become a Premium member to access this, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://feedads.g.doubleclick.net/~a/UEdgBDBdWzNiMNkUBGJOUvpRGpc/0/da"><img src="http://feedads.g.doubleclick.net/~a/UEdgBDBdWzNiMNkUBGJOUvpRGpc/0/di" border="0"></img></a><br />
<a href="http://feedads.g.doubleclick.net/~a/UEdgBDBdWzNiMNkUBGJOUvpRGpc/1/da"><img src="http://feedads.g.doubleclick.net/~a/UEdgBDBdWzNiMNkUBGJOUvpRGpc/1/di" border="0"></img></a></p>
<p>
Combining HTML with the all new <code>&lt;canvas&gt;</code> feature, you can make some pretty awesome web apps! In this Premium exclusive tutorial, we will create a neat interactive drawing application using HTML and JavaScript. Along the way, we’ll also learn the basic concepts of the all new <code>&lt;canvas&gt;</code> feature. <a href="//net.tutsplus.com/about/join-plus/&quot;">Become a Premium member</a> to access this, as well as many other amazing tutorials and screencasts.
</p>
<p><span></span></p>
<div><img src="http://nettutsplus.s3.amazonaws.com/95_canvas/preview_1.jpg" alt="Preview" /></div>
<div><img src="http://nettutsplus.s3.amazonaws.com/95_canvas/preview_2.jpg" alt="Preview" /></div>
<div><img src="http://nettutsplus.s3.amazonaws.com/95_canvas/preview3.jpg" alt="Preview" /></div>
<div><img src="http://nettutsplus.s3.amazonaws.com/95_canvas/preview4.jpg" alt="Preview" /></div>
<hr />
<h2>Join Net Premium</h2>
<div><img src="//miscfiles.s3.amazonaws.com/banners/nettuts_468x60.jpg&quot;" border="0" alt="&quot;NETTUTS+" width="468" height="60"></div>
<p>  For those unfamiliar, the family of Tuts+ sites runs a premium membership service. For $9 per month, you gain access to exclusive premium tutorials, screencasts, and freebies from <a href="//net.tutsplus.com&quot;">Nettuts+</a>, <a href="http://net.tutsplus.com/&quot;psd.tutsplus.com&quot;">Psdtuts+</a>, <a href="http://net.tutsplus.com/&quot;ae.tutsplus.com&quot;">Aetuts+</a>, <a href="http://net.tutsplus.com/&quot;audio.tutsplus.com&quot;">Audiotuts+</a>, and <a href="http://net.tutsplus.com/&quot;vector.tutsplus.com&quot;">Vectortuts+!</a> For the price of a pizza, you&#8217;ll learn from some of the best minds in the business. <a href="//net.tutsplus.com/about/join-plus/&quot;">Become a Premium member. </a>  </p>
<div>
<a href="http://feeds.feedburner.com/~ff/nettuts?a=finskT7vXfA:EmT3v4YeT6c:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=finskT7vXfA:EmT3v4YeT6c:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nettuts?i=finskT7vXfA:EmT3v4YeT6c:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=finskT7vXfA:EmT3v4YeT6c:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nettuts?i=finskT7vXfA:EmT3v4YeT6c:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=finskT7vXfA:EmT3v4YeT6c:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/nettuts?i=finskT7vXfA:EmT3v4YeT6c:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=finskT7vXfA:EmT3v4YeT6c:TzevzKxY174"><img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"></img></a>
</div>
<p><img src="http://feeds.feedburner.com/~r/nettuts/~4/finskT7vXfA" height="1" width="1" /></p>
]]></content:encoded>
			<wfw:commentRss>http://terrytoledo.com/2010/09/how-to-create-a-web-based-drawing-application-using-canvas-new-premium-tutorial/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quick Tip: Getting Offline Access with HTML5 Application Cache</title>
		<link>http://terrytoledo.com/2010/09/quick-tip-getting-offline-access-with-html5-application-cache/</link>
		<comments>http://terrytoledo.com/2010/09/quick-tip-getting-offline-access-with-html5-application-cache/#comments</comments>
		<pubDate>Fri, 03 Sep 2010 00:24:38 +0000</pubDate>
		<dc:creator>Nettuts</dc:creator>
				<category><![CDATA[Nettuts]]></category>

		<guid isPermaLink="false">http://terrytoledo.com/2010/09/quick-tip-getting-offline-access-with-html5-application-cache/</guid>
		<description><![CDATA[Just when you thought you&#8217;d seen all the cool features of HTML5, I&#8217;m here to bring you yet another one. The internet is no longer about just websites; it&#8217;s about web applications. Often, our users are on portable or mobile devices, and they won&#8217;t always have access to a network. With HTML5&#8217;s Application Cache, you [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://feedads.g.doubleclick.net/~a/ZlINbghp4YUGDU8PvGjy0GqCAQs/0/da"><img src="http://feedads.g.doubleclick.net/~a/ZlINbghp4YUGDU8PvGjy0GqCAQs/0/di" border="0"></img></a><br />
<a href="http://feedads.g.doubleclick.net/~a/ZlINbghp4YUGDU8PvGjy0GqCAQs/1/da"><img src="http://feedads.g.doubleclick.net/~a/ZlINbghp4YUGDU8PvGjy0GqCAQs/1/di" border="0"></img></a></p>
<p>Just when you thought you&#8217;d seen all the cool features of HTML5, I&#8217;m here to bring you yet another one. The internet is no longer about just websites; it&#8217;s about web applications. Often, our users are on portable or mobile devices, and they won&#8217;t always have access to a network. With HTML5&#8217;s Application Cache, you can provide them with all or some of the functionality they would have online, no matter where they go.</p>
<p><span></span></p>
<hr />
<div>
<div>Premium Members: <a href="http://tutsplus.com/plus-content/nettuts/bonus-nettuts/getting-offline-access-with-html5-application-cache-video-download/">Download this Video</a> ( Must be <a href="http://tutsplus.com/amember/member.php">logged in</a>) </div>
<p><span><a href="http://www.youtube.com/user/nettutsplus">Subscribe to our YouTube page to watch all of the video tutorials!</a></span>
</div>
<hr />
<h2><span>Step 1:</span> Make the Cache Manifest</h2>
<p>The trick here is using a cache manifest file. In its most basic form, it&#8217;s incredibly simple:</p>
<pre>
CACHE MANIFEST

# version 0.1

index.html
style.css
script.js
preview.jpg
</pre>
<hr />
<h2><span>Step 2: </span> Serve the Manifest Correctly</h2>
<p>This file needs to be served with a content-type header of <code>text/cache-manifest</code>; it&#8217;s really simple to do this with a .htaccess file:</p>
<pre>
AddType text/cache-manifest manifest
</pre>
<p>This will serve all files with an extention of &#8220;manifest&#8221; with the appropriate content-type header.</p>
<hr />
<h2><span>Step 3: </span> Hook the Manifest In</h2>
<p>To use the cache manifest file, you simply add a property to the <code>html</code> element:</p>
<pre>
&lt;!DOCTYPE html&gt;
&lt;html lang="en" manifest="site.manifest"&gt;
	&lt;meta charset='utf-8'&gt;
</pre>
<p>Now, the next time a user visits your site / app, their browser will cache the required files. It&#8217;s that easy. If they browse to your URL when they&#8217;re offline, they&#8217;ll get the cached content.</p>
<hr />
<h2><span>Caveat: </span> Refreshing the Cache</h2>
<p>It&#8217;s important to note that even when the user is online, the browser will only go to the server to get new content in three cases:</p>
<ol>
<li>The user clears their cache (obviously removing your content).</li>
<li>The manifest file changes.</li>
<li>The cache is updated via JavaScript</li>
</ol>
<p>So, to force all your users to reload their cache, you can change something in the manifest file (not the files linked to, the actual content of the manifest file). Most of the time, you&#8217;ll probably just want to change a comment, and that will be enough.</p>
<p>If you want, build cache updating into your app via the JavaScript API; that&#8217;s beyond the scope of this quick tip, but if you want to learn more, check out <a href="http://www.html5rocks.com/tutorials/appcache/beginner/">this article at html5rocks.com</a>.</p>
<hr />
<h2>Browser Support</h2>
<p>Like a lot of other HTML5 features, the Application Cache is supported by all the modern browsers.</p>
<div>
<img src="http://nettuts.s3.amazonaws.com/785_HTML5Manifest/support.png" /><br />
Chart from <a href="http://www.findmebyip.com/litmus/#html5-web-applications">www.findmebyip.com</a>
</div>
<p>And that&#8217;s HTML5&#8242;s Application Cache; it&#8217;s pretty cool, and I&#8217;m sure it will be used by developers, of almost any site, to provide a gracefully degrading experience that keeps their users happy wherever they are. Thanks for reading!</p>
<div>
<a href="http://feeds.feedburner.com/~ff/nettuts?a=wx3tc9UAw8s:a8Nsn90qdkg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=wx3tc9UAw8s:a8Nsn90qdkg:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nettuts?i=wx3tc9UAw8s:a8Nsn90qdkg:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=wx3tc9UAw8s:a8Nsn90qdkg:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nettuts?i=wx3tc9UAw8s:a8Nsn90qdkg:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=wx3tc9UAw8s:a8Nsn90qdkg:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/nettuts?i=wx3tc9UAw8s:a8Nsn90qdkg:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=wx3tc9UAw8s:a8Nsn90qdkg:TzevzKxY174"><img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"></img></a>
</div>
<p><img src="http://feeds.feedburner.com/~r/nettuts/~4/wx3tc9UAw8s" height="1" width="1" /></p>
]]></content:encoded>
			<wfw:commentRss>http://terrytoledo.com/2010/09/quick-tip-getting-offline-access-with-html5-application-cache/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
