Fork me on GitHub

30 days of
MooTools


30 days of MooTools is a collection of tutorials to learn to use the MooTools javascrit library, first published in 2008 by ConsiderOpen.

The lessons are actually 23, as they where interrupted after this day.

As the original site is currently offline, the tutorials have been collected using the Wayback Machine to make them available to everyone interested in learning to use MooTools.

The tutorials are based on MooTools 1.2 so some parts could be deprecated and they should be updated and expanded based on the new MooTools versions.

The copyright (and gratitude) for the original lessons is hold by ConsiderOpen.




Idea Paolo Manganiello. Licence CC 3.0.

Project - A few ways to created “tabbed” content

If you haven’t already, be sure and check out the rest of the Mootools 1.2 tutorials in our 30 days series.

Welcome back to 30 days of Mootools. From here on out, we are going to loosen our publishing schedule, instead of every day, you can expect new tutorials every few days because we are pretty busy.

Today, we are going to break away from the our coverage of the library and programming basics to do a short project. Using what we have learned so far, there are several ways we can use tabs (and other li’s) to create content that will only show on hover or on click.

Simple “Extra Info” Tabs

Tabs with info on hover

For this first step, we are going to create a simple menu that will reveal additional info when you hover over a list item. First, set up the html - lets do a ul with four items, then create four divs (one corresponding to each list item):

<!-- here is our menu -->
<ul id="tabs">
   	<li id="one">One</li>
        <li id="two">Two</li>
        <li id="three">Three</li>
        <li id="four">Four</li>
</ul>
 
<!-- and here are our content divs -->
<div id="contentone" class="hidden">content for one</div>
<div id="contenttwo" class="hidden">content for two</div>
<div id="contentthree" class="hidden">content for three</div>
<div id="contentfour" class="hidden">content for four</div>

For now, let’s not worry about making this pretty. In the css, all we need to do is hide the content boxes:

.hidden {
	display: none;
}

Now, for the Mootools. If we want the content to show when someone mouses over it and hide when they leave, we need to set up some functions:

var showFunction = function() {
	this.setStyle('display', 'block');
}

var hideFunction = function() {
	this.setStyle('display', 'none');
}

and some events:

window.addEvent('domready', function() {
	//here we can pass our container elements to a var
	var elOne = $('contentone');

	$('one').addEvents({
		//for the mousenter event, we call showFunction
		//and bind elOne, so we can pass the element to the function
		'mouseenter': showFunction.bind(elOne),
		'mouseleave': hideFunction.bind(elOne)
	});
});

Now, we just repeat this pattern for each tab and the corresponding content. Here it is complete:

//here are our functions to change the styles
var showFunction = function() {
	this.setStyle('display', 'block');
}

var hideFunction = function() {
	this.setStyle('display', 'none');
}

window.addEvent('domready', function() {
	//here we turn our content elements into vars
	var elOne = $('contentone');
	var elTwo = $('contenttwo');
	var elThree = $('contentthree');
	var elFour = $('contentfour');

	//add the events to the tabs
	$('one').addEvents({
		//set up the events types
		//and bind the function with the variable to pass
		'mouseenter': showFunction.bind(elOne),
		'mouseleave': hideFunction.bind(elOne)
	});

	$('two').addEvents({
		'mouseenter': showFunction.bind(elTwo),
		'mouseleave': hideFunction.bind(elTwo)
	});

	$('three').addEvents({
		'mouseenter': showFunction.bind(elThree),
		'mouseleave': hideFunction.bind(elThree)
	});

	$('four').addEvents({
		'mouseenter': showFunction.bind(elFour),
		'mouseleave': hideFunction.bind(elFour)
	});
});

As you can see, this is all very familiar and setting this up doesn’t require anything we havn’t covered so far.

  • One
  • Two
  • Three
  • Four
content for one
content for two
content for three
content for four

Tabs that show content on click

Taking the idea above, we can easily adjust it to reveal content on click. Let’s use the same html as above, and adjust the Mootools code for a click event.

First, we are going to need to adjust our functions. Since we can’t hide the content on mouseleave, we need to find another way to switch between the divs. Perhaps the easiest option is to hide them all on click, and just show “this” one (being whichever one is passed on click):

var showFunction = function() {
	$$('.hiddenB').setStyle('display', 'none'); 
	this.setStyle('display', 'block');
}

Now, when we pass the function an element using bind, it will hide the others and reveal that element.

Next, we need to adjust events. First, we only need a single event, so we will use .addEvent();, and next we need to change the event type to ‘click.’

