text: /* Add to Homescreen v3.1.1 ~ (c) 2014 Matteo Spinelli ~ @license: http://cubiq.org/license */
  (function (window, document) {
  /*
         _   _ _____     _____
   ___ _| |_| |_   _|___|  |  |___ _____ ___ ___ ___ ___ ___ ___ ___
  | .'| . | . | | | | . |     | . |     | -_|_ -|  _|  _| -_| -_|   |
  |__,|___|___| |_| |___|__|__|___|_|_|_|___|___|___|_| |___|___|_|_|
                                by Matteo Spinelli ~ http://cubiq.org
  */
  
  // Check for addEventListener browser support (prevent errors in IE<9)
  var _eventListener = 'addEventListener' in window;
  
  // Check if document is loaded, needed by autostart
  var _DOMReady = false;
  if ( document.readyState === 'complete' ) {
  	_DOMReady = true;
  } else if ( _eventListener ) {
  	window.addEventListener('load', loaded, false);
  }
  
  function loaded () {
  	window.removeEventListener('load', loaded, false);
  	_DOMReady = true;
  }
  
  // regex used to detect if app has been added to the homescreen
  var _reSmartURL = /\/ath(\/)?$/;
  var _reQueryString = /([\?&]ath=[^&]*$|&ath=[^&]*(&))/;
  
  // singleton
  var _instance;
  function ath (options) {
  	_instance = _instance || new ath.Class(options);
  
  	return _instance;
  }
  
  // message in all supported languages
  ath.intl = {
  	de_de: {
  		ios: 'Um diese Web-App zum Home-Bildschirm hinzuzufügen, tippen Sie auf %icon und dann <strong>Zum Home-Bildschirm</strong>.',
  		android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class="ath-action-icon">icon</span>.</small>'
  	},
  
  	en_us: {
  		ios: 'To add this web app to the home screen: tap %icon and then <strong>Add to Home Screen</strong>.',
  		android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class="ath-action-icon">icon</span>.</small>'
  	},
  
  	es_es: {
  		ios: 'Para añadir esta aplicación web a la pantalla de inicio: pulsa %icon y selecciona <strong>Añadir a pantalla de inicio</strong>.',
  		android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class="ath-action-icon">icon</span>.</small>'
  	},
  
  	fr_fr: {
  		ios: 'Pour ajouter cette application web sur l\'écran d\'accueil : Appuyez %icon et sélectionnez <strong>Ajouter sur l\'écran d\'accueil</strong>.',
  		android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class="ath-action-icon">icon</span>.</small>'
  	},
  
  	he_il: {
  		ios: '<span dir="rtl">להוספת האפליקציה למסך הבית: ללחוץ על %icon ואז <strong>הוסף למסך הבית</strong>.</span>',
  		android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class="ath-action-icon">icon</span>.</small>'
  	},
  
  	it_it: {
  		ios: 'Per aggiungere questa web app alla schermata iniziale: premi %icon e poi <strong>Aggiungi a Home</strong>.',
  		android: 'Per aggiungere questa web app alla schermata iniziale, apri il menu opzioni del browser e premi su <strong>Aggiungi alla homescreen</strong>. <small>Puoi accedere al menu premendo il pulsante hardware delle opzioni se la tua device ne ha uno, oppure premendo l\'icona <span class="ath-action-icon">icon</span> in alto a destra.</small>'
  	},
  
  	nb_no: {
  		ios: 'For å installere denne appen på hjem-skjermen: trykk på %icon og deretter <strong>Legg til på Hjem-skjerm</strong>.',
  		android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class="ath-action-icon">icon</span>.</small>'
  	},
  
  	pt_br: {
  		ios: 'Para adicionar este app à tela de início: clique %icon e então <strong>Tela de início</strong>.',
  		android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class="ath-action-icon">icon</span>.</small>'
  	},
  
  	pt_pt: {
  		ios: 'Para adicionar esta app ao ecrã principal: clique %icon e depois <strong>Ecrã principal</strong>.',
  		android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class="ath-action-icon">icon</span>.</small>'
  	},
  
  	nl_nl: {
  		ios: 'Om deze webapp op je telefoon te installeren, klik op %icon en dan <strong>Zet in beginscherm</strong>.',
  		android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class="ath-action-icon">icon</span>.</small>'
  	},
  
  	sv_se: {
  		ios: 'För att lägga till denna webbapplikation på hemskärmen: tryck på %icon och därefter <strong>Lägg till på hemskärmen</strong>.',
  		android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class="ath-action-icon">icon</span>.</small>'
  	},
  
  	zh_cn: {
  		ios: '如要把应用程式加至主屏幕,请点击%icon, 然后<strong>加至主屏幕</strong>',
  		android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class="ath-action-icon">icon</span>.</small>'
  	},
  
  	zh_tw: {
  		ios: '如要把應用程式加至主屏幕, 請點擊%icon, 然後<strong>加至主屏幕</strong>.',
  		android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class="ath-action-icon">icon</span>.</small>'
  	}
  };
  
  // Add 2 characters language support (Android mostly)
  for ( var lang in ath.intl ) {
  	ath.intl[lang.substr(0, 2)] = ath.intl[lang];
  }
  
  // default options
  ath.defaults = {
  	appID: 'org.cubiq.addtohome',		// local storage name (no need to change)
  	fontSize: 15,				// base font size, used to properly resize the popup based on viewport scale factor
  	debug: false,				// override browser checks
  	modal: false,				// prevent further actions until the message is closed
  	mandatory: false,			// you can't proceed if you don't add the app to the homescreen
  	autostart: true,			// show the message automatically
  	skipFirstVisit: false,		// show only to returning visitors (ie: skip the first time you visit)
  	startDelay: 1,				// display the message after that many seconds from page load
  	lifespan: 15,				// life of the message in seconds
  	displayPace: 1440,			// minutes before the message is shown again (0: display every time, default 24 hours)
  	maxDisplayCount: 0,			// absolute maximum number of times the message will be shown to the user (0: no limit)
  	icon: true,					// add touch icon to the message
  	message: '',				// the message can be customized
  	validLocation: [],			// list of pages where the message will be shown (array of regexes)
  	onInit: null,				// executed on instance creation
  	onShow: null,				// executed when the message is shown
  	onRemove: null,				// executed when the message is removed
  	onAdd: null,				// when the application is launched the first time from the homescreen (guesstimate)
  	onPrivate: null,			// executed if user is in private mode
  	privateModeOverride: false,	// show the message even in private mode (very rude)
  	detectHomescreen: false		// try to detect if the site has been added to the homescreen (false | true | 'hash' | 'queryString' | 'smartURL')
  };
  
  // browser info and capability
  var _ua = window.navigator.userAgent;
  
  var _nav = window.navigator;
  _extend(ath, {
  	hasToken: document.location.hash === '#ath' || _reSmartURL.test(document.location.href) || _reQueryString.test(document.location.search),
  	isRetina: window.devicePixelRatio && window.devicePixelRatio > 1,
  	isIDevice: (/iphone|ipod|ipad/i).test(_ua),
  	isMobileChrome: _ua.indexOf('Android') > -1 && (/Chrome\/[.0-9]*/).test(_ua),
  	isMobileIE: _ua.indexOf('Windows Phone') > -1,
  	language: _nav.language && _nav.language.toLowerCase().replace('-', '_') || ''
  });
  
  // falls back to en_us if language is unsupported
  ath.language = ath.language && ath.language in ath.intl ? ath.language : 'en_us';
  
  ath.isMobileSafari = ath.isIDevice && _ua.indexOf('Safari') > -1 && _ua.indexOf('CriOS') < 0;
  ath.OS = ath.isIDevice ? 'ios' : ath.isMobileChrome ? 'android' : ath.isMobileIE ? 'windows' : 'unsupported';
  
  ath.OSVersion = _ua.match(/(OS|Android) (\d+[_\.]\d+)/);
  ath.OSVersion = ath.OSVersion && ath.OSVersion[2] ? +ath.OSVersion[2].replace('_', '.') : 0;
  
  ath.isStandalone = window.navigator.standalone || ( ath.isMobileChrome && ( screen.height - document.documentElement.clientHeight < 40 ) );	// TODO: check the lame polyfill
  ath.isTablet = (ath.isMobileSafari && _ua.indexOf('iPad') > -1) || (ath.isMobileChrome && _ua.indexOf('Mobile') < 0);
  
  ath.isCompatible = (ath.isMobileSafari && ath.OSVersion >= 6) || ath.isMobileChrome;	// TODO: add winphone
  
  var _defaultSession = {
  	lastDisplayTime: 0,			// last time we displayed the message
  	returningVisitor: false,	// is this the first time you visit
  	displayCount: 0,			// number of times the message has been shown
  	optedout: false,			// has the user opted out
  	added: false				// has been actually added to the homescreen
  };
  
  ath.removeSession = function (appID) {
  	try {
  		localStorage.removeItem(appID || ath.defaults.appID);
  	} catch (e) {
  		// we are most likely in private mode
  	}
  };
  
  ath.Class = function (options) {
  	// merge default options with user config
  	this.options = _extend({}, ath.defaults);
  	_extend(this.options, options);
  
  	// IE<9 so exit (I hate you, really)
  	if ( !_eventListener ) {
  		return;
  	}
  
  	// normalize some options
  	this.options.mandatory = this.options.mandatory && ( 'standalone' in window.navigator || this.options.debug );
  	this.options.modal = this.options.modal || this.options.mandatory;
  	if ( this.options.mandatory ) {
  		this.options.startDelay = -0.5;		// make the popup hasty
  	}
  	this.options.detectHomescreen = this.options.detectHomescreen === true ? 'hash' : this.options.detectHomescreen;
  
  	// setup the debug environment
  	if ( this.options.debug ) {
  		ath.isCompatible = true;
  		ath.OS = typeof this.options.debug === 'string' ? this.options.debug : ath.OS === 'unsupported' ? 'android' : ath.OS;
  		ath.OSVersion = ath.OS === 'ios' ? '8' : '4';
  	}
  
  	// the element the message will be appended to
  	this.container = document.documentElement;
  
  	// load session
  	this.session = localStorage.getItem(this.options.appID);
  	this.session = this.session ? JSON.parse(this.session) : undefined;
  
  	// user most likely came from a direct link containing our token, we don't need it and we remove it
  	if ( ath.hasToken && ( !ath.isCompatible || !this.session ) ) {
  		ath.hasToken = false;
  		_removeToken();
  	}
  
  	// the device is not supported
  	if ( !ath.isCompatible ) {
  		return;
  	}
  
  	this.session = this.session || _defaultSession;
  
  	// check if we can use the local storage
  	try {
  		localStorage.setItem(this.options.appID, JSON.stringify(this.session));
  		ath.hasLocalStorage = true;
  	} catch (e) {
  		// we are most likely in private mode
  		ath.hasLocalStorage = false;
  
  		if ( this.options.onPrivate ) {
  			this.options.onPrivate.call(this);
  		}
  	}
  
  	// check if this is a valid location
  	var isValidLocation = !this.options.validLocation.length;
  	for ( var i = this.options.validLocation.length; i--; ) {
  		if ( this.options.validLocation[i].test(document.location.href) ) {
  			isValidLocation = true;
  			break;
  		}
  	}
  
  	// check compatibility with old versions of add to homescreen. Opt-out if an old session is found
  	if ( localStorage.getItem('addToHome') ) {
  		this.optOut();
  	}
  
  	// critical errors:
  	// user opted out, already added to the homescreen, not a valid location
  	if ( this.session.optedout || this.session.added || !isValidLocation ) {
  		return;
  	}
  
  	// check if the app is in stand alone mode
  	if ( ath.isStandalone ) {
  		// execute the onAdd event if we haven't already
  		if ( !this.session.added ) {
  			this.session.added = true;
  			this.updateSession();
  
  			if ( this.options.onAdd && ath.hasLocalStorage ) {	// double check on localstorage to avoid multiple calls to the custom event
  				this.options.onAdd.call(this);
  			}
  		}
  
  		return;
  	}
  
  	// (try to) check if the page has been added to the homescreen
  	if ( this.options.detectHomescreen ) {
  		// the URL has the token, we are likely coming from the homescreen
  		if ( ath.hasToken ) {
  			_removeToken();		// we don't actually need the token anymore, we remove it to prevent redistribution
  
  			// this is called the first time the user opens the app from the homescreen
  			if ( !this.session.added ) {
  				this.session.added = true;
  				this.updateSession();
  
  				if ( this.options.onAdd && ath.hasLocalStorage ) {	// double check on localstorage to avoid multiple calls to the custom event
  					this.options.onAdd.call(this);
  				}
  			}
  
  			return;
  		}
  
  		// URL doesn't have the token, so add it
  		if ( this.options.detectHomescreen === 'hash' ) {
  			history.replaceState('', window.document.title, document.location.href + '#ath');
  		} else if ( this.options.detectHomescreen === 'smartURL' ) {
  			history.replaceState('', window.document.title, document.location.href.replace(/(\/)?$/, '/ath$1'));
  		} else {
  			history.replaceState('', window.document.title, document.location.href + (document.location.search ? '&' : '?' ) + 'ath=');
  		}
  	}
  
  	// check if this is a returning visitor
  	if ( !this.session.returningVisitor ) {
  		this.session.returningVisitor = true;
  		this.updateSession();
  
  		// we do not show the message if this is your first visit
  		if ( this.options.skipFirstVisit ) {
  			return;
  		}
  	}
  
  	// we do no show the message in private mode
  	if ( !this.options.privateModeOverride && !ath.hasLocalStorage ) {
  		return;
  	}
  
  	// all checks passed, ready to display
  	this.ready = true;
  
  	if ( this.options.onInit ) {
  		this.options.onInit.call(this);
  	}
  
  	if ( this.options.autostart ) {
  		this.show();
  	}
  };
  
  ath.Class.prototype = {
  	// event type to method conversion
  	events: {
  		load: '_delayedShow',
  		error: '_delayedShow',
  		orientationchange: 'resize',
  		resize: 'resize',
  		scroll: 'resize',
  		click: 'remove',
  		touchmove: '_preventDefault',
  		transitionend: '_removeElements',
  		webkitTransitionEnd: '_removeElements',
  		MSTransitionEnd: '_removeElements'
  	},
  
  	handleEvent: function (e) {
  		var type = this.events[e.type];
  		if ( type ) {
  			this[type](e);
  		}
  	},
  
  	show: function (force) {
  		// in autostart mode wait for the document to be ready
  		if ( this.options.autostart && !_DOMReady ) {
  			setTimeout(this.show.bind(this), 50);
  			return;
  		}
  
  		// message already on screen
  		if ( this.shown ) {
  			return;
  		}
  
  		var now = Date.now();
  		var lastDisplayTime = this.session.lastDisplayTime;
  
  		if ( force !== true ) {
  			// this is needed if autostart is disabled and you programmatically call the show() method
  			if ( !this.ready ) {
  				return;
  			}
  
  			// we obey the display pace (prevent the message to popup too often)
  			if ( now - lastDisplayTime < this.options.displayPace * 60000 ) {
  				return;
  			}
  
  			// obey the maximum number of display count
  			if ( this.options.maxDisplayCount && this.session.displayCount >= this.options.maxDisplayCount ) {
  				return;
  			}
  		}
  
  		this.shown = true;
  
  		// increment the display count
  		this.session.lastDisplayTime = now;
  		this.session.displayCount++;
  		this.updateSession();
  
  		// try to get the highest resolution application icon
  		if ( !this.applicationIcon ) {
  			if ( ath.OS === 'ios' ) {
  				this.applicationIcon = document.querySelector('head link[rel^=apple-touch-icon][sizes="152x152"],head link[rel^=apple-touch-icon][sizes="144x144"],head link[rel^=apple-touch-icon][sizes="120x120"],head link[rel^=apple-touch-icon][sizes="114x114"],head link[rel^=apple-touch-icon]');
  			} else {
  				this.applicationIcon = document.querySelector('head link[rel^="shortcut icon"][sizes="196x196"],head link[rel^=apple-touch-icon]');
  			}
  		}
  
  		var message = '';
  
  		if ( this.options.message in ath.intl ) {		// you can force the locale
  			message = ath.intl[this.options.message][ath.OS];
  		} else if ( this.options.message !== '' ) {		// or use a custom message
  			message = this.options.message;
  		} else {										// otherwise we use our message
  			message = ath.intl[ath.language][ath.OS];
  		}
  
  		// add the action icon
  		message = '<p>' + message.replace('%icon', '<span class="ath-action-icon">icon</span>') + '</p>';
  
  		// create the message container
  		this.viewport = document.createElement('div');
  		this.viewport.className = 'ath-viewport';
  		if ( this.options.modal ) {
  			this.viewport.className += ' ath-modal';
  		}
  		if ( this.options.mandatory ) {
  			this.viewport.className += ' ath-mandatory';
  		}
  		this.viewport.style.position = 'absolute';
  
  		// create the actual message element
  		this.element = document.createElement('div');
  		this.element.className = 'ath-container ath-' + ath.OS + ' ath-' + ath.OS + (ath.OSVersion + '').substr(0,1) + ' ath-' + (ath.isTablet ? 'tablet' : 'phone');
  		this.element.style.cssText = '-webkit-transition-property:-webkit-transform,opacity;-webkit-transition-duration:0s;-webkit-transition-timing-function:ease-out;transition-property:transform,opacity;transition-duration:0s;transition-timing-function:ease-out;';
  		this.element.style.webkitTransform = 'translate3d(0,-' + window.innerHeight + 'px,0)';
  		this.element.style.transform = 'translate3d(0,-' + window.innerHeight + 'px,0)';
  
  		// add the application icon
  		if ( this.options.icon && this.applicationIcon ) {
  			this.element.className += ' ath-icon';
  			this.img = document.createElement('img');
  			this.img.className = 'ath-application-icon';
  			this.img.addEventListener('load', this, false);
  			this.img.addEventListener('error', this, false);
  
  			this.img.src = this.applicationIcon.href;
  			this.element.appendChild(this.img);
  		}
  
  		this.element.innerHTML += message;
  
  		// we are not ready to show, place the message out of sight
  		this.viewport.style.left = '-99999em';
  
  		// attach all elements to the DOM
  		this.viewport.appendChild(this.element);
  		this.container.appendChild(this.viewport);
  
  		// if we don't have to wait for an image to load, show the message right away
  		if ( !this.img ) {
  			this._delayedShow();
  		}
  	},
  
  	_delayedShow: function (e) {
  		setTimeout(this._show.bind(this), this.options.startDelay * 1000 + 500);
  	},
  
  	_show: function () {
  		var that = this;
  
  		// update the viewport size and orientation
  		this.updateViewport();
  
  		// reposition/resize the message on orientation change
  		window.addEventListener('resize', this, false);
  		window.addEventListener('scroll', this, false);
  		window.addEventListener('orientationchange', this, false);
  
  		if ( this.options.modal ) {
  			// lock any other interaction
  			document.addEventListener('touchmove', this, true);
  		}
  
  		// Enable closing after 1 second
  		if ( !this.options.mandatory ) {
  			setTimeout(function () {
  				that.element.addEventListener('click', that, true);
  			}, 1000);
  		}
  
  		// kick the animation
  		setTimeout(function () {
  			that.element.style.webkitTransitionDuration = '1.2s';
  			that.element.style.transitionDuration = '1.2s';
  			that.element.style.webkitTransform = 'translate3d(0,0,0)';
  			that.element.style.transform = 'translate3d(0,0,0)';
  		}, 0);
  
  		// set the destroy timer
  		if ( this.options.lifespan ) {
  			this.removeTimer = setTimeout(this.remove.bind(this), this.options.lifespan * 1000);
  		}
  
  		// fire the custom onShow event
  		if ( this.options.onShow ) {
  			this.options.onShow.call(this);
  		}
  	},
  
  	remove: function () {
  		clearTimeout(this.removeTimer);
  
  		// clear up the event listeners
  		if ( this.img ) {
  			this.img.removeEventListener('load', this, false);
  			this.img.removeEventListener('error', this, false);
  		}
  
  		window.removeEventListener('resize', this, false);
  		window.removeEventListener('scroll', this, false);
  		window.removeEventListener('orientationchange', this, false);
  		document.removeEventListener('touchmove', this, true);
  		this.element.removeEventListener('click', this, true);
  
  		// remove the message element on transition end
  		this.element.addEventListener('transitionend', this, false);
  		this.element.addEventListener('webkitTransitionEnd', this, false);
  		this.element.addEventListener('MSTransitionEnd', this, false);
  
  		// start the fade out animation
  		this.element.style.webkitTransitionDuration = '0.3s';
  		this.element.style.opacity = '0';
  	},
  
  	_removeElements: function () {
  		this.element.removeEventListener('transitionend', this, false);
  		this.element.removeEventListener('webkitTransitionEnd', this, false);
  		this.element.removeEventListener('MSTransitionEnd', this, false);
  
  		// remove the message from the DOM
  		this.container.removeChild(this.viewport);
  
  		this.shown = false;
  
  		// fire the custom onRemove event
  		if ( this.options.onRemove ) {
  			this.options.onRemove.call(this);
  		}
  	},
  
  	updateViewport: function () {
  		if ( !this.shown ) {
  			return;
  		}
  
  		this.viewport.style.width = window.innerWidth + 'px';
  		this.viewport.style.height = window.innerHeight + 'px';
  		this.viewport.style.left = window.scrollX + 'px';
  		this.viewport.style.top = window.scrollY + 'px';
  
  		var clientWidth = document.documentElement.clientWidth;
  
  		this.orientation = clientWidth > document.documentElement.clientHeight ? 'landscape' : 'portrait';
  
  		var screenWidth = ath.OS === 'ios' ? this.orientation === 'portrait' ? screen.width : screen.height : screen.width;
  		this.scale = screen.width > clientWidth ? 1 : screenWidth / window.innerWidth;
  
  		this.element.style.fontSize = this.options.fontSize / this.scale + 'px';
  	},
  
  	resize: function () {
  		clearTimeout(this.resizeTimer);
  		this.resizeTimer = setTimeout(this.updateViewport.bind(this), 100);
  	},
  
  	updateSession: function () {
  		if ( ath.hasLocalStorage === false ) {
  			return;
  		}
  
  		localStorage.setItem(this.options.appID, JSON.stringify(this.session));
  	},
  
  	clearSession: function () {
  		this.session = _defaultSession;
  		this.updateSession();
  	},
  
  	optOut: function () {
  		this.session.optedout = true;
  		this.updateSession();
  	},
  
  	optIn: function () {
  		this.session.optedout = false;
  		this.updateSession();
  	},
  
  	clearDisplayCount: function () {
  		this.session.displayCount = 0;
  		this.updateSession();
  	},
  
  	_preventDefault: function (e) {
  		e.preventDefault();
  		e.stopPropagation();
  	}
  };
  
  // utility
  function _extend (target, obj) {
  	for ( var i in obj ) {
  		target[i] = obj[i];
  	}
  
  	return target;
  }
  
  function _removeToken () {
  	if ( document.location.hash === '#ath' ) {
  		history.replaceState('', window.document.title, document.location.href.split('#')[0]);
  	}
  
  	if ( _reSmartURL.test(document.location.href) ) {
  		history.replaceState('', window.document.title, document.location.href.replace(_reSmartURL, '$1'));
  	}
  
  	if ( _reQueryString.test(document.location.search) ) {
  		history.replaceState('', window.document.title, document.location.href.replace(_reQueryString, '$2'));
  	}
  }
  
  // expose to the world
  window.addToHomescreen = ath;
  
  })(window, document);