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

<channel>
	<title>Tutorialzine &#187; PHP</title>
	<atom:link href="http://tutorialzine.com/category/tutorials/php-tutorials/feed/" rel="self" type="application/rss+xml" />
	<link>http://tutorialzine.com</link>
	<description>PHP MySQL jQuery CSS Tutorials, Resources and Freebies</description>
	<lastBuildDate>Wed, 28 Jul 2010 17:33:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>An AJAX Click to Appreciate Badge</title>
		<link>http://tutorialzine.com/2010/07/click-to-appreciate-badge-ajax-jquery-css/</link>
		<comments>http://tutorialzine.com/2010/07/click-to-appreciate-badge-ajax-jquery-css/#comments</comments>
		<pubDate>Wed, 28 Jul 2010 17:33:42 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=1036</guid>
		<description><![CDATA[If you've ever dropped by Behance, you've probably noticed their appreciate badge, with which you can show your appreciation for somebody's creative work. In this tutorial we are making an improved version, which you can include in every page of your site with a bit of jQuery magic.]]></description>
			<content:encoded><![CDATA[<p>When you publish something online, there are not that many ways to determine whether people like what you have to say. Comments, the cornerstone of blogging, are too demanding, and users often prefer not to post one. If you&#8217;ve dropped by <a href="http://www.behance.net/" target="_blank">Behance</a>, you&#8217;ve probably noticed their <strong>appreciate badge</strong>, which is a neat solution to this exact problem. With it people share their appreciation for somebody&#8217;s work.</p>
<p>Today we are implementing such a badge, which you can include in every page of your website with a bit of jQuery magic. So go ahead and download the zip from the button above (<em><strong>PSD included!</strong></em>) and continue with the tutorial.</p>
<h3>The Database Schema</h3>
<p>The script we are doing today uses two tables. The first holds one record for each of the pages which have the appreciate button enabled. The second one stores the IP of the person that voted along the unique ID of the page. This way we can easily determine whether the person has previously voted for the page and display the appropriate version of the button (active or disabled).</p>
<div id="attachment_1040" class="wp-caption alignnone" style="width: 630px"><img class="size-full wp-image-1040" title="Table Schema appreciate_pages" src="http://tutorialzine.com/wp-content/uploads/2010/07/i11.png" alt="Table Schema appreciate_pages" width="620" height="260" /><p class="wp-caption-text">Table Schema appreciate_pages</p></div>
<p>The hash field holds an <strong>MD5 </strong>sum of the URL of the page. This way we add an <strong>UNIQUE </strong>index which will speed up the <em>selects</em> we run on the records, as well ensure there are no duplicate records in the table. The <strong>appreciated </strong>column holds the number of appreciations of the pages.</p>
<div id="attachment_1041" class="wp-caption alignnone" style="width: 630px"><img class="size-full wp-image-1041" title="Table Schema appreciate_votes" src="http://tutorialzine.com/wp-content/uploads/2010/07/i21.png" alt="Table Schema appreciate_votes" width="620" height="260" /><p class="wp-caption-text">Table Schema appreciate_votes</p></div>
<p>The <strong>appreciate_votes</strong> table contains the IP of the person that has voted (in the form of an integer), and the id of the page from the <strong>appreciate_pages</strong> table. The timestamp is automatically updated to the current time when an insert occurs.</p>
<p>You can create these two tables by running the code from <strong>tables.sql</strong> in the <strong>SQL </strong>section of <strong>phpMyAdmin</strong> from the downloadable archive, part of this tutorial.</p>
<h3>Step 1 &#8211; XHTML</h3>
<p>Lets start with the XHTML part of the tutorial. The markup of the page is extremely simple. To have the appreciate button functioning, you just need to provide a  container in which the button is inserted, and an optional element,  which holds the total number of clicks on the button. You can safely omit the  latter one, leaving you with only one div to code.</p>
<h4>page.html</h4>
<pre class="brush:html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;
&lt;title&gt;An AJAX Click To Appreciate Badge&lt;/title&gt;

&lt;link rel="stylesheet" type="text/css" href="styles.css" /&gt;
&lt;link rel="stylesheet" type="text/css" href="appreciateMe/appreciate.css"/&gt;
&lt;/head&gt;

&lt;body&gt;

&lt;div id="countDiv"&gt;&lt;/div&gt;
&lt;div id="main"&gt;&lt;/div&gt;

&lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"&gt;&lt;/script&gt;
&lt;script src="appreciateMe/plugin.js" type="text/javascript"&gt;&lt;/script&gt;
&lt;script src="script.js" type="text/javascript"&gt;&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>In the page above, you can see that I am  including two stylesheet files. The first is <strong>styles.css,</strong> which is used to style the page, and <strong>appreciate.css</strong>, which is located in the plugin directory, and is responsible for the styling of the appreciate button.</p>
<p>Before the closing body tag, you can see that I also include the jQuery library from Google&#8217;s CDN repository, the <strong>plugin.js</strong> file and <strong>script.js</strong>, which uses the plugin to create the button on the page. You will only need to change the contents of <strong>script.js</strong> to make the script working on your pages.</p>
<div id="attachment_1042" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/07/click-to-appreciate-badge-ajax-jquery-css/page.html"><img class="size-full wp-image-1042" title="Click To Appreciate Button" src="http://tutorialzine.com/wp-content/uploads/2010/07/i3.png" alt="Click To Appreciate Button" width="620" height="460" /></a><p class="wp-caption-text">Click To Appreciate - looks good on both dark and light backgrounds</p></div>
<h3>Step 2 &#8211; PHP</h3>
<p>PHP handles the database interactions and is on the backend of the AJAX requests. Most of the script logic is located in c <strong>script.php</strong> which you can see below. But first lets take a look at <strong>connect.php,</strong> which handles the database connection.</p>
<h4>appreciateMe/connect.php</h4>
<pre class="brush:php">$db_host = 'localhost';
$db_user = 'YourUsername';
$db_pass = 'YouPassword';
$db_name = 'NameOfDB';

@$mysqli = new mysqli($db_host, $db_user, $db_pass, $db_name);

if (mysqli_connect_errno()) {
	die('&lt;h1&gt;Could not connect to the database&lt;/h1&gt;');
}

$mysqli-&gt;set_charset("utf8");
</pre>
<p>Up until now, we&#8217;ve always used the old <strong>mysql</strong> extension for database connections under PHP, as it is a bit easier to use and I wanted to keep the code compatible with PHP 4. However, with the recent announcement that WordPress (our favorite blogging engine) will be <a href="http://wordpress.org/news/2010/07/eol-for-php4-and-mysql4/" target="_blank">dropping support for that version of PHP</a>, I decided that it is time to also make the switch to the new version &#8211; MySQLi (MySQL improved).</p>
<p>As you can see from the code above, the only major difference with the old way we connected to a database, is that here we create a <strong>MySQLi</strong> object instead of using the <strong>mysql_</strong> functions. Also, as you will see in a moment, when we query the database a MySQL resource object is returned, which in turn has its own set of methods. This might sound intimidating, but it will become perfectly clear once you see it in action.</p>
<h4>appreciateMe/script.php</h4>
<pre class="brush:php">/* Setting the error reporting level */
error_reporting(E_ALL ^ E_NOTICE);
include 'connect.php';

if(!$_GET['url'] || !filter_input(INPUT_GET,'url',FILTER_VALIDATE_URL)){
	exit;
}

$pageID			= 0;
$appreciated	= 0;
$jsonArray		= array();
$hash			= md5($_GET['url']);
$ip				= sprintf('%u',ip2long($_SERVER['REMOTE_ADDR']));

// $result is an object:
$result = $mysqli-&gt;query("SELECT id,appreciated FROM appreciate_pages WHERE hash='".$hash."'");

if($result)
{
	list($pageID,$appreciated) = $result-&gt;fetch_row();
	// fetch_row() is a method of result
}

// The submit parameter denotes that we need to write to the database

if($_GET['submit'])
{
	if(!$pageID)
	{
		// If the page has not been appreciated yet, insert a new
		// record to the database.

		$mysqli-&gt;query("
			INSERT INTO appreciate_pages
			SET
				hash='".$hash."',
				url='".$mysqli-&gt;real_escape_string($_GET['url'])."'"
		);

		if($mysqli-&gt;affected_rows){

			// The insert_id property contains the value of
			// the primary key. In our case this is also the pageID.

			$pageID = $mysqli-&gt;insert_id;
		}
	}

	// Write the vote to the DB, so the user can vote only once

	$mysqli-&gt;query("
		INSERT INTO appreciate_votes
		SET
			ip = ".$ip.",
			pageid = ".$pageID
	);

	if($mysqli-&gt;affected_rows){
		$mysqli-&gt;query("
			UPDATE appreciate_pages
			SET appreciated=appreciated+1 WHERE id=".$pageID
		);

		// Increment the appreciated field
	}

	$jsonArray = array('status'=&gt;1);
}
else
{
	// Only print the stats

	$voted = 0;

	// Has the user voted?
	$res = $mysqli-&gt;query("
		SELECT 1 FROM appreciate_votes
		WHERE ip=".$ip." AND pageid=".$pageID
	);

	if($res-&gt;num_rows){
		$voted = 1;
	}

	$jsonArray = array('status'=&gt;1,'voted'=&gt;$voted,'appreciated'=&gt;$appreciated);
}

// Telling the browser to interpret the response as JSON:
header('Content-type: application/json');

echo json_encode($jsonArray);
</pre>
<p>The script handles two different types of AJAX requests &#8211; <strong>read only request</strong> (which returns a JSON object with information about the number of appreciations of the page, and whether the current user has clicked the button), and <strong>write requests </strong>(which save the visitor&#8217;s vote to the database, and if necessary, save the page URL and hash as well).</p>
<p>As you an see in the code snippet above, one of the first things that the script does is to calulate the <strong>MD5</strong> hash of the page. This is used as a unique key in the database, as URLs have unlimited length which is incompatible with MySQL&#8217;s UNIQUE keys. As an MD5 hash is unique for most practical purposes, we can safely use it in our selects and inserts, instead of the long URL addresses.</p>
<p>In the last line of the code, we convert the <strong>$jsonArray</strong> array into a valid JSON object with the inbuilt <strong>json_encode</strong> PHP function, and output it with a <strong>applicatoin/json</strong> content type.</p>
<div id="attachment_1043" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/07/click-to-appreciate-badge-ajax-jquery-css/page.html"><img class="size-full wp-image-1043" title="Click To Appreciate - Inactive" src="http://tutorialzine.com/wp-content/uploads/2010/07/i4.png" alt="Click To Appreciate - Inactive" width="620" height="260" /></a><p class="wp-caption-text">Click To Appreciate - Inactive</p></div>
<h3>Step 3 &#8211; jQuery</h3>
<p>Inside the <strong>appreciateMe</strong> directory you can find the plugin.js file. You must include it in the page you wish to show the Appreciate button on. It uses AJAX to request data from the PHP backend and uses the response it receives to create the markup of the button.</p>
<h4>appreciateMe/plugin.js</h4>
<pre class="brush:js">function(){

	$.appreciateButton = function(options){

		// The options object must contain a URL and a Holder property
		// These are the URL of the Appreciate php script, and the
		// div in which the badge is inserted

		if(!'url' in options || !'holder' in options){
			return false;
		}

		var element = $(options.holder);

		// Forming the url of the current page:

		var currentURL = 	window.location.protocol+'//'+
					window.location.host+window.location.pathname;

		// Issuing a GET request. A rand parameter is passed
		// to prevent the request from being cached in IE

		$.get(options.url,{url:currentURL,rand:Math.random()},function(response){

			// Creating the appreciate button:

			var button = $('&lt;a&gt;',{
				href:'',className:'appreciateBadge',
				html:'Appreciate Me'
			});

			if(!response.voted){
				// If the user has not voted previously,
				// make the button active / clickable.
				button.addClass('active');
			}
			else button.addClass('inactive');

			button.click(function(){
				if(button.hasClass('active')){

					button.removeClass('active').addClass('inactive');

					if(options.count){
						// Incremented the total count
						$(options.count).html(1 + parseInt(response.appreciated));
					}

					// Sending a GET request with a submit parameter.
					// This will save the appreciation to the MySQL DB.

					$.getJSON(options.url,{url:currentURL,submit:1});
				}

				return false;
			});

			element.append(button);

			if(options.count){
				$(options.count).html(response.appreciated);
			}
		},'json');

		return element;
	}

})(jQuery);
</pre>
<p>The script basically creates a new method in the main jQuery object. This differs from the plugins that we usually do, in that this type of plugins are not called on a set of elements (no need to select elements). You can just call <strong>$.appreciateButton()</strong> while passing a configuration object as a parameter. This is exactly what we&#8217;ve done in <strong>script.js</strong> add a button to the page:</p>
<h4>script.js</h4>
<pre class="brush:css">$(document).ready(function(){

	// Creating an appreciate button.

	$.appreciateButton({
		url		: 'appreciateMe/script.php',	// URL to the PHP script.
		holder	: '#main',				// The button will be inserted here.
		count	: '#countDiv'			// Optional. Will show the total count.
	});

});
</pre>
<p>The configuration object, which is passed as a parameter, has to contain a <strong>url</strong> and a <strong>holder</strong> properties, whereas <strong>count</strong> is optional. Notice that I&#8217;ve specified the path to <strong>script.php</strong> relatively, as appreciateMe is a child directory of the one the page is currently in.</p>
<p>However, if you plan to add the script to a site with a variable path structure, you should probably specify an absolute path. Either add a <strong>leading slash</strong>, or provide a complete URL with <strong>http://</strong>.</p>
<h3>Step 4 &#8211; CSS</h3>
<p>Now that we have all the markup and code in place, it is time to turn to the styling. The CSS rules that style the appreciate badge are located in <strong>appreciate.css</strong>. You could optionally copy these rules to your main stylesheet file, if you&#8217;d like to avoid the extra request, but beware that you will need to change the paths to the background images.</p>
<h4>appreciateMe/appreciate.css</h4>
<pre class="brush:css">.appreciateBadge{
	width:129px;
	height:129px;
	display:block;
	text-indent:-9999px;
	overflow:hidden;
	background:url('sprite.png') no-repeat;
	text-decoration:none;
	border:none;
}

.appreciateBadge.active{
	background-position:left top;
}

.appreciateBadge.active:hover{
	background-position:0 -129px;
}

.appreciateBadge.inactive{
	background-position:left bottom;
	cursor:default;
}
</pre>
<p>There are three versions of the appreciate badge image. A default one, a hover one, and an inactive one. All three of these reside in the same file &#8211; <strong>sprite.png</strong>, one below the other. With this technique you can switch between the versions instantaneously by offsetting the background image of the hyperlink.</p>
<h4>styles.css</h4>
<pre class="brush:css">#main{
	margin:80px auto;
	width:130px;
}

#countDiv{
	color:#eee;
	font-size:35px;
	margin-right:120px;
	position:absolute;
	right:50%;
	top:265px;
}
</pre>
<p>You can find the rest of the styles, which refine the looks of <strong>page.html</strong>, in <strong>styles.css</strong>. Only two sets of styles affect the appreciate button directly. The <strong>#main</strong> div, which contains the button and centers it on the page, and <strong>#countDiv</strong> in which the total number of appreciations is inserted.</p>
<p><strong>With this our Click to Appreciate Badge is complete!</strong></p>
<h3>Conclusion</h3>
<p>Before being able to run this script on your server, you first have to replace the MySQL credentials in <strong>connect.php</strong> with your own. Also, you will need to run the contents of <strong>tables.sql</strong> in the SQL tab of <strong>phpMyAdmin, </strong>so the two tables are created. Lastly, depending on your URL paths, you may have to change the URL property of <strong>appreciateMe/script.php</strong> in the script.js JavaScript File.</p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/07/click-to-appreciate-badge-ajax-jquery-css/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Simple AJAX Commenting System</title>
		<link>http://tutorialzine.com/2010/06/simple-ajax-commenting-system/</link>
		<comments>http://tutorialzine.com/2010/06/simple-ajax-commenting-system/#comments</comments>
		<pubDate>Wed, 30 Jun 2010 18:02:24 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=990</guid>
		<description><![CDATA[This time, we are making a Simple AJAX Commenting System. It will feature a gravatar integration and demonstrate how to achieve effective communication between jQuery and PHP/MySQL with the help of JSON.]]></description>
			<content:encoded><![CDATA[<p>This time, we are making a Simple AJAX Commenting System. It will feature a gravatar integration and demonstrate how to achieve effective communication between jQuery and PHP/MySQL with the help of JSON.</p>
<h3>Step 1 &#8211; XHTML</h3>
<p>First, lets take a look at the markup of the comments. This code is generated by PHP in the Comment class, which we are going  to take a look at in a moment.</p>
<h4>demo.php</h4>
<pre class="brush:html">&lt;div class="comment"&gt;
    &lt;div class="avatar"&gt;
        &lt;a href="http://tutorialzine.com/"&gt;
        &lt;img src="http://www.gravatar.com/avatar/112fdf7a8fe3609e7af2cd3873b5c6bd?size=50&amp;default=http%3A%2F%2Fdemo.tutorialzine.com%2F2010%2F06%2Fsimple-ajax-commenting-system%2Fimg%2Fdefault_avatar.gif"&gt;
        &lt;/a&gt;
    &lt;/div&gt;

    &lt;div class="name"&gt;&lt;a href="http://tutorialzine.com/"&gt;Person's Name&lt;/a&gt;&lt;/div&gt;
    &lt;div title="Added at 06:40 on 30 Jun 2010" class="date"&gt;30 Jun 2010&lt;/div&gt;
    &lt;p&gt;Comment Body&lt;/p&gt;
&lt;/div&gt;</pre>
<p>The avatar div contains a hyperlink (if the user entered a valid URL when submitting the comment) and an avatar image, which is fetched from <a href="http://en.gravatar.com/site/implement/images/" target="_blank">gravatar.com</a>. We will return to this in the PHP step of the tut. Lastly we have the name and time divs, and the comment body.</p>
<p>The other important element in the XHTML part is the comment form. It is sent via <strong>POST</strong>. All fields except for the URL field are required.</p>
<h4>demo.php</h4>
<pre class="brush:html">&lt;div id="addCommentContainer"&gt;
	&lt;p&gt;Add a Comment&lt;/p&gt;
	&lt;form id="addCommentForm" method="post" action=""&gt;
    	&lt;div&gt;
        	&lt;label for="name"&gt;Your Name&lt;/label&gt;
        	&lt;input type="text" name="name" id="name" /&gt;

            &lt;label for="email"&gt;Your Email&lt;/label&gt;
            &lt;input type="text" name="email" id="email" /&gt;

            &lt;label for="url"&gt;Website (not required)&lt;/label&gt;
            &lt;input type="text" name="url" id="url" /&gt;

            &lt;label for="body"&gt;Comment Body&lt;/label&gt;
            &lt;textarea name="body" id="body" cols="20" rows="5"&gt;&lt;/textarea&gt;

            &lt;input type="submit" id="submit" value="Submit" /&gt;
        &lt;/div&gt;
    &lt;/form&gt;
&lt;/div&gt;</pre>
<p>The form is submitted via AJAX. The validation is performed entirely in the backend by <strong>submit.php</strong>, as you will see in the jQuery step of the tutorial. Every field has a corresponding label element, with an appropriate <strong>for</strong> attribute.</p>
<div id="attachment_998" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/06/simple-ajax-commenting-system/demo.php"><img class="size-full wp-image-998" title="Simple AJAX Commenting System" src="http://tutorialzine.com/wp-content/uploads/2010/06/i11.jpg" alt="Simple AJAX Commenting System" width="620" height="460" /></a><p class="wp-caption-text">Simple AJAX Commenting System</p></div>
<h3>Step 2 &#8211; PHP</h3>
<p>PHP handles the communication with the MySQL database and generates the markup of the comments. It is also on the receiving end of the AJAX requests and inserts the comment data to the <strong>comments</strong> table. You can see the code that prints the comments to the page below.</p>
<h4>demo.php</h4>
<pre class="brush:php">/*
/	Select all the comments and populate the $comments array with objects
*/

$comments = array();
$result = mysql_query("SELECT * FROM comments ORDER BY id ASC");

while($row = mysql_fetch_assoc($result))
{
	$comments[] = new Comment($row);
}</pre>
<p>The MySQL query selects all the entries from the database and fills the <strong>$comments</strong> array with objects of the comment class, which you will see below. This array is outputted later in the execution of the script.</p>
<h4>demo.php</h4>
<pre class="brush:php">/*
/	Output the comments one by one:
*/

foreach($comments as $c){
	echo $c-&gt;markup();
}</pre>
<p>Each comment has a<strong> markup()</strong> method, which generates valid HTML code ready to be printed to the page. You can see the definition of this method and the class below.</p>
<p>The class takes a row from the database (fetched with <strong>mysql_fetch_assoc()</strong> ) and stores it in the private variable<strong> $data</strong>. It is available only to  the methods of the class and cannot be accessed from outside.</p>
<h4>comment.class.php &#8211; Part 1</h4>
<pre class="brush:php">class Comment
{
	private $data = array();

	public function __construct($row)
	{
		/*
		/	The constructor
		*/

		$this-&gt;data = $row;
	}

	public function markup()
	{
		/*
		/	This method outputs the XHTML markup of the comment
		*/

		// Setting up an alias, so we don't have to write $this-&gt;data every time:
		$d = &amp;$this-&gt;data;

		$link_open = '';
		$link_close = '';

		if($d['url']){

			// If the person has entered a URL when adding a comment,
			// define opening and closing hyperlink tags

			$link_open = '&lt;a href="'.$d['url'].'"&gt;';
			$link_close =  '&lt;/a&gt;';
		}

		// Converting the time to a UNIX timestamp:
		$d['dt'] = strtotime($d['dt']);

		// Needed for the default gravatar image:
		$url = 'http://'.dirname($_SERVER['SERVER_NAME'].$_SERVER["REQUEST_URI"]).
				'/img/default_avatar.gif';

		return '

			&lt;div class="comment"&gt;
				&lt;div class="avatar"&gt;
					'.$link_open.'
					&lt;img src="http://www.gravatar.com/avatar/'.
				md5($d['email']).'?size=50&amp;default='.
				urlencode($url).'" /&gt;
					'.$link_close.'
				&lt;/div&gt;

				&lt;div class="name"&gt;'.$link_open.$d['name'].$link_close.'&lt;/div&gt;
				&lt;div class="date" title="Added at '.
				date('H:i \o\n d M Y',$d['dt']).'"&gt;'.
				date('d M Y',$d['dt']).'&lt;/div&gt;
				&lt;p&gt;'.$d['body'].'&lt;/p&gt;
			&lt;/div&gt;
		';
	}</pre>
<p>This script uses <a href="http://en.gravatar.com/site/implement/images/" target="_blank">gravatar</a> to present avatars in the comments. For those of you, who have not used gravatar, this is a really useful service, which lets you associate an avatar with your email address. The avatar image can easily be fetched by passing an <strong>md5()</strong> encoded hash of your email address to gravatar.com. This is exactly what we do on <strong>line 48</strong>.</p>
<p>Notice <strong>line 39</strong> above it &#8211; the script tries to figure out the URL at which it is located, and determines the exact address of the <strong>default_avatar.gif</strong> image. This gif is passed to gravatar along the md5 hash, so if no avatar was found for this particular email, the fallback image is displayed instead.</p>
<h4>comment.class.php &#8211; Part 2</h4>
<pre class="brush:php">	public static function validate(&amp;$arr)
	{
		/*
		/	This method is used to validate the data sent via AJAX.
		/
		/	It return true/false depending on whether the data is valid, and populates
		/	the $arr array passed as a paremter (notice the ampersand above) with
		/	either the valid input data, or the error messages.
		*/

		$errors = array();
		$data	= array();

		// Using the filter_input function introduced in PHP 5.2.0

		if(!($data['email'] = filter_input(INPUT_POST,'email',FILTER_VALIDATE_EMAIL)))
		{
			$errors['email'] = 'Please enter a valid Email.';
		}

		if(!($data['url'] = filter_input(INPUT_POST,'url',FILTER_VALIDATE_URL)))
		{
			// If the URL field was not populated with a valid URL,
			// act as if no URL was entered at all:

			$url = '';
		}

		// Using the filter with a custom callback function:

		if(!($data['body'] = filter_input(INPUT_POST,'body',FILTER_CALLBACK,
						array('options'=&gt;'Comment::validate_text'))))
		{
			$errors['body'] = 'Please enter a comment body.';
		}

		if(!($data['name'] = filter_input(INPUT_POST,'name',FILTER_CALLBACK,
						array('options'=&gt;'Comment::validate_text'))))
		{
			$errors['name'] = 'Please enter a name.';
		}

		if(!empty($errors)){

			// If there are errors, copy the $errors array to $arr:

			$arr = $errors;
			return false;
		}

		// If the data is valid, sanitize all the data and copy it to $arr:

		foreach($data as $k=&gt;$v){
			$arr[$k] = mysql_real_escape_string($v);
		}

		// Ensure that the email is in lower case (for a correct gravatar hash):
		$arr['email'] = strtolower(trim($arr['email']));

		return true;

	}</pre>
<p>The<strong> validate()</strong> method above (also part of the class) is defined as <strong>static</strong>. This means that it can be evoked directly like <strong>Comment::validate()</strong>, without the need of creating an object of the class. What this method does, is validate the input data which is submitted via AJAX.</p>
<p>This method uses the new filter functions, which are available as of <strong>PHP 5.2.0</strong>. These allow us to easily validate and filter any input data that is passed to the script. For example <em>filter_input(INPUT_POST,&#8217;url&#8217;,FILTER_VALIDATE_URL)</em> means that we are checking whether <strong>$_POST['url']</strong> is a valid URL address. If it is, the function returns the value of the variable, otherwise it return <strong>false</strong>.</p>
<p>This is really useful, as up until now, we had to use custom regular expressions to validate data (and have series of if statements). Also, another advantage is that this data is fetched before any configuration-specific transformations (like magic quotes) are applied.</p>
<p>We also have the option of specifying a custom function which is going to apply some more advanced modifications of the data, as you can see from lines 31 and 37.</p>
<h4>comment.class.php &#8211; Part 3</h4>
<pre class="brush:php">	private static function validate_text($str)
	{
		/*
		/	This method is used internally as a FILTER_CALLBACK
		*/

		if(mb_strlen($str,'utf8')&lt;1)
			return false;

		// Encode all html special characters (&lt;, &gt;, ", &amp; .. etc) and convert
		// the new line characters to &lt;br&gt; tags:

		$str = nl2br(htmlspecialchars($str));

		// Remove the new line characters that are left
		$str = str_replace(array(chr(10),chr(13)),'',$str);

		return $str;
	}

}</pre>
<p>The last method is <strong>validate_text,</strong> which we are passing as a callback function in the two filter_input calls above. It encodes all special HTML characters, effectively blocking XSS attacks. It also replaces the newline characters with &lt;br /&gt; line breaks.</p>
<h4>submit.php</h4>
<pre class="brush:php">/*
/	This array is going to be populated with either
/	the data that was sent to the script, or the
/	error messages:
/*/

$arr = array();

$validates = Comment::validate($arr);

if($validates)
{
	/* Everything is OK, insert to database: */

	mysql_query("	INSERT INTO comments(name,url,email,body)
					VALUES (
						'".$arr['name']."',
						'".$arr['url']."',
						'".$arr['email']."',
						'".$arr['body']."'
					)");

	$arr['dt'] = date('r',time());
	$arr['id'] = mysql_insert_id();

	/*
	/	The data in $arr is escaped for the mysql insert query,
	/	but we need the unescaped text, so we apply,
	/	stripslashes to all the elements in the array:
	/*/

	$arr = array_map('stripslashes',$arr);

	$insertedComment = new Comment($arr);

	/* Outputting the markup of the just-inserted comment: */

	echo json_encode(array('status'=&gt;1,'html'=&gt;$insertedComment-&gt;markup()));

}
else
{
	/* Outputting the error messages */
	echo '{"status":0,"errors":'.json_encode($arr).'}';
}</pre>
<p><strong>submit.php</strong> receives the comment form data via an AJAX request. It validates it and outputs a JSON object with either the XHTML markup of the successfully inserted comment, or a list of error messages. jQuery uses the status property to determine whether to display the error messages or add the comment markup to the page.</p>
<p>You can see two example responses below.</p>
<h4>Successful response</h4>
<pre class="brush:js">{
    "status": 1,
    "html": "Html Code Of The Comment Comes Here..."
}</pre>
<p>The <strong>html</strong> property contains the code of the comment, similar to markup in step one.</p>
<h4>Failure response</h4>
<pre class="brush:js">{
    "status": 0,
    "errors": {
        "email": "Please enter a valid Email.",
        "body": "Please enter a comment body.",
        "name": "Please enter a name."
    }
}</pre>
<p>On failure, jQuery loops through the errors object, and outputs the errors next to the fields that caused them.</p>
<div id="attachment_999" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/06/simple-ajax-commenting-system/demo.php"><img class="size-full wp-image-999" title="Fancy CSS3 &amp; jQuery Submit Form" src="http://tutorialzine.com/wp-content/uploads/2010/06/i21.jpg" alt="Fancy CSS3 &amp; jQuery Submit Form" width="620" height="460" /></a><p class="wp-caption-text">Fancy CSS3 &amp; jQuery Submit Form</p></div>
<h3>Step 3 &#8211; CSS</h3>
<p>Now that we have all the markup properly generated and displayed on the page, we can move on to styling it.</p>
<h4>styles.css &#8211; Part 1</h4>
<pre class="brush:css">.comment,
#addCommentContainer{

	/* Syling the comments and the comment form container */

	padding:12px;
	width:400px;
	position:relative;
	background-color:#fcfcfc;
	border:1px solid white;
	color:#888;
	margin-bottom:25px;

	/* CSS3 rounded corners and drop shadows */

	-moz-border-radius:10px;
	-webkit-border-radius:10px;
	border-radius:10px;

	-moz-box-shadow:2px 2px 0 #c2c2c2;
	-webkit-box-shadow:2px 2px 0 #c2c2c2;
	box-shadow:2px 2px 0 #c2c2c2;
}

.comment .avatar{

	/*
	/	The avatar is positioned absolutely,
	/	and offset outside the comment div
	/*/

	height:50px;
	left:-70px;
	position:absolute;
	width:50px;
	background:url('img/default_avatar.gif') no-repeat #fcfcfc;

	/* Centering it vertically: */

	margin-top:-25px;
	top:50%;

	-moz-box-shadow:1px 1px 0 #c2c2c2;
	-webkit-box-shadow:1px 1px 0 #c2c2c2;
	box-shadow:1px 1px 0 #c2c2c2;
}</pre>
<p>The .comment divs and the #addCommentContainer are styled at once because they share most of the styling. A number of CSS3 rules are applied, including rounded corners and a box-shadow. Needless to say, these do not work in older browsers, but as they are purely presentational, the script will still work without them.</p>
<h4>styles.css &#8211; Part 2</h4>
<pre class="brush:css">.comment .avatar img{
	display:block;
}

.comment .name{
	font-size:20px;
	padding-bottom:10px;
	color:#ccc;
}

.comment .date{
	font-size:10px;
	padding:6px 0;
	position:absolute;
	right:15px;
	top:10px;
	color:#bbb;
}

.comment p,
#addCommentContainer p{
	font-size:18px;
	line-height:1.5;
}

#addCommentContainer input[type=text],
#addCommentContainer textarea{

	/* Styling the inputs */

	display:block;
	border:1px solid #ccc;
	margin:5px 0 5px;
	padding:3px;
	font-size:12px;
	color:#555;
	font-family:Arial, Helvetica, sans-serif;
}

#addCommentContainer textarea{
	width:300px;
}

label{
	font-size:10px;
}

label span.error{
	color:red;
	position:relative;
	right:-10px;
}

#submit{

	/* The submit button */

	background-color:#58B9EB;
	border:1px solid #40A2D4;
	color:#FFFFFF;
	cursor:pointer;
	font-family:'Myriad Pro',Arial,Helvetica,sans-serif;
	font-size:14px;
	font-weight:bold;
	padding:4px;
	margin-top:5px;

	-moz-border-radius:4px;
	-webkit-border-radius:4px;
	border-radius:4px;
}

#submit:hover{
	background-color:#80cdf5;
	border-color:#52b1e2;
}</pre>
<p>In the second part of the stylesheet, we style the comment and form elements. Notice the <strong>input[type=text]</strong> selector, which selects elements depending on the type attribute.</p>
<h3>Step 4 &#8211; jQuery</h3>
<p>Now lets continue with jQuery, which is the last step of this tutorial. After including the library to the bottom of the page (best for the perceived performance of the page) we can start coding the script file.</p>
<h4>script.js</h4>
<pre class="brush:js">$(document).ready(function(){
	/* The following code is executed once the DOM is loaded */

	/* This flag will prevent multiple comment submits: */
	var working = false;

	/* Listening for the submit event of the form: */
	$('#addCommentForm').submit(function(e){

 		e.preventDefault();
		if(working) return false;

		working = true;
		$('#submit').val('Working..');
		$('span.error').remove();

		/* Sending the form fileds to submit.php: */
		$.post('submit.php',$(this).serialize(),function(msg){

			working = false;
			$('#submit').val('Submit');

			if(msg.status){

				/*
				/	If the insert was successful, add the comment
				/	below the last one on the page with a slideDown effect
				/*/

				$(msg.html).hide().insertBefore('#addCommentContainer').slideDown();
				$('#body').val('');
			}
			else {

				/*
				/	If there were errors, loop through the
				/	msg.errors object and display them on the page
				/*/

				$.each(msg.errors,function(k,v){
					$('label[for='+k+']').append('&lt;span class="error"&gt;'+
						v+'&lt;/span&gt;');
				});
			}
		},'json');

	});

});</pre>
<p>Starting from the top, we have the <strong>$(document).ready()</strong> call, which binds a function to the <em>DOM content loaded</em> event. The working variable acts as a flag, which tells the script if an AJAX request is in progress (thus preventing double posting).</p>
<p>In the callback function for the POST AJAX request, we check the status property to determine whether the comment was successfully inserted. If it was, we add the received markup to the page after the last comment with a <em>slideDown </em>animation.</p>
<p>If there were problems, we display the error messages by appending an error span to the appropriate label element (the for attribute of the label contains the id of the input that caused the error).</p>
<p><strong>With this our Simple AJAX Commenting System is complete!</strong></p>
<h3>Conclusion</h3>
<p>To be able to run this script on your server, you need to create the <strong><em>comments</em></strong> table in your MySQL database. You can do this by executing the SQL code found in <strong>table.sql</strong> from the SQL tab of phpMyAdmin. After this you need to enter your MySQL connection details in <strong><em>connect.php</em></strong>.</p>
<p>You are free to modify and use this code any way you see fit.</p>
<p><strong>What do you think? How would you improve this script?</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/06/simple-ajax-commenting-system/feed/</wfw:commentRss>
		<slash:comments>47</slash:comments>
		</item>
		<item>
		<title>Combined Facebook, Twitter &amp; RSS Social Stats with jQuery, PHP &amp; YQL</title>
		<link>http://tutorialzine.com/2010/05/showing-facebook-twitter-rss-stats-jquery-yql/</link>
		<comments>http://tutorialzine.com/2010/05/showing-facebook-twitter-rss-stats-jquery-yql/#comments</comments>
		<pubDate>Wed, 19 May 2010 21:50:43 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=909</guid>
		<description><![CDATA[This week we are going to create a simple widget, which combines the number of your RSS readers, twitter followers, and fans of your facebook fan page, to give a rough estimate of your social popularity.]]></description>
			<content:encoded><![CDATA[<p>As we increasingly depend on more and more social services, there rises the need to provide a simple way to let our website visitors take part of our diverse social presence.</p>
<p>In this tutorial we are going to create a simple widget, which combines the number of your RSS readers, twitter followers, and fans of your facebook fan page, to give a rough estimate of your social popularity.</p>
<p>We are using jQuery and the <a href="http://code.drewwilson.com/entry/tiptip-jquery-plugin" target="_blank">tipTip plugin</a>, object-oriented PHP, and <a href="http://developer.yahoo.com/yql/" target="_blank">Yahoo&#8217;s YQL</a>, while demonstrating a number of interesting web development techniques.</p>
<h3>Step 1 &#8211; PHP</h3>
<p>YQL is a free Yahoo web service, which enables us to communicate  with numerous third-party APIs through a consistent SQL-like language (and hence the name). It is basically a gateway that sits between you and the other APIs.</p>
<p>This is especially important here, as we are using Yahoo&#8217;s YQL for  three very different tasks:</p>
<ul>
<li>Fetch your RSS subscriber count with FeedBurner&#8217;s <a href="http://code.google.com/apis/feedburner/awareness_api.html" target="_blank"> awareness API</a> (which comes in the form of an XML file that has to be parsed).<strong><br />
Note: </strong><em>You have to enable the awareness API to use this widget with your own feed. This is done from the Publicize Tab on your feed settings page</em>;</li>
<li>Use twitter&#8217;s API to get your number of followers;</li>
<li>Use Facebook&#8217;s new <strong>Graph API</strong> (<a href="http://developers.facebook.com/docs/api" target="_blank">link</a>) to get  information about the number of fans of your facebook fanpage.</li>
</ul>
<p>If it weren&#8217;t for YQL, we&#8217;d have to research and implement three very different solutions, which would slow us down significantly.</p>
<h4>includes/subscriber_stats.class.php</h4>
<pre class="brush:php">class SubscriberStats{

	public	$twitter,$rss,$facebook;
	public	$services = array();

	public function __construct($arr){

		$this-&gt;services = $arr;

		$yqlQueries = array();

		// Forming the Feedburner Awaraness API URL from the passed feed URL:
		$feedBurnerAwarenessAPI = 'http://feedburner.google.com/api/awareness'.
		'/1.0/GetFeedData?uri='.end(split('/',trim($arr['feedBurnerURL'],'/')));

		// Building an array with queries:

		if($arr['feedBurnerURL'])
			$yqlQueries[] = '
				SELECT * FROM xml
				WHERE url=\''.$feedBurnerAwarenessAPI.'\'
			';

		if($arr['twitterName'])
			$yqlQueries[] = '
				SELECT * FROM twitter.user.profile
				WHERE id=\''.$arr['twitterName'].'\'
			';

		if($arr['facebookFanPageURL'])
			$yqlQueries[] = '
			SELECT fan_count FROM facebook.graph
			WHERE id=\''.end(split('/',trim($arr['facebookFanPageURL'],'/'))).'\'
			';

		// Combing them into a YQL multiquery:
		$multiQuery =
		'SELECT * FROM query.multi WHERE queries = "'.join(';',$yqlQueries).'"';

		// Executing the query:
		$result = json_decode(
			file_get_contents('http://query.yahooapis.com/v1/public/yql?q='.
			urlencode($multiQuery).'&amp;format=json&amp;diagnostics=false&amp;'
			'amp;env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys')
		)-&gt;query-&gt;results-&gt;results;

		// The results from the queries are accessible in the $results array:

		$this-&gt;rss = $result[0]-&gt;rsp-&gt;feed-&gt;entry-&gt;circulation;
		$this-&gt;twitter = $result[1]-&gt;item-&gt;meta[5]-&gt;content;
		$this-&gt;facebook = $result[2]-&gt;json-&gt;fan_count;
	}

	public function generate(){

		$total = number_format($this-&gt;rss+$this-&gt;twitter+$this-&gt;facebook);

		echo '
			&lt;div class="subscriberStats"&gt;
				&lt;div class="subscriberCount"
				title="'.$total.'+ Total Social Media Followers"&gt;'.$total.'&lt;/div&gt;

				&lt;div class="socialIcon"
				title="'.number_format($this-&gt;rss).' RSS Subscribers"&gt;
					&lt;a href="'.$this-&gt;services['feedBurnerURL'].'"&gt;
					&lt;img src="img/rss.png" alt="RSS" /&gt;&lt;/a&gt;
				&lt;/div&gt;

				&lt;div class="socialIcon"
				title="'.number_format($this-&gt;facebook).' Fans on Facebook"&gt;
					&lt;a href="'.$this-&gt;services['facebookFanPageURL'].'"&gt;
					&lt;img src="img/facebook.png" alt="Facebook" /&gt;&lt;/a&gt;
				&lt;/div&gt;

				&lt;div class="socialIcon"
				title="'.number_format($this-&gt;twitter).' Twitter Followers"&gt;
				&lt;a href="http://twitter.com/'.$this-&gt;services['twitterName'].'"&gt;
					&lt;img src="img/twitter.png" alt="Twitter" /&gt;&lt;/a&gt;
				&lt;/div&gt;
			&lt;/div&gt;
		';
	}
}</pre>
<p>When we create an object of this class, the construct method is called, and a YQL query is created and executed.</p>
<p>To request the data from YQL&#8217;s servers, we just use <strong>file_get_contents()</strong> with the query passed as a parameter of the URL address. This returns a JSON object (basically a JavaScript object) which we can decode into a native PHP array with the in-build <strong>json_decode()</strong> function.</p>
<p>The results of these queries are saved locally and are made available for use in the <strong>generate()</strong> method which renders all the needed markup.</p>
<p>And now lets see how this class is used:</p>
<h4>subscriber_count.php</h4>
<pre class="brush:php">require "includes/subscriber_stats.class.php";

$cacheFileName = "cache.txt";

// IMPORTANT: after making changes to this file (or the SubscriberStats class)
// remeber to delete cache.txt from your server, otherwise you wont see your changes.

// If a cache file exists and it is less than 6*60*60 seconds (6 hours) old, use it:

if(file_exists($cacheFileName) &amp;&amp; time() - filemtime($cacheFileName) &gt; 6*60*60)
{
	$stats = unserialize(file_get_contents($cacheFileName));
}

if(!$stats)
{
	// If no cache was found, fetch the subscriber stats and create a new cache:

	$stats = new SubscriberStats(array(
		'facebookFanPageURL'	=&gt; 'http://www.facebook.com/smashmag',
		'feedBurnerURL'			=&gt; 'http://feeds.feedburner.com/Tutorialzine',
		'twitterName'			=&gt; 'Tutorialzine'
	));

	// Serialize turns the object into a string,
	// which can later be restored with unserialize():

	file_put_contents($cacheFileName,serialize($stats));
}

//	You can access the individual stats like this:
//	$stats-&gt;twitter;
//	$stats-&gt;facebook;
//	$stats-&gt;rss;

//	Output the markup for the stats:

$stats-&gt;generate();</pre>
<p>Sending a query to YQL&#8217;s servers and receiving a response is a relatively slow process and would be unwise to request the same information on every page load (not to mention that we could get banned from the API for abuse).</p>
<p>This is why we implement a simple caching system. The idea is simple: if a cache file does not exist (or is older than 6 hours), connect to YQL, create a new cache file and output the XHTML markup. Otherwise, just read the cache and output directly. This way we send a request to the API only once every six hours which is perfect for any practical purposes.</p>
<div id="attachment_913" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/05/showing-facebook-twitter-rss-stats-jquery-yql/demo.html"><img class="size-full wp-image-913 " title="Combined Social Media Followers Count" src="http://tutorialzine.com/wp-content/uploads/2010/05/i11.png" alt="Combined Social Media Followers Count" width="620" height="260" /></a><p class="wp-caption-text">Combined Social Media Followers Count</p></div>
<h3>Step 2 &#8211; XHTML</h3>
<p>As mentioned in the PHP section above, the generate() method renders all the XHTML markup used to display the stats. Here is what the generated code looks like:</p>
<h4>sample code</h4>
<pre class="brush:html">&lt;div class="subscriberStats"&gt;
    &lt;div class="subscriberCount"  title="25,382+ Total Social Media Followers&gt;25,382&lt;/div&gt;

    &lt;div class="socialIcon" title="5,921 RSS Subscribers"&gt;
        &lt;a href="http://feeds.feedburner.com/Tutorialzine"&gt;
        &lt;img alt="RSS" src="img/rss.png" /&gt;&lt;/a&gt;
    &lt;/div&gt;

    &lt;div class="socialIcon" title="16,813 Fans on Facebook"&gt;
        &lt;a href="http://www.facebook.com/smashmag"&gt;
        &lt;img alt="Facebook" src="img/facebook.png" /&gt;&lt;/a&gt;
    &lt;/div&gt;

    &lt;div class="socialIcon" title="2,648 Twitter Followers"&gt;
        &lt;a href="http://twitter.com/Tutorialzine"&gt;
        &lt;img alt="Twitter" src="img/twitter.png" /&gt;&lt;/a&gt;
    &lt;/div&gt;
&lt;/div&gt;
</pre>
<p>This code is fetched via AJAX and displayed on the page. Notice the title attributes. They are used as the contents of the fancy tooltips which are created by jQuery and the tipTip plugin, which we will discuss in a moment.</p>
<h3>Step 3 &#8211; CSS</h3>
<p>The CSS code is also quite simple and straightforward. The <strong>subscriberStats</strong> is the main outer div, inside it we have a number of <strong>.socialIcon</strong> divs and the <strong>subscrberCount</strong>.</p>
<h4>css/styles.css</h4>
<pre class="brush:css">.subscriberStats{
	height:35px;
	padding:5px;
	width:220px;
}

.socialIcon{
	float:left;
	height:32px;
	width:32px;
}

a img{
	border:none;
}

.subscriberCount{
	border-bottom:1px dotted #CCCCCC;
	color:#999999;
	float:left;
	font-size:28px;
	line-height:32px;
	margin-right:10px;
}

#main{
	height:100px;
	margin:140px auto 50px;
	position:relative;
	width:200px;
}
</pre>
<p>All of these are floated to the left. Also notice that we disable the borders on the icon images on line 14, which are displayed by default and ruin your design.</p>
<h3>Step 4 &#8211; jQuery</h3>
<p>After including the jQuery library to the page, we just need to listen to the $(document).ready event, which is executed when all the markup of the page is accessible (this happens before things like images are loaded and comes earlier than the onload event).</p>
<h4>js/script.js</h4>
<pre class="brush:js">$(document).ready(function(){

	// Using the load AJAX method to fetch the subscriber markup
	// from subscriber_count.php:

	$('#main').load('subscriber_count.php',function(){

		// Once loaded, convert the title attributes to tooltips
		// with the tipTip jQuery plugin:

		$('.subscriberStats div').tipTip({defaultPosition:'top'});
	})

});</pre>
<p><strong>#main</strong> is the div where we want to insert the stats. This could be your sidebar or website header. The load method fetches the markup from <strong>suscriber_count.php</strong> and displays it on the page.  The callback function is called after this and all the div titles are replaced with fancy tooltips by the <em>tipTip plugin</em>.</p>
<p><strong>With this our combined social stats widget is complete!</strong></p>
<h3>Conclusion</h3>
<p>With services like YQL working with third party APIs is a charm. Not only it provides a common interface to a sea of technologies, but it also guarantees that you will be able to access to the services you want even as the underlying APIs change overtime.</p>
<p><strong>What do you think? How would you improve this code?</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/05/showing-facebook-twitter-rss-stats-jquery-yql/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Making a Donation Center With PHP, MySQL and PayPal&#8217;s APIs</title>
		<link>http://tutorialzine.com/2010/05/donation-center-php-mysql-paypal-api/</link>
		<comments>http://tutorialzine.com/2010/05/donation-center-php-mysql-paypal-api/#comments</comments>
		<pubDate>Thu, 13 May 2010 13:27:21 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=891</guid>
		<description><![CDATA[Today we are making a dedicated Donation Center with PHP, MySQL &#038; PayPal's APIs. It will feature goal setting, a complete PayPal integration, and a donor list with the people who have already donated.]]></description>
			<content:encoded><![CDATA[<p>It all started last month when I received the following email:</p>
<blockquote><p>Hey there Tutorialzine!</p>
<p>Thanks for publishing such great tutorials, you have truly helped me increase my (growing) development skills. I know you enjoy getting ideas for tutorials, so I thought I&#8217;d toss one your way.</p>
<p>Donation buttons are a very common among blogs and websites in general, but they often don&#8217;t provide much else than a button for someone to click and pay. Why not kick it up a notch and create a sweet &#8220;donation center&#8221;, which doesn&#8217;t just take donations, but perhaps includes a &#8220;meter&#8221;, a top-donator list, and various other bells and whistles that may encourage the visitor to donate?</p>
<p>Devon</p></blockquote>
<p>You are right, Devon, it is always nice to hear fresh ideas for tutorials. And a donation center is a great chance to experiment with PayPal&#8217;s APIs and build something that many people can benefit from.</p>
<h3>The Idea</h3>
<p>PayPal provides numerous APIs and integration options for third-party developers. One of these is the Donation button, which you can generate straight from PayPal&#8217;s site and include directly into your pages. Conversion rate for these buttons is typically minimal, but the right incentive can make a big difference.</p>
<p>The idea is to have a dedicated <strong>Donation Center</strong>. This is a place, where you get to see what a difference your donation would make, and a list of people who have already donated.</p>
<p>After choosing the amount you wish to donate and clicking the button, you are redirected to <em>paypal.com</em> to complete the transaction. After this is done, you are redirected back to the donation center where you can fill a form and get included in the official <strong>Donor List</strong>.</p>
<div id="attachment_899" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/05/donation-center-php-mysql-paypal-api/donate.php"><img class="size-full wp-image-899" title="A Complete PHP &amp; MySQL Donation Center" src="http://tutorialzine.com/wp-content/uploads/2010/05/i21.png" alt="A Complete PHP &amp; MySQL Donation Center" width="620" height="260" /></a><p class="wp-caption-text">A Complete PHP &amp; MySQL Donation Center</p></div>
<h3>Step 1 &#8211; Database</h3>
<p>The script uses two tables &#8211; <strong>dc_donations</strong> and <strong>dc_comments</strong>. The first stores the donation data which is passed in a request from PayPal (we will come back to this in the PHP step of the tutorial).</p>
<div id="attachment_900" class="wp-caption alignnone" style="width: 630px"><a href="http://tutorialzine.com/wp-content/uploads/2010/05/i5.png"><img class="size-full wp-image-900" title="Table Schema for dc_donations" src="http://tutorialzine.com/wp-content/uploads/2010/05/i5.png" alt="Table Schema for dc_donations" width="620" height="260" /></a><p class="wp-caption-text">Table Schema for dc_donations</p></div>
<p>The second table holds the information about the donors, which they fill for themselves on the thank you page.</p>
<div id="attachment_901" class="wp-caption alignnone" style="width: 630px"><a href="http://tutorialzine.com/wp-content/uploads/2010/05/i4.png"><img class="size-full wp-image-901" title="Table Schema for dc_comments" src="http://tutorialzine.com/wp-content/uploads/2010/05/i4.png" alt="Table Schema for dc_comments" width="620" height="260" /></a><p class="wp-caption-text">Table Schema for dc_comments</p></div>
<p>You can create these tables in your database by running the SQL code from <strong>tables.sql</strong> (found in the download archive) from the SQL tab of phpMyAdmin. You can also just upload the file via the &#8220;Import&#8221; feature.</p>
<p>After this remember to add your MySQL login details to <strong>connect.php</strong>.</p>
<h3>Step 2 &#8211; XHTML</h3>
<p>Moving to the markup of the donation center iself. Donate PHP is the only page which your visitors see. The other page is <strong>thankyou.php</strong>, which is displayed only to the donors, once they&#8217;ve completed the donation process.</p>
<h4>donate.php</h4>
<pre class="brush:html">&lt;div id="main"&gt;
	&lt;h1&gt;Donation Center&lt;/h1&gt;
	&lt;h2&gt;Show Your Support for our Cause&lt;/h2&gt;

	&lt;div class="lightSection"&gt;
		&lt;h3&gt;Hello, dear visitor!&lt;/h3&gt;
		&lt;p&gt;This is Tutorialzine's Donation Center...&lt;/p&gt;	

		&lt;!-- The PayPal Donation Button --&gt;

	&lt;/div&gt;

	&lt;div class="chart"&gt;
		Our Goal
	&lt;/div&gt;

	&lt;div class="donations"&gt;
		&lt;?php echo $percent?&gt;% done
	&lt;/div&gt;

	&lt;div class="clear"&gt;&lt;/div&gt;

	&lt;div class="donors"&gt;
		&lt;h3&gt;The Donor List&lt;/h3&gt;
		&lt;h4&gt;Folks Who Showed Their Support&lt;/h4&gt;

		&lt;div class="comments"&gt;

		&lt;!-- PHP Code that generates the comments --&gt;

		&lt;/div&gt; &lt;!-- Closing the comments div --&gt;

	&lt;/div&gt; &lt;!-- Closing the donors div --&gt;

&lt;/div&gt; &lt;!-- Closing the main div --&gt;</pre>
<p>The <strong>.lightSection</strong> div holds the message that we show to the visitor of the page and the markup of the PayPal donation button, which you can see below. After this is the Pie chart which shows how much of our initial goal is met. The chart is generated with <a href="http://code.google.com/apis/charttools/index.html" target="_blank">Google&#8217;s Charting API</a>. Lastly is the <strong>.donors</strong> div, which holds a list of donors that have already donated.</p>
<h4>donate.php</h4>
<pre class="brush:html">&lt;form action="&lt;?php echo $payPalURL?&gt;" method="post" class="payPalForm"&gt;
	&lt;div&gt;
		&lt;input type="hidden" name="cmd" value="_donations" /&gt;
		&lt;input type="hidden" name="item_name" value="Donation" /&gt;

		&lt;!-- Your PayPal email: --&gt;
		&lt;input type="hidden" name="business"
		value="&lt;?php echo $myPayPalEmail?&gt;"/&gt;

		&lt;!-- PayPal will send an IPN notification to this URL: --&gt;
		&lt;input type="hidden" name="notify_url"
		value="&lt;?php echo $url.'/ipn.php'?&gt;" /&gt; 

		&lt;!-- The return page to which the user is
		navigated after the donations is complete: --&gt;

		&lt;input type="hidden" name="return"
		value="&lt;?php echo $url.'/thankyou.php'?&gt;" /&gt; 

		&lt;!-- Signifies that the transaction data will be
		passed to the return page by POST: --&gt;

		&lt;input type="hidden" name="rm" value="2" /&gt; 

		&lt;!-- General configuration variables for the paypal landing page. --&gt;

		&lt;input type="hidden" name="no_note" value="1" /&gt;
		&lt;input type="hidden" name="cbt" value="Go Back To The Site" /&gt;
		&lt;input type="hidden" name="no_shipping" value="1" /&gt;
		&lt;input type="hidden" name="lc" value="US" /&gt;
		&lt;input type="hidden" name="currency_code" value="USD" /&gt;

		&lt;!-- The amount of the transaction: --&gt;

		&lt;select name="amount"&gt;
		&lt;option value="50"&gt;$50&lt;/option&gt;
		&lt;option value="20"&gt;$20&lt;/option&gt;
		&lt;option value="10" selected="selected"&gt;$10&lt;/option&gt;
		&lt;option value="5"&gt;$5&lt;/option&gt;
		&lt;option value="2"&gt;$2&lt;/option&gt;
		&lt;option value="1"&gt;$1&lt;/option&gt;
		&lt;/select&gt;

		&lt;input type="hidden" name="bn" value="
		PP-DonationsBF:btn_donate_LG.gif:NonHostedGuest" /&gt;

		&lt;!-- You can change the image of the button: --&gt;
		&lt;input type="image" src="https://www.paypal.com/en_US/i/btn/btn_donate_LG.gif" name="submit" alt="PayPal - The safer, easier way to pay online!" /&gt;

	&lt;img alt="" src="https://www.paypal.com/en_US/i/scr/pixel.gif"
	width="1" height="1" /&gt;

	&lt;/div&gt;
&lt;/form&gt;
</pre>
<p>The PayPal Donation button is structured as a regular html form. When you click the Donate graphic, the form is submitted to PayPal. A number of customizations are available, such as the the amount of the donation, the email of the recipient of the donation and many more (the full list of options is located <a href="http://www.paypal.com/IntegrationCenter/ic_std-variable-ref-donate.html" target="_blank">here</a>). Each of this options is added as a hidden field to the form.</p>
<p>Note the <strong>return</strong> and the <strong>notify_url</strong> variables. The first takes the URL of the page to which the user is redirected after the completion of the payment (in our case  <strong>thankyou.php</strong>), and the other is a special page, which listens for PayPal&#8217;s Instant Payment Notifications (<strong>IPN</strong>).</p>
<blockquote><p>When a payment occurs, PayPal sends a special IPN notification to a page on your server. Data about the transaction is passed along the way, including the amount received, the email of the payee, currency and more. For example our IPN listener page, <strong>ipn.php</strong>, inserts the amount received to the donations table, which is later used by the Donation Center to calculate how much money has been gathered and what percentage of the goal has been met.</p></blockquote>
<p>Now lets move to the PHP part of the tutorial.</p>
<div id="attachment_902" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/05/donation-center-php-mysql-paypal-api/donate.php"><img class="size-full wp-image-902  " title="Setting a Goal with Google's Charting API" src="http://tutorialzine.com/wp-content/uploads/2010/05/i3.png" alt="Setting a Goal with Google's Charting API" width="620" height="260" /></a><p class="wp-caption-text">Setting a Goal with Google&#39;s Charting API</p></div>
<h3>Step 3 &#8211; PHP</h3>
<p>As mentioned in the previous step, when a payment occurs, PayPal sends an IPN notification to your script, which contains all kinds of data for the transaction. Implementing this IPN listener page involves a lot of coding, as the script must validate that the notification was issued by PayPal.</p>
<p>Lucky for us, there are nice people out there who have already implemented these validations and packed them into an easy to use <a href="http://www.phpclasses.org/package/2249-PHP-Process-Paypal-payment-interactions.html" target="_blank">PHP5 PayPal class</a>. Now lets take a look at how this is used:</p>
<h4>ipn.php</h4>
<pre class="brush:php">require "paypal_integration_class/paypal.class.php";
require "config.php";
require "connect.php";

$p = new paypal_class;
$p-&gt;paypal_url = $payPalURL; // $payPalURL is defined in config.php

if ($p-&gt;validate_ipn()) {
	if($p-&gt;ipn_data['payment_status']=='Completed')
	{
		$amount = $p-&gt;ipn_data['mc_gross'] - $p-&gt;ipn_data['mc_fee'];

		mysql_query("	INSERT INTO dc_donations (transaction_id,donor_email,amount,original_request)
						VALUES (
							'".esc($p-&gt;ipn_data['txn_id'])."',
							'".esc($p-&gt;ipn_data['payer_email'])."',
							".(float)$amount.",
							'".esc(http_build_query($_POST))."'
						)");
	}
}

function esc($str)
{
	global $link;
	return mysql_real_escape_string($str,$link);
}</pre>
<p>First we create a new <strong>paypal_class</strong> and assign it PayPal&#8217;s URL. The rest is just a matter of calling the <strong>$p-&gt;validate_ipn()</strong> method and it will do all the hard work for us. If everything went OK, we insert the amount of the transaction, the email of the payee and the transaction id to the <strong>dc_donations</strong> table. It is probably a good place to note, that this page is not visible to the end user, it only exists to listen for IPN notifications from paypal which happen on the backend.</p>
<h4>thankyou.php</h4>
<pre class="brush:php">require "config.php";
require "connect.php";

if(isset($_POST['submitform']) &amp;&amp; isset($_POST['txn_id']))
{
	$_POST['nameField'] = esc($_POST['nameField']);
	$_POST['websiteField'] =  esc($_POST['websiteField']);
	$_POST['messageField'] = esc($_POST['messageField']);

	$error = array();

	if(mb_strlen($_POST['nameField'],"utf-8")&lt;2)
	{
		$error[] = 'Please fill in a valid name.';
	}

	if(mb_strlen($_POST['messageField'],"utf-8")&lt;2)
	{
		$error[] = 'Please fill in a longer message.';
	}

	if(!validateURL($_POST['websiteField']))
	{
		$error[] = 'The URL you entered is invalid.';
	}

	$errorString = '';
	if(count($error))
	{
		$errorString = join('&lt;br /&gt;',$error);
	}
	else
	{
		mysql_query("	INSERT INTO dc_comments (transaction_id, name, url, message)
						VALUES (
							'".esc($_POST['txn_id'])."',
							'".$_POST['nameField']."',
							'".$_POST['websiteField']."',
							'".$_POST['messageField']."'
						)");

		if(mysql_affected_rows($link)==1)
		{
			$messageString = '&lt;a href="donate.php"&gt;You were added to our donor section!&lt;/a&gt;';
		}
	}
}</pre>
<p>After the use has donated, he is redirected by PayPal to our thank you page. Here he can add himself to the donor list by filling in a form. Wen redirecting, PayPal places transaction data in the <strong>$_POST</strong> array, which is available to <strong>thankyou.php</strong>. We can use this data to confirm that the user has in fact donated, and not just navigated manually to <strong>thankyou.php</strong>, bypassing PayPal. After the form is submitted, the user is added to the <strong>dc_comments</strong> table.</p>
<h4>donate.php</h4>
<pre class="brush:php">require "config.php";
require "connect.php";

// Determining the URL of the page:
$url = 'http://'.$_SERVER['SERVER_NAME'].dirname($_SERVER["REQUEST_URI"]);

// Fetching the number and the sum of the donations:
list($number,$sum) = mysql_fetch_array(mysql_query("SELECT COUNT(*),SUM(amount) FROM dc_donations"));

// Calculating how many percent of the goal are met:
$percent = round(min(100*($sum/$goal),100));

// Building a URL with Google's Chart API:
$chartURL = 'http://chart.apis.google.com/chart?chf=bg,s,f9faf7&amp;cht=p&amp;chd=t:'.$percent.',-'.(100-$percent).'&amp;chs=200x200&amp;chco=639600&amp;chp=1.57';
</pre>
<p>Google&#8217;s Chart Api is an easy way to generate any kind of chart. To use it you just have to create a URL to <a href="http://chart.apis.google.com/" target="_blank">http://chart.apis.google.com/</a> which contains settings such as background color, type of chart (in our case a Pie), and a comma-separated list of values which serve as the data. You can include this URL as you would do a regular image, and a chart will be dynamically generated for you.</p>
<h4>donate.php</h4>
<pre class="brush:php">&lt;?php
    $comments = mysql_query("SELECT * FROM dc_comments ORDER BY id DESC");

    // Building the Donor List:

    if(mysql_num_rows($comments))
    {
        while($row = mysql_fetch_assoc($comments))
        {
            ?&gt;

                &lt;div class="entry"&gt;
                    &lt;p class="comment"&gt;
                    &lt;?php
                        echo nl2br($row['message']); // Converting the newlines of the comment to &lt;br /&gt; tags
                    ?&gt;
                    &lt;span class="tip"&gt;&lt;/span&gt;
                    &lt;/p&gt;

                    &lt;div class="name"&gt;
                        &lt;?php echo $row['name']?&gt; &lt;a class="url" href="&lt;?php echo $row['url']?&gt;"&gt;&lt;?php echo $row['url']?&gt;&lt;/a&gt;
                    &lt;/div&gt;
                &lt;/div&gt;

            &lt;?php
        }
    }
?&gt;</pre>
<p>Later in <strong>donate.php</strong>, we are building the donor list after running a query against the <strong>dc_comments</strong> table.</p>
<div id="attachment_898" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/05/donation-center-php-mysql-paypal-api/donate.php"><img class="size-full wp-image-898 " title="The Donor List" src="http://tutorialzine.com/wp-content/uploads/2010/05/i1.png" alt="The Donor List" width="620" height="260" /></a><p class="wp-caption-text">The Donor List</p></div>
<h3>Step 4 &#8211; CSS</h3>
<p>Having all the markup generated and included in the page, it is time to style it. You may find it surprising but the entire design is entirely CSS based and does not use a single image (apart from PayPal&#8217;s Donate button image that is).</p>
<h4>styles.css &#8211; Part 1</h4>
<pre class="brush:css">*{
	/* Universal page reset */
	margin:0;
	padding:0;
}

body{
	/* Setting default text color, background and a font stack */
	font-size:13px;
	color:#9bb370;
	background-color:#f9faf7;
	font-family:Rockwell, 'Courier New', Courier, Georgia, serif;
}

p{
	font-family:Arial, Helvetica, sans-serif;
	font-size:20px;
}

h1{
	/* The Donation Center text */
	border-bottom:1px solid #E3EBD2;
	color:#639600;
	font-size:70px;
	line-height:1;
	margin-left:-20px;
	padding:0 0 0 30px;
}

h2{
	/* The subtitle, notice the line-height property */
	border-left:1px solid #E3EBD2;
	color:#ABC084;
	font-size:35px;
	height:35px;
	line-height:75px;
	margin:-70px 0 0;
	padding:55px 0 0 10px;
}

h3{
	color:#639600;
	font-size:38px;
}

#main{
	/* The main container div */
	margin:40px auto;
	padding:0 0 0 20px;
	position:relative;
	width:860px;
}</pre>
<p>You may notice in the demo page, how the Donation Center heading and subheading form an interesting set of lines. These are in fact the bottom and left borders of the h1 and h2 respectively.</p>
<h4>styles.css &#8211; Part 2</h4>
<pre class="brush:css">.chart{
	/* The Google Chart is set as this div's background via the style attribute.
	The negative text-indent moves the text outside the box */

	margin:0 0 0 300px;
	text-indent:-300px;
	width:200px;
}

.donations,.chart{
	color:#ABC084;
	font-size:50px;
	font-weight:bold;
	float:left;
	height:200px;
	line-height:200px;
}

.donations{ text-align:right; width:340px;}
.comments{ margin-top:60px;}
.entry{ margin-bottom:50px;}

.comment{
	background-color:#edf2e4;
	padding:20px;
	position:relative;
	margin-bottom:20px;
}

.name{
	color:#639600;
	font-size:24px;
	font-style:italic;
	font-weight:bold;
	position:relative;
}

.name a.url{
	color:#C0D39C;
	font-weight:normal;
	padding-left:10px;
}

.tip{
	width:0;
	height:0;
	bottom:-40px;
	left:20px;

	/* A neat CSS trick which creates a triangle shape*/
	/* from the div's top border */

	border:20px solid #f9faf7;
	border-width:20px 15px;
	border-top-color:#edf2e4;
	position:absolute;
}</pre>
<p>Creating a triangle shape with CSS is also possible by setting the width and the height of the div to zero and specifying a big value for the widths of the borders.</p>
<p><strong>With this our PHP &amp; MySQL Donation Center is complete!</strong></p>
<h3>Conclusion</h3>
<p>You can use this donation center to turn the usually anonymous act of donating funds into a more social and open process. You can possibly modify the code to include Twitter &amp; Facebook integration or improve it in any other way you see fit.</p>
<p><strong>What do you think? How would you improve this code?</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/05/donation-center-php-mysql-paypal-api/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>Simple Banner Rotator With PHP, jQuery &amp; MySQL</title>
		<link>http://tutorialzine.com/2010/04/simple-banner-rotator-with-php-jquery-mysql/</link>
		<comments>http://tutorialzine.com/2010/04/simple-banner-rotator-with-php-jquery-mysql/#comments</comments>
		<pubDate>Tue, 27 Apr 2010 20:59:49 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=867</guid>
		<description><![CDATA[In this tutorial we are making a simple PHP, jQuery &#038; MySQL banner rotator, with which you can create and randomly display banners on your site.]]></description>
			<content:encoded><![CDATA[<p>In this tutorial we are making a simple PHP, jQuery &amp; MySQL banner rotator, with which you can create and randomly display banners on your site. Each of the banners features a neat jQuery animation effect, which you can customize to fit your own needs.</p>
<h3>The database schema</h3>
<p>Before we start coding, lets take a look at the database. All the banners are inserted into the <strong>banners</strong> MySQL table. It has the following structure:</p>
<div id="attachment_871" class="wp-caption alignnone" style="width: 630px"><a href="http://tutorialzine.com/wp-content/uploads/2010/04/i13.png"><img class="size-full wp-image-871" title="The Database Schema" src="http://tutorialzine.com/wp-content/uploads/2010/04/i13.png" alt="The Database Schema" width="620" height="260" /></a><p class="wp-caption-text">The Database Schema</p></div>
<p><strong>ID</strong> is a primary key, which is auto-incremented, which means that you don&#8217;t need to add a number in that field if you are manually inserting new banners. Next is the <strong>image</strong> field, which holds the filename of the banner, after it is the <strong>company name</strong> and lastly the <strong>URL</strong> of the company&#8217;s site, all of which are varchar fields (regular strings).</p>
<p>If you want to run the demo on your own host, you will need to recreate this table from the definitions inside <strong>table.sql</strong> in the download archive. Just paste the SQL colde in your MySQL manager. Also don&#8217;t forget to fill in your MySQL login details in <strong>connect.php</strong>, before uploading the files to your server.</p>
<h3>Step 1 &#8211; XHTML</h3>
<p>The XHTML code of the banners is generated on the fly by PHP after a database query, and outputted to the page. Here is how the markup for a sample banner looks like:</p>
<h4>demo.php</h4>
<pre class="brush:html">&lt;div class="banner"&gt;
	&lt;a href="http://www.rapidxhtml.com/"&gt;
		&lt;img src="img/banners/rapidHTML.png" alt="Rapid HTML"
		width="125" height="125" /&gt;
	&lt;/a&gt;
	&lt;p class="companyInfo"&gt;Visit Rapid HTML&lt;/p&gt;
	&lt;div class="cornerTL"&gt;&lt;/div&gt;
	&lt;div class="cornerTR"&gt;&lt;/div&gt;
	&lt;div class="cornerBL"&gt;&lt;/div&gt;
	&lt;div class="cornerBR"&gt;&lt;/div&gt;
&lt;/div&gt;</pre>
<p>Inside each banner div, we have a hyperlink to the company&#8217;s site, a standard 125 by 125 px banner, a paragraph with the company name, and four corner divs.</p>
<p>The paragraph and the corner divs are hidden by default and are shown when the user moves their mouse over the main <strong>.banner</strong> div. This ensures that the banners are perfectly functional even with JavaScript disabled, albeit without the fancy transition.</p>
<div id="attachment_872" class="wp-caption alignnone" style="width: 630px"><a href="http://tutorialzine.com/wp-content/uploads/2010/04/i41.png"><img class="size-full wp-image-872" title="The jQuery Animation" src="http://tutorialzine.com/wp-content/uploads/2010/04/i41.png" alt="The jQuery Animation" width="620" height="260" /></a><p class="wp-caption-text">The jQuery Animation</p></div>
<h3>Step 2 &#8211; CSS</h3>
<p>Lets move to styling the page. To ensure cross-browser compatibility, we first have to reset the default styles that browsers apply to page elements. This is simple to do with a universal page reset:</p>
<h4>styles.css &#8211; Part 1</h4>
<pre class="brush:css">*{
	/* A universal page reset */
	margin:0;
	padding:0;
}

body{
	/* Setting default text color, background and a font stack */
	font-size:0.825em;
	color:#666;
	background-color:#fff;
	font-family:Arial, Helvetica, sans-serif;
}

.bannerHolder{
	/* The main banner unordered list */

	height:270px;
	width:270px;

	float:left;
	margin:20px 15px;
	padding:10px;
	background:#f7f7f7;
	border:1px solid #eee;

	/* CSS3 rounded corners */

	-moz-border-radius:12px;
	-webkit-border-radius:12px;
	border-radius:12px;
}

.bannerHolder li{
	/* Hiding the bullets of the li elements: */
	list-style:none;
	display:inline;
}

.banner{
	/* The banner divs */
	position:relative;
	width:125px;
	height:125px;
	overflow:hidden;
	float:left;
	margin:5px;
}

.banner img{
	/* The banner divs */
	display:block;
	border:none;
}</pre>
<p>As the banners are organized in an unordered list, we first style the list itself (which is assigned the <strong>bannerHolder</strong> class), then the li elements inside it and lastly the banner divs.</p>
<p>As we have two groups of banners on the page, we have to stick to class names to target the elements in the CSS, as IDs must be unique and don&#8217;t allow for more than one element with the same ID.</p>
<h4>styles.css &#8211; Part 2</h4>
<pre class="brush:css">.banner div{
	/* The dark animated divs */

	position:absolute;
	z-index:100;
	background-color:#222;
	width:60px;
	height:60px;
	cursor:pointer;

	/*	Setting a really big value for border-radius
		will make the divs perfect circles */

	-moz-border-radius:100px;
	-webkit-border-radius:100px;
	border-radius:100px;
}

/*	Positioning the animated divs outside the
	corners of the visible banner area: */

.banner .cornerTL{ left:-63px;top:-63px; }
.banner .cornerTR{ right:-63px;top:-63px; }
.banner .cornerBL{ left:-63px;bottom:-63px; }
.banner .cornerBR{ right:-63px;bottom:-63px; }

.banner p{
	/* The "Visit Company" text */

	display:none;	/* hidden by default */

	left:0;
	top:57px;
	width:100%;
	z-index:200;
	position:absolute;

	font-family:Tahoma, Arial, Helvetica, sans-serif;
	color:white;
	font-size:11px;
	text-align:center;

	cursor:pointer;
}</pre>
<p>In the second part of the code we style the animated rounded divs that slide into view on mouseenter. We are using the <strong>border-radius</strong> CSS3 property and by giving it a <strong>100px</strong> value, we turn the divs into perfect circles. We also position each of the four divs just outside its parent div.</p>
<div id="attachment_873" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/04/simple-banner-rotator-php-mysql-jquery/demo.php"><img class="size-full wp-image-873" title="A PHP, MySQL &amp; jQuery Banner Rotator" src="http://tutorialzine.com/wp-content/uploads/2010/04/i22.jpg" alt="A PHP, MySQL &amp; jQuery Banner Rotator" width="620" height="460" /></a><p class="wp-caption-text">A PHP, MySQL &amp; jQuery Banner Rotator</p></div>
<h3>Step 3 &#8211; PHP</h3>
<p>Moving to the PHP part, we will first take a look at the banner class.</p>
<h4>banner.class.php</h4>
<pre class="brush:php">class Banner{

	private $data = array();

	public function __construct($row){
		$this-&gt;data = $row;
	}

	public function html(){

		/* This method returns the banner's HTML code */

		$d = &amp;$this-&gt;data;
		$d['company'] = htmlspecialchars($d['company']);

		return '
			&lt;div class="banner"&gt;
				&lt;a href="'.$d['url'].'"&gt;
					&lt;img src="img/banners/'.$d['image'].'" alt="'.$d['company'].'"
					width="125" height="125" /&gt;
				&lt;/a&gt;
				&lt;p class="companyInfo"&gt;Visit '.$d['company'].'&lt;/p&gt;
				&lt;div class="cornerTL"&gt;&lt;/div&gt;
				&lt;div class="cornerTR"&gt;&lt;/div&gt;
				&lt;div class="cornerBL"&gt;&lt;/div&gt;
				&lt;div class="cornerBR"&gt;&lt;/div&gt;
			&lt;/div&gt;';
	}

}</pre>
<p>The constructor method of the class is executed when we create a banner object. It copies the <strong>$row</strong> variable we pass as a parameter to its internal private <strong>$data</strong> array.</p>
<p>The other method &#8211; <strong>html()</strong> &#8211; returns the HTML code of the banner.</p>
<p>You can see below how this class and its methods are used:</p>
<h4>demo.php</h4>
<pre class="brush:php">$bannerResult = mysql_query("SELECT * FROM banners");

$banners = array();
while($row=mysql_fetch_assoc($bannerResult))
{
	$banners[] = new Banner($row);
}

// Randomizing the $banners array:
shuffle($banners);

// Splitting the banners array into smaller arrays with 4 banners each:
$bannerGroups = array_chunk($banners,4);</pre>
<p>After selecting all the banners from the database, PHP fetches each row of the result as an associative array, and creates banner objects. After this the resulting <strong>$banners</strong> array is shuffled and split with the help of the in-build <strong>array_chunk()</strong> function.</p>
<blockquote><p>The <strong>array_chunk()</strong> PHP function splits an array into smaller chunks. It takes an <strong>array</strong> as its first parameter and a <strong>number</strong> as its second. The number specifies how many elements you want in the resulting chunks. The function splits the original array into smaller ones and returns them as an array of arrays.<br />
<small>Read more on array_chunk() at the <a href="http://php.net/manual/en/function.array-chunk.php" target="_blank">PHP docs</a>.</small></p></blockquote>
<p>As we have 8 banners, we end up with two elements in <strong>$bannerGroups</strong>, which we can print to the page:</p>
<h4>demo.php</h4>
<pre class="brush:php">&lt;ul class="bannerHolder"&gt;
	&lt;?php

		// Looping through the first group:
		foreach($bannerGroups[0] as $ban)
		{
			echo '&lt;li&gt;'.$ban-&gt;html().'&lt;/li&gt;';
		}

	?&gt;
&lt;/ul&gt;</pre>
<p>With all the markup generated and styled, we can move on with the jQuery part of the tutorial.</p>
<div id="attachment_874" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/04/simple-banner-rotator-php-mysql-jquery/demo.php"><img class="size-full wp-image-874" title="The Hover State" src="http://tutorialzine.com/wp-content/uploads/2010/04/i32.jpg" alt="The Hover State" width="620" height="260" /></a><p class="wp-caption-text">The Hover State</p></div>
<h3>Step 4 &#8211; jQuery</h3>
<p>After including the jQuery library to the page, we can start writing our own JavaScript code in script.js.</p>
<h4>script.js</h4>
<pre class="brush:js">$(document).ready(function(){

	// Lowering the opacity of all slide in divs
	$('.banner div').css('opacity',0.4);

	// Using the hover method
	$('.banner').hover(function(){

		// Executed on mouseenter

		var el = $(this);

		// Find all the divs inside the banner div,
		// and animate them with the new size

		el.find('div').stop().animate({width:200,height:200},'slow',function(){
			// Show the "Visit Company" text:
			el.find('p').fadeIn('fast');
		});

	},function(){

		// Executed on moseleave

		var el = $(this);

		// Hiding the text
		el.find('p').stop(true,true).hide();

		// Animating the divs
		el.find('div').stop().animate({width:60,height:60},'fast');

	}).click(function(){

		// When clicked, open a tab with the address of the hyperlink

		window.open($(this).find('a').attr('href'));

	});
});</pre>
<p>Using the <a href="http://tutorialzine.com/2010/02/the-jquery-hover-method/" target="_blank">hover method</a>, we bind two functions to the <strong>mouseenter </strong>and the <strong>mouseleave </strong>events. These respectively show and hide the four rounded divs and the paragraph tag.</p>
<p>Notice the use of the <strong>stop()</strong> function, which, as it name suggests, stops a running animation. Remember that if you need to stop a build-in effect like <strong>fadeOut()</strong>, you should pass two additional <strong>true</strong> parameters to the function.</p>
<p>Stopping animations is important, as firing a new animation before the old one has completed, will make them pile up, which is definitely not desired.</p>
<p>Finally, because the hyperlink is hidden below the divs and is thus unclickable, we listen to the click event on the main banner div, and open a new tab to the appropriate URL when the event occurs.</p>
<p><strong>With this our simple banner rotating script is complete!</strong></p>
<h3>Conclusion</h3>
<p>In this tutorial we demonstrated some of PHP&#8217;s OOP features, jQuery animations and some interesting CSS effects. You are free to modify this code and use it any way you like.</p>
<p><strong>What do you think? How would you modify this script?</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/04/simple-banner-rotator-with-php-jquery-mysql/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>Simple Bookmarking App With PHP, JS &amp; MySQL</title>
		<link>http://tutorialzine.com/2010/04/simple-bookmarking-app-php-javascript-mysql/</link>
		<comments>http://tutorialzine.com/2010/04/simple-bookmarking-app-php-javascript-mysql/#comments</comments>
		<pubDate>Wed, 14 Apr 2010 17:37:13 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=842</guid>
		<description><![CDATA[We are making a link sharing app, which will give you the ability to instantly share any web page, with a simple click of a bookmarklet on your bookmarks bar, and display it in a widget on your site.]]></description>
			<content:encoded><![CDATA[<p>Part of the developer&#8217;s life, is to strive for simplicity in every aspect of their work. When searching for solutions to common problems, you have the choice to lock yourself into all kinds of third party services and API&#8217;s, or take the opportunity and develop the functionality yourself.</p>
<p>In this week&#8217;s tutorial, we are making a simple link sharing app. This app will give you the ability to instantly share any web page, with a single click of a bookmarklet in your bookmarks bar, and display it in a widget on your site.</p>
<h3>The idea</h3>
<p>Clicking the bookmarklet includes a PHP script (evaluated as a JavaScript file) to the page you are viewing, with the title and the URL passed as <strong>GET</strong> parameters. The PHP script writes the page data to the MySQL database, and outputs a success message that is treated as JavaScript code and executed by the browser.</p>
<div id="attachment_851" class="wp-caption alignnone" style="width: 630px"><a href="http://tutorialzine.com/wp-content/uploads/2010/04/i31.png"><img class="size-full wp-image-851" title="The Idea" src="http://tutorialzine.com/wp-content/uploads/2010/04/i31.png" alt="The Idea" width="620" height="260" /></a><p class="wp-caption-text">The Idea</p></div>
<h3>The database schema</h3>
<p>Before moving to any development work, we need to create the database table that will hold all the bookmarks. The table definition is stored in <strong>table.sql</strong> in the download zip. You can run it in the SQL section of phpMyAdmin to recreate the table on your server. After this remember to change the MySQL login details in <strong>connect.php</strong>.</p>
<div id="attachment_848" class="wp-caption alignnone" style="width: 630px"><a href="http://tutorialzine.com/wp-content/uploads/2010/04/i12.png"><img class="size-full wp-image-848" title="Database Schema" src="http://tutorialzine.com/wp-content/uploads/2010/04/i12.png" alt="Database Schema" width="620" height="260" /></a><p class="wp-caption-text">Database Schema</p></div>
<p>Notice the HASH column. This is a unique field that stores the <strong>md5()</strong> sum of the URL field. We are using this to ensure that there are no duplicate links in the database. Inserting a link that already exists, will cause the query to fail and the <strong>mysql_affected_rows()</strong> function will return 0. We are using this in the PHP section of the tut to determine what message is going to be displayed to the user, as you will see in a few moments.</p>
<h3>Step 1 &#8211; XHTML</h3>
<p>XHTML markup is generated on the fly by PHP. It is only needed when presenting the shared links on your website. It is basically a simple unordered list with each shared page being a li element inside it.</p>
<h4>demo.php</h4>
<pre class="brush:html">&lt;ul class="latestSharesUL"&gt;

      &lt;!-- The LI elements are populated by PHP --&gt;

      &lt;li&gt;
          &lt;div class="title"&gt;&lt;a href="http://perfectionkills.com/" class="bookmrk"&gt;Perfection kills&lt;/a&gt;&lt;/div&gt;
          &lt;div class="dt"&gt;36 seconds ago&lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;
          &lt;div class="title"&gt;&lt;a href="http://html5test.com/" class="bookmrk"&gt;The HTML5 test - How well does your browser support HTML5?&lt;/a&gt;&lt;/div&gt;
          &lt;div class="dt"&gt;2 minutes ago&lt;/div&gt;
      &lt;/li&gt;
&lt;/ul&gt;</pre>
<p>The <strong>li</strong> elements are generated after PHP runs a query against the database for the latest bookmarks, as you will see in step 3. Each li contains the title of the page and the relative time since the bookmark was added. We will get back go this in the PHP part of the tutorial.</p>
<h3>Step 2 &#8211; CSS</h3>
<p>Again, the CSS code is only needed in the presentation part. You can modify the styling to match the rest of your site or ignore this code completely. Also, not all the styles are given here. You can see the rest in <strong>styles.css</strong> in the download archive.</p>
<h4>styles.css</h4>
<pre class="brush:css">ul.latestSharesUL{
	/* The bookmark widet */
	background-color:#f5f5f5;
	margin:0 auto;
	padding:10px;
	width:280px;
	border:1px solid #e0e0e0;
	text-shadow:1px 1px 0 white;

	font-size:13px;
	color:#666;
	font-family:Arial, Helvetica, sans-serif;
}

ul.latestSharesUL li{
	/* Each bookmark entry */
	background-color:#FAFAFA;
	border:1px solid #EAEAEA;
	border-bottom:none;
	list-style:none;
	padding:12px;
}

ul.latestSharesUL li:last-child{
	/* Targeting the last element of the set */
	border-bottom:1px solid #EAEAEA;
}

ul.latestSharesUL,
ul.latestSharesUL li{
	/* Adding regular and inset shadows */
	-moz-box-shadow:1px 1px 0 white inset, 0 0 2px white;
	-webkit-box-shadow:1px 1px 0 white inset, 0 0 2px white;
	box-shadow:1px 1px 0 white inset, 0 0 2px white;
}

.dt{
	/* The date time field */
	font-size:10px;
	padding-top:10px;
	color:#888;
}

a.bookmrk,
a.bookmrk:visited{
	/* The bookmark title in the widget */
	color:#666;
}
</pre>
<p>By using the box-shadow and border-radius CSS3 properties, we are cutting down on the number of divs that would otherwise be needed to achieve the same design. Also notice the use of the <strong>:last-child</strong> selector, which targets the last li in the unordered list, and adds a bottom border.</p>
<div id="attachment_849" class="wp-caption alignnone" style="width: 630px"><a href="http://tutorialzine.com/wp-content/uploads/2010/04/i21.png"><img class="size-full wp-image-849" title="The Bookmark Widget" src="http://tutorialzine.com/wp-content/uploads/2010/04/i21.png" alt="The Bookmark Widget" width="620" height="260" /></a><p class="wp-caption-text">The Bookmark Widget</p></div>
<h3>Step 3 &#8211; PHP</h3>
<p>First lets take a look at how the links are saved. As mentioned earlier, clicking the bookmarklet includes <strong>bookmark.php</strong> as a script in the head section of the current page. As it is served with a JavaScript content type, the browser will evaluate it as a regular JS file.</p>
<h4>bookmark.php</h4>
<pre class="brush:php">// Setting the content-type header to javascript:
header('Content-type: application/javascript');

// Validating the input data
if(empty($_GET['url']) || empty($_GET['title']) || !validateURL($_GET['url'])) die();

// Sanitizing the variables
$_GET['url'] = sanitize($_GET['url']);
$_GET['title'] = sanitize($_GET['title']);

// Inserting, notice the use of the hash field and the md5 function:
mysql_query("	INSERT INTO bookmark_app (hash,url,title)
				VALUES (
					'".md5($_GET['url'])."',
					'".$_GET['url']."',
					'".$_GET['title']."'
				)");

$message = '';
if(mysql_affected_rows($link)!=1)
{
	$message = 'This URL already exists in the database!';
}
else
$message = 'The URL was shared!';
</pre>
<p>The document title and URL are passed to this script by the bookmarklet and are available in the <strong>$_GET</strong> array. The data is sanitized and validated with our custom made <strong>sanitize()</strong> function, after which it is inserted in the database. Then, after checking the status of the <strong>mysql_affected_rows()</strong> function, we assign to the <strong>$message </strong>variable the appropriate status message that is going to be displayed to the user.</p>
<p>I would suggest to take a quick look at <strong>bookmark.php</strong> in the download zip, to see how PHP and JavaScript work together to successfully insert the bookmark and output the result.</p>
<p>Now lets move on to see how the bookmarks are displayed in a simple widget.</p>
<h4>demo.php</h4>
<pre class="brush:php">$shares = mysql_query("SELECT * FROM bookmark_app ORDER BY id DESC LIMIT 6");

while($row=mysql_fetch_assoc($shares))
{
	// Shortening the title if it is too long:
	if(mb_strlen($row['title'],'utf-8')&gt;80)
		$row['title'] = mb_substr($row['title'],0,80,'utf-8').'..';

	// Outputting the list elements:
	echo '
	&lt;li&gt;
		&lt;div class="title"&gt;&lt;a href="'.$row['url'].'" class="bookmrk"&gt;'.$row['title'].'&lt;/a&gt;&lt;/div&gt;
		&lt;div class="dt"&gt;'.relativeTime($row['dt']).'&lt;/div&gt;
	&lt;/li&gt;';
}</pre>
<p>This code selects the last 6 shared links from the database, generates the appropriate LI elements containing the title as a hyperlink to the bookmarked page, and calculate the relative time since the entry was published with our custom made <strong>relativeTime()</strong> function.</p>
<p>The custom functions we are using are defined in <strong>functions.php</strong>.</p>
<h4>functions.php</h4>
<pre class="brush:php">/* Helper functions */

function validateURL($str)
{
	return preg_match('/(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:\/~\+#]*[\w\-\@?^=%&amp;\/~\+#])?/i',$str);
}

function sanitize($str)
{
	if(ini_get('magic_quotes_gpc'))
		$str = stripslashes($str);

	$str = strip_tags($str);
	$str = trim($str);
	$str = htmlspecialchars($str);
	$str = mysql_real_escape_string($str);

	return $str;
}

function relativeTime($dt,$precision=2)
{
	if(is_string($dt)) $dt = strtotime($dt);

	$times=array(	365*24*60*60	=&gt; "year",
					30*24*60*60		=&gt; "month",
					7*24*60*60		=&gt; "week",
					24*60*60		=&gt; "day",
					60*60			=&gt; "hour",
					60				=&gt; "minute",
					1				=&gt; "second");

	$passed=time()-$dt;

	if($passed&lt;5)
	{
		$output='less than 5 seconds ago';
	}
	else
	{
		$output=array();
		$exit=0;

		foreach($times as $period=&gt;$name)
		{
			if($exit&gt;=$precision || ($exit&gt;0 &amp;&amp; $period&lt;60)) break;

			$result = floor($passed/$period);
			if($result&gt;0)
			{
				$output[]=$result.' '.$name.($result==1?'':'s');
				$passed-=$result*$period;
				$exit++;
			}
			else if($exit&gt;0) $exit++;
		}

		$output=implode(' and ',$output).' ago';
	}

	return $output;
}
</pre>
<p>One of the guiding principles when building web applications is &#8220;Do not trust your users&#8221;. This implies that all input data has to be properly escaped. This is exactly what the <strong>sanitize()</strong> function is doing &#8211; it prevents possible XSS attacks, strips any HTML tags and escapes all the HTML characters that could potentially break your markup when displayed.</p>
<p>The other interesting function is <strong>relativeTime()</strong>, which takes the timestamp field, assigned to each bookmark, and turns it into a user-friendly relative time string. It also takes an optional second argument, which limits the number of time units that are returned (setting precision to 1 will return <em>1 hour ago</em>, instead of <em>1 hour and 10 minutes</em> ago).</p>
<h3>Step 4 &#8211; JavaScript</h3>
<p>As the script is dynamically included in third party pages, it is not a good idea to rely on third party libraries like jQuery. This is why, for a change, we are going to work with pure JavaScript.</p>
<p>First, lets take a look at the bookmarklet code.</p>
<h4>bookmarklet code</h4>
<pre class="brush:js">(function () {
	var jsScript = document.createElement('script');

	jsScript.setAttribute('type', 'text/javascript');
	jsScript.setAttribute('src', '/bookmark.php?url=' + encodeURIComponent(location.href) + '&amp;title=' + encodeURIComponent(document.title));

	document.getElementsByTagName('head')[0].appendChild(jsScript);
})();</pre>
<p>The bookmarklet is just a regular hyperlink, which has the code above preceded with the <strong>javascript:</strong> protocol as its <strong>href</strong> attribute. When clicked, the snippet creates a new script element, sets <strong>bookmark.php</strong> as its URL (along with the encoded title and URL of the currently active page), and appends it to the head section of the document. It is not as pretty as it would have been if we used the jQuery library, but it gets the job done.</p>
<p>Now lets return to <strong>bookmark.php</strong>.</p>
<h4>bookmark.php</h4>
<pre class="brush:js">function displayMessage(str)
{
	// Using pure JavaScript to create and style a div element

	var d = document.createElement('div');

	with(d.style)
	{
		// Applying styles:

		position='fixed';
		width = '350px';
		height = '20px';
		top = '50%';
		left = '50%';
		margin = '-30px 0 0 -195px';
		backgroundColor = '#f7f7f7';
		border = '1px solid #ccc';
		color = '#777';
		padding = '20px';
		fontSize = '18px';
		fontFamily = '"Myriad Pro",Arial,Helvetica,sans-serif';
		textAlign = 'center';
		zIndex = 100000;

		textShadow = '1px 1px 0 white';

		MozBorderRadius = "12px";
		webkitBorderRadius = "12px";
		borderRadius = "12px";

		MozBoxShadow = '0 0 6px #ccc';
		webkitBoxShadow = '0 0 6px #ccc';
		boxShadow = '0 0 6px #ccc';
	}

	d.setAttribute('onclick','document.body.removeChild(this)');

    // Adding the message passed to the function as text:
	d.appendChild(document.createTextNode(str));

    // Appending the div to document
	document.body.appendChild(d);

    // The message will auto-hide in 3 seconds:

	setTimeout(function(){
		try{
			document.body.removeChild(d);
		}	catch(error){}
	},3000);
}</pre>
<p>The JavaScript code above is right below the PHP logic that inserts the bookmark to the database in bookmark.php. The <strong>displayMessage()</strong> JavaScript function creates a div element, styles it and displays it in the center of the page.</p>
<p>As <strong>bookmark.php</strong> is evaluated as a JS file, every text that it outputs is treated as regular JavaScirpt code. As we mentioned in the PHP step, bookmark.php receives the document title and URL, inserts them in the database, and creates the <strong>$message</strong> variable. This is later outputted as a call to the <strong>displayMessage()</strong> function, which executes the above code and shows the message:</p>
<pre class="brush:php">// Adding a line that will call the JavaScript function:
echo 'displayMessage("'.$message.'");';
</pre>
<p><strong>With this our simple bookmarking app is complete!</strong></p>
<h3>Conclusion</h3>
<p>If you plan to use this widget to share links with your visitors (or to save them for yourself) be sure to upload the script to a directory with a random name, as this script does not offer authentication. This is also the reason why it is so simple to set up and use.</p>
<p><strong>What do you think? What do you plan to use it for?</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/04/simple-bookmarking-app-php-javascript-mysql/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>Carbon Fiber Signup Form With PHP, jQuery and CSS3</title>
		<link>http://tutorialzine.com/2010/04/carbon-signup-form/</link>
		<comments>http://tutorialzine.com/2010/04/carbon-signup-form/#comments</comments>
		<pubDate>Wed, 07 Apr 2010 14:28:51 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=830</guid>
		<description><![CDATA[In this tutorial we are making a carbon fiber - style form, build using progressive enhancement. It is fully AJAX-ed, features its own custom tooltip validation, and is even perfectly usable with JavaScript disabled.]]></description>
			<content:encoded><![CDATA[<p>Today we are making a carbon fiber &#8211; style form, build using progressive enhancement. This  means that we first ensure that the form works well without JavaScript  and fancy CSS support (think of IE6 here) and later move on by layering  over cool styling, AJAX and jQuery magic.</p>
<p>The form features its own custom tooltip validation, and is even perfectly usable with JavaScript disabled.</p>
<h3>Step 1 &#8211; XHTML</h3>
<p>The first step includes creating the XHTML backbone of the form. It has to be simple, and, according to the principles defined by progressive enhancement, must be perfectly usable by itself.</p>
<h4>demo.html</h4>
<pre class="brush:html">&lt;div id="carbonForm"&gt;
	&lt;h1&gt;Signup&lt;/h1&gt;

	&lt;form action="submit.php" method="post" id="signupForm"&gt;

		&lt;div class="fieldContainer"&gt;
			&lt;div class="formRow"&gt;&lt;/div&gt;
			&lt;!-- Two more formRow divs --&gt;
		&lt;/div&gt;

		&lt;div class="signupButton"&gt;
			&lt;input type="submit" name="submit" id="submit" value="Signup" /&gt;
		&lt;/div&gt;

	&lt;/form&gt;
&lt;/div&gt;</pre>
<p>The <strong>carbonForm </strong>div is the main container for the form. It is centered in the middle of the page with the CSS <strong>margin </strong>property, and then centered vertically with jQuery (take a look at <a href="http://tutorialzine.com/2010/03/centering-div-vertically-and-horizontally/" target="_blank">our MicroTut</a> for more info about centering).</p>
<p>Inside it we have the heading and the form with the <strong>fieldContainer </strong>div. Inside it there are three <strong>formRow </strong>divs, which share the markup given below:</p>
<h4>demo.html</h4>
<pre class="brush:html">&lt;div class="formRow"&gt;
	&lt;div class="label"&gt;
		&lt;label for="name"&gt;Name:&lt;/label&gt;
	&lt;/div&gt;

	&lt;div class="field"&gt;
		&lt;input type="text" name="name" id="name" /&gt;
	&lt;/div&gt;
&lt;/div&gt;</pre>
<p>Each pair of <strong>label </strong>and <strong>input </strong>elements is positioned inside its own wrapping divs, which are floated to the left. This allows for the layout of the form you can see in the demonstration page. It is important to have the text box names the <strong>same</strong> as their <strong>id</strong>s, because this is used to display the error tooltips as you will see in the next steps.</p>
<div id="attachment_837" class="wp-caption alignnone" style="width: 630px"><a href="http://tutorialzine.com/wp-content/uploads/2010/04/i11.png"><img class="size-full wp-image-837" title="Carbon Fiber Signup Form" src="http://tutorialzine.com/wp-content/uploads/2010/04/i11.png" alt="Carbon Fiber Signup Form" width="620" height="460" /></a><p class="wp-caption-text">Carbon Fiber Signup Form</p></div>
<h3>Step 2 &#8211; CSS</h3>
<p>The form relies heavily on CSS to achieve the carbon fiber effect. A number of CSS3 rules are used as well, which successfully mimic the effects previously possible only in graphic suites as Photoshop. Only the most interesting styles are given here, you can see the rest in <strong>styles.css</strong> in the download archive.</p>
<h4>styles.css</h4>
<pre class="brush:css">#carbonForm{
	/* The main form container */
	background-color:#1C1C1C;
	border:1px solid #080808;
	margin:20px auto;
	padding:20px;
	width:500px;

	-moz-box-shadow:0 0 1px #444 inset;
	-webkit-box-shadow:0 0 1px #444 inset;
	box-shadow:0 0 1px #444 inset;
}

.fieldContainer{
	/* The light rounded section, which contans the fields */
	background-color:#1E1E1E;
	border:1px solid #0E0E0E;
	padding:30px 10px;

	/* CSS3 box shadow, used as an inner glow */
	-moz-box-shadow:0 0 20px #292929 inset;
	-webkit-box-shadow:0 0 20px #292929 inset;
	box-shadow:0 0 20px #292929 inset;
}

#carbonForm,.fieldContainer,.errorTip{
	/* Rounding the divs at once */
	-moz-border-radius:12px;
	-webkit-border-radius:12px;
	border-radius:12px;
}

.formRow{
	height:35px;
	padding:10px;
	position:relative;
}

.label{
	float:left;
	padding:0 20px 0 0;
	text-align:right;
	width:70px;
}

label{
	font-family:Century Gothic,Myriad Pro,Arial,Helvetica,sans-serif;
	font-size:11px;
	letter-spacing:1px;
	line-height:35px; /* Neat line height trick */
}

.field{
	float:left;
}

.field input{
	/* The text boxes */
	border:1px solid white;
	color:#666666;
	font-family:Arial,Helvetica,sans-serif;
	font-size:22px;
	padding:4px 5px;
	background:url("img/box_bg.png") repeat-x scroll left top #FFFFFF;
	outline:none;
}

#submit{
	/* The submit button */
	border:1px solid #f4f4f4;
	cursor:pointer;
	height:40px;
	text-indent:-9999px;
	text-transform:uppercase;
	width:110px;

	background:url("img/submit.png") no-repeat center center #d0ecfd;

	-moz-border-radius:6px;
	-webkit-border-radius:6px;
	border-radius:6px;
}

#submit.active{
	/* Marking the submit button as active adds the preloader gif as background */
	background-image:url("img/preloader.gif");
}

input:hover,
input:focus{
	/* CSS3 glow effect */
	-moz-box-shadow:0 0 8px lightblue;
	-webkit-box-shadow:0 0 8px lightblue;
	box-shadow:0 0 8px lightblue;
}</pre>
<p>Most of these rules are pretty straightforward. You may find interesting how we handle the submit button, as this element is quite tricky to style consistently cross-browser.</p>
<p>To hide the text of the button (in our case &#8220;<em>Signup</em>&#8220;), we can use the <strong>negative text-indent</strong> trick, but in IE it only works if we also specify the <strong>text-transform:uppercase</strong> rule. We also add a transparent background image consisting of the text &#8220;<em>Submit</em>&#8221; in <em>Century Gothic</em>, which is replaced with a rotating gif preloader if the button is assigned an &#8220;<em>active</em>&#8221; class.</p>
<p>We also use a number of CSS3 effects along with their vendor-specific versions for better compatibility. <strong>border-radius</strong> is for rounded corners, and with <strong>box-shadow</strong> we can mimic different glow and shadow effects.</p>
<div id="attachment_838" class="wp-caption alignnone" style="width: 630px"><a href="http://tutorialzine.com/wp-content/uploads/2010/04/i2.png"><img class="size-full wp-image-838" title="CSS3 Rounded Corners &amp; Glow" src="http://tutorialzine.com/wp-content/uploads/2010/04/i2.png" alt="CSS3 Rounded Corners &amp; Glow" width="620" height="260" /></a><p class="wp-caption-text">CSS3 Rounded Corners &amp; Glow</p></div>
<h3>Step 3 &#8211; jQuery</h3>
<p>After including the jQuery library and our own <strong>script.js</strong> file in the page, we can move on to writing the JavaScript code that will breathe some life into the form.</p>
<h4>script.js</h4>
<pre class="brush:js">$(document).ready(function(){
	// $(document).ready() is executed after the page DOM id loaded

	// Binding an listener to the submit event on the form:
	$('#signupForm').submit(function(e){

		// If a previous submit is in progress:
		if($('#submit').hasClass('active')) return false;

		// Adding the active class to the button. Will show the preloader gif:
		$('#submit').addClass('active');

		// Removing the current error tooltips
		$('.errorTip').remove();

		// Issuing a POST ajax request to submit.php (the action attribute of the form):
		$.post($('#signupForm').attr('action'),
			$('#signupForm').serialize()+'&amp;fromAjax=1',function(response){

			if(!response.status)
			{
				// Some kind of input error occured

				// Looping through all the input text boxes,
				// and checking whether they produced an error
				$('input[type!=submit]').each(function(){
					var elem = $(this);
					var id = elem.attr('id');

					if(response[id])
						showTooltip(elem,response[id]);
				});
			}
			else location.replace(response.redirectURL);

			$('#submit').removeClass('active');
		},'json');

		e.preventDefault();
	});

	$(window).resize();
});

// Centering the form vertically on every window resize:
$(window).resize(function(){
	var cf = $('#carbonForm');

	$('#carbonForm').css('margin-top',($(window).height()-cf.outerHeight())/2)
});

// Helper function that creates an error tooltip:
function showTooltip(elem,txt)
{
	// elem is the text box, txt is the error text
	$('&lt;div class="errorTip"&gt;').html(txt).appendTo(elem.closest('.formRow'));
}</pre>
<p>Clicking the submit button (or pressing the <em>enter </em>key while entering text in one of the fields) submits the form. The function that is bound to the submit event prevents this from happening with <strong>e.preventDefault()</strong> and issues an AJAX request to <strong>submit.php</strong> instead.</p>
<p>The response that is returned is evaluated as JSON code (a JavaScript object), which contains a special <strong>status </strong>property. Depending on its value, the script either shows error tooltips on the fields, or redirects the browser to the specified URL in the response.</p>
<h4>sample error response</h4>
<pre class="brush:js">{
	"status"	: 0,	// Indicates that the response is an error
	"email"		: "Please fill in a valid email!",		// Error message
	"pass"		: "Please fill in a valid password!"	// Error message
}
</pre>
<p>The error tooltips are generated by the script while looping though all the fields in the form and checking whether their ids exist as properties in the response object. If they do, a tooltip is created with the <strong>showTooltip()</strong> function.</p>
<p>Also notice how we use the <strong>serialize()</strong> method on line 18 to send all the form fields at once. Also, on this same line, we set <strong>fromAjax=1</strong>, which is going to tell PHP to return the response as JSON.</p>
<p>Now lets see how this response is generated and how the form is  validated.</p>
<div id="attachment_839" class="wp-caption alignnone" style="width: 630px"><a href="http://tutorialzine.com/wp-content/uploads/2010/04/i3.png"><img class="size-full wp-image-839" title="Dynamically Inserted Error Tooltips" src="http://tutorialzine.com/wp-content/uploads/2010/04/i3.png" alt="Dynamically Inserted Error Tooltips" width="620" height="260" /></a><p class="wp-caption-text">Dynamically Inserted Error Tooltips</p></div>
<h3>Step 4 &#8211; PHP</h3>
<p>The good thing about this form is that it is usable even if JavaScript is disabled. This works, because the action attribute of the form element is also set to <strong>submit.php</strong>. This means that we only have to implement the validation once no matter how the form is sent.</p>
<h4>submit.php</h4>
<pre class="brush:php">// Error reporting:
error_reporting(E_ALL^E_NOTICE);

// This is the URL your users are redirected,
// when registered succesfully:

$redirectURL = 'http://demo.tutorialzine.com/2010/04/carbon-signup-form/demo.html';

$errors = array();

// Checking the input data and adding potential errors to the $errors array:

if(!$_POST['name'] || strlen($_POST['name'])&lt;3 || strlen($_POST['name'])&gt;50)
{
	$errors['name']='Please fill in a valid name!&lt;br /&gt;Must be between 3 and 50 characters.';
}

if(!$_POST['email'] || !preg_match("/^[\.A-z0-9_\-\+]+[@][A-z0-9_\-]+([.][A-z0-9_\-]+)+[A-z]{1,4}$/", $_POST['email']))
{
	$errors['email']='Please fill in a valid email!';
}

if(!$_POST['pass'] || strlen($_POST['pass'])&lt;5)
{
	$errors['pass']='Please fill in a valid password!&lt;br /&gt;Must be at least 5 characters long.';
}

// Checking whether the request was sent via AJAX
// (we manually send the fromAjax var with the AJAX request):

if($_POST['fromAjax'])
{
	if(count($errors))
	{
		$errString = array();
		foreach($errors as $k=&gt;$v)
		{
			// The name of the field that caused the error, and the
			// error text are grouped as key/value pair for the JSON response:
			$errString[]='"'.$k.'":"'.$v.'"';
		}

		// JSON error response:
		die	('{"status":0,'.join(',',$errString).'}');
	}

	// JSON success response. Returns the redirect URL:
	echo '{"status":1,"redirectURL":"'.$redirectURL.'"}';

	exit;
}

// If the request was not sent via AJAX (probably JavaScript
// has been disabled in the visitors' browser):

if(count($errors))
{
	echo '&lt;h2&gt;'.join('&lt;br /&gt;&lt;br /&gt;',$errors).'&lt;/h2&gt;';
	exit;
}

// Directly redirecting the visitor if JS is disabled:

header("Location: ".$redirectURL);</pre>
<p>All the encountered errors are added to the <strong>$errors</strong> array. This, depending on whether <strong>fromAjax</strong> was set or not,  is later returned either as a JSON object, or directly printed to the screen.</p>
<p>With this our carbon fiber signup form is complete!</p>
<h3>Conclusion</h3>
<p>You can modify and build upon this form any way you like. At present, the form does not actually register users, but you can add the code necessary to do so. It will also do a great job as a contact form for your site.</p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/04/carbon-signup-form/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>AJAX-ed Todo List With PHP, MySQL &amp; jQuery</title>
		<link>http://tutorialzine.com/2010/03/ajax-todo-list-jquery-php-mysql-css/</link>
		<comments>http://tutorialzine.com/2010/03/ajax-todo-list-jquery-php-mysql-css/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 21:21:00 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=807</guid>
		<description><![CDATA[In this tutorial we are making a simple AJAX-ed Todo List App, with PHP, MySQL and jQuery. In the process we are going to demonstrate PHP's OOP capabilities, play with jQuery UI and implement some nice AJAX functionality.]]></description>
			<content:encoded><![CDATA[<p>In this tutorial we are making a simple AJAX-ed Todo List App, with PHP, MySQL and jQuery. In the process we are going to demonstrate PHP&#8217;s OOP capabilities, play with jQuery UI and implement some nice AJAX functionality.</p>
<p>For a better understanding of the steps of this tutorial, you an go ahead and download the <strong>demo archive</strong> available from the button above.</p>
<h3>Step 1 &#8211; PHP</h3>
<p>As this is more of a developer-oriented tutorial, we are going to start with the PHP part. Unlike previous tutorials, this time we are leveraging the OOP features of PHP 5.</p>
<blockquote><p>The author presumes you have a basic understanding of the core concepts behind object oriented programming, and PHP 5&#8242;s OOP implementation. For a quick reference, check out these pages of PHP&#8217;s documentation: <a href="http://php.net/manual/en/language.oop5.basic.php" target="_blank">OOP Basics</a>, <a href="http://php.net/manual/en/language.oop5.static.php" target="_blank">Static Methods</a>, <a href="http://php.net/manual/en/language.exceptions.php" target="_blank">Exceptions</a>, <a href="http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.tostring" target="_blank">Magic Methods</a>.</p></blockquote>
<p>All of the functionality available to the end user &#8211; creating, editing, deleting and reordering the todo items &#8211; is implemented as different methods of a class, explained in detail below.</p>
<h4>todo.class.php &#8211; Part 1</h4>
<pre class="brush:php">/* Defining the ToDo class */

class ToDo{

	/* An array that stores the todo item data: */

	private $data;

	/* The constructor */
	public function __construct($par){
		if(is_array($par))
			$this-&gt;data = $par;
	}

	/*
		This is an in-build "magic" method that is automatically called
		by PHP when we output the ToDo objects with echo.
	*/

	public function __toString(){

		// The string we return is outputted by the echo statement

		return '
			&lt;li id="todo-'.$this-&gt;data['id'].'" class="todo"&gt;

				&lt;div class="text"&gt;'.$this-&gt;data['text'].'&lt;/div&gt;

				&lt;div class="actions"&gt;
					&lt;a href="" class="edit"&gt;Edit&lt;/a&gt;
					&lt;a href="" class="delete"&gt;Delete&lt;/a&gt;
				&lt;/div&gt;

			&lt;/li&gt;';
	}</pre>
<p>The constructor takes the array passed as a parameter and stores it in the <strong>$data</strong> property of the class. This array is a row fetched from the database with <strong>mysql_fetch_assoc()</strong> and contains the id and the text of the todo item.</p>
<p>After this is the magic <strong>__toString()</strong> method, which is called internally when we attempt to echo out an object of this class. The string it returns contains the markup used by each todo item &#8211; a <strong>&lt;li&gt;</strong> element with a unique id and a classname  &#8220;todo&#8221;, inside of which we have the text of the todo and the two action hyperlinks.</p>
<div id="attachment_810" class="wp-caption alignnone" style="width: 630px"><a href="http://tutorialzine.com/wp-content/uploads/2010/03/i23.png"><img class="size-full wp-image-810" title="AJAX, jQuery &amp; CSS3 To Do List" src="http://tutorialzine.com/wp-content/uploads/2010/03/i23.png" alt="AJAX, jQuery &amp; CSS3 To Do List" width="620" height="260" /></a><p class="wp-caption-text">AJAX, jQuery &amp; CSS3 To Do List</p></div>
<h4>todo.class.php &#8211; Part 2</h4>
<pre class="brush:php">	/*
		The edit method takes the ToDo item id and the new text
		of the ToDo. Updates the database.
	*/

	public static function edit($id, $text){

		$text = self::esc($text);
		if(!$text) throw new Exception("Wrong update text!");

		mysql_query("	UPDATE tz_todo
						SET text='".$text."'
						WHERE id=".$id
					);

		if(mysql_affected_rows($GLOBALS['link'])!=1)
			throw new Exception("Couldn't update item!");
	}

	/*
		The delete method. Takes the id of the ToDo item
		and deletes it from the database.
	*/

	public static function delete($id){

		mysql_query("DELETE FROM tz_todo WHERE id=".$id);

		if(mysql_affected_rows($GLOBALS['link'])!=1)
			throw new Exception("Couldn't delete item!");
	}

	/*
		The rearrange method is called when the ordering of
		the todos is changed. Takes an array parameter, which
		contains the ids of the todos in the new order.
	*/

	public static function rearrange($key_value){

		$updateVals = array();
		foreach($key_value as $k=&gt;$v)
		{
			$strVals[] = 'WHEN '.(int)$v.' THEN '.((int)$k+1).PHP_EOL;
		}

		if(!$strVals) throw new Exception("No data!");

		// We are using the CASE SQL operator to update the ToDo positions en masse:

		mysql_query("	UPDATE tz_todo SET position = CASE id
						".join($strVals)."
						ELSE position
						END");

		if(mysql_error($GLOBALS['link']))
			throw new Exception("Error updating positions!");
	}</pre>
<p>The definition of the class continues with a number of static methods. Those are special methods, which can be accessed without the need of an object of the class to be created. For example, you can call the edit method by writing: <strong>ToDo::edit($par1,$par2)</strong>.</p>
<p>Notice how we are using exceptions to handle errors. When an exception occurs the script execution halts and it is up to the rest of the script to catch it and output the appropriate status.</p>
<p>Also you may find interesting the way we are updating the database with the new positions of the todo items. We are using the <strong>CASE</strong> operator, available in MySQL.  This way, no matter how many todos are in the database, we execute only one query.</p>
<blockquote><p>Saving queries and optimizing your scripts, although tedious, is hugely beneficial in the long run. You can read more about the<strong> CASE </strong>operator (among other interesting features) in <a href="http://dev.mysql.com/doc/refman/5.0/en/case-statement.html" target="_blank">MySQL&#8217;s official documentation</a>.</p></blockquote>
<h4>todo.class.php &#8211; Part 3</h4>
<pre class="brush:php">	/*
		The createNew method takes only the text of the todo as a parameter,
		writes to the database and outputs the new todo back to
		the AJAX front-end.
	*/

	public static function createNew($text){

		$text = self::esc($text);
		if(!$text) throw new Exception("Wrong input data!");

		$posResult = mysql_query("SELECT MAX(position)+1 FROM tz_todo");

		if(mysql_num_rows($posResult))
			list($position) = mysql_fetch_array($posResult);

		if(!$position) $position = 1;

		mysql_query("INSERT INTO tz_todo SET text='".$text."', position = ".$position);

		if(mysql_affected_rows($GLOBALS['link'])!=1)
			throw new Exception("Error inserting TODO!");

		// Creating a new ToDo and outputting it directly:

		echo (new ToDo(array(
			'id'	=&gt; mysql_insert_id($GLOBALS['link']),
			'text'	=&gt; $text
		)));

		exit;
	}

	/*
		A helper method to sanitize a string:
	*/

	public static function esc($str){

		if(ini_get('magic_quotes_gpc'))
			$str = stripslashes($str);

		return mysql_real_escape_string(strip_tags($str));
	}

} // closing the class definition
</pre>
<p>Accessing static methods from the same class can easily be done with the <strong>self::</strong> keyword. This way we are using the <strong>esc()</strong> method to sanitize the incoming user data.</p>
<p>Also notice the <strong>createNew()</strong> method. In it, after running the INSERT query on the database, we use the returned auto-assigned unique id with <strong>mysql_insert_id()</strong> and create a new todo object, which is then echoed out to the front end.</p>
<p>Now lets take a look at how this class is used.</p>
<h4>demo.php &#8211; Part 1</h4>
<pre class="brush:php">// Select all the todos, ordered by position:
$query = mysql_query("SELECT * FROM `tz_todo` ORDER BY `position` ASC");

$todos = array();

// Filling the $todos array with new ToDo objects:

while($row = mysql_fetch_assoc($query)){
	$todos[] = new ToDo($row);
}</pre>
<p>After including <strong>todo.class.php</strong> in <strong>demo.php</strong>, we select the todo items and loop through the MySQL result set, filling in the <strong>$todos</strong> array with objects.</p>
<h4>demo.php &#8211; Part 2</h4>
<pre class="brush:php">// Looping and outputting the $todos array. The __toString() method
// is used internally to convert the objects to strings:

foreach($todos as $item){
	echo $item;
}</pre>
<p>Later in the page, these objects are echoed out. Thanks to the <strong>__toString()</strong> method discussed above, all the markup is automatically generated, so we do not have to deal with any of that.</p>
<p>The front end issues a number of different AJAX calls. Making a separate file to handle each of them would be a bit of overkill, so the best solution is to group them in a single AJAX handling file. This is done in <strong>ajax.php</strong>, which you can see below.</p>
<h4>ajax.php</h4>
<pre class="brush:php">$id = (int)$_GET['id'];

try{

	switch($_GET['action'])
	{
		case 'delete':
			ToDo::delete($id);
			break;

		case 'rearrange':
			ToDo::rearrange($_GET['positions']);
			break;

		case 'edit':
			ToDo::edit($id,$_GET['text']);
			break;

		case 'new':
			ToDo::createNew($_GET['text']);
			break;
	}

}
catch(Exception $e){
//	echo $e-&gt;getMessage();
	die("0");
}

echo "1";</pre>
<p>With the help of a switch statement, we decide which of the static methods of the ToDo class to execute. If an error occurs in one of these methods, an exception is dispatched. Because the whole switch is enclosed in a <strong>try statement</strong>, execution of the script halts and control is passed to the catch statement, which outputs a zero and exits the script.</p>
<p>You could potentially echo (or write to a log) exactly what kind of error occurred by uncommenting line 26.</p>
<h3>Step 2 &#8211; MySQL</h3>
<p>The <strong>tz_todo</strong> table holds and assigns the unique ids of the todo items (via the auto_increment setting of the field), the position, the text and the dt_added timestamp.</p>
<div id="attachment_811" class="wp-caption alignnone" style="width: 630px"><a href="http://tutorialzine.com/wp-content/uploads/2010/03/i13.png"><img class="size-full wp-image-811" title="Database Schema" src="http://tutorialzine.com/wp-content/uploads/2010/03/i13.png" alt="Database Schema" width="620" height="260" /></a><p class="wp-caption-text">Database Schema</p></div>
<p>You can find the SQL that will recreate the table in <strong>table.sql</strong> in the download archive. Also, if you plan to run the demo on your own server, don&#8217;t forget to fill in your login details in <strong>connect.php</strong>.</p>
<h3>Step 3 &#8211; XHTML</h3>
<p>As most of the markup is generated by PHP, we are left with taking care of the rest of the page&#8217;s XHTML. First we need to include <strong>jQuery</strong>, <strong>jQuery UI</strong>, and the stylesheets in the document. It is considered a good practice to include the stylesheets to the head section, and the JavaScript files right before the closing <strong>&lt;/body&gt;</strong> tag.</p>
<pre class="brush:html">&lt;link rel="stylesheet" href="jquery-ui.css" type="text/css" /&gt;
&lt;link rel="stylesheet" type="text/css" href="styles.css" /&gt;

&lt;script type="text/javascript" src="jquery.min.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="jquery-ui.min.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="script.js"&gt;&lt;/script&gt;</pre>
<p>After this we can move on to coding the rest of the page.</p>
<h4>demo.php</h4>
<pre class="brush:html">&lt;div id="main"&gt;

	&lt;ul class="todoList"&gt;

	&lt;?php

		// Looping and outputting the $todos array. The __toString() method
		// is used internally to convert the objects to strings:

		foreach($todos as $item){
			echo $item;
		}

		?&gt;

	&lt;/ul&gt;

	&lt;a id="addButton" class="green-button" href=""&gt;Add a ToDo&lt;/a&gt;

&lt;/div&gt;

&lt;!-- This div is used as the base for the confirmation jQuery UI dialog box. Hidden by CSS. --&gt;
&lt;div id="dialog-confirm" title="Delete TODO Item?"&gt;Are you sure you want to delete this TODO item?&lt;/div&gt;</pre>
<p>Each todo is a <strong>li</strong> item inside of the <strong>todoList</strong> unordered list. This way, we can later use the sortable method of <strong>jQuery UI</strong> to easily convert it into an interactive sortable element. Also, in the process, we enhance the semantic value of the code.</p>
<h3>Step 4 &#8211; CSS</h3>
<p>Now lets move on to the styling of the todos. Only parts of the original stylesheet are given here for better readability. You can find the rest in <strong>styles.css</strong> in the download archive.</p>
<h4>styles.css &#8211; Part 1</h4>
<pre class="brush:css">/* The todo items are grouped into an UL unordered list */

ul.todoList{
	margin:0 auto;
	width:500px;
	position:relative;
}

ul.todoList li{
	background-color:#F9F9F9;
	border:1px solid #EEEEEE;
	list-style:none;
	margin:6px;
	padding:6px 9px;
	position:relative;
	cursor:n-resize;

	/* CSS3 text shadow and rounded corners: */

	text-shadow:1px 1px 0 white;

	-moz-border-radius:6px;
	-webkit-border-radius:6px;
	border-radius:6px;
}

ul.todoList li:hover{
	border-color:#9be0f9;

	/* CSS3 glow effect: */
	-moz-box-shadow:0 0 5px #A6E5FD;
	-webkit-box-shadow:0 0 5px #A6E5FD;
	box-shadow:0 0 5px #A6E5FD;
}
</pre>
<p>The <strong>todoList</strong> <strong>ul</strong> is horizontally centered on the page and is assigned a relative positioning. The <strong>li</strong> elements inside it (the todo items) share a number of CSS3 rules. These, unfortunately, do not work in older browsers, but as they are solely for presentation purposes even browsers as old as IE6 can enjoy a fully working script, albeit not as pretty as intentioned.</p>
<h4>styles.css &#8211; Part 2</h4>
<pre class="brush:css">/* The edit textbox */

.todo input{
	border:1px solid #CCCCCC;
	color:#666666;
	font-family:Arial,Helvetica,sans-serif;
	font-size:0.725em;
	padding:3px 4px;
	width:300px;
}

/* The Save and Cancel edit links: */

.editTodo{
	display:inline;
	font-size:0.6em;
	padding-left:9px;
}

.editTodo a{
	font-weight:bold;
}

a.discardChanges{
	color:#C00 !important;
}

a.saveChanges{
	color:#4DB209 !important;
}</pre>
<p>In the second part of the code we style the input text box, shown when the todo item is edited, and the save and cancel links.</p>
<div id="attachment_812" class="wp-caption alignnone" style="width: 630px"><a href="http://tutorialzine.com/wp-content/uploads/2010/03/i33.png"><img class="size-full wp-image-812" title="jQuery UI Dialog Box" src="http://tutorialzine.com/wp-content/uploads/2010/03/i33.png" alt="jQuery UI Dialog Box" width="620" height="260" /></a><p class="wp-caption-text">jQuery UI Dialog Box</p></div>
<h3>Step 5 &#8211; jQuery</h3>
<p>Moving to the JavaScript code. Here we are using two of jQuery UI&#8217;s user interface components &#8211; <strong>sortable</strong>, and <strong>dialog</strong>. These alone save us at least a couple of hours of development time, which is one of the benefits of using a nicely thought out library like jQuery.</p>
<h4>script.js &#8211; Part 1</h4>
<pre class="brush:js">$(document).ready(function(){
	/* The following code is executed once the DOM is loaded */

	$(".todoList").sortable({
		axis		: 'y',				// Only vertical movements allowed
		containment	: 'window',			// Constrained by the window
		update		: function(){		// The function is called after the todos are rearranged

			// The toArray method returns an array with the ids of the todos
			var arr = $(".todoList").sortable('toArray');

			// Striping the todo- prefix of the ids:

			arr = $.map(arr,function(val,key){
				return val.replace('todo-','');
			});

			// Saving with AJAX
			$.get('ajax.php',{action:'rearrange',positions:arr});
		}
	});

	// A global variable, holding a jQuery object
	// containing the current todo item:

	var currentTODO;

	// Configuring the delete confirmation dialog
	$("#dialog-confirm").dialog({
		resizable: false,
		height:130,
		modal: true,
		autoOpen:false,
		buttons: {
			'Delete item': function() {

				$.get("ajax.php",{"action":"delete","id":currentTODO.data('id')},function(msg){
					currentTODO.fadeOut('fast');
				})

				$(this).dialog('close');
			},
			Cancel: function() {
				$(this).dialog('close');
			}
		}
	});</pre>
<p>To display the dialog, we need to have a base div, which is going to be converted to a dialog. The contents of the div is going to be displayed as the text of the dialog, and the contents of the title attribute of the div will become the title of the dialog window. You can find this div (id=<strong>dialog-confirm</strong>) in <strong>demo.php</strong>.</p>
<h4>script.js &#8211; Part 2</h4>
<pre class="brush:js">	// When a double click occurs, just simulate a click on the edit button:
	$('.todo').live('dblclick',function(){
		$(this).find('a.edit').click();
	});

	// If any link in the todo is clicked, assign
	// the todo item to the currentTODO variable for later use.

	$('.todo a').live('click',function(e){

		currentTODO = $(this).closest('.todo');
		currentTODO.data('id',currentTODO.attr('id').replace('todo-',''));

		e.preventDefault();
	});

	// Listening for a click on a delete button:

	$('.todo a.delete').live('click',function(){
		$("#dialog-confirm").dialog('open');
	});

	// Listening for a click on a edit button

	$('.todo a.edit').live('click',function(){

		var container = currentTODO.find('.text');

		if(!currentTODO.data('origText'))
		{
			// Saving the current value of the ToDo so we can
			// restore it later if the user discards the changes:

			currentTODO.data('origText',container.text());
		}
		else
		{
			// This will block the edit button if the edit box is already open:
			return false;
		}

		$('&lt;input type="text"&gt;').val(container.text()).appendTo(container.empty());

		// Appending the save and cancel links:
		container.append(
			'&lt;div class="editTodo"&gt;'+
				'&lt;a class="saveChanges" href=""&gt;Save&lt;/a&gt; or &lt;a class="discardChanges" href=""&gt;Cancel&lt;/a&gt;'+
			'&lt;/div&gt;'
		);

	});</pre>
<p>Notice the use of the jQuery <strong>live()</strong> method to bind events. We are using <strong>live()</strong>, instead of <strong>bind()</strong>, because live() can listen for events on any elements, even those who do not yet exist. This way we make sure that all the todo items added in the future to the page by the user, will also trigger the same event handlers, as the currently existing ones.</p>
<h4>script.js &#8211; Part 3</h4>
<pre class="brush:js">	// The cancel edit link:

	$('.todo a.discardChanges').live('click',function(){
		currentTODO.find('.text')
					.text(currentTODO.data('origText'))
					.end()
					.removeData('origText');
	});

	// The save changes link:

	$('.todo a.saveChanges').live('click',function(){
		var text = currentTODO.find("input[type=text]").val();

		$.get("ajax.php",{'action':'edit','id':currentTODO.data('id'),'text':text});

		currentTODO.removeData('origText')
					.find(".text")
					.text(text);
	});

	// The Add New ToDo button:

	var timestamp;
	$('#addButton').click(function(e){

		// Only one todo per 5 seconds is allowed:
		if(Date.now() - timestamp&lt;5000) return false;

		$.get("ajax.php",{'action':'new','text':'New Todo Item. Doubleclick to Edit.'},function(msg){

			// Appending the new todo and fading it into view:
			$(msg).hide().appendTo('.todoList').fadeIn();
		});

		// Updating the timestamp:
		timestamp = Date.now();

		e.preventDefault();
	});

}); // Closing $(document).ready()</pre>
<p>In the last part of the code we are binding events to the <strong>Save</strong> and <strong>Cancel</strong> links, which are added to the todo when editing it. We also set up an event listener for the <strong>&#8220;Add&#8221;</strong> button. Notice how we prevent flooding by limiting the submit rate of new todos to one every 5 seconds.</p>
<p><strong>With this our AJAX-ed To Do List is complete!</strong></p>
<h3>Conclusion</h3>
<p>Today we created a simple AJAX enabled ToDo web script with PHP, MySQL and jQuery. You can use it to create your own task management application or turn it into a fully fledged web app.</p>
<p><strong>What do you think? How would you modify this code?</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/03/ajax-todo-list-jquery-php-mysql-css/feed/</wfw:commentRss>
		<slash:comments>36</slash:comments>
		</item>
		<item>
		<title>Sponsor Flip Wall With jQuery &amp; CSS</title>
		<link>http://tutorialzine.com/2010/03/sponsor-wall-flip-jquery-css/</link>
		<comments>http://tutorialzine.com/2010/03/sponsor-wall-flip-jquery-css/#comments</comments>
		<pubDate>Wed, 24 Mar 2010 19:40:29 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=797</guid>
		<description><![CDATA[We are using PHP, CSS and jQuery with the jQuery Flip plug-in, to create a flipping sponsors page. The resulting code can be used to showcase your clients or portfolio projects with a neat flipping animation.]]></description>
			<content:encoded><![CDATA[<p>Designing and coding a sponsors page is part of the developer&#8217;s life (at least the lucky developer&#8217;s life, if it is about a personal site of theirs). It, however, follows different rules than those for the other pages of the site. You have to find a way to fit a lot of information and organize it clearly, so that the emphasis is put on your sponsors, and not on other elements of your design.</p>
<p>We are using PHP, CSS and jQuery with the <a href="http://lab.smashup.it/flip/" target="_blank">jQuery Flip plug-in</a>, to do just that. The resulting code can be used to showcase your sponsors, clients or portfolio projects as well.</p>
<h3>Step 1 &#8211; XHTML</h3>
<p>Most of the markup is generated by PHP for each of the sponsors after looping the main <strong>$sponsor</strong> array. Below you can see the code that would be generated and outputted for Google:</p>
<h4>demo.php</h4>
<pre class="brush:html">&lt;div title="Click to flip" class="sponsor"&gt;
	&lt;div class="sponsorFlip"&gt;
		&lt;img alt="More about google" src="img/sponsors/google.png"&gt;
	&lt;/div&gt;

	&lt;div class="sponsorData"&gt;
		&lt;div class="sponsorDescription"&gt;
			The company that redefined web search.
		&lt;/div&gt;
		&lt;div class="sponsorURL"&gt;
			&lt;a href="http://www.google.com/"&gt;http://www.google.com/ &lt;/a&gt;
		&lt;/div&gt;
	&lt;/div&gt;
&lt;/div&gt;</pre>
<p>The outermost <strong>.sponsor</strong> div contains two additional div elements. The first &#8211; <strong>sponsorFlip</strong> &#8211; contains the company logo. Every click on this element causes the Flip effect to be initiated, as you will see in the jQuery part of the tutorial.</p>
<p>Maybe more interesting is the <strong>sponsorData</strong> div. It is hidden from view with a <strong>display:none</strong> CSS rule, but is accessible to jQuery. This way we can pass the description and the URL of the sponsoring company to the front end. After the flipping animation is complete, the contents of this div is dynamically inserted into <strong>sponsorFlip</strong>.</p>
<div id="attachment_802" class="wp-caption alignnone" style="width: 630px"><a href="http://tutorialzine.com/wp-content/uploads/2010/03/i12.png"><img class="size-full wp-image-802" title="Sponsor Flip Wall" src="http://tutorialzine.com/wp-content/uploads/2010/03/i12.png" alt="Sponsor Flip Wall" width="620" height="460" /></a><p class="wp-caption-text">Sponsor Flip Wall</p></div>
<h3>Step 2 &#8211; CSS</h3>
<p>We can start laying down the styling of the wall, as without it there is no much use of the page. The code is divided in two parts. Some classes are omitted for clarity. You can see all the styles used by the demo in <strong>styles.css</strong> in the download archive.</p>
<h4>styles.css &#8211; Part 1</h4>
<pre class="brush:css">body{
	/* Setting default text color, background and a font stack */
	font-size:0.825em;
	color:#666;
	background-color:#fff;
	font-family:Arial, Helvetica, sans-serif;
}

.sponsorListHolder{
	margin-bottom:30px;
}

.sponsor{
	width:180px;
	height:180px;
	float:left;
	margin:4px;

	/* Giving the sponsor div a relative positioning: */
	position:relative;
	cursor:pointer;
}

.sponsorFlip{
	/*  The sponsor div will be positioned absolutely with respect
		to its parent .sponsor div and fill it in entirely */

	position:absolute;
	left:0;
	top:0;
	width:100%;
	height:100%;
	border:1px solid #ddd;
	background:url("img/background.jpg") no-repeat center center #f9f9f9;
}

.sponsorFlip:hover{
	border:1px solid #999;

	/* CSS3 inset shadow: */
	-moz-box-shadow:0 0 30px #999 inset;
	-webkit-box-shadow:0 0 30px #999 inset;
	box-shadow:0 0 30px #999 inset;
}</pre>
<p>After styling the <strong>sponsor</strong> and <strong>sponsorFlip</strong> divs, we add a <strong>:hover</strong> state for the latter. We are using CSS3 inset <strong>box-shadow</strong> to mimic the inner shadow effect you may be familiar with from Photoshop. At the moment of writing inset shadows only work in the latest versions of Firefox, Opera and Chrome, but being primarily a visual enhancement, without it the page is still perfectly usable in all browsers.</p>
<h4>styles.css &#8211; Part 2</h4>
<pre class="brush:css">.sponsorFlip img{
	/* Centering the logo image in the middle of the .sponsorFlip div */

	position:absolute;
	top:50%;
	left:50%;
	margin:-70px 0 0 -70px;
}

.sponsorData{
	/* Hiding the .sponsorData div */
	display:none;
}

.sponsorDescription{
	font-size:11px;
	padding:50px 10px 20px 20px;
	font-style:italic;
}

.sponsorURL{
	font-size:10px;
	font-weight:bold;
	padding-left:20px;
}

.clear{
	/* This class clears the floats */
	clear:both;
}</pre>
<p>As mentioned earlier, the <strong>sponsorData</strong> div is not meant for viewing, so it is hidden with <strong>display:none</strong>. Its purpose is to only store the data which is later extracted by jQuery and displayed at the end of the flipping animation.</p>
<div id="attachment_803" class="wp-caption alignnone" style="width: 630px"><a href="http://tutorialzine.com/wp-content/uploads/2010/03/i22.png"><img class="size-full wp-image-803" title="Flipping Animation" src="http://tutorialzine.com/wp-content/uploads/2010/03/i22.png" alt="Flipping Animation" width="620" height="260" /></a><p class="wp-caption-text">Flipping Animation</p></div>
<h3>Step 3 &#8211; PHP</h3>
<p>You have many options in storing your sponsors data &#8211; in a MySQL database, XML document or even a plain text file. These all have their benefits and we&#8217;ve used all of them in the previous tutorials (except XML storage, note to self).</p>
<p>However, the sponsor data is not something that changes often. This is why a different approach is needed. For the purposes of the task at hand, we are using a multidimensional array with all the sponsor information inside it. It is easy to update and even easier to implement:</p>
<h4>demo.php &#8211; Part 1</h4>
<pre class="brush:php">// Each sponsor is an element of the $sponsors array:

$sponsors = array(
	array('facebook','The biggest social..','http://www.facebook.com/'),
	array('adobe','The leading software de..','http://www.adobe.com/'),
	array('microsoft','One of the top software c..','http://www.microsoft.com/'),
	array('sony','A global multibillion electronics..','http://www.sony.com/'),
	array('dell','One of the biggest computer develo..','http://www.dell.com/'),
	array('ebay','The biggest online auction and..','http://www.ebay.com/'),
	array('digg','One of the most popular web 2.0..','http://www.digg.com/'),
	array('google','The company that redefined w..','http://www.google.com/'),
	array('ea','The biggest computer game manufacturer.','http://www.ea.com/'),
	array('mysql','The most popular open source dat..','http://www.mysql.com/'),
	array('hp','One of the biggest computer manufacturers.','http://www.hp.com/'),
	array('yahoo','The most popular network of so..','http://www.yahoo.com/'),
	array('cisco','The biggest networking and co..','http://www.cisco.com/'),
	array('vimeo','A popular video-centric social n..','http://www.vimeo.com/'),
	array('canon','Imaging and optical technology ma..','http://www.canon.com/')
);

// Randomizing the order of sponsors:

shuffle($sponsors);</pre>
<p>The sponsors are grouped into the main <strong>$sponsors</strong> array. Each sponsor entry is organized as a separate regular array. The first element of that array is the unique key of the sponsor, which corresponds to the file name of the logo. The second element is a description of the sponsor and the last is a link to the sponsor&#8217;s website.</p>
<p>After defining the array, we use the in-build <strong>shuffle()</strong> PHP function to randomize the order in which the sponsors are displayed.</p>
<h4>demo.php &#8211; Part 2</h4>
<pre class="brush:php">// Looping through the array:

foreach($sponsors as $company)
{
	echo'
		&lt;div class="sponsor" title="Click to flip"&gt;
			&lt;div class="sponsorFlip"&gt;
				&lt;img src="img/sponsors/'.$company[0].'.png" alt="More about '.$company[0].'" /&gt;
			&lt;/div&gt;

			&lt;div class="sponsorData"&gt;
				&lt;div class="sponsorDescription"&gt;
					'.$company[1].'
				&lt;/div&gt;
				&lt;div class="sponsorURL"&gt;
					&lt;a href="'.$company[2].'"&gt;'.$company[2].'&lt;/a&gt;
				&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;

	';
}</pre>
<p>The code above can be found halfway down <strong>demo.php</strong>. It basically loops through the shuffled <strong>$sponsors</strong> array and outputs the markup we discussed in step one. Notice how the different elements of the array are inserted into the template.</p>
<h3>Step 4 &#8211; jQuery</h3>
<p>The jQuery Flip plugin requires both the <strong>jQuery</strong> library and<strong> jQuery UI</strong>. So, after including those in the page, we can move on with writing the code that will bring our sponsor wall to life.</p>
<h4>script.js</h4>
<pre class="brush:js">$(document).ready(function(){
	/* The following code is executed once the DOM is loaded */

	$('.sponsorFlip').bind("click",function(){

		// $(this) point to the clicked .sponsorFlip element (caching it in elem for speed):

		var elem = $(this);

		// data('flipped') is a flag we set when we flip the element:

		if(elem.data('flipped'))
		{
			// If the element has already been flipped, use the revertFlip method
			// defined by the plug-in to revert to the default state automatically:

			elem.revertFlip();

			// Unsetting the flag:
			elem.data('flipped',false)
		}
		else
		{
			// Using the flip method defined by the plugin:

			elem.flip({
				direction:'lr',
				speed: 350,
				onBefore: function(){
					// Insert the contents of the .sponsorData div (hidden
					// from view with display:none) into the clicked
					// .sponsorFlip div before the flipping animation starts:

					elem.html(elem.siblings('.sponsorData').html());
				}
			});

			// Setting the flag:
			elem.data('flipped',true);
		}
	});

});</pre>
<p>First we bind a function as a listener for the click event on the .<strong>sponsorFlip</strong> divs.  After a click event occurs, we check whether the <strong>flipped</strong> flag is set via the jquery <strong>data()</strong> method. This flag is set individually for each <strong>sponsorFlip </strong>div and helps us determine whether the div has already been flipped. If this is so, we use the <strong>revertFlip()</strong> method which is defined by the Flip plugin. It returns the div to its previous state.</p>
<p>If the flag is not present, however, we initiate a flip on the element. As mentioned earlier, the <strong>.sponsorData</strong> div, which is contained in every sponsor div, contains the description and the URL of the sponsor, and is hidden from view with CSS. Before the flipping starts, the plug-in executes the <strong>onBefore </strong>function we define in the configuration object that is passed as a parameter (line 29). In it we change the content of the <strong>sponsorFlip </strong>div to the one of <strong>sponsorData </strong>div, which replaces the logo image with information about the sponsor.</p>
<p><strong>With this our sponsor flip wall is complete!</strong></p>
<h3>Conclusion</h3>
<p>Today we used the jQuery Flip plug-in to build a sponsor wall for your site. You can use this example to bring interactivity to your site&#8217;s pages. And as the data for the wall is read from an array, you can easily modify it to work with any kind of database or storage.</p>
<p><strong>What do you think? How would you modify this code?</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/03/sponsor-wall-flip-jquery-css/feed/</wfw:commentRss>
		<slash:comments>73</slash:comments>
		</item>
		<item>
		<title>&#8220;Who Is Online&#8221; Widget With PHP, MySQL &amp; jQuery</title>
		<link>http://tutorialzine.com/2010/03/who-is-online-widget-php-mysql-jquery/</link>
		<comments>http://tutorialzine.com/2010/03/who-is-online-widget-php-mysql-jquery/#comments</comments>
		<pubDate>Tue, 02 Mar 2010 22:37:22 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=744</guid>
		<description><![CDATA[We are making a "Who is online" widget with PHP, MySQL &#038; jQuery. It will display the number of visitors, currently viewing your site, and a list of countries they are from in a slide out panel.]]></description>
			<content:encoded><![CDATA[<p>For this week&#8217;s tutorial, we are taking a look at our ever-so-interesting inbox. It all started with a letter from one of our readers a couple of weeks ago:</p>
<blockquote><p>My boss is always coming into my office asking me to install things on our client&#8217;s sites. One of the items that&#8217;s been coming up more and more is &#8220;How can we tell who&#8217;s currently online?&#8221;  So, the next time you need a tutorial idea, there you go &#8211; a php/mysql/jquery &#8216;online users&#8217; widget. Oh, and a geomap of each visitor would be super rad too.</p>
<p>Thanks for everything you guys do,<br />
Taylor</p></blockquote>
<p>Taylor, we are always happy when we receive good tutorial ideas, so today we are doing just that &#8211; a &#8220;<strong>Who is online</strong>&#8221; widget with PHP, MySQL &amp; jQuery. It will display the number of visitors, currently viewing your site, and thanks to <a href="http://www.hostip.info/" target="_blank">Hostip&#8217;s free IP to location API</a>, it will even be able to detect the country your visitors are from and display it in a slide out panel.</p>
<h3>Step 1 &#8211; XHTML</h3>
<p>As usual, we start off with the XHTML part. The code presented here might not look like much, but it is all that we need to show off all the work that has been done by the backend. The widget features a slick slide-out panel with all the geolocation data, shown on mouse over.</p>
<h4>demo.html</h4>
<pre class="brush:html">&lt;div class="onlineWidget"&gt;

&lt;div class="panel"&gt;

	&lt;!-- Fetched with AJAX: --&gt;

	&lt;div class="geoRow"&gt;
	&lt;div class="flag"&gt;&lt;img src="who-is-online/img/famfamfam-countryflags/us.gif" width="16" height="11"&gt;&lt;/div&gt;
	&lt;div class="country" title="UNITED STATES"&gt;UNITED STATES&lt;/div&gt;
	&lt;div class="people"&gt;2&lt;/div&gt;
	&lt;/div&gt;

	&lt;div class="geoRow"&gt;
	&lt;div class="flag"&gt;&lt;img src="who-is-online/img/famfamfam-countryflags/uk.gif" width="16" height="11"&gt;&lt;/div&gt;
	&lt;div class="country" title="UNITED KINGDOM"&gt;UNITED KINGDOM&lt;/div&gt;
	&lt;div class="people"&gt;1&lt;/div&gt;
	&lt;/div&gt;

&lt;/div&gt;

&lt;div class="count"&gt;8&lt;/div&gt;
&lt;div class="label"&gt;online&lt;/div&gt;
&lt;div class="arrow"&gt;&lt;/div&gt;
&lt;/div&gt;</pre>
<p>As you may see from the markup above, the main container div &#8211; &#8220;<strong>onlineWidget</strong>&#8221; contains the slide-out panel (the div with class name &#8220;<strong>panel</strong>&#8220;), the total number of people online (the &#8220;<strong>count</strong>&#8221; div), the &#8220;<strong>online</strong>&#8221; label and the green arrow to the right.</p>
<div id="attachment_750" class="wp-caption alignnone" style="width: 630px"><a href="http://tutorialzine.com/wp-content/uploads/2010/03/i1.png"><img class="size-full wp-image-750" title="Geolocation-enabled Who Is Online Widget" src="http://tutorialzine.com/wp-content/uploads/2010/03/i1.png" alt="Geolocation-enabled Who Is Online Widget" width="620" height="460" /></a><p class="wp-caption-text">Geolocation-enabled Who Is Online Widget</p></div>
<p>The panel div is dynamically filled by AJAX with the countries with the most visitors currently online. The default content of this div is a rotating gif preloader, which is replaced with the geo data once the AJAX request is complete (usually in less than a second). We will come back to this in a moment.</p>
<h3>Step 2 &#8211; The Database</h3>
<p>Unlike the usual routine, here we are going to take a look at how the database is structured, as it is fundamental to the rest of the script.</p>
<p>All of the widget data is stored into the <strong>tz_who_is_online</strong> table. It consists of six fields (or columns). The first one &#8211; ID, is a standard primary key / auto increment field. After this is the IP field which stores the visitor&#8217;s IP address (converted to a integer beforehand with the <strong>ip2long</strong> PHP function).</p>
<p>After this are three fields fetched by Hostip&#8217;s API -<strong> Country, CountryCode</strong> and <strong>City</strong>. The widget is not using the city field at this point, but it is good to have in case somebody wants to implement it. Last is the <strong>DT</strong> timestamp field, which is updated on every page load and enables us to track who is online (users without a page load in the last 10 minutes have probably left the site).</p>
<div id="attachment_749" class="wp-caption alignnone" style="width: 630px"><a href="http://tutorialzine.com/wp-content/uploads/2010/03/i3.png"><img class="size-full wp-image-749" title="Table Structure Of tz_who_is_online" src="http://tutorialzine.com/wp-content/uploads/2010/03/i3.png" alt="Table Structure Of tz_who_is_online" width="620" height="260" /></a><p class="wp-caption-text">Table Structure Of tz_who_is_online</p></div>
<h3>Step 3 &#8211; CSS</h3>
<p>The widget is (almost) image free, and is only styled with CSS. Lets take a look at the styling, as defined in <strong>styles.css</strong>. The code is divided in two parts, so it is easier to follow.</p>
<h4>who-is-online/styles.css &#8211; Part 1</h4>
<pre class="brush:css">.onlineWidget,.panel{

	/* Styling the widget and the sliding panel at once */

	background-color:#F9F9F9;
	border:2px solid #FFFFFF;
	height:25px;
	padding:4px 8px;
	position:relative;
	width:130px;

	cursor:pointer;

	/* CSS3 rules for rounded corners, box and text shadows: */

	-moz-border-radius:6px;
	-webkit-border-radius:6px;
	border-radius:6px;

	-moz-box-shadow:0 0 3px #CCCCCC;
	-webkit-box-shadow:0 0 3px #CCCCCC;
	box-shadow:0 0 3px #CCCCCC;

	text-shadow:0 2px 0 white;
}

.onlineWidget:hover{
	background-color:#fcfcfc;
}

.onlineWidget:hover .arrow{
	/* Changing the background image for the green arrow on hover: */
	background-position:bottom center;
}

.count{
	/* The total number of people online div */

	color:#777777;
	float:left;
	font-size:26px;
	font-weight:bold;
	margin-top:-3px;
	text-align:center;
	width:30px;
}

.label{
	/* The online label */

	float:left;
	font-size:10px;
	padding:7px 0 0 7px;
	text-transform:uppercase;
}</pre>
<p>In the first step above, you can see that we style the <strong>widget</strong> and the <strong>slide-out panel</strong> at once. This is to ensure that they have consistent styling which is easy to change later on. Some rules are unique to the panel, however, so we include a individually targeted set of rules in the second part of the code.</p>
<p>We also define the hover state and style the <strong>label</strong> and <strong>count</strong> divs.</p>
<h4>who-is-online/styles.css &#8211; Part 2</h4>
<pre class="brush:css">.arrow{
	/* The green arrow on the right */

	background:url(img/arrow.png) no-repeat top center;
	position:absolute;
	right:6px;

	width:25px;
	height:25px;
}

.panel{
	/* The slideout panel */

	position:absolute;
	cursor:default;

	bottom:50px;
	left:0;
	height:auto;
	display:none;
	margin:-2px;
	z-index:1000;
}

.preloader{
	/* The rotating gif preloader image */
	display:block;
	margin:10px auto;
}

.geoRow{
	/* The div that contains each country */

	height:16px;
	overflow:hidden;
	padding:2px 0;
}

.flag{
	float:left;
	margin:0 4px;
}

.country, .people{
	float:left;
	font-size:10px;
	padding:2px;
}

.country{
	width:85px;
	overflow:hidden;
}

.people{
	font-weight:bold;
}</pre>
<p>In the second part of the file, we style the how the geolocation data that is presented in the slide-out panel, after jQuery fetches it from the back-end. With this we can continue with the next step.</p>
<div id="attachment_751" class="wp-caption alignnone" style="width: 630px"><a href="http://tutorialzine.com/wp-content/uploads/2010/03/i2.png"><img class="size-full wp-image-751" title="CSS3 &amp; jQuery Front End" src="http://tutorialzine.com/wp-content/uploads/2010/03/i2.png" alt="CSS3 &amp; jQuery Front End" width="620" height="260" /></a><p class="wp-caption-text">CSS3 &amp; jQuery Front End</p></div>
<h3>Step 4 &#8211; PHP</h3>
<p>This is where the magic happens. PHP has to keep the database of online users up to date and fetch IP-to-location data from <strong>Hostip&#8217;s API</strong>. This is later cached for future use in a cookie on the visitors PC.</p>
<h4>who-is-online/online.php</h4>
<pre class="brush:php">require "connect.php";
require "functions.php";

// We don't want web bots altering our stats:
if(is_bot()) die();

$stringIp = $_SERVER['REMOTE_ADDR'];
$intIp = ip2long($stringIp);

// Checking wheter the visitor is already marked as being online:
$inDB = mysql_query("SELECT 1 FROM tz_who_is_online WHERE ip=".$intIp);

if(!mysql_num_rows($inDB))
{
	// This user is not in the database, so we must fetch
	// the geoip data and insert it into the online table:

	if($_COOKIE['geoData'])
	{
		// A "geoData" cookie has been previously set by the script, so we will use it

		// Always escape any user input, including cookies:
		list($city,$countryName,$countryAbbrev) = explode('|',mysql_real_escape_string(strip_tags($_COOKIE['geoData'])));
	}
	else
	{
		// Making an API call to Hostip:

		$xml = file_get_contents('http://api.hostip.info/?ip='.$stringIp);

		$city = get_tag('gml:name',$xml);
		$city = $city[1];

		$countryName = get_tag('countryName',$xml);
		$countryName = $countryName[0];

		$countryAbbrev = get_tag('countryAbbrev',$xml);
		$countryAbbrev = $countryAbbrev[0];

		// Setting a cookie with the data, which is set to expire in a month:
		setcookie('geoData',$city.'|'.$countryName.'|'.$countryAbbrev, time()+60*60*24*30,'/');
	}

	$countryName = str_replace('(Unknown Country?)','UNKNOWN',$countryName);

	mysql_query("	INSERT INTO tz_who_is_online (ip,city,country,countrycode)
					VALUES(".$intIp.",'".$city."','".$countryName."', '".$countryAbbrev."')");
}
else
{
	// If the visitor is already online, just update the dt value of the row:
	mysql_query("UPDATE tz_who_is_online SET dt=NOW() WHERE ip=".$intIp);
}

// Removing entries not updated in the last 10 minutes:
mysql_query("DELETE FROM tz_who_is_online WHERE dt&lt;SUBTIME(NOW(),'0 0:10:0')");

// Counting all the online visitors:
list($totalOnline) = mysql_fetch_array(mysql_query("SELECT COUNT(*) FROM tz_who_is_online"));

// Outputting the number as plain text:
echo $totalOnline;</pre>
<p>This PHP script is initially called by jQuery in order to populate the count div with the current number of people online. Behind the scenes, however, this script writes the visitor&#8217;s IP to the database and resolves their IP-to-location data.</p>
<p>This is the best strategy in organizing the back-end, as we keep the calls to the API (which are quite time expensive) distributed to each user as they visit the site for the first time.</p>
<p>The other alternative would be to store only the IPs of the visitors and queue the geolocation data once the panel is shown. This would mean to resolve a huge number of IPs simultaneously, which would make the script unresponsive and get us black-listed from the API. Totally not cool.</p>
<p>You can queue the Hostip&#8217;s API by opening a connection to a URL similar to this: <strong>http://api.hostip.info/?ip=128.128.128.128</strong>. It returns a valid XML response, which contains all sorts of data, including a <strong>country </strong>and <strong>city </strong>name associated with the IP, country <strong>abbreviation </strong>and even <strong>absolute coordinates</strong>. We are fetching this data with the PHP <strong>file_get_contents()</strong> function and extracting the bits of information we need.</p>
<h4>who-is-online/geodata.php</h4>
<pre class="brush:php">require "connect.php";
require "functions.php";

// We don't want web bots accessing this page:
if(is_bot()) die();

// Selecting the top 15 countries with the most visitors:
$result = mysql_query("	SELECT countryCode,country, COUNT(*) AS total
						FROM tz_who_is_online
						GROUP BY countryCode
						ORDER BY total DESC
						LIMIT 15");

while($row=mysql_fetch_assoc($result))
{
	echo '
	&lt;div class="geoRow"&gt;
		&lt;div class="flag"&gt;&lt;img src="who-is-online/img/famfamfam-countryflags/'.strtolower($row['countryCode']).'.gif" width="16" height="11" /&gt;&lt;/div&gt;
		&lt;div class="country" title="'.htmlspecialchars($row['country']).'"&gt;'.$row['country'].'&lt;/div&gt;
		&lt;div class="people"&gt;'.$row['total'].'&lt;/div&gt;
	&lt;/div&gt;
	';
}</pre>
<p><strong>Geodata.php</strong> is fetched by jQuery to populate the slide-out panel with location data. This file basically queues the database with a <strong>GROUP BY</strong> query, which groups the individual users by country and orders the resulting rows in a descending order, with the most popular countries at the top.</p>
<p>For the flag icons, we are using the <a href="http://www.famfamfam.com/lab/icons/flags/" target="_blank">famfamfam flag icon set</a>, which is released as public domain. A great thing about the Hostip API, is that it returns the country code in a standard two letter format, which is also shared by the famfamfam icon set. This means that in the while loop, it is really easy to find the appropriate flag to show, by just lowering the case of the country abbreviation stored in the database and adding a <strong>gif</strong> extension.</p>
<h3>Step 5 &#8211; jQuery</h3>
<p>JavaScript manages the AJAX requests and slides the panel. This would be a daunting task with pure JS alone, which is why we are using the newest version of the jQuery library.</p>
<p>Now lets take a look at what the code looks like.</p>
<h4>who-is-online/widget.js</h4>
<pre class="brush:js">$(document).ready(function(){
	// This function is executed once the document is loaded

	// Caching the jQuery selectors:
	var count = $('.onlineWidget .count');
	var panel = $('.onlineWidget .panel');
	var timeout;

	// Loading the number of users online into the count div with the load AJAX method:
	count.load('who-is-online/online.php');

	$('.onlineWidget').hover(
		function(){
			// Setting a custom 'open' event on the sliding panel:

			clearTimeout(timeout);
			timeout = setTimeout(function(){panel.trigger('open');},500);
		},
		function(){
			// Custom 'close' event:

			clearTimeout(timeout);
			timeout = setTimeout(function(){panel.trigger('close');},500);
		}
	);

	var loaded=false;	// A flag which prevents multiple AJAX calls to geodata.php;

	// Binding functions to custom events:

	panel.bind('open',function(){
		panel.slideDown(function(){
			if(!loaded)
			{
				// Loading the countries and the flags
				// once the sliding panel is shown:

				panel.load('who-is-online/geodata.php');
				loaded=true;
			}
		});
	}).bind('close',function(){
		panel.slideUp();
	});

});</pre>
<p>You might be a bit perplexed with the use of <strong>setTimeout </strong>in the menu. This is done, so we have a bit of delay between the hovering of the mouse and the actual opening of the slide-out panel. This way, unintentional movements of the mouse cursor over the widget won&#8217;t fire the open event, and once opened, will not <strong>close</strong> it immediately once the mouse leaves it.</p>
<p><strong>With this our widget is ready!</strong></p>
<h3>Setting up the demo</h3>
<p>At this point you probably want to grab the widget and put it on your site. To make it work, you need to execute the SQL code found in <strong>table.sql</strong> in the download archive. It will create the <strong>tz_who_is_online</strong> table in your database, which is used by the widget. Later you need to upload the files to your server and include <strong>widget.js</strong> to the head section of your page (along with the jQuery  library). After this you have to fill your MySQL login details in <strong>connect.php</strong> and finally add the markup from <strong>demo.html</strong> to your web page.</p>
<h3>Conclusion</h3>
<p>Having access to real time data on your site userbase is a dream to any webmaster. Tools like Google Analytics give a great perspective on your site&#8217;s reach, but lack the real time feel a simple widget like this can provide.</p>
<p><strong>What do you think? How would you modify this code?</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/03/who-is-online-widget-php-mysql-jquery/feed/</wfw:commentRss>
		<slash:comments>60</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk
Page Caching using disk (enhanced) (user agent is rejected)

Served from: tutorialzine.com @ 2010-08-01 03:00:22 -->