Sunday, November 21, 2010

9:32 PM
There's nothing like a subtle, slick website widget that effectively uses CSS and JavaScript to enhance the user experience.  Of course widgets like that take many hours to perfect, but it doesn't take long for that effort to be rewarded with above-average user retention and buzz.  


One of the widgets I love is Twitter's "Follow" button.  Let me show you how you can implement this functionality with three popular JavaScript toolkits:  MooTools, jQuery, and Dojo.
Note:  This tutorial will only display the client side handling of the form submission — NOT any PHP/MySQL/server-side handling of the request.

The HTML Structure


<form class="follow-form" method="post" action="twitter-follow.php">
<input type="hidden" name="followID" value="123456">
<button type="submit" value="Actions" class="btn follow" title="123456">
<i></i><span>follow</span>
</button>
</form>


The HTML for the button is very simple.  The structure revolves around a BUTTON element which contains an I element and SPAN element.  You're probably thinking "An I element?  WTF."  I know I did.  The truth of the matter is that the I element is deprecated and, as far as I'm concerned, and be used for any purpose the developer would like.  I'm also sure that Twitter doesn't mind saving bytes here or there

The CSS Styles


/* twitter button and its children */
button.btn { 
-moz-border-radius:4px;
-webkit-border-radius:4px;
background-attachment:scroll;
background-color:#ddd;
background-image:url(http://s.twimg.com/a/1282150308/images/buttons/bg-btn.gif);
background-position:0 0;
background-repeat:repeat-x;
border:1px solid #ddd;
border-bottom:1px solid #ccc;
color:#333;
cursor:pointer;
font-family:"Lucida Grande",sans-serif;
font-size:11px;
line-height:14px;
padding:4px 8px 5px 8px;
text-shadow:1px 1px 0 #fff;
vertical-align:top;
}
button.btn:hover {
border:1px solid #999;
border-bottom-color:#888;
color:#000;
background-color:#d5d5d5;
background-position:0 -6px;
}
button.btn:active {
background-image:none !important;
text-shadow:none !important;
}
button.btn i {
background-image:url(http://s.twimg.com/a/1282150308/images/sprite-icons.png);
background-position:-176px -32px;
background-repeat:no-repeat;
display:inline-block;
height:13px;
margin-right:5px;
width:15px;
}
button.btn i.active { background:url(http://s.twimg.com/a/1282150308/images/spinner.gif); }

/* properties for the element that is generated *after* following */
span.following {  background:#ffd; padding:5px 10px; }
span.following span { width:10px; height:9px; margin-right:5px; display:inline-block; background:url("http://s.twimg.com/a/1282150308/images/sprite-icons.png") -160px -16px no-repeat; }


Most of the styling for this button goes onto the BUTTON element itself.  You'll notice directives to round the button;  leaving the button sharp also please the eye.  Through the regular, hover, and active button states, check out how Twitter users the background position and colors to nicely modify the button without the need for additional images.  You'll also notice Twitter uses sprites...as should you.

The MooTools JavaScript


/* with mootools */
window.addEvent('domready',function() {
/* fetch elements */
$$('form.follow-form').each(function(form) {
/* stop form event */
form.addEvent('submit',function(e) {
/* stop event */
if(e) e.stop();
/* send ajax request */
var i = form.getElement('i');
new Request({
url: 'twitter-follow.php',
method: 'post',
data: {
followID: form.getElement('input').value
},
onRequest: function() {
i.addClass('active');
},
onSuccess: function() {
var button = form.getElement('button');
button.setStyle('display','none');
new Element('span',{
html: '<span></span>Following!',
'class': 'following'
}).inject(button,'after');
},
onComplete: function() {
i.removeClass('active');
}
}).send();
});
});
});


The first step is grabbing all of the FORM elements with the follow-form CSS class.  Upon form submission, the default submission action is stopped.  An AJAX request is fired, using the INPUT element's ID as the user to follow.  When the request is fired, the I element's background image is set to the spinner.  When the request is complete, the button is hidden and a new SPAN element is displayed informing the user that they are now following the given user!

The jQuery JavaScript


// Idiomatic jQuery by Doug Neiner
jQuery(function ($) {
/* fetch elements and stop form event */
$("form.follow-form").submit(function (e) {
/* stop event */
e.preventDefault();
/* "on request" */
$(this).find('i').addClass('active');
/* send ajax request */
$.post('twitter-follow.php', {
followID: $(this).find('input').val()
}, function () {
/* find and hide button, create element */
$(e.currentTarget)
 .find('button').hide()
 .after('<span class="following"><span></span>Following!</span>');
});
});
});


The code above is based off of the MooTools code.  The workflow is exactly the same.

The Dojo JavaScript


/* when the DOM is ready */
dojo.ready(function() {
/* fetch elements */
dojo.query('form.follow-form').forEach(function(form) {
/* stop form event */
dojo.connect(form,'onsubmit',function(e) {
/* stop event */
dojo.stopEvent(e);
/* active class */
dojo.query('i',form).addClass('active');
/* get button */
var button = dojo.query('button',form)[0];
/* ajax request */
dojo.xhrPost({
form: form,
load: function() {
dojo.style(button,'display','none');
dojo.create('span',{
innerHTML: '<span></span>Following',
className: 'following'
},button,'after');
}
});
});
});
});


The code above is based off of the MooTools code.  The workflow is exactly the same.

This "Follow" button is only one of many details that Twitter has paid attention to, just to make the user experience on the site better.  Take note from the effort put forth by large websites — adding these types of details to your smaller websites can make the user experience much better for YOUR users!

0 comments: