Apr
18
2012

MooTools FullScreen API Wrapper

The other day I released a quick method to extend the full screen API to any DOM element thats supports full screen. (view)

Today I am pleased to release a fully functional API wrapper that supports events and maintains its state as well as merges the F11 key with the api all with an easy to use mootools class. Skip to the demo

The Class

/**
 * FullScreen
 * A Mootools wrapper of the FullScreen API.
 *
 * @copyright Copyright (c) 2011, Tim Wickstrom
 * @link http://www.timwickstrom.com Tim Wickstrom Blog
 * @version 0.2
 *
 * @License
 * This content is released under the (http://www.opensource.org/licenses/MIT) MIT License.
 *
 * @Attribution not required (but appreciated)
 * 
 * @Changelog
 * Version 0.2
 * 		- Fixed IE F11/Click Event Bug
 * Version 0.1
 *      - Initial Release
**/

var FullScreen = new Class({
	
	Implements: [Options, Events],	
	
	options: {
		/*	AVAILABLE EVENTS:
			onOpen: function(){},
			onClose: function(){},
			onBeforeStart: function(){},
			onDisabled: function(securityPrevention){}
		*/
		opener: '', // id (str) - required
		closer: '', // id (str) - optional
		target: '', // id (str) - optional default document.body
		ie: true, // true/false (boolean) - OLD IE support
		forceFull: false, // true/false (boolean) - forces the full screen target to be 100% width and 100% height default false
		classes: 'fullscreen' // adds classname to HTML element on full screen optional See CSS for more info
	},

	/* Initializes the Class */
	initialize: function(opener, closer, options) {
		// Set our options
		this.setOptions(typeOf(closer)=='object'?closer:options);
		
		// Lets try and rememeber our state
		this.state = 'normal';
		
		this.opener = document.id(opener) || false;
		
		this.closer = document.id(closer) || false;
		
		// Cache some variables
		this.target = document.id(this.options.target || document.body);
		this.html = document.id(document.html);
		
		// THIS IS BAD... and will need to be reworked but easiest way to know what we are dealing with
		this.types = {
			moz: {
				change: 'mozfullscreenchange',
				full: 'mozRequestFullScreen',
				cancel: 'mozCancelFullScreen',
				state: 'mozFullScreen'
			},
			webkit: {
				change: 'webkitfullscreenchange',
				full: 'webkitRequestFullScreen',
				cancel: 'webkitCancelFullScreen',
				state: 'webkitIsFullScreen'
			},
			w3c: {
				change: 'fullscreenchange',
				full: 'requestFullscreen',
				cancel: 'exitFullscreen',
				state: 'fullscreen'
			}
		}
		
		// If IE and OLD IE is supported lets test it out and target is IE
		if(this.options.ie && this.target == document.body && typeof window.ActiveXObject != "undefined") {
			try {
				this.wscript = new ActiveXObject("WScript.Shell");
			} catch(e){
				this.wscript = false;
			}	
		}
		
		// OK Lets see what we are dealing with
		this.client = this.test();
		
		// If were are enabled lets GO!
		if(this.client.enabled) {
			if(this.opener) {
				this.addOpener(this.opener);
			}
			if(this.closer) {
				this.addCloser(this.closer);
			}
			// Only firefox will force full mode on elements (not sure if this is good, prob not for videos, but we can easily extend te everyone if we want to)
			if(this.options.forceFull) {
				this.target.store('prevStyle',this.target.getStyles('margin', 'padding', 'width', 'height', 'border'));
			}
		} else {
			// Add Class of disabled to our buttons if full screen is not supported
			if(this.opener) {
				this.opener.addClass('disabled');	
			}
			if(this.closer) {
				this.opener.addClass('disabled');	
			}
			
			// Nothing to do here but lets provide a method to return to the programmer
			this.state = 'disabled';
			this.fireEvent('disabled', !this.client.enabled && this.client.oldIE ? true : false);
		}
		
		// Lets make sure to support native full screen functionality
		document.id(document).addEvent('keydown', function(e) {
			if(e.code==122 && this.client.enabled) {
				if(this.options.ie && Browser.ie) {
					this.state = 'fullscreen';
					this._set();
				} else {
					if(this.state == 'normal') {
						e.stop();
						this.opener.fireEvent('click');
					} else if(this.closer) {
						e.stop();
						this.closer.fireEvent('click');
					}
				}
			}
		}.bind(this));
		
		// browsers disable escape key detection when in fullscreen so lets!
		if(this.client.html5) { 
			var self = this;
			document.addEventListener(self.types[self.client.prefix].change, function (e) {
				if(!document[self.types[self.client.prefix].state] && self.state=='fullscreen') {
					self.state = 'normal';
					self._remove();
				}
			}, false);
		}
	},
	_set: function() {
		if(this.options.ie && Browser.ie && !this.ieTimer) {
			this.ieTimer = this.ieMonitor.periodical(100,this);
		}
		this.html.addClass(this.options.classes);
		if(this.options.forceFull) {
			this.target.setStyles({
				border: 'none',
				margin: '0',
				padding: '0',
				width: '100%',
				height: '100%'
			});
		}
		this.fireEvent('open');
	},
	_remove: function() {
		this.html.removeClass(this.options.classes);
		if(this.options.forceFull) {
			this.target.setStyles(this.target.retrieve('prevStyles'));
		}
		this.fireEvent('close');	
	},
	open: function() {
		if(this.state != 'fullscreen') {
			this.state = 'fullscreen';
			if(this.client.html5) {
				this.fireEvent('beforeStart');
				this.target[this.types[this.client.prefix].full].call(this.target);
				this.state = 'fullscreen';
			} else if(this.options.ie && Browser.ie) {
				this.fireEvent('beforeStart');
				this.wscript.SendKeys("{F11}");
			}
			if(this.state=='fullscreen') {
				this._set();
			}
		}
	},
	close: function() {
		if(this.state != 'normal') {
			if(this.client.html5) {
				document[this.types[this.client.prefix].cancel].call(document);
				this.state = 'normal';
			} else if(this.options.ie && Browser.ie) {
				this.state = 'normal';
				this.wscript.SendKeys("{F11}");
				this.ieClick = true;
			}
			if(this.state=='normal') {
				this._remove();
			}
		}
	},
	addOpener: function(str) {
		return document.id(str) != null ? document.id(str).addEvent("click", this.open.bind(this)) : false;
	},
	addCloser: function(str) {
		return document.id(str) != null ? document.id(str).addEvent("click", this.close.bind(this)) : false;
	},
	test: function() {
		return {
			enabled: (this.target.requestFullscreen || this.target.mozRequestFullScreen || this.target.webkitRequestFullScreen || this.target.msRequestFullScreen) || (this.options.ie && this.wscript !== false) ? true : false,
			html5: (this.target.requestFullscreen || this.target.mozRequestFullScreen || this.target.webkitRequestFullScreen || this.target.msRequestFullScreen) ? true : false,
			oldIE: Browser.ie ? true : false,
			prefix: this.target.requestFullscreen ? 'w3c' : this.target.mozRequestFullScreen ? 'moz' : this.target.webkitRequestFullScreen ? 'webkit' : ''
		}
		
	},
	ieMonitor: function() {
		var size = document.id(document.body).getSize();
		var scrollSize = document.id(document.body).getScrollSize();
		var statusSize = 23;
		if(this.state == 'fullscreen' && ((size.y + statusSize + (size.x==scrollSize.x ? 0 : 15)) < window.screen.availHeight)) {
			clearInterval(this.ieTimer);
			this.ieTimer = false;
			this.state = 'normal';
			this._remove();
		}
	}
});

