<?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; CSS</title>
	<atom:link href="http://tutorialzine.com/category/tutorials/css-tutorials/feed/" rel="self" type="application/rss+xml" />
	<link>http://tutorialzine.com</link>
	<description>Web Development Tutorials &#38; Resources</description>
	<lastBuildDate>Thu, 02 Sep 2010 19:31:09 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Creating an Animated 404 Page</title>
		<link>http://tutorialzine.com/2010/08/animated-404-not-found-page-css-jquery/</link>
		<comments>http://tutorialzine.com/2010/08/animated-404-not-found-page-css-jquery/#comments</comments>
		<pubDate>Thu, 26 Aug 2010 15:31:29 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=1095</guid>
		<description><![CDATA[This time we are going to create an animated 404 page, which will make the experience of running into the notorious 404 error a lot less frustrating. You can also easily modify and improve it.]]></description>
			<content:encoded><![CDATA[<p>It is bound to happen. Sooner or later, somebody is going to type in a wrong URL or follow a broken link to your site. This is when the notorious 404 page is displayed. To make the experience less frustrating, you can take the time and design a friendly error page, which will encourage your user to stay at your web site.</p>
<p>Today we are making just that. We are going to create an animated 404 page, which you can easily customize and improve.</p>
<h3>The HTML</h3>
<p>As usual, we start off with the HTML markup. Here we are using the new HTML5 doctype and the new <strong>hgroup</strong> tag. In the head section, we are including the HTML5 enabling script for IE inside a conditional comment. This script will help Internet Explorer understand the new HTML5 tags.</p>
<h4>404.html</h4>
<pre class="brush:html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;
&lt;title&gt;Creating an Animated 404 Page | Tutorialzine Demo&lt;/title&gt;

&lt;!-- Internet Explorer HTML5 enabling script: --&gt;

&lt;!--[if IE]&gt;
    &lt;script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"&gt;&lt;/script&gt;
&lt;![endif]--&gt;

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

&lt;/head&gt;

&lt;body&gt;

&lt;div id="rocket"&gt;&lt;/div&gt;

&lt;hgroup&gt;
    &lt;h1&gt;Page Not Found&lt;/h1&gt;
    &lt;h2&gt;We couldn't find what you were looking for.&lt;/h2&gt;
&lt;/hgroup&gt;

&lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"&gt;&lt;/script&gt;
&lt;script src="script.js"&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>After the HTML5 enabling script, we include the stylesheet, an excerpt of which is given in the next section. Inside the body tag, you can see the <strong>#rocket</strong> div and the aforementioned <strong>hgroup</strong>. The <strong>#rocket</strong> div has <em>rocket.png</em> as its background, and it has a number of styles applied, including relative positioning, which is needed for the animation, as you will see in a moment.</p>
<p>Lastly we have the jQuery library and our <strong>script.js</strong> file, also discussed in the next sections.</p>
<p>The page is minimalistic and presents only basic information to the user. You could improve it by including a more site-specific message and a link to your homepage (or other resources you find suitable).</p>
<div id="attachment_1099" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/08/animated-404-not-found-page-css-jquery/404.html"><img class="size-full wp-image-1099" title="The Not Found Rocket" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/08/i1.png" alt="The Not Found Rocket" width="620" height="460" /></a><p class="wp-caption-text">The Not Found Rocket</p></div>
<h3>The CSS</h3>
<p>Now lets move on to the styling. As mentioned in the HTML part of the tut, the <strong>#rocket</strong> div&#8217;s positioning is set to relative. This allows us to insert the <a href="http://tutorialzine.com/2010/06/microtut-how-css-position-works/" target="_blank">absolutely positioned spans</a>, which form the exhaust gases coming out of the engine, and offset them with regards to the rocket.</p>
<pre class="brush:css">body{
	background:url('img/bg.png') no-repeat center center #1d1d1d;
	color:#eee;
	font-family:Corbel,Arial,Helvetica,sans-serif;
	font-size:13px;
}

#rocket{
	width:275px;
	height:375px;
	background:url('img/rocket.png') no-repeat;
	margin:140px auto 50px;
	position:relative;
}

/*	Two steam classes. */

.steam1,
.steam2{
	position:absolute;
	bottom:78px;
	left:50px;
	width:80px;
	height:80px;
	background:url('img/steam.png') no-repeat;
	opacity:0.8;
}

.steam2{

   /*	.steam2 shows the bottom part (dark version)
	*	of the background image.
	*/

	background-position:left bottom;
}

hgroup{

	/* Using the HTML4 hgroup element */

	display:block;
	margin:0 auto;
	width:850px;
	font-family:'Century Gothic',Calibri,'Myriad Pro',Arial,Helvetica,sans-serif;
	text-align:center;
}

h1{
	color:#76D7FB;
	font-size:60px;
	text-shadow:3px 3px 0 #3D606D;
	white-space:nowrap;
}

h2{
	color:#9FE3FC;
	font-size:18px;
	font-weight:normal;
	padding:25px 0;
}</pre>
<p>Each steam span is 80px wide by 80px high, and is assigned steam.png as its background. This image is twice the height of the spans, and actually contains two versions of the steam &#8211; white and black.The <strong>steam1</strong> and <strong>steam2</strong> classes show the respective version of the image. The light version of the steam creates the illusion of smoke, whereas  the black one makes the flames of the rocket engine flicker.</p>
<p>jQuery creates and inserts the steam spans into the <strong>#rocket</strong> container, and moves them in the opposite direction of the movement of the rocket with the <em>animate</em> method, as you will see in a few moments.</p>
<h3>The jQuery</h3>
<p>As we discussed above, jQuery&#8217;s part is to create the animation of the exhaust gases. Lets take a closer look at how this is achieved.</p>
<p>The script begins with attaching an event listener to the <em><strong>window load</strong></em> event. This differs from the <em><strong>document ready</strong></em> event we usually target, in  that <em>window.load</em> is fired when not only the DOM, but images as well are  loaded. This way we can be sure that the user is not going to see the  smoke of the rocket before <strong>rocket.png</strong> is loaded.</p>
<pre class="brush:js">$(window).load(function(){

	// We are listening for the window load event instead of the regular document ready.

	function animSteam(){

		// Create a new span with the steam1, or steam2 class:

		$('&lt;span&gt;',{
			className:'steam'+Math.floor(Math.random()*2 + 1),
			css:{
				// Apply a random offset from 10px to the left to 10px to the right
				marginLeft	: -10 + Math.floor(Math.random()*20)
			}
		}).appendTo('#rocket').animate({
			left:'-=58',
			bottom:'-=100'
		}, 120,function(){

			// When the animation completes, remove the span and
			// set the function to be run again in 10 milliseconds

			$(this).remove();
			setTimeout(animSteam,10);
		});
	}

	function moveRocket(){
		$('#rocket').animate({'left':'+=100'},5000).delay(1000)
					.animate({'left':'-=100'},5000,function(){
				setTimeout(moveRocket,1000);
		});
	}

	// Run the functions when the document and all images have been loaded.

	moveRocket();
	animSteam();
});</pre>
<p>The <strong>animSteam()</strong> function is what creates the smoke effect. When called, the function runs an animation, which, when complete, uses <strong>setTimeout</strong> to schedule the same function to be run again in 10 milliseconds. This prevents build ups &#8211; starting a second animation before the first has completed.</p>
<p>The script chooses randomly between the <strong>steam1</strong> and <strong>steam2</strong> classes on line 10 and offsets the span horizontally with a random value of  <strong>margin-left</strong>. In the <strong>animate()</strong> method, later in the chain, we tell jQuery to start an animation from the current position of the steam div (which is exactly over the nozzle of the rocket) and move the element 58 pixels to the left and 100 pixels to the bottom.</p>
<div id="attachment_1098" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/08/animated-404-not-found-page-css-jquery/404.html"><img class="size-full wp-image-1098" title="How the Animation is Created" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/08/i2.png" alt="How the Animation is Created" width="620" height="260" /></a><p class="wp-caption-text">How the Animation is Created</p></div>
<p>After this we pass the duration of the animation &#8211; 120 milliseconds, and a callback function, which will be executed after the animation completes.</p>
<p>The other animation function &#8211; <strong>moveRocket()</strong> slowly moves the rocket to the left and right by modifying the left CSS property. Both functions are called once at the end of the file. If you want to disable one of the animations, just comment out the respective function call.</p>
<p><strong>With this our Animated 404 Page is complete!</strong></p>
<h3>Conclusion</h3>
<p>Remember, that to make the page show up when a 404 error actually occurs, you need to add this line to your <strong>.htaccess</strong> file:</p>
<pre class="brush:plain">ErrorDocument 404 /404.html</pre>
<p>This will output the page with the appropriate headers, given that you&#8217;ve placed it in your root folder. You can also add more helpful information to the page, such as links to your home page, a more personalized message or even a way for users to report the errors they&#8217;ve encountered.</p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/08/animated-404-not-found-page-css-jquery/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Feature Suggest App w/ PHP, MySQL &amp; jQuery</title>
		<link>http://tutorialzine.com/2010/08/ajax-suggest-vote-jquery-php-mysql/</link>
		<comments>http://tutorialzine.com/2010/08/ajax-suggest-vote-jquery-php-mysql/#comments</comments>
		<pubDate>Thu, 19 Aug 2010 16:42:27 +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=1072</guid>
		<description><![CDATA[In this tutorial we are making a feature suggestion app with PHP, MySQL &#038; jQuery. With it your website visitors can request features, vote and give feedback for your site.]]></description>
			<content:encoded><![CDATA[<p>Listening to what your visitors have to say, is always beneficial when planning new features or changes in your website. For a long time we&#8217;ve been limited to just setting up a contact form and hoping that quality feedback will follow, which unfortunately is not always the case.</p>
<p>Today we are taking things up a notch &#8211; we are applying the same social principles that have brought success to sharing sites such as Digg and delicious, and encourage visitors to suggest and vote on features that they want implemented on your website.</p>
<h3>The XHTML</h3>
<p>Starting with the new HTML5 doctype, we define the opening and closing head  and title tags, and include the main stylesheet of the app &#8211;  <strong>styles.css</strong>, in the document.</p>
<h4>suggestions.php</h4>
<pre class="brush:html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;
&lt;title&gt;Feature Suggest w/ PHP, jQuery &amp; MySQL | Tutorialzine Demo&lt;/title&gt;

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

&lt;/head&gt;

&lt;body&gt;

&lt;div id="page"&gt;

    &lt;div id="heading" class="rounded"&gt;
    	&lt;h1&gt;Feature Suggest&lt;i&gt;for Tutorialzine.com&lt;/i&gt;&lt;/h1&gt;
    &lt;/div&gt;

    &lt;!-- The generated suggestion list comes here --&gt;

    &lt;form id="suggest" action="" method="post"&gt;
        &lt;p&gt;
            &lt;input type="text" id="suggestionText" class="rounded" /&gt;
            &lt;input type="submit" value="Submit" id="submitSuggestion" /&gt;
        &lt;/p&gt;
	&lt;/form&gt;

&lt;/div&gt;

&lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"&gt;&lt;/script&gt;
&lt;script src="script.js"&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>After this comes the body tag and the <strong>#page</strong> div, which is the main container element. It holds the heading, the unordered list with all the suggestions (which is generated by PHP, as you will see in a moment), and the submit form.</p>
<p>Lastly we include the jQuery library from Google&#8217;s AJAX Library CDN, and our own script.js file, which is discussed in detail in the last section of this tutorial.</p>
<div id="attachment_1076" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/08/ajax-suggest-vote-jquery-php-mysql/suggestions.php"><img class="size-full wp-image-1076" title="Feature Suggest App w/ jQuery, PHP, MySQL" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/08/11.png" alt="Feature Suggest App w/ jQuery, PHP, MySQL" width="620" height="460" /></a><p class="wp-caption-text">Feature Suggest App w/ jQuery, PHP, MySQL</p></div>
<h3>The Table Schema</h3>
<p>The app uses two MySQL tables to store data. Suggestions and Suggestions_votes. The first table contains the text of the suggestion and data such as rating and the number of votes the item has received. The second table keeps record of the IPs of the voters and prevents more than one vote to be cast in a single day per IP.</p>
<div id="attachment_1080" class="wp-caption alignnone" style="width: 630px"><img class="size-full wp-image-1080" title="Suggestion Table Schema" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/08/i4.png" alt="Suggestion Table Schema" width="620" height="260" /><p class="wp-caption-text">Suggestion Table Schema</p></div>
<p>To speed up the selection queries, an index is defined on the <strong>rating </strong>field. This helps when showing the suggestions ordered by popularity.</p>
<p>The suggestion votes table has a primary key consisting of three fields &#8211; the <strong>suggestion_id</strong>, the<strong> IP</strong> of the voter, and the <strong>date </strong>of the vote. And because primary keys do not allow for duplicate rows, we can be sure that users can vote only once per day by just checking the value of the affected_rows variable after the insert.</p>
<div id="attachment_1082" class="wp-caption alignnone" style="width: 630px"><img class="size-full wp-image-1082" title="Suggestions_Votes Schema" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/08/i3.png" alt="Suggestions_Votes Schema" width="620" height="260" /><p class="wp-caption-text">Suggestions_Votes Schema</p></div>
<h3>The PHP</h3>
<p>Before delving into the generation of the suggestion items and the AJAX interactions, first we have to take a look at the suggestion PHP class. It uses two <a href="http://php.net/manual/en/language.oop5.magic.php" target="_blank">PHP magic methods </a>(apart  from the constructor) to provide rich functionality to our code. When  generating the front page, PHP runs a MySQL select query against the  database, and creates an object of this class for every table row. The  columns of the row are added as properties to the object.</p>
<h4>suggestion.class.php</h4>
<pre class="brush:php">class Suggestion
{
	private $data = array();

	public function __construct($arr = array())
	{
		if(!empty($arr)){

			// The $arr array is passed only when we manually
			// create an object of this class in ajax.php

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

	public function __get($property){

		// This is a magic method that is called if we
		// access a property that does not exist.

		if(array_key_exists($property,$this-&gt;data)){
			return $this-&gt;data[$property];
		}

		return NULL;
	}

	public function __toString()
	{
		// This is a magic method which is called when
		// converting the object to string:

		return '
		&lt;li id="s'.$this-&gt;id.'"&gt;
			&lt;div class="vote '.($this-&gt;have_voted ? 'inactive' : 'active').'"&gt;
				&lt;span class="up"&gt;&lt;/span&gt;
				&lt;span class="down"&gt;&lt;/span&gt;
			&lt;/div&gt;

			&lt;div class="text"&gt;'.$this-&gt;suggestion.'&lt;/div&gt;
			&lt;div class="rating"&gt;'.(int)$this-&gt;rating.'&lt;/div&gt;
		&lt;/li&gt;';
	}
}
</pre>
<p>The <strong>__toString()</strong> method is used to create a string representation of the object. With its help we can build the HTML markup, complete with the suggestion title and number of votes.</p>
<p>The <strong>__get()</strong> method is used to route the access to undefined properties of the class to the <strong>$data</strong> array. This means that if we access <strong>$obj-&gt;suggestion</strong>, and this property is undefined, it is going to be fetched from the $data array, and returned to us as if it existed. This way we can just pass an array to the constructor, instead of setting up all the properties. We are using this when creating an object in <strong>ajax.php</strong>.</p>
<p>Now lets proceed with the generation of the unordered list on the front page.</p>
<h4>suggestions.php</h4>
<pre class="brush:php">require "connect.php";
require "suggestion.class.php";

// Converting the IP to a number. This is a more effective way
// to store it in the database:

$ip	= sprintf('%u',ip2long($_SERVER['REMOTE_ADDR']));

// The following query uses a left join to select
// all the suggestions and in the same time determine
// whether the user has voted on them.

$result = $mysqli-&gt;query("
	SELECT s.*, if (v.ip IS NULL,0,1) AS have_voted
	FROM suggestions AS s
	LEFT JOIN suggestions_votes AS v
	ON(
		s.id = v.suggestion_id
		AND v.day = CURRENT_DATE
		AND v.ip = $ip
	)
	ORDER BY s.rating DESC, s.id DESC
");

$str = '';

if(!$mysqli-&gt;error)
{
	// Generating the UL

	$str = '&lt;ul class="suggestions"&gt;';

	// Using MySQLi's fetch_object method to create a new
	// object and populate it with the columns of the result query:

	while($suggestion = $result-&gt;fetch_object('Suggestion')){

		$str.= $suggestion;	// Uses the __toString() magic method.

	}

	$str .='&lt;/ul&gt;';
}</pre>
<p>After running the query, we use the <strong>fetch_object()</strong> method of the <strong>$result</strong> object. This method creates an object of the given class for every row in the result, and assigns the columns of that row to the object as public properties.</p>
<p>PHP also manages the AJAX requests sent by jQuery. This is done in <strong>ajax.php</strong>. To distinguish one AJAX action from another, the script takes a <strong>$_GET['action']</strong> parameter, which can have one of two values &#8211; &#8216;<strong>vote</strong>&#8216; or &#8216;<strong>submit</strong>&#8216;.</p>
<h4>ajax.php</h4>
<pre class="brush:php">require "connect.php";
require "suggestion.class.php";

// If the request did not come from AJAX, exit:
if($_SERVER['HTTP_X_REQUESTED_WITH'] !='XMLHttpRequest'){
	exit;
}

// Converting the IP to a number. This is a more effective way
// to store it in the database:

$ip	= sprintf('%u',ip2long($_SERVER['REMOTE_ADDR']));

if($_GET['action'] == 'vote'){

	$v = (int)$_GET['vote'];
	$id = (int)$_GET['id'];

	if($v != -1 &amp;&amp; $v != 1){
		exit;
	}

	// Checking to see whether such a suggest item id exists:
	if(!$mysqli-&gt;query("SELECT 1 FROM suggestions WHERE id = $id")-&gt;num_rows){
		exit;
	}

	// The id, ip and day fields are set as a primary key.
	// The query will fail if we try to insert a duplicate key,
	// which means that a visitor can vote only once per day.

	$mysqli-&gt;query("
		INSERT INTO suggestions_votes (suggestion_id,ip,day,vote)
		VALUES (
			$id,
			$ip,
			CURRENT_DATE,
			$v
		)
	");

	if($mysqli-&gt;affected_rows == 1)
	{
		$mysqli-&gt;query("
			UPDATE suggestions SET
				".($v == 1 ? 'votes_up = votes_up + 1' : 'votes_down = votes_down + 1').",
				rating = rating + $v
			WHERE id = $id
		");
	}

}
else if($_GET['action'] == 'submit'){

	// Stripping the content
	$_GET['content'] = htmlspecialchars(strip_tags($_GET['content']));

	if(mb_strlen($_GET['content'],'utf-8')&lt;3){
		exit;
	}

	$mysqli-&gt;query("INSERT INTO suggestions SET suggestion = '".$mysqli-&gt;real_escape_string($_GET['content'])."'");

	// Outputting the HTML of the newly created suggestion in a JSON format.
	// We are using (string) to trigger the magic __toString() method.

	echo json_encode(array(
		'html'	=&gt; (string)(new Suggestion(array(
			'id'			=&gt; $mysqli-&gt;insert_id,
			'suggestion'	=&gt; $_GET['content']
		)))
	));
}
</pre>
<p>When jQuery fires the &#8216;<strong>vote</strong>&#8216; request, it does not expect any return values, so the script does not output any. In the &#8216;<strong>submit</strong>&#8216; action, however, jQuery expects a JSON object to be returned, containing the HTML markup of the suggestion that was just inserted. This is where we create a new <strong>Suggestion</strong> object for the sole purpose of using its <strong>__toString()</strong> magic method and converting it with the inbuilt <strong>json_encode()</strong> function.</p>
<div id="attachment_1077" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/08/ajax-suggest-vote-jquery-php-mysql/suggestions.php"><img class="size-full wp-image-1077" title="Suggest &amp; Vote on Features" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/08/2.png" alt="Suggest &amp; Vote on Features" width="620" height="260" /></a><p class="wp-caption-text">Suggest &amp; Vote on Features</p></div>
<h3>The jQuery</h3>
<p>All of the jQuery code resides in <strong>script.js</strong>. It listens for click events on the green and red arrows. But as  suggestions can be inserted at any point, we are using the <strong>live()</strong> jQuery method, so we can listen for the event even on elements that are not yet created.</p>
<h4>script.js</h4>
<pre class="brush:js">$(document).ready(function(){

	var ul = $('ul.suggestions');

	// Listening of a click on a UP or DOWN arrow:

	$('div.vote span').live('click',function(){

		var elem		= $(this),
			parent		= elem.parent(),
			li			= elem.closest('li'),
			ratingDiv	= li.find('.rating'),
			id			= li.attr('id').replace('s',''),
			v			= 1;

		// If the user's already voted:

		if(parent.hasClass('inactive')){
			return false;
		}

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

		if(elem.hasClass('down')){
			v = -1;
		}

		// Incrementing the counter on the right:
		ratingDiv.text(v + +ratingDiv.text());

		// Turning all the LI elements into an array
		// and sorting it on the number of votes:

		var arr = $.makeArray(ul.find('li')).sort(function(l,r){
			return +$('.rating',r).text() - +$('.rating',l).text();
		});

		// Adding the sorted LIs to the UL
		ul.html(arr);

		// Sending an AJAX request
		$.get('ajax.php',{action:'vote',vote:v,'id':id});
	});

	$('#suggest').submit(function(){

		var form		= $(this),
			textField	= $('#suggestionText');

		// Preventing double submits:
		if(form.hasClass('working') || textField.val().length&lt;3){
			return false;
		}

		form.addClass('working');

		$.getJSON('ajax.php',{action:'submit',content:textField.val()},function(msg){
			textField.val('');
			form.removeClass('working');

			if(msg.html){
				// Appending the markup of the newly created LI to the page:
				$(msg.html).hide().appendTo(ul).slideDown();
			}
		});

		return false;
	});
});</pre>
<p>When a click on one of those arrows occurs, jQuery determines whether the &#8216;inactive&#8217; class is present on the LI element. This class is only assigned to the suggestion, if the user has voted during the last day, and, if present, the script will ignore any click events.</p>
<p>Notice how <strong>$.makeArray</strong> is used to turn the jQuery objects, containing the LI elements, into a true array. This is done, so we can use the <strong>array.sort()</strong> method and pass it a custom sort function, which takes two LIs at the same time and outputs a negative integer, zero or a positive integer depending on which of the two elements has a grater rating. This array is later inserted into the unordered list.</p>
<h3>The CSS</h3>
<p>Now that we have all the markup generated, we can move on with the styling. As the styling is pretty much trivial, I only want to show you the class that rounds the top-left and bottom-right corners of the elements that it is applied to. You can see the rest of the CSS rules in styles.css.</p>
<h4>styles.css</h4>
<pre class="brush:css">.rounded,
#suggest,
.suggestions li{
	-moz-border-radius-topleft:12px;
	-moz-border-radius-bottomright:12px;

	-webkit-border-top-left-radius:12px;
	-webkit-border-bottom-right-radius:12px;

	border-top-left-radius:12px;
	border-bottom-right-radius:12px;
}</pre>
<p>Notice that the Mozilla syntax differs from the standard in the way it targets the different corners of the element. Keeping that in mind, we can apply this class to pretty much every element, as you can see from the demonstration.</p>
<p><strong>With this our Feature Suggest App is complete!</strong></p>
<h3>Conclusion</h3>
<p>If you plan to set up this script on your own server, you would need to create the two suggestion tables by running the code found in <strong>tables.sql</strong> in the SQL tab of phpMyAdmin. Also remember to fill in your database connection details in <strong>connect.php</strong>.</p>
<p>You can use this script to gather precious feedback from your visitors. You can also disable the option for users to add new suggestions, and use it as a kind of an advanced poll system.</p>
<p>Be sure to share your thoughts in your comment section below.</p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/08/ajax-suggest-vote-jquery-php-mysql/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Dynamic FAQ Section w/ jQuery, YQL &amp; Google Docs</title>
		<link>http://tutorialzine.com/2010/08/dynamic-faq-jquery-yql-google-docs/</link>
		<comments>http://tutorialzine.com/2010/08/dynamic-faq-jquery-yql-google-docs/#comments</comments>
		<pubDate>Wed, 11 Aug 2010 15:22:49 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=1061</guid>
		<description><![CDATA[In this tutorial, we are making a dynamic FAQ section. The script, with the help of jQuery &#038; YQL, will pull the contents of a shared spreadsheet in your Google Docs account, and use the data to populate the FAQ section with content.]]></description>
			<content:encoded><![CDATA[<p>In this tutorial, we are making a dynamic FAQ section. The script, with the help of jQuery &amp; <a href="http://developer.yahoo.com/yql/" target="_blank">YQL</a>, will pull the contents of a shared spreadsheet in your Google Docs account, and use the data to populate the FAQ section with questions and answers.</p>
<p>The best aspect of this solution, is that you can change the contents of  the FAQ section from within Google Docs &#8211; just edit the spreadsheet.  You can even leverage the rest of Google Docs&#8217; features, such as  collaborative editing. This way, a small team can support the FAQ  section without the need of a dedicated CMS solution.</p>
<p><em>Thanks to <a href="http://csi.nfshost.com/goodies/" target="_blank">Chris Ivarson</a> for designing the Google Docs icon, used in the featured illustration of this tutorial.</em></p>
<h3>Google Docs</h3>
<p>Before starting work on the FAQ section, we first need to create a new Google Docs Spreadsheet. As you probably already have an account with Google (if not, <a href="https://docs.google.com/">create one</a>), we&#8217;ll move straight to the interesting part.</p>
<p>In a blank spreadsheet, start filling in two columns of data. The first column should contain the questions, and the second one the answers, that are going to become entries in your FAQ section. Each FAQ goes on a separate line. You can see the one that I created <a href="https://spreadsheets.google.com/ccc?key=0Ahe1-YRnPKQ_dEI0STVPX05NVTJuNENhVlhKZklNUlE&amp;hl=en&amp;authkey=CJiB3agC" target="_blank">here</a>.</p>
<p>After this, click <strong>Share &gt; Publish as webpage</strong> and choose CSV from the dropdown list. This will generate a link to your spreadsheet in the form of a regular CSV file, which we will use later.</p>
<h3>The HTML</h3>
<p>The first step in developing the script is the markup. The <strong>#page</strong> div is the main container element. It is the only div with an explicit width. It is also centered in the middle of the page with a <a href="http://tutorialzine.com/2010/03/centering-div-vertically-and-horizontally/">margin:auto</a>, as you will see in the CSS part of the tut.</p>
<h4>faq.html</h4>
<pre class="brush:html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;

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

&lt;/head&gt;

&lt;body&gt;

&lt;div id="page"&gt;

    &lt;div id="headingSection"&gt;
    	&lt;h1&gt;Frequently Asked Questions&lt;/h1&gt;
        &lt;a class="button expand" href="#"&gt;Expand&lt;/a&gt;
    &lt;/div&gt;

    &lt;div id="faqSection"&gt;
    	&lt;!-- The FAQs are inserted here --&gt;
    &lt;/div&gt;

&lt;/div&gt;

&lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"&gt;&lt;/script&gt;
&lt;script src="script.js"&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>The stylesheet is included in the head of the document, and the jQuery library and our <strong>script.js</strong> are included at the bottom. All of these are discussed in detail in the next sections of this tutorial.</p>
<p>The <strong>#headingSection</strong> contains the h1 heading, and the expand/collapse button. After it comes the <strong>#faqSection</strong> div, where the FAQ entries are inserted after jQuery fetched the contents of your Google Docs Spreadsheet.</p>
<p>The FAQ entries are organized as a definition list structure (<strong>dl</strong>). This is one of the least used HTML elements, but is perfect for our task. Here is how it looks once jQuery adds it to the page.</p>
<h4>faq.html</h4>
<pre class="brush:html">&lt;dl&gt;
    &lt;dt&gt;&lt;span class="icon"&gt;&lt;/span&gt;How does this FAQ section work?&lt;/dt&gt;
    &lt;dd&gt;With the help of jQuery and YQL, this script pulls the latest data ..&lt;/dd&gt;

    &lt;dt&gt;&lt;span class="icon"&gt;&lt;/span&gt;Can you modify it?&lt;/dt&gt;
    &lt;dd&gt;This is the best part of it - you can change the contents ..&lt;/dd&gt;
&lt;/dl&gt;</pre>
<p>The <strong>dl</strong> element holds a <strong>dt</strong> for each question and a <strong>dd</strong> for each answer. The dd elements are hidden with display:none, and are only shown with a <strong>slideDown</strong> animation once the respective <strong>dt</strong> is clicked.</p>
<div id="attachment_1066" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/08/dynamic-faq-jquery-yql-google-docs/faq.html"><img class="size-full wp-image-1066" title="Dynamic FAQ Section" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/08/21.jpg" alt="Dynamic FAQ Section" width="620" height="460" /></a><p class="wp-caption-text">Dynamic FAQ Section</p></div>
<h3>The CSS</h3>
<p>The styles, (held in styles.css) are pretty straightforward and self-explanatory. As mentioned above, only the <strong>#page</strong> div, which acts as the main container, is explicitly assigned a width. It is also centered in the middle of the page with an auto value for the left/right margins.</p>
<h4>styles.css &#8211; Part 1</h4>
<pre class="brush:css">#page{
	width:753px;
	margin:50px auto;
}

#headingSection{
	background-color:#7b8b98;
	padding:40px;
	padding-left:60px;
	position:relative;
	border:1px solid #8b9ba7;
	border-bottom:none;
}

#faqSection{
	background:url('img/faq_bg.jpg') repeat-y #fff;
	padding:20px 90px 60px 60px;
	border:1px solid white;
	text-shadow:1px 1px 0 white;
}

h1{
	color:#fff;
	font-size:36px;
	font-weight:normal;
}

/* The expand / collapse button */

a.button{
	background:url('img/buttons.png') no-repeat;
	width:80px;
	height:38px;
	position:absolute;
	right:50px;
	top:45px;
	text-indent:-9999px;
	overflow:hidden;
	border:none !important;
}

a.button.expand:hover{ background-position:0 -38px;}
a.button.collapse{ background-position:0 -76px;}
a.button.collapse:hover{ background-position:0 bottom;}
</pre>
<p>We are using a single anchor tag for both the expand and the collapse button, by assigning it either the <strong>expand</strong> or the <strong>collapse</strong> CSS class. These classes determine which parts of the background image are offset into view. The background image itself is four times the height of the button, and contains a normal and a hover state for both the expand and collapse button versions.</p>
<h4>styles.css &#8211; Part 2</h4>
<pre class="brush:css">/* Definition Lists */

dt{
	color:#8F9AA3;
	font-size:25px;
	margin-top:30px;
	padding-left:25px;
	position:relative;
	cursor:pointer;
	border:1px solid transparent;
}

dt:hover{ color:#5f6a73;}

dt .icon{
	background:url('img/bullets.png') no-repeat;
	height:12px;
	left:0;
	position:absolute;
	top:11px;
	width:12px;
}

dt.opened .icon{ background-position:left bottom;}

dd{
	font-size:14px;
	color:#717f89;
	line-height:1.5;
	padding:20px 0 0 25px;
	width:580px;
	display:none;
}
</pre>
<p>When a definition title (dt) is clicked, its respective dd is expanded into view (as you will see in the next section). With this, the dt is also assigned an <strong>opened</strong> class. This class helps jQuery determine which FAQ&#8217;s are opened, and in the same time affects the styling of the small bullet on the left of the title.</p>
<div id="attachment_1067" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/08/dynamic-faq-jquery-yql-google-docs/faq.html"><img class="size-full wp-image-1067" title="FAQ expanded" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/08/3.png" alt="FAQ expanded" width="620" height="260" /></a><p class="wp-caption-text">FAQ expanded</p></div>
<h3>The jQuery</h3>
<p>Moving to probably the most interesting part of the tutorial. If you&#8217;ve been following the tutorials on this site, you&#8217;ve probably noticed that <a href="http://developer.yahoo.com/yql/" target="_blank">YQL</a> finds its way into <a href="http://tutorialzine.com/?s=YQL">a lot of the tutorials here</a>. The main reason behind this, is that YQL makes possible for developers to use it as a proxy for a wide range of APIs, and implement a diverse functionality entirely in JavaScript.</p>
<p>Today we are using YQL to fetch our Google Spreadsheet as CSV and parse it, so that it is available as a regular JSON object. This way, we end up with a free and easy to update data storage for our simple app.</p>
<h4>script.js</h4>
<pre class="brush:js">$(document).ready(function(){

	// The published URL of your Google Docs spreadsheet as CSV:
	var csvURL = 'https://spreadsheets.google.com/pub?key='+
			'0Ahe1-YRnPKQ_dEI0STVPX05NVTJuNENhVlhKZklNUlE&amp;hl=en&amp;output=csv';

	// The YQL address:
	var yqlURL =	"http://query.yahooapis.com/v1/public/yql?q="+
			"select%20*%20from%20csv%20where%20url%3D'"+encodeURIComponent(csvURL)+
			"'%20and%20columns%3D'question%2Canswer'&amp;format=json&amp;callback=?";

	$.getJSON(yqlURL,function(msg){

		var dl = $('&lt;dl&gt;');

		// Looping through all the entries in the CSV file:
		$.each(msg.query.results.row,function(){

			// Sometimes the entries are surrounded by double quotes. This is why
			// we strip them first with the replace method:

			var answer = this.answer.replace(/""/g,'"').replace(/^"|"$/g,'');
			var question = this.question.replace(/""/g,'"').replace(/^"|"$/g,'');

			// Formatting the FAQ as a definition list: dt for the question
			// and a dd for the answer.

			dl.append('&lt;dt&gt;&lt;span class="icon"&gt;&lt;/span&gt;'+
			question+'&lt;/dt&gt;&lt;dd&gt;'+answer+'&lt;/dd&gt;');
		});

		// Appending the definition list:
		$('#faqSection').append(dl);

		$('dt').live('click',function(){
			var dd = $(this).next();

			// If the title is clicked and the dd is not currently animated,
			// start an animation with the slideToggle() method.

			if(!dd.is(':animated')){
				dd.slideToggle();
				$(this).toggleClass('opened');
			}

		});

		$('a.button').click(function(){

			// To expand/collapse all of the FAQs simultaneously,
			// just trigger the click event on the DTs

			if($(this).hasClass('collapse')){
				$('dt.opened').click();
			}
			else $('dt:not(.opened)').click();

			$(this).toggleClass('expand collapse');

			return false;
		});

	});
});</pre>
<p>It may not be clear from the code above, but jQuery sends a JSONP request to YQL&#8217;s servers with the following YQL query:</p>
<pre class="brush:sql">SELECT * FROM csv
WHERE url='https://spreadsheets.google.com/...'
AND columns='question,answer'</pre>
<p><strong><em>CSV</em></strong> is a YQL table, which takes the URL of a csv file and a list of column names. It returns a JSON object with the column names as its properties. The script then filters them (stripping off unnecessary double quotes) and inserts them as a definition list (DL)  into the page.</p>
<p><strong>With this our dynamic FAQ section is complete!</strong></p>
<h3>Customization</h3>
<p>To use this script with your own spreadsheet, you only need to edit the csvURL variable in <strong>script.js</strong>, and replace it with the CSV  URL of your spreadsheet. You can obtain this address from <strong>Share &gt; Publish as webpage &gt; CSV dropdown</strong>. Also, be aware that when you make changes to the spreadsheet, it could take a few minutes for the changes to take effect. You can speed this up by clicking the <em><strong>Republish now</strong></em> button, found in the same overlay window.</p>
<div id="attachment_1065" class="wp-caption alignnone" style="width: 630px"><img class="size-full wp-image-1065" title="Obtaining the CSV URL" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/08/1.png" alt="Obtaining the CSV URL" width="620" height="460" /><p class="wp-caption-text">Obtaining the CSV URL</p></div>
<h3>Final Words</h3>
<p>You can use the same technique to power different kinds of dynamic pages. However, this implementation does have its shortcomings. All the content is generated with JavaScript, which means that it will not be visible to search engines.</p>
<p>To guarantee that your data will be crawled, you can take a different route. You could use PHP, or other back-end language, to fetch and display the data from YQL in a fixed interval of time &#8211; say 30 minutes (or even less frequently, if you don&#8217;t plan to update the data often).</p>
<p><strong>Be sure to share your suggestions in the comment section below.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/08/dynamic-faq-jquery-yql-google-docs/feed/</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
		<item>
		<title>A Simple Movie Search App w/ jQuery UI</title>
		<link>http://tutorialzine.com/2010/08/simple-movie-search-app-jquery-ajax/</link>
		<comments>http://tutorialzine.com/2010/08/simple-movie-search-app-jquery-ajax/#comments</comments>
		<pubDate>Thu, 05 Aug 2010 17:59:19 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=1046</guid>
		<description><![CDATA[In this tutorial, we are using jQuery UI's autocomplete widget, to build a simple AJAX movie search form. The script is going to use TheMovieDatabase.org's free API, to provide auto suggestions against a vast database of movie titles.]]></description>
			<content:encoded><![CDATA[<p>In this tutorial, we are using <a href="http://jqueryui.com/demos/autocomplete/" target="_blank">jQuery UI&#8217;s autocomplete widget</a>, to build a simple AJAX movie search form. The script is going to use <a href="http://www.themoviedb.org/" target="_blank">TheMovieDatabase.org</a>&#8216;s free <a href="http://api.themoviedb.org/2.1/">API</a>, to provide auto suggestions against a vast database of movie titles.</p>
<p>For those of you who might not be familiar with TMDb.org, this is an open, community driven movie database. It is similar to <a href="http://www.imdb.com/">IMDb</a>, which you&#8217;ve probably heard about, but also provides a number of useful API&#8217;s for developers.</p>
<h3>Prerequisites</h3>
<p>Before being able to use the API, you need to get a free developer key from TMDb after a quick <a href="http://www.themoviedb.org/account/signup" target="_blank">registration</a>. After this, remember to copy your key to <strong>movieInfo.php</strong> from the download archive.</p>
<h3>Step 1 &#8211; XHTML</h3>
<p>The markup consists of  the two main div containers &#8211; <strong>#logo</strong> and <strong>#holder</strong>.  The former holds the icon and the logo text in the form of transparent  PNG images (defined as backgrounds to the respective divs), while the latter contains the search form and the submit button.</p>
<h4>movieApp.html</h4>
<pre class="brush:html">&lt;div id="page"&gt;

    &lt;div id="logo"&gt;
        &lt;div id="icon"&gt;&lt;/div&gt;
        &lt;div id="movieAppLabel"&gt;&lt;/div&gt;
    &lt;/div&gt;

    &lt;div id="holder"&gt;
    	&lt;form action="http://www.themoviedb.org/search" method="post" target="_blank"&gt;
            &lt;fieldset&gt;
            	&lt;input type="text" id="movieName" name="search" /&gt;
            &lt;/fieldset&gt;
        &lt;/form&gt;
        &lt;a href="#" class="button"&gt;Submit&lt;/a&gt;
    &lt;/div&gt;

&lt;/div&gt;

&lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"&gt;&lt;/script&gt;
&lt;script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/jquery-ui.min.js"&gt;&lt;/script&gt;
&lt;script src="script.js"&gt;&lt;/script&gt;
</pre>
<p>Notice that the action attribute of the form is pointed at TMDB&#8217;s search page. The search terms are passed via POST with the <strong>#movieName</strong> text field. You can test it by filling in a movie name and submitting the form.</p>
<p>Lastly in the page are included jQuery, jQuery UI and our own script file. We are using jQuery UI&#8217;s autocomplete widget to display a drop down list of movie titles which are fetched from TMDb&#8217;s API. You can see the markup that is generated by the widget below.</p>
<pre class="brush:html">&lt;input class="ui-autocomplete-input"/&gt;
&lt;ul class="ui-autocomplete ui-menu ui-widget ui-widget-content ui-corner-all"&gt;
  &lt;li class="ui-menu-item"&gt;
    &lt;a class="ui-corner-all"&gt;item 1&lt;/a&gt;
  &lt;/li&gt;
  &lt;li class="ui-menu-item"&gt;
    &lt;a class="ui-corner-all"&gt;item 2&lt;/a&gt;
  &lt;/li&gt;
  &lt;li class="ui-menu-item"&gt;
    &lt;a class="ui-corner-all"&gt;item 3&lt;/a&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</pre>
<p>This code is generated automatically by the widget and appended before the closing body tag.</p>
<div id="attachment_1051" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/08/simple-movie-search-app-jquery-ajax/movieApp.html"><img class="size-full wp-image-1051 " title="Simple Movie Search App" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/08/2.jpg" alt="Simple Movie Search App" width="620" height="460" /></a><p class="wp-caption-text">Simple Movie Search App</p></div>
<h3>Step 2 &#8211; PHP</h3>
<p>When you start typing a movie title in the text box of the form, an AJAX request is sent to <strong>moveInfo.php</strong>. This script sends a search request to TMDb&#8217;s API, with our developer key. The service returns a JSON object with suitable movie titles. The script processes them and outputs them back as a response to the AJAX request.</p>
<p>Lets take a closer look at how this works.</p>
<h4>movieInfo.php</h4>
<pre class="brush:php">/**
 *	Define your API key below. To obtain one, visit
 *	http://www.themoviedb.org/account/signup
 */

$api_key = '...';

// If the request was not issued by AJAX, or
// the search term is missing, exit:

if(!$_SERVER["HTTP_X_REQUESTED_WITH"] || !$_GET['term']){
	exit;
}

include 'tmdbAPI/TMDb.php';

$tmdb = new TMDb($api_key);

// Send a search API request to TMDb,
// and parse the returned JSON data:

$json = json_decode($tmdb-&gt;searchMovie($_GET['term']));

$response = array();

$i=0;
foreach($json as $movie){

	// Only movies existing in the IMDB catalog (and are not adult) are shown

	if(!$movie-&gt;imdb_id || $movie-&gt;adult) continue;
	if($i &gt;= 8 ) break;

	// The jQuery autocomplete widget shows the label in the drop down,
	// and adds the value property to the text box.

	$response[$i]['value'] = $movie-&gt;name;
	$response[$i]['label'] = $movie-&gt;name . ' &lt;small&gt;(' . date('Y',strtotime($movie-&gt;released)).')&lt;/small&gt;';
	$i++;
}

// Presenting the response as a JSON object:

echo json_encode($response);</pre>
<p>Luckily for us, there is a <a href="http://github.com/glamorous/TMDb-PHP-API" target="_blank">PHP class available</a>, that handles all communication with the TMDb API. We just need to include it into the page, and provide the developer API key we received from TMDb. The search terms, that the user has entered into the search box, are available in <strong>$_GET['term']</strong>. Calling the <strong>searchMovie()</strong> method with these terms, will yield a JSON object, containing all kinds of information about the movies that match our search criteria. You can see a sample response below.</p>
<pre class="brush:js">[{
    "score": 8.750235,
    "popularity": 3,
    "translated": true,
    "adult": false,
    "language": "en",
    "name": "The Hitchhiker's Guide to the Galaxy",
    "alternative_name": "The Hitchhikers Guide to the Galaxy",
    "movie_type": "movie",
    "id": 7453,
    "imdb_id": "tt0371724",
    "url": "http://www.themoviedb.org/movie/7453",
    "rating": 6.8,
    "certification": "PG",
    "overview": "Mere seconds before the Earth is to be demolished by an alien construction crew, Arthur Dent is swept off the planet by his friend Ford Prefect, a researcher penning a new edition of \"The Hitchhiker's Guide to the Galaxy.\"",
    "released": "2005-04-20",
    "posters": [{
        "image": {
            "type": "poster",
            "size": "original",
            "height": 1000,
            "width": 675,
            "url": "http://hwcdn.themoviedb.org/posters/16e/4bcc96cd017a3c0f2600016e/the-hitchhiker-s-guide-to-the-galaxy-original.jpg",
            "id": "4bcc96cd017a3c0f2600016e"
        }
    }],
    "version": 22,
    "last_modified_at": "2010-07-19 22:59:02"
}]
</pre>
<p>The response contains the<em> title</em> of the movie, an <em>overview</em>,<em> release date</em>, a corresponding IMDB id, and even <em>posters </em>and <em>fan art</em>. We do not need most of this information, so PHP reduces it only to a title and a release year, after which outputs it in the form of a JSON object, ready to be used by the autocomplete. This brings us to the next step.</p>
<h3>Step 3 &#8211; jQuery</h3>
<p>As you know, jQuery comes with a lot of useful functionality in the form of plugins. There is also a dedicated extension of the library, for building user interfaces, known as jQuery UI. It gives developers widgets, which are ready for use and easy to customize. One of these widgets is the new <a href="http://jqueryui.com/demos/autocomplete/" target="_blank">autocomplete widget</a>, introduced in the newer versions of the library.</p>
<p>Lets take a look at how it is used.</p>
<h4>script.js</h4>
<pre class="brush:js">$(document).ready(function(){

	// Caching the movieName textbox:
	var movieName = $('#movieName');

	// Defining a placeholder text:
	movieName.defaultText('Type a Move Title');

	// Using jQuery UI's autocomplete widget:
	movieName.autocomplete({
		minLength	: 5,
		source		: 'movieInfo.php'
	});

	$('#holder .button').click(function(){
		if(movieName.val().length &amp;&amp; movieName.data('defaultText') != movieName.val()){
			$('#holder form').submit();
		}
	});
});

// A custom jQuery method for placeholder text:

$.fn.defaultText = function(value){

	var element = this.eq(0);
	element.data('defaultText',value);

	element.focus(function(){
		if(element.val() == value){
			element.val('').removeClass('defaultText');
		}
	}).blur(function(){
		if(element.val() == '' || element.val() == value){
			element.addClass('defaultText').val(value);
		}
	});

	return element.blur();
}</pre>
<p>To create an autocomplete, we just need to call the <strong>autocomplete()</strong> method. It takes a number of optional parameters. The most important ones are <strong>minLength</strong> (which prevents request to the server from being fired before a certain number of characters has been typed) and <strong>source,</strong> which determines the data that is shown in the drop down list.</p>
<p><strong>Source</strong> can take either an array with strings, a URL (to which an AJAX request will be sent) or a callback function. In our case, the URL of <strong>movieInfo.php</strong> will suffice.</p>
<p>Here is a sample response, which is returned by movieInfo.php (this JSON object was compiled after a request to TMDb&#8217;s API for &#8220;<em>Hitchhiker&#8217;s guide</em>&#8220;).</p>
<pre class="brush:js">[{
    "value": "Hachiko: A Dog's Story",
    "label": "Hachiko: A Dog's Story &lt;small&gt;(2009)&lt;\/small&gt;"
},
{
    "value": "Teenage Hitch-hikers",
    "label": "Teenage Hitch-hikers &lt;small&gt;(1975)&lt;\/small&gt;"
},
{
    "value": "The Hitchhiker's Guide to the Galaxy",
    "label": "The Hitchhiker's Guide to the Galaxy &lt;small&gt;(2005)&lt;\/small&gt;"
},
{
    "value": "The Hitch-Hiker",
    "label": "The Hitch-Hiker &lt;small&gt;(1953)&lt;\/small&gt;"
}]</pre>
<p>Each object in the array contains a <strong>value</strong> and a <strong>label</strong> property. The label is only shown in the dropdown list, while the value is inserted into the textbox once the item is selected.</p>
<div id="attachment_1052" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/08/simple-movie-search-app-jquery-ajax/movieApp.html"><img class="size-full wp-image-1052" title="Custom Styled jQuery UI Autocomplete" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/08/1.jpg" alt="Custom Styled jQuery UI Autocomplete" width="620" height="460" /></a><p class="wp-caption-text">Custom Styled jQuery UI Autocomplete</p></div>
<h3>Step 4 &#8211; CSS</h3>
<p>Now that all the markup is generated and is in place, it is time to start beautifying.</p>
<h4>styles.css &#8211; Part 1</h4>
<pre class="brush:css">#page{
	width:600px;
	margin:150px auto 0;
}

/* Logo */

#logo{
	width:380px;
	position:relative;
	height:90px;
	margin:0 auto;
}

#icon{
	width:80px;
	height:86px;
	background:url('img/icon.png') no-repeat;
	float:left;
}

#movieAppLabel{
	width:268px;
	height:58px;
	background:url('img/logo_txt.png') no-repeat;
	position:absolute;
	right:0;
	top:18px;
}

/* The Search Box &amp; Holder */

#holder{
	width:530px;
	height:145px;
	background:url('img/holder.png') no-repeat center center;
	margin:30px auto;
	position:relative;
}

#holder fieldset{
	position:absolute;
	top:52px;
	left:40px;
	border-bottom:1px solid #fff;
}

#holder input{
	font-family:'Myriad Pro',Arial,Helvetica,sans-serif;
	border:none;
	border-bottom:1px solid #bbb;
	background:none;
	color:#8D8D8D;
	font-size:20px;
	padding:4px 0;
	width:250px;
	text-shadow:1px 1px #fff;
	outline:none;
}
</pre>
<p>In the first part of the code, we style the <strong>#logo</strong>, and the <strong>#holder</strong> divs. The shutter icon and the logo text are defined as backgrounds to the <strong>#icon</strong> and <strong>#movieAppLabel</strong> divs respectively. Relative positioning is applied to the <strong>#holder</strong> so that it is easier to position the input box and the submit button.</p>
<h4>styles.css &#8211; Part 2</h4>
<pre class="brush:css">fieldset{
	border:none;
}

/* The Blue Button */

a.button{
	background:url('img/buttons.png') no-repeat;
	width:105px;
	height:37px;
	position:absolute;
	top:52px;
	right:42px;
	text-indent:-9999px;
	overflow:hidden;
	border:none !important;
}

a.button:hover{
	background-position:left bottom;
}

/* Styling the markup generated by the autocomplete jQuery UI widget */

ul.ui-autocomplete{
	width:250px;
	background-color:#f5f5f5;
	border:1px solid #fff;
	outline:1px solid #ccc;
}

ul.ui-autocomplete li{
	list-style:none;
	border-bottom:1px solid #e0e0e0;
	border-top:1px solid #fff;
}

ul.ui-autocomplete li:first-child{
	border-top:none;
}

ul.ui-autocomplete li:last-child{
	border-bottom:none;
}

ul.ui-autocomplete li a{
	color:#999;
	border:none !important;
	text-decoration:none !important;
	padding:10px 17px;
	display:block;
}

#ui-active-menuitem{
	background-color:#fff;
	color:#666;
	cursor:pointer;
}
</pre>
<p>jQuery UI does come <a href="http://jqueryui.com/themeroller/" target="_blank">with its own styles</a>, however they are rather clunky and do not fit well into the current design. This is why we are applying a number of rules (starting from line 23), which apply a custom design to the autocomplete widget. The structure of the widget is basically an unordered list, with each of the suggested items being a hyperlink in a <strong>li</strong> element. With this in mind (and after looking up the appropriate class names from the code in step one) we can safely style the drop down list and perfectly blend it with the rest of the design.</p>
<p><strong>With this our Simple Movie Search App is complete!</strong></p>
<h3>To Wrap it Up</h3>
<p>You can modify this script to use any kind of api and data. This can be a powerful tool, as it might assist users in typing search terms that they may not normally think of themselves. For example providing your product names as search suggestions, may be an effective tactic to expose more of your merchandise and improve sales.</p>
<p><strong>What do you think? How would you improve this app?</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/08/simple-movie-search-app-jquery-ajax/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<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://cdn.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://cdn.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://cdn.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://cdn.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>14</slash:comments>
		</item>
		<item>
		<title>Making a Custom YouTube Video Player With YouTube&#8217;s APIs</title>
		<link>http://tutorialzine.com/2010/07/youtube-api-custom-player-jquery-css/</link>
		<comments>http://tutorialzine.com/2010/07/youtube-api-custom-player-jquery-css/#comments</comments>
		<pubDate>Fri, 23 Jul 2010 18:06:04 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=1027</guid>
		<description><![CDATA[Today we are going to make a jQuery plugin which uses YouTube's chromeless player, and creates our own set of minimalistic controls, which allows for perfect integration with your designs. The supported controls include a Play/Pause/Replay button, and a clickable progress bar.]]></description>
			<content:encoded><![CDATA[<p>Video presentations are a great addition to any product page. With a presentation you can showcase your product&#8217;s features without making the visitor read through long paragraphs of text. But apart from producing the video, you still need to manually convert it and find (or code) some sort of flash player that will display it on your site.</p>
<p>The other possible path is that you upload it to a video sharing site such as youtube, but you are going to have a rough time trying to incorporate the player into your design.</p>
<p>Luckily for us, YouTube does provide a solution to this problem &#8211; their <a href="http://code.google.com/apis/youtube/youtube_player_demo.html?playerType=chromeless&amp;playerVersion=as3" target="_blank">chromeless player</a> (a stripped down version of the regular embeddable player), which allow you to build and style your own custom controls. This way you have both a quick and secure way to include videos in your pages, and the freedom to customize any way you might want to.</p>
<h3>The Idea</h3>
<p>Today we are going to make a jQuery plugin which uses YouTube&#8217;s <strong>chromeless player</strong>, and creates our own set of minimalistic controls, which   allows for perfect integration with your designs. The supported controls include a Play/Pause/Replay button, and a clickable progress bar.</p>
<p>The plugin is going to use YouTube&#8217;s <a href="http://code.google.com/apis/youtube/2.0/developers_guide_jsonc.html" target="_blank">gdata api</a> to determine whether embedding has been allowed for the video, and fetch extensive information about it, such as title, description, tags, screenshots &amp; more, which you can use to improve the plugin.</p>
<p>Using the plugin to embed videos is extremely easy:</p>
<pre class="brush:js">// Embed a video into the #player div:
$('#player').youTubeEmbed('http://www.youtube.com/watch?v=u1zgFlCw8Aw');

// Chaining is also supported:
$('#player').youTubeEmbed('http://www.youtube.com/watch?v=u1zgFlCw8Aw');
		.youTubeEmbed('http://www.youtube.com/watch?v=AsdfFdwlzdAw');
</pre>
<p>You can also specify a width for the embedded video (the height will be calculated automatically depending on the aspect ratio), and choose to disable the progress bar:</p>
<pre class="brush:js">$('#player').youTubeEmbed({
	video			: 'http://www.youtube.com/watch?v=u1zgFlCw8Aw',
	width			: 600, 		// Height is calculated automatically
	progressBar	: false		// Hide the progress bar
});
</pre>
<p>You can grab the plugin from the download button above, and start with the first step.</p>
<h3>Step 1 &#8211; XHTML</h3>
<p>Our plugin depends on <a href="http://jquery.thewikies.com/swfobject/" target="_blank">jQuery SWFObject</a> to embed the SWF files in the page. Below you can see the combined markup that is generated by both of the plugins.</p>
<h4>youtube-player.html</h4>
<pre class="brush:html">&lt;div class="flashContainer" style="width: 640px; height: 360px;"&gt;

	&lt;object height="360" width="640" id="video_26ELpS3Wc4Q" type="application/x-shockwave-flash"
	data="http://www.youtube.com/apiplayer?enablejsapi=1&amp;version=3"&gt;

		&lt;param value="always" name="allowScriptAccess"&gt;
		&lt;param value="transparent" name="wmode"&gt;
		&lt;param value="video_id=26ELpS3Wc4Q&amp;playerapiid=26ELpS3Wc4Q"
		name="flashvars"&gt;
		&lt;param value="http://www.youtube.com/apiplayer?enablejsapi=1&amp;version=3"
		name="movie"&gt;

	&lt;/object&gt;

	&lt;div class="controlDiv play"&gt;&lt;/div&gt;

	&lt;div class="progressBar"&gt;
		&lt;div class="elapsed"&gt;&lt;/div&gt;
	&lt;/div&gt;
&lt;/div&gt;</pre>
<p>The <strong>.flashContainerDiv</strong> is dynamically created by the plugin for each video on the page. It is populated with the embed code generated by  SWFObject, the <strong>.controlDiv</strong> (which acts as a play/pause button) and the progress bar.</p>
<p>As mentioned above, the insertion of the player itself is handled by the SWFObject plugin. Depending on the browser, it can output either an <strong>object</strong> element, or a non-standard <strong>embed</strong> element for IE. This lifts the burden from us and allows us to concentrate on tasks such as querying YouTube&#8217;s APIs and building the player controls.</p>
<div id="attachment_1032" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/07/youtube-api-custom-player-jquery-css/youtube-player.html"><img class="size-full wp-image-1032" title="Custom YouTube Player" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/07/i11.jpg" alt="Custom YouTube Player" width="620" height="460" /></a><p class="wp-caption-text">Custom YouTube Player</p></div>
<h3>Step 2 &#8211; jQuery</h3>
<p>The plugin&#8217;s code is located in the <strong>youTubeEmbed-jquery-1.0.js</strong> file. However, before being able to use it, you need to include the latest version of the jQuery library in the page, along with the jQuery SWFObject plugin and lastly <strong>script.js</strong>, which inserts two videos in the demonstration page and handles the submissions of the preview form.</p>
<pre class="brush:html">&lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"&gt;&lt;/script&gt;
&lt;script src="jquery.swfobject.1-1-1.min.js"&gt;&lt;/script&gt;
&lt;script src="youTubeEmbed/youTubeEmbed-jquery-1.0.js"&gt;&lt;/script&gt;
&lt;script src="script.js"&gt;&lt;/script&gt;
</pre>
<p>Before we start digging into the player plugin&#8217;s code, lets take a look at a sample response from YouTube&#8217;s gdata api. It can give you a  lot of useful information about a video, including duration, access  control (both of which used by the plugin) and all sorts of additional  data such as title, description, tags, screenshots and more.</p>
<h4>Sample JSON response</h4>
<pre class="brush:js">{
    "id": "u1zgFlCw8Aw",
    "uploaded": "2008-03-05T01:22:17.000Z",
    "updated": "2010-07-23T01:02:42.000Z",
    "uploader": "GoogleDevelopers",
    "category": "People",
    "title": "The YouTube API: Upload, Player APIs and more!",
    "description": "Listen to the YouTube APIs and Tools team talk about...",
    "tags": ["youtube", "launch", "api", "engineering"],
    "thumbnail": {
        "sqDefault": "http://i.ytimg.com/vi/u1zgFlCw8Aw/default.jpg",
        "hqDefault": "http://i.ytimg.com/vi/u1zgFlCw8Aw/hqdefault.jpg"
    },
    "player": {
        "default": "http://www.youtube.com/watch?v=u1zgFlCw8Aw",
        "mobile": "http://m.youtube.com/details?v=u1zgFlCw8Aw"
    },
    "content": {
        "1": "rtsp://v4.cache5.c.youtube.com/CiILE..",
        "5": "http://www.youtube.com/v/u1zgFlCw8Aw?f..",
        "6": "rtsp://v3.cache4.c.youtube.com/CiILENy73.."
    },
    "duration": 259,
    "location": "san bruno, ca",
    "rating": 4.3,
    "likeCount": "119",
    "ratingCount": 144,
    "viewCount": 251024,
    "favoriteCount": 164,
    "commentCount": 118,
    "accessControl": {
        "syndicate": "allowed",
        "commentVote": "allowed",
        "rate": "allowed",
        "list": "allowed",
        "comment": "allowed",
        "embed": "allowed",
        "videoRespond": "allowed"
    }
}
</pre>
<p>All the fields of this response objects are available as properties in the <strong>data </strong>variable (<strong>data.fieldname</strong>). You could potentially modify the plugin to show the title with a link to the video page on youtube, or show the rating of the video.</p>
<p>Now lets dive directly into the script&#8217;s source code.</p>
<h4>youTubeEmbed-jquery-1.0.js &#8211; Part 1</h4>
<pre class="brush:js">(function($){

	$.fn.youTubeEmbed = function(settings){

		// Settings can be either a URL string,
		// or an object

		if(typeof settings == 'string'){
			settings = {'video' : settings}
		}

		// Default values

		var def = {
			width		: 640,
			progressBar	: true
		};

		settings = $.extend(def,settings);

		var elements = {
			originalDIV	: this,	// The "this" of the plugin
			container	: null,	// A container div, inserted by the plugin
			control		: null,	// The control play/pause button
			player		: null,	// The flash player
			progress	: null,	// Progress bar
			elapsed		: null	// The light blue elapsed bar
		};

		try{	

			settings.videoID = settings.video.match(/v=(\w+)/)[1];

			// safeID is a stripped version of videoID,
			// ready for use as a JavaScript function name

			settings.safeID = settings.videoID.replace(/[^a-z0-9]/ig,'');

		} catch (e){
			// If the url was invalid, just return the "this"
			return elements.originalDIV;
		}

		// Fetch data about the video from YouTube's API

		var youtubeAPI = 'http://gdata.youtube.com/feeds/api/videos?v=2&amp;alt=jsonc';

		$.get(youtubeAPI,{'q':settings.videoID},function(response){

			var data = response.data;

			if(!data.totalItems || data.items[0].accessControl.embed!="allowed"){

				// If the video was not found, or embedding is not allowed;

				return elements.originalDIV;
			}

			// data holds API info about the video:

			data = data.items[0];

			settings.ratio = 3/4;
			if(data.aspectRatio == "widescreen"){
				settings.ratio = 9/16;
			}

			settings.height = Math.round(settings.width*settings.ratio);
</pre>
<p>We start by defining our script as a jQuery plugin by adding it as a function to the <strong>$.fn</strong> object. To make the code easier to follow and read, I put all the elements of the page, such as the control and the progressBar divs in a structure called <strong>elements</strong>.</p>
<p>After extracting the <strong>id</strong> of the video (a unique 11 character sequence after the <strong>?v=</strong> parameter), we send a JSONP request to youtube&#8217;s gdata API. Depending on whether such a video exists, and on whether embedding is allowed on it, we proceed with calculating the aspect ratio. The height of the video is calculated by using this ratio and multiplying it to the width.</p>
<h4>youTubeEmbed-jquery-1.0.js &#8211; Part 2</h4>
<pre class="brush:js">			// Creating a container inside the original div, which will
			// hold the object/embed code of the video

			elements.container = $('&lt;div&gt;',{className:'flashContainer',css:{
				width	: settings.width,
				height	: settings.height
			}}).appendTo(elements.originalDIV);

			// Embedding the YouTube chromeless player
			// and loading the video inside it:

			elements.container.flash({
				swf			: 'http://www.youtube.com/apiplayer?enablejsapi=1&amp;version=3',
				id			: 'video_'+settings.safeID,
				height		: settings.height,
				width		: settings.width,
				allowScriptAccess:'always',
				wmode		: 'transparent',
				flashvars	: {
					"video_id"		: settings.videoID,
					"playerapiid"	: settings.safeID
				}
			});

			// We use get, because we need the DOM element
			// itself, and not a jquery object:

			elements.player = elements.container.flash().get(0);

			// Creating the control Div. It will act as a ply/pause button

			elements.control = $('&lt;div&gt;',{className:'controlDiv play'})
							   .appendTo(elements.container);

			// If the user wants to show the progress bar:

			if(settings.progressBar){
				elements.progress =	$('&lt;div&gt;',{className:'progressBar'})
									.appendTo(elements.container);

				elements.elapsed =	$('&lt;div&gt;',{className:'elapsed'})
									.appendTo(elements.progress);

				elements.progress.click(function(e){

					// When a click occurs on the progress bar, seek to the
					// appropriate moment of the video.

					var ratio = (e.pageX-elements.progress.offset().left)/elements.progress.outerWidth();

					elements.elapsed.width(ratio*100+'%');
					elements.player.seekTo(Math.round(data.duration*ratio), true);
					return false;
				});

			}
</pre>
<p>In the second part of the code, we use the <strong>SWFObject </strong>plugin to generate the embed code of  the youtube chromeless player. Notice that the id of the video is passed as a flashvar so the player can load it directly. The safeID variable (a JavaScript safe version of the videoid) becomes the value of the <strong>id</strong> parameter of the to-be generated object element. This way we can later fetch the DOM element by running <strong>document.getElementById(&#8216;video_&#8217;+settings.safeID)</strong> and get access to the <a href="http://code.google.com/apis/youtube/js_api_reference.html" target="_blank">methods which control the youtube player</a> (play, pause etc).</p>
<h4>youTubeEmbed-jquery-1.0.js &#8211; Part 3</h4>
<pre class="brush:js">var initialized = false;

// Creating a global event listening function for the video
// (required by YouTube's player API):

window['eventListener_'+settings.safeID] = function(status){

	var interval;

	if(status==-1)	// video is loaded
	{
		if(!initialized)
		{
			// Listen for a click on the control button:

			elements.control.click(function(){
				if(!elements.container.hasClass('playing')){

					// If the video is not currently playing, start it:

					elements.control.removeClass('play replay').addClass('pause');
					elements.container.addClass('playing');
					elements.player.playVideo();

					if(settings.progressBar){
						interval = window.setInterval(function(){
							elements.elapsed.width(
					((elements.player.getCurrentTime()/data.duration)*100)+'%'
							);
						},1000);
					}

				} else {

					// If the video is currently playing, pause it:

					elements.control.removeClass('pause').addClass('play');
					elements.container.removeClass('playing');
					elements.player.pauseVideo();

					if(settings.progressBar){
						window.clearInterval(interval);
					}
				}
			});

			initialized = true;
		}
		else{
			// This will happen if the user has clicked on the
			// YouTube logo and has been redirected to youtube.com

			if(elements.container.hasClass('playing'))
			{
				elements.control.click();
			}
		}
	}</pre>
<p>In order to be able to control the video player, we need to be notified when certain events (like playback stopped, video ready etc) occur. Normally, this would mean that we need to pass a callback function, which is executed by the player every time such an event happens.</p>
<p>Unfortunately, flash can only execute functions if they are defined in the global scope and cannot see the functions which are defined inside the plugin. However, by creating functions with unique names (with the <strong>safeID</strong>) and explicitly adding them to the <strong>window</strong> object we can make this happen. If it weren&#8217;t for this little trick, it would be impossible for the plugin to work.</p>
<h4>youTubeEmbed-jquery-1.0.js &#8211; Part 4</h4>
<pre class="brush:js">				if(status==0){ // video has ended
					elements.control.removeClass('pause').addClass('replay');
					elements.container.removeClass('playing');
				}
			}

			// This global function is called when the player is loaded.
			// It is shared by all the videos on the page:

			if(!window.onYouTubePlayerReady)
			{
				window.onYouTubePlayerReady = function(playerID){
					document.getElementById('video_'+playerID).addEventListener('onStateChange','eventListener_'+playerID);
				}
			}
		},'jsonp');

		return elements.originalDIV;
	}

})(jQuery);
</pre>
<p>The event listening function we created in the previous section of the code, is attached to the player with the <strong>addEventListener</strong> method. It is called every time when a &#8220;<strong>stateChange</strong>&#8221; occurs (playback start, playback pause, end of playback etc). A numeric code is passed to the event listening function as a parameter, corresponding to the event.</p>
<p>Now lets take a look at how our plugin is used.</p>
<h4>script.js</h4>
<pre class="brush:js">$(document).ready(function(){

	$('#player').youTubeEmbed('http://www.youtube.com/watch?v=u1zgFlCw8Aw');

	/*
		//You can alternatively pass an object:

		$('#player').youTubeEmbed({
			video			: 'http://www.youtube.com/watch?v=u1zgFlCw8Aw',
			width			: 600, 		// Height is calculated automatically
			progressBar	: false		// Hide the progress bar
		});

	*/

});
</pre>
<p>You just need to call the <strong>youTubeEmbed()</strong> method and pass it either a string or a configuration object. If a string is passed, it is assumed to be the URL of a YouTube video. If you are passing an object make sure that you are passing the <strong>video </strong>property with a correct video URL.</p>
<div id="attachment_1033" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/07/youtube-api-custom-player-jquery-css/youtube-player.html"><img class="size-full wp-image-1033" title="Video Playing with a Progress Bar" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/07/i21.jpg" alt="Video Playing with a Progress Bar" width="620" height="460" /></a><p class="wp-caption-text">Video Playing with a Progress Bar</p></div>
<h3>Step 3 &#8211; CSS</h3>
<p>Finally we are left with applying a few CSS styles to the player. They will change the design of the player controls and define the way they are positioned in the player window.</p>
<h4>youTubeEmbed-jquery-1.0.css</h4>
<pre class="brush:css">.flashContainer{

	/*	Setting the container to relative positioning
		so we can center the control div */

	position:relative;
	overflow:hidden;
}

.progressBar{
	display:none;
	position:absolute;
	width:auto;
	height:8px;
	left:20px;
	right:105px;
	bottom:20px;
	background-color:#141414;
	overflow:hidden;
	cursor:pointer;

	/* A light CSS3 bottom highlight */

	-moz-box-shadow:0 1px 0 rgba(255, 255, 255, 0.3);
	-webkit-box-shadow:0 1px 0 rgba(255, 255, 255, 0.3);
	box-shadow:0 1px 0 rgba(255, 255, 255, 0.3);
}

.progressBar .elapsed{
	position:absolute;
	width:0;
	height:100%;
	background-color:#1fa2f6;
	border-right:1px solid #49AFF0;
}

.controlDiv{
	/* Centering the control div */
	position:absolute;
	width:120px;
	height:120px;
	cursor:pointer;
	top:50%;
	left:50%;
	margin:-60px 0 0 -60px;
}

.controlDiv.play{
	background:url('img/play.png') no-repeat center center;
}

.controlDiv.replay{
	background:url('img/replay.png') no-repeat center center;
}

.controlDiv.pause{
	background:url('img/pause.png') no-repeat -99999px;
}

.flashContainer:hover .controlDiv.pause{
	background-position:center center;
}

/* Only show the progress bar when the video is playing */

.flashContainer.playing:hover .progressBar{
	display:block;
}</pre>
<p>To customize the look of the player you just need to change the color values above. Also you can edit the png files with the play/pause buttons. Clearly this is much easier than modifying the looks of the default youtube player. It also strips all of the unnecessary chrome and leaves you with what matters most &#8211; your video.</p>
<p><strong>With this our Custom YouTube Player plugin is complete!</strong></p>
<p>Did you like this tutorial? Share your thoughts in the comment section below.</p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/07/youtube-api-custom-player-jquery-css/feed/</wfw:commentRss>
		<slash:comments>36</slash:comments>
		</item>
		<item>
		<title>Colortip &#8211; a jQuery Tooltip Plugin</title>
		<link>http://tutorialzine.com/2010/07/colortips-jquery-tooltip-plugin/</link>
		<comments>http://tutorialzine.com/2010/07/colortips-jquery-tooltip-plugin/#comments</comments>
		<pubDate>Wed, 14 Jul 2010 19:48:49 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=1019</guid>
		<description><![CDATA[In this tutorial we are going to write a simple jQuery tooltip plugin. It is going to convert the title attributes of elements withing your page, into a series of colorful tooltips.]]></description>
			<content:encoded><![CDATA[<p>In this tutorial we are going to write a simple jQuery tooltip plugin. It is going to convert the title attributes of elements withing your page, into a series of colorful tooltips. Six color themes are available, so you can easily match it with the rest of your design.</p>
<h3>Step 1 &#8211; XHTML</h3>
<p>The plugin we are about to write today, works by converting the title of an element on the page to a structure of three spans, which form a tooltip, displayed on hover. So if you start with a regular link like this one:</p>
<pre class="brush:html">&lt;a href="http://tutorialzine.com/" class="blue" title="Go to Tutorialzine"&gt;Tutorialzine&lt;/a&gt;</pre>
<p>jQuery will convert it to the markup you can see below.</p>
<pre class="brush:html">&lt;a class="blue colorTipContainer" href="http://tutorialzine.com/"&gt;Tutorialzine
&lt;span class="colorTip" style="margin-left: -60px;"&gt;Go to Tutorialzine
&lt;span class="pointyTipShadow"&gt;&lt;/span&gt;
&lt;span class="pointyTip"&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;/a&gt;</pre>
<p>Notice that the first block of code above specifies a &#8220;<strong>blue</strong>&#8221; class name. This  is because we are overriding the default color of the tip (yellow). You  can choose from <strong>red</strong>, <strong>blue</strong>, <strong>green</strong>, <strong>yellow</strong>, <strong>white </strong>and <strong>black</strong>, or you can  create your own colors in the plugin stylesheet.</p>
<p>Users which have JavaScript disabled are still going to see the regular title tooltips on the page, so the script degrades gracefully.</p>
<h3>Step 2 &#8211; CSS</h3>
<p>To display the colorful tips on your page, you first need to include the plugin stylesheet file in the head section of the html document.</p>
<pre class="brush:html">&lt;link rel="stylesheet" type="text/css" href="colortip-1.0/colortip-1.0-jquery.css"/&gt;</pre>
<p>You could also just copy the styles from the file and paste them directly in your main stylesheet, if you do not want to keep a separate include file. This stylesheet defines both the positioning and the design of the tooltips. It comes with six color themes, and you can easily add more.</p>
<h4>colortip-1.0-jquery.css &#8211; Part 1</h4>
<pre class="brush:css">.colorTipContainer{
	position:relative;
	text-decoration:none !important;
}

.colorTip{
	/* This class is assigned to the color tip span by jQuery */

	display:none;
	position:absolute;
	left:50%;
	top:-30px;
	padding:6px;

	background-color:white;
	font-family:Arial,Helvetica,sans-serif;
	font-size:11px;
	font-style:normal;
	line-height:1;
	text-decoration:none;
	text-align:center;
	text-shadow:0 0 1px white;
	white-space:nowrap;

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

.pointyTip,.pointyTipShadow{
	/* Setting a thick transparent border on a 0x0 div to create a triangle */
	border:6px solid transparent;
	bottom:-12px;
	height:0;
	left:50%;
	margin-left:-6px;
	position:absolute;
	width:0;
}

.pointyTipShadow{
	/* The shadow tip is 1px larger, so it acts as a border to the tip */
	border-width:7px;
	bottom:-14px;
	margin-left:-7px;
}</pre>
<p>The <strong>.colorTipContainer</strong> class is assigned to the elements to which the color tips are added. It sets their positioning to relative, so that the tips can be <a href="http://tutorialzine.com/2010/03/centering-div-vertically-and-horizontally/" target="_blank">centered</a> above them.</p>
<p>A neat CSS trick is used to create the triangular pointy tips. As  you know, divs and spans can only take a rectangular shape (or an ellipse / rounded rectangle if you apply border-radius). However, if you apply a thick border to a 0 by 0 element, the only way the borders are going to fit is to take up a triangular space on each side. Then, by setting the default border color to transparent, you can make visible any of the four triangular shapes.</p>
<div id="attachment_1023" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/07/colortips-jquery-tooltip-plugin/colortips.html"><img class="size-full wp-image-1023" title="Making a triangular shape with a div" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/07/i2.jpg" alt="Making a triangular shape with a div" width="620" height="260" /></a><p class="wp-caption-text">Making a triangular shape with a div</p></div>
<p>This is actually done on both the .<strong>pointyTip </strong>and the .<strong>pointyTipShadow </strong>spans, in order to give an impression that the pointy tip has a border applied so it matches the rest of the colortip design. Now lets take a closer look at the six color themes.</p>
<h4>colortip-1.0-jquery.css &#8211; Part 2</h4>
<pre class="brush:css">/* 6 Available Color Themes */

.white .pointyTip{ border-top-color:white;}
.white .pointyTipShadow{ border-top-color:#ddd;}
.white .colorTip{
	background-color:white;
	border:1px solid #DDDDDD;
	color:#555555;
}

.yellow .pointyTip{ border-top-color:#f9f2ba;}
.yellow .pointyTipShadow{ border-top-color:#e9d315;}
.yellow .colorTip{
	background-color:#f9f2ba;
	border:1px solid #e9d315;
	color:#5b5316;
}

.blue .pointyTip{ border-top-color:#d9f1fb;}
.blue .pointyTipShadow{ border-top-color:#7fcdee;}
.blue .colorTip{
	background-color:#d9f1fb;
	border:1px solid #7fcdee;
	color:#1b475a;
}

.green .pointyTip{ border-top-color:#f2fdf1;}
.green .pointyTipShadow{ border-top-color:#b6e184;}
.green .colorTip{
	background-color:#f2fdf1;
	border:1px solid #b6e184;
	color:#558221;
}

.red .pointyTip{ border-top-color:#bb3b1d;}
.red .pointyTipShadow{ border-top-color:#8f2a0f;}
.red .colorTip{
	background-color:#bb3b1d;
	border:1px solid #8f2a0f;
	color:#fcfcfc;
	text-shadow:none;
}

.black .pointyTip{ border-top-color:#333;}
.black .pointyTipShadow{ border-top-color:#111;}
.black .colorTip{
	background-color:#333;
	border:1px solid #111;
	color:#fcfcfc;
	text-shadow:none;
}</pre>
<p>Remember that only the borders are the only visible part of the pointy tips. You can add your own color themes by following the same structure.</p>
<h3>Step 3 &#8211; jQuery</h3>
<p>First you need to include the jquery library and the plugin files to the page, after which our script.js file, which is going to utilize the plugin and add colortips to the links on the page.</p>
<pre class="brush:html">&lt;script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="colortip-1.0/colortip-1.0-jquery.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="script.js"&gt;&lt;/script&gt;</pre>
<p>For performance reasons, I&#8217;ve put this code at the bottom of the <strong>colortips.html</strong> file. This allow for the page design to be rendered before the browser blocks for the loading of the js files.</p>
<p>Now lets take a look at the colortip the plugin.</p>
<h4>colortip-1.0-jquery.js &#8211; Part 1</h4>
<pre class="brush:js">(function($){
	$.fn.colorTip = function(settings){

		var defaultSettings = {
			color		: 'yellow',
			timeout		: 500
		}

		var supportedColors = ['red','green','blue','white','yellow','black'];

		/* Combining the default settings object with the supplied one */
		settings = $.extend(defaultSettings,settings);

		/*
		*	Looping through all the elements and returning them afterwards.
		*	This will add chainability to the plugin.
		*/

		return this.each(function(){

			var elem = $(this);

			// If the title attribute is empty, continue with the next element
			if(!elem.attr('title')) return true;

			// Creating new eventScheduler and Tip objects for this element.
			// (See the class definition at the bottom).

			var scheduleEvent = new eventScheduler();
			var tip = new Tip(elem.attr('title'));

			// Adding the tooltip markup to the element and
			// applying a special class:

			elem.append(tip.generate()).addClass('colorTipContainer');

			// Checking to see whether a supported color has been
			// set as a classname on the element.

			var hasClass = false;
			for(var i=0;i&lt;supportedColors.length;i++)
			{
				if(elem.hasClass(supportedColors[i])){
					hasClass = true;
					break;
				}
			}

			// If it has been set, it will override the default color

			if(!hasClass){
				elem.addClass(settings.color);
			}</pre>
<p>When you call the plugin, you can pass a configuration object, which holds the default color and the timeout after which the tooltips disappear on mouseleave.</p>
<p>You can choose from six possible colors and assign them as a class name to the element. The plugin would check if a color class is present, and if it is not, it will apply the default one you&#8217;ve passed in the config object. If you&#8217;ve not passed a config object, yellow will be used instead.</p>
<div id="attachment_1024" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/07/colortips-jquery-tooltip-plugin/colortips.html"><img class="size-full wp-image-1024" title="Colortip jQuery Plugin" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/07/i1.png" alt="Colortip jQuery Plugin" width="620" height="260" /></a><p class="wp-caption-text">Colortip jQuery Plugin</p></div>
<h4>colortip-1.0-jquery.js &#8211; Part 2</h4>
<pre class="brush:js">			// On mouseenter, show the tip, on mouseleave set the
			// tip to be hidden in half a second.

			elem.hover(function(){

				tip.show();

				// If the user moves away and hovers over the tip again,
				// clear the previously set event:

				scheduleEvent.clear();

			},function(){

				// Schedule event actualy sets a timeout (as you can
				// see from the class definition below).

				scheduleEvent.set(function(){
					tip.hide();
				},settings.timeout);

			});

			// Removing the title attribute, so the regular OS titles are
			// not shown along with the tooltips.

			elem.removeAttr('title');
		});

	}

	/*
	/	Event Scheduler Class Definition
	*/

	function eventScheduler(){}

	eventScheduler.prototype = {
		set	: function (func,timeout){

			// The set method takes a function and a time period (ms) as
			// parameters, and sets a timeout

			this.timer = setTimeout(func,timeout);
		},
		clear: function(){

			// The clear method clears the timeout

			clearTimeout(this.timer);
		}
	}</pre>
<p>In the second part of the plugin code, we bind event listeners to the hover event (combination of  a mouseenter and a mouseleave event).</p>
<p>Notice the event scheduler class. It is used to set a function to be executed after a predetermined period of time. At its heart lays a call to <strong> setTimeout</strong>. A <em><strong>clear()</strong></em> method is also provided as a part of the class, so previously scheduled events can be destroyed (useful when you move your mouse away from a tooltip and then move it back over before it has disappeared).</p>
<h4>colortip-1.0-jquery.js &#8211; Part 3</h4>
<pre class="brush:js">	/*
	/	Tip Class Definition
	*/

	function Tip(txt){
		this.content = txt;
		this.shown = false;
	}

	Tip.prototype = {
		generate: function(){

			// The generate() method returns either a previously generated element
			// stored in the tip variable, or generates and saves it in tip for
			// later use, after which returns it.

			return this.tip || (this.tip = $('&lt;span class="colorTip"&gt;'+this.content+
											 '&lt;span class="pointyTipShadow"&gt;&lt;/span&gt;&lt;span class="pointyTip"&gt;&lt;/span&gt;&lt;/span&gt;'));
		},
		show: function(){
			if(this.shown) return;

			// Center the tip and start a fadeIn animation
			this.tip.css('margin-left',-this.tip.outerWidth()/2).fadeIn('fast');
			this.shown = true;
		},
		hide: function(){
			this.tip.fadeOut();
			this.shown = false;
		}
	}

})(jQuery);</pre>
<p>In the last part of the code we define the tip class. It has a <strong>generate</strong>, <strong>show </strong>and <strong>hide </strong>methods. An object from this class is created for each of the tooltips. The generate method is called first, and the tooltip is stored in the local <strong>this.tip</strong> variable. The show and hide methods operate on this variable to run fade in/out animations.</p>
<p>Now we are only left with calling the plugin and adding colortips to all the links on the page.</p>
<h4>script.js</h4>
<pre class="brush:js">$(document).ready(function(){

	/* Adding a colortip to any tag with a title attribute: */

	$('[title]').colorTip({color:'yellow'});

});</pre>
<p>The configuration object here might as well be omitted, because yellow is the default value anyway. But you could specify a different color for the tooltips. If you apply <em>red,</em> <em>green,</em> <em>blue</em>, <em>white</em>, <em>yellow</em> or <em>black</em> as a class name of the element, the design of the tooltip will be overridden.</p>
<p><strong>With this our Colortip plugin is complete!</strong></p>
<h3>Wrapping it up</h3>
<p>Using the plugin we wrote today is really easy, as it does not require any specific configuration. It just takes a series of elements and replaces their title attributes with colorful tooltips. You can also easily create your own tooltip designs by just including three additional style classes to your stylesheet and adding an element to the supported colors array in <strong><em>colortip-1.0-jquery.js.</em></strong></p>
<p><strong>What do you think? How would you improve this plugin?<em><br />
</em></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/07/colortips-jquery-tooltip-plugin/feed/</wfw:commentRss>
		<slash:comments>41</slash:comments>
		</item>
		<item>
		<title>Making a Slick MobileApp Website with jQuery &amp; CSS</title>
		<link>http://tutorialzine.com/2010/07/making-slick-mobileapp-website-jquery-css/</link>
		<comments>http://tutorialzine.com/2010/07/making-slick-mobileapp-website-jquery-css/#comments</comments>
		<pubDate>Fri, 09 Jul 2010 15:47:53 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=1006</guid>
		<description><![CDATA[This time we are making a complete jQuery &#038; CSS website for a fictional mobile application. It is going to feature semantic markup and a progressively enhanced slideshow effect.]]></description>
			<content:encoded><![CDATA[<p>As a web developer, you have to bring creativity and attention to detail to your work. It is often the little things that leave a lasting impression to a visitor. Be it a lovable character illustration, or unique slideshow, it is usually not the information you present that is memorable, but the way you present it.</p>
<p>Today we are making a complete jQuery &amp; CSS website for a fictional mobile application. It is going to feature semantic markup and a progressively enhanced slideshow effect. It will allow the user to see four of the most popular smartphones running the mobile app.</p>
<h3>Step 1 &#8211; XHTML</h3>
<p>When building websites it is important that you lay your code in a semantic way. This would include using tags for what they were supposed to be used for. You should use headings for titles, paragraphs for text (instead of generic divs) and lists where applicable.</p>
<h4>mobileapp.html</h4>
<pre class="brush:html">&lt;div id="page"&gt;

    &lt;h1 id="logoh1"&gt;&lt;a href="/" id="logo"&gt;MobileApp - the most useful mobile app!&lt;/a&gt;&lt;/h1&gt;

    &lt;div id="phoneCarousel"&gt;
    	&lt;div class="previous arrow"&gt;&lt;/div&gt;
        &lt;div class="next arrow"&gt;&lt;/div&gt;

        &lt;div id="stage"&gt;
            &lt;img id="iphone" class="default" src="img/phones/iphone.png" width="270" height="400" alt="iPhone" /&gt;
            &lt;img id="nexus" src="img/phones/nexus_one.png" width="270" height="400" alt="Nexus One" /&gt;
            &lt;img id="nokia" src="img/phones/nokia.png" width="270" height="400" alt="Nokia" /&gt;
            &lt;img id="blackberry" src="img/phones/blackberry.png" width="270" height="400" alt="BlackBerry" /&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;img class="availableAppStore" src="img/available_on_the_appstore.png" width="230" height="80" alt="Available on the Appstore" /&gt;

    &lt;div class="text"&gt;
    	&lt;h3&gt;&lt;img src="img/thumb.png" alt="MobileApp" width="114" height="114" class="thumb" /&gt;A wonderful app&lt;/h3&gt;
        &lt;p&gt;Lorem ipsum dolor sit amet.. &lt;/p&gt;
    &lt;/div&gt;

    &lt;div class="text"&gt;
    	&lt;h3&gt;&lt;img src="img/thumb.png" alt="MobileApp" width="114" height="114" class="thumb" /&gt;More awesome facts&lt;/h3&gt;
        &lt;p&gt;Lorem ipsum dolor sit amet.. &lt;/p&gt;
    &lt;/div&gt;

&lt;/div&gt;</pre>
<p>This is all the markup that is used to display the website. The h1 heading holds a hyperlink which is styled as the logo (the logo image is set as the background of the hyperlink and a negative text indent is used to hide the text of the link).</p>
<p>After this we have the <strong>#phoneCarousel</strong> div and inside it are the arrows and the stage. The phone images inside the stage are rotated with jQuery as you will see in a moment.</p>
<p>Lastly we have the <em>Available on the Appstore</em> badge, and two blocks of text.</p>
<div id="attachment_1010" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/07/making-slick-mobileapp-website-jquery-css/mobileapp.html"><img class="size-full wp-image-1010" title="Slick MobileApp Website - Slideshow" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/07/i1.jpg" alt="Slick MobileApp Website - Slideshow" width="620" height="460" /></a><p class="wp-caption-text">Slick MobileApp Website - Slideshow</p></div>
<h3>Step 2 &#8211; CSS</h3>
<p>CSS is responsible for converting our semantic markup into a true website. Take a closer look at the <strong>#stage</strong> styles in the second part of the code, as these are what make the animation possible.</p>
<h4>styles.css &#8211; Part 1</h4>
<pre class="brush:css">body{
	font-size:14px;
	color:#515151;
	background:url('img/bg.png') repeat-x #f6f8f9;
	font-family:'Myriad Pro',Arial, Helvetica, sans-serif;
}

#logoh1{ margin:40px 0 0;}

#page{
	/* This the main container div */
	width:1000px;
	min-height:700px;
	margin:0 auto;
	background:url('img/bokeh.jpg') no-repeat 0 120px;
	position:relative;
	padding-top:1px;
}

#phoneCarousel{
	/*	This is the carousel section, it
		contains the stage and the arrows */
	height:390px;
	margin:90px auto 120px;
	position:relative;
	width:800px;
}

#phoneCarousel .arrow{
	/* The two arrows */
	width:44px;
	height:44px;
	background:url('img/arrows.png') no-repeat;
	position:absolute;
	top:50%;
	margin-top:-22px;
	left:0;
	cursor:pointer;
}

#phoneCarousel .next{
	/* Individual styles for the next icon */
	background-position:right top;
	left:auto;
	right:0;
}

/* Hover styles */

#phoneCarousel .arrow:hover{
	background-position:left bottom;
}

#phoneCarousel .next:hover{
	background-position:right bottom;
}</pre>
<p>After defining the  body styles we can move on to styling the <strong>#page</strong> div, which holds everything together. Its <a href="http://demo.tutorialzine.com/2010/07/making-slick-mobileapp-website-jquery-css/img/bokeh.jpg" target="_blank">background image</a> is offset 120px vertically, so it matches the background of the body, filling the full width of the page.</p>
<p>Next is the <strong>#phoneCarousel</strong> div. It has a relative positioning applied, so the stage (where all the animations take place) can be <a href="http://tutorialzine.com/2010/03/centering-div-vertically-and-horizontally/" target="_blank">properly centered</a>. The previous/next arrows are styled as well.</p>
<h4>styles.css &#8211; Part 2</h4>
<pre class="brush:css">#logo{
	background:url('img/logo.png') no-repeat;
	height:40px;
	text-indent:-9999px;
	width:210px;
	display:block;
}

#stage{
	/* The stage contains the animated phone images */
	left:50%;
	margin-left:-350px;
	position:absolute;
	width:700px;
	height:100%;
}

#stage img{
	/* Hiding all the images by default */
	display:none;
}

#stage .default{
	/*	This class is applied only to the iphone img by default
		and it is the only one visible if JS is disabled */
	display:block;
	left:50%;
	margin-left:-135px;
	position:absolute;
}

#stage .animationReady{
	/* This class is assigned to the images on load */
	display:block;
	position:absolute;
	top:0;
	left:0;
}

.text{	margin-top:70px;width:700px;}

.text p,
.text h3{
	padding-bottom:15px;
	line-height:1.4;
	text-align:justify;
}

.text h3{	font-size:30px;}
.text p{	font-size:20px;}

.thumb{	float:left;margin-right:40px;}

.availableAppStore{float:right;}</pre>
<p>In the second part of the stylesheet, we continue with the <strong>#stage</strong> styles. The phone pictures are hidden by default, so if JavaScript is disabled, the user is not left with a bunch of scattered images.</p>
<p>As you will see in the next step, the animation is achieved through changing the top and left CSS properties. For this to work, the images must be absolutely positioned. This is why the <strong>.animatonReady</strong> class is assigned on load with jQuery (if JS is disabled, this style would not be applied).</p>
<p>Lastly we style the text blocks, which explain details about our fictional MobileApp.</p>
<div id="attachment_1011" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/07/making-slick-mobileapp-website-jquery-css/mobileapp.html"><img class="size-full wp-image-1011" title="Text Blocks" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/07/i2.png" alt="Text Blocks" width="620" height="260" /></a><p class="wp-caption-text">Text Blocks</p></div>
<h3>Step 3 &#8211; jQuery</h3>
<p>When you click on one of the arrows, an animation starts, which uses sine and cosine calculations to move and scale down the images, creating the illusion of a circular movement. It is not as complicated as it sounds, as you can see for yourself from the code below.</p>
<h4>script.js</h4>
<pre class="brush:js">$(document).ready(function(){

	var deg=0;

	/* Storing all the images into a variable */

	var images	= $('#stage img').removeClass('default').addClass('animationReady');
	var dim		= { width:images.width(),height:images.height()};

	var cnt = images.length;

	/* Finding the centers of the animation container: */
	var centerX = $('#stage').width()/2;
	var centerY = $('#stage').height()/2 - dim.height/2;

	function rotate(step,total){
		// This function will loop through all the phone images, and rotate them
		// with "step" degrees (10 in this implementation) till total &gt; 0

		/* Increment the degrees: */
		deg+=step;

		var eSin,eCos,newWidth,newHeight,q;

		/* Loop through all the images: */
		for(var i=0;i&lt;cnt;i++){

			/* Calculate the sine and cosine for the i-th image */

			q = ((360/cnt)*i+deg)*Math.PI/180;
			eSin		= Math.sin(q);
			eCos		= Math.cos(q);

			/*
			/	With the sine value, we can calculate the vertical movement,
			/	and the cosine will give us the horizontal movement.
			*/

			q = (0.6+eSin*0.4);
			newWidth	= q*dim.width;
			newHeight	= q*dim.height;

			/*
			/	We are using the calculated sine value (which is in the range
			/	of -1 to 1) to calculate the opacity and z-index. The
 			/	frontmost image has a sine value of 1, while the backmost
			/	one has a sine value of -1.
			*/

			// eq() extracts the image at the i-th position:

			images.eq(i).css({
				top			: centerY+15*eSin,
				left		: centerX+200*eCos,
				opacity		: 0.8+eSin*0.2,
				marginLeft	: -newWidth/2,
				zIndex		: Math.round(80+eSin*20)
			}).width(newWidth).height(newHeight);
		}

		total-=Math.abs(step);
		if(total&lt;=0) return false;

		// Setting the function to be run again in 40 milliseconds (equals to 25 frames per second):
		setTimeout(function(){rotate(step,total)},40);

	}

	// Running the animation once at load time (and moving the iPhone into view):
	rotate(10,360/cnt);

	$('#phoneCarousel .previous').click(function(){
		// 360/cnt lets us distribute the phones evenly in a circle
		rotate(-10,360/cnt);
	});

	$('#phoneCarousel .next').click(function(){
		rotate(10,360/cnt);
	});
});</pre>
<p>To start an animation you just need to call the <strong>rotate</strong> function with two arguments &#8211; a step, and a total rotation, both of which are numbers. Step can be negative, which would mean that the rotation is run in the opposite way. Each time the function is run, total is decremented with the absolute value of the step, and once it reaches zero the animation is stopped.</p>
<p>In a number of places in this code, you can see that I&#8217;ve used a specific calculation &#8211; <strong>360/cnt</strong>. This is done to distribute the phones evenly (360 being the number of degrees in a circle).  This way you can add or remove images and they will be properly animated.</p>
<div id="attachment_1012" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/07/making-slick-mobileapp-website-jquery-css/mobileapp.html"><img class="size-full wp-image-1012" title="Slick MobileApp Website" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/07/i3.jpg" alt="Slick MobileApp Website" width="620" height="260" /></a><p class="wp-caption-text">Slick MobileApp Website</p></div>
<p><strong>With this our Slick MobleApp Website is complete!</strong></p>
<h3>Wrapping it up</h3>
<p>Today we made a complete jQuery &amp; CSS website for a fictional  mobile application. You are free to modify the code and use it any way you see fit. If you liked the tutorial be sure to subscribe to our <a href="http://feeds.feedburner.com/Tutorialzine" target="_blank">RSS feed</a>, <a href="http://twitter.com/Tutorialzine">follow us on twitter</a>, or leave a comment in the section below.</p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/07/making-slick-mobileapp-website-jquery-css/feed/</wfw:commentRss>
		<slash:comments>20</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://cdn.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"]).
				'http://cdn.tutorialzine.com/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://cdn.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>52</slash:comments>
		</item>
		<item>
		<title>CSS3 Minimalistic Navigation Menu</title>
		<link>http://tutorialzine.com/2010/06/css3-minimalistic-navigation-menu/</link>
		<comments>http://tutorialzine.com/2010/06/css3-minimalistic-navigation-menu/#comments</comments>
		<pubDate>Fri, 25 Jun 2010 13:03:04 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=981</guid>
		<description><![CDATA[Today we are making something practical - a simple CSS3 animated navigation menu, which degrades gracefully and is future-proofed to work with the next generation of browsers.]]></description>
			<content:encoded><![CDATA[<p>As you have probably heard by now, CSS3 animations are a powerful tool, which enables you to create  animations which run without the need of applying additional scripting to the page. What is even better, in the next generation of browsers we will have even more powerful tools, including 3D transformations (already present in  Safari).</p>
<p>But what difference does it make for us <em><strong>today</strong></em>? At the moment only three browsers give you the ability to animate CSS properties &#8211; Chrome, Safari and Opera, which together take up only a small part of the browser market. Firefox is expected to soon join the club, and with the impending release of IE9, it suddenly makes sense to start leveraging this technique.</p>
<p>So today we are making something practical &#8211; a simple CSS3 animated navigation menu, which degrades gracefully in older browsers and is future-proofed to work with the next generation of browsers.</p>
<h3>The XHTML</h3>
<p>The menu is organized as an unordered list. This is the most suitable  structure for a menu, as it provides an easy way to style the menu links  and is semantically correct.</p>
<h4>demo.html</h4>
<pre class="brush:html">&lt;ul id="navigationMenu"&gt;
    &lt;li&gt;
	    &lt;a class="home" href="#"&gt;
            &lt;span&gt;Home&lt;/span&gt;
        &lt;/a&gt;
    &lt;/li&gt;

    &lt;li&gt;
    	&lt;a class="about" href="#"&gt;
            &lt;span&gt;About&lt;/span&gt;
        &lt;/a&gt;
    &lt;/li&gt;

    &lt;li&gt;
	     &lt;a class="services" href="#"&gt;
            &lt;span&gt;Services&lt;/span&gt;
         &lt;/a&gt;
    &lt;/li&gt;

    &lt;li&gt;
    	&lt;a class="portfolio" href="#"&gt;
            &lt;span&gt;Portfolio&lt;/span&gt;
        &lt;/a&gt;
    &lt;/li&gt;

    &lt;li&gt;
    	&lt;a class="contact" href="#"&gt;
            &lt;span&gt;Contact us&lt;/span&gt;
        &lt;/a&gt;
    &lt;/li&gt;
&lt;/ul&gt;</pre>
<p>Inside each li we have a <strong>hyperlink </strong>with a <strong>span </strong>inside it.  By default these spans are hidden, and are only shown when you hover over the link. Each link has a <strong>unique class name</strong>, which is used to give it a unique background and style the inner span, as you will see in a moment.</p>
<div id="attachment_984" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/06/css3-minimalistic-navigation-menu/demo.html"><img class="size-full wp-image-984" title="CSS3 Animated Navigation Menu" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/06/i12.png" alt="CSS3 Animated Navigation Menu" width="620" height="260" /></a><p class="wp-caption-text">CSS3 Animated Navigation Menu</p></div>
<h3>The CSS</h3>
<p>Once we have the basic structure in place, we can now move to creating the fancy CSS3 effects and styling. This works even on browsers, which do not support CSS3 <em>transition animations</em> (all browsers except <em>Chrome, </em><em>Safari </em>and<em> Opera, </em>at the moment of this writing) albeit with less glitter. The menu is even perfectly usable in browsers as old as IE6.</p>
<h4>styles.css &#8211; Part 1</h4>
<pre class="brush:css">*{
	/* A universal CSS reset */
	margin:0;
	padding:0;
}

body{
	font-size:14px;
	color:#666;
	background:#111 no-repeat;

	/* CSS3 Radial Gradients */
	background-image:-moz-radial-gradient(center -100px 45deg, circle farthest-corner, #444 150px, #111 300px);
	background-image:-webkit-gradient(radial, 50% 0, 150, 50% 0, 300, from(#444), to(#111));

	font-family:Arial, Helvetica, sans-serif;
}

#navigationMenu li{
	list-style:none;
	height:39px;
	padding:2px;
	width:40px;
}</pre>
<p>For the styling of the body background, I first supplied a background color, which acts as a fallback, and then added two CSS3 radial gradients (for Firefox and Chrome/Safari respectfully) as background images. If the visitor&#8217;s browser does not support gradients, it will just ignore the rules and go with the plain background color.</p>
<p>You can see in the styles, that most of the rules are preceded by the id of the unordered list &#8211; <strong>#navigationMenu</strong>. This is to prevent collisions with the rest of your page styles, if you incorporate the menu into your site.</p>
<h4>styles.css &#8211; Part 2</h4>
<pre class="brush:css">#navigationMenu span{
	/* Container properties */
	width:0;
	left:38px;
	padding:0;
	position:absolute;
	overflow:hidden;

	/* Text properties */
	font-family:'Myriad Pro',Arial, Helvetica, sans-serif;
	font-size:18px;
	font-weight:bold;
	letter-spacing:0.6px;
	white-space:nowrap;
	line-height:39px;

	/* CSS3 Transition: */
	-webkit-transition: 0.25s;

	/* Future proofing (these do not work yet): */
	-moz-transition: 0.25s;
	transition: 0.25s;
}

#navigationMenu a{
	/* The background sprite: */
	background:url('img/navigation.jpg') no-repeat;

	height:39px;
	width:38px;
	display:block;
	position:relative;
}

/* General hover styles */

#navigationMenu a:hover span{ width:auto; padding:0 20px;overflow:visible; }
#navigationMenu a:hover{
	text-decoration:none;

	/* CSS outer glow with the box-shadow property */
	-moz-box-shadow:0 0 5px #9ddff5;
	-webkit-box-shadow:0 0 5px #9ddff5;
	box-shadow:0 0 5px #9ddff5;
}
</pre>
<p>The <strong>CSS3 transition</strong> property is  a really powerful one. It enables you to animate changes that occur on a element when a pseudo properties take effect. For example here, when the user moves their mouse over a navigation link, the <em>:hover</em> pseudo-property takes effect, showing the span which is otherwise hidden.</p>
<p>Without the definition of a transition property, this change is instantaneous. But with a transition we can animate it. Here we are telling the browser, that the duration of the animation is 250 milliseconds. You can optionally specify a list of specific properties to be animated instead of all of them.</p>
<p>Transitions are currently only supported in <em>webkit </em>based browsers (<em>Safari </em>and <em>Chrome</em>), but the next version of Firefox is also expected to support them, so we future-proof the script by specifying a <em>-moz-transition</em>.</p>
<div id="attachment_985" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/06/css3-minimalistic-navigation-menu/demo.html"><img class="size-full wp-image-985" title="The CSS3 Transition" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/06/i22.png" alt="The CSS3 Transition" width="620" height="260" /></a><p class="wp-caption-text">The CSS3 Transition</p></div>
<h4>styles.css &#8211; Part 3</h4>
<pre class="brush:css">/* Green Button */

#navigationMenu .home {	background-position:0 0;}
#navigationMenu .home:hover {	background-position:0 -39px;}
#navigationMenu .home span{
	background-color:#7da315;
	color:#3d4f0c;
	text-shadow:1px 1px 0 #99bf31;
}

/* Blue Button */

#navigationMenu .about { background-position:-38px 0;}
#navigationMenu .about:hover { background-position:-38px -39px;}
#navigationMenu .about span{
	background-color:#1e8bb4;
	color:#223a44;
	text-shadow:1px 1px 0 #44a8d0;
}

/* Orange Button */

#navigationMenu .services { background-position:-76px 0;}
#navigationMenu .services:hover { background-position:-76px -39px;}
#navigationMenu .services span{
	background-color:#c86c1f;
	color:#5a3517;
	text-shadow:1px 1px 0 #d28344;
}

/* Yellow Button */

#navigationMenu .portfolio { background-position:-114px 0;}
#navigationMenu .portfolio:hover{ background-position:-114px -39px;}
#navigationMenu .portfolio span{
	background-color:#d0a525;
	color:#604e18;
	text-shadow:1px 1px 0 #d8b54b;
}

/* Purple Button */

#navigationMenu .contact { background-position:-152px 0;}
#navigationMenu .contact:hover { background-position:-152px -39px;}
#navigationMenu .contact span{
	background-color:#af1e83;
	color:#460f35;
	text-shadow:1px 1px 0 #d244a6;
}</pre>
<p>In the last part of the styling, we specify 5 different designs for the navigation links. All the background images for the links are contained inside a single sprite file. They have a normal and a hover state one under another. When a hover occurs, the background is offset to show the appropriate version of the background image.</p>
<p>A PSD file is included in the downloadable archive, so you can customize the images as much as you like.</p>
<p><strong>With this our minimalistic CSS3 navigation menu is complete!</strong></p>
<h3>Conclusion</h3>
<p>Sooner or later, we are going to have a quick access to powerful, hardware accelerated graphics, right in the browser. When this day comes, a whole new world will open to web developers, and we will come even closer to building rich internet applications, which behave exactly like native apps.</p>
<p>Till then, we have to make the best with what we have, and slowly start adopting CSS3 techniques into our work.</p>
<p><strong>What do you think? How would you improve this navigation menu?</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/06/css3-minimalistic-navigation-menu/feed/</wfw:commentRss>
		<slash:comments>26</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)
Content Delivery Network via cdn.tutorialzine.com

Served from: tutorialzine.com @ 2010-09-02 22:58:17 -->