Posted by Rob | Posted in Code, Javascript, MooTools | Posted on 22-10-2009
Tags: Ajax, Content, facebook, LinkedIn, loader, Mootools
Welcome to my second attempt at writing up a mootools class. This one’s a little more advanced this time.
It attaches an Ajax handler to all links on a page which conform to the selector you give it. For example, you can tell it to attach to all standard links (<A HREF=’/here/’>Hello</A>), or links with a specific class as i’ve done with the code below (<A HREF=’/here/’ CLASS=’ajax’>Hello</A>).
I hope someone finds this useful. As ever this was created after I kept saying that I could write something a hell of a lot better than anything else I was finding. This might be a bold statement, but I was having trouble finding anything that would do the job, and simply.
(Demo to come, I’m just posting the code up right now.)
/*
* ContentHandler
*
* Content handler that attaches to links and loads content through AJAX
*
* @author Rob Taylor
* @created 28/09/09
* @modified 29/09/09
* @version 1.3.5.10
*/
var ContentHandler = new Class({
Implements: [Options, Events, Log],
options : {
// Array of container elements to load via AJAX
container : $('content'),
// Loading graphic and text to display while working
loadingImage : '/images/ajax-loader.gif',
loadingMessage : 'Loading Content...',
// How much Opacity to set on 'Container' while loading new page.
loadingTransparency : 0,
// Type of link to load via AJAX. Defaults to <a> tags
linkIdentifier : 'a',
// TRUE to enable console logging. FALSE by default
debugMode : false
},
currentURL : '',
isNavigating : false,
/*
* initialize
*
* Default constructor. Sets configuration options, attaches load event links and triggers initial load
*
* @param mixed options Array of config options. Supported elements:
* container - Container element to load Ajax into
* loadingImage - URL of image to display while working
* loadingMessage - Message to display while working
* loadingTransparency - Transparency level of 'container' when request is made. Must be between 0 and 1. Defaults to 0
* linkIdentifier - HTML tagname to attach onclick loader to. Defaults to <a>
* debugMode - TRUE to enable console logging. FALSE by default
*/
initialize : function( options ) {
// Set configuration options
this.setOptions(options);
this.debug('Starting :: ContentHandler');
// Loop through link elements attaching loader
$$(this.options.linkIdentifier).each( function( element ){
this.attachHandler( element );
}.bind(this));
// Do initial content load if location is specified
if( window.location.hash && window.location.hash.length > 1 )
{
// Get initial page
var url = window.location.hash.substr( 1, window.location.hash.length );
this.getContent( url, true );
}
// Attach check to re-load content if URL changes or previous attempt fails
this.updateContent.periodical( 200, this );
},
/*
* createLoader
*
* Populates and displays
*/
createLoader : function(){
this.debug('Creating :: Loader Image');
// Container padding
var padding = 40;
// Create image element
var content = $( this.options.container );
var loaderImage = new Element( 'img', {
src : this.options.loadingImage,
alt : 'Loading',
title : 'Loading'
});
// Create test element
var loaderMessage = new Element( 'div' ).set('text',this.options.loadingMessage);
loader = new Element( 'div' );
// Style elements
content.setStyle( 'position', 'relative' );
loader.setStyles({
margin : 'auto',
textAlign : 'center',
position : 'absolute',
opacity : 0
});
// Autoresize container onload to fit image
loaderImage.addEvent('load', function(){
loader.setStyles({
height : ( loaderImage.getSize().y + padding ),
width : ( loaderImage.getSize().x + padding ),
top : 20 + content.getPosition().y,
left : ( ( ( content.getSize().x / 2 ) - ( loaderImage.getSize().x / 2 ) ) - padding ) + content.getPosition().x
});
});
// Add image and message to container
loader.adopt( loaderImage,loaderMessage );
// Attach loader to content area and fade in
$(document.body).adopt( loader );
loader.fade('in');
},
destroyLoader : function(){
if( loader )
loader.destroy();
},
getContent : function( url, freshStart ){
this.debug('Collecting :: Page Content');
var content = $( this.options.container );
if( this.isNavigating && request_content )
request_content.cancel();
request_content = new Request.HTML({
url : url,
method : 'get',
link : 'cancel',
update : content,
onRequest : function(){
this.debug('Collecting :: Page Content -> Request Made');
// Set active request flag (prevents periodical spawning simultaneous requests)
this.isNavigating = true;
// Store current content in case of rollback (e.g. if request fails)
content.store( 'content', content.get('html') );
if( freshStart ){
// Flush content
content.empty();
}
else{
content.get('tween', {
property: 'opacity',
duration: 'normal'
}).start( this.options.loadingTransparency );
}
// Display loaders
this.createLoader();
}.bind(this),
onComplete : function(){
this.debug('Collecting :: Page Content -> Complete');
// Reset active request flag
this.isNavigating = false;
this.destroyLoader();
if( !freshStart ){
content.get('tween', {
property: 'opacity',
duration: 'short'
}).start(1);
}
}.bind(this),
onSuccess : function(){
this.debug('Collecting :: Page Content -> Success');
// Track new content URL
this.currentURL = url;
// Flush stored content
content.store( 'content', '' );
if( !freshStart ){
window.location.hash = url;
}
content.getElements( this.options.linkIdentifier ).each( function( inner_element ){
this.attachHandler( inner_element );
}.bind(this));
this.debug('Current URL: '+this.currentURL);
}.bind(this),
onFailure : function(){
this.debug('Collecting :: Page Content -> Fail');
// Retrieve stored content
content.retrieve( 'content' );
}
}).send();
return false;
},
attachHandler : function( element ){
if( $(element) ){
if( this.checkLink( $(element).get('href') ) )
{
url = $(element).get('href');
//this.debug('Adding Handler : "'+url+'"');
$(element).addEvent('click', this.getContent.bind(this,url) );
}
}
else{
this.debug('No Valid Element.');
}
},
updateContent : function(){
var url = window.location.hash.substr( 1, window.location.hash.length );
if( this.currentURL != url && !this.isNavigating && this.checkLink( url ) ){
this.debug('Updating :: Page Content: "'+url+'"');
this.getContent( url );
}
},
checkLink : function( url ){
if( url.test('^http:|^https:' ) ) // We're assuming here, that external links, do not want to be loaded inside the container.
return false;
return true;
},
debug : function( message ){
if( !this.options.debugMode )
return;
this.log( '[Content Handler] ' + message );
}
});
document.addEvent('domready', function(){
content = new ContentHandler({
linkIdentifier : 'a.ajax' // this will attach to any link with a class of 'ajax'.
//linkIdentifier : 'a' // This will attach to any link.
});
});
Available Options
- container : Container element to load Ajax into
- loadingImage : URL of image to display while working
- loadingMessage : Message to display while working
- loadingTransparency : Transparency level of ‘container’ when request is made. Must be between 0 and 1. Defaults to 0
- linkIdentifier : HTML tagname to attach onclick loader to. Defaults to <a>
- debugMode : TRUE to enable console logging. FALSE by default

Like
I'm a 26 year old 