window.addEvent('domready', function() {
	var elOneB = $('contentoneB');
	var elTwoB = $('contenttwoB');
	var elThreeB = $('contentthreeB');
	var elFourB = $('contentfourB');
 
	$('oneB').addEvent('click', showFunction.bind(elOneB));
	$('twoB').addEvent('click', showFunction.bind(elTwoB));
	$('threeB').addEvent('click', showFunction.bind(elThreeB));
	$('fourB').addEvent('click', showFunction.bind(elFourB));
});
  • One
  • Two
  • Three
  • Four
content for one
content for two
content for three
content for four

Morph Content Tabs

Extending on the code we have above, we can add some morph functionality when our hidden content is displayed. To begin, we can set up an Fx.Morph effect just like the previous example, except instead of setting the styles, we will morph them. Of course, we also have to create our morph objects:

var showFunction = function() {
	//resets all the styles before it morphs the current one
	$$('.hiddenM').setStyles({
		'display': 'none',
		'opacity': 0,
		'background-color': '#fff',
		'font-size': '16px'
	}); 

	//here we start the morph and set the styles to morph to
	this.start({
		'display': 'block',
		'opacity': 1,
		'background-color': '#d3715c',
		'font-size': '31px'
	});
}

window.addEvent('domready', function() {
	var elOneM = $('contentoneM');
	var elTwoM = $('contenttwoM');
	var elThreeM = $('contentthreeM');
	var elFourM = $('contentfourM');

	//creat morph object
	elOneM = new Fx.Morph(elOneM, {
		link: 'cancel'
	});
	
	elTwoM = new Fx.Morph(elTwoM, {
		link: 'cancel'
	});
	
	elThreeM = new Fx.Morph(elThreeM, {
		link: 'cancel'
	});
	
	elFourM = new Fx.Morph(elFourM, {
		link: 'cancel'
	});

	$('oneM').addEvent('click', showFunction.bind(elOneM));
	$('twoM').addEvent('click', showFunction.bind(elTwoM));
	$('threeM').addEvent('click', showFunction.bind(elThreeM));
	$('fourM').addEvent('click', showFunction.bind(elFourM));
});

If we use the same html that we have above, we will get something like this:

  • One
  • Two
  • Three
  • Four
content for one
content for two
content for three
content for four

Note: If you click on the above example quickly you will see that it pushes out multiple content divs. Basically, if showFunction is called before the last one finishes tweening, it will not register it when it hides all content divs. To solve this, we are going to need to break out of this exact formula, and play a bit with Fx.Elements.

Example

This example works just like the above example, except when you click on two tabs quickly, it will not “stack” the content divs.

//create a "hide all" function

//create a parameter so you can pass the element
var hideAll = function(fxElementObject){
	fxElementObject.set({
		'0': {
			'display': 'none'
		},
		'1': {
			'display': 'none'
		},
		'2': {
			'display': 'none'
		},
		'3': {
			'display': 'none'
		}
	});
}

//here we create a function for each content element
var showFunctionOne = function() {
	//first, call the hideAll function
	//then pass "this" as the Fx.element object
	hideAll(this);
	//start the Fx.element morph for the index that corresponds to the click event
	this.start({
		'0': {
			'display': ['none', 'block'],
			'background-color': ['#fff', '#999'],
			'font-size': ['16px', '25px']
		}
	});
}

var showFunctionTwo = function() {
	hideAll(this);
	this.start({
		'1': {
			'display': ['none', 'block'],
			'background-color': ['#fff', '#999'],
			'font-size': ['16px', '25px']
		}
	});
}

var showFunctionThree = function() {
	hideAll(this);
	this.start({
		'2': {
			'display': ['none', 'block'],
			'background-color': ['#fff', '#999'],
			'font-size': ['16px', '25px']
		}
	});
}

var showFunctionFour = function() {
	hideAll(this);
	this.start({
		'3': {
			'display': ['none', 'block'],
			'background-color': ['#fff', '#999'],
			'font-size': ['16px', '25px']
		}
	});
}

window.addEvent('domready', function() {
	//create your array to pass to Fx.elements
	var morphElements = $$('.hiddenMel');

	//create a new Fx.Element object
	var elementEffects = new Fx.Elements(morphElements, {
		//set the "link" option to cancel
		link: 'cancel'
	}); 

	$('oneMel').addEvent('click', showFunctionOne.bind(elementEffects));
	$('twoMel').addEvent('click', showFunctionTwo.bind(elementEffects));
	$('threeMel').addEvent('click', showFunctionThree.bind(elementEffects)); 
	$('fourMel').addEvent('click', showFunctionFour.bind(elementEffects)); 
});
  • One a
  • Two
  • Three
  • Four
content for one
content for two
content for three
content for four

To Learn More…

This one is mostly a review and an application of the stuff we covered in the previous tutorials. As such, I am going to recommend that you read over the docs, in full, if you haven’t already. It’s more fun than it sounds. If you are new to the library and have been learning along with this tutorial, you may be surprised at how much you understand.

Tomorrow’s Tutorial

Classes part 2