Hostingheaderbarlogoj
Join InMotion Hosting for $3.49/mo & get a year on Tuts+ FREE (worth $180). Start today.
Advertisement

Twitter Emulation Using MooTools 1.2 and PHP

by
Gift

Want a free year on Tuts+ (worth $180)? Start an InMotion Hosting plan for $3.49/mo.

People all over the world love Twitter because of how easy it is to use. All you need to do is type in your current status, click "Update", and you're done. What most people probably don't know is how simple it is to emulate Twitter's functionality. Using PHP, MySQL, and MooTools javascript, you can implement a Twitter-like status system in no time.

Assumptions

Before we create this system, lets keep in mind a few assumptions we're making:

  1. We assume that the only user we're keep track of is the person logged in and that the user's ID is 1.
  2. We also assume that user has javascript enabled. The great thing about this solution is that it works with javascript turned on or off.
  3. We assume that the user's image is stored in the following directory structure: /graphics/users/{user_id}.png
  4. We assume that we're using the full MooTools 1.2 core with the Fx.Slide plugin.

The Show

Here's the sequence of events that will take place in our concoction:

  • The page loads and shows previous statuses (or "tweets").
  • The user types in their new status and clicks submit.
  • A message slides in from behind the submit button saying "Status Updated!"
  • The new status and user photo slides in right after the "Recent Updates" heading.

As you can see, it's very simple functionality that will be presented in an elegant manner.

Step One: The MySQL

We need a place to store these updates, right? Here's what our "statuses"
table will look like:

		CREATE TABLE IF NOT EXISTS `statuses` (
		  `status_id` MEDIUMINT(10) unsigned NOT NULL auto_increment,
		  `user_id` SMALLINT(5) NOT NULL,
		  `status` varchar(150) NOT NULL,
		  `date_set` datetime NOT NULL,
		  PRIMARY KEY  (`status_id`)
		) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

It's important that status ID is the primary key and that the field auto-increments.

Step Two: The XHTML

Before any of our MooTools magic can be used, we need to create the "update" form
and place our message DIV next to the submit button so that MooTools can effectively
slide in the message from behind the button. Note that we set the form's action to
this same page. Also note that we place an initial $message variable inside the
message DIV for users who do not have javascript enabled.

		<h3>What are you doing?</h3>
		<form action="<?php echo $_SERVER['REQUEST_URI']; ?>" method="post">
			<textarea name="status" id="status"></textarea><br />
			<input type="submit" value="Update Status" id="submit" />
			<div id="message"><?php echo $message; ?></div>
		</form>

We're not done with the XHTML part yet. The next step is to add the
"wrapper" DIV for all of the previous statuses.

		<h3>Recent Updates</h3>
		<div id="statuses">
			<!-- php/mysql will go here -->
		</div>

Lastly, we include the MooTools library in the header of the page.

		<script type="text/javascript" src="moo1.2.js"></script>

Step 3: The PHP/MySQL - Part 1

This first snippet of PHP will be placed inside our "statuses" DIV. We've chosen
to display the most recent 20 statuses.

		$query  = 'SELECT status, DATE_FORMAT(date_set,\'%M %e, %Y @ %l:%i:%s %p\') AS ds FROM statuses ORDER BY date_set DESC LIMIT 20';
		$result = mysql_query($query,$link) or die(mysql_error().': '.$query);
		while($row = mysql_fetch_assoc($result))
		{
			echo '<div class="status-box">',stripslashes($row['status']),'<br /><span class="time">',$row['ds'],'</span></div>';
		}

Step 4: The CSS

