MooTools Overlay Plugin

By  on  

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!

Recent Features

  • By
    Designing for Simplicity

    Before we get started, it's worth me spending a brief moment introducing myself to you. My name is Mark (or @integralist if Twitter happens to be your communication tool of choice) and I currently work for BBC News in London England as a principal engineer/tech...

  • By
    Create a CSS Flipping Animation

    CSS animations are a lot of fun; the beauty of them is that through many simple properties, you can create anything from an elegant fade in to a WTF-Pixar-would-be-proud effect. One CSS effect somewhere in between is the CSS flip effect, whereby there's...

Incredible Demos

  • By
    MooTools CountDown Plugin

    There are numerous websites around the internet, RapidShare for example, that make you wait an allotted amount of time before presenting you with your reward. Using MooTools, I've created a CountDown plugin that allows you to easily implement a similar system. The MooTools JavaScript The CountDown class...

  • By
    jQuery UI DatePicker:  Disable Specified Days

    One project I'm currently working on requires jQuery. The project also features a datepicker for requesting a visit to their location. jQuery UI's DatePicker plugin was the natural choice and it does a really nice job. One challenge I encountered was the...

Discussion

  1. 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.

  2. Very nice! Thanks for the post.

  3. EmEhRKay

    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 domready call and just call window.Overlay.show/hide when I needed to cover the whole window.

    Good stuff

  4. @Timothy: please give a link to your class…

  5. 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');
    
  6. Great stuff indeed! :D

  7. olivier

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

  8. Nikolaj

    @ 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).

  9. hi , very nice posting, please post more like this

  10. 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!

  11. @Crispijn: Seems like an edge case.

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

  13. @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.

  14. theodore

    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();				
    	});
    
  15. John

    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

  16. @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.

  17. Hello, I’m in the same camp with theodore up there…
    Can’t figure out how to have non-trasparent elements inside the overlay…

    Any hint will be very appreciated :)

    Bau,
    Wiz

  18. Thorsten

    After hiding the overlay again and resizing the window it causes nasty scrollbars as the hidden overlay is keeping the old window width. (tested on mac -> FF and safari)

    Anyone here with a workaround to fix this?

  19. Is there any way to use the overlay without an animation?
    I’d like to have overlay.set() on ‘domready’ and use overlay.start() on ‘load’.

    This is what I’ve tried, somehow this.tween.set() just doesn’t work:

    Overlay.implement({
    set: function() {
    this.fireEvent(‘set’);
    this.tween.set(this.options.opacity);
    }
    });

  20. Paddy

    Hi,
    how i can set the opacity of my content box “text” to 100%?

    var test = new Element('div', {
        'styles': {
              'background-color': '#FFF',
                'width': 300,
    'height': 200,
    'position': 'absolute',
    'top': 10,
    'left': 200
        },
    'html': 'test'
    });
    
    $('overlay').grab(test);
    

    thanks

  21. Sky

    It has a bug in it –

    on high resolution screens (above 1440×900) the dark area on your Demo does not cover entire page. There can be a huge gap on right.

  22. Crispijn

    @Sky: does this appear after you’ve changed the window size? This is correct. You can change this by adding a onResize event to the class.

  23. Han Solo

    Hi there,

    is there any possibility to fix the content of the first div layer while this overlay is open (and scrollable), and make it scrollable again when the overlay is closed?

    I’m a absolute beginner in terms of HTML, JS and CSS. But what I did so far is set up a HTML file with linked images. This page is scrollable. When I click on a image I use your Overlay script to fade-in a dark background make a hidden div visible. This div contains either text, several images or flash video. I use onShow document.getElementById("overlaycontent").style.display = 'block'; onClose I use document.getElementById("overlaycontent").style.display = 'none'. This works so far.

    But how can I make the lower content div unscrollable while the overlay is scrollable and on close the other way round? I tried to use document.getElementById("content").style.position = 'fixed'. But than the background jumps to the first position. It should be fixed at the current scroll position. Any idea?

    I hope you got me :)

  24. false

    @Crispijn: Hi, did you tried to add a ‘onResize’ event to your overlay class ? If yes, what did you do in this event ? Because i have this issue and i would like to solved it :/ but fail

    ty :)

  25. aschemel

    how can i embed a html in the overlay, i want the overlay to carry a form, so i can edit some text fields? I new in web developing =D

  26. bobgodwin

    How do I change “shower” to a class instead of an id. I’d like to use it on several links.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!