<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="http://feeds.feedburner.com/~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:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Notes from Phazm</title>
	
	<link>http://www.phazm.com/notes</link>
	<description>Just another WordPress weblog</description>
	<pubDate>Wed, 05 Mar 2008 04:56:45 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/NotesFromPhazm" type="application/rss+xml" /><item>
		<title>Easy as Pie - Ajax Requests (Part 2)</title>
		<link>http://feeds.feedburner.com/~r/NotesFromPhazm/~3/245912749/</link>
		<comments>http://www.phazm.com/notes/easy-as-pie/easy-as-pie-ajax-requests-part-2/#comments</comments>
		<pubDate>Wed, 05 Mar 2008 04:56:45 +0000</pubDate>
		<dc:creator>Jon Hughes</dc:creator>
		
		<category><![CDATA[Ajax]]></category>

		<category><![CDATA[Easy As Pie]]></category>

		<category><![CDATA[MySQL]]></category>

		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Jon Hughes]]></category>

		<category><![CDATA[serverside ajax]]></category>

		<guid isPermaLink="false">http://www.phazm.com/notes/easy-as-pie/easy-as-pie-ajax-requests-part-2/</guid>
		<description><![CDATA[

This article is the fourth in a continuing series of DIY tutorials, which aims to make things as simple as possible.
To be honest, I wasn't planning on writing this article, but it would seem that there are quite  a few people that want to know - what does the server-side code for the Ajax [...]]]></description>
			<content:encoded><![CDATA[<img src="/images/blog/easy-as-pie.png" alt="Easy As Pie" class="fr" />
<!--<p class="alert">If you enjoy this article, please <a href="http://www.digg.com/programming/Easy_as_Pie_Working_with_a_MySQL_Database">digg it</a>.</p>-->
<p>This article is the fourth in a continuing series of <abbr title="Do It Yourself">DIY</abbr> tutorials, which aims to make things as simple as possible.</p>
<p>To be honest, I wasn't planning on writing this article, but it would seem that there are <a href="http://www.phazm.com/notes/productivity/easy-as-pie-ajax-requests#comment-127">quite</a>  <a href="http://www.phazm.com/notes/productivity/easy-as-pie-ajax-requests#comment-280">a</a> <a href="http://www.phazm.com/notes/productivity/easy-as-pie-ajax-requests#comment-281">few</a> <a href="http://www.phazm.com/notes/productivity/easy-as-pie-ajax-requests#comment-359">people</a> <a href="http://www.phazm.com/notes/productivity/easy-as-pie-ajax-requests#comment-393">that</a> want to know - <strong>what does the server-side code for the Ajax article look like?</strong>
<p>In the <a href="http://www.phazm.com/notes/productivity/easy-as-pie-ajax-requests/" title="Easy as Pie - Ajax Requests">previous Ajax article</a> I outlined how to make a simple voting script, and a simple 'shoutbox' using Ajax. If you didn't read that post, I recommend doing so now, before reading this one.</p>
<p>It's always a bit harder to post server-side code, because there are a lot of ways you can do a something, and many people think their way is the better than any other. So let me just say that while there may be other ways to do things, this way works just fine. Anyway, back to your regularly scheduled program.</p>
<p>In this session, you are going to learn how to work the backend (in this case, PHP) for Ajax requests.</p>
<span id="more-23"></span>
<h4>Previous articles in this series</h4>
<ul>
<li><a href="http://www.phazm.com/notes/productivity/easy-as-pie-ajax-requests/" title="Easy as Pie - Ajax Requests">[Easy as Pie] Ajax Requests</a>
<li><a href="http://www.phazm.com/notes/javascript/easy-as-pie-unobtrusive-javascript/" title="Easy as Pie - Unobtrusive JavaScript">[Easy as Pie] Unobtrusive JavaScript</a>
<li><a href="http://www.phazm.com/notes/easy-as-pie/easy-as-pie-working-with-databases/" title="Easy as Pie - Working With A Database">[Easy as Pie] Working With A Database</a>
</ul>
<h4>What is PHP?</h4>
<p><a href="http://en.wikipedia.org/wiki/PHP" title="Wikipedia page for 'PHP'"><acronym title="PHP: Hypertext Preprocessor">PHP</acronym></a> is a server-side language, which means the server translates the code before sending to back to you. I'm no good at drawing diagrams, so imagine two computer-looking boxes. One of the boxes (the client, that's your browser) sends a request over to the other box (which is the server) which runs the server-side code, which then replies to your orinigal request with whatever the result is. Pretty simple. Other examples of server-side languages are ASP Classic, ASP.NET, Ruby on Rails and Coldfusion. If you want to learn more about server-side languages, you can read about them on the <a href="http://en.wikipedia.org/wiki/Server-side_scripting" title="Wikipedia page for 'Server-side Scripting'">Wikipedia page for 'Server-side Scripting'</a>.</p>
<p>So to not confuse anyone, I will be using the same examples from the last Ajax article (the fact that the code is already written played no part in this decision. Really.)</p>
<h4>Voting Script</h4>
<p>Okay, so here's the voting script:</p>
<div id="votes">
<!--Yes, these events are obtrusive, but it's only an example!  C'mon! -->
<a href="javascript:void(0)" onclick="fillElementId('/landfill/CallMe.php','link1','link=1')" id="link1">I have 6934 votes</a> 
<a href="javascript:void(0)" onclick="fillElementId('/landfill/CallMe.php','link2','link=2')" id="link2">I haz 6907</a>

</div>
<p>Click on either the cat or the dog to vote for them. You can vote multiple times, so have a blast. Continue reading when you've had your fill.</p>
<p>Fun stuff. I'm not going to show the Ajax part of this example here (as I already did so in the <a href="http://www.phazm.com/notes/productivity/easy-as-pie-ajax-requests/" title="Easy as Pie - Ajax Requests">previous article</a>) so first, here's the database query you will need to run to set up the database:</p>
<pre class="sql code" title="code">CREATE TABLE `clicks` (                                 
           `id` tinyint(4) NOT NULL auto_increment,               
           `clicks` mediumint(9) default 0,                     
           PRIMARY KEY  (`id`)                                    
         )</pre>
<p>See <a href="http://www.phazm.com/notes/easy-as-pie/easy-as-pie-working-with-databases/" title="Easy as Pie - Working With A Database">[Easy as Pie] Working With A Database</a> for more information on how databases work and help on setting up your first script using one.</p>
<p>Now create two rows by running:</p>
<pre class="sql code" title="code">INSERT INTO `clicks` (`id`,`clicks`) VALUES ( '1',0)
INSERT INTO `clicks` (`id`,`clicks`) VALUES ( '2',0)</pre>
<p>And here's the PHP code for <a href="/landfill/script/CallMe.zip" title="CallMe.php download">CallMe.php</a>:</p>
<pre class="php code" title="code">&lt;?php
$user=&quot;username&quot;;
$password=&quot;password&quot;;
$database=&quot;database&quot;;
$votes = mysql_connect('localhost',$user,$password);
@mysql_select_db($database) or die( &quot;Unable to select database&quot;);
if($_REQUEST['link'] == &quot;1&quot;) {
	$query=&quot;SELECT clicks FROM clicks WHERE id = 1&quot;;
} elseif($_REQUEST['link'] == &quot;2&quot;) {
	$query=&quot;SELECT clicks FROM clicks WHERE id = 2&quot;;
} else {
	$query=&quot;SELECT clicks from clicks&quot;;
	$result = mysql_query($query);
	$votes1 = mysql_result($result,0);
	$votes2 = mysql_result($result,1);
}
if($_REQUEST['link'] != &quot;&quot;) {
	$result = mysql_query($query);
	$clicks = mysql_result($result,0);
	$newClicks = $clicks+1;
}
if($_REQUEST['link'] == &quot;1&quot;) {
	mysql_query(&quot;UPDATE clicks set clicks = &quot; . $newClicks . &quot; where id = 1&quot;);
} elseif($_REQUEST['link'] == &quot;2&quot;) {
	mysql_query(&quot;UPDATE clicks set clicks = &quot; . $newClicks . &quot; where id = 2&quot;);
}
mysql_close($votes);
if($_REQUEST['link'] == &quot;1&quot;) {
   	echo(&quot;I have &quot; . $newClicks . &quot; votes&quot;);
} elseif($_REQUEST['link'] == &quot;2&quot;) {
	echo(&quot;I haz &quot; . $newClicks);
} else {
?&gt;
&lt;a href=&quot;javascript:void(0)&quot; onclick=&quot;fillElementId('/landfill/CallMe.php','link1','link=1')&quot; id=&quot;link1&quot;&gt;I have &lt;?php echo($votes1); ?&gt; votes&lt;/a&gt; 
&lt;a href=&quot;javascript:void(0)&quot; onclick=&quot;fillElementId('/landfill/CallMe.php','link2','link=2')&quot; id=&quot;link2&quot;&gt;I haz &lt;?php echo($votes2); ?&gt;&lt;/a&gt;
&lt;?php
}
?&gt;</pre>
<p>Now I'll go through and explain each block of code:</p>
<pre class="php code" title="code">$user=&quot;username&quot;;
$password=&quot;password&quot;;
$database=&quot;database&quot;;
$votes = mysql_connect('localhost',$user,$password);
@mysql_select_db($database) or die( &quot;Unable to select database&quot;);</pre>
<p>This creates a connection to the database server.</p>
<pre class="php code" title="code">if($_REQUEST['link'] == &quot;1&quot;) {
	$query=&quot;SELECT clicks FROM clicks WHERE id = 1&quot;;
} elseif($_REQUEST['link'] == &quot;2&quot;) {
	$query=&quot;SELECT clicks FROM clicks WHERE id = 2&quot;;
}</pre>
<p>The <span class="code">$_REQUEST['link']</span> is getting the value of <span class="code">link</span> which was posted by the Ajax. This section defines which option the user voted for.</p>
<pre class="php code" title="code">} else {
	$query=&quot;SELECT clicks from clicks&quot;;
	$result = mysql_query($query);
	$votes1 = mysql_result($result,0);
	$votes2 = mysql_result($result,1);
}</pre>
<p>The <span class="code">else</span> in this code means, "if the user didn't click on '1' or '2' then run this." Then it creates a query that selects the <span class="code">clicks</span> from the <span class="code">clicks</span> table. It also sets the values of the <span class="code">$votes1</span> and <span class="code">$votes2</span> variables to whatever is in first and second cell, respectively.</p>
<pre class="php code" title="code">if($_REQUEST['link'] != &quot;&quot;) {
	$result = mysql_query($query);
	$clicks = mysql_result($result,0);
	$newClicks = $clicks+1;
}</pre>
<p>The <span class="code">if</span> in this block checks to see if there was a vote cast (<span class="code">!=</span> means does not equal, so what it is asking is 'if link does not equal nothing') and if so, it will execute the code in the block.</p>
<p>The code sets the variable <span class="code">$result</span> to whatever is returned from the MySQL query, then sets <span class="code">$clicks</span> to the first returned cell, and finally sets <span class="code">$newClicks</span> to the same number as <span class="code">$clicks</span>, but adds 1.</p>
<pre class="php code" title="code">if($_REQUEST['link'] == &quot;1&quot;) {
	mysql_query(&quot;UPDATE clicks set clicks = &quot; . $newClicks . &quot; where id = 1&quot;);
} elseif($_REQUEST['link'] == &quot;2&quot;) {
	mysql_query(&quot;UPDATE clicks set clicks = &quot; . $newClicks . &quot; where id = 2&quot;);
}</pre>
<p>This block checks to see which option was voted for, and updates the database accordingly.</p>
<pre class="php code" title="code">mysql_close($votes);</pre>
<p>Because we dont need the database connection any longer, we can close it.</p>
<pre class="php code" title="code">if($_REQUEST['link'] == &quot;1&quot;) {
   	echo(&quot;I have &quot; . $newClicks . &quot; votes&quot;);
} elseif($_REQUEST['link'] == &quot;2&quot;) {
	echo(&quot;I haz &quot; . $newClicks);</pre>
<p>This outputs (via <span class="code">echo</span>) the new number of clicks on the item the user clicked on.</p>
<pre class="php code" title="code">} else {
?&gt;
&lt;a href=&quot;javascript:void(0)&quot; onclick=&quot;fillElementId('/landfill/CallMe.php','link1','link=1')&quot; id=&quot;link1&quot;&gt;I have &lt;?php echo($votes1); ?&gt; votes&lt;/a&gt; 
&lt;a href=&quot;javascript:void(0)&quot; onclick=&quot;fillElementId('/landfill/CallMe.php','link2','link=2')&quot; id=&quot;link2&quot;&gt;I haz &lt;?php echo($votes2); ?&gt;&lt;/a&gt;
&lt;?php
}</pre>
<p>This is the action that takes place when there was no vote counted (meaning the user just ran the script without voting) - This happens on the inital page load, so we can just use a php include to call it.</p>
<p>That's it for the voting script, now on to the:</p>
<h4>Shoutbox</h4>
<p>This tiny little script allows visitors to chat with you and other visitors.</p>
<div class="shoutbox">
<form action="" onsubmit="fillElementId('/landfill/FillElement.php','fillMe','say='+this.msg.value+'&amp;name='+this.name.value); this.msg.value=''; return false;">
<fieldset>
<label for="name">Name:</label>
<input type="text" name="name" id="name" />
<label for="msg">Message</label>
<input type="text" name="msg" id="msg" />
<input type="image" src="/images/sayit.png" title="Submit it!" value="Submit" class="button" />
<input type="image" src="/images/refresh.png" onclick="fillElementId('/landfill/FillElement.php','fillMe'); return false;" value="Refresh Shoutbox" title="Refresh Shoutbox" />
</fieldset>
</form>
<div id="fillMe"><ul>
<li class="alt"><strong>she</strong> said: i like it</li><li><strong>whoever</strong> said: tddhsid  id</li><li class="alt"><strong>tuit</strong> said: yuity</li><li><strong>alan chin</strong> said: hi all</li><li class="alt"><strong>asdf</strong> said: asdf</li><li><strong>NameBot</strong> said: Phazmashouten: Best. Name. Ever.</li><li class="alt"><strong>jon</strong> said: hi</li><li><strong>phoenix</strong> said: try</li><li class="alt"><strong>phoenix</strong> said: try</li><li><strong>Phazm</strong> said: Shoutbox</li></ul></div>
</div>
<p>Here's the sql statement you need to use to set up the database:</p>
<pre class="sql code" title="code">CREATE TABLE `shoutbox` (                                  
	`id` mediumint(9) NOT NULL auto_increment,               
	`ip` INT UNSIGNED default NULL,                           
	`timestamp` datetime default NULL,                       
	`message` varchar(100) default 'No Comment...',          
	`name` varchar(30) default 'Anonymous',                  
	PRIMARY KEY  (`id`))</pre>
<p>Here's the code for the <a href="/landfill/script/FillElement.zip" title="FillElement.php download">FillElement.php:</a></p>
<pre class="php code" title="code">&lt;?php
$user="username";
$password="password";
$database="database";
$shoutbox = mysql_connect('localhost',$user,$password);
@mysql_select_db($database) or die("Unable to select database");
$say = $_REQUEST['say'];
$name = $_REQUEST['name'];
if($say != "") {
	if($name == "") {
		$name = "Anonymous Coward";
	}
	$date = date("Y-m-d H:i:s");
	mysql_query("INSERT INTO shoutbox (ip,timestamp,message,name) VALUES(INET_ATON('$REMOTE_ADDR'),'$date','" . mysql_real_escape_string($say) . "','" . mysql_real_escape_string($name) . "')");
}
$query="SELECT message, name FROM shoutbox ORDER BY timestamp DESC LIMIT 10";
$result=mysql_query($query);
$num=mysql_numrows($result);
mysql_close($shoutbox);
echo("&lt;ul&gt;\n");
for ($i = 0; $i &lt; $num; $i++) {
if(($i % 2) == 1) {
	$alt = "";
} else {
	$alt = " class=\"alt\"";
}
$say = mysql_result($result,$i,"message");
$name = mysql_result($result,$i,"name");
echo("&lt;li$alt&gt;&lt;strong&gt;".htmlentities($name)."&lt;/strong&gt; said: ".htmlentities($say)."&lt;/li&gt;");
}
echo("&lt;/ul&gt;");
?&gt;</pre>
<p>Here's what's going on:</p>
<pre class="php code" title="code">$user="username";
$password="password";
$database="database";
$shoutbox = mysql_connect('localhost',$user,$password);
@mysql_select_db($database) or die("Unable to select database");</pre>
<p>Again we are setting up the connection to the database.</p>
<pre class="php code" title="code">$say = $_REQUEST['say'];
$name = $_REQUEST['name'];</pre>
<p>I am just defining the <span class="code">$say</span> and <span class="code">$name</span> variables for easy use later.</p>
<pre class="php code" title="code">if($say != "") {
	if($name == "") {
		$name = "Anonymous Coward";
	}</pre>
<p>This makes sure that <span class="code">$say</span> is set, then checks if <span class="code">$name</span> is set. If no <span class="code">$name</span> was specified, it defaults to 'Anonymous Coward'</p>
<pre class="php code" title="code">	$date = date("Y-m-d H:i:s");
	mysql_query("INSERT INTO shoutbox (ip,timestamp,message,name) VALUES(INET_ATON('$REMOTE_ADDR'),'$date','" . mysql_real_escape_string($say) . "','" . mysql_real_escape_string($name) . "')");</pre>
<p>This sets the <span class="code">$date</span> variable to the current time. This is the format it outputs it in: 2008-07-29 05:32:06. It then inserts data into the database.</p>
<p>You may notice I am running a MySQL function called <span class="code">INET_ATON</span> on the ip address(<span class="code">$REMOTE_ADDR</span>). This saves some space in the database, taking up only 4 bytes, but if I had been using a varchar(15) and storing the IP normally, it would take up 15 bytes for each entry. For a little application like this, it's probably not a big deal, but it certainly doesn't hurt.</p>
<p>And as always, don't forget to escape everything you get from a user before putting it in the database.</p>
<pre class="php code" title="code">$query="SELECT message, name FROM shoutbox ORDER BY timestamp DESC LIMIT 10";
$result=mysql_query($query);
$num=mysql_numrows($result);</pre>
<p>The first line of this block is creating a query which <span class="code">select</span>s both the message and the name from the <span class="code">shoutbox</span> table, orders it by the <span class="code">timestamp</span> field descending (meaning newest first) and limits the return to 10 rows. Then we store the return in a variable called <span class="code">$result</span>, then count how many rows were returned, using <span class="code">mysql_numrows()</span>.
<pre class="php code" title="code">mysql_close($shoutbox);</pre>
<p>You should always close the connection as soon as you are done needing it</p>
<pre class="php code" title="code">echo("&lt;ul&gt;\n");
for ($i = 0; $i &lt; $num; $i++) {</pre>
<p>As you can see, it is writing a starting <span class="code">&lt;ul&gt;</span>. The <span class="code">\n</span> means 'new line', so it will start a new line before <span class="code">echo</span>ing the <span class="code">&lt;li&gt;</span>'s. The next line is a loop. The <span class="code">for</span> loop will simply loop through until the condition is no longer met -- in this case, as soon as <span class="code">$i</span> becomes greater than <span class="code">$num</span>.
<pre class="php code" title="code">if(($i % 2) == 1) {
	$alt = "";
} else {
	$alt = " class=\"alt\"";
}</pre>
<p>This fun little bit of code may look a bit different to you. Some of you may be familiar with the '<span class="code">mod</span>' command. That is exactly what this is. The <span class="code">%</span> is short-hand for <span class="code">mod</span>. <span class="code">Mod</span> simply gets the remainder of an equation. In this case, it gets the remainder of <span class="code">$i</span> divided by 2. It checks to see if the remainder equals 1. This will be <span class="code">true</span> for every odd number. As you can see from the code following the statment, it will set the variable <span class="code">$alt</span> to have a class of 'alt' for all even values. This way, we can "zebra-stripe" or in other words, alternate colors.</p>
<pre class="php code" title="code">$say = mysql_result($result,$i,"message");
$name = mysql_result($result,$i,"name");
echo("&lt;li$alt&gt;&lt;strong&gt;".htmlentities($name)."&lt;/strong&gt; said: ".htmlentities($say)."&lt;/li&gt;");</pre>
<p>Now we are setting the values of <span class="code">$say</span> and <span class="code">$name</span> to be what we get out of the database, then outputting the whole line. Again, you will notice that I am escaping the output with <span class="code">htmlentities()</span>.
<pre class="php code" title="code">echo("&lt;/ul&gt;");</pre>
<p>And finally, we close the unordered list, and end the PHP.</p>
<h4>Download the code</h4>
<p>Because I know that I learn far better from example, I have made this code available for download. Click the following links to download the PHP files in zip format.</p>
<p><a href="/landfill/script/CallMe.zip" title="CallMe.php download">Download CallMe.php</a></p>
<p><a href="/landfill/script/FillElement.zip" title="FillElement.php download">Download FillElement.php</a></p>
<h4>That's all, folks</h4>
<p>And another [Easy as Pie] article comes to fruiition. I would like to take a moment and thank everyone for dropping by, and I really hope that I have helped you with something that might have previously been very confusing. If I did help you, please leave a comment letting me know. As always, be sure to subscribe to my <a title="Stay Updated!" href="http://feeds.feedburner.com/notesfromphazm">RSS Feed</a> for notification of future articles.</p>
<p><a href="http://feeds.feedburner.com/~a/NotesFromPhazm?a=4LbiiT"><img src="http://feeds.feedburner.com/~a/NotesFromPhazm?i=4LbiiT" border="0"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.phazm.com/notes/easy-as-pie/easy-as-pie-ajax-requests-part-2/feed/</wfw:commentRss>
		<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=NotesFromPhazm&amp;itemurl=http%3A%2F%2Fwww.phazm.com%2Fnotes%2Feasy-as-pie%2Feasy-as-pie-ajax-requests-part-2%2F</feedburner:awareness><feedburner:origLink>http://www.phazm.com/notes/easy-as-pie/easy-as-pie-ajax-requests-part-2/</feedburner:origLink></item>
		<item>
		<title>Feb 12th, 2008 -  A Glorious Day!</title>
		<link>http://feeds.feedburner.com/~r/NotesFromPhazm/~3/220398923/</link>
		<comments>http://www.phazm.com/notes/productivity/feb-12th-2008-a-glorious-day/#comments</comments>
		<pubDate>Mon, 21 Jan 2008 14:32:05 +0000</pubDate>
		<dc:creator>Jon Hughes</dc:creator>
		
		<category><![CDATA[IE6]]></category>

		<category><![CDATA[browser compatibility]]></category>

		<category><![CDATA[events]]></category>

		<category><![CDATA[productivity]]></category>

		<guid isPermaLink="false">http://www.phazm.com/notes/productivity/feb-12th-2008-a-glorious-day/</guid>
		<description><![CDATA[NO MORE Internet Explorer 6!
Update: For a select few  
IE6 is being phased out with a mandatory push from Microsoft, requiring all computers to upgrade to IE7.
The article from Microsoft mentions several ways you can disable the WGA-free update, so the war might not be over. But in my opinion, this is a major [...]]]></description>
			<content:encoded><![CDATA[<p class="alert">NO MORE Internet Explorer 6!</p>
<p><small>Update: For a select few <img src='http://www.phazm.com/notes/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </small></p>
<p>IE6 is being phased out with a mandatory push from Microsoft, requiring all computers to upgrade to IE7.</p>
<p>The <a href="http://support.microsoft.com/kb/946202" title="No more IE6">article from Microsoft</a> mentions several ways you can disable the WGA-free update, so the war might not be over. But in my opinion, this is a major step forward.</p>
<p><a href="http://feeds.feedburner.com/~a/NotesFromPhazm?a=qnlmsp"><img src="http://feeds.feedburner.com/~a/NotesFromPhazm?i=qnlmsp" border="0"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.phazm.com/notes/productivity/feb-12th-2008-a-glorious-day/feed/</wfw:commentRss>
		<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=NotesFromPhazm&amp;itemurl=http%3A%2F%2Fwww.phazm.com%2Fnotes%2Fproductivity%2Ffeb-12th-2008-a-glorious-day%2F</feedburner:awareness><feedburner:origLink>http://www.phazm.com/notes/productivity/feb-12th-2008-a-glorious-day/</feedburner:origLink></item>
		<item>
		<title>Easy as Pie - Working with a Database</title>
		<link>http://feeds.feedburner.com/~r/NotesFromPhazm/~3/218886387/</link>
		<comments>http://www.phazm.com/notes/easy-as-pie/easy-as-pie-working-with-databases/#comments</comments>
		<pubDate>Fri, 18 Jan 2008 14:34:53 +0000</pubDate>
		<dc:creator>Jon Hughes</dc:creator>
		
		<category><![CDATA[Easy As Pie]]></category>

		<category><![CDATA[MySQL]]></category>

		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.phazm.com/notes/easy-as-pie/easy-as-pie-working-with-databases/</guid>
		<description><![CDATA[

This post is the third in a continuing series of DIY tutorials, which aims to make things as simple as possible.
The [Easy as Pie] series focuses on tasks that most people consider too challenging and presents it in a way that is easy (as pie!) to understand.
Introduction
In this post, you are going to have a [...]]]></description>
			<content:encoded><![CDATA[<img src="/images/blog/easy-as-pie.png" alt="Easy As Pie" class="fr" />
<!--<p class="alert">Post Updated! Now with 100% less SQL Injection. If you downloaded the script previously, please download the new version.</p>-->
<p>This post is the third in a continuing series of <abbr title="Do It Yourself">DIY</abbr> tutorials, which aims to make things as simple as possible.</p>
<p>The [Easy as Pie] series focuses on tasks that most people consider too challenging and presents it in a way that is easy (as pie!) to understand.</p>
<h4>Introduction</h4>
<p>In this post, you are going to have a fantastic time learning:</p>
<ul>
<li><a href="http://www.phazm.com/notes/easy-as-pie/easy-as-pie-working-with-databases#createdatabase" title="How do I create a database?">How to create a MySQL Database</a></li>
<li><a href="http://www.phazm.com/notes/easy-as-pie/easy-as-pie-working-with-databases#createtable" title="How do I create a table in a database?">How to create a table in a MySQL Database</a></li>
<li><a href="http://www.phazm.com/notes/easy-as-pie/easy-as-pie-working-with-databases#adddata" title="How do I insert data into a database?">How to add data to a MySQL Database</a></li>
<li><a href="http://www.phazm.com/notes/easy-as-pie/easy-as-pie-working-with-databases#getdata" title="How do I retrieve data from a database?">How to get data from a MySQL Database</a></li>
<li><a href="http://www.phazm.com/notes/easy-as-pie/easy-as-pie-working-with-databases#randomquote" title="How do I create a random quote generator">How to create a random quote generator</a></li>
</ul>
<h4>The good stuff</h4>
<p>If you're like me, you learn really well from example. For this reason, I include the download for the random quote generator right here. Enjoy!</p>
<p><a href="/landfill/random-quote-generator.zip" title="Download the Random Quote Generator">Download the Random Quote Generator source code</a></p>
<p>Let's get started!</p>
<span id="more-20"></span>
<h4>Previous articles in this series</h4>
<ul>
<li><a href="http://www.phazm.com/notes/javascript/easy-as-pie-unobtrusive-javascript/" title="Easy as Pie - Unobtrusive JavaScript">[Easy as Pie] Unobtrusive JavaScript</a></li>
<li><a href="http://www.phazm.com/notes/productivity/easy-as-pie-ajax-requests/" title="Easy as Pie - Ajax Requests">[Easy as Pie] Ajax Requests</a></li>
</ul>
<h4 id="createdatabase">Creating a MySQL Database</h4>
<p>I am going to use cPanel for this example, as it is what my host uses.</p>
<p>Step 1: Go into cPanel</p>
<p>Step 2: Click on 'MySQL&reg; Databases'</p>
<p>Step 3: Find the input box where it says 'New Database:'</p>
<p>Step 4: Insert your database name, and click 'Create Database'</p>
<p>Step 5: Find 'Current Users:' and input a new username and password into the fields, then click create user</p>
<p>Step 6: Find 'Add Users To Your Databases:' Select your new database and username from the dropdowns, then hit 'Add User to Database'</p>
<p>Now you have a database set up!</p>
<p>From here, you can open PHPMyAdmin from the link at the bottom of the page, but I prefer using <a href="http://www.shareit.com/product.html?cart=1&amp;productid=300047916&amp;backlink=http%3A%2F%2Fwww.phazm.com%2Fnotes&amp;cookies=1&amp;oplayout=USA&amp;affiliateid=200070426" title="Buy SQLyog Enterprise Edition">SQLyog Enterprise</a> <small>(<a href="http://www.webyog.com/en/downloads.php" title="Download SQLyog Community Edition">free</a> version available)</small></p>
<p class="alert">If you are going to be using SQLyog, you may have to add your IP into the 'Access Hosts:' section. You can get your IP from <a href="http://www.cmyip.com/" title="'See' My IP">cmyip.com</a>.<br /><strong>PLEASE BE AWARE OF THE SECURITY RISKS INVOLVED WITH ALLOWING REMOTE ACCESS TO YOUR DATABASE(S)</strong></p>
<h4 id="createtable">Creating a Table in a MySQL Database</h4>
<p>Now we have transitioned into SQLyog, if you want to use PHPMyAdmin, you can go into the 'Query Window' that PHPMyAdmin provides, which is very similar to SQLyog's query input area, albeit much less verbose.</p>
<p>First, we have to decide the columns we are going to need. Because we are going to be making a random quote generator, we're going to need the following columns:</p>
<ul>
<li><span class="code">id</span> - this will automatically increment as entries are added</li>
<li><span class="code">quote</span> - this will contain the quote</li>
<li><span class="code">author</span> - this will contain the person who said the quote</li>
</ul>
<p>The syntax for creating our table is:</p>
<pre title="code" class="php code">
CREATE TABLE `quotes` (
    `id` int(11) NOT NULL auto_increment,
    `quote` varchar(255),
    `author` varchar(40),
    PRIMARY KEY  (`id`)
)</pre>
<p>This will create a table named 'quotes' with our 3 columns.</p>
<p><span class="code">id</span> is set to <span class="code">NOT NULL</span> as it will always have a value, and it will automatically increment (so long as we don't define a value)</p>
<p><span class="code">quote</span> is set to <span class="code"><abbr title="Variable Character Field">VARCHAR</abbr></span> and is limited to 255 characters</p>
<p><span class="code">author</span> is also set to <span class="code">VARCHAR</span>, but is limited to only 40 characters</p>
<p>Our primary key is set to <span class="code">id</span> - this means that you cannot have two of the same <span class="code">id</span></p>
<p><small>To execute this in SQLyog, go to 'Edit' => 'Execute Query' => 'Execute Current Query' ('F5' or 'F9' depending on your version) after putting the query in the query area at the top.</small></p>
<p>While we are here, we can add a few entries to our newly-created table. We could do this with the <acronym title="What You See Is What You Get">WYSIWYG</acronym> interface, but that's no fun, so here's how you add values using a query:</p>
<pre title="code" class="sql code">INSERT INTO `quotes` (`quote`,`author`) values ('A rose by any other name would smell as sweet','William Shakespeare')</pre>
<p>By not defining the <span class="code">id</span> column, it auto-fills with the value of <span class="code">1</span>.</p>
<p>Feel free to add a few more, though it's not necessary as we will be building a script to add them right about... now.</p>
<h4 id="adddata">Adding data to a MySQL Database</h4>
<p>We just learned the query to add data, now we just need to create an interface for it. I'm going to be using PHP for the backend code.</p>
<p>Before we begin, create a new page, and call it <span class="code">quotemanager.php</span></p>
<p>The first step will be creating the HTML form.</p>
<pre title="code" class="php code">
&lt;form action="" method="post"&gt;
&lt;fieldset&gt;
&lt;legend&gt;Add a Quote&lt;/legend&gt;
&lt;label for="quote"&gt;Quote:&lt;/label&gt;
&lt;input type="text" name="quote" id="quote" maxlength="255" /&gt;
&lt;label for="author"&gt;Author:&lt;/label&gt;
&lt;input type="text" name="author" id="author" maxlength="40" /&gt;
&lt;input type="submit" value="Add Quote" /&gt;
&lt;/fieldset&gt;
&lt;/form&gt;</pre>
<p>Here's how that will look:</p>
<img src="/images/blog/databases/add-a-quote-form.png" alt="Form for adding a quote" />
<p>Then we have to do the PHP stuff.</p>
<p>Here's the code used to connect to a MySQL database:</p>
<pre title="code" class="php code">
$user="username";
$password="password";
$database="database";
$connection = mysql_connect('localhost',$user,$password);
@mysql_select_db($database) or die( "Unable to select database");</pre>
<p>Most of this should be pretty self-explanatory. The first 3 lines are simply declaring variables, then you run the <span class="code">mysql_connect()</span> function which connects to the server using your credentials, then the next line is selecting the appropriate database, and if it is unable to do so, it spits out an error.</p>
<p>You may need to change 'localhost' to your domain if you are using an external database.</p>
<p>Now, we are going to create the PHP code that will grab the form values on submit and add it to the database.</p>
<pre title="code" class="php code">
&lt;?php
if ($_REQUEST['quote'] != "") {
    if($_REQUEST['author'] != "") {
	    $author = $_REQUEST['author'];
    } else {
	    $author = "Anonymous";
    }
    $quote = $_REQUEST['quote'];
    
    $query="INSERT INTO `quotes` (`quote`,`author`) values ('" . mysql_real_escape_string($quote) . "','" . mysql_real_escape_string($author) . "')";
    $result = mysql_query($query) or die(mysql_error());
    echo("inserted quote: " . htmlentities($quote) . " by " . htmlentities($author) . " into database");
} else {
    echo("&lt;p&gt;Please enter a quote and author&lt;/p&gt;");
}
?&gt;</pre>
<p>Here's what this script is doing:</p>
<pre title="code" class="php code">
if ($_REQUEST['quote'] != "") {
</pre>
<p>This means "if there is a <span class="code">quote</span> specified (<span class="code">quote</span> does not equal nothing) then continue on."</p>
<pre title="code" class="php code">
if($_REQUEST['author'] != "") {
 $author = $_REQUEST['author'];
} else {
 $author = "Anonymous";
}
</pre>
<p>This means "if there is an <span class="code">author</span> specified, use that value, otherwise (<span class="code">else</span>) define <span class="code">author</span> as 'Anonymous'."</p>
<pre title="code" class="php code">
$query="INSERT INTO `quotes` (`quote`,`author`) values ('" . mysql_real_escape_string($quote) . "','" . mysql_real_escape_string($author) . "')";
</pre>
<p>This defines the query we learned earlier</p>
<p>The <span class="code">mysql_real_escape_string()</span> escapes the string so you aren't opened up to <a href="http://en.wikipedia.org/wiki/SQL_injection" title="SQL Injection">SQL Injection</a> vulnerabilities.</p>
<p class="alert">Don't forget to escape the user input!</p>
<pre title="code" class="php code">
$result = mysql_query($query) or die(mysql_error());
</pre>
<p>This actually runs the query, and spits out an error if it fails</p>
<pre title="code" class="php code">
echo("inserted quote: " . htmlentities($quote) . " by " . htmlentities($author) . " into database");
</pre>
<p>This outputs what we put into the database</p>
<p>The <span class="code">htmlentities()</span> converts things like &lt; to &amp;lt;, so you don't run into <a href="http://en.wikipedia.org/wiki/Cross-site_scripting" title="Cross Site Scripting"><acronym title="Cross Site Scripting">XSS</acronym></a> vulnerabilities.</p>
<pre title="code" class="php code">
} else {
    echo("&lt;p&gt;Please enter a quote and author&lt;/p&gt;");
}
</pre>
<p>This means that there was no <span class="code">quote</span> specified, so it asks for input from the person viewing the page.</p>
<p>So that's it, now we can add all the data we want into our quotes table. But really, that's not all that helpful, we need to have a way to output it!</p>
<h4 id="getdata">Retrieving data from the Database</h4>
<p>We are now going to list all quotes in the database along with the author.</p>
<pre title="code" class="php code">&lt;?php
$query="SELECT `quote`, `author` FROM `quotes`";
$result=mysql_query($query) or die(mysql_error());
$num=mysql_numrows($result);
$i=0;
while ($i &lt; $num) {
  $quote = htmlentities(mysql_result($result,$i,"quote"));
  $author = htmlentities(mysql_result($result,$i,"author"));
  echo("&lt;blockquote&gt;" . $quote . " ~ &lt;cite&gt;" . $author . "&lt;/cite&gt;&lt;/blockquote&gt;");
  $i++;
}
mysql_close($connection);
?&gt;</pre>
<p>This is what is going on:</p>
<pre title="code" class="php code">
$query="SELECT `quote`, `author` FROM `quotes`";
$result=mysql_query($query) or die(mysql_error());
</pre>
<p>Look familiar? This is the <span class="code">select</span> query which selects the <span class="code">quote</span> and <span class="code">author</span> columns out of the <span class="code">quotes</span> table, or more accurately, selects the values therein.</p>
<pre title="code" class="php code">$num=mysql_numrows($result);</pre>
<p>This sets <span class="code">$num</span> to the number of rows that are returned by the <span class="code">select</span> query. So for instance, if you have 9 quotes in the table, the number will be... you guessed it -- 9!</p>
<pre title="code" class="php code">$i=0;</pre>
<p>Just setting the <span class="code">$i</span> variable to <span class="code">0</span>, as we are about to loop through the results, and need a counter</p>
<pre title="code" class="php code">while ($i &lt; $num) {</pre>
<p>This is the beginning of a <span class="code">while</span> loop. Each iteration, it checks for a condition (in this case, it checks that <span class="code">$i</span> is <span class="code">less than</span> the number of results (which is stored in <span class="code">$num</span>))</p>
<pre title="code" class="php code">
$quote = htmlentities(mysql_result($result,$i,"quote"));
$author = htmlentities(mysql_result($result,$i,"author"));</pre>
<p>In order to use the values in the loop, we have to define them in this way. The syntax being used is:</p>
<ul>
<li>mysql_result() - function</li>
<li>$result - Which resultset to use</li>
<li>$i - Which row you want to pull (as this increments, it will pull each row)</li>
<li>"quote"/"author" - Specified which field/column to pull from</li>
</ul>
<pre title="code" class="php code">$i++;</pre>
<p>This means "Increment <span class="code">$i</span> by 1 (The same could be written <span class="code">$i = $i + 1;</span> or <span class="code">$i+=1;</span>)</p>
<pre title="code" class="php code">mysql_close($connection);</pre>
<p>As we are no longer using the MySQL Connection, we can close it here.</p>
<p>That's it for getting data out of a database - pretty straightforward! Now on to the fun stuff!</p>
<h4 id="randomquote">Making a random quote generator</h4>
<p>Alright, if you have read this far and retained around 15% of it, you are scientifically proven to be a genius. Great job!</p>
<p>We're going to create a random quote generator, using the scripts we have already made</p>
<p>The first thing we need to do is create a new page, where the quote will show up. We'll call this page <span class="code">quote.php</span>, because I'm feeling adventurous.</p>
<p>Here's the code we're going to put on this page:</p>
<pre title="code" class="php code">&lt;h1&gt;Quote of the moment&lt;/h1&gt;
&lt;?php
$user="username";
$password="password";
$database="database";
$connection=mysql_connect('localhost',$user,$password);
@mysql_select_db($database) or die( "Unable to select database");
$query="SELECT `quote`, `author` FROM `quotes` ORDER by rand() LIMIT 1";
$result=mysql_query($query) or die(mysql_error());
$quote = htmlentities(mysql_result($result,$i,"quote"));
$author = htmlentities(mysql_result($result,$i,"author"));
echo("&lt;blockquote&gt;" . $quote . " ~ &lt;cite&gt;" . $author . "&lt;/cite&gt;&lt;/blockquote&gt;");
mysql_close($connection);
?&gt;</pre>
<p>Alright, so the only new thing is:</p>
<pre title="code" class="php code">
$query="SELECT `quote`, `author` FROM `quotes` ORDER by rand() LIMIT 1";
</pre>
<p>Here is our query for randomly selecting one of the quotes and authors out of the database. The <span class="code">rand()</span> means random, and will generate a random column to pull from each time it is run</p>
<p>The <span class="code">LIMIT 1</span> means just that, limit the query to one result.</p>
<p>That's all you need for your random quote generator! By only slightly modifying this code, you can create a plethora of mini-applications, such as a random image generator, random trivia, etc. The possibilities, as they say, are endless.</p>
<p><a href="/landfill/random-quote-generator.zip" title="Download the Random Quote Generator">Download the Random Quote Generator source code.</a></p>
<h4>That's all, folks</h4>
<p>And so concludes the article. If you enjoyed it, please leave a comment. Don't forget to subscribe to the <a href="http://feeds.feedburner.com/notesfromphazm" title="Stay Updated!"><acronym title="Really Simple Syndication">RSS</acronym> feed</a> for future articles.</p>
<p><a href="http://feeds.feedburner.com/~a/NotesFromPhazm?a=nTNQ4P"><img src="http://feeds.feedburner.com/~a/NotesFromPhazm?i=nTNQ4P" border="0"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.phazm.com/notes/easy-as-pie/easy-as-pie-working-with-databases/feed/</wfw:commentRss>
		<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=NotesFromPhazm&amp;itemurl=http%3A%2F%2Fwww.phazm.com%2Fnotes%2Feasy-as-pie%2Feasy-as-pie-working-with-databases%2F</feedburner:awareness><feedburner:origLink>http://www.phazm.com/notes/easy-as-pie/easy-as-pie-working-with-databases/</feedburner:origLink></item>
		<item>
		<title>Alexa Redirect is Broken</title>
		<link>http://feeds.feedburner.com/~r/NotesFromPhazm/~3/218264044/</link>
		<comments>http://www.phazm.com/notes/comments-needed/alexa-redirect-is-broken/#comments</comments>
		<pubDate>Sat, 12 Jan 2008 16:08:28 +0000</pubDate>
		<dc:creator>Jon Hughes</dc:creator>
		
		<category><![CDATA[Alexa]]></category>

		<category><![CDATA[Comments Needed]]></category>

		<guid isPermaLink="false">http://www.phazm.com/notes/comments-needed/alexa-redirect-is-broken/</guid>
		<description><![CDATA[
It seems that using Alexa's redirect URL to game your rank is no longer an option.
UPDATE

Just got this in my inbox:
]]></description>
			<content:encoded><![CDATA[<img src="/images/blog/alexa-logo.png" alt="Alexa" class="fr" />
<p>It seems that using Alexa's redirect URL to game your rank is no longer an option.</p>
<h3>UPDATE</h3>
<div class="alert">
<p>Just got this in my inbox:</p>
<!-- I didn't want to do inline styles... but it's a very rare case!  C'mon!  Stop looking at me like that... -->
<small style="display:block; text-align:left; padding-left:10px;">Dear Jon,<br />
Thank you for your message.<br />
We no longer provide support for the redirect function.<br />
<br />
Best regards,<br />
Alexa Internet Customer Service</small>
<p>I guess that answers the question as to whether they are coming back or not!</p>
</div>
<p>On about 4:00PM on Thursday, January 10th, I clicked one of the comment author's names, which I assumed lead to their blog. Instead of their page, however, I got:</p>
<blockquote class="full"><p>The requested URL /redirect was not found on this server.</p></blockquote>
<p>I glanced at the address bar, and saw this:</p>
<p class="code">http://redirect.Alexa.com/redirect?myblog.com</p>
<p>That's not good for business...</p>
<span id="more-18"></span>
<p>A quick google for <span class="code">"Alexa redirect"</span> brings up over 50,000 results, <a href="http://www.doshdosh.com/20-quick-ways-to-increase-your-Alexa-rank/" title="DoshDosh">some</a> of them promote the Alexa redirect, <a href="http://www.friedbeef.com/2007/08/11/debunking-popular-Alexa-myths/" title="Fried Beef">others</a> say it is a myth.</p>
<p>Personally, I am inclined to believe it is nothing more than a redirect script, and has nothing at all to do with your Alexa rank.</p>
<p>Here's a quote from the Alexa project manager, <a href="http://www.blogger.com/profile/11928379463688917546" title="Geoffrey Mack's Blogger Profile">Geoffrey Mack</a>:</p>
<blockquote class="full"><p>...The [Alexa] redirect doesn't do anything to your rank. The rank is based on one thing only: logs from toolbar usage. I should know, I am the product manager at Alexa...."</p></blockquote>
<p>This sort of this just calls attention to the fact that you cannot rely on third party links.</p>
<p>Case in point, not long ago <a href="http://tinyurl.com/" title="TinyURL">TinyURL</a> went down, rendering more than 54 million links completely useless.</p>
<p>I also find it interesting that I am unable to find any official word on Alexa.com about even the <strong>existence</strong> of a redirect URL.</p>
<h4>What do you think?</h4>
<p>Do you think Alexa should have removed the redirect abilities without any notice?</p>
<p>Do you think the Alexa redirect actually did what so many people though it did?</p>
<p><a href="http://feeds.feedburner.com/~a/NotesFromPhazm?a=phqNrJ"><img src="http://feeds.feedburner.com/~a/NotesFromPhazm?i=phqNrJ" border="0"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.phazm.com/notes/comments-needed/alexa-redirect-is-broken/feed/</wfw:commentRss>
		<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=NotesFromPhazm&amp;itemurl=http%3A%2F%2Fwww.phazm.com%2Fnotes%2Fcomments-needed%2Falexa-redirect-is-broken%2F</feedburner:awareness><feedburner:origLink>http://www.phazm.com/notes/comments-needed/alexa-redirect-is-broken/</feedburner:origLink></item>
		<item>
		<title>Easy as Pie - Ajax Requests</title>
		<link>http://feeds.feedburner.com/~r/NotesFromPhazm/~3/218264045/</link>
		<comments>http://www.phazm.com/notes/productivity/easy-as-pie-ajax-requests/#comments</comments>
		<pubDate>Thu, 27 Dec 2007 06:13:13 +0000</pubDate>
		<dc:creator>Jon Hughes</dc:creator>
		
		<category><![CDATA[Ajax]]></category>

		<category><![CDATA[Easy As Pie]]></category>

		<category><![CDATA[JavaScript]]></category>

		<category><![CDATA[productivity]]></category>

		<guid isPermaLink="false">http://www.phazm.com/notes/productivity/easy-as-pie-ajax-requests/</guid>
		<description><![CDATA[

This post is the second in a continuing series of DIY tutorials, which aims to make things as simple as possible.
Ajax. Some would say that it is simply an over-used buzzword, but I disagree. Ajax (formerly known as AJAX) is a fantastic way to enhance websites and improve user interactivity. However, like all things, it [...]]]></description>
			<content:encoded><![CDATA[<img src="/images/blog/easy-as-pie.png" alt="Easy As Pie" class="fr" />
<!--<p class="alert"><a href="http://www.digg.com/programming/Easy_as_Pie_Ajax_Requests" title="digg this">Digg This Please</a> &laquo; Will be removed after 24 hours.</p>-->
<p>This post is the second in a continuing series of <abbr title="Do It Yourself">DIY</abbr> tutorials, which aims to make things as simple as possible.</p>
<p>Ajax. Some would say that it is simply an over-used buzzword, but I disagree. Ajax (<a href="http://blog.jjg.net/weblog/2005/08/ajax_vs_ajax.html" title="Jesse James Garrett - The one who coined AJAX in 2005">formerly known</a> as <abbr title="Asynchronous JavaScript and XML">AJAX</abbr>) is a fantastic way to enhance websites and improve user interactivity. However, like all things, it should be used in moderation, and has the potential to be used improperly (I'm looking at you, flash.)</p>
<p>But I don't want to get off-topic so early on. In this tutorial, you will:</p>
<ul>
<li>Learn how to use Ajax in the simplest way I could think of</li>
<li>Create an addictive voting script</li>
<li>Create a simple shoutbox</li>
<li>Download source and create your own within minutes!</li>
</ul>
<span id="more-17"></span>
<p>But first, I will explain a bit about what Ajax really is (and what it isn't) for those of you just starting out.</p>
<h4>What Ajax Isn't</h4>
<p>Ajax is not flashy JavaScript. Ajax is not a fancy form, radical menu or custom tool-tip. Ajax is definately not a styled popup.</p>
<h4>What Ajax Is</h4>
<p>Ajax, also known as <abbr title="XML Http Request">XHR</abbr>, is a technology used to send and receive requests for data to and from a server without having to refresh the whole page. That's really all there is to it.</p>
<p>Don't let that put you off though! You can still accomplish some really neat things using Ajax. The first 'neat thing' is a voting script. You click a button to vote, which will poll phazm.com's server and come back with an updated tally of how many votes there are -- <em>without</em> a single page refresh. Fascinating, am I right?</p>
<h4>Let's Vote!</h4>
<p>Alright, here's the little script I made. This took me about 12 minutes to write the script, 8 minutes to set up the database, and 2 minutes to come up with the idea. (For those of you keeping track at home, that's a total of <strong>22</strong> minutes!)</p>
<p class="alert">Note: Feel free to vote more than once to see the number rise.</p>
<h4>Which one is the cutest?</h4>
<div id="votes">
<!--Yes, these events are obtrusive, but it's only an example!  C'mon! -->
<a href="javascript:void(0)" onclick="fillElementId('/landfill/CallMe.php','link1','link=1')" id="link1">I have 6934 votes</a> 
<a href="javascript:void(0)" onclick="fillElementId('/landfill/CallMe.php','link2','link=2')" id="link2">I haz 6907</a>

</div>
<h4>And the winner is... Ajax!</h4>
<p>This is obviously a very (<em>very</em>) simple example of what Ajax can do, but it's effective, nonetheless. There are significant advantages to using Ajax for this, rather than straight JavaScript. While I could emulate this in JavaScript, the votes would have to be saved on your machine via cookies or sessions and other votes wouldn't be counted, only your own.</p>
<h4>So how did you do it?</h4>
<p>Like this!</p>
<p class="code">
function getHTTPObject() {<br />
&nbsp;var xhr = false;<br />
&nbsp;if (window.XMLHttpRequest) {<br />
&nbsp;&nbsp;xhr = new XMLHttpRequest();<br />
&nbsp;} else if (window.ActiveXObject) {<br />
&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;xhr = new ActiveXObject("Msxml2.XMLHTTP");<br />
&nbsp;&nbsp;} catch(e) {<br />
&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;xhr = new ActiveXObject("Microsoft.XMLHTTP");<br />
&nbsp;&nbsp;&nbsp;} catch(e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;xhr = false;<br />
&nbsp;&nbsp;&nbsp;};<br />
&nbsp;&nbsp;};<br />
&nbsp;};<br />
&nbsp;return xhr;<br />
};<br />
<br />
function fillElementId(url,elementId) {<br />
&nbsp;if(!document.getElementById(elementId)) {<br />
&nbsp;&nbsp;return;<br />
&nbsp;};<br />
&nbsp;parameters = encodeURI(parameters);<br />
&nbsp;var xmlHttp = getHTTPObject();<br />
&nbsp;xmlHttp.onreadystatechange=function(){<br />
&nbsp;&nbsp;if(xmlHttp.readyState==4){<br />
&nbsp;&nbsp;&nbsp;if(xmlHttp.status==200){<br />
&nbsp;&nbsp;&nbsp;&nbsp;document.getElementById(elementId).innerHTML = xmlHttp.responseText;<br />
&nbsp;&nbsp;&nbsp;&nbsp;xmlHttp=null;<br />
&nbsp;&nbsp;&nbsp;} else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;alert("Error: "+xmlHttp.statusText);<br />
&nbsp;&nbsp;&nbsp;};<br />
&nbsp;&nbsp;};<br />
&nbsp;};<br />
&nbsp;xmlHttp.open('POST',url,true);<br />
&nbsp;xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");<br />
&nbsp;xmlHttp.setRequestHeader("Content-Length", parameters.length);<br />
&nbsp;xmlHttp.setRequestHeader("Connection", "close");<br />
&nbsp;xmlHttp.send(parameters);<br />
};
</p>
<ul>
<li><a href="/landfill/script/ajaxRequest.js" title="Download the Ajax Request Script">Download this script (with comments!)</a></li>
</ul>
<p>Let's break it down line by line:</p>
<h5>getHTTPObject</h5>
<p class="code">function getHTTPObject() {</p>
<p>This is the function that actually loads the XmlHttpRequest</p>
<p class="code">var xhr = false;</p>
<p>Simply pre-defining the variable.</p>
<p class="code">if (window.XMLHttpRequest) {<br />xhr = new XMLHttpRequest();</p>
<p>Firefox, Safari, Opera and Netscape and IE7 all use window.XMLHttpRequest</p>
<p class="code">} else if (window.ActiveXObject) {</p>
<p>window.ActiveXObject is used by IE6 and below.</p>
<p class="code">xhr = new ActiveXObject(&quot;Msxml2.XMLHTTP&quot;);</p>
<p>Internet Explorer 6 uses Msxml2.XMLHTTP</p>
<p class="code">xhr = new ActiveXObject(&quot;Microsoft.XMLHTTP&quot;);</p>
<p>IE 5 uses Microsoft.XMLHTTP</p>
<p class="code">xhr = false;</p>
<p>If you get in here, it means your browser doesn't support XHR</p>
<p class="code">return xhr;</p>
<p>This returns the value of 'xhr' to whatever called it.</p>
<h5>fillElementId</h5>
<p class="code">function fillElementId(url,elementId) {</p>
<p>This is the function that tells the XHR what to do, and this is the function you can modify.</p>
<p class="code">if(!document.getElementById(elementId)) {<br />
return;
</p>
<p>This will check if the id you gave it exists, and if it doesn't, it will break out of the function.</p>
<p class="code">parameters = encodeURI(parameters);</p>
<p>This will encode the parameters passed to it, turning spaces (" ") into %20 and the like.</p>
<p class="code">var xmlHttp = getHTTPObject();</p>
<p>As you can see, we have just defined <span class="code">xmlHttp</span> as the function we looked at earlier. This simply sets <span class="code">xmlHttp</span> to whatever is returned from the <span class="code">getHTTPObject</span> function.</p>
<p class="code">xmlHttp.onreadystatechange=function(){</p>
<p>This will fire off every time the <span class="code">readyState</span> changes</p>
<p class="code">if(xmlHttp.readyState==4){</p>
<p><span class="code">readyState</span> can be any of the following:</p>
<ul>
<li>0 = uninitialized</li>
<li>1 = connection open</li>
<li>2 = data sent</li>
<li>3 = receiving data</li>
<li>4 = transaction complete</li>
</ul>
<p class="code">if(xmlHttp.status==200){</p>
<p><span class="code">status</span> is the HTML status received, these are the most commonly received:</p>
<ul>
<li>200 = OK</li>
<li>301 = Redirected</li>
<li>400 = Bad Request</li>
<li>401 = Unauthorized</li>
<li>403 = Forbidden</li>
<li>404 = Not Found</li>
<li>408 = Request Timeout</li>
<li>500 = Internal Server Error</li>
<li>503 = Service Unavailable</li>
</ul>
<p class="code">document.getElementById(elementId).innerHTML = xmlHttp.responseText;</p>
<p>This simply replaces everything in the container with the ID we specified with whatever is in the variable <span class="code">xmlHttp.responseText</span></p>
<p class="code">xmlHttp=null;</p>
<p>This removes the reference to the object</p>
<p class="code">alert(&quot;Error: &quot;+xmlHttp.statusText);</p>
<p>This will output what the server returns, such as &quot;Not Found&quot; or &quot;Forbidden&quot;</p>
<p class="code">xmlHttp.open('POST',url,true);</p>
<p>This is where you open the request. You can use either GET or POST for the request. The "true" means asynchronous, so if you change it to false, it will wait for a response before doing anything else.</p>
<p class="code">xmlHttp.setRequestHeader(&quot;Content-Type&quot;, &quot;application/x-www-form-urlencoded&quot;);</p>
<p>This tells the script to expect a form</p>
<p class="code">xmlHttp.setRequestHeader(&quot;Content-Length&quot;, parameters.length);</p>
<p>This declares the length of the parameters to the script</p>
<p class="code">xmlHttp.setRequestHeader("Connection", "close");</p>
<p>If you want to have a persistent connection, you don't need this line, but I don't want a persistent connection open, so I close it.</p>
<p class="code">xmlHttp.send(parameters);</p>
<p>This sends the request, which will begin to change the <span class="code">readyState</span>, and thus start firing off the above code, and wait for the <span class="code">readyState</span> to be <span class="code">4</span>.</p>
<h5>Initiation</h5>
<p>Then you have to initiate it somehow, which I am doing using an onclick event. You should probably add this event <a href="http://www.phazm.com/notes/JavaScript/easy-as-pie-unobtrusive-JavaScript/" title="Easy as Pie - Unobtrusive JavaScript">unobtrusively</a>, but for examples sake I'm doing it inline.</p>
<p class="code">&lt;a id=&quot;link1&quot; onclick=&quot;fillElementId('/landfill/CallMe.php','link1','link=1')&quot; href=&quot;javascript:void(0)&quot;&gt;I have 2 votes&lt;/a&gt; <br />
  &lt;a id=&quot;link2&quot; onclick=&quot;fillElementId('/landfill/CallMe.php','link2','link=2')&quot; href=&quot;javascript:void(0)&quot;&gt;I haz 3&lt;/a&gt;</p>
<p>So when you click on one of those links, it sends the three variables (<span class="code">url</span>, <span class="code">elementId</span> and <span class="code">parameters</span>) that are in the onclick to the <span class="code">fillElement</span> function.</p>
<p>The function calls the url, and replaces the content of the element with that id with whatever it gets from the url. Simple enough?</p>
<p>Here's another really simple example:</p>
<h4>Phazm Shoutbox Mini (beta!)</h4>
<div class="shoutbox">
<form action="" onsubmit="fillElementId('/landfill/FillElement.php','fillMe','say='+this.msg.value+'&amp;name='+this.name.value); this.msg.value=''; return false;">
<fieldset>
<label for="name">Name:</label>
<input type="text" name="name" id="name" />
<label for="msg">Message</label>
<input type="text" name="msg" id="msg" />
<input type="image" src="/images/sayit.png" title="Submit it!" value="Submit" class="button" />
<input type="image" src="/images/refresh.png" onclick="fillElementId('/landfill/FillElement.php','fillMe'); return false;" value="Refresh Shoutbox" title="Refresh Shoutbox" />
</fieldset>
</form>
<div id="fillMe"><ul>
<li class="alt"><strong>she</strong> said: i like it</li><li><strong>whoever</strong> said: tddhsid  id</li><li class="alt"><strong>tuit</strong> said: yuity</li><li><strong>alan chin</strong> said: hi all</li><li class="alt"><strong>asdf</strong> said: asdf</li><li><strong>NameBot</strong> said: Phazmashouten: Best. Name. Ever.</li><li class="alt"><strong>jon</strong> said: hi</li><li><strong>phoenix</strong> said: try</li><li class="alt"><strong>phoenix</strong> said: try</li><li><strong>Phazm</strong> said: Shoutbox</li></ul></div>
</div>
<h4>How did you do that, then?</h4>
<p>Almost exactly the same as the voting script. The only thing that changed was the <span class="code">onclick</span> (or <span class="code">onsubmit</span>, in this case)</p>
<p>Now, it's calling a different php file, with two variables: <span class="code">name</span> and <span class="code">msg</span> - the PHP is doing the rest, as it should.</p>
<h4>Ajax - A Dumb Waiter</h4>
<p><a href="http://adactio.com/" title="Adactio - By Jeremy Keith">Jeremy Keith</a> said in last years <a href="http://north08.webdirections.org/" title="Web Directions North">Web Directions North</a> <small>(Links to 2008 page)</small> that Ajax should be a "dumb waiter" - Not doing any of the heavy lifting, just sending and receiving data that is generated server-side. This way, you have less problems with browser imcompatibilities and such, and it makes the speed of your application depend on your server, not on the computer running the code.</p>
<p>So there you have it, your very own Ajax script -- Easy as Pie!</p>
<h4>Download It</h4>
<p>If you would like to download the JavaScript file, you may do so at <a href="/landfill/script/ajaxRequest.js" title="Download Ajax Request File">this link</a>. Feel free to use it any way you want to, you don't need to link back unless you wish to.</p>
<h4>What's next?</h4>
<p>I'm thinking an "Easy as Pie - Debugging CSS and JavaScript" next, but that might change depending on the comments I receive here. What would YOU like to see simplified?</p>
<p><a href="http://feeds.feedburner.com/~a/NotesFromPhazm?a=MeQHj0"><img src="http://feeds.feedburner.com/~a/NotesFromPhazm?i=MeQHj0" border="0"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.phazm.com/notes/productivity/easy-as-pie-ajax-requests/feed/</wfw:commentRss>
		<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=NotesFromPhazm&amp;itemurl=http%3A%2F%2Fwww.phazm.com%2Fnotes%2Fproductivity%2Feasy-as-pie-ajax-requests%2F</feedburner:awareness><feedburner:origLink>http://www.phazm.com/notes/productivity/easy-as-pie-ajax-requests/</feedburner:origLink></item>
		<item>
		<title>Easy as Pie - Unobtrusive JavaScript</title>
		<link>http://feeds.feedburner.com/~r/NotesFromPhazm/~3/218264046/</link>
		<comments>http://www.phazm.com/notes/javascript/easy-as-pie-unobtrusive-javascript/#comments</comments>
		<pubDate>Mon, 17 Dec 2007 01:34:34 +0000</pubDate>
		<dc:creator>Jon Hughes</dc:creator>
		
		<category><![CDATA[Easy As Pie]]></category>

		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.phazm.com/notes/javascript/easy-as-pie-unobtrusive-javascript/</guid>
		<description><![CDATA[

This post is the first in a continuing series of DIY tutorials, which aims to make things as simple as possible. I will also monitor the comments on the 'Easy as Pie' posts more carefully so I can address any questions anyone has.

Before I delve into the technique I use for unobtrusive JavaScript, I'll give [...]]]></description>
			<content:encoded><![CDATA[<img src="/images/blog/easy-as-pie.png" alt="Easy As Pie" class="fr" />
<!--<p class="alert"><a href="http://www.digg.com/programming/Easy_as_Pie_Unobtrusive_JavaScript" title="digg this">Digg This Please</a> &laquo; Will be removed after 24 hours.</p>-->
<p>This post is the first in a continuing series of <abbr title="Do It Yourself">DIY</abbr> tutorials, which aims to make things as simple as possible. I will also monitor the comments on the 'Easy as Pie' posts more carefully so I can address any questions anyone has.</p>
<span id="more-14"></span>
<p>Before I delve into the technique I use for unobtrusive JavaScript, I'll give a brief overview of what unobtrusive JavaScript is, and the benefits of using it.</p>
<h4>What is unobtrusive JavaScript?</h4>
<p>Quite simply put, it's removing JavaScript from the source of the document, and including it in an external file. That's what unobtrusive JavaScript IS - but what is far more important is what unobtrusive JavaScript symbolizes. Unobtrusive JavaScript to me is a largely promoted technique to adhere to web development best practices and standards. It encourages the separation of the "behavior" layer from the "presentation" and "structure" layer.</p>
<p>In essence, it's the same thing that we have been doing with CSS for years - Calling a style sheet and within itself, selecting the elements you wish to style. With the ability to traverse the DOM, JavaScript is essentially the same thing, just with a bit more functionality.</p>
 
<p>To fully understand what unobtrusive JavaScript is, you need to be able to identify obtrusive JavaScript -- here are some examples of obtrusive JavaScript:</p>
<p class="code">&lt;a href=&quot;JavaScript:alert('You clicked!')&quot;&gt;Click Me!&lt;/a&gt;</p>
<p>You may have seen this around, and sometimes you may see something like this:</p>
<p class="code">&lt;a href=&quot;#&quot; onclick=&quot;alert('You clicked!')&quot;&gt;Click Me!&lt;/a&gt;</p>
<p>Obviously, this will not do anything for those with JavaScript disabled. A slightly better version would be this:</p>
<p class="code">&lt;a href=&quot;clicked.html&quot; onclick=&quot;alert('You clicked!')&quot;&gt;Click Me!&lt;/a&gt;</p>
<p>This way, if the user does not have JavaScript capabilities, or has JavaScript disabled, they will still go to the '<span class="code">clicked.html</span>' page.</p>
<h4>Making your JavaScript unobtrusive</h4>
<p>The process for making your JavaScript unobtrusive is actually quite simple - you simply need to 'hook' into it and apply an event handler (such as '<span class="code">onclick</span>'). Let's get started.</p>
<p>First, one option you have is to create a listener to run when the window has fully loaded by using <span class="code">window.onload</span>. Here is a quick example:</p>
<p class="code">window.onload = function() {<br />
&nbsp;&nbsp;&nbsp;//run this on page load<br />
}</p>
<p>However, this will wait until ALL elements are completely loaded (even large images) before running the JavaScript.</p>
<p>To get around that hurdle, we can use <a href="http://www.brothercake.com/site/resources/scripts/domready/" title="domFunction" class="code">domFunction</a>.</p>
<p><span class="code">domFunction</span> is a small (2k) JavaScript file that waits for the DOM to be ready before running your JavaScript, this allows you to traverse the DOM without waiting for images to load. It does this by checking for an element/id on the page, and if it can access it with the DOM, it assumes the DOM is ready. The syntax is:</p>
<p class="code">var foobar = new domFunction(function() {<br />
&nbsp;&nbsp;//run this when DOM  is ready
}, {'footer' : 'id'});</p>
<ul>
<li><a href="http://www.brothercake.com/scripts/domready/domfunction.html" title="domFunction Demo" rel="nofollow">Click here for a demo</a></li>
</ul>
<h4>The code</h4>
<p>Alright, now you know how to initiate a script as soon as it can use the DOM, now we have to hook into the elements we want to add JavaScript to.</p>
<p>Here's the HTML we are going to use:</p>
<p class="code">&lt;div id="mylinks"&gt;<br />
&lt;a href=&quot;mypage.html&quot; title=&quot;Go to my page&quot;&gt;My Page&lt;/a&gt; | &lt;a href=&quot;yourpage.html&quot; title=&quot;Go to your page&quot;&gt;Your Page&lt;/a&gt;<br />
&lt;/div&gt;</p>
<p>And the JavaScript (not including the domFunction):</p>
<pre class="code">
function unobtrusifier() {
	if(document.getElementById('mylinks')) {
		var links = document.getElementById('mylinks').getElementsByTagName('a');
		linklength = links.length;
		for(var i=0;i&lt;linklength;i++) {
			links[i].onclick = function() { alert(this.title); return false; };
		};		
	};
};
</pre>
<ul>
<li><a href="/landfill/script/easy-as-pie-unobtrusive-javascript.js" title="View JavaScript (With Comments)">Click Here</a> to view the JavaScript with comments</li>
</ul>
<h4>The example</h4>
<ul>
<li><a href="/landfill/easy-as-pie-unobtrusive-javascript.html" title="Example of unobtrusive JavaScript">Click Here</a> to see the above code in action</li>
</ul>
<h4>The end</h4>
<p>Please let me know if you found this at all helpful. I tried to make it as simple as possible without neglecting standards.</p>
 
<p>The next 'Easy as Pie' will be on Ajax. Fun stuff!</p>
<p><a href="http://feeds.feedburner.com/~a/NotesFromPhazm?a=t2Mojk"><img src="http://feeds.feedburner.com/~a/NotesFromPhazm?i=t2Mojk" border="0"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.phazm.com/notes/javascript/easy-as-pie-unobtrusive-javascript/feed/</wfw:commentRss>
		<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=NotesFromPhazm&amp;itemurl=http%3A%2F%2Fwww.phazm.com%2Fnotes%2Fjavascript%2Feasy-as-pie-unobtrusive-javascript%2F</feedburner:awareness><feedburner:origLink>http://www.phazm.com/notes/javascript/easy-as-pie-unobtrusive-javascript/</feedburner:origLink></item>
		<item>
		<title>Firefox 3 &amp; Web Developers</title>
		<link>http://feeds.feedburner.com/~r/NotesFromPhazm/~3/218264047/</link>
		<comments>http://www.phazm.com/notes/browser-compatibility/firefox-3-web-developers/#comments</comments>
		<pubDate>Wed, 28 Nov 2007 14:10:09 +0000</pubDate>
		<dc:creator>Jon Hughes</dc:creator>
		
		<category><![CDATA[browser compatibility]]></category>

		<category><![CDATA[firefox]]></category>

		<guid isPermaLink="false">http://www.phazm.com/notes/browser-compatibility/firefox-3-web-developers/</guid>
		<description><![CDATA[
While it pains me to do so, the following warning is needed:
This entry best viewed in Firefox 3
Since Mozilla released the Firefox 3 Beta (Code Name: Minefield) there have been a rash of blog posts regarding the many new features, increased security, and enhanced UI. However, one thing I have yet to see is what [...]]]></description>
			<content:encoded><![CDATA[<img src="/images/blog/ff3/minefield-icon.png" alt="Minefield (Firefox Beta)" class="fr" />
<p><small>While it pains me to do so, the following warning is needed:</small></p>
<p class="alert">This entry best viewed in Firefox 3</p>
<p>Since Mozilla released the Firefox 3 Beta (Code Name: Minefield) there have been a rash of blog posts regarding the many new features, increased security, and enhanced UI. However, one thing I have yet to see is what I am really need to know: how does this affect web developers?</p>
<span id="more-13"></span>

<p>When I heard that Safari was releasing a PC version of their browser, I was overjoyed... <q>Now I don't need to boot up my Mac to test sites in Safari, right?</q> Well, as we all know, the answer to that very naive assumption is a resounding "Not even close" - We now have just one <strong>more</strong> browser we need to test in. <small>(Note: Safari did clean up its act a bit since release, but it's still not exactly the same as its Mac counterpart, and thus is simply more work.)</small></p>
<p>I had my apprehensions when I heard Firefox was jumping up a full version... I was determined to not make the same foolish mistake twice... So I did my research.</p>
<p>Good news? It passes the <a href="http://www.webstandards.org/files/acid2/test.html" rel="nofollow" title="Acid2 Test">Acid2 test</a>!</p>
<div class="thumbrow"> <a href="/images/blog/ff3/acid-ff2.png" title="Firefox 2 Acid2 Results" rel="lightbox[acid]"><img src="/images/blog/ff3/acid-ff2-th.png" alt="Firefox 2 Acid2 Results" /></a> <a href="/images/blog/ff3/acid-ff3.png" title="Firefox 3 Acid2 Results" rel="lightbox[acid]"><img src="/images/blog/ff3/acid-ff3-th.png" alt="Firefox 3 Acid2 Results" /></a> <a href="/images/blog/ff3/acid-ie7.png" title="Internet Explorer 7 Acid2 Results" rel="lightbox[acid]"><img src="/images/blog/ff3/acid-ie7-th.png" alt="Internet Explorer 7 Acid2 Results" /></a> <span>From left to right: Firefox 2, Firefox 3, Internet Explorer 7. Click for larger image.</span> </div>
<p>Looks like we aren't going to have to test in <em>both</em> Firefox 2 and 3*.</p>
<p><small class="inset">* That is, unless you are using the newly-proprietary/implemented enhancements, such as getElementsByClassName <ins class="bl">ALSO</ins> While it is fantastic that the newest Firefox fixes CSS issues, it's not retroactive, so visitors still using FF2 will still have the same problems as before. I recommend waiting until usage is below 5% to completely phase it out.</small></p>
<p>So, here are what I consider to be the most important things for us Web Designer/Developers to be aware of.</p>
<h3>1) Full-Page Zoom</h3>
<p>This new scaling scales everything on the page (a la Opera and IE7), not just text. I wouldn't say this means that we can stop using em's for text sizing, but it's good to see that accessibility is beginning to become more supported by the software we use, so it isn't dependant on the designer.</p>
<div class="thumbrow">
<a href="/images/blog/ff3/zoom-ff2.gif" title="Firefox 2 Zoom (Animated Gif)" rel="lightbox[zoom]"><img src="/images/blog/ff3/zoom-ff2-th.png" alt="Firefox 2 Zoom" /></a>
<a href="/images/blog/ff3/zoom-ff3.gif" title="Firefox 3 Zoom (Animated Gif)" rel="lightbox[zoom]"><img src="/images/blog/ff3/zoom-ff3-th.png" alt="Firefox 3 Zoom" /></a>
<span>Left: Firefox 2 Zoom, Right: Firefox 3 Zoom. Click for larger image.</span>
</div>
<p>tracker: <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=4821">https://bugzilla.mozilla.org/show_bug.cgi?id=4821</a></p>
<h3>2) Animated PNG (APNG) Support</h3>
<p>While I don't look forward to seeing alpha-transparent rotating "Email Me" graphics all over the place like it's 1998 again, I am very pleased to see APNG finally getting implemented. While it wont become a standard for quite a while, it's a step in the right direction. One thing to note is that if your browser does not support APNG (but does support PNG) it will simply render the first frame of the PNG.</p>
<div class="thumbrow" id="apngcontainer">
<img src="/images/blog/ff3/apng-animation.gif" alt="Animated GIF" />
<img src="/images/blog/ff3/apng-animation.png" alt="Animated PNG" />
<span>Left: Animated GIF, Right: Animated PNG<br />
Use the links below to change background color (JavaScript Required)<br />
<!-- Please forgive the obtrusive JS! -->
<a href="javascript:void(0)" title="Swap Color" onclick="document.getElementById('apngcontainer').style.backgroundColor='green'">Green</a> | <a href="javascript:void(0)" title="Swap Color" onclick="document.getElementById('apngcontainer').style.backgroundColor='pink'">Pink</a> | <a href="javascript:void(0)" title="Swap Color" onclick="document.getElementById('apngcontainer').style.backgroundColor='red'">Red</a> | <a href="javascript:void(0)" title="Swap Color" onclick="document.getElementById('apngcontainer').style.backgroundColor='blue'">Blue</a> | <a href="javascript:void(0)" title="Swap Color" onclick="document.getElementById('apngcontainer').style.backgroundColor='black'">Black</a> | <a href="javascript:void(0)" title="Swap Color" onclick="document.getElementById('apngcontainer').style.backgroundColor='orange'">Orange</a> | <a href="javascript:void(0)" title="Swap Color" onclick="document.getElementById('apngcontainer').style.backgroundColor='white'">White</a>
<br />
Image Credits go to http://www.gamani.com/apng.htm</span>
</div>
<p>tracker: <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=257197">https://bugzilla.mozilla.org/show_bug.cgi?id=257197</a></p>
<!-- Please fogive the misplaced script tags! -->
<script type="text/javascript">
navigator.registerProtocolHandler('mailto', 'https://mail.google.com/mail?view=cm&#038;tf=0&#038;to=%s', 'Google Mail');
navigator.registerProtocolHandler('validate', 'http://validator.w3.org/check?uri=%s', 'W3C HTML Validation')
</script>
<h3>3) Support for arbitrary protocols</h3>
<p>This will allow you to map protocols such as <a href="mailto:nobody@nowhere.com" title="Test 'mailto' Protocol Handler">mailto:nobody@nowhere.com</a> (Which will use Gmail) or <a href="validate:http://www.phazm.com/" title="Test 'Validate' Protocol Handler">validate:http://www.phazm.com/</a> (Which will use the W3C validation service) to a proprietary handler, which will allow you to select it instead of only using the default.</p>
<div class="thumbrow">
<a href="/images/blog/ff3/handler.png" title="Protocol Handler UI" rel="lightbox"><img src="/images/blog/ff3/handler-th.png" alt="Protocol Handler UI" /></a>
<span>UI for notification/accepting Protocol Handlers. Click for larger image.</span>
</div>
<p>tracker: <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=372441">https://bugzilla.mozilla.org/show_bug.cgi?id=372441</a></p>
<h3>4) getElementsByClassName</h3>
<p>This has been available for some time using some frameworks, but now it's in the DOM! Now we will be able to loop through all elements with a specific class on our document. The original specification is in the HTML 5 working draft. (link: http://www.whatwg.org/specs/web-apps/current-work/#getelementsbyclassname).</p>
<p>tracker: <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=357450">https://bugzilla.mozilla.org/show_bug.cgi?id=357450</a></p>
<h3>5) Support for offline web apps</h3>
<p>The support has been added to allow web applications to be run offline.  Unfortunately, it will require the apps to accommodate this new system, and thus far, there has been no word from Google saying they intend to code Gmail or any of their other apps to be used offline, but I'm sure it will come in time.</p>
<p>Demo: <a href="http://starkravingfinkle.org/blog/2007/02/firefox-3-offline-app-demo/" rel="nofollow">http://starkravingfinkle.org/blog/2007/02/firefox-3-offline-app-demo/</a><br />tracker: <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=367447">https://bugzilla.mozilla.org/show_bug.cgi?id=367447</a></p>
<h3>Other useful additions:</h3>
<h4>Now properly supported:</h4>
<ul>
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=18217"><code>display: inline-table</code></a></li>
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=9458"><code>display: inline-block</code></a></li>
</ul>
<h4>Added support for:</h4>
<ul>
<li><code>onCut</code></li>
<li><code>onCopy</code></li>
<li><code>onPaste</code></li>
<li><code>onBeforeCut</code></li>
<li><code>onBeforeCopy</code></li>
<li><code>onBeforePaste</code></li>
</ul>
<p>
demo: <a href="https://bugzilla.mozilla.org/attachment.cgi?id=272228">https://bugzilla.mozilla.org/attachment.cgi?id=272228</a><br />
tracker: <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=280959">https://bugzilla.mozilla.org/show_bug.cgi?id=280959</a></p>
<h4>contentEditable</h4>
<p>contentEditable allows you to do inline editing of text.</p>
<p>demo: <a href="https://bugzilla.mozilla.org/attachment.cgi?id=157048">https://bugzilla.mozilla.org/attachment.cgi?id=157048</a><br />
tracker: <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=237964">https://bugzilla.mozilla.org/show_bug.cgi?id=237964</a></p>
<h4>Resizable=<del>no</del><ins>yes</ins></h4>
<p>With Firefox 3 , the window.open property "resizable=no" is ignored, so all pop up windows will now be resizable.</p>
<p><a href="javascript:void(0)" onclick="window.open('http://www.google.com/', 'Can you resize?','width=100,height=100,resizable=no')">Click here to open a window with resizable=no</a><br />
tracker: <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=177838">https://bugzilla.mozilla.org/show_bug.cgi?id=177838</a></p>
<h4>Long Tool tips</h4>
<p>Now, instead of having one huge line for a tool tip, they will wrap over several lines.</p>
<p>To test, hover over <abbr title="This is an intentionally long title attribute, which will wrap in Firefox 3, but not Firefox 2. This will allow you to create exceptionally descriptive alternate text for links and/or images, so you will no longer have any excuse. 'A picture means a thousand words' - I don't know if the tool tip will fit one thousand words, maybe one day I will find out.">this</abbr><br />
tracker: <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=218223">https://bugzilla.mozilla.org/show_bug.cgi?id=218223</a></p>
<h4>Printing &amp; Absolute Position</h4>
<p>Containers that span multiple pages and are absolutely positioned will now correctly wrap to the next page instead of just being cut off.</p>
<p>tracker: <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=154892">https://bugzilla.mozilla.org/show_bug.cgi?id=154892</a></p>
<h3>A few notes:</h3>
<p>By default, you will not be able to run any extensions that haven't been updated to be used with Firefox 3 . However, if you go into about:config, right click, then go to 'New' =&gt; '<code>Boolean</code>' - Enter, "<code>extensions.checkCompatibility</code>" and hit '<code>OK</code>' then click "<code>false</code>" and restart, you will be able to use the extensions that don't break.<br />
<strong>WARNING:</strong> Some extensions will actually crash Firefox 3, so if that happens, start up in safe mode with all extensions disabled, then either uninstall the extension(s) that are breaking it, or go set checkCompatibility to "true."</p>
<p><small>This is somewhat unrelated, but I don't want to make a new blog entry for it, and it is pretty useful: You can use <a href="https://addons.mozilla.org/en-US/firefox/addon/5972">RAMBack</a> in Firefox 3 to free up a bunch of memory that it uses.</small></p>
<h3>Thanks for listening</h3>
<p>If you found this helpful or informative, I would really appreciate it if you left a comment... it gets so lonely at nights!</p>
<p><small>A <a href="http://digg.com/design/5_Ways_Firefox_3_will_affect_Web_Developers_pics_examples" title="Digg it">digg</a> wouldn't hurt either...</small></p>

<p><a href="http://feeds.feedburner.com/~a/NotesFromPhazm?a=b5NTXk"><img src="http://feeds.feedburner.com/~a/NotesFromPhazm?i=b5NTXk" border="0"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.phazm.com/notes/browser-compatibility/firefox-3-web-developers/feed/</wfw:commentRss>
		<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=NotesFromPhazm&amp;itemurl=http%3A%2F%2Fwww.phazm.com%2Fnotes%2Fbrowser-compatibility%2Ffirefox-3-web-developers%2F</feedburner:awareness><feedburner:origLink>http://www.phazm.com/notes/browser-compatibility/firefox-3-web-developers/</feedburner:origLink></item>
		<item>
		<title>Designer Interview: Nik Ainley</title>
		<link>http://feeds.feedburner.com/~r/NotesFromPhazm/~3/218264051/</link>
		<comments>http://www.phazm.com/notes/inspiration/designer-interview-nik-ainley/#comments</comments>
		<pubDate>Mon, 12 Nov 2007 14:05:50 +0000</pubDate>
		<dc:creator>Jon Hughes</dc:creator>
		
		<category><![CDATA[inspiration]]></category>

		<category><![CDATA[inverviews]]></category>

		<guid isPermaLink="false">http://www.phazm.com/notes/inspiration/designer-interview-nik-ainley/</guid>
		<description><![CDATA[I am speaking to Nik Ainley, a UK based designer with a passion for producing awe-inspiring art and illustrations. You'll see what I mean in a few minutes.


JH: Nik, Thank you so much for taking the time for this interview.

JH: So how long have you been doing design?
Nik: It's been about 5 years now, although [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.phazm.com/images/blog/Nik-Ainley/photo.jpg" alt="Nik Ainley" title="Nik Ainley" class="portrait" />I am speaking to Nik Ainley, a UK based designer with a passion for producing awe-inspiring art and illustrations. You'll see what I mean in a few minutes.</p>
<span id="more-9"></span>
<div class="interview">
<p><abbr title="Jon Hughes">JH:</abbr> Nik, Thank you so much for taking the time for this interview.</p>
<img src="http://www.phazm.com/images/blog/Nik-Ainley/rainbow.jpg" alt="" />
<p><abbr title="Jon Hughes">JH:</abbr> So how long have you been doing design?</p>
<p class="code blogquote"><abbr title="Nik Ainley">Nik:</abbr> It's been about 5 years now, although at the start it could barely be called design, just random Photoshop doodling.</p>
<img src="http://www.phazm.com/images/blog/Nik-Ainley/type.jpg" alt="" />
<p><abbr title="Jon Hughes">JH:</abbr> Have you always done design, or did you start in another field?</p>
<p class="code blogquote"><abbr title="Nik Ainley">Nik:</abbr> Well it's the only job I've done professionally. I started off as a web designer based on my ability to produce graphics and the fact that web coding is pretty easy. Since then I have moved into pure illustration and design as I find it more creatively rewarding. I actually have a degree in physics though, and was probably going to be using that for my career before I found design.</p>
<img src="http://www.phazm.com/images/blog/Nik-Ainley/20-20-visions.jpg" alt="" />
<p><abbr title="Jon Hughes">JH:</abbr> What made you want to become a designer?</p>
<p class="code blogquote"><abbr title="Nik Ainley">Nik:</abbr> I just enjoyed it. I started off doing it as a hobby, and when I realized I could make a career out of it, it wasn't too hard a decision to make.</p>
<img src="http://www.phazm.com/images/blog/Nik-Ainley/100-games.jpg" alt="" />
<p><abbr title="Jon Hughes">JH:</abbr> Do you freelance for a living, or do you have an employer?</p>
<p class="code blogquote"><abbr title="Nik Ainley">Nik:</abbr> I freelance, all my work is commission based.</p>
<img src="http://www.phazm.com/images/blog/Nik-Ainley/101-better-images.jpg" alt="" />
<p><abbr title="Jon Hughes">JH:</abbr> What do you do in your spare time?</p>
<p class="code blogquote"><abbr title="Nik Ainley">Nik:</abbr> Oh all the usual stuff, going out for drinks, reading, playing games down the pub, computer games. I go to see a lot of live music as well. I try to make it to a gig every 2 weeks at the least.</p>
<img src="http://www.phazm.com/images/blog/Nik-Ainley/face.jpg" alt="" />
<p><abbr title="Jon Hughes">JH:</abbr> Would you mind giving our readers a brief overview of what an average day is like for Nik Ainley?</p>
<p class="code blogquote"><abbr title="Nik Ainley">Nik:</abbr> That's very difficult as it changes massively depending on if I have a lot of work on or not. If I don't I could literally check my emails and then spend the rest of the day out or messing about the house. If I've got a serious job on and need to get work I might spend 12 hours at the computer and barely talk to anyone.</p>
<img src="http://www.phazm.com/images/blog/Nik-Ainley/major-wound.jpg" alt="" />
<p><abbr title="Jon Hughes">JH:</abbr> Looking over your art, you have an extremely diverse portfolio, ranging from melting faces to elaborate typography... where do you find your inspiration?</p>
<p class="code blogquote"><abbr title="Nik Ainley">Nik:</abbr> I just like to make things that look nice and try to have a go at every image type within my images. If I could paint, or do complex 3D art or character design I'd be doing that as well. Unfortunately I'm not that multi-talented.</p>
<img src="http://www.phazm.com/images/blog/Nik-Ainley/melting-face.jpg" alt="" />
<p><abbr title="Jon Hughes">JH:</abbr> If you ever find yourself short on creativity, what sorts of activities do you do to get it back?</p>
<p class="code blogquote"><abbr title="Nik Ainley">Nik:</abbr> I find you have to work it through. I just try and get all the crap ideas out of my head and onto canvas. Until the dodgy ideas are out I don't get new ones coming in.</p>
<img src="http://www.phazm.com/images/blog/Nik-Ainley/UNICEF.jpg" alt="" />
<p><abbr title="Jon Hughes">JH:</abbr> A lot of your work is reminiscent of traditional artwork, do you like free hand drawing (inks, painting, etc) as well?</p>
<p class="code blogquote"><abbr title="Nik Ainley">Nik:</abbr> Not at all actually, I am a purely digital artist. Partly because I've never really done traditional art and so would be rubbish at it, but also because I have very literal interest in it. The power of the computer for producing art is so exceptional I would feel like my hands were tied with traditional art.</p>
<img src="http://www.phazm.com/images/blog/Nik-Ainley/type-tips.jpg" alt="" />
<p><abbr title="Jon Hughes">JH:</abbr> I see you have done a lot of work for well-known magazines, what tips can you give our readers on getting these types of deals?  Did you contact them, or vice-versa?</p>
<p class="code blogquote"><abbr title="Nik Ainley">Nik:</abbr> Well they contacted me, I think that's mostly how it works. Although for Digit I did send stuff in for their showcase and ended up being commissioned and doing the cover. That's a good way to get their attention, otherwise I think they spend a lot of time looking for new talent so a website is essential.</p>
<img src="http://www.phazm.com/images/blog/Nik-Ainley/staring.jpg" alt="" />
<p><abbr title="Jon Hughes">JH:</abbr> What has been the most fun project to work on so far?</p>
<p class="code blogquote"><abbr title="Nik Ainley">Nik:</abbr> I couldn't pick one really, generally I have the most fun when I've just started a personal picture and I'm getting something I like going. Since I have complete creative freedom with these projects and no deadline it can great fun just experimenting.</p>
<img src="http://www.phazm.com/images/blog/Nik-Ainley/strange.jpg" alt="" />
<p><abbr title="Jon Hughes">JH:</abbr> On your page <a href="http://www.shinybinary.com/" rel="nofollow">(ShinyBinary.com)</a> you list many programs that you use... what are the primary 3 for the majority of your designs?</p>
<p class="code blogquote"><abbr title="Nik Ainley">Nik:</abbr> Photoshop, Photoshop and Photoshop. I spend nearly all my time in it, the others are just for additional details generally.</p>
<img src="http://www.phazm.com/images/blog/Nik-Ainley/plunge.jpg" alt="" />
<p><abbr title="Jon Hughes">JH:</abbr> What is your favorite website? (besides Phazm of course...)</p>
<p class="code blogquote"><abbr title="Nik Ainley">Nik:</abbr> Probably something boring like the BBC news site. I waste half of my time reading any old rubbish on that site.</p>
<img src="http://www.phazm.com/images/blog/Nik-Ainley/grassnation.jpg" alt="" />
<p><abbr title="Jon Hughes">JH:</abbr> Do you do much web design?</p>
<p class="code blogquote"><abbr title="Nik Ainley">Nik:</abbr> Not anymore. As I said I was a full time web designer for 2 and a half years or so, spending most of my time writing HTML and CSS and producing web graphics, I found it a bit dull though.</p>
<img src="http://www.phazm.com/images/blog/Nik-Ainley/never.jpg" alt="" />
<p><abbr title="Jon Hughes">JH:</abbr> Imagine yourself in 20 years... what do you see yourself doing?</p>
<p class="code blogquote"><abbr title="Nik Ainley">Nik:</abbr> Absolutely no idea… I hope it's creative though. I'd be disappointed if I was still doing the same thing though, I need to move on.</p>
<img src="http://www.phazm.com/images/blog/Nik-Ainley/keep-it-together.jpg" alt="" />
<p><abbr title="Jon Hughes">JH:</abbr> What is your favorite beverage?</p>
<p class="code blogquote"><abbr title="Nik Ainley">Nik:</abbr> A nice cup of tea.</p>
<img src="http://www.phazm.com/images/blog/Nik-Ainley/icarus.jpg" alt="" />
<p><abbr title="Jon Hughes">JH:</abbr> Any additional tips you would like to impart on our readers?</p>
<p class="code blogquote"><abbr title="Nik Ainley">Nik:</abbr> Nope, I'm sure they've got more sense than I do.</p>
<img src="http://www.phazm.com/images/blog/Nik-Ainley/only-this.jpg" alt="" />
<p><abbr title="Jon Hughes">JH:</abbr> Thank you again for your time, Nik. Your art is truly inspiring!</p>
</div>
<p>You can buy prints of Nik Ainley's art <a href="http://www.clickforart.com/artist.asp?artistid=30&amp;artid=214" rel="nofollow">here</a>.</p>
<p><a href="http://feeds.feedburner.com/~a/NotesFromPhazm?a=3d2TU4"><img src="http://feeds.feedburner.com/~a/NotesFromPhazm?i=3d2TU4" border="0"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.phazm.com/notes/inspiration/designer-interview-nik-ainley/feed/</wfw:commentRss>
		<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=NotesFromPhazm&amp;itemurl=http%3A%2F%2Fwww.phazm.com%2Fnotes%2Finspiration%2Fdesigner-interview-nik-ainley%2F</feedburner:awareness><feedburner:origLink>http://www.phazm.com/notes/inspiration/designer-interview-nik-ainley/</feedburner:origLink></item>
		<item>
		<title>Stop the Hate - IE6 Isn’t So Bad!</title>
		<link>http://feeds.feedburner.com/~r/NotesFromPhazm/~3/218264053/</link>
		<comments>http://www.phazm.com/notes/productivity/stop-the-hate-ie6-isnt-so-bad/#comments</comments>
		<pubDate>Wed, 24 Oct 2007 06:47:24 +0000</pubDate>
		<dc:creator>Jon Hughes</dc:creator>
		
		<category><![CDATA[browser compatibility]]></category>

		<category><![CDATA[productivity]]></category>

		<guid isPermaLink="false">http://www.phazm.com/notes/uncategorized/stop-the-hate-ie6-isnt-so-bad/</guid>
		<description><![CDATA[I have recently been getting mildly irritated at all of the "Just don't code for Internet Explorer 6 and people will stop using it" blog entries I've been seeing lately. I consider it a huge problem in the mentality of a designer when they disregard a large portion of visitors and/or customers. No disrespect to [...]]]></description>
			<content:encoded><![CDATA[<p>I have recently been getting mildly irritated at all of the "<a href="http://www.webdesignerwall.com/general/trash-all-ie-hacks/" rel="nofollow" title="Nick La - Web Designer Wall">Just don't code for Internet Explorer 6 and people will stop using it</a>" blog entries I've been seeing lately. I consider it a huge problem in the mentality of a designer when they disregard a large portion of visitors and/or customers. No disrespect to <a href="http://www.webdesignerwall.com/general/trash-all-ie-hacks/" rel="nofollow" title="Nick La's post on IE6">Nick La</a>, but simply "giving up" on IE6 is not (at this time) a viable solution, especially because IE6 still has the largest user base.</p>
<p>The fact is, IE6 is not that hard to code for, as long as you have a good understanding of Semantic XHTML, you shouldn't have much of a problem. In this post, I'm going to outline some of the steps you can take to reduce the time it takes to develop your pages for Internet Explorer 6.<br/>
</p>
<span id="more-5"></span>
<h4>The Stats</h4>
<p>According to <a href="http://www.thecounter.com/stats/2007/October/browser.php" rel="nofollow" title="TheCounter.com Stats">TheCounter.com</a>, IE6 is at 50%, the next largest being IE7 at 24% and following that is FF, at 13%.</p>
<p class="img"><img src="http://www.phazm.com/images/blog/stop-hate-browser-stats.png" alt="TheCounter.com's Browser Statistics"/><br/>
<em>Bar graph showing top 3 browsers. -- Image courtesy of <a href="http://www.thecounter.com/stats/2007/October/browser.php" rel="nofollow" title="TheCounter.com Stats">TheCounter.com</a></em></p>
<p>Of course, these results will differ from your own website, which is a much better reference. For instance, according to <a href="http://www.phazm.com/" title="Phazm Webdesign">Phazm.com</a>'s statistics, IE7 is (very) slightly more used than IE6 -- 24.7% to 24.5%.</p>
<p>Either way you look at it, Internet Explorer 6 still constitutes a very large portion of visits. I don't know why anyone would suggest abandoning 25-50% of their traffic, but if you ask me, it's not a good decision. Read below for some tips on speeding up the entire process.</p>
<h4>Reset Your CSS</h4>
<p>There are two main differing behaviors in browsers: Their default rendering of HTML elements, and how they handle CSS. To start with, I recommend you always (or whenever possible) use a CSS Reset. Resetting the CSS takes away one of the differing behaviors between multiple browsers. For example, IE6 and Firefox both give &lt;p&gt; tags a default margin, however, that margin is slightly different between both browsers. When you eliminate that behavior, and set everything to have no default(browser) styling, you make your job a whole lot easier. <a href="http://meyerweb.com/" rel="nofollow" title="Eric Meyer">Eric Meyer</a> has created a fantastic CSS Reset which you can find <a href="http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/" rel="nofollow" title="Eric Meyer's Reset CSS">here</a>.
</p> 
<p>There are several ways you can use this CSS. I prefer to import it within my main/global CSS File.</p>
<p class="code">@import url("reset.css");</p>
<p>Simply put this at the top of the CSS file that is linked on every page on your site, and it will set nearly everything back to have no styling whatsoever. Obviously, there are downsides to doing this. The first is that you really need to start from a clean slate, because any elements that depend on the default margin of a header tag are going to break. The other downside is having to re-declare styles, such as making a list have bullets, making text within  italic, and so on.</p>
<h4>Conditional Comments</h4>
<p>Using conditional comments, most (if not all) CSS hacks can be avoided. Because we only have to worry about the rendering of the CSS, and not the default styling (due to using the CSS Reset) this can actually go quite fast.</p>
<p>Now, some say that you shouldn't use a conditional comment, due to it being proprietary Microsoft code, but I disagree. Not only does your page still validate, other browsers simply ignore the code - I have never had an instance where a properly formatted conditional comment went awry in any browser.</p>
<p>Here is the syntax for creating a conditional comment:</p>
<p class="code">&lt;!--[if (condition) IE (version)]&gt;<br />
Code to run<br />
&lt;![endif]--&gt;</p>
<p>Possible conditions/operators:</p>
<ul>
<li>lt = Less Than</li>
<li>lte =Less Than or Equal To</li>
<li>gt = greater than</li>
<li>gte = Greater Than or Equal To</li>
<li>! = Not</li>
</ul>
<p>Using the above operators, if you want to have a stylesheet for all Internet Explorers below IE7, you would put the following in your code within the  tags:</p>
<p class="code">&lt;!--[if lt IE 7]&gt;<br />
&lt;link rel="stylesheet" href="LegacyBrowser.css" type="text/CSS" /&gt;<br />
&lt;![endif]--&gt;</p>
<p>This will call a separate CSS file, called <span class="code">LegacyBrowser.css</span>, which will only affect IE versions below IE7.</p>
<h4>Styling the Page</h4>
<p>Now, get your page working in Firefox.  Once you have done that (completely) you open up your page in IE6, and start creating over-ride classes as necessary.  If <span class="code">.imagedisplay</span> is 3 pixels too far to the left, simply add in your LegacyBrowser.css:</p>
<p class="code">.imagedisplay { margin-right : -3px; }</p>
<p>or something similar, to get the desired effect.</p>
<p>Note that if you have already specified margin-right, you may need to add <span class="code">!important</span> to the mix, like so:</p>
<p class="code">.imagedisplay { margin-right : -3px !important; }</p>
<p>This is a very loose example, and in most cases you will simply replace a margin/padding with a slightly increased or decreased value, and use <span class="code">!important</span>.</p>
<p>In this way, you can avoid using CSS Hacks that could possibly break in future browsers, and you give yourself more control over how your page displays in Internet Explorer.</p>
<h4>Feedback</h4>
<p>I would love your comments regarding this topic. Do you agree that IE6 is still prevalent enough to be worth the additional coding time, or do you think it is a waste of time to cater to a dying browser? Let me know!</p>
<p><a href="http://feeds.feedburner.com/~a/NotesFromPhazm?a=kSFobB"><img src="http://feeds.feedburner.com/~a/NotesFromPhazm?i=kSFobB" border="0"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.phazm.com/notes/productivity/stop-the-hate-ie6-isnt-so-bad/feed/</wfw:commentRss>
		<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=NotesFromPhazm&amp;itemurl=http%3A%2F%2Fwww.phazm.com%2Fnotes%2Fproductivity%2Fstop-the-hate-ie6-isnt-so-bad%2F</feedburner:awareness><feedburner:origLink>http://www.phazm.com/notes/productivity/stop-the-hate-ie6-isnt-so-bad/</feedburner:origLink></item>
	<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetFeedData?uri=NotesFromPhazm</feedburner:awareness></channel>
</rss><!-- Dynamic Page Served (once) in 0.551 seconds -->
