MooTools Overlay Plugin

Written by David Walsh on Tuesday, December 22, 2009


Overlays have become a big part of modern websites; we can probably attribute that to the numerous lightboxes that use them. I’ve found a ton of overlay code snippets out there but none of them satisfy my taste in code. Many of them are bloated, inflexible, or nonfunctional. The only way to make myself happy was to create one of my own.

The MooTools Javascript

var Overlay = new Class({
	
	Implements: [Options,Events],
	
	options:  {
		id: 'overlay',
		color: '#000',
		duration: 500,
		opacity: 0.5,
		zIndex: 5000/*,
		onClick: $empty,
		onClose: $empty,
		onHide: $empty,
		onOpen: $empty,
		onShow: $empty
		*/
	},
	
	initialize: function(container,options) {
		this.setOptions(options);
		this.container = document.id(container);
		this.overlay = new Element('div',{
			id: this.options.id,
			opacity: 0,
			styles: {
				position: 'absolute',
				background: this.options.color,
				left: 0,
				top: 0,
				'z-index': this.options.zIndex
			},
			events: {
				click: function() {
					this.fireEvent('click');
				}.bind(this)
			}
		}).inject(this.container);
		this.tween = new Fx.Tween(this.overlay,{ 
			duration: this.options.duration,
			link: 'cancel',
			property: 'opacity',
			onStart: function() {
				var size = this.container.getScrollSize();
				this.overlay.setStyles({
					width: size.x,
					height: size.y
				});
			}.bind(this),
			onComplete: function() {
				this.fireEvent(this.overlay.get('opacity') == this.options.opacity ? 'show' : 'hide');
			}.bind(this)
		});
	},
	open: function() {
		this.fireEvent('open');
		this.tween.start(this.options.opacity);
	},
	close: function() {
		this.fireEvent('close');
		this.tween.start(0);
	}
});

Arguments for Overlay include:

  • container: The container of that will host the overlay.
  • options: The class’ options.

