Twitter App

Twitter Emulation Using MooTools 1.2 and PHP

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: '',
				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 + '
A moment ago' }).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!

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://home.expatlist.be Simon

    Fantastic – Loads of food for thought

  • Pingback: Cómo emular Twitter en nuestro sitio web… - dsd2hosting.com

  • Casper

    okay i tried almost everything no matter what i do i cant get it to show æøå properly.. it ocmes out as æøå… or actually it works while posted with ajax and so, but when refreshing the page and all the content is fetched from the db it comes out as æøå..

    any advice?? searched google the whole day and tried all kind of solutions

  • Pingback: Best Ever 65 mooTools Plugins and Demos, is it Better than jQuery? : Speckyboy - Web Design, Web Development and Graphic Design Resources

  • Isaac

    Haha… the web blunders of 2008 post complains about the huge number of Twitter clones… Slightly ironic…

  • joe6pack

    this code almost works. unfortunately “sliding” doesn’t work with the source provided.

  • http://www.kweech.com James

    Its working on this site they have implemented it to the web appplication.

    http://www.kweech.com

  • http://cmdrk.net Commander K

    Great tutorial. Just one question, does anyone know how I can add message deletion?

  • Pingback: Crea tu propio Twitter con MooTools 1.2 | aNieto2K

  • Pingback: November Roundup « Craig Farrall’s Blog

  • Jason

    Ok so I ran through all the code….
    everything works but….
    the $_POST array is always empty even after submitting
    I hard coded a dummy insert status and it enters the table just fine but
    I can’t seem to get anything out of the $_POST array
    I even get a 200 from firebug with all the right post data
    any help???

  • http://www.intekhab.co.cc intekhab khan

    very good tutorial

  • Muhammad Ali Mansoor

    Good Work!

  • moo-newbie

    Good Work! I wonder if the “tweets” deletion could be make using another post I have found in your blog.

    http://davidwalsh.name/animated-ajax-record-deletion-mootools

    ¿Could you tell me how to integrate this?

    • Pratik

      even im looking for the same.. plz let me know when this is possible

  • Kepler

    BUG REPORT :

    Fx.Slide is not a constructor
    (?)()()nettuts-…-file.php (ligne 29)
    returns()mootools…ore-nc.js (ligne 607)
    create()mootools…ore-nc.js (ligne 612)
    fireEvent()mootools…ore-nc.js (ligne 2015)
    fireEvent()mootools…ore-nc.js (ligne 2016)
    domready()mootools…ore-nc.js (ligne 2830)
    defn()mootools…ore-nc.js (ligne 1958)

    [Break on this error] mode: ‘horizontal’

    What kind of mootools do you use ?

  • Kepler

    This error appear with the latest Mootools : mootools-1.2.1-core-nc.js

  • http://www.riderznet.com zaanrider

    wow nice tutorial

  • Pingback: 25 Useful MooTools Tutorials

  • http://myfacefriends.com Myfacefriends

    this is im looking thanks.

  • Pablo DiCiacco

    To: Someone with complete success with this,

    Can you clarify the correct naming in the db section? Where this tut shows “nettuts1″ on line 11, what does that name reflect? The php-file name?
    The db name? ???

    • Pratik

      its the table name… replace it by ‘statuses’, if u are using the SQL query above

      • Pablo DiCiacco

        Thanks, Had this set up for some time, but just cleared bunches of nonsense messages from the db.
        ?: Is this setup intended to show any username when entered? That part isn’t working for me. (?)
        Pablo

  • Pingback: blogg | animadverto corporate blog

  • Jim

    Check greenbor.com – it has twitter like micro blogging built in .NET and also it has other social networking features. I like a full blown social network like facebook rather than twitter

  • Pratik

    gr8 tutorial.. just 1 question is this architecture scalable ?

  • king

    buen tutorial

  • http://www.iddeasac.com jorge

    Vamos implementarlo es un web service que estamos desarrollando

  • Pingback: My Top Thirty Wordpress Themes : Speckyboy Design Magazine

  • Pingback: 50 of the Best Ever MooTools Plugins and Tutorials : Speckyboy Design Magazine

  • Pingback: 陈宝成のBlog » 16个SNS网站常用JS组件

  • Pingback: 50 of the Best Ever MooTools Plugins and Tutorials | WEBDESIGN FAN

  • Pingback: 16 Javascript Tutorials Inspired By Social Networking Sites | Dev Words

  • Pingback: Best of the Mootools plugins | 77even

  • TechMan8

    If only I knew anything about MySQL… that’s the only part I can’t figure out.

    What exactly am I supposed to do with the code in Step 1?

  • Prashant

    awesome!! if i’d be tweeting and tweeting then the page would scroll to infinite? any way to stop that?

  • jxd

    will this actually show up on your twitter ?

  • Pingback: 25 Useful MooTools Tutorials « PSD to HTML , Slicing PSD to HTML

  • GoodDog

    Isso é mara

  • http://mixa-blog.org.ua Mixa

    Not afraid to keep in the sample code examples information about database?
    http://clip2net.com/clip/m5763/1268130897-clip-2kb.png

  • http://none Justin

    Good tut bro, but what if I was to send the status to some one, how do you do the whole @ thing where you can even have multiple @ @ in the text field and it’s all sent to the correct people.

  • George

    Great tutorial. But how can I get rid of the refresh problem which adds the message repeatedly?

  • http://www.danielwhitedesign.com DanielWhiteDesign

    i have had a mess about with the code and started a twitter style website – looking good, but so many features to add? http://www.dwhitewebdesign.com/desfolio/ any advice???

    Thanks!

  • http://niyum.com Sitthykun LY

    great!!

    If it can use external javascript

    <input type="hidden" id="phpFile" value="”

  • Pingback: Twitter clone using MooTools/PHP | ajaxdump

  • http://thelab7.net Arif

    There is an error with this page. After the intro there is a tag that shows & the source code is showing on this page.

  • Josh

    wow great job works like a charm. I have one question though. I’m trying to use this so i can update statuses for all the users on my website to see when they are logged in. But im not sure how to only let me update statuses. any ideas, im not that good with php. would i have to set a specific user_id for me or something?

  • Pingback: MooTools Plug-ins for Javascript Die Hards | Devlounge

  • http://www.paulohsms.com Paulo Henrique

    Is it still working ?

  • Pingback: Twitter plugins | DaniloFreitas.net

  • http://www.democratandchronicle.com/apps/pbcs.dll/section?category=PluckPersona&U=f512eff83dd941febdf9c3388964ea01&plckPersonaPage=BlogViewPost&plckUserId=f512eff83dd941febdf9c3388964ea01& Rex Derflinger

    F*ckin’ awesome things here. I’m very happy to look your post. Thanks a lot and i’m looking forward to touch you. Will you kindly drop me a e-mail?

  • Pingback: Twitter Emulation Using MooTools 1.2 and PHP | Web Page Tutorials

  • http://www.docstoc.com/docs/76106967/Eradicate-Relationship-Problems---Talk-Forgive-and-Forget marriage help online