onReady JS

window.addEvent('domready' , function(){
	var full = new FullScreen("view-fullscreen","close-fullscreen",{
		onOpen: function() {
			// this refers to calling class instance
			console.log('callback open');
		},
		onClose: function() {
			// this refers to calling class instance
			console.log('callback close');
		}
	});
});

CSS

/****
	The class will add a class of fill screen to the HTML tag for easy referencing of body atributes when in full screen mode (even in IE)
	However the fullscreen specification adds the following pseudo-classes:
	html:-moz-full-screen {
	
	}

	html:-webkit-full-screen {
		background: red;
	}

	html:fullscreen {
		background: red;
	}
****/
.fullscreen body {
	background: #a7a7a7;
}

The HTML

<div id="view-fullscreen">Open Full Screen</div>
<div id="close-fullscreen">Exit Full Screen - optional</div>

View the demo

5 Comments + Add Comment

  • Hi Tim! ! Im very impressed by your work. Is there a way to tweak it into an “OnLoad” event? I would like my webpage to automatically fullscreen when people visit it.
    Let me know, and your work is REALLY good.

    Thumb up 0 Thumb down 0

    • Hey Mike try the following (neither tested).

      Assumes the same dom ready as in example code above:

      window.addEvent(‘load’ , function(){
      full.open();
      // or try
      $(“view-fullscreen”).fireEvent(‘click’);
      });

      Now with that being said I think it would be horrible practice to force a user into fullscreen mode even if the above solutions work UNLESS it is an internal application or some sort of SaaS that requires fullscreen viewing.

      For example why I crated this is so users could view our internal reports table that are huge and super convoluted with as much real estate of the screen as possible albeit onClick of the full screen icon.

      As for our report that is an issue I will tackle with the team at a later date, lol

      Thumb up 1 Thumb down 0

  • What happens to the scrollbars when it goes fullscreen ? And why it goes back to normal screen when i click on any link on the site ??

    Thanks

    Thumb up 0 Thumb down 0

  • @107 of your script:

    if (this.closer) {
    this.opener.addClass(‘disabled’);
    }

    shouldnt that be this.closer ?

    Thumb up 0 Thumb down 0

Leave a comment

Show/Hide Footer Actions

Status: Available for your project.