Options for Overlay include:

  • id: (defaults to ‘overlay’) The ID of the overlay to be created.
  • color: (defaults to ‘#000′) The background color of the overlay.
  • duration: (defaults to 500) The open/close duration of the overlay.
  • opacity: (defaults to 0.5) The destination opacity level of the overlay.
  • zIndex: (defaults to 5000) The z-index of the overlay.

Events for Overlay include:

  • onClick: Executes when the overlay is clicked
  • onClose: Executes when the close directive has been given
  • onHide: Executes when the overlay is completely hidden
  • onOpen: Executes when open directive is given
  • onShow: Executes when overlay has faded into view

The Usage

var overlay = new Overlay(document.body,{
	id: 'overlay',
	color: '#000',
	duration: 300,
	opacity: 0.4,
	onClick: function() {
		this.close();
	},
	onShow: function() {
		//make ajax call while the overlay is happening...?
		//var Request = new Request()....
	}
});

As simple as it gets. Be sure to set the “id” option if you plan on using more than one overlay in the page (boooo).

Overlay Guidelines

A few notes about overlays:

  • Please, please, please use the click event above to hide the overlay:
    onClick: function() {
    	this.close();
    }
    
    Nothing bugs me more than clicking on an overlay and nothing happening.
  • Use the same background color for your overlays — consistency is key.
  • Try to stick to using/re-using the same overlay — creating a bunch of them only pollutes the DOM.

Now your body can easily get overlaid! Sweet!


Epic Discussion

Commenter Avatar December 22 / #
Timothy says:

Not bad. I have a custom class I’ve set up which does the same thing. It shows a veil over the page with a ‘Loading’ status at the top left.

I use mine whenever I am doing an Ajax request, to prevent users from doing anything to page.

Mine has the following methods:
Loading [+ 1 to loading queue, brings up veil if needed]
loaded [-1 to loading queue, hides veil if queue is empty]
toggle [if no veil, calls loading. if veil, calls loaded]
lock [+1 to lock queue, keeps veil up even if loaded]
unlock [-1 to lock queue, hides veil if no locks or loads]
toggleLock [if locked, calls unlock. if not locked, calls lock]
lightsOff [makes veil mostly opaque]
lightsOn [back to default transparency]
toggleLights [toggles lightsOn / lightsOff]
forceOff [clears queues, hides veil]
timeless [no timeout on veil]
timed [back to default, where veil calls forceOff after 90 seconds]
toggleTimed [toggles timed / timeless]

Also, when loading the veil has a z-index of 20. When locked it has a z-index of 10. These can be overridden in the options.

I do use a small amount of HTML in the footer, since I have a loading image next to ‘Loading.’ You could avoid this by not using the image and injecting the elements via DOM on init.

Commenter Avatar December 22 / #

Very nice! Thanks for the post.

Commenter Avatar December 22 / #
Commenter Avatar December 22 / #
EmEhRKay says:

Nice. I love the perceived simplicity of the code, but it is full-featured — it does one thing and does it well.

To reuse the same instance I would do a window.Overlay = new Overlay(..) in a dom ready call and just call window.Overlay.show/hide when I needed to cover the whole window.

Good stuff

Commenter Avatar December 22 / #
Adriaan says:

@Timothy: please give a link to your class…

Commenter Avatar December 22 / #

Why not do more of this in css?

All of my overlays are just css.

background: black;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1000;

Even the transparency can be done in css.

Granted position:fixed may not work 100% in IE6, but come on… it’s IE 6.

I like this better because it works better when resizing the window. (JS is too slow in IE and FF … IMO)

For the fade in I just do something like:
fade(‘hide’);
fade(‘in’);

Commenter Avatar December 23 / #
Richard says:

Great stuff indeed! :D

Commenter Avatar December 23 / #
olivier says:

isn’t there already a class for this in mootools’ More?

Commenter Avatar December 23 / #
Nikolaj says:

@ olivier & Marc Fowler
You can in a way say that More already does have such class – though there’s differences between them.

A short comparison of the two versions:

Mask version:
- No support for Fx
- Size is calculated by .getSize()
- Ability to add a mask over a specific Element through .mask()
- IframeShim-support, to fix IE6’s issue with selectboxes, flash etc

David’s version:
- Support for Fx, giving ability to use fade-in/out
- Size is calculated by .getScrollSize()
- Much more simplified, does exactly what it’s supposed to

Since Mask uses .getSize(), it gives issues if the user manages to scroll down the page. Both versions have a small issue if switching between normal and fullscreen-view though, where the size of the mask aren’t updated like it probably should (if mask is put inside the document.body).

Commenter Avatar December 29 / #

hi , very nice posting, please post more like this

Commenter Avatar December 30 / #
Crispijn says:

Maybe you should add an window.resize function to it so your overlay is always the correct size!

But nice plugin, I just needed this!

David Walsh December 30 / #

@Crispijn: Seems like an edge case.

Commenter Avatar December 30 / #
Crispijn says:

Yeah… I thought: Small tweak, and more effort but it isn’t necessary indeed.

David Walsh December 30 / #

@Crispijn: Not so much about effort as it is about adding extra code. I may extend the class in the future to do more advanced things.

Commenter Avatar January 03 / #
theodore says:

Hi, very nice! I just used it to generate a greeting card for my home page (see below) and it works very well except one minor issue…the new image element created upon ‘onShow’ was also faded out (even if a z-index had been set for the image to >5000). How to make the image remains original? Thanks and happy new year!


window.addEvent('domready',function() {
new Overlay(document.body, {
duration: 400,
opacity: 0.5,
onShow: function() {
new Element('img', {
'id': 'greetingcard',
'src': '2010.jpg',
'width': 800,
'height': 400,
'styles': {
'position': 'absolute',
'top': 100,
'left': 200
}
}).inject(document.body);
},
onClick: function() {
$('card').destroy();
this.close();
}
}).open();
});

Commenter Avatar March 08 / #
John says:

Hello i have problem, i want to use the overlay by calling of a funtion:

window.addEvent(‘domready’,function() {
var olay = new Overlay(document.body, {
duration: 400,
onClick: function() { this.close(); }
});
});

//Change DIV tab
function showDiv(t){
if(t==1){
document.getElementById(‘Div’).style.display=’block’;
olay.open();
}
if(t==0){
document.getElementById(‘Div’).style.display=’none’;
olay.close();
}
}

But i give a error:

olay is not defined: olay.open();

Please help me.

Thanks

David Walsh March 08 / #

@John: Your “olay” variable has lost scope. You need to give the olay variable global scope for your stuff to work, although I don’t advise it.

Be Heard!

I want to hear what you have to say! Share your comments and questions below.

Name*:
Email*:
Website:  


© David Walsh 2007-2010. Contact David Walsh. Powered by the remarkable MooTools javascript framework.