As you know, CSS is our presentation layer so style up your page however you'd
like. We create the "failure" and "success" classes for the result message
-- note that the success message uses green and failure message is colored red.
Also note that the status-box class contains the user's avatar, set by PHP.

		#message		{ padding:7px 10px; float:left; width:350px; }
		#status		{ border:1px solid #999; padding:5px; width:500px; height:75px; margin:5px 0; }
		#statuses	{ width:512px; }
		#submit		{ cursor:pointer; padding:5px; border:1px solid #ccc; float:left; margin:0 20px 0 0; }
		
		.status-box	{ padding:10px 20px 10px 70px; height:48px; background:url(/graphics/users/<?php echo $_SESSION['user_id']; ?>.png) 10px 10px no-repeat; border-bottom:1px dotted #aaa; }
		.status-box:hover	{ background-color:#eee; }
		.success		{ color:#008000; }
		.failure		{ color:#f00; }
		.time			{ color:#2a447b; font-size:10px; }

Step 5: The MooTools Javascript

Now for the fun part -- using MooTools 1.2 goodness to create our subtle
animations and Ajax request.

Once the DOM is ready...

window.addEvent('domready', function() {

We create a horizontal slider for the success/failure message. We hide it for now...

var fx = new Fx.Slide('message', { mode: 'horizontal' }).hide();

We now create our (Ajax) Request. We do this outside of the click event
(which will follow in a moment) so that we don't waste memory.

When the user clicks the submit button, we want to disabled
it to prevent double-submission. Upon completion, we enable
the submit button and direct the status message notifier message to hide
in 2 seconds.

If the request fails, the message reflects that by sliding in the
"Status could not be updated. Try again." message. If the request is
successful, quite a bit more happens.

We start by sliding in a "Status Updated" message. Next we clear the
status textarea. Then we inject the new element box into the statuses
container and slide it in. Here is the MooTools code in its entirety.

		//make the ajax call to the database to save the update
		var request = new Request({
			url: '<?php echo $_SERVER['PHP_SELF']; ?>',
			method: 'post',
			onRequest: function() {
				$('submit').disabled = 1;
			},
			onComplete: function(response) {
				$('submit').disabled = 0;
				$('message').removeClass('success').removeClass('failure');
				(function() { fx.slideOut(); }).delay(2000);
			},
			onSuccess: function() {
				//update message
				$('message').set('text','Status updated!').addClass('success');
				fx.slideIn();
				
				//store value, clear out box
				var status = $('status').value;
				$('status').value = '';
				
				//add new status to the statuses container
				var element = new Element('div', {
					'class': 'status-box',
					'html': status + '<br /><span class="time">A moment ago</span>'
				}).inject('statuses','top');
				
				//create a slider for it, slide it in.
				var slider = new Fx.Slide(element).hide().slideIn();
				
				//place the cursor in the text area
				$('status').focus();
				
			},
			onFailure: function() {
				//update message
				$('message').set('text','Status could not be updated.  Try again.').addClass('failure');
				fx.slideIn();
			}
		});

When form submission is triggered...

$('submit').addEvent('click', function(event) {

Prevent the page from refreshing due to the form submission.

event.preventDefault();

If the "status" textarea has a value...

if($('status').value.length && !$('status').disabled) {

We execute the request, passing along the new status.

			request.send({
				data: {
					'status': $('status').value,
					'ajax': 1
				}
			});

Here's the complete MooTools script:

		/* when the dom is ready */
		window.addEvent('domready', function() {
			
			//create the message slider
			var fx = new Fx.Slide('message', {
				mode: 'horizontal'
			}).hide();
			
			//make the ajax call to the database to save the update
			var request = new Request({
				url: '<?php echo $_SERVER['PHP_SELF']; ?>',
				method: 'post',
				onRequest: function() {
					$('submit').disabled = 1;
				},
				onComplete: function(response) {
					$('submit').disabled = 0;
					$('message').removeClass('success').removeClass('failure');
					(function() { fx.slideOut(); }).delay(2000);
				},
				onSuccess: function() {
					//update message
					$('message').set('text','Status updated!').addClass('success');
					fx.slideIn();
					
					//store value, clear out box
					var status = $('status').value;
					$('status').value = '';
					
					//add new status to the statuses container
					var element = new Element('div', {
						'class': 'status-box',
						'html': status + '<br /><span class="time">A moment ago</span>'
					}).inject('statuses','top');
					
					//create a slider for it, slide it in.
					var slider = new Fx.Slide(element).hide().slideIn();
					
					//place the cursor in the text area
					$('status').focus();
					
				},
				onFailure: function() {
					//update message
					$('message').set('text','Status could not be updated.  Try again.').addClass('failure');
					fx.slideIn();
				}
			});
			
			//when the submit button is clicked...
			$('submit').addEvent('click', function(event) {
				
				//stop regular form submission
				event.preventDefault();
				
				//if there's anything in the textbox
				if($('status').value.length && !$('status').disabled) {
					
					request.send({
						data: {
							'status': $('status').value,
							'ajax': 1
						}
					});
					
				}
				
			});
			
		});

Step 5: The PHP/MySQL - Part 2

This "header" portion of PHP code goes at the top of the same PHP file the rest of our
code is in. This code will also be run by both Ajax requests and users who have javascript
disabled. Upon form submission (and assuming the user is logged in), we insert the new
status into the database. If the Ajax flag is set (by the MooTools code above), we know that
the user does have javascript enabled and we kill the script. If the user did not
use javascript, we simply set the $message variable's initial value to "Status Updated!"
and display the page. Simple!

		//connect to the db
		$link = @mysql_connect('localhost','username','password');
		@mysql_select_db('blog',$link);
		
		/* form submission post */
		if(isset($_POST['status']) && $_SESSION['user_id'])
		{
			//record the occurence
			$query = 'INSERT INTO nettuts1 (user_id, status, date_set) VALUES ('.$_SESSION['user_id'].',\''.mysql_escape_string(htmlentities(strip_tags($_POST['status']))).'\',NOW())';
			$result = @mysql_query($query,$link);
			
			//die if this was done via ajax...
			if($_POST['ajax']) { die(); } else { $message = 'Status Updated!'; }
		}

That's It?

Yes! Here's the entire PHP / MooTools / XHTML / CSS file:

<?php

//connect to the db
$link = @mysql_connect('localhost','username','password');
@mysql_select_db('blog',$link);

/* form submission post */
if(isset($_POST['status']) && $_SESSION['user_id'])
{
	//record the occurence
	$query = 'INSERT INTO nettuts1 (user_id, status, date_set) VALUES ('.$_SESSION['user_id'].',\''.mysql_escape_string(htmlentities(strip_tags($_POST['status']))).'\',NOW())';
	$result = @mysql_query($query,$link);
	
	//die if this was done via ajax...
	if($_POST['ajax']) { die(); } else { $message = 'Status Updated!'; }
}

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"  dir="ltr">
<head>
<title>Twitter Emulation</title>
<style type="text/css">
	
	#message		{ padding:7px 10px; float:left; width:350px; }
	#status		{ border:1px solid #999; padding:5px; width:500px; height:75px; margin:5px 0; }
	#statuses	{ width:512px; }
	#submit		{ cursor:pointer; padding:5px; border:1px solid #ccc; float:left; margin:0 20px 0 0; }
	
	.status-box	{ padding:10px 20px 10px 70px; height:48px; background:url(nettuts-david.jpg) 10px 10px no-repeat; border-bottom:1px dotted #aaa; }
	.status-box:hover	{ background-color:#eee; }
	.success		{ color:#008000; }
	.failure		{ color:#f00; }
	.time			{ color:#2a447b; font-size:10px; }
	
</style>
<script type="text/javascript" src="moo1.2.js"></script>

<script type="text/javascript">

	/* when the dom is ready */
	window.addEvent('domready', function() {
		
		//create the message slider
		var fx = new Fx.Slide('message', {
			mode: 'horizontal'
		}).hide();
		
		//make the ajax call to the database to save the update
		var request = new Request({
			url: '/dw-content/nettuts-twitter.php',
			method: 'post',
			onRequest: function() {
				$('submit').disabled = 1;
			},
			onComplete: function(response) {
				$('submit').disabled = 0;
				$('message').removeClass('success').removeClass('failure');
				(function() { fx.slideOut(); }).delay(2000);
			},
			onSuccess: function() {
				//update message
				$('message').set('text','Status updated!').addClass('success');
				fx.slideIn();
				
				//store value, clear out box
				var status = $('status').value;
				$('status').value = '';
				
				//add new status to the statuses container
				var element = new Element('div', {
					'class': 'status-box',
					'html': status + '<br /><span class="time">A moment ago</span>'
				}).inject('statuses','top');
				
				//create a slider for it, slide it in.
				var slider = new Fx.Slide(element).hide().slideIn();
				
				//place the cursor in the text area
				$('status').focus();
				
			},
			onFailure: function() {
				//update message
				$('message').set('text','Status could not be updated.  Try again.').addClass('failure');
				fx.slideIn();
			}
		});
		
		//when the submit button is clicked...
		$('submit').addEvent('click', function(event) {
			
			//stop regular form submission
			event.preventDefault();
			
			//if there's anything in the textbox
			if($('status').value.length && !$('status').disabled) {
				
				request.send({
					data: {
						'status': $('status').value,
						'ajax': 1
					}
				});
				
			}
			
		});
		
	});
	
</script>
</head>
<body>

<h3>What are you doing?</h3>

<form action="/dw-content/nettuts-twitter.php" method="post">
	<textarea name="status" id="status"></textarea><br />
	<input type="submit" value="Update Status" id="submit" />
	<div id="message"></div>
</form>

<div class="clear"></div>
<p> </p>
<h3>Recent Updates</h3>

<div id="statuses">
	<?php
		//get the latest 20
		$query  = 'SELECT status, DATE_FORMAT(date_set,\'%M %e, %Y @ %l:%i:%s %p\') AS ds FROM nettuts1 ORDER BY date_set DESC LIMIT 20';
		$result = mysql_query($query,$link) or die(mysql_error().': '.$query);
		while($row = mysql_fetch_assoc($result))
		{
			echo '<div class="status-box">',stripslashes($row['status']),'<br /><span class="time">',$row['ds'],'</span></div>';
		}
	?>
</div>
</body>
</html>

Updates & Enhancements


While the above code provides a slick, functional interface, by no means
would you consider this a completed system. Here are a few ideas for enhancements
you can implement:

  • Updated time displays upon new status submission
  • Friend status integration
  • Javascript-based status length limiter
  • Anything else you can think of!

What are you thoughts? Have any suggestions? Please share them below!

Advertisement