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

<channel>
	<title>Tutorialzine &#187; PHP</title>
	<atom:link href="http://tutorialzine.com/category/tutorials/php-tutorials/feed/" rel="self" type="application/rss+xml" />
	<link>http://tutorialzine.com</link>
	<description>Web Development Tutorials &#38; Resources</description>
	<lastBuildDate>Wed, 01 Feb 2012 14:50:22 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Question of the Day with CodeIgniter and MySQL</title>
		<link>http://tutorialzine.com/2012/01/question-of-the-day-codeigniter-php-mysql/</link>
		<comments>http://tutorialzine.com/2012/01/question-of-the-day-codeigniter-php-mysql/#comments</comments>
		<pubDate>Thu, 19 Jan 2012 19:30:12 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=1801</guid>
		<description><![CDATA[<div><a href="http://tutorialzine.com/2012/01/question-of-the-day-codeigniter-php-mysql/"><img src="http://cdn.tutorialzine.com/img/featured/1801.jpg" /></a></div> In this tutorial we will build a small application with CodeIgniter that will be backed by a MySQL database. It will present questions and give visitors the ability to post answers.]]></description>
			<content:encoded><![CDATA[<div><a href="http://tutorialzine.com/2012/01/question-of-the-day-codeigniter-php-mysql/"><img src="http://cdn.tutorialzine.com/img/featured/1801.jpg" /></a></div> <p>In this tutorial we will build a small application with CodeIgniter that will be backed by a MySQL database. It will present questions and give visitors the ability to post answers. There isn&#8217;t an admin interface for adding or changing questions, but if you follow and understand this tutorial, you will be able to create one yourself.</p>
<p>As this might be the first exposure to CodeIgniter for some of you, we will start with a brief intro. If you know what CI is, you can skip directly to the code.</p>
<h3>First, what is CodeIgniter?</h3>
<p><a href="http://codeigniter.com/" target="_blank">CodeIgniter</a> is a framework for developing web applications in PHP. It will help you properly organize your code using the model-view-controller (MVC) pattern, and give you useful functionality for getting your site up and running quickly. It hides away the tedious work like building and validating forms, communicating with a database, managing error pages and much more.</p>
<p>There are certainly a lot of frameworks to choose from, but CI has the winning combination of a big community, nice documentation and good performance. Unless you enjoy spending time building sites from scratch (which is not a bad thing), using a framework is the smarter way to go.</p>
<p>You should probably start by reading the <a href="http://codeigniter.com/user_guide/overview/getting_started.html" target="_blank">CodeIgniter introductory guide</a>, which will give you a better understanding of how CI works. Of course, if you are experienced with PHP you can grab the zip and jump directly to the code.</p>
<p><strong>Let&#8217;s begin!</strong></p>
<h3>The database</h3>
<p>Naturally, we will need a table for the questions, and a table for the answers.</p>
<div id="attachment_1809" class="wp-caption alignnone" style="width: 630px"><img class="size-full wp-image-1809" title="The Database Schema" src="http://cdn.tutorialzine.com/wp-content/uploads/2012/01/database_schema.jpg" alt="The Database Schema" width="620" height="460" /><p class="wp-caption-text">The Database Schema</p></div>
<p>The questions table has only two fields &#8211; the <strong>ID</strong> of the question (automatically assigned with auto_increment) and the <strong>question</strong> body field. The answers also have an ID column, but they also have a <strong>qid</strong> field for the id of the question they relate to. The rest of the fields are the email and name of the author, along with the answer body and a timestamp (the dt field).</p>
<p>It is possible to create these tables with PHP code (CI gives us the ability to manipulate tables), but we will keep things simple and design them using a database management system like <em>phpMyAdmin</em>. It is even simpler for you, as I&#8217;ve included an export of the tables as an SQL file (<strong>tables.sql</strong> in the download archive). Import it into your database or copy/paste the code into the SQL tab of phpMyAdmin and you should be ready to go.</p>
<h3>Setting up CodeIgniter</h3>
<p>At this point you should <a href="http://codeigniter.com/downloads/" target="_blank">download CodeIgniter</a>. In this tutorial I am using version 2.1.0, the latest at the time of writing. Extract it in the directory where you are developing your website (move the files outside the CodeIgniter_2.1.0 folder and remove it). We will need to edit a few settings so the framework works the way we want it.</p>
<blockquote class="note"><p><strong>Important</strong><strong>:</strong> This section assumes that you are downloading a fresh copy of CodeIgniter. If you only want to make the downloaded demo work, you will only need to change your $config['base_url'] setting in config.php, and add your MySQL login details to database.php. The other changes are already made (you still need to create the MySQL tables).</p></blockquote>
<h4>Edit routes.php</h4>
<p>The application/config/routes.php file determines which controller is called by default. We need to set this to <strong>questions</strong>, which we will be creating in a moment.</p>
<pre class="brush:php">// Find this line:
$route['default_controller'] = "welcome";
// Replace it with this:
$route['default_controller'] = "questions";</pre>
<p>This will show the questions controller as the start page of the application.</p>
<h4>Edit config.php</h4>
<p>The application/config/config.php file holds much of the configuration settings of the framework.</p>
<pre class="brush:php">// Find this line:
$config['base_url'] = '';
// Replace it with the following:
$config['base_url']	= 'http://example.com/';</pre>
<p>The above setting, <strong>base_url</strong>, tells CI where your site is located. This information is used when forming links and including resources like stylesheets and images.</p>
<p>The following setting is optional. CodeIgniter adds index.php to every URL by default (like so: http://example.com/index.php/products/). If you want to hide it (so that the url becomes http://example.com/products/), you will need to edit the <strong>index_page</strong> setting:</p>
<pre class="brush:php">// Find this line:
$config['index_page'] = 'index.php';
// Replace it with the following:
$config['index_page'] = '';</pre>
<p>You will also need to create an <strong>.htaccess</strong> file, which rewrites the URLs so that they still get to index.php, although it is not included explicitly. The .htaccess I use in the demo follows:</p>
<h4>.htaccess</h4>
<pre class="brush:plain">Options +FollowSymLinks
Options +Indexes
RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteCond $1 !^(index\.php)
RewriteRule ^(.*)$ index.php/$1 [L]</pre>
<p>Now you only need to add your MySQL connection settings so that your application can connect to your database.</p>
<h4>Edit database.php</h4>
<p>Find these four lines in application/config/database.php and change them to reflect your connection settings:</p>
<pre class="brush:php">$db['default']['hostname'] = 'localhost';
$db['default']['username'] = 'user';
$db['default']['password'] = 'pass';
$db['default']['database'] = 'your_database_name';</pre>
<p>Great! We are done setting up CodeIgniter, so we can now move on with the code.</p>
<div id="attachment_1813" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2012/01/question-of-the-day-codeigniter-php-mysql/"><img class="size-full wp-image-1813" title="Question of the Day with CodeIgniter" src="http://cdn.tutorialzine.com/wp-content/uploads/2012/01/comments.jpg" alt="Question of the Day with CodeIgniter" width="620" height="460" /></a><p class="wp-caption-text">Question of the Day with CodeIgniter</p></div>
<h3>Showing the questions</h3>
<p>To show the questions we will need to create two files &#8211; a controller, which will be called when we visit the <strong>/question/</strong> URL, and a view, which outputs the HTML code of the page. The controller will handle selecting records from the database and passing them to view. Note that we are not using any models in this app (the M in MVC). For simple applications like this one, they are purely optional and you can write CI apps without them.</p>
<h4>/application/controllers/questions.php</h4>
<pre class="brush:php">if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Questions extends CI_Controller {

	public function index(){

		// Loading only the libraries and helpers that we need.
		// This is one of the things that make CI fast.

		$this-&gt;load-&gt;database();
		$this-&gt;load-&gt;helper(array('date','url'));

		// Get the id of the last question

		$res = $this-&gt;db-&gt;
				select_max('id')-&gt;
				get('qod_questions')-&gt;
				result_array();

		$id = $res[0]['id'];

		$this-&gt;show($id);
	}

	public function show($id = -1){

		$this-&gt;load-&gt;database();
		$this-&gt;load-&gt;helper(array('date','url'));

		// Select the question

		$q = $this-&gt;db-&gt;
				where(array('id'=&gt;$id))-&gt;
				get('qod_questions')-&gt;
				result_array();

		if(empty($q)){
			// Show an error page
			show_404();
		}

		$a = $this-&gt;db-&gt;
				where(array('qid'=&gt;$id))-&gt;
				order_by('id','desc')-&gt;
				get('qod_answers')-&gt;
				result_array();

		// Get the ids of the previous
		// and next questions

		$prev = 0;
		$next = 0;

		$res = $this-&gt;db-&gt;
				select_min('id')-&gt;
				where("id &gt; $id")-&gt;
				get('qod_questions')-&gt;
				result_array();

		if(!empty($res)){
			$next = $res[0]['id'];
		}

		$res = $this-&gt;db-&gt;
				select_max('id')-&gt;
				where("id &lt; $id")-&gt;
				get('qod_questions')-&gt;
				result_array();

		if(!empty($res)){
			$prev = $res[0]['id'];
		}

		$this-&gt;load-&gt;view('question_of_the_day',array(
			'question'	=&gt; $q[0]['question'],
			'answers'	=&gt; $a,
			'previous'	=&gt; $prev,
			'next'		=&gt; $next,
			'id'		=&gt; $id
		));
	}
}</pre>
<p>The controller is basically a class that extends <strong>CI_Controller</strong> and resides in the <em>controllers</em> folder. The class methods are called by the framework depending on the URL. For example http://example.com/questions/ will execute the <em>index</em> method, and http://example.com/questions/show/213 &#8211; the <em>show</em> method. In the latter case, 213 will be passed as the id parameter.</p>
<p>In the <strong>show</strong> method we select the question with the passed ID and display it in the view. What the <strong>index</strong> method does, is to select the id of the newest question, and also call the show method. Because it is set as the default controller, this would mean that when you visit the start page of the application (the base url you set in the previous section), the latest question will be shown.</p>
<blockquote class="note"><p>Read more about the <a href="http://codeigniter.com/user_guide/general/urls.html" target="_blank">URLs</a>, <a href="http://codeigniter.com/user_guide/general/controllers.html" target="_blank">controllers</a>, <a href="http://codeigniter.com/user_guide/general/views.html" target="_blank">views</a>, <a href="http://codeigniter.com/user_guide/general/helpers.html" target="_blank">helpers</a> and the <a href="http://codeigniter.com/user_guide/database/examples.html" target="_blank">database class</a> of CodeIgniter in the docs.</p></blockquote>
<p>Now let&#8217;s see how the view works. When we load it, we pass an array. Each of the array keys (<em>question</em>, <em>answers</em>, <em>previous</em>, <em>next</em> and <em>id</em>) will be extracted and transformed into a variable. Instead of a class, the view is a simple PHP file.</p>
<h4>/application/views/question_of_the_day.php</h4>
<pre class="brush:html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;meta charset="utf-8" /&gt;
        &lt;title&gt;&lt;?php echo $question?&gt; - Question of the day | Tutorialzine Demo&lt;/title&gt;

        &lt;!-- Our CSS stylesheet file --&gt;
        &lt;link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Rancho" /&gt;
        &lt;link rel="stylesheet" href="&lt;?php echo base_url()?&gt;assets/css/styles.css" /&gt;

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

    &lt;body&gt;

		&lt;header id="blackboard"&gt;
			&lt;h1&gt;&lt;?php echo $question?&gt;&lt;/h1&gt;
			&lt;?php if($previous) echo anchor("questions/show/$previous",'&amp;laquo;','class="arrow left"')?&gt;
			&lt;?php if($next) echo anchor("questions/show/$next",'&amp;raquo;','class="arrow right"')?&gt;
		&lt;/header&gt;

		&lt;?php 

		// This method will create a link to the answer form. It is given relative
		// to your index page, but will be transformed depending on your base in config.php

		echo anchor("answers/add/$id",'Add your answer','class="addAnswer"');

		?&gt;

		&lt;ul id="answers"&gt;

		&lt;?php foreach ($answers as $ans): ?&gt;

			&lt;li&gt;
				&lt;?php
					// Forming the URL of the gravatar image.
					$gravatar = 'http://www.gravatar.com/avatar/'.md5( strtolower( trim($ans['email']) ) ).'?d=mm';
				?&gt;

				&lt;span class="avatar" style="background-image:url(&lt;?php echo $gravatar?&gt;)"&gt;&lt;/span&gt;
				&lt;span class="meta"&gt;
					&lt;a href="#" class="author"&gt;&lt;?php echo $ans['name']?&gt;&lt;/a&gt;
					&lt;?php
						// We are using the built-in timestamp method. We are using
						// array slice to limit the shown time divisions.
						$ts = explode(',', timespan(strtotime($ans['dt'])));
						$t = implode(',',array_slice($ts,0,2));
					?&gt;
					&lt;i&gt;&lt;?php echo $t?&gt; ago&lt;/i&gt;
				&lt;/span&gt;
				&lt;p class="answer"&gt;&lt;?php echo $ans['answer']?&gt;&lt;/p&gt;
			&lt;/li&gt;

		&lt;?php endforeach; ?&gt;

		&lt;/ul&gt;

    &lt;/body&gt;
&lt;/html&gt;</pre>
<p>The script loops through the <strong>$answers</strong> array and outputs a li element for each answer. It <a href="http://en.gravatar.com/site/implement/hash/" target="_blank">assembles a gravatar URL</a> by generating an md5 hash of the email and includes it as the background-image of a rounded span element.</p>
<p>This gives us a functional answer browsing page. But how do we let people answer these questions?</p>
<div id="attachment_1814" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2012/01/question-of-the-day-codeigniter-php-mysql/"><img class="size-full wp-image-1814" title="The Blackboard" src="http://cdn.tutorialzine.com/wp-content/uploads/2012/01/the-blackboard.jpg" alt="The Blackboard" width="620" height="260" /></a><p class="wp-caption-text">The Blackboard</p></div>
<h3>Posting answers</h3>
<p>We will again need to write a controller and a view for adding answers. Here we will use a few more of the neat CodeIgniter features &#8211; generating forms and validating them. The generation is handled by the <a href="http://codeigniter.com/user_guide/helpers/form_helper.html" target="_blank">form helper</a>, and the validation &#8211; by the <a href="http://codeigniter.com/user_guide/libraries/form_validation.html" target="_blank">form validation class</a>.</p>
<p>You can see the <strong>answers</strong> controller below.</p>
<h4>/application/controllers/answers.php</h4>
<pre class="brush:php">if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Answers extends CI_Controller {

	public function add($id = -1){

		$this-&gt;load-&gt;database();
		$this-&gt;load-&gt;helper(array('url','form'));
		$this-&gt;load-&gt;library('form_validation');

		// Check if there is such a question

		$q = $this-&gt;db-&gt;
				where(array('id'=&gt;$id))-&gt;
				get('qod_questions')-&gt;
				result_array();

		if(empty($q)){
			// Show an error page
			show_404();
		}

		// Adding validation rules.

		$this-&gt;form_validation-&gt;set_rules('name', 'Name', 'required|min_length[2]|max_length[32]');
		$this-&gt;form_validation-&gt;set_rules('email', 'Email', 'required|valid_email');
		$this-&gt;form_validation-&gt;set_rules('answer', 'Answer', 'required|min_length[5]|max_length[255]');

		// If there are errors, show the form
		if ($this-&gt;form_validation-&gt;run() == FALSE){

			$this-&gt;load-&gt;view('add_answer',array(
				'question'	=&gt; $q[0]['question'],
				'qid'		=&gt; $q[0]['id']
			));

		}
		else{

			// Otherwise insert the answer to the database

			$this-&gt;db-&gt;insert('qod_answers', array(
				'qid'	=&gt; $q[0]['id'],
				'email'	=&gt; htmlspecialchars($this-&gt;input-&gt;post('email')),
				'name'	=&gt; htmlspecialchars($this-&gt;input-&gt;post('name')),

				// preserving new lines:
				'answer'=&gt; nl2br(htmlspecialchars($this-&gt;input-&gt;post('answer')))
			));

			redirect('questions/show/'.$q[0]['id']);
		}

	}
}</pre>
<p>With the help of the form validation class, we are able to add rules by which the data should be validated. We will insert the answer in the database only when presented with correct data. I am using the <code>htmlspecialchars()</code> PHP function to escape any HTML code that might have been typed in the form fields. When the answer is inserted, we redirect to the question page. If everything went as it should, the newly added answer should be at the top.</p>
<p>Equally interesting is how the answer form is generated. For this we will take a look at the view file.</p>
<h4>/application/views/add_answer.php</h4>
<pre class="brush:html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;meta charset="utf-8" /&gt;
        &lt;title&gt;&lt;?php echo $question?&gt; - Add Answer | Tutorialzine Demo&lt;/title&gt;

        &lt;!-- Our CSS stylesheet file --&gt;
        &lt;link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Rancho" /&gt;
        &lt;link rel="stylesheet" href="&lt;?php echo base_url()?&gt;assets/css/styles.css" /&gt;

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

    &lt;body&gt;

		&lt;header id="blackboard"&gt;
			&lt;h1&gt;&lt;?php echo $question?&gt;&lt;/h1&gt;
		&lt;/header&gt;

		&lt;?php 

		// This will print a link to the question page
		echo anchor("questions/show/$qid",'Back to the question','class="addAnswer"');

		// Creating the form using the form helper

		echo form_open('');

		echo form_label('Name','name');
		echo form_input(array(
          'name'        =&gt; 'name',
          'id'          =&gt; 'name',
          'value'       =&gt; set_value('name'),
          'maxlength'   =&gt; '64'
        ));

		echo form_label('Email (gravatar enabled)','email');
		echo form_input(array(
          'name'        =&gt; 'email',
          'id'          =&gt; 'email',
          'value'       =&gt; set_value('email'),
          'maxlength'   =&gt; '128'
        ));

		echo form_label('Answer','answer');
		echo form_textarea(array(
          'name'        =&gt; 'answer',
          'id'          =&gt; 'answer',
          'value'       =&gt; set_value('answer'),
        ));

		echo form_submit('subm', 'Add Answer!'); 

		// Showing the validation errors
		$validation = validation_errors(); 

		if($validation):
		?&gt;
			&lt;div class="errorMessages"&gt;
				&lt;?php echo $validation?&gt;
			&lt;/div&gt;

		&lt;?php endif;?&gt;

		&lt;?php echo form_close()?&gt;

    &lt;/body&gt;
&lt;/html&gt;</pre>
<p>As we included the form helper in the controller, we have access to all of its functions here, in the view. These functions make it easier to create forms and form fields. Of course, you can directly write the HTML of the forms, but you will have to update the code if you change the URL of your site.</p>
<p>At the bottom of the file we are accessing the <code>validate_errors()</code> function which will return a string with error messages, generated by the validation class. If there are any errors, we show them in a <em>.errorMessages</em> div.</p>
<p>That is it! All that is left is to add a pretty stylesheet and some images.</p>
<h3>The styling</h3>
<p>To finish this application, we need to add a stylesheet and images. Where we put them is more a matter of personal preference. I have chosen to go with an <strong>assets</strong> folder in the base directory of the application (you can see it in the zip file).</p>
<p>In the views I have specified the URL of the stylesheet like this: <code>&lt;?php echo base_url()?&gt;assets/css/styles.css</code> which gives us the correct location. <code>base_url()</code> is a function defined in the <a href="http://codeigniter.com/user_guide/helpers/url_helper.html" target="_blank">URL helper</a> of the framework, which we&#8217;ve included in the controller.</p>
<p>As the tutorial is already quite lengthy, I won&#8217;t be discussing the styling here. You can see it for yourself by opening /assets/css/styles.css in your code editor.</p>
<h3>We&#8217;re done!</h3>
<p>I am hoping that you learned a lot in this tutorial. If you decide to go with CodeIgniter for your next website, it will be a useful experience for you. Although there is a learning curve, once you understand the basics, you will appreciate just how much time you can save. And with <a href="http://getsparks.org/" target="_blank">Sparks</a>, you will become even more productive by adding easy to use open source modules to your projects.</p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2012/01/question-of-the-day-codeigniter-php-mysql/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Lets Write Some Tests with Testify.php</title>
		<link>http://tutorialzine.com/2011/11/lets-write-some-tests-testify-php/</link>
		<comments>http://tutorialzine.com/2011/11/lets-write-some-tests-testify-php/#comments</comments>
		<pubDate>Sat, 19 Nov 2011 17:23:39 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=1674</guid>
		<description><![CDATA[<div><a href="http://tutorialzine.com/2011/11/lets-write-some-tests-testify-php/"><img src="http://cdn.tutorialzine.com/img/featured/1674.jpg" /></a></div> In this tutorial you will learn how to test your code with Testify - a new open source framework for PHP with elegant syntax.]]></description>
			<content:encoded><![CDATA[<div><a href="http://tutorialzine.com/2011/11/lets-write-some-tests-testify-php/"><img src="http://cdn.tutorialzine.com/img/featured/1674.jpg" /></a></div> <p>If you have only recently started out with web development, testing your code is probably not very high on your list. You write something that does what you need to, refresh your browser, and quickly find out if it works or not. Testing is more of a chore than anything else. The less you do of it the better. And who knows, someday, when you become more experienced you won&#8217;t even need to test &#8211; we all know rockstar programmers never make mistakes.</p>
<p><strong>So very wrong!</strong></p>
<p>But there <em>is</em> something right in the paragraph above. Testing does feel like a chore. A hopelessly boring and tedious one at that. There isn&#8217;t much you can do about it, unless you start seeing it in terms of <a href="http://en.wikipedia.org/wiki/Game_mechanics" target="_blank">game mechanics</a>. Tests should be your scoreboard and each passed test should be an achievement you are proud of. This is where a small framework I wrote the other day comes into play.</p>
<h3>Introducing Testify.php</h3>
<p><a href="http://tutorialzine.com/projects/testify/" target="_blank">Testify</a> is a micro testing framework for PHP, released under the GPL license. It aims to be elegant and easy to use. Testify takes advantage of PHP 5.3&#8242;s anonymous function syntax to make defining tests almost JavaScript-like. Tests are logically grouped in test cases. The collection of test cases is considered a test suite. Now lets see how we can use this micro framework to make our development lives easier.</p>
<div id="attachment_1681" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2011/11/lets-write-some-tests-testify-php/"><img class="size-full wp-image-1681" title="Testify.php - a micro unit testing framework" src="http://cdn.tutorialzine.com/wp-content/uploads/2011/11/everything-pass-testify-php-unit-testing.png" alt="Testify.php - a micro unit testing framework" width="620" height="436" /></a><p class="wp-caption-text">Testify.php - a micro unit testing framework</p></div>
<h3>Shall we write some tests?</h3>
<p>As a short example, we will be writing a PHP class for converting timestamps like the ones you get from a date/time database column (&#8220;15-10-2011 22:32&#8243;), into relative time strings (&#8220;1 month ago&#8221;). This is the sort of class that requires a lot of testing to get right, which would be a great use case for Testify.</p>
<h3>The RelativeTime class</h3>
<p>There are a lot of ways you can calculate relative time offsets. You could simply dump a pile of if/else statements and it still might work, but the code would be really hard to maintain and bug prone. However, we will go with something a bit more elegant. We will use the fact that each period we use to measure time with, is fixed in relation to a lesser one. In other words one day has exactly 24 hours, each hour has 60 minutes and each minute has 60 seconds.</p>
<p>Here is the skeleton of our class that uses this observation:</p>
<h4>RelativeTime.class.php</h4>
<pre class="brush:php">class RelativeTime{

	// The period names
	private $names = array('second','minute','hour','day','week','month','year');

	// How many times is the current period bigger than the previous one
	private $divisions = array(1,60,60,24,7,4.34,12); 

	private $time = NULL;

	public function __construct($timestr = NULL){

		// You can pass a timestamp when constructing an object

	}

	public function getOffsetFrom($timestr = NULL){

		// This method calculates the relative string.
		// This is where the magic happens.

	}

	public function __toString(){

		// This is one of the convenient PHP magic methods
	}

	private function timestampFromString($time){

		// This private method will parse the time string
		// into a valid time offset (in seconds)

	}
}</pre>
<p>Now lets write our tests.</p>
<h3>Using Testify</h3>
<p>There is a software development process called <a href="http://en.wikipedia.org/wiki/Test_driven_development" target="_blank">Test Driven Development</a> (TDD), according to which you should write your tests first for best results. Lets explore how this would work with the framework.</p>
<p>The first step is to <a href="https://github.com/martinaglv/Testify.php" target="_blank">download Testify</a>. After this, extract the <span style="text-decoration: underline;">testify</span> folder and include it in a new PHP file, along with the RelativeTime class:</p>
<h4>index.php</h4>
<pre class="brush:php">include 'RelativeTime.class.php';
include 'testify/testify.class.php';</pre>
<p>Now the stage is set for a new test suite. The first step is to create an instance of the Testify class.</p>
<pre class="brush:php">$tf = new Testify("Testing RelativeTime with Testify");</pre>
<p>The string you pass here is used as the title of the suite (and displayed on top of the page). We can now move on to defining the test cases (logical collections of tests). The first test is more general and oriented to the functionality of the class as a whole.</p>
<h4>index.php</h4>
<pre class="brush:php">$tf-&gt;test("General tests of the class", function($tf){
	$relative = new RelativeTime();

	// We haven't specified a timestamp yet.
	$tf-&gt;assert($relative == "Timestamp not specified!");

	try{
		// Should throw an exception
		$relative-&gt;getOffsetFrom();

		// If we get to here, it means the test has failed:
		$tf-&gt;fail();
	}
	catch (Exception $e){
		$tf-&gt;assert($e-&gt;getMessage() == "Timestamp not specified!");
	}

	try{
		// Should work
		$relative-&gt;getOffsetFrom("22-10-2011");
		$tf-&gt;pass();
	}
	catch (Exception $e){
		$tf-&gt;fail();
	}

});</pre>
<p>The RelativeTime class throws an exception if we are accessing the relative time string but we haven&#8217;t yet passed a timestamp (either to the constructor or to the <code>getOffsetFrom()</code> method). But as the <code>__toString</code> magic method cannot throw exceptions, we will only return the exception text.</p>
<p>You can see some of the testing methods that testify supports &#8211; <code>assert()</code>, <code>pass()</code> and <code>fail()</code>. You can read more about them in the <a href="http://tutorialzine.com/projects/testify/#TestMethods" target="_blank">documentation</a>.</p>
<p>We will now need to add a second test case, which tests the validity of the generated relative time strings.</p>
<h4>index.php</h4>
<pre class="brush:php">$tf-&gt;test("Testing the relative time functionality", function($tf){

	// Testing the class with a string timestamp
	$relative = new RelativeTime(timestamp(time()-130));

	// Testing the getOffsetFrom method
	$tf-&gt;assert($relative-&gt;getOffsetFrom() == "2 minutes ago");

	// Testing using the __toString conversion
	$tf-&gt;assert($relative == "2 minutes ago");

	// Quick and dirty tests
	$tf-&gt;assert( new RelativeTime( time()) 				== "just now");
	$tf-&gt;assert( new RelativeTime( time()-11)			== "11 seconds ago");
	$tf-&gt;assert( new RelativeTime( time()-59)			== "59 seconds ago");
	$tf-&gt;assert( new RelativeTime( time()-60)			== "1 minute ago");
	$tf-&gt;assert( new RelativeTime( time()-89)			== "1 minute ago");
	$tf-&gt;assert( new RelativeTime( time()-90)			== "2 minutes ago");
	$tf-&gt;assert( new RelativeTime( time()-30*60)			== "30 minutes ago");
	$tf-&gt;assert( new RelativeTime( time()-59*60)			== "59 minutes ago");
	$tf-&gt;assert( new RelativeTime( time()-60*60)			== "1 hour ago");
	$tf-&gt;assert( new RelativeTime( time()-90*60)			== "2 hours ago");
	$tf-&gt;assert( new RelativeTime( time()-86400) 		== "1 day ago");
	$tf-&gt;assert( new RelativeTime( time()-3*86400)		== "3 days ago");
	$tf-&gt;assert( new RelativeTime( time()-9*86400)		== "1 week ago");
	$tf-&gt;assert( new RelativeTime( time()-29*86400)		== "4 weeks ago");
	$tf-&gt;assert( new RelativeTime( time()-31*86400)		== "1 month ago");
	$tf-&gt;assert( new RelativeTime( time()-100*86400)		== "3 months ago");
	$tf-&gt;assert( new RelativeTime( time()-350*86400)		== "12 months ago");
	$tf-&gt;assert( new RelativeTime( time()-365*86400)		== "1 year ago");
	$tf-&gt;assert( new RelativeTime( time()-20*365*86400)	== "20 years ago");

});

// Helper function for constructing string timestamps
function timestamp($unixTime){
	return date('r',$unixTime);
}</pre>
<p>Great! What is left is to call the <strong>run()</strong> method and we get a pretty (albeit failing) test report.</p>
<pre class="brush:php">$tf-&gt;run();</pre>
<div id="attachment_1680" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2011/11/lets-write-some-tests-testify-php/"><img class="size-full wp-image-1680" title="Testify Unit Testing - Everything Failing" src="http://cdn.tutorialzine.com/wp-content/uploads/2011/11/everything-fail-testify-php-framework.png" alt="Testify Unit Testing - Everything Failing" width="620" height="436" /></a><p class="wp-caption-text">Testify Unit Testing - Everything Failing</p></div>
<p>Now we can move on with writing the actual methods of the class. You can see the complete class implementation below:</p>
<pre class="brush:php">class RelativeTime{

	// The period names
	private $names = array('second','minute','hour','day','week','month','year');

	// How many of the previous period are contained in the next
	private $divisions = array(1,60,60,24,7,4.34,12); 

	private $time = NULL;

	public function __construct($timestr = NULL){
		// You can pass a timestamp when constructing an object
		$this-&gt;timestampFromString($timestr);
	}

	public function getOffsetFrom($timestr = NULL){

		// This method calculates the relative string

		$this-&gt;timestampFromString($timestr);

		if(is_null($this-&gt;time)){
			throw new Exception("Timestamp not specified!");
		}

		$time = $this-&gt;time;
		$name = "";

		if($time &lt; 10){
			return "just now";
		}

		for($i=0; $i&lt;count($this-&gt;divisions); $i++){
			if($time &lt; $this-&gt;divisions[$i]) break;

			$time = $time/$this-&gt;divisions[$i];
			$name = $this-&gt;names[$i];
		}

		$time = round($time);

		if($time != 1){
			$name.= 's';
		}

		return "$time $name ago";
	}

	public function __toString(){

		// __toString cannot throw exceptions

		try{
			return $this-&gt;getOffsetFrom();
		}
		catch(Exception $e){
			return $e-&gt;getMessage();
		}
	}

	private function timestampFromString($time){

		if(is_numeric($time)){
			// a unix timestamp (number of seconds since 1st Jan 1970)
			$this-&gt;time = time() - $time;
		}
		else if(is_string($time)){
			// a string timestamp
			$this-&gt;time = time() - strtotime($time);
		}
	}
}</pre>
<p>This gives us a satisfying all-green test page. <strong>Achievement unlocked!</strong></p>
<h3>Done!</h3>
<p>Testing is necessary. It can give you peace of mind when changing existing code or help you in debugging new one. Hopefully this small framework will make testing more fun!</p>
<p>As always, be sure to share your thoughts and suggestions in the comment section.</p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2011/11/lets-write-some-tests-testify-php/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Chained AJAX Selects</title>
		<link>http://tutorialzine.com/2011/11/chained-ajax-selects-jquery/</link>
		<comments>http://tutorialzine.com/2011/11/chained-ajax-selects-jquery/#comments</comments>
		<pubDate>Thu, 03 Nov 2011 15:40:06 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=1662</guid>
		<description><![CDATA[<div><a href="http://tutorialzine.com/2011/11/chained-ajax-selects-jquery/"><img src="http://cdn.tutorialzine.com/img/featured/1662.jpg" /></a></div> In today's tutorial, we will build a set of chained select elements. Selecting an option in one of them will trigger an update on the page, showing you more choices to refine your selection.]]></description>
			<content:encoded><![CDATA[<div><a href="http://tutorialzine.com/2011/11/chained-ajax-selects-jquery/"><img src="http://cdn.tutorialzine.com/img/featured/1662.jpg" /></a></div> <p>In today&#8217;s tutorial, we will build a set of chained select elements. Selecting an option in one of them will trigger an update on the page, showing you more choices to refine your selection. We will describe the options server side with PHP, so it is easy for you to hook today&#8217;s example to a database.</p>
<p>The idea for this tutorial was suggested by <a href="http://www.crea-aalborg.dk/" target="_blank">Casper Hansen</a> from Denmark.</p>
<h3>The HTML</h3>
<p>As you can see from the screenshot below, the select box is accompanied by a title that explains what the selection is about. The title and the selectbox are enclosed in a LI item.</p>
<div id="attachment_1671" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2011/11/chained-ajax-selects-jquery/"><img class="size-full wp-image-1671" title="Chained AJAX Selects with jQuery and PHP" src="http://cdn.tutorialzine.com/wp-content/uploads/2011/11/chained-ajax-selects-jquery-php.jpg" alt="Chained AJAX Selects with jQuery and PHP" width="620" height="460" /></a><p class="wp-caption-text">Chained AJAX Selects with jQuery and PHP</p></div>
<p>When adding more questions, additional LIs are created by jQuery. All of these sit inside an unordered list called <strong>#questions</strong>. The title and options for these items are served as JSON, as you will see in the PHP part of the tut. Here is the markup that is generated for the li items:</p>
<h4>index.html &#8211; generated code</h4>
<pre class="brush:html">&lt;ul id="questions"&gt;
	&lt;!-- Generated by jQuery --&gt;
	&lt;li&gt;
		&lt;p&gt;What would you like to purchase?&lt;/p&gt;
		&lt;select data-placeholder="Choose a product category"&gt;
			&lt;option data-connection="phoneSelect" value="Phones"&gt;Phones&lt;/option&gt;
			&lt;option data-connection="notebookSelect" value="Notebooks"&gt;Notebooks&lt;/option&gt;
			&lt;option data-connection="tabletSelect" value="Tablets"&gt;Tablets&lt;/option&gt;
		&lt;/select&gt;
	&lt;/li&gt;
	&lt;!-- The next sections are inserted here depending on the choices above --&gt;
&lt;/ul&gt;</pre>
<p>You might notice in the demo page that we aren&#8217;t using the default browser select controls. This is because we are making use of the <a href="http://harvesthq.github.com/chosen/" target="_blank">Chosen jQuery plugin</a> to upgrade our selects into the fancy widgets you see. We simply need to call the <strong>chosen()</strong> method on the selects, and the plugin will handle the rest.</p>
<h3>The jQuery code</h3>
<p>Here is what our jQuery code does in short &#8211; it fetches the select boxes information as JSON from the server, generates their HTML, and sets up event listeners for selection changes. If a change in the selection does occur, the process is repeated for the new select item.</p>
<p>In the code, this is achieved using two JavaScript functions:</p>
<ul>
<li><strong>refreshSelects</strong> triggers the Chosen plugin and binds event listeners every time an item is added to the page;</li>
<li><strong>fetchSelect</strong> requests a JSON feed from the server and generates the markup from the response.</li>
</ul>
<p>You can see them below.</p>
<h4>assets/js/script.js</h4>
<pre class="brush:javascript">$(function(){

	var questions = $('#questions');

	function refreshSelects(){
		var selects = questions.find('select');

		// Improve the selects with the Chose plugin
		selects.chosen();

		// Listen for changes
		selects.unbind('change').bind('change',function(){

			// The selected option
			var selected = $(this).find('option').eq(this.selectedIndex);
			// Look up the data-connection attribute
			var connection = selected.data('connection');

			// Removing the li containers that follow (if any)
			selected.closest('#questions li').nextAll().remove();

			if(connection){
				fetchSelect(connection);
			}

		});
	}

	var working = false;

	function fetchSelect(val){

		if(working){
			return false;
		}
		working = true;

		$.getJSON('ajax.php',{key:val},function(r){

			var connection, options = '';

			$.each(r.items,function(k,v){
				connection = '';
				if(v){
					connection = 'data-connection="'+v+'"';
				}

				options+= '&lt;option value="'+k+'" '+connection+'&gt;'+k+'&lt;/option&gt;';
			});

			if(r.defaultText){

				// The chose plugin requires that we add an empty option
				// element if we want to display a "Please choose" text

				options = '&lt;option&gt;&lt;/option&gt;'+options;
			}

			// Building the markup for the select section

			$('&lt;li&gt;\
				&lt;p&gt;'+r.title+'&lt;/p&gt;\
				&lt;select data-placeholder="'+r.defaultText+'"&gt;\
					'+ options +'\
				&lt;/select&gt;\
				&lt;span class="divider"&gt;&lt;/span&gt;\
			&lt;/li&gt;').appendTo(questions);

			refreshSelects();

			working = false;
		});

	}

	$('#preloader').ajaxStart(function(){
		$(this).show();
	}).ajaxStop(function(){
		$(this).hide();
	});

	// Initially load the product select
	fetchSelect('productSelect');
});</pre>
<p>Great! We are now left with generating the actual JSON feed. Notice that the <strong>fetchSelect</strong> function takes a string argument. This is the key we will be passing back to PHP, denoting which set of items we want.</p>
<p>Here is a sample response from our PHP script:</p>
<pre class="brush:js">{
    "items": {
        "Phones": "phoneSelect",
        "Notebooks": "notebookSelect",
        "Tablets": ""
    },
    "title": "What would you like to purchase?",
    "defaultText": "Choose a product category"
}</pre>
<p><strong>fetchSelect</strong> loops through the items and uses the keys as content of the option elements, and the values as connections. Phones and Notebooks would cause the script to generate new select boxes, while Tablets would not.</p>
<div id="attachment_1672" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2011/11/chained-ajax-selects-jquery/"><img class="size-full wp-image-1672" title="Improved Select boxes using the Chosen Plugin" src="http://cdn.tutorialzine.com/wp-content/uploads/2011/11/chosen-selectbox.jpg" alt="Improved Select boxes using the Chosen Plugin" width="620" height="260" /></a><p class="wp-caption-text">Improved Select boxes using the Chosen Plugin</p></div>
<h3>The PHP</h3>
<p>We need to somehow store the information about the select boxes, the options they contain and the connections between them. With a database this could be done by selecting a specific set of rows. But here we will be storing this data statically as objects. For this purpose, we will define a simple class that will hold the information for a select box:</p>
<h4>ajax.php / 1</h4>
<pre class="brush:php">// Each select box will be an instance of this class

class SelectBox{
	public $items = array();
	public $defaultText = '';
	public $title = '';

	public function __construct($title, $default){
		$this-&gt;defaultText = $default;
		$this-&gt;title = $title;
	}

	public function addItem($name, $connection = NULL){
		$this-&gt;items[$name] = $connection;
		return $this;
	}

	public function toJSON(){
		return json_encode($this);
	}
}</pre>
<p>Now we only need to create an instance of this class for every select box, and call the <strong>addItem()</strong> to add options. This method has an optional <span style="text-decoration: underline;">$connection</span> parameter, that holds the name of a dependent select box.</p>
<h4>ajax.php / 2</h4>
<pre class="brush:php">/* Configuring the selectboxes */

// Product selectbox

$productSelect = new SelectBox('What would you like to purchase?','Choose a product category');
$productSelect-&gt;addItem('Phones','phoneSelect')
			  -&gt;addItem('Notebooks','notebookSelect')
			  -&gt;addItem('Tablets','tabletSelect');

// Phone types

$phoneSelect = new SelectBox('What kind of phone are you interested in?', 'Pick a phone type');
$phoneSelect-&gt;addItem('Smartphones','smartphoneSelect')
			-&gt;addItem('Feature phones','featurephoneSelect');

// Smartphones

$smartphoneSelect = new SelectBox('Which is your desired smartphone?','Choose a smartphone model');
$smartphoneSelect-&gt;addItem('Samsung Galaxy Nexus')
				 -&gt;addItem('iPhone 4S','iphoneSelect')
				 -&gt;addItem('Samsung Galaxy S2')
				 -&gt;addItem('HTC Sensation');

// Feature phones

$featurephoneSelect = new SelectBox('Which is your desired featurephone?','Choose a feature phone');
$featurephoneSelect-&gt;addItem('Nokia N34')
				   -&gt;addItem('Sony Ericsson 334')
				   -&gt;addItem('Motorola');

// iPhone colors

$iphoneSelect = new SelectBox('What color would you like?','Choose a color');
$iphoneSelect-&gt;addItem('White')-&gt;addItem('Black');

// Notebook select

$notebookSelect = new SelectBox('Which notebook would you like to buy?', 'Choose a notebook model');
$notebookSelect-&gt;addItem('Asus Zenbook','caseSelect')
			   -&gt;addItem('Macbook Air','caseSelect')
			   -&gt;addItem('Acer Aspire','caseSelect')
			   -&gt;addItem('Lenovo Thinkpad','caseSelect')
			   -&gt;addItem('Dell Inspiron','caseSelect');

// Tablet select

$tabletSelect = new SelectBox('Which tablet would you like to buy?', 'Pick a tablet');
$tabletSelect-&gt;addItem('Asus Transformer','caseSelect')
			 -&gt;addItem('Samsung Galaxy Tab','caseSelect')
			 -&gt;addItem('iPad 16GB','caseSelect')
			 -&gt;addItem('iPad 32GB','caseSelect')
			 -&gt;addItem('Acer Iconia Tab','caseSelect');

// Case select

$caseSelect = new SelectBox('Buy protective casing?','');
$caseSelect-&gt;addItem('Yes')-&gt;addItem('No');

// Register all the select items in an array

$selects = array(
	'productSelect'			=&gt; $productSelect,
	'phoneSelect'			=&gt; $phoneSelect,
	'smartphoneSelect'		=&gt; $smartphoneSelect,
	'featurephoneSelect'	=&gt; $featurephoneSelect,
	'iphoneSelect'			=&gt; $iphoneSelect,
	'notebookSelect'		=&gt; $notebookSelect,
	'tabletSelect'			=&gt; $tabletSelect,
	'caseSelect'			=&gt; $caseSelect
);</pre>
<p>The code above defines a number of select items and places them in the <strong>$selects</strong> array. When this script receives an AJAX request, it will look into this array and return a response:</p>
<h4>ajax.php / 3</h4>
<pre class="brush:php">// We look up this array and return a select object depending
// on the $_GET['key'] parameter passed by jQuery

// You can modify it to select results from a database instead

if(array_key_exists($_GET['key'],$selects)){
	header('Content-type: application/json');
	echo $selects[$_GET['key']]-&gt;toJSON();
}
else{
	header("HTTP/1.0 404 Not Found");
	header('Status: 404 Not Found');
}</pre>
<p>By calling the <strong>toJSON()</strong> method we defined in the beginning, we output all the data for the select object as JSON, ready for use by our jQuery frontend.</p>
<p><strong>With this our Chained AJAX Selects example is complete!</strong></p>
<h3>Done</h3>
<p>You can use this example to power user guides, product recommendations or search pages. Upgrading the script to use a live database is straightforward and it will actually simplify the PHP script.</p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2011/11/chained-ajax-selects-jquery/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>HTML5 File Uploads with jQuery</title>
		<link>http://tutorialzine.com/2011/09/html5-file-upload-jquery-php/</link>
		<comments>http://tutorialzine.com/2011/09/html5-file-upload-jquery-php/#comments</comments>
		<pubDate>Mon, 26 Sep 2011 10:48:24 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=1621</guid>
		<description><![CDATA[<div><a href="http://tutorialzine.com/2011/09/html5-file-upload-jquery-php/"><img src="http://cdn.tutorialzine.com/img/featured/1621.jpg" /></a></div> Today we will be developing a small HTML5 web application that will allow people to upload photos from their computers by dragging and dropping them onto the browser window.]]></description>
			<content:encoded><![CDATA[<div><a href="http://tutorialzine.com/2011/09/html5-file-upload-jquery-php/"><img src="http://cdn.tutorialzine.com/img/featured/1621.jpg" /></a></div> <p>Today we will be developing a small web application called <em><strong>Upload Center</strong></em>, that will allow people to upload photos from their computers by dragging and dropping them onto the browser window, possible with the new HTML5 APIs exposed by modern browsers.</p>
<p>The photos will have a preview and a progress bar, all of which controlled on the client side. Currently, the photos are only stored in a folder on the server, but you could improve it any way you like.</p>
<h3>What are HTML5 File Uploads?</h3>
<p>Uploading files using HTML5 is actually a combination of three technologies &#8211; the new <a href="http://www.html5rocks.com/en/tutorials/file/dndfiles/" target="_blank">File Reader API</a>, the also new <a href="https://developer.mozilla.org/en/Using_files_from_web_applications" target="_blank">Drag &amp; Drop API</a>, and the good ol&#8217; AJAX (with the addition of binary data transfer). Here is a description of a HTML5 file upload process:</p>
<ol>
<li>The user drops one or more files from their file system to the browser window by dragging. Browsers that support the <em>Drag &amp; Drop API</em> will fire an event, which alongside other useful information, contains a list of files that were dropped;</li>
<li>Using the <em>File Reader API</em>, we read the files in the list as binary data, and store them in memory;</li>
<li>We use the new <strong>sendAsBinary</strong> method of the <em>XMLHttpRequest</em> object, and send the file data to the server.</li>
</ol>
<p>Sounds complicated? Yes, it could use some optimization. Fortunately, there are jQuery plugins that can do this for us. One of them is <a href="https://github.com/weixiyen/jquery-filedrop" target="_blank">Filedrop</a>, which is a wrapper around this functionality, and provides features for limiting maximum file size and specifying callback functions, which is really handy for integrating it into your web applications.</p>
<p>Currently file uploads work <strong>only in Firefox and Chrome</strong>, but upcoming major versions of the other browsers also include support for it. A simple fallback solution for older browsers would be to display a regular file input dialog, but we won&#8217;t be doing this today, as we will be focusing our attention on using HTML5.</p>
<p><strong>So lets get started!</strong></p>
<h3>The HTML</h3>
<p>The markup of our <em>Upload Center</em> couldn&#8217;t be simpler. We have a regular HTML5 document, which includes our stylesheet and<em><strong> script.js</strong></em> file, the <em>Filedrop plugin</em> and the <em>jQuery library</em>.</p>
<h4>index.html</h4>
<pre class="brush:html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;meta charset="utf-8" /&gt;
        &lt;title&gt;HTML5 File Drag and Drop Upload with jQuery and PHP | Tutorialzine Demo&lt;/title&gt;

        &lt;!-- Our CSS stylesheet file --&gt;
        &lt;link rel="stylesheet" href="assets/css/styles.css" /&gt;

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

    &lt;body&gt;

		&lt;header&gt;
			&lt;h1&gt;HTML5 File Upload with jQuery and PHP&lt;/h1&gt;
		&lt;/header&gt;

		&lt;div id="dropbox"&gt;
			&lt;span class="message"&gt;Drop images here to upload. &lt;br /&gt;&lt;i&gt;(they will only be visible to you)&lt;/i&gt;&lt;/span&gt;
		&lt;/div&gt;

        &lt;!-- Including The jQuery Library --&gt;
		&lt;script src="http://code.jquery.com/jquery-1.6.3.min.js"&gt;&lt;/script&gt;

		&lt;!-- Including the HTML5 Uploader plugin --&gt;
		&lt;script src="assets/js/jquery.filedrop.js"&gt;&lt;/script&gt;

		&lt;!-- The main script file --&gt;
        &lt;script src="assets/js/script.js"&gt;&lt;/script&gt;

    &lt;/body&gt;
&lt;/html&gt;</pre>
<p>The only div that the Filedrop interacts with, is <strong>#dropbox</strong>. We will pass this element to the plugin, which will detect when a file is dropped on top of it. The message span is updated if there is an error condition (for example if your browser does not support one of the HTML5 APIs that this example relies on).</p>
<div id="attachment_1627" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2011/09/html5-file-upload-jquery-php/"><img class="size-full wp-image-1627" title="HTML5 File Upload Center with PHP and jQuery" src="http://cdn.tutorialzine.com/wp-content/uploads/2011/09/html5-jquery-php-upload-progress.jpg" alt="HTML5 File Upload Center with PHP and jQuery" width="620" height="300" /></a><p class="wp-caption-text">HTML5 File Upload Center with PHP and jQuery</p></div>
<p>Later, when we drop a file, our jQuery code will display a preview by adding the following markup to the page:</p>
<pre class="brush:html">&lt;div class="preview done"&gt;

	&lt;span class="imageHolder"&gt;
		&lt;img src="" /&gt;
		&lt;span class="uploaded"&gt;&lt;/span&gt;
	&lt;/span&gt;

	&lt;div class="progressHolder"&gt;
		&lt;div class="progress"&gt;&lt;/div&gt;
	&lt;/div&gt;

&lt;/div&gt;</pre>
<p>This snippet contains a preview of the image (the source attribute is going to be populated with a <a href="http://en.wikipedia.org/wiki/Data_URI_scheme" target="_blank">DataURL</a> of the picture) and a progress bar. The whole preview can have the <em>&#8220;.done&#8221;</em> class, which causes the <em>&#8220;.uploaded&#8221;</em> span to show up (it is hidden by default). This span has the green check mark as its background, and indicates the upload is complete.</p>
<p>Great, lets move on to our <em>script.js</em> file!</p>
<h3>The jQuery Code</h3>
<p>As all of the actual file transfer functionality is handled by the Filedrop plugin, we only need to call it and pass a few callbacks, so we can hook it to our <em>Upload Center</em>. We will be writing a small PHP script that handles the uploads on the server in the next section.</p>
<p>The first step is to write a helper function that takes a file object (a special object which is created by the web browser on file drop, and has properties like file name, path and size), and creates the markup for previewing the upload.</p>
<h4>assets/js/script.js</h4>
<pre class="brush:js">var template = '&lt;div class="preview"&gt;'+
						'&lt;span class="imageHolder"&gt;'+
							'&lt;img /&gt;'+
							'&lt;span class="uploaded"&gt;&lt;/span&gt;'+
						'&lt;/span&gt;'+
						'&lt;div class="progressHolder"&gt;'+
							'&lt;div class="progress"&gt;&lt;/div&gt;'+
						'&lt;/div&gt;'+
					'&lt;/div&gt;'; 

	function createImage(file){

		var preview = $(template),
			image = $('img', preview);

		var reader = new FileReader();

		image.width = 100;
		image.height = 100;

		reader.onload = function(e){

			// e.target.result holds the DataURL which
			// can be used as a source of the image:

			image.attr('src',e.target.result);
		};

		// Reading the file as a DataURL. When finished,
		// this will trigger the onload function above:
		reader.readAsDataURL(file);

		message.hide();
		preview.appendTo(dropbox);

		// Associating a preview container
		// with the file, using jQuery's $.data():

		$.data(file,preview);
	}</pre>
<p>The <em><strong>template</strong></em> variable holds the HTML5 markup of the preview. We get the DataURL of the image (a base64 encoded representation of the image bytes) and add it as the source of the image. Everything is then appended to the dropbox container. Now we are left with calling the filedrop plugin:</p>
<h4>assets/js/script.js</h4>
<pre class="brush:js">$(function(){

	var dropbox = $('#dropbox'),
		message = $('.message', dropbox);

	dropbox.filedrop({
		// The name of the $_FILES entry:
		paramname:'pic',

		maxfiles: 5,
    	maxfilesize: 2, // in mb
		url: 'post_file.php',

		uploadFinished:function(i,file,response){
			$.data(file).addClass('done');
			// response is the JSON object that post_file.php returns
		},

    	error: function(err, file) {
			switch(err) {
				case 'BrowserNotSupported':
					showMessage('Your browser does not support HTML5 file uploads!');
					break;
				case 'TooManyFiles':
					alert('Too many files! Please select 5 at most!');
					break;
				case 'FileTooLarge':
					alert(file.name+' is too large! Please upload files up to 2mb.');
					break;
				default:
					break;
			}
		},

		// Called before each upload is started
		beforeEach: function(file){
			if(!file.type.match(/^image\//)){
				alert('Only images are allowed!');

				// Returning false will cause the
				// file to be rejected
				return false;
			}
		},

		uploadStarted:function(i, file, len){
			createImage(file);
		},

		progressUpdated: function(i, file, progress) {
			$.data(file).find('.progress').width(progress);
		}

	});

	var template = '...'; 

	function createImage(file){
		// ... see above ...
	}

	function showMessage(msg){
		message.html(msg);
	}

});</pre>
<p>With this, every valid image file that is dropped on the <em><strong>#dropbox</strong></em> div gets uploaded to <strong>post_file.php</strong>, which you can see in the next section.</p>
<div id="attachment_1628" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2011/09/html5-file-upload-jquery-php/"><img class="size-full wp-image-1628" title="Upload Complete!" src="http://cdn.tutorialzine.com/wp-content/uploads/2011/09/html5-jquery-php-upload-done.jpg" alt="Upload Complete!" width="620" height="300" /></a><p class="wp-caption-text">Upload Complete!</p></div>
<h3>The PHP Code</h3>
<p>On the PHP side of things, there is no difference between a regular form file upload and a drag and drop one. This means that you can easily provide a fallback solution to your application and reuse the same backend.</p>
<h4>post_file.php</h4>
<pre class="brush:php">// If you want to ignore the uploaded files,
// set $demo_mode to true;

$demo_mode = false;
$upload_dir = 'uploads/';
$allowed_ext = array('jpg','jpeg','png','gif');

if(strtolower($_SERVER['REQUEST_METHOD']) != 'post'){
	exit_status('Error! Wrong HTTP method!');
}

if(array_key_exists('pic',$_FILES) &amp;&amp; $_FILES['pic']['error'] == 0 ){

	$pic = $_FILES['pic'];

	if(!in_array(get_extension($pic['name']),$allowed_ext)){
		exit_status('Only '.implode(',',$allowed_ext).' files are allowed!');
	}	

	if($demo_mode){

		// File uploads are ignored. We only log them.

		$line = implode('		', array( date('r'), $_SERVER['REMOTE_ADDR'], $pic['size'], $pic['name']));
		file_put_contents('log.txt', $line.PHP_EOL, FILE_APPEND);

		exit_status('Uploads are ignored in demo mode.');
	}

	// Move the uploaded file from the temporary
	// directory to the uploads folder:

	if(move_uploaded_file($pic['tmp_name'], $upload_dir.$pic['name'])){
		exit_status('File was uploaded successfuly!');
	}

}

exit_status('Something went wrong with your upload!');

// Helper functions

function exit_status($str){
	echo json_encode(array('status'=&gt;$str));
	exit;
}

function get_extension($file_name){
	$ext = explode('.', $file_name);
	$ext = array_pop($ext);
	return strtolower($ext);
}</pre>
<p>The script runs some checks on the HTTP method that was used to request the page and the validity of the file extension. Demo mode is mainly for <em>demo.tutorialzine.com</em>, where I don&#8217;t want to store any file uploads (if you don&#8217;t call <em>move_uploaded_file</em> in your script, the file is deleted automatically at the end of the request).</p>
<p>Now lets make it pretty!</p>
<h3>The CSS Styles</h3>
<p>I left out the parts of the stylesheet that are not directly related to the uploads. You can see everything in <em><strong>styles.css</strong></em>.</p>
<h4>assets/css/styles.css</h4>
<pre class="brush:css">/*-------------------------
	Dropbox Element
--------------------------*/

#dropbox{
	background:url('../img/background_tile_3.jpg');

	border-radius:3px;
	position: relative;
	margin:80px auto 90px;
	min-height: 290px;
	overflow: hidden;
	padding-bottom: 40px;
    width: 990px;

	box-shadow:0 0 4px rgba(0,0,0,0.3) inset,0 -3px 2px rgba(0,0,0,0.1);
}

#dropbox .message{
	font-size: 11px;
    text-align: center;
    padding-top:160px;
    display: block;
}

#dropbox .message i{
	color:#ccc;
	font-size:10px;
}

#dropbox:before{
	border-radius:3px 3px 0 0;
}

/*-------------------------
	Image Previews
--------------------------*/

#dropbox .preview{
	width:245px;
	height: 215px;
	float:left;
	margin: 55px 0 0 60px;
	position: relative;
	text-align: center;
}

#dropbox .preview img{
	max-width: 240px;
	max-height:180px;
	border:3px solid #fff;
	display: block;

	box-shadow:0 0 2px #000;
}

#dropbox .imageHolder{
	display: inline-block;
	position:relative;
}

#dropbox .uploaded{
	position: absolute;
	top:0;
	left:0;
	height:100%;
	width:100%;
	background: url('../img/done.png') no-repeat center center rgba(255,255,255,0.5);
	display: none;
}

#dropbox .preview.done .uploaded{
	display: block;
}

/*-------------------------
	Progress Bars
--------------------------*/

#dropbox .progressHolder{
	position: absolute;
	background-color:#252f38;
	height:12px;
	width:100%;
	left:0;
	bottom: 0;

	box-shadow:0 0 2px #000;
}

#dropbox .progress{
	background-color:#2586d0;
	position: absolute;
	height:100%;
	left:0;
	width:0;

	box-shadow: 0 0 1px rgba(255, 255, 255, 0.4) inset;

	-moz-transition:0.25s;
	-webkit-transition:0.25s;
	-o-transition:0.25s;
	transition:0.25s;
}

#dropbox .preview.done .progress{
	width:100% !important;
}</pre>
<p>The <em>.progress</em> div is positioned absolutely. Changing its width (in percent) makes for a natural progress indicator. Throw in a 0.25 transition, and you have animated increments which would be a bit tricky to do with jQuery alone.</p>
<p><strong>With this our HTML5 Upload Center is complete!</strong></p>
<h3>We&#8217;re done!</h3>
<p>You can use this as a starting point for a file upload service, HTML5 gallery, file manager or your app&#8217;s new admin panel. Add your thoughts or suggestions in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2011/09/html5-file-upload-jquery-php/feed/</wfw:commentRss>
		<slash:comments>61</slash:comments>
		</item>
		<item>
		<title>Building a Website with PHP, MySQL and jQuery Mobile, Part 2</title>
		<link>http://tutorialzine.com/2011/08/jquery-mobile-mvc-website-part-2/</link>
		<comments>http://tutorialzine.com/2011/08/jquery-mobile-mvc-website-part-2/#comments</comments>
		<pubDate>Tue, 23 Aug 2011 12:34:01 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[jQuery]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=1585</guid>
		<description><![CDATA[<div><a href="http://tutorialzine.com/2011/08/jquery-mobile-mvc-website-part-2/"><img src="http://cdn.tutorialzine.com/img/featured/1585.jpg" /></a></div> In the second part of this two-part tutorial, we will complete our MVC driven computer web store by writing the views and discussing jQuery mobile.]]></description>
			<content:encoded><![CDATA[<div><a href="http://tutorialzine.com/2011/08/jquery-mobile-mvc-website-part-2/"><img src="http://cdn.tutorialzine.com/img/featured/1585.jpg" /></a></div> <p>This is the second part of a two-part tutorial, in which we use PHP, MySQL and jQuery mobile to build a simple computer web store. <a title="Go to Part 1" href="http://tutorialzine.com/2011/08/jquery-mobile-product-website/">In the previous part</a> we created the models and the controllers, and this time we will be writing our views.</p>
<h3>jQuery mobile</h3>
<p>First, lets say a few words about the library we will be using. <a href="http://jquerymobile.com/" target="_blank">jQuery mobile</a> is a user interface library that sits on top of jQuery and provides support for a wide array of devices in the form of ready to use widgets and a touch-friendly development environment. It is still in beta, but upgrading to the official 1.0 release will be as simple as swapping a CDN URL.</p>
<p>The library is built around progressive enhancement. You, as the developer, only need to concern yourself with outputting the correct HTML, and the library will take care of the rest. jQuery mobile makes use of the HTML5 <strong>data-</strong> attributes and by adding them, you instruct the library how it should render your markup.</p>
<p>In this tutorial we will be using some of the interface components that this library gives us &#8211; <a href="http://jquerymobile.com/demos/1.0b2/#/demos/1.0b2/docs/lists/docs-lists.html" target="_blank">lists</a>, <a href="http://jquerymobile.com/demos/1.0b2/#/demos/1.0b2/docs/toolbars/docs-headers.html" target="_blank">header</a> and <a href="http://jquerymobile.com/demos/1.0b2/#/demos/1.0b2/docs/toolbars/docs-footers.html" target="_blank">footer</a> bars and <a href="http://jquerymobile.com/demos/1.0b2/#/demos/1.0b2/docs/buttons/buttons-types.html" target="_blank">buttons</a>, all of which are defined using the <strong>data-role</strong> attributes, which you will see in use in the next section.</p>
<h3>Rendering Views</h3>
<p>The views are PHP files, or templates, that generate HTML code. They are printed by the controllers using the <strong>render()</strong> helper function. We have 7 views in use for this website &#8211; <em>_category.php</em>, <em>_product.php</em>, <em>_header.php</em>, <em>_footer.php</em>, <em>category.php</em>, <em>home.php</em> and <em>error.php</em>, which are discussed later on. First, here is <strong>render() </strong>function:</p>
<h4>includes/helpers.php</h4>
<pre class="brush:php">/* These are helper functions */

function render($template,$vars = array()){

	// This function takes the name of a template and
	// a list of variables, and renders it.

	// This will create variables from the array:
	extract($vars);

	// It can also take an array of objects
	// instead of a template name.
	if(is_array($template)){

		// If an array was passed, it will loop
		// through it, and include a partial view
		foreach($template as $k){

			// This will create a local variable
			// with the name of the object's class

			$cl = strtolower(get_class($k));
			$$cl = $k;

			include "views/_$cl.php";
		}

	}
	else {
		include "views/$template.php";
	}
}</pre>
<p>The first argument of this function is the name of the template file in the <strong>views/</strong> folder (without the <em>.php</em> extension). The next is an array with arguments. These are extracted and form real variables which you can use in your template.</p>
<p>There is one more way this function can be called &#8211; instead of a template name, you can pass an array with objects. If you recall from last time, this is what is returned by using the <strong>find()</strong> method. So basically if you pass the result of <code>Category::find()</code> to <strong>render</strong>, the function will loop through the array, get the class names of the objects inside it, and automatically include the <strong>_category.php</strong> template for each one. Some frameworks (Rails for example) call these partials.</p>
<div id="attachment_1579" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2011/08/jquery-mobile-product-website/"><img class="size-full wp-image-1579" title="Computer Store with PHP, MySQL and jQuery Mobile" src="http://cdn.tutorialzine.com/wp-content/uploads/2011/08/mobile-computer-store.jpg" alt="Computer Store with PHP, MySQL and jQuery Mobile" width="620" height="460" /></a><p class="wp-caption-text">Computer Store with PHP, MySQL and jQuery Mobile</p></div>
<h3>The Views</h3>
<p>Lets start off with the first view &#8211; the header. You can see that this template is simply the top part of a regular HTML5 page with interleaved PHP code. This view is used in <strong>home.php</strong> and <strong>category.php</strong> to promote code reuse.</p>
<h4>includes/views/_header.php</h4>
<pre class="brush:html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
	&lt;head&gt;
	&lt;title&gt;&lt;?php echo formatTitle($title)?&gt;&lt;/title&gt; 

	&lt;meta name="viewport" content="width=device-width, initial-scale=1" /&gt; 

	&lt;link rel="stylesheet" href="http://code.jquery.com/mobile/1.0b2/jquery.mobile-1.0b2.min.css" /&gt;
    &lt;link rel="stylesheet" href="assets/css/styles.css" /&gt;
	&lt;script type="text/javascript" src="http://code.jquery.com/jquery-1.6.2.min.js"&gt;&lt;/script&gt;
	&lt;script type="text/javascript" src="http://code.jquery.com/mobile/1.0b2/jquery.mobile-1.0b2.min.js"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt; 

&lt;div data-role="page"&gt;

	&lt;div data-role="header" data-theme="b"&gt;
	    &lt;a href="./" data-icon="home" data-iconpos="notext" data-transition="fade"&gt;Home&lt;/a&gt;
		&lt;h1&gt;&lt;?php echo $title?&gt;&lt;/h1&gt;
	&lt;/div&gt;

	&lt;div data-role="content"&gt;</pre>
<p>In the head section we include jQuery and jQuery mobile from jQuery&#8217;s CDN, and two stylesheets. The body section is where it gets interesting. We define a div with the <strong>data-role=&#8221;page&#8221;</strong> attribute. This, along with the <strong>data-role=&#8221;content&#8221;</strong> div, are the two elements <a href="http://jquerymobile.com/demos/1.0b2/#/demos/1.0b2/docs/pages/page-anatomy.html" target="_blank">required by the library to be present on every page</a>.</p>
<p>The <strong>data-role=&#8221;header&#8221;</strong> div is transformed into a header bar. The <strong>data-theme</strong> attribute chooses one of the <a href="http://jquerymobile.com/demos/1.0b2/#/demos/1.0b2/docs/api/themes.html" target="_blank">5 standard themes</a>. Inside it, we have a link that is assigned a home icon, and has its text hidden. jQuery Mobile comes with a <a href="http://jquerymobile.com/demos/1.0b2/#/demos/1.0b2/docs/buttons/buttons-icons.html" target="_blank">set of icons</a> you can choose from.</p>
<p>The closing tags (and the footer bar) reside in the <em>_footer.php</em> view:</p>
<h4>includes/views/_footer.php</h4>
<pre class="brush:php">	&lt;/div&gt;

	&lt;div data-role="footer" id="pageFooter"&gt;
		&lt;h4&gt;&lt;?php echo $GLOBALS['defaultFooter']?&gt;&lt;/h4&gt;
	&lt;/div&gt;
&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Nothing too fancy here. We only have a div with the <strong>data-role=&#8221;footer&#8221;</strong> attribute, and inside it we print the globally accessible <strong>$defaultFooter</strong> variable, defined in <strong>includes/config.php</strong>.</p>
<p>Neither of the above views are printed directly by our controllers. They are instead used by <strong>category.php</strong> and <strong>home.php</strong>:</p>
<h4>includes/views/home.php</h4>
<pre class="brush:php">&lt;?php render('_header',array('title'=&gt;$title))?&gt;

&lt;p&gt;Welcome! This is a demo for a ...&lt;/p&gt;
&lt;p&gt;Remember to try browsing this ...&lt;/p&gt;

&lt;ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b"&gt;
    &lt;li data-role="list-divider"&gt;Choose a product category&lt;/li&gt;
    &lt;?php render($content) ?&gt;
&lt;/ul&gt;

&lt;?php render('_footer')?&gt;</pre>
<p>If you may recall, the home view was rendered in the home controller. There we passed an array with all the categories, which is available here as <code>$content</code>. So what this view does, is to print the header, and footer, define a jQuery mobile listview (using the data-role attribute), and generate the markup of the categories passed by the controller, using this template (used implicitly by <strong>render()</strong>):</p>
<h4>index.php/views/_category.php</h4>
<pre class="brush:php">&lt;li &lt;?php echo ($active == $category-&gt;id ? 'data-theme="a"' : '') ?&gt;&gt;
&lt;a href="?category=&lt;?php echo $category-&gt;id?&gt;" data-transition="fade"&gt;
	&lt;?php echo $category-&gt;name ?&gt;
    &lt;span class="ui-li-count"&gt;&lt;?php echo $category-&gt;contains?&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/li&gt;</pre>
<p>Notice that we have a <code>$category</code> PHP variable that points to the actual object this view is being generated for. This is done in lines 24/25 of the render function. When the user clicks one of the links generated by the above fragment, he will be taken to the <strong>/?category=someid</strong> url, which will show the <strong>category.php</strong> view, given below.</p>
<pre class="brush:php">&lt;?php render('_header',array('title'=&gt;$title))?&gt;

&lt;div class="rightColumn"&gt;
	&lt;ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="c"&gt;
        &lt;?php render($products) ?&gt;
    &lt;/ul&gt;
&lt;/div&gt;

&lt;div class="leftColumn"&gt;
    &lt;ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b"&gt;
        &lt;li data-role="list-divider"&gt;Categories&lt;/li&gt;
        &lt;?php render($categories,array('active'=&gt;$_GET['category'])) ?&gt;
    &lt;/ul&gt;
&lt;/div&gt;

&lt;?php render('_footer')?&gt;</pre>
<p>This file also uses the header, footer and _category views, but it also presents a column with products (passed by the category controller). The products are rendered using the <em>_product.php</em> partial:</p>
<pre class="brush:php">&lt;li class="product"&gt;
	&lt;img src="assets/img/&lt;?php echo $product-&gt;id ?&gt;.jpg" alt="&lt;?php echo $product-&gt;name ?&gt;" /&gt;
	&lt;?php echo $product-&gt;name ?&gt; &lt;i&gt;&lt;?php echo $product-&gt;manufacturer?&gt;&lt;/i&gt;
	&lt;b&gt;$&lt;?php echo $product-&gt;price?&gt;&lt;/b&gt;
&lt;/li&gt;</pre>
<p>As we have an image as the first child of the li elements, it is automatically displayed as an 80px thumbnail by jQuery mobile.</p>
<p>One of the advantages to using the interface components defined in the library is that they are automatically scaled to the width of the device. But what about the columns we defined above? We will need to style them ourselves with some CSS3 magic:</p>
<h4>assets/css/styles.css</h4>
<pre class="brush:css">media all and (min-width: 650px){

	.rightColumn{
		width:56%;
		float:right;
		margin-left:4%;
	}

	.leftColumn{
		width:40%;
		float:left;
	}

}

.product i{
	display:block;
	font-size:0.8em;
	font-weight:normal;
	font-style:normal;
}

.product img{
	margin:10px;
}

.product b{
	position: absolute;
	right: 15px;
	top: 15px;
	font-size: 0.9em;
}

.product{
	height: 80px;
}</pre>
<p>Using a media query, we tell the browser that if the view area is wider than 650px, it should display the columns side by side. If it is not (or if the browser does not support media queries) they will be displayed one on top of the other, the regular &#8220;block&#8221; behavior.</p>
<h3>We&#8217;re done!</h3>
<p>In the second and last part of this tutorial, we wrote our views to leverage the wonderful features of jQuery mobile. With minimal effort on our part, we were able to describe the roles of our markup and easily create a fully fledged mobile website.</p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2011/08/jquery-mobile-mvc-website-part-2/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Building a Website with PHP, MySQL and jQuery Mobile, Part 1</title>
		<link>http://tutorialzine.com/2011/08/jquery-mobile-product-website/</link>
		<comments>http://tutorialzine.com/2011/08/jquery-mobile-product-website/#comments</comments>
		<pubDate>Fri, 19 Aug 2011 18:58:17 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[jQuery]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=1569</guid>
		<description><![CDATA[<div><a href="http://tutorialzine.com/2011/08/jquery-mobile-product-website/"><img src="http://cdn.tutorialzine.com/img/featured/1569.jpg" /></a></div> This is the first of a two-part tutorial, in which we will be building a simple computer shop website with PHP, MySQL and jQuery Mobile using the Model-View-Controller (MVC) pattern.]]></description>
			<content:encoded><![CDATA[<div><a href="http://tutorialzine.com/2011/08/jquery-mobile-product-website/"><img src="http://cdn.tutorialzine.com/img/featured/1569.jpg" /></a></div> <p>In this two-part tutorial, we will be building a simple website with PHP and MySQL, using the Model-View-Controller (MVC) pattern. Finally, with the help of the <a href="http://jquerymobile.com/" target="_blank">jQuery Mobile framework</a>, we will turn it into a touch-friendly mobile website, that works on any device and screen size.</p>
<p>In this first part, we concentrate on the backend, discussing the database and MVC organization. <a title="Go to Part 2" href="http://tutorialzine.com/2011/08/jquery-mobile-mvc-website-part-2/">In part two</a>, we are writing the views and integrating jQuery Mobile.</p>
<h3>The File Structure</h3>
<p>As we will be implementing the MVC pattern (in effect writing a simple micro-framework), it is natural to split our site structure into different folders for the models, views and controllers. Don&#8217;t let the number of files scare you &#8211; although we are using a lot of files, the code is concise and easy to follow.</p>
<div id="attachment_1575" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2011/08/jquery-mobile-product-website/"><img class="size-full wp-image-1575" title="The Directory Structure" src="http://cdn.tutorialzine.com/wp-content/uploads/2011/08/jquery-mobile-php-mysql-file-structure.jpg" alt="The Directory Structure" width="620" height="260" /></a><p class="wp-caption-text">The Directory Structure</p></div>
<h3>The Database Schema</h3>
<p>Our simple application operates with two types of resources &#8211; categories and products. These are given their own tables &#8211; <strong>jqm_categories</strong>, and <strong>jqm_products</strong>. Each product has a category field, which assigns it to a category.</p>
<div id="attachment_1576" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2011/08/jquery-mobile-product-website/"><img class="size-full wp-image-1576" title="jqm_categories Table Structure" src="http://cdn.tutorialzine.com/wp-content/uploads/2011/08/categories-table-structure.jpg" alt="jqm_categories Table Structure" width="620" height="260" /></a><p class="wp-caption-text">jqm_categories Table Structure</p></div>
<p>The categories table has an <strong>ID</strong> field, a <strong>name</strong> and a <strong>contains</strong> column, which shows how many products there are in each category.</p>
<div id="attachment_1577" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2011/08/jquery-mobile-product-website/"><img class="size-full wp-image-1577" title="jqm_products Table Structure" src="http://cdn.tutorialzine.com/wp-content/uploads/2011/08/products-table-structure.jpg" alt="jqm_products Table Structure" width="620" height="260" /></a><p class="wp-caption-text">jqm_products Table Structure</p></div>
<p>The product table has a <strong>name</strong>, <strong>manufacturer</strong>, <strong>price</strong> and a <strong>category</strong> field. The latter holds the ID of the category the product is added to.</p>
<blockquote class="note"><p>You can find the SQL code to create these tables in tables.sql in the download archive. Execute it in the SQL tab of phpMyAdmin to have a working copy of this database. Remember to also fill in your MySQL login details in config.php.</p></blockquote>
<h3>The Models</h3>
<p>The models in our application will handle the communication with the database. We have two types of resources in our application &#8211; <strong>products</strong> and <strong>categories</strong>. The models will expose an easy to use method &#8211; <code>find()</code> which will query the database behind the scenes and return an array with objects.</p>
<p>Before starting work on the models, we will need to establish a database connection. I am using the <a href="http://www.php.net/manual/en/intro.pdo.php" target="_blank">PHP PDO class</a>, which means that it would be easy to use a different database than MySQL, if you need to.</p>
<h4>includes/connect.php</h4>
<pre class="brush:php">/*
	This file creates a new MySQL connection using the PDO class.
	The login details are taken from includes/config.php.
*/

try {
	$db = new PDO(
		"mysql:host=$db_host;dbname=$db_name;charset=UTF-8",
		$db_user,
		$db_pass
	);

    $db-&gt;query("SET NAMES 'utf8'");
	$db-&gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e) {
	error_log($e-&gt;getMessage());
	die("A database error was encountered");
}</pre>
<p>This will put the <strong>$db</strong> connection object in the global scope, which we will use in our models. You can see them below.</p>
<h4>includes/models/category.model.php</h4>
<pre class="brush:php">class Category{

	/*
		The find static method selects categories
		from the database and returns them as
		an array of Category objects.
	*/

	public static function find($arr = array()){
		global $db;

		if(empty($arr)){
			$st = $db-&gt;prepare("SELECT * FROM jqm_categories");
		}
		else if($arr['id']){
			$st = $db-&gt;prepare("SELECT * FROM jqm_categories WHERE id=:id");
		}
		else{
			throw new Exception("Unsupported property!");
		}

                // This will execute the query, binding the $arr values as query parameters
		$st-&gt;execute($arr);

		// Returns an array of Category objects:
		return $st-&gt;fetchAll(PDO::FETCH_CLASS, "Category");
	}
}</pre>
<p>Both models are simple class definitions with a single static method &#8211; <strong>find()</strong>. In the fragment above, this method takes an optional array as a parameter and executes different queries as prepared statements.</p>
<p>In the return declaration, we are using the <a href="http://www.php.net/manual/en/pdostatement.fetchall.php" target="_blank">fetchAll</a> method passing it the <strong>PDO::FETCH_CLASS</strong> constant. What this does, is to loop though all the result rows, and create a new object of the Category class. The columns of each row will be added as public properties to the object.</p>
<p>This is also the case with the <em>Product model</em>:</p>
<h4>includes/models/product.model.php</h4>
<pre class="brush:php">class Product{

	// The find static method returns an array
	// with Product objects from the database.

	public static function find($arr){
		global $db;

		if($arr['id']){
			$st = $db-&gt;prepare("SELECT * FROM jqm_products WHERE id=:id");
		}
		else if($arr['category']){
			$st = $db-&gt;prepare("SELECT * FROM jqm_products WHERE category = :category");
		}
		else{
			throw new Exception("Unsupported property!");
		}

		$st-&gt;execute($arr);

		return $st-&gt;fetchAll(PDO::FETCH_CLASS, "Product");
	}
}</pre>
<p>The return values of both find methods are arrays with instances of the class. We could possibly return an array of generic objects (or an array of arrays) in the find method, but creating specific instances will allow us to automatically style each object using the appropriate template in the views folder (the ones that start with an underscore). We will talk again about this in the next part of the tutorial.</p>
<p>There, now that we have our two models, lets move on with the controllers.</p>
<div id="attachment_1579" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2011/08/jquery-mobile-product-website/"><img class="size-full wp-image-1579" title="Computer Store with PHP, MySQL and jQuery Mobile" src="http://cdn.tutorialzine.com/wp-content/uploads/2011/08/mobile-computer-store.jpg" alt="Computer Store with PHP, MySQL and jQuery Mobile" width="620" height="460" /></a><p class="wp-caption-text">Computer Store with PHP, MySQL and jQuery Mobile</p></div>
<h3>The controllers</h3>
<p>The controllers use the <strong>find()</strong> methods of the models to fetch data, and render the appropriate views. We have two controllers in our application &#8211; one for the <em>home page</em>, and another one for the <em>category pages</em>.</p>
<h4>includes/controllers/home.controller.php</h4>
<pre class="brush:php">/* This controller renders the home page */

class HomeController{
	public function handleRequest(){

		// Select all the categories:
		$content = Category::find();

		render('home',array(
			'title'		=&gt; 'Welcome to our computer store',
			'content'	=&gt; $content
		));
	}
}</pre>
<p>Each controller defines a <strong>handleRequest()</strong> method. This method is called when a specific URL is visited. We will return to this in a second, when we discuss <em>index.php</em>.</p>
<p>In the case with the <strong>HomeController</strong>, <strong>handleRequest()</strong> just selects all the categories using the model&#8217;s find() method, and renders the home view (<em>includes/views/home.php</em>) using our <em>render</em> helper function (<em>includes/helpers.php</em>), passing a title and the selected categories. Things are a bit more complex in <strong>CategoryController</strong>:</p>
<h4>includes/controllers/category.controller.php</h4>
<pre class="brush:php">/* This controller renders the category pages */

class CategoryController{
	public function handleRequest(){
		$cat = Category::find(array('id'=&gt;$_GET['category']));

		if(empty($cat)){
			throw new Exception("There is no such category!");
		}

		// Fetch all the categories:
		$categories = Category::find();

		// Fetch all the products in this category:
		$products = Product::find(array('category'=&gt;$_GET['category']));

		// $categories and $products are both arrays with objects

		render('category',array(
			'title'			=&gt; 'Browsing '.$cat[0]-&gt;name,
			'categories'	=&gt; $categories,
			'products'		=&gt; $products
		));
	}
}</pre>
<p>The first thing this controller does, is to select the category by id (it is passed as part of the URL). If everything goes to plan, it fetches a list of categories, and a list of products associated with the current one. Finally, the category view is rendered.</p>
<p>Now lets see how all of these work together, by inspecting <em>index.php</em>:</p>
<h4>index.php</h4>
<pre class="brush:php">/*
	This is the index file of our simple website.
	It routes requests to the appropriate controllers
*/

require_once "includes/main.php";

try {

	if($_GET['category']){
		$c = new CategoryController();
	}
	else if(empty($_GET)){
		$c = new HomeController();
	}
	else throw new Exception('Wrong page!');

	$c-&gt;handleRequest();
}
catch(Exception $e) {
	// Display the error page using the "render()" helper function:
	render('error',array('message'=&gt;$e-&gt;getMessage()));
}</pre>
<p>This is the first file that is called on a new request. Depending on the <strong>$_GET</strong> parameters, it creates a new controller object and executes its <strong>handleRequest()</strong> method. If something goes wrong anywhere in the application, an exception will be generated which will find its way to the catch clause, and then in the error template.</p>
<p>One more thing that is worth noting, is the very first line of this file, where we require <em>main.php</em>. You can see it below:</p>
<h4>main.php</h4>
<pre class="brush:php">/*
	This is the main include file.
	It is only used in index.php and keeps it much cleaner.
*/

require_once "includes/config.php";
require_once "includes/connect.php";
require_once "includes/helpers.php";
require_once "includes/models/product.model.php";
require_once "includes/models/category.model.php";
require_once "includes/controllers/home.controller.php";
require_once "includes/controllers/category.controller.php";

// This will allow the browser to cache the pages of the store.

header('Cache-Control: max-age=3600, public');
header('Pragma: cache');
header("Last-Modified: ".gmdate("D, d M Y H:i:s",time())." GMT");
header("Expires: ".gmdate("D, d M Y H:i:s",time()+3600)." GMT");</pre>
<p>This file holds the <strong>require_once</strong> declarations for all the models, controllers and helper files. It also defines a few headers to enable caching in the browser (PHP disables caching by default), which speeds up the performance of the jQuery mobile framework.</p>
<h3>Continue to Part 2</h3>
<p>With this the first part of the tutorial is complete! <a title="Continue to Part 2" href="http://tutorialzine.com/2011/08/jquery-mobile-mvc-website-part-2/">Continue to part 2</a>, where we will be writing the views and incorporate jQuery Mobile. Feel free to share your thoughts and suggestions in the comment section below.</p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2011/08/jquery-mobile-product-website/feed/</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
		<item>
		<title>Display your Favorite Tweets using PHP and jQuery</title>
		<link>http://tutorialzine.com/2011/08/display-favorite-tweets-php-css/</link>
		<comments>http://tutorialzine.com/2011/08/display-favorite-tweets-php-css/#comments</comments>
		<pubDate>Fri, 05 Aug 2011 14:22:01 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=1559</guid>
		<description><![CDATA[<div><a href="http://tutorialzine.com/2011/08/display-favorite-tweets-php-css/"><img src="http://cdn.tutorialzine.com/img/featured/1559.jpg" /></a></div> In this tutorial, we will be writing a PHP class that will fetch, cache, and display your favorite tweets in a beautiful CSS3 interface.]]></description>
			<content:encoded><![CDATA[<div><a href="http://tutorialzine.com/2011/08/display-favorite-tweets-php-css/"><img src="http://cdn.tutorialzine.com/img/featured/1559.jpg" /></a></div> <p>If you have a twitter account, you oftentimes find yourself looking for a way to display your latest tweets on your website or blog. This is pretty much a solved problem. There are jQuery plugins, PHP classes and <a href="http://tutorialzine.com/2009/10/jquery-twitter-ticker/" target="_blank">tutorials</a> that show you how to do this.</p>
<p>However, what happens if you only want to display certain tweets, that you have explicitly marked to show? As minimalistic twitter&#8217;s feature set is, it does provide a solution to this problem &#8211; favorites.</p>
<p>In this tutorial, we will be writing a PHP class that will fetch, cache, and display your favorite tweets in a beautiful CSS3 interface.</p>
<h3>HTML</h3>
<p>You can see the markup of the page that we will be using as a foundation below. The <strong>#container</strong> div will hold the tweets (which we will be generating in the PHP section of the tutorial).</p>
<h4>index.php</h4>
<pre class="brush:html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;meta charset="utf-8" /&gt;
        &lt;title&gt;Display your Favorite Tweets using PHP and jQuery | Tutorialzine Demo&lt;/title&gt;

        &lt;!-- Our CSS stylesheet file --&gt;
        &lt;link rel="stylesheet" href="assets/css/styles.css" /&gt;

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

    &lt;body&gt;

		&lt;div id="container"&gt;
	        &lt;!-- The tweets will go here --&gt;
        &lt;/div&gt;

        &lt;!-- JavaScript includes --&gt;
		&lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"&gt;&lt;/script&gt;
        &lt;script src="assets/js/jquery.splitlines.js"&gt;&lt;/script&gt;
        &lt;script src="assets/js/script.js"&gt;&lt;/script&gt;

    &lt;/body&gt;
&lt;/html&gt;</pre>
<p>We will be using the <a href="http://42pixels.com/demos/splitlines/demos.html" target="_blank">splitLines plugin</a>, which as its name suggest, will split the tweets into separate divs, one for each line of text. This is necessary as it is the only we can apply padding to the lines individually (as an illustration, view the demo with JS disabled). However, the demo will still keep most of its design without it.</p>
<p>As for the generation of the tweets, we will be creating a PHP class that will handle it for us. We will only need to call its generate method inside the <strong>#container</strong> div like this: <code>$tweets-&gt;generate(5)</code>, which will show the 5 most recent liked tweets. This method will output an unordered list with tweets:</p>
<h4>Tweet markup</h4>
<pre class="brush:html">&lt;ul class="tweetFavList"&gt;
&lt;li&gt;
	&lt;p&gt;The text of the tweet goes here&lt;/p&gt;
	&lt;div class="info"&gt;
		&lt;a title="Go to Tutorialzine's twitter page" class="user"
			href="http://twitter.com/Tutorialzine"&gt;Tutorialzine&lt;/a&gt;

		&lt;span title="Retweet Count" class="retweet"&gt;19&lt;/span&gt;

		&lt;a title="Shared 3 days ago" target="_blank" class="date"
			href="http://twitter.com/Tutorialzine/status/98439169621241856"&gt;3 days ago&lt;/a&gt;
	&lt;/div&gt;

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

&lt;/li&gt;

&lt;!-- More tweets here .. --&gt;

&lt;/ul&gt;</pre>
<p>The text of the tweet will be held in a paragraph, with additional information available in the <strong>.info</strong> div. Now lets write the PHP class.</p>
<div id="attachment_1564" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2011/08/display-favorite-tweets-php-css/"><img class="size-full wp-image-1564" title="Display Your Favorite Tweets with jQuery and PHP" src="http://cdn.tutorialzine.com/wp-content/uploads/2011/08/display-favorite-tweets-php-jquery-css.jpg" alt="Display Your Favorite Tweets with jQuery and PHP" width="620" height="460" /></a><p class="wp-caption-text">Display Your Favorite Tweets with jQuery and PHP</p></div>
<h3>PHP</h3>
<p>We will name our class <strong><em>FavoriteTweetsList</em></strong>. It will take a twitter username as a parameter, and expose a number of useful methods for fetching tweets and generating HTML markup.</p>
<p>The class will fetch the favorite tweets json feed, located at <em>http://api.twitter.com/1/favorites/<strong>USERNAME</strong>.json</em> (see <a href="http://api.twitter.com/1/favorites/Tutorialzine.json">Tutorialzine&#8217;s feed</a> as an example). Additionally, it will include caching, so that a request is made only once every three hours, which will speed things up.</p>
<h4>FavoriteTweetsList.class.php</h4>
<pre class="brush:php">class FavoriteTweetsList{
	private $username;
	const cache = "cache_tweets.ser";

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

	/* The get method returns an array of tweet objects */

	public function get(){

		$cache = self::cache;
		$tweets = array();

		if(file_exists($cache) &amp;&amp; time() - filemtime($cache) &lt; 3*60*60){

			// Use the cache if it exists and is less than three hours old
			$tweets = unserialize(file_get_contents($cache));
		}
		else{

			// Otherwise rebuild it
			$tweets = json_decode($this-&gt;fetch_feed());
			file_put_contents($cache,serialize($tweets));
		}

		if(!$tweets){
			$tweets = array();
		}

		return $tweets;
	}

	/* The generate method takes an array of tweets and build the markup */

	public function generate($limit=10, $className = 'tweetFavList'){

		echo "&lt;ul class='$className'&gt;";

		// Limiting the number of shown tweets
		$tweets = array_slice($this-&gt;get(),0,$limit);

		foreach($tweets as $t){

			$id			= $t-&gt;id_str;
			$text		= self::formatTweet($t-&gt;text);
			$time		= self::relativeTime($t-&gt;created_at);
			$username	= $t-&gt;user-&gt;screen_name;
			$retweets	= $t-&gt;retweet_count;

			?&gt;

			&lt;li&gt;
				&lt;p&gt;&lt;?php echo $text ?&gt;&lt;/p&gt;
				&lt;div class="info"&gt;
					&lt;a href="http://twitter.com/&lt;?php echo $username ?&gt;" class="user"
						title="Go to &lt;?php echo $username?&gt;'s twitter page"&gt;
                    	                    	&lt;?php echo $username ?&gt;&lt;/a&gt;

					&lt;?php if($retweets &gt; 0):?&gt;
						&lt;span class="retweet" title="Retweet Count"&gt;
                    	                    	&lt;?php echo $retweets ?&gt;&lt;/span&gt;
					&lt;?php endif;?&gt;

					&lt;a href="http://twitter.com/&lt;?php echo $username,'/status/',$id?&gt;"
                    	class="date" target="_blank" title="Shared &lt;?php echo $time?&gt;"&gt;
                    	&lt;?php echo $time?&gt;&lt;/a&gt;
				&lt;/div&gt;

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

            &lt;/li&gt;

            &lt;?php
		}

		echo "&lt;/ul&gt;";
	}

	/* Helper methods and static functions */

	private function fetch_feed(){
		return file_get_contents("http://api.twitter.com/1/favorites/{$this-&gt;username}.json");
	}

	private static function relativeTime($time){

		$divisions	= array(1,60,60,24,7,4.34,12);
		$names		= array('second','minute','hour','day','week','month','year');
		$time		= time() - strtotime($time);

		$name = "";

		if($time &lt; 10){
			return "just now";
		}

		for($i=0; $i&lt;count($divisions); $i++){
			if($time &lt; $divisions[$i]) break;

			$time = $time/$divisions[$i];
			$name = $names[$i];
		}

		$time = round($time);

		if($time != 1){
			$name.= 's';
		}

		return "$time $name ago";
	}

	private static function formatTweet($str){

		// Linkifying URLs, mentionds and topics. Notice that
		// each resultant anchor type has a unique class name.

		$str = preg_replace(
			'/((ftp|https?):\/\/([-\w\.]+)+(:\d+)?(\/([\w\/_\.]*(\?\S+)?)?)?)/i',
			'&lt;a class="link" href="$1" target="_blank"&gt;$1&lt;/a&gt;',
			$str
		);

		$str = preg_replace(
			'/(\s|^)@([\w\-]+)/',
			'$1&lt;a class="mention" href="http://twitter.com/#!/$2" target="_blank"&gt;@$2&lt;/a&gt;',
			$str
		);

		$str = preg_replace(
			'/(\s|^)#([\w\-]+)/',
			'$1&lt;a class="hash" href="http://twitter.com/search?q=%23$2"&gt;#$2&lt;/a&gt;',
			$str
		);

		return $str;
	}
}</pre>
<p>Of the methods above, <code>generate()</code> is the one that you will most likely be working with directly. It takes the number of tweets to be displayed, and an optional <strong>class</strong> parameter, that overrides the default class attribute of the unordered list.</p>
<p>Now that we have the <strong>FavoriteTweetsList</strong> class in place, we simply need to instantiate an object, passing it a twitter username, like this:</p>
<h4>index.php</h4>
<pre class="brush:php">require "includes/FavoriteTweetsList.class.php";

$tweets = new FavoriteTweetsList('Tutorialzine');</pre>
<p>Calling the <code>$tweets-&gt;generate()</code> will show that user&#8217;s latest faved tweets.</p>
<h3>jQuery</h3>
<p>As we are using the <em>splitLines</em> jQuery plugin, we already have most of the work done for us. We simply have to loop through the paragraph elements holding the text of the tweets, and call the plugin.</p>
<h4>script.js</h4>
<pre class="brush:js">$(function(){
	var width = $('ul.tweetFavList p').outerWidth();

	// Looping through the p elements
	// and calling the splitLines plugin

	$('ul.tweetFavList p').each(function(){
		$(this).addClass('sliced').splitLines({width:width});
	});
});</pre>
<p>This will split the contents of the paragraph into lines, each held in an individual div, which we can style.</p>
<h3>CSS</h3>
<p>First lets style the unordered list and the paragraph elements.</p>
<h4>styles.css &#8211; 1</h4>
<pre class="brush:css">ul.tweetFavList{
	margin:0 auto;
	width:600px;
	list-style:none;
}

ul.tweetFavList p{
	background-color: #363636;
	color: #FFFFFF;
	display: inline;
	font-size: 28px;
	line-height: 2.25;
	padding: 10px;
}

/* Coloring the links differently */

ul.tweetFavList a.link		{ color:#aed080;}
ul.tweetFavList a.mention	{ color:#6fc6d9;}
ul.tweetFavList a.hash		{ color:#dd90e9;}</pre>
<p>If you take a closer look at the <strong>formatTweet()</strong> static method in the PHP class, you will see that we are adding a class name for each type of hyperlink &#8211; a regular link, a mention or a hash, so we can style them differently.</p>
<p>When the page loads, jQuery adds <strong><em>sliced</em></strong> as a class to each paragraph. This class undoes some of the styling applied to the paragraphs by default as a fallback, so we can display the individual lines properly.</p>
<h4>styles.css &#8211; 2</h4>
<pre class="brush:css">/* The sliced class is assigned by jQuery */

ul.tweetFavList p.sliced{
	background:none;
	display:block;
	padding:0;
	line-height:2;
}

/* Each div is a line generated by the splitLines plugin */

ul.tweetFavList li p div{
	background-color: #363636;
	box-shadow: 2px 2px 2px rgba(33, 33, 33, 0.5);
	display: inline-block;
	margin-bottom: 6px;
	padding: 0 10px;
	white-space: nowrap;
}</pre>
<p>Next we will style the colorful information boxes that hold the <em>author username</em>, <em>publish date</em> and <em>retweet count</em>.</p>
<h4>styles.css &#8211; 3</h4>
<pre class="brush:css">ul.tweetFavList .info{
	overflow: hidden;
	padding: 15px 0 5px;
}

/* The colorful info boxes */

ul.tweetFavList .user,
ul.tweetFavList .retweet,
ul.tweetFavList .date{
	float:left;
	padding:4px 8px;
	color:#fff !important;
	text-decoration:none;
	font-size:11px;
	box-shadow: 1px 1px 1px rgba(33, 33, 33, 0.3);
}

ul.tweetFavList .user{
	background-color:#6fc6d9;
}

ul.tweetFavList .retweet{
	background-color:#dd90e9;
	cursor:default;
}

ul.tweetFavList .date{
	background-color:#aed080;
}</pre>
<p>And finally we will style the divider. This is a single div, but thanks to <code>:before</code>/<code>:after</code> pseudo elements, we add two more circles to the left and to the right of it.</p>
<h4>styles.css &#8211; 4</h4>
<pre class="brush:css">/* Styling the dotted divider */

ul.tweetFavList .divider,
ul.tweetFavList .divider:before,
ul.tweetFavList .divider:after{
	background-color: #777777;
	border-radius: 50% 50% 50% 50%;
	height: 12px;
	margin: 60px auto 80px;
	width: 12px;
	position:relative;
	box-shadow: 1px 1px 0 rgba(255, 255, 255, 0.5);
}

ul.tweetFavList .divider:before,
ul.tweetFavList .divider:after{
	margin:0;
	position:absolute;
	content:'';
	top:0;
	left:-40px;
}

ul.tweetFavList .divider:after{
	left:auto;
	right:-40px;
}

ul.tweetFavList li:last-child .divider{
	display:none;
}</pre>
<p>With this our favorited tweet list is complete!</p>
<h3>Done</h3>
<p>This example can be used to build a simple testimonials section, or to highlight tweets that you think your readers would find worthy. You can even see it implemented on the sidebar of this very site.</p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2011/08/display-favorite-tweets-php-css/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Creating a PHP and CSS3 Powered About Page</title>
		<link>http://tutorialzine.com/2011/07/about-page-vcard-php-css/</link>
		<comments>http://tutorialzine.com/2011/07/about-page-vcard-php-css/#comments</comments>
		<pubDate>Tue, 12 Jul 2011 19:46:46 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=1530</guid>
		<description><![CDATA[<div><a href="http://tutorialzine.com/2011/07/about-page-vcard-php-css/"><img src="http://cdn.tutorialzine.com/img/featured/1530.jpg" /></a></div> Here we will be creating a simple about page that is powered by PHP, HTML5 and CSS3. It will present your contact information to your visitors, with an option for downloading it as a vCard (useful for importing it in third party applications).]]></description>
			<content:encoded><![CDATA[<div><a href="http://tutorialzine.com/2011/07/about-page-vcard-php-css/"><img src="http://cdn.tutorialzine.com/img/featured/1530.jpg" /></a></div> <p>In this tutorial, we will be creating a simple about page that is powered by PHP, HTML5 and CSS3. It will present your contact information to your visitors, with an option for downloading it as a vCard (useful for importing it in third party applications).</p>
<p>You can use today&#8217;s example as a placeholder for your upcoming personal website, or as an actual about page.</p>
<h3>HTML</h3>
<p>As always, the first step is to write the HTML markup that will be powering our example. This is a simple page the main purpose of which is to present our contact details semantically. This will require adding appropriate meta tags and using the <a href="http://en.wikipedia.org/wiki/HCard" target="_blank">hCard microformat</a> to embed data in the page.</p>
<h4>index.php</h4>
<pre class="brush:html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;meta charset="utf-8" /&gt;
        &lt;meta name="description" content="Online info page of &lt;?php echo $profile-&gt;fullName()?&gt;. Learn more about me and download a vCard." /&gt;

        &lt;title&gt;Creating a PHP and CSS Powered About Page  | Tutorialzine Demo&lt;/title&gt;

        &lt;!-- Our CSS stylesheet file --&gt;
        &lt;link rel="stylesheet" href="assets/css/styles.css" /&gt;

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

    &lt;body&gt;

		&lt;section id="infoPage"&gt;

    		&lt;img src="&lt;?php echo $profile-&gt;photoURL()?&gt;" alt="&lt;?php echo $profile-&gt;fullName()?&gt;" width="164" height="164" /&gt;

            &lt;header&gt;
                &lt;h1&gt;&lt;?php echo $profile-&gt;fullName()?&gt;&lt;/h1&gt;
                &lt;h2&gt;&lt;?php echo $profile-&gt;tags()?&gt;&lt;/h2&gt;
            &lt;/header&gt;

            &lt;p class="description"&gt;&lt;?php echo nl2br($profile-&gt;description())?&gt;&lt;/p&gt;

            &lt;a href="&lt;?php echo $profile-&gt;facebook()?&gt;" class="grayButton facebook"&gt;Find me on Facebook&lt;/a&gt;
            &lt;a href="&lt;?php echo $profile-&gt;twitter()?&gt;" class="grayButton twitter"&gt;Follow me on Twitter&lt;/a&gt;

            &lt;ul class="vcard"&gt;
                &lt;li class="fn"&gt;&lt;?php echo $profile-&gt;fullName()?&gt;&lt;/li&gt;
                &lt;li class="org"&gt;&lt;?php echo $profile-&gt;company()?&gt;&lt;/li&gt;
                &lt;li class="tel"&gt;&lt;?php echo $profile-&gt;cellphone()?&gt;&lt;/li&gt;
                &lt;li&gt;&lt;a class="url" href="&lt;?php echo $profile-&gt;website()?&gt;"&gt;&lt;?php echo $profile-&gt;website()?&gt;&lt;/a&gt;&lt;/li&gt;
            &lt;/ul&gt;

		&lt;/section&gt;

        &lt;section id="links"&gt;
        	&lt;a href="?vcard" class="vcard"&gt;Download as V-Card&lt;/a&gt;
            &lt;a href="?json" class="json"&gt;Get as a JSON feed&lt;/a&gt;
            &lt;p&gt;In this tutorial: &lt;a href="http://www.flickr.com/photos/levycarneiro/4144428707/"&gt;Self Portrait&lt;/a&gt; by &lt;a href="http://www.flickr.com/photos/levycarneiro/"&gt;Levy Carneiro Jr&lt;/a&gt;&lt;/p&gt;
        &lt;/section&gt;

    &lt;/body&gt;
&lt;/html&gt;</pre>
<p>The <code>$profile</code> variable you see above, holds an object of the AboutPage PHP class that we will be writing in a moment. It holds our contact details and provides a number of useful methods for generating JSON and vCard files.</p>
<p>As mentioned above, we are using the hCard microformat to embed contact details in the page. This is a simple standard with which we use the class names of regular HTML elements to specify data, easily recognizable by search engines. The hCard holds information about our full name, organization, phone and home page:</p>
<pre class="brush:html">&lt;ul class="vcard"&gt;
    &lt;li class="fn"&gt;&lt;?php echo $profile-&gt;fullName()?&gt;&lt;/li&gt;
    &lt;li class="org"&gt;&lt;?php echo $profile-&gt;company()?&gt;&lt;/li&gt;
    &lt;li class="tel"&gt;&lt;?php echo $profile-&gt;cellphone()?&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a class="url" href="&lt;?php echo $profile-&gt;website()?&gt;"&gt;&lt;?php echo $profile-&gt;website()?&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</pre>
<p>You can also optionally specify a home / work address and other kinds of useful information.</p>
<div id="attachment_1534" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2011/07/about-page-vcard-php-css/"><img class="size-full wp-image-1534" title="PHP &amp; CSS3 Powered About Page" src="http://cdn.tutorialzine.com/wp-content/uploads/2011/07/php-css3-html5-about-page.jpg" alt="PHP &amp; CSS3 Powered About Page" width="620" height="460" /></a><p class="wp-caption-text">PHP &amp; CSS3 Powered About Page</p></div>
<h3>PHP</h3>
<p>One of the points of using a server side language is that we can leave some aspects of the page to be generated on the fly. This frees us from having to manually keep various parts of the page up to date.</p>
<p>In the case with our about page, we have a simple configuration file, which holds the data, used by the page. This same resource is used for the generation of the vCard file and the JSON feed.</p>
<h4>config.php</h4>
<pre class="brush:php">$info = array(
	'firstName'		=&gt; 'John',
	'middleName'	=&gt; 'S.',
	'lastName'		=&gt; 'Smith',
	'photoURL'		=&gt; 'assets/img/photo.jpg',
	'birthDay'		=&gt; strtotime('22-03-1983'),
	'city'			=&gt; 'MyCity',
	'country'		=&gt; 'United States',
	'street'		=&gt; 'My Street 21',
	'zip'			=&gt; '12345',
	'company'		=&gt; 'Google Inc',
	'website'		=&gt; 'http://tutorialzine.com/',
	'email'			=&gt; 'email@example.com',
	'cellphone'		=&gt; '12345678910',
	'description'	=&gt; "I am a webdeveloper living in ...",
	'tags'			=&gt; 'Developer, Designer, Photographer',
	'facebook'		=&gt; 'http://www.facebook.com/',
	'twitter'		=&gt; 'http://twitter.com/Tutorialzine'
);</pre>
<p>Not all of these properties are presented on the about page. Some of them (like the <em>address fields</em>, <em>company</em>, <em>email</em> and <em>birthday</em>) are only made available when the user downloads the profile as a <em>vCard</em> or as a <em>JSON file</em>. You can also add quite a few more properties to this array (a complete list is given as a comment in the <em>config.php</em> file).</p>
<p>So now that we have provided all the information we wanted, we need to build a class that will handle the task of presenting a complete about page.</p>
<h4>aboutPage.class.php</h4>
<pre class="brush:php">class AboutPage{
	private $info = array();

	// The constructor:

	public function __construct(array $info){
		$this-&gt;info = $info;
	}

	// A helper method that assembles the person's full name:

	public function fullName(){
		return $this-&gt;firstName().' '.$this-&gt;middleName().' '.$this-&gt;lastName();
	}

	// Using PHP's Magick __call method to make the
	// properties of $this-&gt;info available as method calls:

	public function __call($method,$args = array()){

		if(!array_key_exists($method,$this-&gt;info)){
			throw new Exception('Such a method does not exist!');
		}

		if(!empty($args)){
			$this-&gt;info[$method] = $args[0];
		}
		else{
			return $this-&gt;info[$method];
		}
	}

	// This method generates a vcard from the $info
	// array, using the third party vCard class:

	public function downloadVcard(){

		$vcard = new vCard;

		$methodCalls = array();

		// Translating the properties of $info to method calls
		// understandable by the third party vCard class:

		$propertyMap = array(
			'firstName'		=&gt; 'setFirstName',
			'middleName'	=&gt; 'setMiddleName',
			'lastName'		=&gt; 'setLastName',
			'birthDay'		=&gt; 'setBirthday',
			'city'			=&gt; 'setHomeCity',
			'zip'			=&gt; 'setHomeZIP',
			'country'		=&gt; 'setHomeCountry',
			'website'		=&gt; 'setURLWork',
			'email'			=&gt; 'setEMail',
			'description'	=&gt; 'setNote',
			'cellphone'		=&gt; 'setCellphone');

		// Looping though the properties in $info:

		foreach($this-&gt;info as $k=&gt;$v){

			// Mapping a property of the array to a recognized method:

			if($propertyMap[$k]){
				$methodCalls[$propertyMap[$k]] = $v;
			}
			else {

				// If it does not exist, transform it to setPropertyName,
				// which might be recognized by the vCard class:

				$methodCalls['set'.ucfirst($k)] = $v;
			}
		}

		// Attempt to call these methods:

		foreach($methodCalls as $k=&gt;$v){
			if(method_exists($vcard,$k)){
				$vcard-&gt;$k($v);
			}
			else error_log('Invalid property in your $info array: '.$k);
		}

		// Serving the vcard with a x-vcard Mime type:

		header('Content-Type: text/x-vcard; charset=utf-8');
		header('Content-Disposition: attachment; filename="'.$this-&gt;fullName().'.vcf"');
		echo $vcard-&gt;generateCardOutput();
	}

	// This method generates and serves a JSON object from the data:

	public function generateJSON(){
		header('Content-Type: application/json');
		header('Content-Disposition: attachment; filename="'.$this-&gt;fullName().'.json"');

		// If you wish to allow cross-domain AJAX requests, uncomment the following line:
		// header('Access-Control-Allow-Origin: *');

		echo json_encode($this-&gt;info);
	}
}</pre>
<p>As you can see from the code below, we are using a <a href="http://www.phpclasses.org/package/874-PHP-class-for-creating-vCard-files.html" target="_blank">third party open source class</a> for the actual generation of the vCard file (vcf). As this class uses its own set of method calls, we will need to transform our configuration file to something that it will understand. We are doing this with the <code>$propertyMap</code> array which maps properties found in our $info array to the names of method calls that will need to be executed on the vCard object. After we configure the <code>$vcard</code> object, we set the content headers and call the object&#8217;s <code>generateCardOutput()</code> method. This causes the browser to display a file download dialog.</p>
<p>We are doing basically the same thing in the generateJSON method, with the worthy exception that we are not using a third party PHP class, but the <code>json_encode()</code> built-in. We are serving the JSON file with an application/json content type. You can also uncomment the access control header if you wish to be able to access your data via AJAX from other domains.</p>
<p>Now lets see how we are using this class in index.php:</p>
<h4>index.php</h4>
<pre class="brush:php">require 'includes/config.php';
require 'includes/aboutPage.class.php';
require 'includes/vcard.class.php';

$profile = new AboutPage($info);

if(array_key_exists('json',$_GET)){
	$profile-&gt;generateJSON();
	exit;
}
else if(array_key_exists('vcard',$_GET)){
	$profile-&gt;downloadVcard();
	exit;
}</pre>
<p>The fragment you see above is found at the top of <em>index.php</em>, before any of the HTML, as we have to be able to set headers. After including the appropriate PHP source files, we create a new <code>AboutPage</code> object with the configuration array as its parameter. After this we check whether the requested URL is <em>?json</em> or <em>?vcard</em>, and serve the appropriate data. Otherwise, the regular about page is displayed.</p>
<h3>CSS</h3>
<p>Most of the design of the about page is pretty straightforward. However, a fair share of CSS3 is used to keep the number of images to a minimum. The two buttons &#8211; <em>Find me on facebook</em>, and <em>Follow me on twitter</em>, that are positioned below the text, are ordinary hyperlinks with a <code>.grayButton</code> class name. You can see the definition of this class below:</p>
<h4>assets/css/styles.css</h4>
<pre class="brush:css">a.grayButton{
	padding:6px 12px 6px 30px;
	position:relative;

	background-color:#fcfcfc;
	background:-moz-linear-gradient(left top -90deg, #fff, #ccc);
	background:-webkit-linear-gradient(left top -90deg, #fff, #ccc);
	background:linear-gradient(left top -90deg, #fff, #ccc);

	-moz-box-shadow: 1px 1px 1px #333;
	-webkit-box-shadow: 1px 1px 1px #333;
	box-shadow: 1px 1px 1px #333;

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

	font-size:11px;
	color:#444;
	text-shadow:1px 1px 0 #fff;
	display:inline-block;
	margin-right:10px;

	-moz-transition:0.25s;
	-webkit-transition:0.25s;
	transition:0.25s;
}

a.grayButton:hover{
	text-decoration:none !important;
	box-shadow:0 0 5px #2b99ff;
}

a.grayButton:before{
	background:url('../img/icons.png') no-repeat;
	height: 18px;
	left: 4px;
	position: absolute;
	top: 6px;
	width: 20px;
	content: '';
}

a.grayButton.twitter:before{
	background-position:0 -20px;
}</pre>
<p>The code above applies a CSS3 linear gradient to the button, text shadows and rounded corners. It also defines a 0.25 sec transition, that animates the glow that is applied on hover. We are also using the <code>:before</code> pseudo element to create the icon that goes with the button. As we are using a sprite, the only thing that differs between the two buttons is the offset of the background image.</p>
<p>After this we have the &#8220;<em>Download as vCard</em>&#8221; and &#8220;<em>Get as a JSON file</em>&#8221; links:</p>
<h4>assets/css/styles.css</h4>
<pre class="brush:css">#links{
	text-align:center;
	padding-top: 20px;
	border-top:1px solid #4a4a4a;
	text-shadow: 1px 1px 0 #333333;
	width:655px;
	margin:0 auto;
}

#links a{
	color: #ccc;
	position:relative;
}

#links &gt; a{
	display: inline-block;
	font-size: 11px;
	margin: 0 10px;
	padding-left:15px;
}

#links &gt; a:before{
	background: url("../img/icons.png") no-repeat -10px -60px;
	position:absolute;
	content:'';
	width:16px;
	height:16px;
	top:2px;
	left:-4px;
}

#links &gt; a.vcard:before{
	background-position: -10px -40px;
	top: 0;
	left: -8px;
}

#links p{
	color: #888888;
	font-size: 10px;
	font-style: normal;
	padding: 30px;
}</pre>
<p>As the <code>#links</code> section element contains more than these links (it contains a paragraph with a link to a great <a href="http://www.flickr.com/photos/levycarneiro/" target="_blank">portrait image by Levy Carneiro Jr.</a>) , we have to limit the styling to the anchor elements that are direct children of the section.</p>
<p><strong>With this our PHP &amp; CSS3 powered about page is complete!</strong></p>
<h3>To Wrap it up</h3>
<p>You can use this about page as a simple placeholder for your personal website. You can also use an existing users database and create beautiful profiles for your users. Combined with some of our previous tutorials, you can display your latest posts on facebook, flickr images or tweets as a personalized home page.</p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2011/07/about-page-vcard-php-css/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Generating Files with JavaScript</title>
		<link>http://tutorialzine.com/2011/05/generating-files-javascript-php/</link>
		<comments>http://tutorialzine.com/2011/05/generating-files-javascript-php/#comments</comments>
		<pubDate>Tue, 17 May 2011 16:46:55 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[jQuery]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=1461</guid>
		<description><![CDATA[<div><a href="http://tutorialzine.com/2011/05/generating-files-javascript-php/"><img src="http://cdn.tutorialzine.com/img/featured/1461.jpg" /></a></div> This time we will be making a jQuery plugin which, combined with a simple php script, can generate a file and make it available for download. Perfect for exporting the settings of your webapp or providing reports.]]></description>
			<content:encoded><![CDATA[<div><a href="http://tutorialzine.com/2011/05/generating-files-javascript-php/"><img src="http://cdn.tutorialzine.com/img/featured/1461.jpg" /></a></div> <p>When building a web application, you oftentimes need to give users the ability to download a piece of data as a file. It could be a backup of configuration settings, reports, or other piece of information that is generated dynamically.</p>
<p>The usual solution to this problem would be to have a dedicated export script that selects from a database and builds the file you need. However, as we will be proving in this short tutorial, there is another way.</p>
<p>We will make a jQuery plugin which, combined with a simple php script, can generate every kind of textual file, and make it available for download. You will initiate the download from your JavaScript front end by only providing the file contents, and leave the rest to the plugin.</p>
<h3>The HTML</h3>
<p>We shall start by laying down a simple HTML page with a textarea and a download button, so we can demonstrate the plugin at work.</p>
<h4>index.html</h4>
<pre class="brush:html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;meta charset="utf-8" /&gt;

        &lt;title&gt;Generating files with JS &amp;amp; PHP | Tutorialzine Demo&lt;/title&gt;

        &lt;!-- Our CSS stylesheet file --&gt;
        &lt;link rel="stylesheet" href="assets/css/styles.css" /&gt;

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

    &lt;body&gt;

        &lt;header&gt;
            &lt;h1&gt;Generating Files with JavaScript&lt;/h1&gt;
            &lt;h2&gt;&lt;a href="http://tutorialzine.com/2011/05/generating-files-javascript-php/"&gt;&amp;laquo; Read and download on Tutorialzine&lt;/a&gt;&lt;/h2&gt;
        &lt;/header&gt;

        &lt;form action="./" method="post"&gt;
            &lt;textarea&gt;&lt;/textarea&gt;
            &lt;a href="#" class="blueButton" id="download"&gt;Download&lt;/a&gt;
        &lt;/form&gt;

        &lt;footer&gt;Another cool example: &lt;a href="#" id="downloadPage"&gt;download this page.&lt;/a&gt; &lt;b&gt;To download the source code, visit &lt;a href="http://tutorialzine.com/2011/05/generating-files-javascript-php/"&gt;Tutorialzine.com&lt;/a&gt;&lt;/b&gt;&lt;/footer&gt;

        &lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"&gt;&lt;/script&gt;
        &lt;script src="assets/js/jquery.generateFile.js"&gt;&lt;/script&gt;
        &lt;script src="assets/js/script.js"&gt;&lt;/script&gt;

    &lt;/body&gt;
&lt;/html&gt;</pre>
<p>The page uses the HTML5 doctype, as we are using some of the tags defined by the standard. For it to work in IE, we also need to include the <a href="http://remysharp.com/2009/01/07/html5-enabling-script/" target="_blank">HTML5 enabling script</a> in the head section.</p>
<p>Before the closing body tag, we are adding the jQuery library, the <em>generateFile plugin</em> we will be writing in a moment, and the <em>script.js</em> file that listens for events and triggers the file downloads.</p>
<div id="attachment_1465" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2011/05/generating-files-javascript-php/"><img class="size-full wp-image-1465" title="Generating Files with jQuery and PHP" src="http://cdn.tutorialzine.com/wp-content/uploads/2011/05/downloading-files-jquery-php.jpg" alt="Generating Files with jQuery and PHP" width="620" height="460" /></a><p class="wp-caption-text">Generating Files with jQuery and PHP</p></div>
<h3>The PHP</h3>
<p>As you probably know, generating files is not possible with JavaScript alone. Different solutions exist (some of them even relying on Flash), but using a generic PHP script on the backend provides better control and ease of use (not to mention that it works in every major browser out there).</p>
<p>You can see the generic file generation script below:</p>
<h4>download.php</h4>
<pre class="brush:php">if(empty($_POST['filename']) || empty($_POST['content'])){
	exit;
}

// Sanitizing the filename:
$filename = preg_replace('/[^a-z0-9\-\_\.]/i','',$_POST['filename']);

// Outputting headers:
header("Cache-Control: ");
header("Content-type: text/plain");
header('Content-Disposition: attachment; filename="'.$filename.'"');

echo $_POST['content'];</pre>
<p>What this PHP script does is simply add some headers on top of an echo statement. The plugin we are building must pass two parameters along with the POST request: <em>filename</em> and <em>content</em>. The script will print the content of the file, while setting three headers that will force the file download box to appear (instead of your browser simply opening it).</p>
<p>To use the plugin you need to upload this file somewhere on your server  and pass its URL to the plugin we will be coding next.</p>
<h3>The jQuery</h3>
<p>As you saw in the previous section, our plugin has to issue a POST request to <em>download.php</em>. The natural choice for making a request would be by using AJAX. However, there is a shortcoming to using this method &#8211; it does not trigger the file download dialog to appear.</p>
<p>So what we need is a bit more old school. We will be dynamically creating a hidden iframe and write a form to it, which we will later submit via POST. The action attribute of the form points to <em>download.php</em>, so the file download dialog will pop up, exactly as we need it to.</p>
<p>Now lets lay down the jQuery code that does this:</p>
<h4>assets/jquery.generateFile.js</h4>
<pre class="brush:js">(function($){

	// Creating a jQuery plugin:

	$.generateFile = function(options){

		options = options || {};

		if(!options.script || !options.filename || !options.content){
			throw new Error("Please enter all the required config options!");
		}

		// Creating a 1 by 1 px invisible iframe:

		var iframe = $('&lt;iframe&gt;',{
			width:1,
			height:1,
			frameborder:0,
			css:{
				display:'none'
			}
		}).appendTo('body');

		var formHTML = '&lt;form action="" method="post"&gt;'+
			'&lt;input type="hidden" name="filename" /&gt;'+
			'&lt;input type="hidden" name="content" /&gt;'+
			'&lt;/form&gt;';

		// Giving IE a chance to build the DOM in
		// the iframe with a short timeout:

		setTimeout(function(){

			// The body element of the iframe document:

			var body = (iframe.prop('contentDocument') !== undefined) ?
							iframe.prop('contentDocument').body :
							iframe.prop('document').body;	// IE

			body = $(body);

			// Adding the form to the body:
			body.html(formHTML);

			var form = body.find('form');

			form.attr('action',options.script);
			form.find('input[name=filename]').val(options.filename);
			form.find('input[name=content]').val(options.content);

			// Submitting the form to download.php. This will
			// cause the file download dialog box to appear.

			form.submit();
		},50);
	};

})(jQuery);</pre>
<p>In less than 50 lines (with comments stripped) the above fragment does what we need. It creates a hidden iframe with a form inside it.</p>
<p>Notice the <code>setTimeout()</code> function. Without it we cannot access the document element of the iframe in Internet Explorer. This way, we are giving it time to build the DOM and make it available to us.</p>
<p>And here is how to use this plugin:</p>
<h4>assets/script.js</h4>
<pre class="brush:js">$(document).ready(function(){

	$('#download').click(function(e){

		$.generateFile({
			filename	: 'export.txt',
			content		: $('textarea').val(),
			script		: 'download.php'
		});

		e.preventDefault();
	});

	$('#downloadPage').click(function(e){

		$.generateFile({
			filename	: 'page.html',
			content		: $('html').html(),
			script		: 'download.php'
		});

		e.preventDefault();
	});

});</pre>
<p>When calling <code>$.generateFile</code>, you need to pass the name of the file (should be something descriptive), its text content, and the path to download.php. As you can see in the example above, we can generate any kind of file, as long as it is text.</p>
<p><strong>With this our simple plugin is complete!</strong></p>
<h3>Conclusion</h3>
<p>You can use this code to add export features to your web app or enhance certain areas of your site with download functionality. It is even possible to generate doc files and spreadsheets if you follow <a href="http://en.wikipedia.org/wiki/Microsoft_Office_XML_formats" target="_blank">Microsoft Office&#8217;s XML formats</a>. The best part is that everything is done with JavaScript and you can easily combine different sources of data.</p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2011/05/generating-files-javascript-php/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Photobooth with PHP, jQuery and CSS3</title>
		<link>http://tutorialzine.com/2011/04/jquery-webcam-photobooth/</link>
		<comments>http://tutorialzine.com/2011/04/jquery-webcam-photobooth/#comments</comments>
		<pubDate>Thu, 14 Apr 2011 16:56:10 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=1419</guid>
		<description><![CDATA[<div><a href="http://tutorialzine.com/2011/04/jquery-webcam-photobooth/"><img src="http://cdn.tutorialzine.com/img/featured/1419.jpg" /></a></div> In this tutorial, we will be building a jQuery and PHP powered photobooth. It will allow your website visitors to take a snapshot with their web camera and upload it from a neat CSS3 interface.]]></description>
			<content:encoded><![CDATA[<div><a href="http://tutorialzine.com/2011/04/jquery-webcam-photobooth/"><img src="http://cdn.tutorialzine.com/img/featured/1419.jpg" /></a></div> <p>In this tutorial, we will be building a jQuery and PHP powered photobooth. It will allow your website visitors to take a snapshot with their web camera and upload it from a neat CSS3 interface.</p>
<p>As you might know, it is not possible to access web cameras and other peripheral devices directly from JavaScript (and it won&#8217;t be for some time). However there is a solution to our problem &#8211; we can use a flash movie. Flash has perfect web camera support, and is installed on nearly all internet &#8211; enabled computers.</p>
<p>The solution we are going to use for this app is <a href="http://code.google.com/p/jpegcam/" target="_blank">webcam.js</a>. It is a JavaScript wrapper around flash&#8217;s API that gives us control over the user&#8217;s webcam.</p>
<h3>HTML</h3>
<p>The first step to building our Photobooth is laying down the HTML structure of the main page. We will be using jQuery to fetch a list of the latest photos, so we don&#8217;t need to embed any PHP logic here. This means we can leave it as a plain HTML file.</p>
<h4>index.html</h4>
<pre class="brush:html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset="utf-8" /&gt;
&lt;title&gt;Photobooth with PHP, jQuery and CSS3 | Tutorialzine Demo&lt;/title&gt;

&lt;link rel="stylesheet" type="text/css" href="assets/css/styles.css" /&gt;
&lt;link rel="stylesheet" type="text/css" href="assets/fancybox/jquery.fancybox-1.3.4.css" /&gt;

&lt;/head&gt;
&lt;body&gt;

&lt;div id="topBar"&gt;
    &lt;h1&gt;jQuery &amp;amp; CSS3 Photobooth&lt;/h1&gt;
    &lt;h2&gt;&amp;laquo; Go back to Tutorialzine&lt;/h2&gt;
&lt;/div&gt;

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

&lt;div id="camera"&gt;
	&lt;span class="tooltip"&gt;&lt;/span&gt;
	&lt;span class="camTop"&gt;&lt;/span&gt;

    &lt;div id="screen"&gt;&lt;/div&gt;
    &lt;div id="buttons"&gt;
    	&lt;div class="buttonPane"&gt;
        	&lt;a id="shootButton" href="" class="blueButton"&gt;Shoot!&lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="buttonPane hidden"&gt;
        	&lt;a id="cancelButton" href="" class="blueButton"&gt;Cancel&lt;/a&gt; &lt;a id="uploadButton" href="" class="greenButton"&gt;Upload!&lt;/a&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;span class="settings"&gt;&lt;/span&gt;
&lt;/div&gt;

&lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"&gt;&lt;/script&gt;
&lt;script src="assets/fancybox/jquery.easing-1.3.pack.js"&gt;&lt;/script&gt;
&lt;script src="assets/fancybox/jquery.fancybox-1.3.4.pack.js"&gt;&lt;/script&gt;
&lt;script src="assets/webcam/webcam.js"&gt;&lt;/script&gt;
&lt;script src="assets/js/script.js"&gt;&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;</pre>
<p>There are three main divs in the page:</p>
<ul>
<li><strong>#topBar</strong> displays the headings;</li>
<li><strong>#photos</strong> is where the images are inserted after they are requested with jQuery&#8217;s $.getJSON method;</li>
<li><strong>#camera</strong> holds the webcam.swf movie (which we are using to communicate with the web camera). It also holds the control buttons for taking photos and uploading.</li>
</ul>
<p>The control buttons are divided in two <code>.buttonPane</code> divs. In the jQuery part of the tutorial, we will be making a simple function to toggle between the panes.</p>
<p>At the bottom of the body, we are including a number of JavaScript files. Starting with the jQuery library, we are also adding the <a href="http://fancybox.net/" target="_blank">fancybox plugin</a> for displaying the photos, the <a href="http://gsgd.co.uk/sandbox/jquery/easing/" target="_blank">easing plugin</a> (to make fancybox even fancier),  <a href="http://code.google.com/p/jpegcam/">webcam.js</a> &#8211; the plugin that enables us to communicate with web cameras through flash, and finally our own <strong>script.js</strong> to make all this work together.</p>
<p>Note that if you are tweaking your website for high load, you might want to combine all these JS files together. This will make the page load faster as JavaScript files block the page while loading.</p>
<div id="attachment_1425" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2011/04/jquery-webcam-photobooth/"><img class="size-full wp-image-1425" title="jQuery, CSS3 &amp; PHP Photobooth" src="http://cdn.tutorialzine.com/wp-content/uploads/2011/04/jquery-php-css3-photobooth.jpg" alt="jQuery, CSS3 &amp; PHP Photobooth" width="620" height="460" /></a><p class="wp-caption-text">jQuery, CSS3 &amp; PHP Photobooth</p></div>
<h3>PHP</h3>
<p>Although the main page is plain old HTML, we do need PHP to make our photo booth work. To be more exact, there are two features of the app that we need PHP for &#8211; receiving the uploaded image from flash, and for listing the uploaded files.</p>
<h4>upload.php</h4>
<pre class="brush:php">/*
	This file receives the JPEG snapshot from
	assets/webcam/webcam.swf as a POST request.
*/

// We only need to handle POST requests:
if(strtolower($_SERVER['REQUEST_METHOD']) != 'post'){
	exit;
}

$folder = 'uploads/';
$filename = md5($_SERVER['REMOTE_ADDR'].rand()).'.jpg';

$original = $folder.$filename;

// The JPEG snapshot is sent as raw input:
$input = file_get_contents('php://input');

if(md5($input) == '7d4df9cc423720b7f1f3d672b89362be'){
	// Blank image. We don't need this one.
	exit;
}

$result = file_put_contents($original, $input);
if (!$result) {
	echo '{
		"error"		: 1,
		"message"	: "Failed save the image. Make sure you chmod the uploads folder and its subfolders to 777."
	}';
	exit;
}

$info = getimagesize($original);
if($info['mime'] != 'image/jpeg'){
	unlink($original);
	exit;
}

// Moving the temporary file to the originals folder:
rename($original,'uploads/original/'.$filename);
$original = 'uploads/original/'.$filename;

// Using the GD library to resize
// the image into a thumbnail:

$origImage	= imagecreatefromjpeg($original);
$newImage	= imagecreatetruecolor(154,110);
imagecopyresampled($newImage,$origImage,0,0,0,0,154,110,520,370); 

imagejpeg($newImage,'uploads/thumbs/'.$filename);

echo '{"status":1,"message":"Success!","filename":"'.$filename.'"}';</pre>
<p>As I mentioned earlier, we can&#8217;t communicate with web cameras directly from JavaScript. This is why we need flash, which has excellent web camera support, to act as an intermediate layer. This leaves us with two choices:</p>
<ul>
<li>we can have flash export the snapshot and make it available to JavaScript (slow and ineffective);</li>
<li>have flash upload the photo directly to a PHP script.</li>
</ul>
<p>Sensibly, the flash webcam plugin uses the second approach. It also has the benefit of uploading the snapshot as a valid JPEG image, which means we can save it to a file directly with PHP, without having to convert it.</p>
<p>In our <em>upload.php</em> we validate that the uploaded data is a JPEG image, save it to a file in the <em><strong>uploads/original/</strong></em> directory, and generate a 154 -by- 110 px thumbnail. I chose this thumbnail size out of convenience, as it shares the same width to height ratio as the original image (520 -by- 370 px), which makes the resize easier.</p>
<div id="attachment_1426" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2011/04/jquery-webcam-photobooth/"><img class="size-full wp-image-1426" title="Take a photo - Webcam Photobooth" src="http://cdn.tutorialzine.com/wp-content/uploads/2011/04/webcam-shot-flash-jquery-php-css3.jpg" alt="Take a photo - Webcam Photobooth" width="620" height="460" /></a><p class="wp-caption-text">Take a photo - Webcam Photobooth</p></div>
<h4>browse.php</h4>
<pre class="brush:php">/*
	In this file we are scanning the image folders and
	returning a JSON object with file names. It is used
	by jQuery to display the images on the main page:
*/

// The standard header for json data:
header('Content-type: application/json');

$perPage = 24;

// Scanning the thumbnail folder for JPG images:
$g = glob('uploads/thumbs/*.jpg');

if(!$g){
	$g = array();
}

$names = array();
$modified = array();

// We loop though the file names returned by glob,
// and we populate a second file with modifed timestamps.

for($i=0,$z=count($g);$i&lt;$z;$i++){
	$path = explode('/',$g[$i]);
	$names[$i] = array_pop($path);

	$modified[$i] = filemtime($g[$i]);
}

// Multisort will sort the array with the filenames
// according to their timestamps, given in $modified:

array_multisort($modified,SORT_DESC,$names);

$start = 0;

// browse.php can also paginate results with an optional
// GET parameter with the filename of the image to start from:

if(isset($_GET['start']) &amp;&amp; strlen($_GET['start'])&gt;1){
	$start = array_search($_GET['start'],$names);

	if($start === false){
		// Such a picture was not found
		$start = 0;
	}
}

// nextStart is returned alongside the filenames,
// so the script can pass it as a $_GET['start']
// parameter to this script if "Load More" is clicked

$nextStart = '';

if($names[$start+$perPage]){
	$nextStart = $names[$start+$perPage];
}

$names = array_slice($names,$start,$perPage);

// Formatting and returning the JSON object:

echo json_encode(array(
	'files' =&gt; $names,
	'nextStart'	=&gt; $nextStart
));</pre>
<p>The <em><strong>browse.php</strong></em> file lists the contents of the image folders as a JSON object. It does it with <a href="http://php.net/manual/en/function.glob.php" target="_blank">PHP&#8217;s glob function</a>, which scans the folder and returns an array with file names. We then sort this array according to the photo upload dates with the <a href="http://php.net/manual/en/function.array-multisort.php" target="_blank">array_multisort</a> function, after which we slice it with <a href="http://bg.php.net/manual/en/function.array-slice.php" target="_blank">array_slice</a> to return only 24 photos at a time.</p>
<h3>jQuery</h3>
<p>As I mentioned earlier, we are using the webcam.js plugin to control the user&#8217;s web camera. This plugin exposes a <a href="http://code.google.com/p/jpegcam/wiki/APIDocs" target="_blank">simple API</a>, available as a global object named <em>webcam</em>. It gives us methods for taking and uploading photos, and for generating the necessary embed code for the swf file.</p>
<p>In script.js below, we will be using this api and build our photo booth script around it. First we will define some variables and cache the most commonly used jQuery selectors throughout the code for better performance:</p>
<h4>assets/js/script.js &#8211; Part 1</h4>
<pre class="brush:js">$(document).ready(function(){

	var camera = $('#camera'),
		photos = $('#photos'),
		screen =  $('#screen');

	var template = '&lt;a href="uploads/original/{src}" rel="cam" '
		+'style="background-image:url(uploads/thumbs/{src})"&gt;&lt;/a&gt;';

	/*----------------------------------
		Setting up the web camera
	----------------------------------*/

	webcam.set_swf_url('assets/webcam/webcam.swf');
	webcam.set_api_url('upload.php');	// The upload script
	webcam.set_quality(80);				// JPEG Photo Quality
	webcam.set_shutter_sound(true, 'assets/webcam/shutter.mp3');

	// Generating the embed code and adding it to the page:
	screen.html(
		webcam.get_html(screen.width(), screen.height())
	);</pre>
<p>The <code>template</code> variable above holds the markup that will be generated for each photo. It is basically a hyperlink that has the thumbnail of the photo as its background-image, and which points to the full size shot. The <code>{src}</code> attribute gets replaced with the actual file name of the photo (the file names were generated automatically by <strong>upload.php</strong> in the previous section).</p>
<p>Next we will be binding event listeners for the control buttons. Notice the use of <strong>webcam.freeze()</strong>, and the <strong>webcam.upload()</strong> methods. This gives the user the ability to take a shot and decide whether to upload it later. <strong>webcam.reset()</strong> prepares the web camera for another shot.</p>
<h4>assets/js/script.js &#8211; Part 2</h4>
<pre class="brush:js">	/*----------------------------------
		Binding event listeners
	----------------------------------*/

	var shootEnabled = false;

	$('#shootButton').click(function(){

		if(!shootEnabled){
			return false;
		}

		webcam.freeze();
		togglePane();
		return false;
	});

	$('#cancelButton').click(function(){
		webcam.reset();
		togglePane();
		return false;
	});

	$('#uploadButton').click(function(){
		webcam.upload();
		webcam.reset();
		togglePane();
		return false;
	});

	camera.find('.settings').click(function(){
		if(!shootEnabled){
			return false;
		}

		webcam.configure('camera');
	});

	// Showing and hiding the camera panel:

	var shown = false;
	$('.camTop').click(function(){

		$('.tooltip').fadeOut('fast');

		if(shown){
			camera.animate({
				bottom:-466
			});
		}
		else {
			camera.animate({
				bottom:-5
			},{easing:'easeOutExpo',duration:'slow'});
		}

		shown = !shown;
	});

	$('.tooltip').mouseenter(function(){
		$(this).fadeOut('fast');
	});</pre>
<p>After this we will need to implement some of the callbacks exposed by the webcam plugin:</p>
<h4>assets/js/script.js &#8211; Part 3</h4>
<pre class="brush:js">	/*----------------------
		Callbacks
	----------------------*/

	webcam.set_hook('onLoad',function(){
		// When the flash loads, enable
		// the Shoot and settings buttons:
		shootEnabled = true;
	});

	webcam.set_hook('onComplete', function(msg){

		// This response is returned by upload.php
		// and it holds the name of the image in a
		// JSON object format:

		msg = $.parseJSON(msg);

		if(msg.error){
			alert(msg.message);
		}
		else {
			// Adding it to the page;
			photos.prepend(templateReplace(template,{src:msg.filename}));
			initFancyBox();
		}
	});

	webcam.set_hook('onError',function(e){
		screen.html(e);
	});</pre>
<p>This completes the web camera integration. However we still need to display a list with the latest photos (and give users a way to browse through older images as well). We will be doing this with a custom function called <code>loadPics()</code> which will communicate with <em><strong>browse.php</strong></em>:</p>
<h4>assets/js/script.js &#8211; Part 4</h4>
<pre class="brush:js">	/*-------------------------------------
		Populating the page with images
	-------------------------------------*/

	var start = '';

	function loadPics(){

		// This is true when loadPics is called
		// as an event handler for the LoadMore button:

		if(this != window){
			if($(this).html() == 'Loading..'){
				// Preventing more than one click
				return false;
			}
			$(this).html('Loading..');
		}

		// Issuing an AJAX request. The start parameter
		// is either empty or holds the name of the first
		// image to be displayed. Useful for pagination:

		$.getJSON('browse.php',{'start':start},function(r){

			photos.find('a').show();
			var loadMore = $('#loadMore').detach();

			if(!loadMore.length){
				loadMore = $('&lt;span&gt;',{
					id			: 'loadMore',
					html		: 'Load More',
					click		: loadPics
				});
			}

			$.each(r.files,function(i,filename){
				photos.append(templateReplace(template,{src:filename}));
			});

			// If there is a next page with images:
			if(r.nextStart){

				// r.nextStart holds the name of the image
				// that comes after the last one shown currently.

				start = r.nextStart;
				photos.find('a:last').hide();
				photos.append(loadMore.html('Load More'));
			}

			// We have to re-initialize fancybox every
			// time we add new photos to the page:

			initFancyBox();
		});

		return false;
	}

	// Automatically calling loadPics to
	// populate the page onload:

	loadPics();</pre>
<p>As <code>loadPics()</code> is bound as a handler for the <em>click</em> event of the <em><strong>Load More</strong></em> tile, this function can be called in two ways: the normal one and as a callback. The difference is that the <code>this</code> object of the function points either to <code>window</code>, or to the DOM element. We can check for this and take appropriate action, like preventing double clicks from issuing multiple requests to browse.php.</p>
<p>Lastly, we have the helper functions, used throughout the rest of the code.</p>
<h4>assets/js/script.js &#8211; Part 5</h4>
<pre class="brush:js">	/*----------------------
		Helper functions
	------------------------*/

	// This function initializes the
	// fancybox lightbox script.

	function initFancyBox(filename){
		photos.find('a:visible').fancybox({
			'transitionIn'	: 'elastic',
			'transitionOut'	: 'elastic',
			'overlayColor'	: '#111'
		});
	}

	// This function toggles the two
	// .buttonPane divs into visibility:

	function togglePane(){
		var visible = $('#camera .buttonPane:visible:first');
		var hidden = $('#camera .buttonPane:hidden:first');

		visible.fadeOut('fast',function(){
			hidden.show();
		});
	}

	// Helper function for replacing "{KEYWORD}" with
	// the respectful values of an object:

	function templateReplace(template,data){
		return template.replace(/{([^}]+)}/g,function(match,group){
			return data[group.toLowerCase()];
		});
	}
});</pre>
<p>Now that we&#8217;ve discussed all of the code, lets say a few words about the CSS styles.</p>
<h3>CSS3</h3>
<p>With the recent introduction of Firefox 4, CSS3 transitions can finally become a fully qualified member of our developer toolbox. In our photobooth, we are using CSS3 to add a bit of class to the photo booth.</p>
<h4>assets/css/styles.css</h4>
<pre class="brush:css">/*-------------------
	Photo area
--------------------*/

#photos{
	margin: 60px auto 100px;
	overflow: hidden;
	width: 880px;
}

#photos:hover a{
	opacity:0.5;
}

#photos a,
#loadMore{
	background-position: center center;
	background-color: rgba(14, 14, 14, 0.3);
	float: left;
	height: 110px;
	margin: 1px 1px 0 0;
	overflow: hidden;
	width: 145px;

	-moz-transition:0.25s;
	-webkit-transition:0.25s;
	-o-transition:0.25s;
	transition:0.25s;
}

#photos a:hover{
	opacity:1;
}

#loadMore{
	cursor: pointer;
	line-height: 110px;
	text-align: center;
	text-transform: uppercase;
	font-size:10px;
}

#loadMore:hover{
	color:#fff;
	text-shadow:0 0 4px #fff;
}</pre>
<p>In the fragment above, you can see that we&#8217;ve defined a 0.25s transition on the photo anchors (these hold our images). This will animate every change to the styles of these elements, including those applied by <em>:hover</em> definitions. This in effect makes all the photos fade out to 50% when we hover over the <strong>#photos</strong> div, except the one directly beneath the mouse pointer.</p>
<p>With that same transition definition, we also affect the #loadMore span. It has a text shadow rule applied on hover, which gets animated into a smooth glow effect.</p>
<div id="attachment_1427" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2011/04/jquery-webcam-photobooth/"><img class="size-full wp-image-1427" title="CSS3 Effects" src="http://cdn.tutorialzine.com/wp-content/uploads/2011/04/jquery-photobooth-hover.jpg" alt="CSS3 Effects" width="620" height="260" /></a><p class="wp-caption-text">CSS3 Effects</p></div>
<p><strong>With this our photo booth is complete!</strong></p>
<h3>Conclusion</h3>
<p>You can use this app as a fun addition to a community forum or other social networking website. You can optionally build in a comment field to go with the photo, or integrate it more deeply with your site.</p>
<p>Did you like this week&#8217;s tutorial? Share you thoughts in the comment section.</p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2011/04/jquery-webcam-photobooth/feed/</wfw:commentRss>
		<slash:comments>63</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using apc
Page Caching using apc
Object Caching 718/774 objects using apc
Content Delivery Network via cdn.tutorialzine.com

Served from: tutorialzine.com @ 2012-02-03 22:16:15 -->
