<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Nettuts+</title>
	
	<link>http://net.tutsplus.com</link>
	<description>Web Development &amp; Design Tutorials</description>
	<lastBuildDate>Thu, 18 Mar 2010 04:34:39 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/nettuts" /><feedburner:info uri="nettuts" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><image><link>http://nettuts.com</link><url>http://envato.s3.amazonaws.com/rss_images/nettuts.jpg</url><title>NETTUTS</title></image><feedburner:emailServiceId>nettuts</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>How to Generate PDFs with PHP: New Premium Tutorial</title>
		<link>http://feedproxy.google.com/~r/nettuts/~3/9T1rRnTjZ4c/</link>
		<comments>http://net.tutsplus.com/tutorials/other/how-to-generate-pdfs-with-php-new-plus-tutorial/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 03:20:19 +0000</pubDate>
		<dc:creator>Andrew Burgess</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[pdf]]></category>
		<category><![CDATA[pdfs]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Premium]]></category>

		<guid isPermaLink="false">http://net.tutsplus.com/?p=10340</guid>
		<description><![CDATA[PDFs may well be the best format for distributing documents on the web. In today&#8217;s tutorial and screencast, I&#8217;ll show you how you can generated PDFs with PHP. Help give back to Nettuts+ by becoming a Premium member! 

Example PDF Created with PHP!


   




By subscribing and becoming a Premium member, you&#8217;ll gain access [...]]]></description>
			<content:encoded><![CDATA[<p>PDFs may well be the best format for distributing documents on the web. In today&#8217;s tutorial and screencast, I&#8217;ll show you how you can generated PDFs with PHP. <a href="http://net.tutsplus.com/about/join-plus/">Help give back to Nettuts+ by becoming a Premium member!</a> </p>
<p><span id="more-10340"></span></p>
<h3>Example PDF Created with PHP!</h3>
<div class="tutorial_image">
<a href="http://net.tutsplus.com/about/join-plus/"><br />
   <img src="http://nettutsplus.s3.cdn.plus.org/61_pdfPHP/reciept.png" alt="Sample PDF" /><br />
</a>
</div>
<blockquote>
<p>
By subscribing and becoming a Premium member, you&#8217;ll gain access to the best tutorial, screencasts, and freebies that every Tuts sites has to offer &#8211; all for a measly $9 a month.
</p>
</blockquote>
<h3>Join Net Premium</h3>
<div class="tutorial_image"><img src="http://miscfiles.s3.amazonaws.com/banners/nettuts_468x60.jpg" border=0 alt="NETTUTS+ Screencasts and Bonus Tutorials" 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="http://net.tutsplus.com">Nettuts+</a>, <a href="psd.tutsplus.com">Psdtuts+</a>, <a href="ae.tutsplus.com">Aetuts+</a>, <a href="audio.tutsplus.com">Audiotuts+</a>, and <a href="vector.tutsplus.com">Vectortuts+!</a> For the price of a pizza, you&#8217;ll learn from some of the best minds in the business. <a href="http://net.tutsplus.com/about/join-plus/">Help give back to Nettuts+ by becoming a Premium member!</a></p>

<p><a href="http://feedads.g.doubleclick.net/~a/6KLisq-yAOlepx172wdvD3HSk4k/0/da"><img src="http://feedads.g.doubleclick.net/~a/6KLisq-yAOlepx172wdvD3HSk4k/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/6KLisq-yAOlepx172wdvD3HSk4k/1/da"><img src="http://feedads.g.doubleclick.net/~a/6KLisq-yAOlepx172wdvD3HSk4k/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nettuts?a=9T1rRnTjZ4c:RKdvK55PciQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=9T1rRnTjZ4c:RKdvK55PciQ:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nettuts?i=9T1rRnTjZ4c:RKdvK55PciQ:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=9T1rRnTjZ4c:RKdvK55PciQ:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nettuts?i=9T1rRnTjZ4c:RKdvK55PciQ:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=9T1rRnTjZ4c:RKdvK55PciQ:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/nettuts?i=9T1rRnTjZ4c:RKdvK55PciQ:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=9T1rRnTjZ4c:RKdvK55PciQ:TzevzKxY174"><img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/nettuts/~4/9T1rRnTjZ4c" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/other/how-to-generate-pdfs-with-php-new-plus-tutorial/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://net.tutsplus.com/tutorials/other/how-to-generate-pdfs-with-php-new-plus-tutorial/</feedburner:origLink></item>
		<item>
		<title>Quick Tip: Cross Domain AJAX Request with YQL and jQuery</title>
		<link>http://feedproxy.google.com/~r/nettuts/~3/z8qWZ1V1TqM/</link>
		<comments>http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-cross-domain-ajax-request-with-yql-and-jquery/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 01:27:41 +0000</pubDate>
		<dc:creator>Jeffrey Way</dc:creator>
				<category><![CDATA[JavaScript & AJAX]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[Videos]]></category>
		<category><![CDATA[yql]]></category>

		<guid isPermaLink="false">http://net.tutsplus.com/?p=10225</guid>
		<description><![CDATA[
For security reasons, we cannot make cross-domain AJAX requests with jQuery. For example, I can&#8217;t call the load() method, and pass in &#8216;cnn.com&#8217;. As we&#8217;d be loading in scripts and such, as well as our desired content, this would present a significant security risk. Nonetheless, there may be times when this is specifically what you [...]]]></description>
			<content:encoded><![CDATA[<p>
For security reasons, we cannot make cross-domain AJAX requests with jQuery. For example, I can&#8217;t call the load() method, and pass in &#8216;cnn.com&#8217;. As we&#8217;d be loading in scripts and such, as well as our desired content, this would present a significant security risk. Nonetheless, there may be times when this is specifically what you require. Thanks to <a href="http://developer.yahoo.com/yql/console/">YQL</a>, we can allow for this functionality rather easily!
</p>
<p><span id="more-10225"></span></p>
<div class="tutorial_image">
<object width="600" height="375"><param name="movie" value="http://www.youtube.com/v/vTCgJo4phso&#038;hl=en_US&#038;fs=1&#038;hd=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/vTCgJo4phso&#038;hl=en_US&#038;fs=1&#038;hd=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="600" height="375"></embed></object><br />
<span><a href="http://www.youtube.com/user/nettutsplus">Subscribe to our YouTube page to watch all of the video tutorials!</a></span>
</div>
<h3>The Script</h3>
<pre name="code" class="js">
// Accepts a url and a callback function to run.
function requestCrossDomain( site, callback ) {

	// If no url was passed, exit.
	if ( !site ) {
		alert('No site was passed.');
		return false;
	}

	// Take the provided url, and add it to a YQL query. Make sure you encode it!
	var yql = 'http://query.yahooapis.com/v1/public/yql?q=' + encodeURIComponent('select * from html where url="' + site + '"') + '&#038;format=xml&#038;callback=?';

	// Request that YSQL string, and run a callback function.
	// Pass a defined function to prevent cache-busting.
	$.getJSON( yql, cbFunc );

	function cbFunc(data) {
	// If we have something to work with...
	if ( data.results[0] ) {
		// Strip out all script tags, for security reasons.
		// BE VERY CAREFUL. This helps, but we should do more.
		data = data.results[0].replace(/&lt;script[^>]*>[\s\S]*?&lt;\/script>/gi, '');

		// If the user passed a callback, and it
		// is a function, call it, and send through the data var.
		if ( typeof callback === 'function') {
			callback(data);
		}
	}
	// Else, Maybe we requested a site that doesn't exist, and nothing returned.
	else throw new Error('Nothing returned from getJSON.');
	}
}
</pre>
<h3>Call the Function</h3>
<pre name="code" class="js">
requestCrossDomain('http://www.cnn.com', function(results) {
   $('#container').html(results);
});
</pre>
<h3>Stripping Out the Script Tags </h3>
<p>I had to progress rather quickly in the video, so perhaps the regular expression that strips out the &lt;script> tags require further detail. </p>
<pre name="code" class="js">
.replace(/&lt;script[^>]*>[\s\S]*?&lt;\/script>/gi, '');
</pre>
<p>When we load our desired page, it&#8217;s also going to load scripts! You must be very careful when making cross domain request. It definitely helps to strip out the &lt;script> tags, but you should do more in an actual project. </p>
<p>Let&#8217;s take the regular expression step by step. </p>
<pre name="code" class="js">
&lt;script[^>]*>
</pre>
<p>Find all open script tags; however, they could come in many forms: <em> &lt;script type=&#8221;text/javascript&#8221; src=&#8221;bla.js&#8221;>&lt;/script> </em>, or <em> &lt;script type=&#8221;text/javascript&#8221;>lots of code here&#8230;&lt;/script> </em>. For this reason, we add a character class ( [^>]* ), which mean, &#8220;Find zero or more of anything that IS NOT a closing bracket. This will take care of the attributes and values. </p>
<pre name="code" class="js">
[\s\S]*?
</pre>
<p>Next, we want to strip out all code, as well as any spacing. <strong>\s</strong> refers to a space. <strong>\S</strong> refers to anything that IS NOT a space. Once again, we add a <strong>*</strong> after the character class to designate that we want zero or more occurrences.</p>
<pre name="code" class="js">
&lt;\/script>
</pre>
<p>Finally, find the closing script tags. </p>
<hr />
<h2>Further Reading </h2>
<ul>
<li><a href="http://net.tutsplus.com/tutorials/other/an-api-for-the-web-learning-yql/">An API for the Web: Learning YQL </a></li>
</ul>
<p>This is only meant to provide a glimpse of how we can achieve this functionality. Only so much can be covered in a five minute video. Feel free to discuss in the comments, and you&#8217;re always encouraged to <a href="http://github.com/JeffreyWay/jQuery-Cross-Domain-Requests">fork the source code</a> to improve upon it! </p>

<p><a href="http://feedads.g.doubleclick.net/~a/p1F2J-aEfgyostnHeqDEwx1l6Ew/0/da"><img src="http://feedads.g.doubleclick.net/~a/p1F2J-aEfgyostnHeqDEwx1l6Ew/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/p1F2J-aEfgyostnHeqDEwx1l6Ew/1/da"><img src="http://feedads.g.doubleclick.net/~a/p1F2J-aEfgyostnHeqDEwx1l6Ew/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nettuts?a=z8qWZ1V1TqM:2UF2GmaBhPU:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=z8qWZ1V1TqM:2UF2GmaBhPU:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nettuts?i=z8qWZ1V1TqM:2UF2GmaBhPU:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=z8qWZ1V1TqM:2UF2GmaBhPU:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nettuts?i=z8qWZ1V1TqM:2UF2GmaBhPU:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=z8qWZ1V1TqM:2UF2GmaBhPU:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/nettuts?i=z8qWZ1V1TqM:2UF2GmaBhPU:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=z8qWZ1V1TqM:2UF2GmaBhPU:TzevzKxY174"><img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/nettuts/~4/z8qWZ1V1TqM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-cross-domain-ajax-request-with-yql-and-jquery/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		<feedburner:origLink>http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-cross-domain-ajax-request-with-yql-and-jquery/</feedburner:origLink></item>
		<item>
		<title>How to Create a PHP/MySQL Powered Forum from Scratch</title>
		<link>http://feedproxy.google.com/~r/nettuts/~3/WCIUQyG-TBo/</link>
		<comments>http://net.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/#comments</comments>
		<pubDate>Wed, 17 Mar 2010 18:23:32 +0000</pubDate>
		<dc:creator>Evert Padje</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[forum]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php forum]]></category>

		<guid isPermaLink="false">http://net.tutsplus.com/?p=10188</guid>
		<description><![CDATA[In this tutorial, we&#8217;re going to build a PHP/MySQL powered forum from scratch. This tutorial is perfect for getting used to basic PHP and database usage. Let&#8217;s dive right in!

Step 1: Creating Database Tables

It&#8217;s always a good idea to start with creating a good data model when building an application. Let&#8217;s describe our application in [...]]]></description>
			<content:encoded><![CDATA[<p>In this tutorial, we&#8217;re going to build a PHP/MySQL powered forum from scratch. This tutorial is perfect for getting used to basic PHP and database usage. Let&#8217;s dive right in!</p>
<p><span id="more-10188"></span></p>
<h2><span>Step 1</span>: Creating Database Tables</h2>
<p>
It&#8217;s always a good idea to start with creating a good data model when building an application. Let&#8217;s describe our application in one sentence: We are going to make a forum which has <strong>users</strong> who create <strong>topics</strong> in various <strong>categories</strong>. Other users can <strong>post</strong> replies. As you can see, I highlighted a couple of nouns which represent our table names.
</p>
<h4>Users</h4>
<ul>
<li>Categories</li>
<li>Topics</li>
<li>Posts</li>
</ul>
<p>
	These three objects are related to each other, so we&#8217;ll process that in our table design. Take a look at the scheme below.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/606_forum/tut_files/1.png" border="0" /></div>
<p>
	Looks pretty neat, huh? Every square is a database table. All the columns are listed in it and the lines between them represent the relationships. I&#8217;ll  explain them further, so it&#8217;s okay if it doesn&#8217;t make a lot of sense to you right now.</p>
<p>
	I&#8217;ll discuss each table by explaining the SQL, which I created using the scheme above. For your own scripts you can create a similar scheme and SQL too. Some editors like MySQL Workbench (the one I used) can generate .sql files too, but I would recommend learning SQL because it&#8217;s more fun to do it yourself. A SQL introduction can be found at <a href="http://w3schools.com/sql/sql_intro.asp">W3Schools</a>.
</p>
<h5>Users Table</h5>
<pre name="code" class="sql">
CREATE TABLE users (
user_id 	INT(8) NOT NULL AUTO_INCREMENT,
user_name	VARCHAR(30) NOT NULL,
user_pass  	VARCHAR(255) NOT NULL,
user_email	VARCHAR(255) NOT NULL,
user_date	DATETIME NOT NULL,
user_level	INT(8) NOT NULL,
UNIQUE INDEX user_name_unique (user_name),
PRIMARY KEY (user_id)
) TYPE=INNODB;
	</pre>
<p>
	The CREATE TABLE statement is used to indicate we want to create a new table, of course. The statement is followed by the name of the table and all the columns are listed between the brackets. The names of all the fields are self-explanatory, so we&#8217;ll only discuss the data types below.
	</p>
<h5>user_id</h5>
<blockquote class="pullquote pqRight">
<p>
&#8220;A primary key is used to uniquely identify each row in a table.&#8221;
</p>
</blockquote>
<p>
		The type of this field is INT, which means this field holds an integer. The field cannot be empty (NOT NULL) and increments which each record inserted. At the bottom of the table you can see the user_id field is declared as a primary key. A primary key is used to uniquely identify each row in a table. No two distinct rows in a table can have the same value (or combination of values) in all columns. That might be a bit unclear, so here&#8217;s a little example.
		</p>
<p>
		There is a user called John Doe. If another users registers with the same name, there&#8217;s a problem, because: which user is which? You can&#8217;t tell and the database can&#8217;t tell either. By using a primary key this problem is solved, because both topics are unique.
		</p>
<p>
		All the other tables have got primary keys too and they work the same way.
	</p>
<h5>user_name</h5>
<p>		This is a text field, called a VARCHAR field in MySQL. The number between brackets is the maximum length. A user can choose a username up to 30 characters long. This field cannot be NULL. At the bottom of the table you can see this field is declared UNIQUE, which means the same username cannot be registered twice. The UNIQUE INDEX part tells the database we want to add a unique key. Then we define the name of the unique key, user_name_unique in this case. Between brackets is the field the unique key applies to, which is user_name.
	</p>
<h5>user_pass</h5>
<p>
		This field is equal to the user_name field, except the maximum length. Since the user password, no matter what length, is hashed with sha1(), the password will always be 40 characters long.
	</p>
<h5>user_email</h5>
<p>
		This field is equal to the user_pass field.
		</p>
<h5>user_date</h5>
<p>
		This is a field in which we&#8217;ll store the date the user registered. It&#8217;s type is DATETIME and the field cannot be NULL.</p>
<h5>user_level</h5>
<p>
		This field contains the level of the user, for example: &#8216;0&#8242; for a regular user and &#8216;1&#8242; for an admin. More about this later.</p>
<p><h4>Categories Table</h4>
<pre name="code" class="sql">
CREATE TABLE categories (
cat_id 		 	INT(8) NOT NULL AUTO_INCREMENT,
cat_name	 	VARCHAR(255) NOT NULL,
cat_description 	VARCHAR(255) NOT NULL,
UNIQUE INDEX cat_name_unique (cat_name),
PRIMARY KEY (cat_id)
) TYPE=INNODB;
</pre>
<p>
These data types basically work the same way as the ones in the users table. This table also has a primary key and the name of the category must be an unique one.
</p>
<h4>Topics Table</h4>
<pre name="code" class="sql">
CREATE TABLE topics (
topic_id		INT(8) NOT NULL AUTO_INCREMENT,
topic_subject  		VARCHAR(255) NOT NULL,
topic_date		DATETIME NOT NULL,
topic_cat		INT(8) NOT NULL,
topic_by		INT(8) NOT NULL,
PRIMARY KEY (topic_id)
) TYPE=INNODB;
</pre>
<p>
		This table is almost the same as the other tables, except for the topic_by field. That field refers to the user who created the topic. The topic_cat refers to the category the topic belongs to. We cannot force these relationships by just declaring the field. We have to let the database know this field must contain an existing user_id from the users table, or a valid cat_id from the categories table. We&#8217;ll add some relationships after I&#8217;ve discussed the posts table.
	</p>
<h4>Posts Table</h4>
<pre name="code" class="sql">
CREATE TABLE posts (
post_id 		INT(8) NOT NULL AUTO_INCREMENT,
post_content		TEXT NOT NULL,
post_date 		DATETIME NOT NULL,
post_topic		INT(8) NOT NULL,
post_by		INT(8) NOT NULL,
PRIMARY KEY (post_id)
) TYPE=INNODB;
</pre>
<p>
	This is the same as the rest of the tables; there&#8217;s also a field which refers to a user_id here: the post_by field. The post_topic field refers to the topic the post belongs to.
	</p>
<blockquote class="pullquote pqRight">
<p>
&#8220;A foreign key is a referential constraint between two tables. The foreign key identifies a column or a set of columns in one (referencing) table that refers to a column or set of columns in another (referenced) table.&#8221;
</p>
</blockquote>
<p>
	Now that we&#8217;ve executed these queries, we have a pretty decent data model, but the relations are still missing. Let&#8217;s start with the definition of a relationship. We&#8217;re going to use something called a foreign key. A foreign key is a referential constraint between two tables. The foreign key identifies a column or a set of columns in one (referencing) table that refers to a column or set of columns in another (referenced) table. Some conditions:
	</p>
<ul>
<li>The column in the referencing table the foreign key refers to must be a primary key</li>
<li>The values that are referred to must exist in the referenced table</li>
</ul>
<p>
	By adding foreign keys the information is linked together which is very important for database normalization. Now you know what a foreign key is and why we&#8217;re using them. It&#8217;s time to add them to the tables we&#8217;ve already made by using the ALTER statement, which can be used to change an already existing table.
	</p>
<p>
	We&#8217;ll link the topics to the categories first:
	</p>
<pre name="code" class="sql">
ALTER TABLE topics ADD FOREIGN KEY(topic_cat) REFERENCES categories(cat_id) ON DELETE CASCADE ON UPDATE CASCADE;
</pre>
<p>
	The last part of the query already says what happens. When a category gets deleted from the database, all the topics will be deleted too. If the cat_id of a category changes, every topic will be updated too. That&#8217;s what the ON UPDATE CASCADE part is for. Of course, you can reverse this to protect your data, so that you can&#8217;t delete a category as long as it still has topics linked to it. If you would want to do that, you could replace the &#8216;ON DELETE CASCADE&#8217; part with &#8216;ON DELETE RESTRICT&#8217;. There is also SET NULL and NO ACTION, which speak for themselves.
	</p>
<p>
	Every topic is linked to a category now. Let&#8217;s link the topics to the user who creates one.
	</p>
<pre name="code" class="sql">
ALTER TABLE topics ADD FOREIGN KEY(topic_by) REFERENCES users(user_id) ON DELETE RESTRICT ON UPDATE CASCADE;
</pre>
<p>
	This foreign key is the same as the previous one, but there is one difference: the user can&#8217;t be deleted as long as there are still topics with the user id of the user. We don&#8217;t use CASCADE here because there might be valuable information in our topics. We wouldn&#8217;t want that information to get deleted if someone decides to delete their account. To still give users the opportunity to delete their account, you could build some feature that anonymizes all their topics and then delete their account. Unfortunately, that is beyond the scope of this tutorial.
	</p>
<p><strong><br />
	Link the posts to the topics:<br />
	</strong></p>
<pre name="code" class="sql">
ALTER TABLE posts ADD FOREIGN KEY(post_topic) REFERENCES topics(topic_id) ON DELETE CASCADE ON UPDATE CASCADE;
</pre>
<p>
	<strong>And finally, link each post to the user who made it:</strong>
	</p>
<pre name="code" class="sql">
ALTER TABLE posts ADD FOREIGN KEY(post_by) REFERENCES users(user_id) ON DELETE RESTRICT ON UPDATE CASCADE;
</pre>
<p>
	That&#8217;s the database part! It was quite a lot of work, but the result, a great data model, is definitely worth it.
</p>
<hr />
<h2><span>Step 2</span>: Introduction to the Header/Footer System</h2>
<p>
	Each page of our forum needs a few basic things, like a doctype and some markup. That&#8217;s why we&#8217;ll include a header.php file at the top of each page, and a footer.php at the bottom. The header.php contains a doctype, a link to the stylesheet and some important information about the forum, such as the title tag and metatags.
	</p>
<h5>header.php</h5>
<pre name="code" class="php">
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="nl" lang="nl">
&lt;head>
	&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	&lt;meta name="description" content="A short description." />
	&lt;meta name="keywords" content="put, keywords, here" />
	&lt;title>PHP-MySQL forum&lt;/title>
	&lt;link rel="stylesheet" href="style.css" type="text/css">
&lt;/head>
&lt;body>
&lt;h1>My forum&lt;/h1>
	&lt;div id="wrapper">
	&lt;div id="menu">
		&lt;a class="item" href="/forum/index.php">Home&lt;/a> -
		&lt;a class="item" href="/forum/create_topic.php">Create a topic&lt;/a> -
		&lt;a class="item" href="/forum/create_cat.php">Create a category&lt;/a>

		&lt;div id="userbar">
		&lt;div id="userbar">Hello Example. Not you? Log out.&lt;/div>
	&lt;/div>
		&lt;div id="content">
	</pre>
<p>
		The wrapper div will be used to make it easier to style the entire page. The menu div obviously contains a menu with links to pages we still have to create, but it helps to see where we&#8217;re going a little bit. The userbar div is going to be used for a small top bar which contains some information like the username and a link to the logout page. The content page holds the actual content of the page, obviously.
	</p>
<p>
		The attentive reader might have already noticed we&#8217;re missing some things. There is no &lt;/body> or &lt;/html> tag. They&#8217;re in the footer.php page, as you can see below.
	</p>
<pre name="code" class="php">
&lt;/div>&lt;!-- content -->
&lt;/div>&lt;!-- wrapper -->
&lt;div id="footer">Created for Nettuts+&lt;/div>
&lt;/body>
&lt;/html>
	</pre>
<p>
		When we include a header and a footer on each page the rest of the page get embedded between the header and the footer. This method has got some advantages. First and foremost, everything will be styled correctly. A short example:
	</p>
<pre name="code" class="php">
&lt;?php
$error = false;
if($error = false)
{
 	//the beautifully styled content, everything looks good
 	echo '&lt;div id="content">some text&lt;/div>';
}
else
{
 	//bad looking, unstyled error <img src='http://net.tutsplus.com/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' />
}
?>
	</pre>
<p>
		As you can see, a page without errors will result in a nice page with the content. But if there&#8217;s an error, everything looks really ugly; so that&#8217;s why it&#8217;s better to make sure not only real content is styled correctly, but also the errors we might get.
	</p>
<p>
		Another advantage is the possibility of making quick changes. You can see for yourself by editing the text in footer.php when you&#8217;ve finished this tutorial; you&#8217;ll notice that the footer changes on every page immediately. Finally, we add a stylesheet which provides us with some basic markup &#8211; nothing too fancy.
	</p>
<pre name="code" class="css">
body {
	background-color: #4E4E4E;
	text-align: center;			/* make sure IE centers the page too */
}

#wrapper {
	width: 900px;
	margin: 0 auto; 			/* center the page */
}

#content {
	background-color: #fff;
	border: 1px solid #000;
	float: left;
	font-family: Arial;
	padding: 20px 30px;
	text-align: left;
	width: 100%;				/* fill up the entire div */
}

#menu {
	float: left;
	border: 1px solid #000;
	border-bottom: none;		/* avoid a double border */
	clear: both;				/* clear:both makes sure the content div doesn't float next to this one but stays under it */
	width:100%;
	height:20px;
	padding: 0 30px;
	background-color: #FFF;
	text-align: left;
	font-size: 85%;
}

#menu a:hover {
	background-color: #009FC1;
}

#userbar {
	background-color: #fff;
	float: right;
	width: 250px;
}

#footer {
	clear: both;
}

/* begin table styles */
table {
	border-collapse: collapse;
	width: 100%;
}

table a {
	color: #000;
}

table a:hover {
	color:#373737;
	text-decoration: none;
}

th {
	background-color: #B40E1F;
	color: #F0F0F0;
}

td {
	padding: 5px;
}

/* Begin font styles */
h1, #footer {
	font-family: Arial;
	color: #F1F3F1;
}

h3 {margin: 0; padding: 0;}

/* Menu styles */
.item {
	background-color: #00728B;
	border: 1px solid #032472;
	color: #FFF;
	font-family: Arial;
	padding: 3px;
	text-decoration: none;
}

.leftpart {
	width: 70%;
}

.rightpart {
	width: 30%;
}

.small {
	font-size: 75%;
	color: #373737;
}
#footer {
	font-size: 65%;
	padding: 3px 0 0 0;
}

.topic-post {
	height: 100px;
	overflow: auto;
}

.post-content {
	padding: 30px;
}

textarea {
	width: 500px;
	height: 200px;
}
	</pre>
<hr />
<h2><span>Step 3</span>: Getting Ready for Action</h2>
<p>
		Before we can read anything from our database, we need a connection. That&#8217;s what connect.php is for. We&#8217;ll include it in every file we are going to create.
	</p>
<pre name="code" class="php">
&lt;?php
//connect.php
$server	= 'localhost';
$username	= 'usernamehere';
$password	= 'passwordhere';
$database	= 'databasenamehere';

if(!mysql_connect($server, $username,  $password))
{
 	exit('Error: could not establish database connection');
}
if(!mysql_select_db($database)
{
 	exit('Error: could not select the database');
}
?>
	</pre>
<p>
		Simply replace the default values of the variables at the top of the page with your own date, save the file and you&#8217;re good to go!
	</p>
<hr />
<h2><span>Step 4</span>: Displaying the Forum Overview</h2>
<p>
		Since we&#8217;re just started with some basic techniques, we&#8217;re going to make a simplified version of the forum overview for now.
	</p>
<pre name="code" class="php">
&lt;?php
//create_cat.php
include 'connect.php';
include 'header.php';

echo '&lt;tr>';
	echo '&lt;td class="leftpart">';
		echo '&lt;h3>&lt;a href="category.php?id=">Category name&lt;/a>&lt;/h3> Category description goes here';
	echo '&lt;/td>';
	echo '&lt;td class="rightpart">';
			echo '&lt;a href="topic.php?id=">Topic subject&lt;/a> at 10-10';
	echo '&lt;/td>';
echo '&lt;/tr>';
include 'footer.php';
?>
	</pre>
<p>
		There you have it: a nice and clean overview. We&#8217;ll be updating this page throughout the tutorial so that it becomes more like the end result, step by step!
	</p>
<hr />
<h2><span>Step 5</span>: Signing up a User</h2>
<p>
		Let&#8217;s start by making a simple HTML form so that a new user can register.
	</p>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/606_forum/tut_files/2.png" border="0" /></div>
<p>
		A PHP page is needed to process the form. We&#8217;re going to use a $_SERVER variable. The $_SERVER variable is an array with values that are automatically set with each request. One of the values of the $_SERVER array is &#8216;REQUEST_METHOD&#8217;. When a page is requested with GET, this variable will hold the value &#8216;GET&#8217;. When a page is requested via POST, it will hold the value &#8216;POST&#8217;. We can use this value to check if a form has been posted. See the signup.php page below.
	</p>
<pre name="code" class="php">
&lt;?php
//signup.php
include 'connect.php';
include 'header.php';

echo '&lt;h3>Sign up&lt;/h3>';

if($_SERVER['REQUEST_METHOD'] != 'POST')
{
    /*the form hasn't been posted yet, display it
	  note that the action="" will cause the form to post to the same page it is on */
    echo '&lt;form method="post" action="">
 	 	Username: &lt;input type="text" name="user_name" />
 		Password: &lt;input type="password" name="user_pass">
		Password again: &lt;input type="password" name="user_pass_check">
		E-mail: &lt;input type="email" name="user_email">
 		&lt;input type="submit" value="Add category" />
 	 &lt;/form>';
}
else
{
    /* so, the form has been posted, we'll process the data in three steps:
		1.	Check the data
		2.	Let the user refill the wrong fields (if necessary)
		3.	Save the data
	*/
	$errors = array(); /* declare the array for later use */

	if(isset($_POST['user_name']))
	{
		//the user name exists
		if(!ctype_alnum($_POST['user_name']))
		{
			$errors[] = 'The username can only contain letters and digits.';
		}
		if(strlen($_POST['user_name']) > 30)
		{
			$errors[] = 'The username cannot be longer than 30 characters.';
		}
	}
	else
	{
		$errors[] = 'The username field must not be empty.';
	}

	if(isset($_POST['user_pass']))
	{
		if($_POST['user_pass'] != $_POST['user_pass_check'])
		{
			$errors[] = 'The two passwords did not match.';
		}
	}
	else
	{
		$errors[] = 'The password field cannot be empty.';
	}

	if(!empty($errors)) /*check for an empty array, if there are errors, they're in this array (note the ! operator)*/
	{
		echo 'Uh-oh.. a couple of fields are not filled in correctly..';
		echo '&lt;ul>';
		foreach($errors as $key => $value) /* walk through the array so all the errors get displayed */
		{
			echo '&lt;li>' . $value . '&lt;/li>'; /* this generates a nice error list */
		}
		echo '&lt;/ul>';
	}
	else
	{
		//the form has been posted without, so save it
		//notice the use of mysql_real_escape_string, keep everything safe!
		//also notice the sha1 function which hashes the password
		$sql = "INSERT INTO
					users(user_name, user_pass, user_email ,user_date, user_level)
				VALUES('" . mysql_real_escape_string($_POST['user_name']) . "',
					   '" . sha1($_POST['user_pass']) . "',
					   '" . mysql_real_escape_string($_POST['user_email']) . "',
						NOW(),
						0)";

		$result = mysql_query($sql);
		if(!$result)
		{
			//something went wrong, display the error
			echo 'Something went wrong while registering. Please try again later.';
			//echo mysql_error(); //debugging purposes, uncomment when needed
		}
		else
		{
			echo 'Successfully registered. You can now &lt;a href="signin.php">sign in&lt;/a> and start posting! <img src='http://net.tutsplus.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> ';
		}
	}
}

include 'footer.php';
?>
	</pre>
<p>
		A lot of explanation is in the comments I made in the file, so be sure to check them out. The processing of the data takes place in three parts:
	</p>
<ul>
<li>Validating the data</li>
<li>If the data is not valid, show the form again</li>
<li>If the data is valid, save the record in the database</li>
</ul>
<p>
		The PHP part is quite self-explanatory. The SQL-query however probably needs a little more explanation.
	</p>
<pre name="code" class="sql">
INSERT INTO
       users(user_name, user_pass, user_email ,user_date, user_level)
VALUES('" . mysql_real_escape_string($_POST['user_name']) . "',
       '" . sha1($_POST['user_pass']) . "',
       '" . mysql_real_escape_string($_POST['user_email']) . "',
       NOW(),
       0);
	</pre>
<p>
		On line 1 we have the INSERT INTO statement which speaks for itself. The table name is specified on the second line. The words between the brackets represent the columns in which we want to insert the data. The VALUES statement tells the database we&#8217;re done declaring column names and it&#8217;s time to specify the values. There is something new here: mysql_real_escape_string. The function escapes special characters in an unescaped string , so that it is safe to place it in a query. This function MUST always be used, with very few exceptions. There are too many scripts that don&#8217;t use it and can be hacked real easy. Don&#8217;t take the risk, use mysql_real_escape_string().
	</p>
<blockquote class="pullquote pqRight">
<p>
&#8220;Never insert a plain password as-is. You MUST always encrypt it.&#8221;
</p>
</blockquote>
<p>
		Also, you can see that the function sha1() is used to encrypt the user&#8217;s password. This is also a very important thing to remember. Never insert a plain password as-is. You MUST always encrypt it. Imagine a hacker who somehow manages to get access to your database. If he sees all the plain-text passwords he could log into any (admin) account he wants. If the password columns contain sha1 strings he has to crack them first which is almost impossible.
	</p>
<p>
		Note: it&#8217;s also possible to use md5(), I always use sha1() because benchmarks have proved it&#8217;s a tiny bit faster, not much though. You can replace sha1 with md5 if you like.
	</p>
<p>
		If the signup process was successful, you should see something like this:
	</p>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/606_forum/tut_files/3.png" border="0" /></div>
<p>
		Try refreshing your phpMyAdmin screen, a new record should be visible in the users table.
	</p>
<hr />
<h2><span>Step 6</span>: Adding Authentication and User Levels</h2>
<p>
		An important aspect of a forum is the difference between regular users and admins/moderators. Since this is a small forum and adding features like adding new moderators and stuff would take way too much time, we&#8217;ll focus on the login process and create some admin features like creating new categories and closing a thread.
	</p>
<p>
		Now that you&#8217;ve completed the previous step, we&#8217;re going to make your freshly created account an admin account. In phpMyAdmin, click on the users table, and then &#8216;Browse&#8217;. Your account will probably pop up right away. Click the edit icon and change the value of the user_level field from 0 to 1. That&#8217;s it for now. You won&#8217;t notice any difference in our application immediately, but when we&#8217;ve added the admin features a normal account and your account will have different capabilities.
	</p>
<p>
		The sign-in process works the following way:
	</p>
<ul>
<li>A visitor enters user data and submits the form</li>
<li>If the username and password are correct, we can start a session</li>
<li>If the username and password are incorrect, we show the form again with a message</li>
</ul>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/606_forum/tut_files/6.png" border="0" /></div>
<p>
		The signin.php file is below. Don&#8217;t think I&#8217;m not explaining what I&#8217;m doing, but check out the comments in the file. It&#8217;s much easier to understand that way.
	</p>
<pre name="code" class="php">
&lt;?php
//signin.php
include 'connect.php';
include 'header.php';

echo '&lt;h3>Sign in&lt;/h3>';

//first, check if the user is already signed in. If that is the case, there is no need to display this page
if(isset($_SESSION['signed_in']) &#038;&#038; $_SESSION['signed_in'] == true)
{
	echo 'You are already signed in, you can &lt;a href="signout.php">sign out&lt;/a> if you want.';
}
else
{
	if($_SERVER['REQUEST_METHOD'] != 'POST')
	{
		/*the form hasn't been posted yet, display it
		  note that the action="" will cause the form to post to the same page it is on */
		echo '&lt;form method="post" action="">
			Username: &lt;input type="text" name="user_name" />
			Password: &lt;input type="password" name="user_pass">
			&lt;input type="submit" value="Sign in" />
		 &lt;/form>';
	}
	else
	{
		/* so, the form has been posted, we'll process the data in three steps:
			1.	Check the data
			2.	Let the user refill the wrong fields (if necessary)
			3.	Varify if the data is correct and return the correct response
		*/
		$errors = array(); /* declare the array for later use */

		if(!isset($_POST['user_name']))
		{
			$errors[] = 'The username field must not be empty.';
		}

		if(!isset($_POST['user_pass']))
		{
			$errors[] = 'The password field must not be empty.';
		}

		if(!empty($errors)) /*check for an empty array, if there are errors, they're in this array (note the ! operator)*/
		{
			echo 'Uh-oh.. a couple of fields are not filled in correctly..';
			echo '&lt;ul>';
			foreach($errors as $key => $value) /* walk through the array so all the errors get displayed */
			{
				echo '&lt;li>' . $value . '&lt;/li>'; /* this generates a nice error list */
			}
			echo '&lt;/ul>';
		}
		else
		{
			//the form has been posted without errors, so save it
			//notice the use of mysql_real_escape_string, keep everything safe!
			//also notice the sha1 function which hashes the password
			$sql = "SELECT
						user_id,
						user_name,
						user_level
					FROM
						users
					WHERE
						user_name = '" . mysql_real_escape_string($_POST['user_name']) . "'
					AND
						user_pass = '" . sha1($_POST['user_pass']) . "'";

			$result = mysql_query($sql);
			if(!$result)
			{
				//something went wrong, display the error
				echo 'Something went wrong while signing in. Please try again later.';
				//echo mysql_error(); //debugging purposes, uncomment when needed
			}
			else
			{
				//the query was successfully executed, there are 2 possibilities
				//1. the query returned data, the user can be signed in
				//2. the query returned an empty result set, the credentials were wrong
				if(mysql_num_rows($result) == 0)
				{
					echo 'You have supplied a wrong user/password combination. Please try again.';
				}
				else
				{
					//set the $_SESSION['signed_in'] variable to TRUE
					$_SESSION['signed_in'] = true;

					//we also put the user_id and user_name values in the $_SESSION, so we can use it at various pages
					while($row = mysql_fetch_assoc($result))
					{
						$_SESSION['user_id'] 	= $row['user_id'];
						$_SESSION['user_name'] 	= $row['user_name'];
						$_SESSION['user_level'] = $row['user_level'];
					}

					echo 'Welcome, ' . $_SESSION['user_name'] . '. &lt;a href="index.php">Proceed to the forum overview&lt;/a>.';
				}
			}
		}
	}
}

include 'footer.php';
?>
	</pre>
<p>
		This is the query that&#8217;s in the signin.php file:
	</p>
<pre name="code" class="sql">
SELECT
	user_id,
	user_name,
	user_level
FROM
	users
WHERE
	user_name = '" . mysql_real_escape_string($_POST['user_name']) . "'
AND
	user_pass = '" . sha1($_POST['user_pass'])
	</pre>
<p>
		It&#8217;s obvious we need a check to tell if the supplied credentials belong to an existing user. A lot of scripts retrieve the password from the database and compare it using PHP. If we do this directly via SQL the password will be stored in the database once during registration and never leave it again. This is safer, because all the real action happens in the database layer and not in our application.
	</p>
<p>
		If the user is signed in successfully, we&#8217;re doing a few things:
	</p>
<pre name="code" class="php">
&lt;?php
//set the $_SESSION['signed_in'] variable to TRUE
$_SESSION['signed_in'] = true;
//we also put the user_id and user_name values in the $_SESSION, so we can use it at various pages
while($row = mysql_fetch_assoc($result))
{
 	$_SESSION['user_id'] = $row['user_id'];
 	$_SESSION['user_name'] = $row['user_name'];
}
?>
	</pre>
<p>
		First, we set the &#8217;signed_in&#8217; $_SESSION var to true, so we can use it on other pages to make sure the user is signed in. We also put the username and user id in the $_SESSION variable for usage on a different page. Finally, we display a link to the forum overview so the user can get started right away.
	</p>
<p>
		Of course signing in requires another function, signing out! The sign-out process is actually a lot easier than the sign-in process. Because all the information about the user is stored in $_SESSION variables, all we have to do is unset them and display a message.
	</p>
<p>
		Now that we&#8217;ve set the $_SESSION variables, we can determine if someone is signed in. Let&#8217;s make a last simple change to header.php:
	</p>
<p>
		Replace:
	</p>
<pre name="code" class="html">
&lt;div id="userbar">Hello Example. Not you? Log out.&lt;/div>
	</pre>
<p>
		With:
	</p>
<pre name="code" class="php">
&lt;?php
&lt;div id="userbar">
 	if($_SESSION['signed_in'])
 	{
 	 	echo 'Hello' . $_SESSION['user_name'] . '. Not you? &lt;a href="signout.php">Sign out&lt;/a>';
 	}
 	else
 	{
 		echo '&lt;a href="signin.php">Sign in&lt;/a> or &lt;a href="sign up">create an account&lt;/a>.';
 	}
&lt;/div>
	</pre>
<p>
		If a user is signed in, he will see his or her name displayed on the front page with a link to the signout page. Our authentication is done! By now our forum should look like this:
	</p>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/606_forum/tut_files/4.png" border="0" /></div>
<hr />
<h2><span>Step 7</span>: Creating a Category</h2>
<p>
		We want to create categories so let&#8217;s start with making a form.
	</p>
<pre name="code" class="html">
&lt;form method="post" action="">
 	Category name: &lt;input type="text" name="cat_name" />
 	Category description: &lt;textarea name="cat_description" />&lt;/textarea>
	&lt;input type="submit" value="Add category" />
 &lt;/form>
	</pre>
<p>
		This step looks a lot like Step 4 (Signing up a user&#8217;), so I&#8217;m not going to do an in-depth explanation here. If you followed all the steps you should be able to understand this somewhat quickly.
	</p>
<pre name="code" class="php">
&lt;?php
//create_cat.php
include 'connect.php';

if($_SERVER['REQUEST_METHOD'] != 'POST')
{
    //the form hasn't been posted yet, display it
    echo '&lt;form method='post' action=''>
 	 	Category name: &lt;input type='text' name='cat_name' />
 		Category description: &lt;textarea name='cat_description' />&lt;/textarea>
 		&lt;input type='submit' value='Add category' />
 	 &lt;/form>';
}
else
{
    //the form has been posted, so save it
    $sql = ìINSERT INTO categories(cat_name, cat_description)
 	   VALUES('' . mysql_real_escape_string($_POST['cat_name']) . ì',
 		     '' . mysql_real_escape_string($_POST['cat_description']) . ì')';
    $result = mysql_query($sql);
    if(!$result)
    {
        //something went wrong, display the error
        echo 'Error' . mysql_error();
    }
    else
    {
        echo 'New category successfully added.';
    }
}
?>
	</pre>
<p>
		As you can see, we&#8217;ve started the script with the $_SERVER check, after checking if the user has admin rights, which is required for creating a category. The form gets displayed if it hasn&#8217;t been submitted already. If it has, the values are saved. Once again, a SQL query is prepared and then executed.
	</p>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/606_forum/tut_files/5.png" border="0" /></div>
<hr />
<h2><span>Step 8</span>: Adding Categories to index.php</h2>
<p>
		We&#8217;ve created some categories, so now we&#8217;re able to display them on the front page. Let&#8217;s add the following query to the content area of index.php.
	</p>
<pre name="code" class="sql">
SELECT
 	categories.cat_id,
	categories.cat_name,
 	categories.cat_description,
FROM
 	categories
	</pre>
<p>
		This query selects all categories and their names and descriptions from the categories table. We only need a bit of PHP to display the results. If we add that part just like we did in the previous steps, the code will look like this.
	</p>
<pre name="code" class="php">
&lt;?php
//create_cat.php
include 'connect.php';
include 'header.php';

$sql = "SELECT
			cat_id,
			cat_name,
			cat_description,
		FROM
			categories";

$result = mysql_query($sql);

if(!$result)
{
	echo 'The categories could not be displayed, please try again later.';
}
else
{
	if(mysql_num_rows($result) == 0)
	{
		echo 'No categories defined yet.';
	}
	else
	{
		//prepare the table
		echo '&lt;table border="1">
			  &lt;tr>
				&lt;th>Category&lt;/th>
				&lt;th>Last topic&lt;/th>
			  &lt;/tr>';	

		while($row = mysql_fetch_assoc($result))
		{
			echo '&lt;tr>';
				echo '&lt;td class="leftpart">';
					echo '&lt;h3>&lt;a href="category.php?id">' . $row['cat_name'] . '&lt;/a>&lt;/h3>' . $row['cat_description'];
				echo '&lt;/td>';
				echo '&lt;td class="rightpart">';
							echo '&lt;a href="topic.php?id=">Topic subject&lt;/a> at 10-10';
				echo '&lt;/td>';
			echo '&lt;/tr>';
		}
	}
}

include 'footer.php';
?>
	</pre>
<p>
		Notice how we&#8217;re using the cat_id to create links to category.php. All the links to this page will look like this: category.php?cat_id=x, where x can be any numeric value. This may be new to you. We can check the url with PHP for $_GET values. For example, we have this link:
	</p>
<pre name="code" class="html">
category.php?cat_id=23
	</pre>
<p>
		The statement echo $_GET[ëcat_id'];&#8217; will display &#8216;23&#8242;. In the next few steps we&#8217;ll use this value to retrieve the topics when viewing a single category, but topics can&#8217;t be viewed if we haven&#8217;t created them yet. So let&#8217;s create some topics!
	</p>
<hr />
<h2><span>Step 9</span>: Creating a Topic</h2>
<p>
		In this step, we&#8217;re combining the techniques we learned in the previous steps. We&#8217;re checking if a user is signed in, we&#8217;ll use an input query to create the topic and create some basic HTML forms.
	</p>
<p>
		The structure of create_topic.php can hardly be explained in a list or something, so I rewrote it in pseudo-code.
	</p>
<pre name="code" class="php">
&lt;?php
if(user is signed in)
{
	//the user is not signed in
}
else
{
	//the user is signed in
	if(form has not been posted)
	{
		//show form
	}
	else
	{
		//process form
	}
}
?>
	</pre>
<p>
		Here&#8217;s the real code of this part of our forum, check the explanations below the code to see what it&#8217;s doing.
	</p>
<pre name="code" class="php">
&lt;?php
//create_cat.php
include 'connect.php';
include 'header.php';

echo '&lt;h2>Create a topic&lt;/h2>';
if($_SESSION['signed_in'] == false)
{
	//the user is not signed in
	echo 'Sorry, you have to be &lt;a href="/forum/signin.php">signed in&lt;/a> to create a topic.';
}
else
{
	//the user is signed in
	if($_SERVER['REQUEST_METHOD'] != 'POST')
	{
		//the form hasn't been posted yet, display it
		//retrieve the categories from the database for use in the dropdown
		$sql = "SELECT
					cat_id,
					cat_name,
					cat_description
				FROM
					categories";

		$result = mysql_query($sql);

		if(!$result)
		{
			//the query failed, uh-oh <img src='http://net.tutsplus.com/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' />
			echo 'Error while selecting from database. Please try again later.';
		}
		else
		{
			if(mysql_num_rows($result) == 0)
			{
				//there are no categories, so a topic can't be posted
				if($_SESSION['user_level'] == 1)
				{
					echo 'You have not created categories yet.';
				}
				else
				{
					echo 'Before you can post a topic, you must wait for an admin to create some categories.';
				}
			}
			else
			{

				echo '&lt;form method="post" action="">
					Subject: &lt;input type="text" name="topic_subject" />
					Category:'; 

				echo '&lt;select name="topic_cat">';
					while($row = mysql_fetch_assoc($result))
					{
						echo '&lt;option value="' . $row['cat_id'] . '">' . $row['cat_name'] . '&lt;/option>';
					}
				echo '&lt;/select>';	

				echo 'Message: &lt;textarea name="post_content" />&lt;/textarea>
					&lt;input type="submit" value="Create topic" />
				 &lt;/form>';
			}
		}
	}
	else
	{
		//start the transaction
		$query  = "BEGIN WORK;";
		$result = mysql_query($query);

		if(!$result)
		{
			//Damn! the query failed, quit
			echo 'An error occured while creating your topic. Please try again later.';
		}
		else
		{

			//the form has been posted, so save it
			//insert the topic into the topics table first, then we'll save the post into the posts table
			$sql = "INSERT INTO
						topics(topic_subject,
							   topic_date,
							   topic_cat,
							   topic_by)
				   VALUES('" . mysql_real_escape_string($_POST['topic_subject']) . "',
							   NOW(),
							   " . mysql_real_escape_string($_POST['topic_cat']) . ",
							   " . $_SESSION['user_id'] . "
							   )";

			$result = mysql_query($sql);
			if(!$result)
			{
				//something went wrong, display the error
				echo 'An error occured while inserting your data. Please try again later.' . mysql_error();
				$sql = "ROLLBACK;";
				$result = mysql_query($sql);
			}
			else
			{
				//the first query worked, now start the second, posts query
				//retrieve the id of the freshly created topic for usage in the posts query
				$topicid = mysql_insert_id();

				$sql = "INSERT INTO
							posts(post_content,
								  post_date,
								  post_topic,
								  post_by)
						VALUES
							('" . mysql_real_escape_string($_POST['post_content']) . "',
								  NOW(),
								  " . $topicid . ",
								  " . $_SESSION['user_id'] . "
							)";
				$result = mysql_query($sql);

				if(!$result)
				{
					//something went wrong, display the error
					echo 'An error occured while inserting your post. Please try again later.' . mysql_error();
					$sql = "ROLLBACK;";
					$result = mysql_query($sql);
				}
				else
				{
					$sql = "COMMIT;";
					$result = mysql_query($sql);

					//after a lot of work, the query succeeded!
					echo 'You have successfully created &lt;a href="topic.php?id='. $topicid . '">your new topic&lt;/a>.';
				}
			}
		}
	}
}

include 'footer.php';
?>
	</pre>
<p>
		I&#8217;ll discuss this page in two parts, showing the form and processing the form.
	</p>
<p>
	<strong>Showing the form</strong><br />
	We&#8217;re starting with a simple HTML form. There is actually something special here, because we use a dropdown. This dropdown is filled with data from the database, using this query:
	</p>
<pre name="code" class="sql">
SELECT
 	cat_id,
 	cat_name,
 	cat_description
FROM
 	categories
	</pre>
<p>
		That&#8217;s the only potentially confusing part here; it&#8217;s quite a piece of code, as you can see when looking at the create_topic.php file at the bottom of this step.
	</p>
<p>	<strong>Processing the form</strong></p>
<p>
		The process of saving the topic consists of two parts: saving the topic in the topics table and saving the first post in the posts table. This requires something quite advanced that goes a bit beyond the scope of this tutorial. It&#8217;s called a transaction, which basically means that we start by executing the start command and then rollback when there are database errors and commit when everything went well. More about <a href="http://www.tutorialspoint.com/mysql/mysql-transactions.htm">transactions</a>.
	</p>
<pre name="code" class="php">
&lt;?php
//start the transaction
$query  = "BEGIN WORK;";
$result = mysql_query($query);
//stop the transaction
$sql = "ROLLBACK;";
$result = mysql_query($sql);
//commit the transaction
$sql = "COMMIT;";
$result = mysql_query($sql);
?>
	</pre>
<p>
		The first query being used to save the data is the topic creation query, which looks like this:
	</p>
<pre name="code" class="sql">
INSERT INTO
	topics(topic_subject,
               topic_date,
               topic_cat,
               topic_by)
VALUES('" . mysql_real_escape_string($_POST['topic_subject']) . "',
       NOW(),
       " . mysql_real_escape_string($_POST['topic_cat']) . ",
       " . $_SESSION['user_id'] . ")
	</pre>
<p>
		At first the fields are defined, then the values to be inserted. We&#8217;ve seen the first one before, it&#8217;s just a string which is made safe by using mysql_real_escape_string(). The second value, NOW(), is a SQL function for the current time. The third value, however, is a value we haven&#8217;t seen before. It refers to a (valid) id of a category. The last value refers to an (existing) user_id which is, in this case, the value of $_SESSION[ëuser_id']. This variable was declared during the sign in process.
	</p>
<p>
		If the query executed without errors we proceed to the second query. Remember we are still doing a transaction here. If we would&#8217;ve got errors we would have used the ROLLBACK command.
	</p>
<pre name="code" class="sql">
INSERT INTO
        posts(post_content,
        post_date,
        post_topic,
        post_by)
VALUES
        ('" . mysql_real_escape_string($_POST['post_content']) . "',
         NOW(),
         " . $topicid . ",
         " . $_SESSION['user_id'] . ")
	</pre>
<p>
		The first thing we do in this code is use mysql_insert_id() to retrieve the latest generated id from the topic_id field in the topics table. As you may remember from the first steps of this tutorial, the id is generated in the database using auto_increment.
	</p>
<p>
		Then the post is inserted into the posts table. This query looks a lot like the topics query. The only difference is that this post refers to the topic and the topic referred to a category. From the start, we decided to create a good data model and here is the result: a nice hierarchical structure.
	</p>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/606_forum/tut_files/7.png" border="0" /></div>
<hr />
<h2><span>Step 10</span>: Category View</h2>
<p>
		We&#8217;re going to make an overview page for a single category. We&#8217;ve just created a category, it would be handy to be able to view all the topics in it. First, create a page called category.php.
	</p>
<p>
		A short list of the things we need:
	</p>
<h4>Needed for displaying the category</h4>
<ul>
<li>cat_name</li>
<li>cat_description</li>
</ul>
<p>	<i>Needed for displaying all the topics</i></p>
<ul>
<li>topic_id</li>
<li>topic_subject</li>
<li>topic_date</li>
<li>topic_cat</li>
</ul>
<p>
		Let&#8217;s create the two SQL queries that retrieve exactly this data from the database.
	</p>
<pre name="code" class="sql">
SELECT
    cat_id,
    cat_name,
    cat_description
FROM
    categories
WHERE
    cat_id = " . mysql_real_escape_string($_GET['id'])
	</pre>
<p>
		The query above selects all the categories from the database.
	</p>
<pre name="code" class="sql">
SELECT
    topic_id,
    topic_subject,
    topic_date,
    topic_cat
FROM
    topics
WHERE
    topic_cat = " . mysql_real_escape_string($_GET['id'])
	</pre>
<p>
		The query above is executed in the while loop in which we echo the categories. By doing it this way, we&#8217;ll see all the categories and the latest topic for each of them.<br />
		The complete code of category.php will be the following:
	</p>
<pre name="code" class="php">
&lt;?php
//create_cat.php
include 'connect.php';
include 'header.php';

//first select the category based on $_GET['cat_id']
$sql = "SELECT
			cat_id,
			cat_name,
			cat_description
		FROM
			categories
		WHERE
			cat_id = " . mysql_real_escape_string($_GET['id']);

$result = mysql_query($sql);

if(!$result)
{
	echo 'The category could not be displayed, please try again later.' . mysql_error();
}
else
{
	if(mysql_num_rows($result) == 0)
	{
		echo 'This category does not exist.';
	}
	else
	{
		//display category data
		while($row = mysql_fetch_assoc($result))
		{
			echo '&lt;h2>Topics in &prime;' . $row['cat_name'] . '&prime; category&lt;/h2>';
		}

		//do a query for the topics
		$sql = "SELECT
					topic_id,
					topic_subject,
					topic_date,
					topic_cat
				FROM
					topics
				WHERE
					topic_cat = " . mysql_real_escape_string($_GET['id']);

		$result = mysql_query($sql);

		if(!$result)
		{
			echo 'The topics could not be displayed, please try again later.';
		}
		else
		{
			if(mysql_num_rows($result) == 0)
			{
				echo 'There are no topics in this category yet.';
			}
			else
			{
				//prepare the table
				echo '&lt;table border="1">
					  &lt;tr>
						&lt;th>Topic&lt;/th>
						&lt;th>Created at&lt;/th>
					  &lt;/tr>';	

				while($row = mysql_fetch_assoc($result))
				{
					echo '&lt;tr>';
						echo '&lt;td class="leftpart">';
							echo '&lt;h3>&lt;a href="topic.php?id=' . $row['topic_id'] . '">' . $row['topic_subject'] . '&lt;/a>&lt;h3>';
						echo '&lt;/td>';
						echo '&lt;td class="rightpart">';
							echo date('d-m-Y', strtotime($row['topic_date']));
						echo '&lt;/td>';
					echo '&lt;/tr>';
				}
			}
		}
	}
}

include 'footer.php';
?>
	</pre>
<p>
		And here is the final result of our categories page:
	</p>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/606_forum/tut_files/8.png" border="0" /></div>
<hr />
<h2><span>Step 11</span>: Topic View</h2>
<p>
		The SQL queries in this step are complicated ones. The PHP-part is all stuff that you&#8217;ve seen before. Let&#8217;s take a look at the queries. The first one retrieves basic information about the topic:
	</p>
<pre name="code" class="sql">
SELECT
    topic_id,
    topic_subject
FROM
    topics
WHERE
    topics.topic_id = " . mysql_real_escape_string($_GET['id'])
	</pre>
<p>
		This information is displayed in the head of the table we will use to display all the data. Next, we retrieve all the posts in this topic from the database. The following query gives us exactly what we need:
	</p>
<pre name="code" class="sql">
SELECT
    posts.post_topic,
    posts.post_content,
    posts.post_date,
    posts.post_by,
    users.user_id,
    users.user_name
FROM
    posts
LEFT JOIN
    users
ON
    posts.post_by = users.user_id
WHERE
    posts.post_topic = " . mysql_real_escape_string($_GET['id'])
	</pre>
<p>
		This time, we want information from the users and the posts table &#8211; so we use the LEFT JOIN again. The condition is: the user id should be the same as the post_by field. This way we can show the username of the user who replied at each post.</p>
<p>
		The final topic view looks like this:
	</p>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/606_forum/tut_files/9.png" border="0" /></div>
<hr />
<h2><span>Step 12</span>: Adding a Reply</h2>
<p>
		Let&#8217;s create the last missing part of this forum, the possibility to add a reply. We&#8217;ll start by creating a form:
	</p>
<pre name="code" class="html">
&lt;form method="post" action="reply.php?id=5">
    &lt;textarea name="reply-content">&lt;/textarea>
    &lt;input type="submit" value="Submit reply" />
&lt;/form>
	</pre>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/606_forum/tut_files/10.png" border="0" /></div>
<p>
		The complete reply.php code looks like this.
	</p>
<pre name="code" class="php">
&lt;?php
//create_cat.php
include 'connect.php';
include 'header.php';

if($_SERVER['REQUEST_METHOD'] != 'POST')
{
	//someone is calling the file directly, which we don't want
	echo 'This file cannot be called directly.';
}
else
{
	//check for sign in status
	if(!$_SESSION['signed_in'])
	{
		echo 'You must be signed in to post a reply.';
	}
	else
	{
		//a real user posted a real reply
		$sql = "INSERT INTO
					posts(post_content,
						  post_date,
						  post_topic,
						  post_by)
				VALUES ('" . $_POST['reply-content'] . "',
						NOW(),
						" . mysql_real_escape_string($_GET['id']) . ",
						" . $_SESSION['user_id'] . ")";

		$result = mysql_query($sql);

		if(!$result)
		{
			echo 'Your reply has not been saved, please try again later.';
		}
		else
		{
			echo 'Your reply has been saved, check out &lt;a href="topic.php?id=' . htmlentities($_GET['id']) . '">the topic&lt;/a>.';
		}
	}
}

include 'footer.php';
?>
	</pre>
<p>
		The comments in the code pretty much detail what&#8217;s happening. We&#8217;re checking for a real user and then inserting the post into the database.
	</p>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/606_forum/tut_files/11.png" border="0" /></div>
<hr />
<h2>Finishing Up</h2>
<p>
		Now that you&#8217;ve finished this tutorial, you should have a much better understanding of what it takes to build a forum. I hope my explanations were clear enough! Thanks again for reading.
	</p>

<p><a href="http://feedads.g.doubleclick.net/~a/Maa_UUCDHJkB7Pr-oH0_TAWNezE/0/da"><img src="http://feedads.g.doubleclick.net/~a/Maa_UUCDHJkB7Pr-oH0_TAWNezE/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/Maa_UUCDHJkB7Pr-oH0_TAWNezE/1/da"><img src="http://feedads.g.doubleclick.net/~a/Maa_UUCDHJkB7Pr-oH0_TAWNezE/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nettuts?a=WCIUQyG-TBo:9oiyKzjjp88:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=WCIUQyG-TBo:9oiyKzjjp88:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nettuts?i=WCIUQyG-TBo:9oiyKzjjp88:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=WCIUQyG-TBo:9oiyKzjjp88:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nettuts?i=WCIUQyG-TBo:9oiyKzjjp88:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=WCIUQyG-TBo:9oiyKzjjp88:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/nettuts?i=WCIUQyG-TBo:9oiyKzjjp88:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=WCIUQyG-TBo:9oiyKzjjp88:TzevzKxY174"><img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/nettuts/~4/WCIUQyG-TBo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/feed/</wfw:commentRss>
		<slash:comments>37</slash:comments>
		<feedburner:origLink>http://net.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/</feedburner:origLink></item>
		<item>
		<title>Winners Announced: CodeCanyon Competition</title>
		<link>http://feedproxy.google.com/~r/nettuts/~3/QKn994yT-Q4/</link>
		<comments>http://net.tutsplus.com/competitions/contests/winners-announced-introducing-codecanyon-competition/#comments</comments>
		<pubDate>Tue, 16 Mar 2010 23:13:29 +0000</pubDate>
		<dc:creator>Jeffrey Way</dc:creator>
				<category><![CDATA[Contests]]></category>

		<guid isPermaLink="false">http://net.tutsplus.com/?p=10159</guid>
		<description><![CDATA[
For the entire month of February, developers were encouraged to submit their best scripts and components to CodeCanyon. With over $6200 worth of prizes to win, it was a battle consisting of many high level items. However, the competition has since concluded, and after two weeks of deliberating, the reviewers and I have made our [...]]]></description>
			<content:encoded><![CDATA[<p>
For the <a href="http://net.tutsplus.com/competitions/contests/the-introducing-codecanyon-scripting-competition-6200-worth-of-prizes/">entire month of February</a>, developers were encouraged to submit their best scripts and components to <a href="http://codecanyon.net">CodeCanyon</a>. With over $6200 worth of prizes to win, it was a battle consisting of many high level items. However, the competition has since concluded, and after two weeks of deliberating, the reviewers and I have made our choices for the top three spots!
</p>
<p><span id="more-10159"></span></p>
<h2>Grand Prize Winner: <a href="http://codecanyon.net/user/Sitebase/portfolio">Sitebase</a></h2>
<div class="tutorial_image"><a href="http://codecanyon.net/item/advanced-backup-system/88574"><img src="http://s3.envato.com/files/277886.jpg" alt="Advanced Backup System" /></a>
</div>
<blockquote>
<p>
&#8220;This script is a must have for every webdeveloper/webmaster that want to save some time. Advanced Backup System or Abs helps you with tasks as backing up files, backing up databases and deploy new version to a server.&#8221;
</p>
</blockquote>
<h3>Prizes Awarded </h3>
<ol>
<li>1 <a href="http://mediatemple.net/webhosting/dv/">Dedicated Virtual Box (Rage) from Media Temple</a> (<strong>$1200 value</strong>) </li>
<li> 1 <a href="http://www.apple.com/ipodtouch/">32 gigabyte iPod Touch</a> (<strong>$299 value</strong>) (Ultimate <a href="http://www.techsmith.com">TechSmith</a> Package) </li>
<li>1 copy of <a href="https://store.techsmith.com/order/camtasiastudio.asp">Camtasia Studio for Mac or PC</a> (<strong>$299 value</strong>) (Ultimate <a href="http://www.techsmith.com">TechSmith</a> Package) </li>
<li>1 copy of <a href="https://store.techsmith.com/order/csguide.asp">Camtasia Studio 6: The Definitive Guide</a> (<strong>$39.95 value</strong>) (Ultimate <a href="http://www.techsmith.com">TechSmith</a> Package)</li>
<li>1 <a href="https://store.techsmith.com/order/webcam.asp">Logitech QuickCam Communicate Deluxe PC Webcam</a> (<strong>$99 value</strong>) (Ultimate <a href="http://www.techsmith.com">TechSmith</a> Package)</li>
<li>1 <a href="https://store.techsmith.com/order/usbmic.asp">Audio Technica USB Studio Condenser Microphone</a> (<strong>$149 value</strong>) (Ultimate <a href="http://www.techsmith.com">TechSmith</a> Package)</li>
<li><strong>$100</strong> <a href="http://codecanyon.net">Envato credit</a> (Can be used across all of the marketplaces)</li>
<li><strong>$200</strong> cash</li>
<li>1 <a href="http://mediatemple.net/webhosting/thehostingcard/">MediaTemple Gift Card</a> &#8211; 1 year of hosting, 1 domain name, Up to 5 websites. (<strong>$95 value</strong>)</li>
<li><strong>$25</strong> <a href="http://www.amazon.com">Amazon Gift Card</a></li>
<li>1 <a href="http://www.tutsplus.com">year Tuts Plus membership</a> &#8211; (<strong>$78 value</strong>)</li>
<li>1 <a href="http://wufoo.com/">Wufoo Subscription</a> &#8211; 1 year (<strong>$288 value</strong>)</li>
<li>1 <a href="http://www.formspring.com/pricing.html">Formspring Pro Subscription</a> &#8211; 1 year (<strong>$348 value</strong>)</li>
<li>1 <a href="http://surrealcms.com/">Surreal CMS Subscription</a> &#8211; 1 year (<strong>$275 value</strong>)</li>
<li>1 <a href="https://typekit.com/plans">Personal TypeKit subscription</a> &#8211; 1 year (<strong>$300 value</strong>)</li>
<li>1 <a href="https://myows.com/">Myows Paid Account</a> &#8211; <strong>FREE for life</strong></li>
<li>1 <a href="http://rockablepress.com/our-products/">Rockable Press Book of your Choice</a> <strong>($29 value</strong>) </li>
<li>1 copy of <a href="http://fuelcollective.com/snippet">Snippet (mac app)</a> (<strong>$13 value</strong>)</li>
<li>1 copy of <a href="http://www.packtpub.com/user-interface-library-for-jquery-ui-1-7">jQuery UI 1.7 from Packt Publishing</a> (<strong>$40.49 value</strong>)</li>
<li>1 copy of <a href="http://www.packtpub.com/magento-beginners-guide">Magento Beginner&#8217;s Guide from Packt Publishing</a> (<strong>$35.99 value</strong>)</li>
<li>1 copy of <a href="http://www.packtpub.com/object-oriented-javascript-applications-libraries/book">Object-Oriented JavaScript from Packt Publishing</a> (<strong>$35.99 value</strong>)</li>
<li>1 copy of <a href="http://oreilly.com/catalog/9780596159788">jQuery Cookbook from O&#8217;Reilly Publishing</a> (<strong>$34.99 value</strong>)</li>
<li>1 <a href="https://www.threadsy.com/">Threadsy Invite</a></li>
<li>You will be featured on the <a href="http://codecanyon.net">front page of CodeCanyon</a> as both the featured author and the featured item of the week!</li>
<li>Your item will be included in a collection of the three winning submissions, and will be promoted on the <a href="http://codecanyon.net">front page of CodeCanyon</a> </li>
<li>As an Envato marketplace author, you&#8217;ll earn 40-70% of every sale! </li>
</ol>
<hr />
<h2>2nd Place: <a href="http://codecanyon.net/user/23andwalnut/portfolio">23andwalnut</a> </h2>
<div class="tutorial_image"><a href="http://codecanyon.net/item/clientele-a-secure-client-portal-/89928"><img src="http://s3.envato.com/files/283788.png" alt="Clientele" /></a>
</div>
<blockquote>
<p>
Clientele is a secure client portal for your business. Each client is given their own account that provides a dashboard for them to monitor project status, upload/download documents and files related to their projects, and communicate with you. Using this portal can significantly reduce the amount of admin work you do, by providing a one stop shop for clients to get details about their projects.
</p>
</blockquote>
<h3>Prizes Awarded</h3>
<ol>
<li>1 <a href="http://www.tutsplus.com">year Tuts Plus membership</a> &#8211; (<strong>$78 value</strong>)</li>
<li><strong>$50</strong> <a href="http://codecanyon.net">Envato credit</a></li>
<li>1 <a href="https://typekit.com/plans">Personal TypeKit subscription</a> &#8211; 1 year (<strong>$300 value</strong>)</li>
<li>1 <a href="http://surrealcms.com/">Surreal CMS Subscription</a> &#8211; 1 year (<strong>$275 value</strong>)</li>
<li>1 <a href="http://wufoo.com/">Wufoo Subscription</a> &#8211; 1 year (<strong>$288 value</strong>)</li>
<li>1 <a href="https://myows.com/">Myows Paid Account</a> &#8211; <strong>FREE for life</strong></li>
<li>1 <a href="http://rockablepress.com/our-products/">Rockable Press Book of your Choice</a> <strong>($29 value</strong>) </li>
<li>1 copy of <a href="http://fuelcollective.com/snippet">Snippet (mac app)</a> (<strong>$13 value</strong>)</li>
<li>1 <a href="https://www.threadsy.com/">Threadsy Invite</a></li>
<li>Your item will be included in a collection of the three winning submissions, and will be promoted on the <a href="http://codecanyon.net">front page of CodeCanyon</a> </li>
<li>As an Envato marketplace author, you&#8217;ll earn 40-70% of every sale! </li>
</ol>
<hr />
<h2>3rd Place : <a href="http://codecanyon.net/user/aeroalquimia">aeroalquimia</a></h2>
<div class="tutorial_image"><a href="http://codecanyon.net/item/sexy-slider/87148"><img src="http://s3.envato.com/files/272171.jpg" alt="Sexy Slider" /></a>
</div>
<blockquote>
<p>
&#8220;SexySlider is a JQuery plugin that lets you easily create powerful javascript Sliders with very nice transition effects. Enhance your website by adding a unique and attractive slider!&#8221;
</p>
</blockquote>
<h3>Prizes Awarded</h3>
<ol>
<li>1 <a href="http://www.tutsplus.com">year Tuts Plus membership</a> &#8211; (<strong>$78 value</strong>)</li>
<li><strong>$50</strong> <a href="http://codecanyon.net">Envato credit</a></li>
<li>1 <a href="https://typekit.com/plans">Personal TypeKit subscription</a> &#8211; 1 year (<strong>$300 value</strong>)</li>
<li>1 <a href="http://surrealcms.com/">Surreal CMS Subscription</a> &#8211; 1 year (<strong>$275 value</strong>)</li>
<li>1 <a href="http://wufoo.com/">Wufoo Subscription</a> &#8211; 1 year (<strong>$288 value</strong>)</li>
<li>1 <a href="https://myows.com/">Myows Paid Account</a> &#8211; <strong>FREE for life</strong></li>
<li>1 <a href="http://rockablepress.com/our-products/">Rockable Press Book of your Choice</a> <strong>($29 value</strong>) </li>
<li>1 copy of <a href="http://fuelcollective.com/snippet">Snippet (mac app)</a> (<strong>$13 value</strong>)</li>
<li>1 <a href="https://www.threadsy.com/">Threadsy Invite</a></li>
<li>Your item will be included in a collection of the three winning submissions, and will be promoted on the <a href="http://codecanyon.net">front page of CodeCanyon</a> </li>
<li>As an Envato marketplace author, you&#8217;ll earn 40-70% of every sale! </li>
</ol>
<hr />
<h2>Honorable Mentions </h2>
<p>We had an extremely difficult time choosing only three winners, when there were so many top level submissions! Here are a sampling of some the other front-runners! </p>
<ul>
<li><a href="http://codecanyon.net/item/sharp-user-management-system/87448">Sharp User Management System</a></li>
<li><a href="http://codecanyon.net/item/mbslider/89466">MBSlider</a></li>
<li><a href="http://codecanyon.net/item/send-to-friend-form/89494">Send to Friend Form</a></li>
<li><a href="http://codecanyon.net/item/uptime-website-uptime-monitoring/86651">Up-Time Website Monitoring</a></li>
<li><a href="http://codecanyon.net/item/live-search-searchengine-for-your-website/86875">Live Search</a></li>
<li><a href="http://codecanyon.net/item/simple-php-rsvp-v15/84077 ">Simple PHP RSVP</a></li>
</ul>
<p>A huge thanks goes out to everyone who entered. Even if you didn&#8217;t win, you&#8217;re now <a href="http://codecanyon.net/wiki/selling/author-selling/author-program/">earning 40-70% of every sale</a> of your item. <strong>Thanks again to our incredible sponsors for helping us out. </strong>So until next time&#8230;</p>

<p><a href="http://feedads.g.doubleclick.net/~a/O7ze8DXeZ1oCVqRWMRIHTtmaH8c/0/da"><img src="http://feedads.g.doubleclick.net/~a/O7ze8DXeZ1oCVqRWMRIHTtmaH8c/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/O7ze8DXeZ1oCVqRWMRIHTtmaH8c/1/da"><img src="http://feedads.g.doubleclick.net/~a/O7ze8DXeZ1oCVqRWMRIHTtmaH8c/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nettuts?a=QKn994yT-Q4:i2htTf6eIzY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=QKn994yT-Q4:i2htTf6eIzY:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nettuts?i=QKn994yT-Q4:i2htTf6eIzY:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=QKn994yT-Q4:i2htTf6eIzY:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nettuts?i=QKn994yT-Q4:i2htTf6eIzY:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=QKn994yT-Q4:i2htTf6eIzY:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/nettuts?i=QKn994yT-Q4:i2htTf6eIzY:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=QKn994yT-Q4:i2htTf6eIzY:TzevzKxY174"><img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/nettuts/~4/QKn994yT-Q4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/competitions/contests/winners-announced-introducing-codecanyon-competition/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		<feedburner:origLink>http://net.tutsplus.com/competitions/contests/winners-announced-introducing-codecanyon-competition/</feedburner:origLink></item>
		<item>
		<title>IE9 May Actually Be a Fantastic Browser</title>
		<link>http://feedproxy.google.com/~r/nettuts/~3/cS1fQNMOTp0/</link>
		<comments>http://net.tutsplus.com/articles/news/ie9-may-actually-be-a-great-browser/#comments</comments>
		<pubDate>Tue, 16 Mar 2010 17:34:35 +0000</pubDate>
		<dc:creator>Jeffrey Way</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[ie9]]></category>
		<category><![CDATA[internet explorer]]></category>
		<category><![CDATA[mix10]]></category>

		<guid isPermaLink="false">http://net.tutsplus.com/?p=10122</guid>
		<description><![CDATA[
Today, as part of MIX 2010, some exciting updates were released on the progress of Internet Explorer 9. The IE team is implementing some incredible features, such as HTML5, CSS3, SVG support, and a new lightning fast JavaScript engine, Chakra! Further, they&#8217;re currently scoring a 55 on the Acid3 test &#8211; a figure that&#8217;s surely [...]]]></description>
			<content:encoded><![CDATA[<p>
Today, as part of <a href="http://live.visitmix.com/">MIX 2010</a>, some exciting updates were released on the progress of Internet Explorer 9. The IE team is implementing some incredible features, such as HTML5, CSS3, SVG support, and a new lightning fast JavaScript engine, Chakra! Further, they&#8217;re currently scoring a 55 on the<a href="http://acid3.acidtests.org/"> Acid3 test</a> &#8211; a figure that&#8217;s surely to increase substantially before the official release. What about the idea of Microsoft contributing to an open source project, jQuery, with their <a href="http://blog.jquery.com/2010/03/16/microsoft-to-expand-its-collaboration-with-the-jquery-community/">proposed templating engine</a>?  Within moments of these announcements, the Twitter-verse spilled &#8220;tears of joy.&#8221;  </p>
<p>Want to dive in and check out the developer preview? <a href="http://ie.microsoft.com/testdrive/">That&#8217;s available too, starting today</a>!
</p>
<p><span id="more-10122"></span></p>
<div class="tutorial_image">
<a href="http://ie.microsoft.com/testdrive/"><br />
<img src="http://nettuts.s3.cdn.plus.org/603_ie9/testdrive.jpg" /><br />
</a><br />
<span>Take IE9 for a Test Drive.</span>
</div>
<blockquote>
<p>
Finally, we announced the availability of the first IE Platform Preview for developers, and our commitment to update it approximately every eight weeks. We want the developer community to have an earlier hands-on experience with the progress we’re making on the IE platform. The Platform Preview, and the feedback loop it is part of, marks a major change from previous IE releases.<br />
<a href="http://blogs.msdn.com/ie/archive/2010/03/16/html5-hardware-accelerated-first-ie9-platform-preview-available-for-developers.aspx" class="source">IE Blog</a>
</p>
</blockquote>
<h3>Demos </h3>
<p>Check out some of the demos below in each browser to learn the unique code required for each. </p>
<ul>
<li><a href="http://ie.microsoft.com/testdrive/HTML5/01BorderRadius/Default.html">Border-Radius</a></li>
<li><a href="http://ie.microsoft.com/testdrive/Performance/40PulsatingBubbles/Default.xhtml">Pulsating Bubbles</a></li>
<li><a href="http://ie.microsoft.com/testdrive/Graphics/21FallingBalls/Default.xhtml">SVG: Falling Balls</a></li>
<li><a href="http://ie.microsoft.com/testdrive/HTML5/10CSS3_Selectors/Default.html">CSS3 Selectors</a></li>
</ul>
<hr />
<h2>New JavaScript Engine: Chakra </h2>
<div class="tutorial_image"><a href="http://blogs.msdn.com/ie/archive/2010/03/16/html5-hardware-accelerated-first-ie9-platform-preview-available-for-developers.aspx"><img src="http://nettuts.s3.cdn.plus.org/603_ie9/Dean_MIX10_2.png" alt="JavaScript Graph" /></a>
</div>
<blockquote>
<p>
&#8220;You’ll notice that IE9 is faster at this benchmark than IE8 and several other browsers. It’s interesting to note that the difference between today’s IE9 preview and the browsers to its right in this graph. It takes about 70 seconds to identify a 300ms difference between browsers.&#8221;<br />
<a href="http://blogs.msdn.com/ie/archive/2010/03/16/html5-hardware-accelerated-first-ie9-platform-preview-available-for-developers.aspx" class="source">IE Blog</a>
</p>
</blockquote>
<h2>Miscellaneous Tweets about IE9 from MIX 2010 </h2>
<blockquote>
<p>
&#8220;Video tag and SVG support in IE 9 as well &#8211; and it&#8217;s crazy fast. Very impressed.&#8221;<br />
<a href="http://twitter.com/jeresig/status/10577296198" class="source">John Resig</a>
</p>
</blockquote>
<blockquote>
<p>
&#8220;Microsoft to Expand its Collaboration with the jQuery Community&#8221;: <a href="http://bit.ly/cxybri">http://bit.ly/cxybri</a><br />
<a href="http://twitter.com/jquery/status/10578542060" class="source">@jQuery</a>
</p>
</blockquote>
<blockquote>
<p>
&#8220;Today makes me very happy to have come to work at Microsoft. Very excited right now to see the reactions of the community.&#8221;<br />
<a href="http://twitter.com/reybango/status/10577630661" class="source">Rey Bango</a>
</p>
</blockquote>
<blockquote>
<p>
&#8220;They&#8217;re asking for help in getting ppl to move IE6 to IE8.  They want users on modern browsers.&#8221;<br />
<a href="http://twitter.com/reybango/status/10577319636" class="source">Rey Bango</a>
</p>
</blockquote>
<blockquote>
<p>
&#8220;Open source, open standards, open Microsoft. Today I woke up to a different world than I thought I was living in.&#8221;<br />
<a href="http://twitter.com/mollydotcom/status/10579165439" class="source">Molly E. Holzschlag</a>
</p>
</blockquote>
<blockquote>
<p>
&#8220;So what we have here is HTML5, CSS3, SVG 1.1 in IE9. If I weren&#8217;t seeing it with my own eyes, I wouldn&#8217;t freakin&#8217; believe it.&#8221;<br />
<a href="http://twitter.com/mollydotcom/status/10576788688" class="source">Molly E. Holzschlag</a>
</p>
</blockquote>
<p>Check back for more details as they become available!</p>

<p><a href="http://feedads.g.doubleclick.net/~a/GndHLkRmQFwKGTJlXE9qYaLLgzQ/0/da"><img src="http://feedads.g.doubleclick.net/~a/GndHLkRmQFwKGTJlXE9qYaLLgzQ/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/GndHLkRmQFwKGTJlXE9qYaLLgzQ/1/da"><img src="http://feedads.g.doubleclick.net/~a/GndHLkRmQFwKGTJlXE9qYaLLgzQ/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nettuts?a=cS1fQNMOTp0:QkHwoIZUdVg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=cS1fQNMOTp0:QkHwoIZUdVg:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nettuts?i=cS1fQNMOTp0:QkHwoIZUdVg:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=cS1fQNMOTp0:QkHwoIZUdVg:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nettuts?i=cS1fQNMOTp0:QkHwoIZUdVg:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=cS1fQNMOTp0:QkHwoIZUdVg:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/nettuts?i=cS1fQNMOTp0:QkHwoIZUdVg:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=cS1fQNMOTp0:QkHwoIZUdVg:TzevzKxY174"><img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/nettuts/~4/cS1fQNMOTp0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/articles/news/ie9-may-actually-be-a-great-browser/feed/</wfw:commentRss>
		<slash:comments>105</slash:comments>
		<feedburner:origLink>http://net.tutsplus.com/articles/news/ie9-may-actually-be-a-great-browser/</feedburner:origLink></item>
		<item>
		<title>10 Features to Look Forward to in WordPress 3.0</title>
		<link>http://feedproxy.google.com/~r/nettuts/~3/685fLsrbHlk/</link>
		<comments>http://net.tutsplus.com/tutorials/wordpress/10-features-to-look-forward-to-in-wordpress-3-0/#comments</comments>
		<pubDate>Tue, 16 Mar 2010 16:48:35 +0000</pubDate>
		<dc:creator>Rohan Mehta</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[wordpress 3.0]]></category>

		<guid isPermaLink="false">http://net.tutsplus.com/?p=10101</guid>
		<description><![CDATA[WordPress 3.0 is scheduled to be released within the next 30-60 days. There are some great new features coming, including custom post types, a new default theme, and a menu manager. Read on to find out what to expect in version three!

1. Choose your Username and Password
You&#8217;ll encounter new features as soon as you start! [...]]]></description>
			<content:encoded><![CDATA[<p>WordPress 3.0 is scheduled to be released within the next 30-60 days. There are some great new features coming, including custom post types, a new default theme, and a menu manager. Read on to find out what to expect in version three!</p>
<p><span id="more-10101"></span></p>
<h2><span>1. </span>Choose your Username and Password</h2>
<p>You&#8217;ll encounter new features as soon as you start! Currently, when you first install WordPress, you are assigned a default username of <strong>admin</strong>, and a randomly generated password. No more &#8211; now WordPress lets you choose a username and password when installing.</p>
<p><h4>What does this mean for us?</h4>
<p>This means that security within WordPress has been enhanced. Previously, a hacker could probably depend on the fact that there was a username called &#8216;admin&#8217;. This will no longer be the case in version three. Read any <a href="http://net.tutsplus.com/tutorials/WordPress/the-definitive-guide-to-securing-WordPress-new-plus-tutorial/">tutorial</a> on securing WordPress &#8211; you will always be told to remove the admin username. You no longer need to!</p>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/602_wp/wp1.jpg" border="0" /></div>
<hr />
<h2><span>2. </span>New Default Theme!</h2>
<p>WordPress 3.0 comes with a new default theme, called TwentyTen (2010, like the current year &#8211; go figure). Apparently, the WP team has an aim to release a new default theme every year! TwentyTen is a nice theme. The main typeface used is Georgia; it has two columns, with a widgetized sidebar and footer &#8211; and it even has some nice dropdown menus built in! Needless to say, custom header and background (new feature) functions are also available.</p>
<p><h4>What does this mean for us?</h4>
<p>
We start off with a nice new theme, and bloggers have more options to try out before they start looking for themes. More options are always helpful, right?  </p>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/602_wp/wp2.jpg" border="0" /></div>
<hr />
<h2><span>3. </span>Custom Background Support</h2>
<p>WordPress 3.0 adds custom background support. Add the code below to your functions.php to make your theme support it:</p>
<pre name="code" class="php">
add_custom_background();
</pre>
<p>
Once that&#8217;s done, you&#8217;ll see an option called <strong>Background</strong> added under Appearance in the WordPress admin. This will allows you to upload a header image and customize it.</p>
<p><h4>What does this mean for us?</h4>
<p>
This doesn&#8217;t really mean much to advanced theme developers, since they often provide an option like this themselves. Nevertheless, I have no doubt that the WordPress community will come up with some creative uses for this.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/602_wp/wp3.jpg" border="0" /></div>
<hr />
<h2><span>4. </span>Multi-site Capabilities and WPMU Codebase Merge</h2>
<p>WordPress and WPMU (WordPress MultiUser) are merging their codebases. This makes it much easier to handle large WordPress networks. See the Multi-Site settings under Settings&gt;Network.</p>
<p><h4>What does this mean for us?</h4>
<p>
A lot! A network of WordPress sites is much easier to maintain &#8211; either with a <em>subdomain.domain.com</em > structure, or a <em>domain.com/subdirectory</em> structure. This network capability is optional, and WordPress and WPMU users shouldn&#8217;t face any difficulties while upgrading. Also, this makes it easier for WPMU users to utilize plugins &#8211; no more plugins that go bust or stop working.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/602_wp/wp4.jpg" border="0" /></div>
<hr />
<h2><span>5. </span>Custom Post Types</h2>
<p>A great new feature! Before, all you could add from the WordPress admin section was new posts and pages. Now, you can create new post types to show up. Add the following code to create a new post type called &#8216;Portfolio&#8217;:</p>
<pre name="code" class="php">
function post_type_portfolio() {
	register_post_type( 'Portfolio',
                array( 'label' => __('Portfolio'), 'public' => true, 'show_ui' => true ) );
	register_taxonomy_for_object_type('post_tag', 'Portfolio');
}

add_action('init', 'post_type_portfolio');
</pre>
<p><h4>What does this mean for us?</h4>
<p>
Quite simply, it means WordPress has become much more of a CMS. This holds unlimited possibilities for theme developers, and reduces the need to fiddle around with custom fields. </p>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/602_wp/wp5.jpg" border="0" /></div>
<hr />
<h2><span>6. </span>Custom Taxonomies</h2>
<p>Custom taxonomies have been made easier to use, as well as hierarchical &#8211; which means you could have a taxonomy called &#8216;Rating&#8217;, with sub-taxonomies like PG-13, R , U etc. </p>
<p><h4>What does this mean for us?</h4>
<p>
It means that WordPress is moving more and more from a blog-type CMS, with effort required for better capabilities, to a much more flexible and usable Content Management System.</p>
<hr />
<h2><span>7. </span>Easy Menu Management</h2>
<p>This is my favorite new feature in WordPress 3.0 &#8211; a menu manager. It&#8217;s developed by WooThemes&#8217; <a href="http://www.woothemes.com/2010/02/woonav-integrated-in-wp-30/">WooNav</a>, and I absolutely love it. You can create multiple menus, categories, and even custom external or internal links! The menu feature even comes with a default widget to add to any widget ready area &#8211; awesome, isn&#8217;t it?</p>
<p><h4>What does this mean for us?</h4>
<p>
On the surface, this provides us a great UI (user interface) for adding new menus, it simplifies the job of WordPress theme developers and makes things as simple as possible for users. Benearth the surface, there is a lot more &#8211; this marks a point where commercial WordPress theme developers join hands with WordPress and contribute to it. A win-win situation for both, and an incentive to continue working.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/602_wp/wp6.jpg" border="0" /></div>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/602_wp/wp7.jpg" border="0" /></div>
<hr />
<h2><span>8. </span>A Bunch of Other Smaller Features</h2>
<ul>
<li>Welcome guide: WordPress 3.0 will be including a guide with it which helps users to know the system better and teach them basic usage.</li>
<li>Specific author templates: We already have hierarchy for categories and tags like <em>category-{slug}.php</em> followed by <em>category-{id}.php</em> in the <a href="http://codex.WordPress.org/Template_Hierarchy">Template Hierarchy</a>, but now you can do the same for authors. So, if the author name was &#8216;Rohan&#8217; with id 1, WordPress would first look for <em>author-rohan.php</em>, then <em>author-1.php</em> before <em>author.php</em> in the template files for display.</li>
<li>Media UI redeign: Started, but not implemented in WordPress 2.9, the Media tab in the admin panel may get a UI redesign</li>
</ul>
<hr />
<h2>Conclusion</h2>
<p>The screenshots and features that I&#8217;ve written about here are taken from the most recent nightly build. You may want to try it out yourself, though keep in mind that it&#8217;s still unstable. Nevertheless, WordPress is evolving at a rate no one could have predicted, and is fully morphing into a powerful and flexible CMS. </p>

<p><a href="http://feedads.g.doubleclick.net/~a/xxsHZTmHHfv7iS71DxgsxQbiSno/0/da"><img src="http://feedads.g.doubleclick.net/~a/xxsHZTmHHfv7iS71DxgsxQbiSno/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/xxsHZTmHHfv7iS71DxgsxQbiSno/1/da"><img src="http://feedads.g.doubleclick.net/~a/xxsHZTmHHfv7iS71DxgsxQbiSno/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nettuts?a=685fLsrbHlk:08-wceb44sY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=685fLsrbHlk:08-wceb44sY:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nettuts?i=685fLsrbHlk:08-wceb44sY:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=685fLsrbHlk:08-wceb44sY:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nettuts?i=685fLsrbHlk:08-wceb44sY:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=685fLsrbHlk:08-wceb44sY:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/nettuts?i=685fLsrbHlk:08-wceb44sY:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=685fLsrbHlk:08-wceb44sY:TzevzKxY174"><img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/nettuts/~4/685fLsrbHlk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/wordpress/10-features-to-look-forward-to-in-wordpress-3-0/feed/</wfw:commentRss>
		<slash:comments>93</slash:comments>
		<feedburner:origLink>http://net.tutsplus.com/tutorials/wordpress/10-features-to-look-forward-to-in-wordpress-3-0/</feedburner:origLink></item>
		<item>
		<title>Winners Announced: Win a Copy of Rockable’s Latest eBook, ‘How to Write Great Copy for the Web’</title>
		<link>http://feedproxy.google.com/~r/nettuts/~3/XgXHsegJsWM/</link>
		<comments>http://net.tutsplus.com/articles/news/win-a-copy-of-rockables-latest-ebook-how-to-write-great-copy-for-the-web/#comments</comments>
		<pubDate>Tue, 16 Mar 2010 04:13:39 +0000</pubDate>
		<dc:creator>Aaron Osteraas</dc:creator>
				<category><![CDATA[News]]></category>

		<guid isPermaLink="false">http://net.tutsplus.com/?p=10066</guid>
		<description><![CDATA[Hi everyone, the winners have been selected and contacted. Thank you all for entering this great competition. If you weren&#8217;t successful there are still two more days for you to get on the Rockin&#8217; List and get the voucher for the book.
The winners are Khaled, Kay and Achikochi.
Today we&#8217;ve got three copies of the new [...]]]></description>
			<content:encoded><![CDATA[<p>Hi everyone, the winners have been selected and contacted. Thank you all for entering this great competition. If you weren&#8217;t successful there are still two more days for you to get on the <a href="http://rockablepress.com/the-rockin-list/"><strong>Rockin&#8217; List</strong></a> and get the voucher for the book.</p>
<p><strong>The winners are Khaled, Kay and Achikochi.</strong></p>
<p>Today we&#8217;ve got three copies of the new eBook from <a href="http://rockablepress.com">Rockable</a> and <a href="http://freelanceswitch.com">FreelanceSwitch</a>, <a href="http://rockablepress.com/minibooks/how-to-write-great-copy-for-the-web/">How to Write Great Copy for the Web</a>, to give away. Entering takes seconds, just leave a comment below and three lucky people will be selected. <span id="more-10066"></span></p>
<h3>Win <em>How to Write Great Copy for the Web</em></h3>
<ul class="webroundup">
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/Articles/012_Copyfortheweb/CopyFront.png" width="250" height="385" alt="How to Write Great Copy for the Web Cover" /></div>
<li>
<h4>About the Book</h4>
<p>How to Write Great Copy for the Web is the latest book from Rockable Press. You may not know this, but Rockable is Envato&#8217;s book publishing house! This book takes a concise and practical approach to writing fantastic copy for any website.</p>
<p>Ever been asked to write the copy for a website you&#8217;re working and had to say no because you aren&#8217;t a copywriter? Or maybe you did it for your client and weren&#8217;t happy with the final product? How to Write Great Copy for the Web will teach you how to add web copy writing to your skill set, maximizing your billable hours.</p>
<p>This book will also help you write great copy for your portfolio or blog, to impress potential clients.</li>
</ul>
<div class="clear:both"></div>
<blockquote><p><strong>From the blurb:</strong> &#8220;In How to Write Great Copy for the Web, author Donna Spencer will help you start writing content for the web that works! Learn about how writing web copy differs from other forms of writing, and how writing useful, functional and concise copy can both help persuade your readers, and also help with search engine optimization!</p>
<p>Whether it’s for your own site, or for somebody else, How to Write Great Copy for the Web will quickly bring you up to speed with some clever strategies that will make you popular with your site’s visitors, or with your clients!&#8221;</p></blockquote>
<h4>How to Enter</h4>
<p>For your chance to win one of the three books all you need to do is leave a comment below. Be sure to include your correct email address so that we can get in touch. The competition is open to anyone but you need to have entered by 12am March 18th AEST.</p>
<h4>Want a Free Book? Join the Rockin&#8217; List</h4>
<p>Afraid you might not win? Sign up to the <strong><a href="http://rockablepress.com/the-rockin-list/">Rockin&#8217; List</a></strong> to get the discount code for $5 off this great book and stay up to date with the latest Rockable news. You also get a free copy of <a href="http://rockablepress.com/minibooks/rockstar-personal-branding/">Rockstar Personal Branding</a> when you subscribe!</p>

<p><a href="http://feedads.g.doubleclick.net/~a/USS9BkH-ADgns0IZrtJGexVosqA/0/da"><img src="http://feedads.g.doubleclick.net/~a/USS9BkH-ADgns0IZrtJGexVosqA/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/USS9BkH-ADgns0IZrtJGexVosqA/1/da"><img src="http://feedads.g.doubleclick.net/~a/USS9BkH-ADgns0IZrtJGexVosqA/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nettuts?a=XgXHsegJsWM:3iatci9AnmU:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=XgXHsegJsWM:3iatci9AnmU:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nettuts?i=XgXHsegJsWM:3iatci9AnmU:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=XgXHsegJsWM:3iatci9AnmU:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nettuts?i=XgXHsegJsWM:3iatci9AnmU:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=XgXHsegJsWM:3iatci9AnmU:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/nettuts?i=XgXHsegJsWM:3iatci9AnmU:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=XgXHsegJsWM:3iatci9AnmU:TzevzKxY174"><img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/nettuts/~4/XgXHsegJsWM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/articles/news/win-a-copy-of-rockables-latest-ebook-how-to-write-great-copy-for-the-web/feed/</wfw:commentRss>
		<slash:comments>531</slash:comments>
		<feedburner:origLink>http://net.tutsplus.com/articles/news/win-a-copy-of-rockables-latest-ebook-how-to-write-great-copy-for-the-web/</feedburner:origLink></item>
		<item>
		<title>Learning Server-Side JavaScript with Node.js</title>
		<link>http://feedproxy.google.com/~r/nettuts/~3/ndZ5-XeHlao/</link>
		<comments>http://net.tutsplus.com/tutorials/javascript-ajax/learning-serverside-javascript-with-node-js/#comments</comments>
		<pubDate>Mon, 15 Mar 2010 16:06:48 +0000</pubDate>
		<dc:creator>Devon Govett</dc:creator>
				<category><![CDATA[JavaScript & AJAX]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[node js]]></category>
		<category><![CDATA[nodejs]]></category>
		<category><![CDATA[server-side JavaScript]]></category>

		<guid isPermaLink="false">http://net.tutsplus.com/?p=10044</guid>
		<description><![CDATA[Node.js is all the buzz at the moment, and makes creating high performance, real-time web applications easy.  It allows JavaScript to be used end to end, both on the server and on the client.  This tutorial will walk you through the installation of Node and your first &#8220;Hello World&#8221; program, to building a [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://nodejs.org/">Node.js</a> is all the buzz at the moment, and makes creating high performance, real-time web applications easy.  It allows JavaScript to be used end to end, both on the server and on the client.  This tutorial will walk you through the installation of Node and your first &#8220;Hello World&#8221; program, to building a scalable streaming Twitter server.</p>
<p><span id="more-10044"></span></p>
<h2>What is Node.js? </h2>
<div class="tutorial_image">
<a href="http://nodejs.org/"><br />
<img src="http://nettuts.s3.cdn.plus.org/601_node/node.jpg" alt="NodeJS" /><br />
</a>
</div>
<p>JavaScript has traditionally only run in the web browser, but recently there has been considerable interest in bringing it to the server side as well, thanks to the <a href="http://commonjs.org/">CommonJS project</a>.  Other server-side JavaScript environments include <a href="http://www.jaxer.org/">Jaxer</a> and <a href="http://narwhaljs.org/">Narwhal</a>.  However, <a href="http://nodejs.org/">Node.js</a> is a bit different from these solutions, because it is event-based rather than thread based.  Web servers like Apache that are used to serve PHP and other CGI scripts are thread based because they spawn a system thread for every incoming request.  While this is fine for many applications, the thread based model does not scale well with many long-lived connections like you would need in order to serve real-time applications like <a href="http://friendfeed.com/">Friendfeed</a> or <a href="http://wave.google.com/">Google Wave</a>.  </p>
<blockquote class="pullquote pqRight"><p>
&#8220;Every I/O operation in Node.js is asynchronous&#8230;&#8221;
</p></blockquote>
<p>Node.js, uses an event loop instead of threads, and is able to scale to millions of concurrent connections.  It takes advantage of the fact that servers spend most of their time waiting for I/O operations, like reading a file from a hard drive, accessing an external web service or waiting for a file to finish being uploaded, because these operations are much slower than in memory operations.  Every I/O operation in Node.js is asynchronous, meaning that the server can continue to process incoming requests while the I/O operation is taking place.  JavaScript is extremely well suited to event-based programming because it has anonymous functions and closures which make defining inline callbacks a cinch, and JavaScript developers already know how to program in this way.  This event-based model makes Node.js very fast, and makes scaling real-time applications very easy.</p>
<hr />
<h2><span>Step 1</span> Installation </h2>
<p>Node.js runs on Unix based systems, such as Mac OS X, Linux, and FreeBSD.  Unfortunately, Windows is not yet supported, so if you are a Windows user, you can install it on Ubuntu Linux using Virtualbox.  To do so, follow <a href="http://www.psychocats.net/ubuntu/virtualbox">this tutorial</a>.  You will need to use the terminal to install and run Node.js.</p>
<ol>
<li>Download the latest release of Node.js from <a href="http://nodejs.org/#download">nodejs.org</a> (the latest version at the time of this writing is 0.1.31) and unzip it.</li>
<li>Open the terminal, and run the following commands.
<pre name="code" class="html">cd /path/to/nodejs
make
sudo make install
		</pre>
<p>		A lot of messages will be outputted to the terminal as Node.js is compiled and installed.
	</li>
</ol>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/601_node/1.jpg" border="0" /></div>
<hr />
<h2><span>Step 2</span> Hello World! </h2>
<p>Every new technology starts with a &#8220;Hello World!&#8221; tutorial, so we will create a simple HTTP server that serves up that message.  First, however, you have to understand the Node.js module system.  In Node, functionality is encapsulated in modules which must be loaded in order to be used.  There are many modules listed in the <a href="http://nodejs.org/api.html">Node.js documentation</a>.  You load these modules by using the <code>require</code> function like so: </p>
<pre name="code" class="js">
var sys = require("sys");
</pre>
<p>This loads the sys module, which contains functions for dealing with system level tasks like printing output to the terminal.  To use a function in a module, you call it on the variable that you stored the module in, in our case <code>sys</code>.</p>
<pre name="code" class="js">
sys.puts("Hello World!");
</pre>
<p>Running these two lines is as simple as running the <code>node</code> command with the filename of the javascript file as an argument.</p>
<pre name="code" class="html">
node test.js
</pre>
<p>This will output &#8220;Hello World!&#8221; to the command line when run.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/601_node/2.jpg" border="0" /></div>
<p>To create an HTTP server, you must <code>require</code> the <code>http</code> module.</p>
<pre name="code" class="js">
var sys = require("sys"),
    http = require("http");

http.createServer(function(request, response) {
    response.sendHeader(200, {"Content-Type": "text/html"});
    response.write("Hello World!");
    response.close();
}).listen(8080);

sys.puts("Server running at http://localhost:8080/");
</pre>
<p>This script imports the <code>sys</code> and <code>http</code> modules, and creates an HTTP server.  The anonymous function that is passed into <code>http.createServer</code> will be called whenever a request comes in to the server.  Once the server is created, it is told to listen on port 8080.  When a request to the server comes in, we first send HTTP headers with the content type and status code of 200 (successful).  Then we send &#8220;Hello World!&#8221; and close the connection.  You might notice that we have to explicitly close the connection.  This will make it very easy to stream data to the client without closing the connection.  If you run this script and go to <code>http://localhost:8080/</code> in your browser, you will see &#8220;Hello World!&#8221;</p>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/601_node/3.jpg" border="0" /></div>
<hr />
<h2><span>Step 3</span> A Simple Static File Server </h2>
<p>OK, so we have built an HTTP server, but it doesn&#8217;t send anything except for &#8220;Hello World,&#8221; no matter what URL you go to.  Any HTTP server must be able to send static files such as HTML files, images and other files.  The following code does just that:</p>
<pre name="code" class="js">
var sys = require("sys"),
    http = require("http"),
    url = require("url"),
    path = require("path"),
    fs = require("fs");

http.createServer(function(request, response) {
    var uri = url.parse(request.url).pathname;
    var filename = path.join(process.cwd(), uri);
    path.exists(filename, function(exists) {
    	if(!exists) {
    		response.sendHeader(404, {"Content-Type": "text/plain"});
    		response.write("404 Not Found\n");
    		response.close();
    		return;
    	}

    	fs.readFile(filename, "binary", function(err, file) {
    		if(err) {
    			response.sendHeader(500, {"Content-Type": "text/plain"});
    			response.write(err + "\n");
    			response.close();
    			return;
    		}

    		response.sendHeader(200);
    		response.write(file, "binary");
    		response.close();
    	});
    });
}).listen(8080);

sys.puts("Server running at http://localhost:8080/");
</pre>
<p>We start by requiring all of the modules that we will need in our code.  This includes the <code>sys</code>, <code>http</code>, <code>url</code>, <code>path</code>, and <code>fs</code> or filesystem modules.  Next we create an HTTP server like we did before.  This time, we will use the <code>url</code> module to parse the incoming URL of the request and find the pathname of the file being accessed.  We find the actual filename on the server&#8217;s hard drive by using <code>path.join</code>, which joins <code>process.cwd()</code>, or the current working directory, with the path to the file being requested.  Next, we check if the file exists, which is an asynchronous operation and thus requires a callback.  If the file does not exist, a 404 Not Found message is sent to the user and the function returns.  Otherwise, we read the file using the <code>fs</code> module using the &#8220;binary&#8221; encoding, and send the file to the user.  If there is an error reading the file, we present the error message to the user, and close the connection.  Because all of this is asynchronous, the server is able to serve other requests while reading the file from the disk no matter how large it is.</p>
<p>If you run this example, and navigate to <code>http://localhost:8080/path/to/file</code>, that file will be shown in your browser.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/601_node/4.jpg" border="0" /></div>
<hr />
<h2><span>Step 4</span> A Real Time Tweet Streamer </h2>
<p>Building on our static file server, we will build a server in Node.js that streams tweets to a client that is served through our static file server.  To start, we will need one extra module in this example: the <code>events</code> module.  Node has a concept called an <code>EventEmitter</code>, which is used all over to handle event listeners for asynchronous tasks.  Much like in jQuery or another client side JavaScript framework where you bind event listeners to things like mouse clicks, and AJAX requests, Node allows you to bind event listeners to many things, some of which we have already used.  These include every I/O operation, such as reading a file, writing a file, checking if a file exists, waiting for HTTP requests, etc.  The <code>EventEmitter</code> abstracts the logic of binding, unbinding, and triggering such event listeners.  We will be using an <code>EventEmitter</code> to notify listeners when new tweets are loaded.  The first few lines of our tweet streamer imports all of the required modules, and defines a function for handling static files, which was taken from our previous example.</p>
<pre name="code" class="js">
var sys = require("sys"),
    http = require("http"),
    url = require("url"),
    path = require("path"),
    fs = require("fs"),
    events = require("events");

function load_static_file(uri, response) {
	var filename = path.join(process.cwd(), uri);
	path.exists(filename, function(exists) {
		if(!exists) {
			response.sendHeader(404, {"Content-Type": "text/plain"});
			response.write("404 Not Found\n");
			response.close();
			return;
		}

		fs.readFile(filename, "binary", function(err, file) {
			if(err) {
				response.sendHeader(500, {"Content-Type": "text/plain"});
				response.write(err + "\n");
				response.close();
				return;
			}

			response.sendHeader(200);
			response.write(file, "binary");
			response.close();
		});
	});
}
</pre>
<p>We have used the <code>http</code> module to create a server before, but it is also possible to create an HTTP client using the module.  We will be creating an HTTP client to load tweets from Twitter&#8217;s public timeline, which is performed by the <code>get_tweets</code> function.</p>
<pre name="code" class="js">
var twitter_client = http.createClient(80, "api.twitter.com");

var tweet_emitter = new events.EventEmitter();

function get_tweets() {
	var request = twitter_client.request("GET", "/1/statuses/public_timeline.json", {"host": "api.twitter.com"});

	request.addListener("response", function(response) {
		var body = "";
		response.addListener("data", function(data) {
			body += data;
		});

		response.addListener("end", function() {
			var tweets = JSON.parse(body);
			if(tweets.length > 0) {
				tweet_emitter.emit("tweets", tweets);
			}
		});
	});

	request.close();
}

setInterval(get_tweets, 5000);
</pre>
<p>First, we create an HTTP client on port 80 to api.twitter.com, and create a new <code>EventEmitter</code>.  The <code>get_tweets</code> function creates an HTTP &#8220;GET&#8221; request to Twitter&#8217;s public timeline, and adds an event listener that will be triggered when Twitter&#8217;s servers respond.  Because Node.js is asynchronous, the data in the body of the response comes in chunks, which are picked up by the response&#8217;s &#8220;data&#8221; listener.  This listener simply appends the chunk to the <code>body</code> variable.  Once all of the chunks have come in, the &#8220;end&#8221; listener is triggered, and we parse the incoming JSON data.  If more than one tweet is returned, we <code>emit</code> the &#8220;tweets&#8221; event on our <code>tweet_emitter</code>, and pass in the array of new tweets.  This will trigger all of the event listeners listening for the &#8220;tweets&#8221; event, and send the new tweets to each client.  We retreive the new tweets every five seconds, by using <code>setInterval</code>.</p>
<p>Finally, we need to create the HTTP server to handle requests.</p>
<pre name="code" class="js">
http.createServer(function(request, response) {
    var uri = url.parse(request.url).pathname;
    if(uri === "/stream") {

    	var listener = tweet_emitter.addListener("tweets", function(tweets) {
    		response.sendHeader(200, { "Content-Type" : "text/plain" });
    		response.write(JSON.stringify(tweets));
    		response.close();

    		clearTimeout(timeout);
    	});

    	var timeout = setTimeout(function() {
    		response.sendHeader(200, { "Content-Type" : "text/plain" });
    		response.write(JSON.stringify([]));
    		response.close();

    		tweet_emitter.removeListener(listener);
    	}, 10000);

    }
    else {
    	load_static_file(uri, response);
    }
}).listen(8080);

sys.puts("Server running at http://localhost:8080/");
</pre>
<p>Just as we did with our static file server, we create an HTTP server that listens on port 8080.  We parse the requested URL, and if the URL is equal to <code>"/stream"</code>, we will handle it, otherwise we pass the request off to our static file server.  Streaming consists of creating a listener to listen for new tweets on our <code>tweet_emitter</code>, which will be triggered by our <code>get_tweets</code> function.  We also create a timer to kill requests tht last over 10 seconds by sending them an empty array.  When new tweets come in, we send the tweets as JSON data, and clear the timer.  You will see how this works better after seeing the client side code, which is below.  Save it as <code>test.html</code> in the same directory as the server side JavaScript.</p>
<pre name="code" class="html">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
	&lt;head&gt;
		&lt;title&gt;Tweet Streamer&lt;/title&gt;
		&lt;script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"&gt;&lt;/script&gt;
	&lt;/head&gt;
	&lt;body&gt;
		&lt;ul id="tweets"&gt;&lt;/ul&gt;
		&lt;script type="text/javascript"&gt;
		var tweet_list = $("#tweets");

		function load_tweets() {
			$.getJSON("/stream", function(tweets) {
				$.each(tweets, function() {
					$("&lt;li&gt;").html(this.text).prependTo(tweet_list);
				});
				load_tweets();
			});
		}

		setTimeout(load_tweets, 1000);
		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Here, we have a simple HTML page that imports the jQuery library and defines an unordered list to put the tweets in.  Our client side JavaScript caches the tweet list, and runs the <code>load_tweets</code> function after one second.  This gives the browser enough time to finish loading the page before we start the AJAX request to the server.  The <code>load_tweets</code> function is very simple: It uses jQuery&#8217;s <code>getJSON</code> function to load <code>/stream</code>.  When a response comes in, we loop through all of the tweets and prepend them to the tweet list.  Then, we call <code>load_tweets</code> again.  This effectively creates a loop that loads new tweets, which times out after ten seconds because of the timeout on the server.  Whenever there are new tweets, they are pushed to the client which maintains a continuous connection to the server.  This technique is called long-polling.</p>
<p>If you run the server using <code>node</code> and go to <code>http://localhost:8080/test.html</code>, you will see the Twitter public timeline stream into your browser.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.cdn.plus.org/601_node/5.jpg" border="0" /></div>
<hr />
<h2>Next Steps </h2>
<p>Node.js is a very exciting technology that makes it easy to create high performance real time applications.  I hope you can see its benefit, and can use it in some of your own applications.  Because of Node&#8217;s great module system, it is easy to use prewritten code in your application, and there are many third party modules available for just about everything &#8211; including database connection layers, templating engines, mail clients, and even entire frameworks connecting all of these things together.  You can see a complete list of modules on the <a href="http://wiki.github.com/ry/node/modules">Node.js wiki</a>, and more Node tutorials can be found on <a href="http://howtonode.org/">How To Node</a>.  I would also recommend that you watch a video from JSConf, in which Ryan Dahl, the creator of Node, describes the design philosophy behind Node.  That is available <a href="http://blip.tv/file/2899135">here</a>.</p>
<p>I hope you have enjoyed this tutorial.  If you have any comments, you can leave one here or send me a message on <a href="http://twitter.com/devongovett">Twitter</a>.  Happy noding!</p>

<p><a href="http://feedads.g.doubleclick.net/~a/wmmZruXav-KgIjnqRy6hb61SA4s/0/da"><img src="http://feedads.g.doubleclick.net/~a/wmmZruXav-KgIjnqRy6hb61SA4s/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/wmmZruXav-KgIjnqRy6hb61SA4s/1/da"><img src="http://feedads.g.doubleclick.net/~a/wmmZruXav-KgIjnqRy6hb61SA4s/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nettuts?a=ndZ5-XeHlao:U3WClRUQdOs:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=ndZ5-XeHlao:U3WClRUQdOs:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nettuts?i=ndZ5-XeHlao:U3WClRUQdOs:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=ndZ5-XeHlao:U3WClRUQdOs:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nettuts?i=ndZ5-XeHlao:U3WClRUQdOs:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=ndZ5-XeHlao:U3WClRUQdOs:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/nettuts?i=ndZ5-XeHlao:U3WClRUQdOs:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=ndZ5-XeHlao:U3WClRUQdOs:TzevzKxY174"><img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/nettuts/~4/ndZ5-XeHlao" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/javascript-ajax/learning-serverside-javascript-with-node-js/feed/</wfw:commentRss>
		<slash:comments>38</slash:comments>
		<feedburner:origLink>http://net.tutsplus.com/tutorials/javascript-ajax/learning-serverside-javascript-with-node-js/</feedburner:origLink></item>
		<item>
		<title>How to Build a Lava-Lamp Style Navigation Menu</title>
		<link>http://feedproxy.google.com/~r/nettuts/~3/D6XYq_6zWvM/</link>
		<comments>http://net.tutsplus.com/tutorials/html-css-techniques/how-to-build-a-lava-lamp-style-navigation-menu/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 20:17:50 +0000</pubDate>
		<dc:creator>Jeffrey Way</dc:creator>
				<category><![CDATA[HTML & CSS]]></category>
		<category><![CDATA[JavaScript & AJAX]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[menu]]></category>
		<category><![CDATA[navigation]]></category>
		<category><![CDATA[navigation menu]]></category>
		<category><![CDATA[Videos]]></category>

		<guid isPermaLink="false">http://net.tutsplus.com/?p=10015</guid>
		<description><![CDATA[
A couple weeks ago, I created a screencast that demonstrated how to build a three-level navigation menu. In a response email, one of our readers requested a tutorial on how to build a lava-lamp style menu. Luckily, it&#8217;s quite a simple task, especially when using a JavaScript library. We&#8217;ll build one from scratch today.



  [...]]]></description>
			<content:encoded><![CDATA[<p>
A <a href="http://net.tutsplus.com/tutorials/design-tutorials/how-to-build-and-enhance-a-3-level-navigation-menu/">couple weeks ago</a>, I created a screencast that demonstrated how to build a three-level navigation menu. In a response email, one of our readers requested a tutorial on how to build a lava-lamp style menu. Luckily, it&#8217;s quite a simple task, especially when using a JavaScript library. We&#8217;ll build one from scratch today.
</p>
<p><span id="more-10015"></span></p>
<div class="tutorial_image">
   <img src="http://nettuts.s3.cdn.plus.org/600_spasticNav/screenshot.jpg" alt="Screenshot" />
</div>
<h2>Prefer a Screencast? </h2>
<div class="tutorial_image">
<embed src="http://blip.tv/play/gcMVgc2HOgA%2Em4v" type="application/x-shockwave-flash" width="600" height="390" allowscriptaccess="always" allowfullscreen="true"></embed>
</div>
<h2><span>Step 1</span> Create the Mark-up</h2>
<p>
Before we can create this neat functionality, we need a base from which to work from. In your favorite code editor, create an unordered list for your navigation, and import both jQuery and jQuery UI, via Google.
</p>
<pre name="code" class="html">
&lt;!DOCTYPE html>

&lt;html lang="en">
&lt;head>
	&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	&lt;title>SpasticNav  Plugin&lt;/title>
	&lt;link rel="stylesheet" href="css/style.css" type="text/css" media="screen" />
&lt;/head>
&lt;body>

&lt;div id="container">

	&lt;ul id="nav">
		&lt;li id="selected">&lt;a href="#">Home&lt;/a>&lt;/li>
		&lt;li>&lt;a href="#">About&lt;/a>&lt;/li>
		&lt;li>&lt;a href="#">Blog&lt;/a>&lt;/li>
		&lt;li>&lt;a href="#">More About My Portfolio&lt;/a>&lt;/li>
		&lt;li>&lt;a href="#">Contact&lt;/a>&lt;/li>
	&lt;/ul>

&lt;/div>

&lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js" type="text/javascript">&lt;/script>	

&lt;script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js">&lt;/script>

&lt;/body>
&lt;/html>
</pre>
<p>Note how we gave an id of &#8220;selected&#8221; to the home page. This is fairly standard in most websites; it allows use to target the current page, and style that particular list item accordingly. </p>
<p>Next, we must decide how to best implement the lava-lamp functionality. To allow for reusability, we&#8217;ll package this little script into a plugin, and call it like: </p>
<pre name="code" class="js">
$('#nav').spasticNav();
</pre>
<p>
Since we&#8217;ve decided to build a plugin, let&#8217;s go ahead and create a new file for that script, and reference it in our mark-up. We&#8217;ll call it jquery.spasticNav.js.
</p>
<pre name="code" class="html">
&lt;script type="text/javascript" src="js/jquery.spasticNav.js">&lt;/script>	

&lt;script type="text/javascript">
$('#nav').spasticNav();
&lt;/script>
&lt;/body>
</pre>
<h2><span>Step 2</span> Beginning the Plugin</h2>
<p>
To reduce the number of global variables that we must create, as well as remove any possibilities of the $ symbol clashing with other JavaScript libraries, let&#8217;s wrap our plugin in a self-executing anonymous function.
</p>
<pre name="code" class="js">
(function($) {

})(jQuery);
</pre>
<p>Now, jQuery will be passed into our plugin, and will be represented via the $ symbol. </p>
<p>Next, it&#8217;s generally a best practice to give the users of the plugin as much flexibility as possible. As such, we&#8217;ll give them the option of passing in an object-literal when they call the plugin to override a handful of settings. As I see it, they should be able to: </p>
<ul>
<li>Set the amount of overlap for our little blob. This refers to how much the blob will exceed the height of the navigation menu. </li>
<li>Set the speed </li>
<li>Set a reset, which causes the blob to move back to the current page item (assuming that the user never clicks on a link) </li>
<li>Set the color of the blob. This can be accomplished with CSS, but it&#8217;s a nice convenience, nonetheless. </li>
<li>Set the easing option. </li>
</ul>
<p>Now, we&#8217;ll name our plugin, and make it equal to a function. $.fn is simply an alias for jquery.prototype. </p>
<pre name="code" class="js">
$.fn.spasticNav = function(options) {

};
</pre>
<p>Knowing that we&#8217;ll be allowing these overrides, we must make sure that we accept an &#8220;options&#8221; parameter. </p>
<h2><span>Step 3</span> Configuration Options </h2>
<p>Now that we&#8217;ve named our plugin, the next step is to create the configuration options. </p>
<pre name="code" class="js">
options = $.extend({
	overlap : 20,
	speed : 500,
	reset : 1500,
	color : '#0b2b61',
	easing : 'easeOutExpo'
}, options);
</pre>
<p>Above, we&#8217;re taking the options variable, setting some default properties and values, and then extending it with whatever (if anything) the user passes in when they call the plugin. That way, the options they pass will override our default settings. For example, if, when I call this plugin, I pass: </p>
<pre name="code" class="js">
$('#nav').spasticNav({
   speed : 2000,
   easing : 'easeOutElastic'
});
</pre>
<p>
Those two properties will override the default settings, while the remainder of the options will remain the same.
</p>
<h2><span>Step 4</span> Implementing the Functionality </h2>
<p>
Now, we&#8217;re ready to cycle through each element that was passed to this plugin, and implement the lava-lamp functionality. Remember, we can&#8217;t assume that the user is going to pass a single element to this plugin. They could, if they wanted, reference a class, which refers to multiple items that should receive this functionality. As such, we&#8217;ll call this.each to iterate over each item in the wrapped set.
</p>
<pre name="code" class="js">
return this.each(function() {

});
</pre>
<p>Within this function, we&#8217;ll create some variables. Not all of them will immediately have values, but since the JavaScript engine will hoist all variable names to the top of the function anyways (behind the scenes), it&#8217;s generally a best practice to declare them at the top, and then initialize them later. </p>
<pre name="code" class="js">
var nav = $(this),
	currentPageItem = $('#selected', nav),
	blob,
	reset;
</pre>
<ul>
<li><strong>nav : </strong> &#8220;Caches&#8221; <em>this</em>, wrapped in the jQuery object. </li>
<li><strong>currentPageItem : </strong> Contains the list item with an id of selected. We pass a second parameter to set the context to search from. That way, we don&#8217;t have to traverse the entire dom to find this element.  </li>
<li><strong>blob : </strong> For lack of a better word, this variable will reference the highlighter, that will follow our mouse when we hover over the menu. </li>
<li><strong>reset : </strong> This will store a reference to the setTimeout function that will create later. It&#8217;s needed in order to call clearTimeout. More on this soon&#8230; </li>
</ul>
<p>Now that we&#8217;ve declared/initialized our variables, let&#8217;s create the actual blob, so to speak. </p>
<pre name="code" class="js">
$('&lt;li id="blob">&lt;/li>').css({
	width : currentPageItem.outerWidth(),
	height : currentPageItem.outerHeight() + options.overlap,
	left : currentPageItem.position().left,
	top : currentPageItem.position().top - options.overlap / 2,
	backgroundColor : options.color
}).appendTo(this);
</pre>
<p>
The reason why we&#8217;re calling the CSS method, rather than simply adding a class, is because these values will vary depending on the current page&#8217;s list item. As such, we must use JavaScript to retrieve they values.
</p>
<ul>
<li><strong>width: </strong> Get the width of currentPageItem, including any borders and padding. </li>
<li><strong>height: </strong> Get the height of currentPageItem, including any borders and padding. Also, add the amount of overlap, to make the blob extend outside of the menu. </li>
<li><strong>left: </strong> Sets the left property of the blob equal to the left position of the currentPageItem. (We must set a positioning context in our CSS for this value to take effect.)</li>
<li><strong>top: </strong> Sets the top value as well, and vertically centers the blob. </li>
<li><strong>backgroundColor: </strong> Sets the background color. </li>
</ul>
<p>Finally, we append this new list item to <em>this</em>, or #nav. </p>
<p>Next, we need to store a reference to #blob. That way, we don&#8217;t have to search the DOM everytime we wish to access it. We declared the <em>blob</em> variable at the top of the function. Now, let&#8217;s initialize it. </p>
<pre name="code" class="js">
blob = $('#blob', nav);
</pre>
<h2><span>Step 5</span> The Hover Event </h2>
<p>
We must now &#8220;listen&#8221; for when the user hovers over one of the list items (excluding the blob of course) in our navigation menu. When they do, we&#8217;ll set the width and left properties of the blob equal to that of the currently hovered list item.
</p>
<pre name="code" class="js">
$('li:not(#blob)', nav).hover(function() {
	// mouse over
	clearTimeout(reset);
	blob.animate(
		{
			left : $(this).position().left,
			width : $(this).width()
		},
		{
			duration : options.speed,
			easing : options.easing,
			queue : false
		}
	);
}, function() {
	// mouse out
	reset = setTimeout(function() {
		blob.animate({
			width : currentPageItem.outerWidth(),
			left : currentPageItem.position().left
		}, options.speed)
	}, options.reset);

});
</pre>
<p>To summarize the script above&#8230; </p>
<ul>
<li>Get all list items &#8211; not the #blob &#8211; within the navigation menu, and when they&#8217;re hovered over, run a function. </li>
<li>Animate the blob, and set its left and width values equal to that of the hovered list item. </li>
<li>Pass an object literal as the second parameter of animate, and set the duration and easing equal to what we set in our configuration options. Set queue to false to prevent animation build-up. </li>
<li>When they mouse out, call setTimeOut, which will push the blob back to the current page item. If we didn&#8217;t do this, and the user didn&#8217;t click on a navigation link, the menu would show that they were on<br />
a different page entirely. This will, after a second or so, animate the blob back to currentPageItem. </li>
</ul>
<p>And that&#8217;s all there is to it! This is a super simple plugin. The next step is to style our navigation menu. </p>
<h2><span>Step 6</span> Styling the Menu </h2>
<p>Without any styling, our menu should look similar to this: </p>
<div class="tutorial_image">
   <img src="http://nettuts.s3.cdn.plus.org/600_spasticNav/unstyled.png" alt="Unstyled mark-up" />
</div>
<p>Let&#8217;s first style the &#8220;nav&#8221; ul. Open your style.css file, and add: </p>
<pre name="code" class="css">
#nav {
	position: relative;
	background: #292929;
	float: left;
}
</pre>
<div class="tutorial_image">
   <img src="http://nettuts.s3.cdn.plus.org/600_spasticNav/two-nav.png" alt="Styling the navigation menu" />
</div>
<p>
Next, we&#8217;ll style each list item.
</p>
<pre name="code" class="css">
#nav li {
	float: left;
	list-style: none;
	border-right: 1px solid #4a4a4a;
	border-left: 1px solid black;
}
</pre>
<p>This simply floats each list item to the left, and adds a border to each side. </p>
<div class="tutorial_image">
   <img src="http://nettuts.s3.cdn.plus.org/600_spasticNav/three-navli.png" alt="Styling the list items" />
</div>
<p>Moving along, we next must style the anchor tags within our navigation menu. </p>
<pre name="code" class="css">
#nav li a {
	color: #e3e3e3;
	position: relative;
	z-index: 2;
	float: left;
	font-size: 30px;
	font-family: helvetica, arial, sans-serif;
	text-decoration: none;
	padding: 30px 45px;
}
</pre>
<p>We&#8217;re setting a color, floating them to the left, setting some font values, and a healthy amount of padding. Take note of the z-index property. This is a necessity, and will be explained shortly. However, remember that, in order to adjust the z-index, we must set a positioning context, which we&#8217;ve done. </p>
<div class="tutorial_image">
   <img src="http://nettuts.s3.cdn.plus.org/600_spasticNav/four-nava.png" alt="Styling the anchor tags" />
</div>
<p>Because we&#8217;re not implementing a full reset stylesheet, let&#8217;s ensure that we zero out any default margins and padding on our ul and li, just to save any potential headaches. </p>
<pre name="code" class="css">
ul, li {
	margin: 0; padding: 0;
}
</pre>
<p>The last step is to style the blob itself! </p>
<pre name="code" class="css">
#blob {
	border-right: 1px solid #0059ec;
	border-left: 1px solid #0059ec;
	position: absolute;
	top: 0;
	z-index : 1;
	background: #0b2b61;
	background: -moz-linear-gradient(top, #0b2b61, #1153c0);
	background: -webkit-gradient(linear, left top, left bottom, from(#0b2b61), to(#1153c0));
	-moz-border-radius: 4px;
	-webkit-border-radius: 4px;
	-moz-box-shadow: 2px 3px 10px #011331;
	-webkit-box-shadow: 2px 3px 10px #011331;
}
</pre>
<p>Once again, we set some pretty colors for our borders, and add some background colors (including CSS3 gradients/borders/shadows for Firefox and Safari/Chrome). Once again, we see that z-index property. Without this, the blob will display above all of the text in the navigation menu. To counter this, we must be sure that its z-index property is LOWER than the list item&#8217;s! We also must set the position to absolute in order to adjust its top and left values with our plugin. </p>
<div class="tutorial_image">
   <img src="http://nettuts.s3.cdn.plus.org/600_spasticNav/screenshot.jpg" alt="Screenshot" />
</div>
<h2>Conclusion</h2>
<p>That&#8217;s all there is to it! With minimal effort, we&#8217;ve created a really neat looking navigation menu from scratch. Let me know if you have any questions! Thanks for reading and watching. </p>

<p><a href="http://feedads.g.doubleclick.net/~a/zz6Sof1P3eoUnVEXnR8OWsz2UZw/0/da"><img src="http://feedads.g.doubleclick.net/~a/zz6Sof1P3eoUnVEXnR8OWsz2UZw/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/zz6Sof1P3eoUnVEXnR8OWsz2UZw/1/da"><img src="http://feedads.g.doubleclick.net/~a/zz6Sof1P3eoUnVEXnR8OWsz2UZw/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nettuts?a=D6XYq_6zWvM:q0e-MSVLTQI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=D6XYq_6zWvM:q0e-MSVLTQI:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nettuts?i=D6XYq_6zWvM:q0e-MSVLTQI:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=D6XYq_6zWvM:q0e-MSVLTQI:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nettuts?i=D6XYq_6zWvM:q0e-MSVLTQI:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=D6XYq_6zWvM:q0e-MSVLTQI:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/nettuts?i=D6XYq_6zWvM:q0e-MSVLTQI:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=D6XYq_6zWvM:q0e-MSVLTQI:TzevzKxY174"><img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/nettuts/~4/D6XYq_6zWvM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/html-css-techniques/how-to-build-a-lava-lamp-style-navigation-menu/feed/</wfw:commentRss>
		<slash:comments>95</slash:comments>
		<feedburner:origLink>http://net.tutsplus.com/tutorials/html-css-techniques/how-to-build-a-lava-lamp-style-navigation-menu/</feedburner:origLink></item>
		<item>
		<title>Quick Tip: HTML5 Video with a Fallback to Flash</title>
		<link>http://feedproxy.google.com/~r/nettuts/~3/YtSdhZaIP0s/</link>
		<comments>http://net.tutsplus.com/tutorials/html-css-techniques/quick-tip-html-5-video-with-a-fallback-to-flash/#comments</comments>
		<pubDate>Fri, 12 Mar 2010 18:52:27 +0000</pubDate>
		<dc:creator>Jeffrey Way</dc:creator>
				<category><![CDATA[HTML & CSS]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[Videos]]></category>

		<guid isPermaLink="false">http://net.tutsplus.com/?p=9982</guid>
		<description><![CDATA[
In this video quick tip, we&#8217;ll review how to work with HTML 5 video in your own projects. Because older browsers and Internet Explorer do not understand the &#60;video> element, we must also find a way to serve a Flash file to viewers who are utilizing those browsers.





Viewing Options

Screenr (Mp4)

Unfortunately, much like HTML 5 audio, [...]]]></description>
			<content:encoded><![CDATA[<p>
In this video quick tip, we&#8217;ll review how to work with HTML 5 video in your own projects. Because older browsers and Internet Explorer do not understand the &lt;video> element, we must also find a way to serve a Flash file to viewers who are utilizing those browsers.
</p>
<p><span id="more-9982"></span></p>
<div class="tutorial_image">
<object width="600" height="450"><param name="movie" value="http://www.youtube.com/v/cO6wSBhPtOY&#038;hl=en_US&#038;fs=1&#038;hd=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/cO6wSBhPtOY&#038;hl=en_US&#038;fs=1&#038;hd=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="600" height="450"></embed></object>
</div>
<h3>Viewing Options</h3>
<ul>
<li><a href="http://screenr.com/Msg">Screenr (Mp4)</a></li>
</ul>
<p>Unfortunately, <a href="http://net.tutsplus.com/tutorials/html-css-techniques/quick-tip-the-html-5-audio-element/">much like HTML 5 audio</a>, Firefox and Safari/Chrome don&#8217;t quite agree when it comes to the file format for videos. As such, if you wish to take advantage of HTML 5 video at this time, you&#8217;ll need to create three versions of your video. </p>
<ul>
<li><strong>.OGG</strong>: This will make Firefox happy. You can use <a href="http://www.videolan.org/vlc/">VLC</a> (File -> Streaming/Export Wizard) to convert your video to this format easily. </li>
<li><strong>.MP4</strong>: Many screencasting tools automatically export to Mp4; so you can use that file for Safari and Chrome. </li>
<li><strong>.FLV/.SWF</strong>: Not all browsers support HTML 5 video, of course. To compensate, make sure that you add a fallback Flash version as well.
</ul>
<pre name="code" class="html">
&lt;!DOCTYPE html>

&lt;html lang="en">
&lt;head>
	&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	&lt;title>untitled&lt;/title>
&lt;/head>
&lt;body>
&lt;video controls width="500">
	&lt;!-- if Firefox -->
	&lt;source src="video.ogg" type="video/ogg" />
	&lt;!-- if Safari/Chrome-->
	&lt;source src="video.mp4" type="video/mp4" />
	&lt;!-- If the browser doesn't understand the &lt;video> element, then reference a Flash file. You could also write something like "Use a Better Browser!" if you're feeling nasty. (Better to use a Flash file though.) -->
	&lt;embed src="http://blip.tv/play/gcMVgcmBAgA%2Em4v" type="application/x-shockwave-flash" width="1024" height="798" allowscriptaccess="always" allowfullscreen="true">&lt;/embed>
&lt;/video>
&lt;/body>
&lt;/html>
</pre>
<p>There are a handful of attributes available to the &lt;video> element. </p>
<ul>
<li><strong>Controls: </strong> Display the play/stop buttons?
<li><strong>Poster: </strong> The value can be a path to an image, that will serve as the display of the video before it is played. </li>
<li><strong>AutoPlay: </strong> Immediately play the video when the page is loaded? </li>
<li><strong>Width: </strong> The desired width of the video. By default, the browser will automatically detect the dimensions of the supplied video. </li>
<li><strong>Height: </strong> The desired height of the video. </li>
<li><strong>Src: </strong> The path to the video file. It&#8217;s better to use the &lt;source> child element instead for this task. </li>
</ul>
<h3>Dos and Don&#8217;ts of HTML 5 Video</h3>
<ol>
<li><strong>DO </strong> create three version of your video to make Firefox, Safari/Chrome, and IE happy. (.ogg, .mp4, .flv/.swf) </li>
<li><strong>DO NOT </strong> omit one of these formats. Unfortunately, you can&#8217;t easily choose to serve HTML 5 video to Firefox, and the Flash fallback to Safari. Safari understands the &lt;video> element, and will expect to find a suitable video format to load. If one is not found, it will display an empty player. </li>
<li><strong>DO </strong> keep in mind that full-screen support will not work in Safari and Chrome. However, with the release of Firefox 3.6, you can right-click, and view in full screen. </li>
<li><strong>DO</strong> remember that the reason why IE loads the Flash file instead is because it does not understand what the &lt;video> element is. However, if a browser DOES understand that element, it will expect to find a suitable file to load. </li>
</ol>
<p><em>Please note that, if I can find a suitable work-around for the full-screen problem, we&#8217;ll be using this method on Nettuts+ in the near future! </em></p>

<p><a href="http://feedads.g.doubleclick.net/~a/cAErp3RQoBpRnK-XcXMLB5Y4lrQ/0/da"><img src="http://feedads.g.doubleclick.net/~a/cAErp3RQoBpRnK-XcXMLB5Y4lrQ/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/cAErp3RQoBpRnK-XcXMLB5Y4lrQ/1/da"><img src="http://feedads.g.doubleclick.net/~a/cAErp3RQoBpRnK-XcXMLB5Y4lrQ/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nettuts?a=YtSdhZaIP0s:XtwtXFfXmgo:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=YtSdhZaIP0s:XtwtXFfXmgo:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nettuts?i=YtSdhZaIP0s:XtwtXFfXmgo:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=YtSdhZaIP0s:XtwtXFfXmgo:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nettuts?i=YtSdhZaIP0s:XtwtXFfXmgo:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=YtSdhZaIP0s:XtwtXFfXmgo:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/nettuts?i=YtSdhZaIP0s:XtwtXFfXmgo:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nettuts?a=YtSdhZaIP0s:XtwtXFfXmgo:TzevzKxY174"><img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/nettuts/~4/YtSdhZaIP0s" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/html-css-techniques/quick-tip-html-5-video-with-a-fallback-to-flash/feed/</wfw:commentRss>
		<slash:comments>40</slash:comments>
		<feedburner:origLink>http://net.tutsplus.com/tutorials/html-css-techniques/quick-tip-html-5-video-with-a-fallback-to-flash/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic Page Served (once) in 2.530 seconds -->
