From 6308beb51b915820e9aa25358b25589ead20fdeb Mon Sep 17 00:00:00 2001 From: Michel Hiemstra Date: Fri, 31 Jul 2015 14:27:39 +0200 Subject: [PATCH] added UMD pattern and package.json for npm --- package.json | 30 + src/addtohomescreen.js | 1230 ++++++++++++++++++------------------ src/addtohomescreen.min.js | 2 +- 3 files changed, 652 insertions(+), 610 deletions(-) create mode 100644 package.json diff --git a/package.json b/package.json new file mode 100644 index 0000000..96a2142 --- /dev/null +++ b/package.json @@ -0,0 +1,30 @@ +{ + "name": "add-to-homescreen", + "title": "add-to-homescreen", + "main": "src/addtohomescreen.js", + "description": "Add to homescreen call out for iOS and Android", + "keywords": [ + "iPhone", + "iPod", + "iPad", + "iOS6", + "iOS7", + "android", + "mobile" + ], + "version": "3.2.7", + "homepage": "https://github.com/cubiq/add-to-homescreen", + "author": { + "name": "Matteo Spinelli ", + "url": "http://cubiq.org" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "licenses": [ + { + "type": "MIT", + "url": "http://opensource.org/licenses/mit-license.php" + } + ] +} diff --git a/src/addtohomescreen.js b/src/addtohomescreen.js index d204ff6..3448cdb 100644 --- a/src/addtohomescreen.js +++ b/src/addtohomescreen.js @@ -1,340 +1,333 @@ -/* Add to Homescreen v3.2.2 ~ (c) 2015 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 Zum Home-Bildschirm.', - android: 'Um diese Web-App zum Home-Bildschirm hinzuzufügen, öffnen Sie das Menü und tippen dann auf Zum Startbildschirm hinzufügen. Wenn Ihr Gerät eine Menütaste hat, lässt sich das Browsermenü über diese öffnen. Ansonsten tippen Sie auf icon.', - }, - - da_dk: { - ios: 'For at tilføje denne web app til hjemmeskærmen: Tryk %icon og derefter Føj til hjemmeskærm.', - android: 'For at tilføje denne web app til hjemmeskærmen, åbn browser egenskaber menuen og tryk på Føj til hjemmeskærm. Denne menu kan tilgås ved at trykke på menu knappen, hvis din enhed har en, eller ved at trykke på det øverste højre menu ikon icon.', - }, - - en_us: { - ios: 'To add this web app to the home screen: tap %icon and then Add to Home Screen.', - android: 'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.', - }, - - es_es: { - ios: 'Para añadir esta aplicación web a la pantalla de inicio: pulsa %icon y selecciona Añadir a pantalla de inicio.', - android: 'Para añadir esta aplicación web a la pantalla de inicio, abre las opciones y pulsa Añadir a pantalla inicio. El menú se puede acceder pulsando el botón táctil en caso de tenerlo, o bien el icono de la parte superior derecha de la pantalla icon.', - }, - - fi_fi: { - ios: 'Liitä tämä sovellus kotivalikkoon: klikkaa %icon ja tämän jälkeen Lisää kotivalikkoon.', - android: 'Lisätäksesi tämän sovelluksen aloitusnäytölle, avaa selaimen valikko ja klikkaa tähti -ikonia tai Lisää aloitusnäytölle tekstiä. Valikkoon pääsee myös painamalla menuvalikkoa, jos laitteessasi on sellainen tai koskettamalla oikealla yläkulmassa menu ikonia icon.', - }, - - fr_fr: { - ios: 'Pour ajouter cette application web sur l\'écran d\'accueil : Appuyez %icon et sélectionnez Ajouter sur l\'écran d\'accueil.', - android: 'Pour ajouter cette application web sur l\'écran d\'accueil : Appuyez sur le bouton "menu", puis sur Ajouter sur l\'écran d\'accueil. Le menu peut-être accessible en appyant sur le bouton "menu" du téléphone s\'il en possède un . Sinon, il se trouve probablement dans la coin supérieur droit du navigateur %icon.', - }, - - he_il: { - ios: 'להוספת האפליקציה למסך הבית: ללחוץ על %icon ואז הוסף למסך הבית.', - android: 'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.', - }, - - it_it: { - ios: 'Per aggiungere questa web app alla schermata iniziale: premi %icon e poi Aggiungi a Home.', - android: 'Per aggiungere questa web app alla schermata iniziale, apri il menu opzioni del browser e premi su Aggiungi alla homescreen. Puoi accedere al menu premendo il pulsante hardware delle opzioni se la tua device ne ha uno, oppure premendo l\'icona icon in alto a destra.', - }, - - ja_jp: { - ios: 'このウェプアプリをホーム画面に追加するために%iconを押してホーム画面に追加。', - android: 'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.', - }, - - ko_kr: { - ios: '홈 화면에 바로가기 생성: %icon 을 클릭한 후 홈 화면에 추가.', - android: '브라우저 옵션 메뉴의 홈 화면에 추가를 클릭하여 홈화면에 바로가기를 생성할 수 있습니다. 옵션 메뉴는 장치의 메뉴 버튼을 누르거나 오른쪽 상단의 메뉴 아이콘 icon을 클릭하여 접근할 수 있습니다.' - }, - - nb_no: { - ios: 'For å installere denne appen på hjem-skjermen: trykk på %icon og deretter Legg til på Hjem-skjerm.', - android: 'For å legge til denne webappen på startsiden åpner en nettlesermenyen og velger Legg til på startsiden. Menyen åpnes ved å trykke på den fysiske menyknappen hvis enheten har det, eller ved å trykke på menyikonet øverst til høyre icon.', - }, - - pt_br: { - ios: 'Para adicionar este app à tela de início: clique %icon e então Tela de início.', - android: 'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.', - }, - - pt_pt: { - ios: 'Para adicionar esta app ao ecrã principal: clique %icon e depois Ecrã principal.', - android: 'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.', - }, - - nl_nl: { - ios: 'Om deze webapp op je telefoon te installeren, klik op %icon en dan Zet in beginscherm.', - android: 'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.', - }, - - ru_ru: { - ios: 'Чтобы добавить этот сайт на свой домашний экран, нажмите на иконку %icon и затем На экран "Домой".', - android: 'Чтобы добавить сайт на свой домашний экран, откройте меню браузера и нажмите на Добавить на главный экран. Меню можно вызвать, нажав на кнопку меню вашего телефона, если она есть. Или найдите иконку сверху справа иконка.', - }, - - sv_se: { - ios: 'För att lägga till denna webbapplikation på hemskärmen: tryck på %icon och därefter Lägg till på hemskärmen.', - android: 'För att lägga till den här webbappen på hemskärmen öppnar du webbläsarens alternativ-meny och väljer Lägg till på startskärmen. Man hittar menyn genom att trycka på hårdvaruknappen om din enhet har en sådan, eller genom att trycka på menyikonen högst upp till höger icon.', - }, - - zh_cn: { - ios: '如要把应用程序加至主屏幕,请点击%icon, 然后添加到主屏幕', - android: 'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.', - }, - - zh_tw: { - ios: '如要把應用程式加至主屏幕, 請點擊%icon, 然後加至主屏幕.', - android: 'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.', - }, - -}; - -// 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 - logging: false, // log reasons for showing or not showing to js console; defaults to true when debug is true - 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) && _ua.indexOf("Version") == -1, - 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 = 'standalone' in window.navigator && window.navigator.standalone; -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 { - if (!localStorage) { - throw new Error('localStorage is not defined'); - } - - localStorage.removeItem(appID || ath.defaults.appID); - } catch (e) { - // we are most likely in private mode +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define([], factory); + } else if (typeof exports === 'object') { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like enviroments that support module.exports, + // like Node. + module.exports = factory(); + } else { + // Browser globals (root is window) + root.returnExports = factory(); + } +}(this, function () { + /* Add to Homescreen v3.2.2 ~ (c) 2015 Matteo Spinelli ~ @license: http://cubiq.org/license */ + /* + _ _ _____ _____ + ___ _| |_| |_ _|___| | |___ _____ ___ ___ ___ ___ ___ ___ ___ + | .'| . | . | | | | . | | . | | -_|_ -| _| _| -_| -_| | + |__,|___|___| |_| |___|__|__|___|_|_|_|___|___|___|_| |___|___|_|_| + 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); } -}; -ath.doLog = function (logStr) { - if ( this.options.logging ) { - console.log(logStr); - } -}; - -ath.Class = function (options) { - // class methods - this.doLog = ath.doLog; - - // merge default options with user config - this.options = _extend({}, ath.defaults); - _extend(this.options, options); - // override defaults that are dependent on each other - if ( options && options.debug && (typeof options.logging === "undefined") ) { - this.options.logging = true; + function loaded () { + window.removeEventListener('load', loaded, false); + _DOMReady = true; } - // IE<9 so exit (I hate you, really) - if ( !_eventListener ) { - return; - } + // 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); - // 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 + return _instance; } - 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'; + // 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 Zum Home-Bildschirm.', + android: 'Um diese Web-App zum Home-Bildschirm hinzuzufügen, öffnen Sie das Menü und tippen dann auf Zum Startbildschirm hinzufügen. Wenn Ihr Gerät eine Menütaste hat, lässt sich das Browsermenü über diese öffnen. Ansonsten tippen Sie auf icon.', + }, + + da_dk: { + ios: 'For at tilføje denne web app til hjemmeskærmen: Tryk %icon og derefter Føj til hjemmeskærm.', + android: 'For at tilføje denne web app til hjemmeskærmen, åbn browser egenskaber menuen og tryk på Føj til hjemmeskærm. Denne menu kan tilgås ved at trykke på menu knappen, hvis din enhed har en, eller ved at trykke på det øverste højre menu ikon icon.', + }, + + en_us: { + ios: 'To add this web app to the home screen: tap %icon and then Add to Home Screen.', + android: 'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.', + }, + + es_es: { + ios: 'Para añadir esta aplicación web a la pantalla de inicio: pulsa %icon y selecciona Añadir a pantalla de inicio.', + android: 'Para añadir esta aplicación web a la pantalla de inicio, abre las opciones y pulsa Añadir a pantalla inicio. El menú se puede acceder pulsando el botón táctil en caso de tenerlo, o bien el icono de la parte superior derecha de la pantalla icon.', + }, + + fi_fi: { + ios: 'Liitä tämä sovellus kotivalikkoon: klikkaa %icon ja tämän jälkeen Lisää kotivalikkoon.', + android: 'Lisätäksesi tämän sovelluksen aloitusnäytölle, avaa selaimen valikko ja klikkaa tähti -ikonia tai Lisää aloitusnäytölle tekstiä. Valikkoon pääsee myös painamalla menuvalikkoa, jos laitteessasi on sellainen tai koskettamalla oikealla yläkulmassa menu ikonia icon.', + }, + + fr_fr: { + ios: 'Pour ajouter cette application web sur l\'écran d\'accueil : Appuyez %icon et sélectionnez Ajouter sur l\'écran d\'accueil.', + android: 'Pour ajouter cette application web sur l\'écran d\'accueil : Appuyez sur le bouton "menu", puis sur Ajouter sur l\'écran d\'accueil. Le menu peut-être accessible en appyant sur le bouton "menu" du téléphone s\'il en possède un . Sinon, il se trouve probablement dans la coin supérieur droit du navigateur %icon.', + }, + + he_il: { + ios: 'להוספת האפליקציה למסך הבית: ללחוץ על %icon ואז הוסף למסך הבית.', + android: 'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.', + }, + + it_it: { + ios: 'Per aggiungere questa web app alla schermata iniziale: premi %icon e poi Aggiungi a Home.', + android: 'Per aggiungere questa web app alla schermata iniziale, apri il menu opzioni del browser e premi su Aggiungi alla homescreen. Puoi accedere al menu premendo il pulsante hardware delle opzioni se la tua device ne ha uno, oppure premendo l\'icona icon in alto a destra.', + }, + + ja_jp: { + ios: 'このウェプアプリをホーム画面に追加するために%iconを押してホーム画面に追加。', + android: 'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.', + }, + + ko_kr: { + ios: '홈 화면에 바로가기 생성: %icon 을 클릭한 후 홈 화면에 추가.', + android: '브라우저 옵션 메뉴의 홈 화면에 추가를 클릭하여 홈화면에 바로가기를 생성할 수 있습니다. 옵션 메뉴는 장치의 메뉴 버튼을 누르거나 오른쪽 상단의 메뉴 아이콘 icon을 클릭하여 접근할 수 있습니다.' + }, + + nb_no: { + ios: 'For å installere denne appen på hjem-skjermen: trykk på %icon og deretter Legg til på Hjem-skjerm.', + android: 'For å legge til denne webappen på startsiden åpner en nettlesermenyen og velger Legg til på startsiden. Menyen åpnes ved å trykke på den fysiske menyknappen hvis enheten har det, eller ved å trykke på menyikonet øverst til høyre icon.', + }, + + pt_br: { + ios: 'Para adicionar este app à tela de início: clique %icon e então Tela de início.', + android: 'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.', + }, + + pt_pt: { + ios: 'Para adicionar esta app ao ecrã principal: clique %icon e depois Ecrã principal.', + android: 'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.', + }, + + nl_nl: { + ios: 'Om deze webapp op je telefoon te installeren, klik op %icon en dan Zet in beginscherm.', + android: 'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.', + }, + + ru_ru: { + ios: 'Чтобы добавить этот сайт на свой домашний экран, нажмите на иконку %icon и затем На экран "Домой".', + android: 'Чтобы добавить сайт на свой домашний экран, откройте меню браузера и нажмите на Добавить на главный экран. Меню можно вызвать, нажав на кнопку меню вашего телефона, если она есть. Или найдите иконку сверху справа иконка.', + }, + + sv_se: { + ios: 'För att lägga till denna webbapplikation på hemskärmen: tryck på %icon och därefter Lägg till på hemskärmen.', + android: 'För att lägga till den här webbappen på hemskärmen öppnar du webbläsarens alternativ-meny och väljer Lägg till på startskärmen. Man hittar menyn genom att trycka på hårdvaruknappen om din enhet har en sådan, eller genom att trycka på menyikonen högst upp till höger icon.', + }, + + zh_cn: { + ios: '如要把应用程序加至主屏幕,请点击%icon, 然后添加到主屏幕', + android: 'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.', + }, + + zh_tw: { + ios: '如要把應用程式加至主屏幕, 請點擊%icon, 然後加至主屏幕.', + android: 'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.', + }, + + }; + + // Add 2 characters language support (Android mostly) + for ( var lang in ath.intl ) { + ath.intl[lang.substr(0, 2)] = ath.intl[lang]; } - // the element the message will be appended to - this.container = document.documentElement; + // 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 + logging: false, // log reasons for showing or not showing to js console; defaults to true when debug is true + 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) && _ua.indexOf("Version") == -1, + 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 = 'standalone' in window.navigator && window.navigator.standalone; + 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 { + if (!localStorage) { + throw new Error('localStorage is not defined'); + } - // load session - this.session = this.getItem(this.options.appID); - this.session = this.session ? JSON.parse(this.session) : undefined; + localStorage.removeItem(appID || ath.defaults.appID); + } catch (e) { + // we are most likely in private mode + } + }; - // 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(); - } + ath.doLog = function (logStr) { + if ( this.options.logging ) { + console.log(logStr); + } + }; + + ath.Class = function (options) { + // class methods + this.doLog = ath.doLog; + + // merge default options with user config + this.options = _extend({}, ath.defaults); + _extend(this.options, options); + // override defaults that are dependent on each other + if ( options && options.debug && (typeof options.logging === "undefined") ) { + this.options.logging = true; + } - // the device is not supported - if ( !ath.isCompatible ) { - this.doLog("Add to homescreen: not displaying callout because device not supported"); - return; - } + // IE<9 so exit (I hate you, really) + if ( !_eventListener ) { + return; + } - this.session = this.session || _defaultSession; + // 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; - // check if we can use the local storage - try { - if (!localStorage) { - throw new Error('localStorage is not defined'); + // 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'; } - localStorage.setItem(this.options.appID, JSON.stringify(this.session)); - ath.hasLocalStorage = true; - } catch (e) { - // we are most likely in private mode - ath.hasLocalStorage = false; + // the element the message will be appended to + this.container = document.documentElement; + + // load session + this.session = this.getItem(this.options.appID); + this.session = this.session ? JSON.parse(this.session) : undefined; - if ( this.options.onPrivate ) { - this.options.onPrivate.call(this); + // 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(); } - } - // 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; + // the device is not supported + if ( !ath.isCompatible ) { + this.doLog("Add to homescreen: not displaying callout because device not supported"); + return; } - } - // check compatibility with old versions of add to homescreen. Opt-out if an old session is found - if ( this.getItem('addToHome') ) { - this.optOut(); - } + this.session = this.session || _defaultSession; - // critical errors: - if ( this.session.optedout ) { - this.doLog("Add to homescreen: not displaying callout because user opted out"); - return; - } - if ( this.session.added ) { - this.doLog("Add to homescreen: not displaying callout because already added to the homescreen"); - return; - } - if ( !isValidLocation ) { - this.doLog("Add to homescreen: not displaying callout because not a valid location"); - return; - } + // check if we can use the local storage + try { + if (!localStorage) { + throw new Error('localStorage is not defined'); + } - // 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(); + 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.onAdd && ath.hasLocalStorage ) { // double check on localstorage to avoid multiple calls to the custom event - this.options.onAdd.call(this); + if ( this.options.onPrivate ) { + this.options.onPrivate.call(this); } } - this.doLog("Add to homescreen: not displaying callout because in standalone mode"); - return; - } + // 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 ( this.getItem('addToHome') ) { + this.optOut(); + } - // (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 + // critical errors: + if ( this.session.optedout ) { + this.doLog("Add to homescreen: not displaying callout because user opted out"); + return; + } + if ( this.session.added ) { + this.doLog("Add to homescreen: not displaying callout because already added to the homescreen"); + return; + } + if ( !isValidLocation ) { + this.doLog("Add to homescreen: not displaying callout because not a valid location"); + return; + } - // this is called the first time the user opens the app from the homescreen + // 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(); @@ -344,376 +337,395 @@ ath.Class = function (options) { } } - this.doLog("Add to homescreen: not displaying callout because URL has token, so we are likely coming from homescreen"); + this.doLog("Add to homescreen: not displaying callout because in standalone mode"); 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='); - } - } + // (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 - // check if this is a returning visitor - if ( !this.session.returningVisitor ) { - this.session.returningVisitor = true; - this.updateSession(); + // this is called the first time the user opens the app from the homescreen + if ( !this.session.added ) { + this.session.added = true; + this.updateSession(); - // we do not show the message if this is your first visit - if ( this.options.skipFirstVisit ) { - this.doLog("Add to homescreen: not displaying callout because skipping first visit"); - return; - } - } + if ( this.options.onAdd && ath.hasLocalStorage ) { // double check on localstorage to avoid multiple calls to the custom event + this.options.onAdd.call(this); + } + } - // we do no show the message in private mode - if ( !this.options.privateModeOverride && !ath.hasLocalStorage ) { - this.doLog("Add to homescreen: not displaying callout because browser is in private mode"); - return; - } + this.doLog("Add to homescreen: not displaying callout because URL has token, so we are likely coming from homescreen"); + return; + } - // all checks passed, ready to display - this.ready = true; + // 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='); + } + } - if ( this.options.onInit ) { - this.options.onInit.call(this); - } + // check if this is a returning visitor + if ( !this.session.returningVisitor ) { + this.session.returningVisitor = true; + this.updateSession(); - if ( this.options.autostart ) { - this.doLog("Add to homescreen: autostart displaying callout"); - 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); - // we are not displaying callout because DOM not ready, but don't log that because - // it would log too frequently - return; + // we do not show the message if this is your first visit + if ( this.options.skipFirstVisit ) { + this.doLog("Add to homescreen: not displaying callout because skipping first visit"); + return; + } } - // message already on screen - if ( this.shown ) { - this.doLog("Add to homescreen: not displaying callout because already shown on screen"); + // we do no show the message in private mode + if ( !this.options.privateModeOverride && !ath.hasLocalStorage ) { + this.doLog("Add to homescreen: not displaying callout because browser is in private mode"); return; } - var now = Date.now(); - var lastDisplayTime = this.session.lastDisplayTime; + // all checks passed, ready to display + this.ready = true; + + if ( this.options.onInit ) { + this.options.onInit.call(this); + } - if ( force !== true ) { - // this is needed if autostart is disabled and you programmatically call the show() method - if ( !this.ready ) { - this.doLog("Add to homescreen: not displaying callout because not ready"); + if ( this.options.autostart ) { + this.doLog("Add to homescreen: autostart displaying callout"); + 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); + // we are not displaying callout because DOM not ready, but don't log that because + // it would log too frequently return; } - // we obey the display pace (prevent the message to popup too often) - if ( now - lastDisplayTime < this.options.displayPace * 60000 ) { - this.doLog("Add to homescreen: not displaying callout because displayed recently"); + // message already on screen + if ( this.shown ) { + this.doLog("Add to homescreen: not displaying callout because already shown on screen"); return; } - // obey the maximum number of display count - if ( this.options.maxDisplayCount && this.session.displayCount >= this.options.maxDisplayCount ) { - this.doLog("Add to homescreen: not displaying callout because displayed too many times already"); - 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 ) { + this.doLog("Add to homescreen: not displaying callout because not ready"); + return; + } + + // we obey the display pace (prevent the message to popup too often) + if ( now - lastDisplayTime < this.options.displayPace * 60000 ) { + this.doLog("Add to homescreen: not displaying callout because displayed recently"); + return; + } + + // obey the maximum number of display count + if ( this.options.maxDisplayCount && this.session.displayCount >= this.options.maxDisplayCount ) { + this.doLog("Add to homescreen: not displaying callout because displayed too many times already"); + return; + } } - } - this.shown = true; + this.shown = true; - // increment the display count - this.session.lastDisplayTime = now; - this.session.displayCount++; - this.updateSession(); + // 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]'); + // 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 ( typeof this.options.message == 'object' && ath.language in this.options.message ) { // use custom language message - message = this.options.message[ath.language][ath.OS]; - } else if ( typeof this.options.message == 'object' && ath.OS in this.options.message ) { // use custom os message - message = this.options.message[ath.OS]; - } else 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 !== '' ) { // use a custom message - message = this.options.message; - } else if ( ath.OS in ath.intl[ath.language] ) { // otherwise we use our message - message = ath.intl[ath.language][ath.OS]; - } + var message = ''; + + if ( typeof this.options.message == 'object' && ath.language in this.options.message ) { // use custom language message + message = this.options.message[ath.language][ath.OS]; + } else if ( typeof this.options.message == 'object' && ath.OS in this.options.message ) { // use custom os message + message = this.options.message[ath.OS]; + } else 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 !== '' ) { // use a custom message + message = this.options.message; + } else if ( ath.OS in ath.intl[ath.language] ) { // otherwise we use our message + message = ath.intl[ath.language][ath.OS]; + } - // add the action icon - message = '

' + message.replace('%icon', 'icon') + '

'; + // add the action icon + message = '

' + message.replace('%icon', 'icon') + '

'; - // 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); - } + // 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; + this.element.innerHTML += message; - // we are not ready to show, place the message out of sight - this.viewport.style.left = '-99999em'; + // 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); + // 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.doLog("Add to homescreen: not displaying callout because waiting for img to load"); - } else { - this._delayedShow(); - } - }, + // if we don't have to wait for an image to load, show the message right away + if ( this.img ) { + this.doLog("Add to homescreen: not displaying callout because waiting for img to load"); + } else { + this._delayedShow(); + } + }, - _delayedShow: function (e) { - setTimeout(this._show.bind(this), this.options.startDelay * 1000 + 500); - }, + _delayedShow: function (e) { + setTimeout(this._show.bind(this), this.options.startDelay * 1000 + 500); + }, - _show: function () { - var that = this; + _show: function () { + var that = this; - // update the viewport size and orientation - this.updateViewport(); + // 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); + // 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); - } + if ( this.options.modal ) { + // lock any other interaction + document.addEventListener('touchmove', this, true); + } - // Enable closing after 1 second - if ( !this.options.mandatory ) { + // 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.addEventListener('click', that, true); - }, 1000); - } + 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); + } - // 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); + } + }, - // fire the custom onShow event - if ( this.options.onShow ) { - this.options.onShow.call(this); - } - }, + remove: function () { + clearTimeout(this.removeTimer); - 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); + } - // 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); - 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); - // 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'; + }, - // 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); - _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); - // remove the message from the DOM - this.container.removeChild(this.viewport); + this.shown = false; - this.shown = false; + // fire the custom onRemove event + if ( this.options.onRemove ) { + this.options.onRemove.call(this); + } + }, - // fire the custom onRemove event - if ( this.options.onRemove ) { - this.options.onRemove.call(this); - } - }, + updateViewport: function () { + if ( !this.shown ) { + return; + } - 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'; - 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; - var clientWidth = document.documentElement.clientWidth; + this.orientation = clientWidth > document.documentElement.clientHeight ? 'landscape' : 'portrait'; - 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; - 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'; + }, - this.element.style.fontSize = this.options.fontSize / this.scale + 'px'; - }, + resize: function () { + clearTimeout(this.resizeTimer); + this.resizeTimer = setTimeout(this.updateViewport.bind(this), 100); + }, - resize: function () { - clearTimeout(this.resizeTimer); - this.resizeTimer = setTimeout(this.updateViewport.bind(this), 100); - }, + updateSession: function () { + if ( ath.hasLocalStorage === false ) { + return; + } - updateSession: function () { - if ( ath.hasLocalStorage === false ) { - return; - } + if (localStorage) { + localStorage.setItem(this.options.appID, JSON.stringify(this.session)); + } + }, - if (localStorage) { - localStorage.setItem(this.options.appID, JSON.stringify(this.session)); - } - }, + clearSession: function () { + this.session = _defaultSession; + this.updateSession(); + }, - clearSession: function () { - this.session = _defaultSession; - this.updateSession(); - }, + getItem: function(item) { + try { + if (!localStorage) { + throw new Error('localStorage is not defined'); + } - getItem: function(item) { - try { - if (!localStorage) { - throw new Error('localStorage is not defined'); + return localStorage.getItem(item); + } catch(e) { + // Preventing exception for some browsers when fetching localStorage key + ath.hasLocalStorage = false; } + }, - return localStorage.getItem(item); - } catch(e) { - // Preventing exception for some browsers when fetching localStorage key - ath.hasLocalStorage = false; - } - }, - - 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(); - } -}; + optOut: function () { + this.session.optedout = true; + this.updateSession(); + }, -// utility -function _extend (target, obj) { - for ( var i in obj ) { - target[i] = obj[i]; - } + optIn: function () { + this.session.optedout = false; + this.updateSession(); + }, - return target; -} + clearDisplayCount: function () { + this.session.displayCount = 0; + this.updateSession(); + }, -function _removeToken () { - if ( document.location.hash == '#ath' ) { - history.replaceState('', window.document.title, document.location.href.split('#')[0]); - } + _preventDefault: function (e) { + e.preventDefault(); + e.stopPropagation(); + } + }; - if ( _reSmartURL.test(document.location.href) ) { - history.replaceState('', window.document.title, document.location.href.replace(_reSmartURL, '$1')); - } + // utility + function _extend (target, obj) { + for ( var i in obj ) { + target[i] = obj[i]; + } - if ( _reQueryString.test(document.location.search) ) { - history.replaceState('', window.document.title, document.location.href.replace(_reQueryString, '$2')); + return target; } -} -// expose to the world -window.addToHomescreen = ath; + 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')); + } + } -})(window, document); + // expose to the world + window.addToHomescreen = ath; +})); diff --git a/src/addtohomescreen.min.js b/src/addtohomescreen.min.js index 040df1b..bbf7276 100644 --- a/src/addtohomescreen.min.js +++ b/src/addtohomescreen.min.js @@ -1,2 +1,2 @@ /* Add to Homescreen v3.2.2 ~ (c) 2015 Matteo Spinelli ~ @license: http://cubiq.org/license */ -!function(e,t){function i(){e.removeEventListener("load",i,!1),r=!0}function n(e){return l=l||new n.Class(e)}function o(e,t){for(var i in t)e[i]=t[i];return e}function s(){"#ath"==t.location.hash&&history.replaceState("",e.document.title,t.location.href.split("#")[0]),h.test(t.location.href)&&history.replaceState("",e.document.title,t.location.href.replace(h,"$1")),d.test(t.location.search)&&history.replaceState("",e.document.title,t.location.href.replace(d,"$2"))}var a="addEventListener"in e,r=!1;"complete"===t.readyState?r=!0:a&&e.addEventListener("load",i,!1);var l,h=/\/ath(\/)?$/,d=/([\?&]ath=[^&]*$|&ath=[^&]*(&))/;n.intl={de_de:{ios:"Um diese Web-App zum Home-Bildschirm hinzuzufügen, tippen Sie auf %icon und dann Zum Home-Bildschirm.",android:'Um diese Web-App zum Home-Bildschirm hinzuzufügen, öffnen Sie das Menü und tippen dann auf Zum Startbildschirm hinzufügen. Wenn Ihr Gerät eine Menütaste hat, lässt sich das Browsermenü über diese öffnen. Ansonsten tippen Sie auf icon.'},da_dk:{ios:"For at tilføje denne web app til hjemmeskærmen: Tryk %icon og derefter Føj til hjemmeskærm.",android:'For at tilføje denne web app til hjemmeskærmen, åbn browser egenskaber menuen og tryk på Føj til hjemmeskærm. Denne menu kan tilgås ved at trykke på menu knappen, hvis din enhed har en, eller ved at trykke på det øverste højre menu ikon icon.'},en_us:{ios:"To add this web app to the home screen: tap %icon and then Add to Home Screen.",android:'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.'},es_es:{ios:"Para añadir esta aplicación web a la pantalla de inicio: pulsa %icon y selecciona Añadir a pantalla de inicio.",android:'Para añadir esta aplicación web a la pantalla de inicio, abre las opciones y pulsa Añadir a pantalla inicio. El menú se puede acceder pulsando el botón táctil en caso de tenerlo, o bien el icono de la parte superior derecha de la pantalla icon.'},fi_fi:{ios:"Liitä tämä sovellus kotivalikkoon: klikkaa %icon ja tämän jälkeen Lisää kotivalikkoon.",android:'Lisätäksesi tämän sovelluksen aloitusnäytölle, avaa selaimen valikko ja klikkaa tähti -ikonia tai Lisää aloitusnäytölle tekstiä. Valikkoon pääsee myös painamalla menuvalikkoa, jos laitteessasi on sellainen tai koskettamalla oikealla yläkulmassa menu ikonia icon.'},fr_fr:{ios:"Pour ajouter cette application web sur l'écran d'accueil : Appuyez %icon et sélectionnez Ajouter sur l'écran d'accueil.",android:'Pour ajouter cette application web sur l\'écran d\'accueil : Appuyez sur le bouton "menu", puis sur Ajouter sur l\'écran d\'accueil. Le menu peut-être accessible en appyant sur le bouton "menu" du téléphone s\'il en possède un . Sinon, il se trouve probablement dans la coin supérieur droit du navigateur %icon.'},he_il:{ios:'להוספת האפליקציה למסך הבית: ללחוץ על %icon ואז הוסף למסך הבית.',android:'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.'},it_it:{ios:"Per aggiungere questa web app alla schermata iniziale: premi %icon e poi Aggiungi a Home.",android:'Per aggiungere questa web app alla schermata iniziale, apri il menu opzioni del browser e premi su Aggiungi alla homescreen. Puoi accedere al menu premendo il pulsante hardware delle opzioni se la tua device ne ha uno, oppure premendo l\'icona icon in alto a destra.'},ja_jp:{ios:"このウェプアプリをホーム画面に追加するために%iconを押してホーム画面に追加。",android:'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.'},ko_kr:{ios:"홈 화면에 바로가기 생성: %icon 을 클릭한 후 홈 화면에 추가.",android:'브라우저 옵션 메뉴의 홈 화면에 추가를 클릭하여 홈화면에 바로가기를 생성할 수 있습니다. 옵션 메뉴는 장치의 메뉴 버튼을 누르거나 오른쪽 상단의 메뉴 아이콘 icon을 클릭하여 접근할 수 있습니다.'},nb_no:{ios:"For å installere denne appen på hjem-skjermen: trykk på %icon og deretter Legg til på Hjem-skjerm.",android:'For å legge til denne webappen på startsiden åpner en nettlesermenyen og velger Legg til på startsiden. Menyen åpnes ved å trykke på den fysiske menyknappen hvis enheten har det, eller ved å trykke på menyikonet øverst til høyre icon.'},pt_br:{ios:"Para adicionar este app à tela de início: clique %icon e então Tela de início.",android:'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.'},pt_pt:{ios:"Para adicionar esta app ao ecrã principal: clique %icon e depois Ecrã principal.",android:'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.'},nl_nl:{ios:"Om deze webapp op je telefoon te installeren, klik op %icon en dan Zet in beginscherm.",android:'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.'},ru_ru:{ios:'Чтобы добавить этот сайт на свой домашний экран, нажмите на иконку %icon и затем На экран "Домой".',android:'Чтобы добавить сайт на свой домашний экран, откройте меню браузера и нажмите на Добавить на главный экран. Меню можно вызвать, нажав на кнопку меню вашего телефона, если она есть. Или найдите иконку сверху справа иконка.'},sv_se:{ios:"För att lägga till denna webbapplikation på hemskärmen: tryck på %icon och därefter Lägg till på hemskärmen.",android:'För att lägga till den här webbappen på hemskärmen öppnar du webbläsarens alternativ-meny och väljer Lägg till på startskärmen. Man hittar menyn genom att trycka på hårdvaruknappen om din enhet har en sådan, eller genom att trycka på menyikonen högst upp till höger icon.'},zh_cn:{ios:"如要把应用程式加至主屏幕,请点击%icon, 然后加至主屏幕",android:'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.'},zh_tw:{ios:"如要把應用程式加至主屏幕, 請點擊%icon, 然後加至主屏幕.",android:'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.'}};for(var p in n.intl)n.intl[p.substr(0,2)]=n.intl[p];n.defaults={appID:"org.cubiq.addtohome",fontSize:15,debug:!1,logging:!1,modal:!1,mandatory:!1,autostart:!0,skipFirstVisit:!1,startDelay:1,lifespan:15,displayPace:1440,maxDisplayCount:0,icon:!0,message:"",validLocation:[],onInit:null,onShow:null,onRemove:null,onAdd:null,onPrivate:null,privateModeOverride:!1,detectHomescreen:!1};var c=e.navigator.userAgent,m=e.navigator;o(n,{hasToken:"#ath"==t.location.hash||h.test(t.location.href)||d.test(t.location.search),isRetina:e.devicePixelRatio&&e.devicePixelRatio>1,isIDevice:/iphone|ipod|ipad/i.test(c),isMobileChrome:c.indexOf("Android")>-1&&/Chrome\/[.0-9]*/.test(c)&&-1==c.indexOf("Version"),isMobileIE:c.indexOf("Windows Phone")>-1,language:m.language&&m.language.toLowerCase().replace("-","_")||""}),n.language=n.language&&n.language in n.intl?n.language:"en_us",n.isMobileSafari=n.isIDevice&&c.indexOf("Safari")>-1&&c.indexOf("CriOS")<0,n.OS=n.isIDevice?"ios":n.isMobileChrome?"android":n.isMobileIE?"windows":"unsupported",n.OSVersion=c.match(/(OS|Android) (\d+[_\.]\d+)/),n.OSVersion=n.OSVersion&&n.OSVersion[2]?+n.OSVersion[2].replace("_","."):0,n.isStandalone="standalone"in e.navigator&&e.navigator.standalone,n.isTablet=n.isMobileSafari&&c.indexOf("iPad")>-1||n.isMobileChrome&&c.indexOf("Mobile")<0,n.isCompatible=n.isMobileSafari&&n.OSVersion>=6||n.isMobileChrome;var u={lastDisplayTime:0,returningVisitor:!1,displayCount:0,optedout:!1,added:!1};n.removeSession=function(e){try{if(!localStorage)throw new Error("localStorage is not defined");localStorage.removeItem(e||n.defaults.appID)}catch(t){}},n.doLog=function(e){this.options.logging&&console.log(e)},n.Class=function(i){if(this.doLog=n.doLog,this.options=o({},n.defaults),o(this.options,i),i.debug&&"undefined"==typeof i.logging&&(this.options.logging=!0),a){if(this.options.mandatory=this.options.mandatory&&("standalone"in e.navigator||this.options.debug),this.options.modal=this.options.modal||this.options.mandatory,this.options.mandatory&&(this.options.startDelay=-.5),this.options.detectHomescreen=this.options.detectHomescreen===!0?"hash":this.options.detectHomescreen,this.options.debug&&(n.isCompatible=!0,n.OS="string"==typeof this.options.debug?this.options.debug:"unsupported"==n.OS?"android":n.OS,n.OSVersion="ios"==n.OS?"8":"4"),this.container=t.documentElement,this.session=this.getItem(this.options.appID),this.session=this.session?JSON.parse(this.session):void 0,!n.hasToken||n.isCompatible&&this.session||(n.hasToken=!1,s()),!n.isCompatible)return void this.doLog("Add to homescreen: not displaying callout because device not supported");this.session=this.session||u;try{if(!localStorage)throw new Error("localStorage is not defined");localStorage.setItem(this.options.appID,JSON.stringify(this.session)),n.hasLocalStorage=!0}catch(r){n.hasLocalStorage=!1,this.options.onPrivate&&this.options.onPrivate.call(this)}for(var l=!this.options.validLocation.length,h=this.options.validLocation.length;h--;)if(this.options.validLocation[h].test(t.location.href)){l=!0;break}if(this.getItem("addToHome")&&this.optOut(),this.session.optedout)return void this.doLog("Add to homescreen: not displaying callout because user opted out");if(this.session.added)return void this.doLog("Add to homescreen: not displaying callout because already added to the homescreen");if(!l)return void this.doLog("Add to homescreen: not displaying callout because not a valid location");if(n.isStandalone)return this.session.added||(this.session.added=!0,this.updateSession(),this.options.onAdd&&n.hasLocalStorage&&this.options.onAdd.call(this)),void this.doLog("Add to homescreen: not displaying callout because in standalone mode");if(this.options.detectHomescreen){if(n.hasToken)return s(),this.session.added||(this.session.added=!0,this.updateSession(),this.options.onAdd&&n.hasLocalStorage&&this.options.onAdd.call(this)),void this.doLog("Add to homescreen: not displaying callout because URL has token, so we are likely coming from homescreen");"hash"==this.options.detectHomescreen?history.replaceState("",e.document.title,t.location.href+"#ath"):"smartURL"==this.options.detectHomescreen?history.replaceState("",e.document.title,t.location.href.replace(/(\/)?$/,"/ath$1")):history.replaceState("",e.document.title,t.location.href+(t.location.search?"&":"?")+"ath=")}if(!this.session.returningVisitor&&(this.session.returningVisitor=!0,this.updateSession(),this.options.skipFirstVisit))return void this.doLog("Add to homescreen: not displaying callout because skipping first visit");if(!this.options.privateModeOverride&&!n.hasLocalStorage)return void this.doLog("Add to homescreen: not displaying callout because browser is in private mode");this.ready=!0,this.options.onInit&&this.options.onInit.call(this),this.options.autostart&&(this.doLog("Add to homescreen: autostart displaying callout"),this.show())}},n.Class.prototype={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 t=this.events[e.type];t&&this[t](e)},show:function(i){if(this.options.autostart&&!r)return void setTimeout(this.show.bind(this),50);if(this.shown)return void this.doLog("Add to homescreen: not displaying callout because already shown on screen");var o=Date.now(),s=this.session.lastDisplayTime;if(i!==!0){if(!this.ready)return void this.doLog("Add to homescreen: not displaying callout because not ready");if(o-s<6e4*this.options.displayPace)return void this.doLog("Add to homescreen: not displaying callout because displayed recently");if(this.options.maxDisplayCount&&this.session.displayCount>=this.options.maxDisplayCount)return void this.doLog("Add to homescreen: not displaying callout because displayed too many times already")}this.shown=!0,this.session.lastDisplayTime=o,this.session.displayCount++,this.updateSession(),this.applicationIcon||(this.applicationIcon=t.querySelector("ios"==n.OS?'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]':'head link[rel^="shortcut icon"][sizes="196x196"],head link[rel^=apple-touch-icon]'));var a="";"object"==typeof this.options.message&&n.language in this.options.message?a=this.options.message[n.language][n.OS]:"object"==typeof this.options.message&&n.OS in this.options.message?a=this.options.message[n.OS]:this.options.message in n.intl?a=n.intl[this.options.message][n.OS]:""!==this.options.message?a=this.options.message:n.OS in n.intl[n.language]&&(a=n.intl[n.language][n.OS]),a="

"+a.replace("%icon",'icon')+"

",this.viewport=t.createElement("div"),this.viewport.className="ath-viewport",this.options.modal&&(this.viewport.className+=" ath-modal"),this.options.mandatory&&(this.viewport.className+=" ath-mandatory"),this.viewport.style.position="absolute",this.element=t.createElement("div"),this.element.className="ath-container ath-"+n.OS+" ath-"+n.OS+(n.OSVersion+"").substr(0,1)+" ath-"+(n.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,-"+e.innerHeight+"px,0)",this.element.style.transform="translate3d(0,-"+e.innerHeight+"px,0)",this.options.icon&&this.applicationIcon&&(this.element.className+=" ath-icon",this.img=t.createElement("img"),this.img.className="ath-application-icon",this.img.addEventListener("load",this,!1),this.img.addEventListener("error",this,!1),this.img.src=this.applicationIcon.href,this.element.appendChild(this.img)),this.element.innerHTML+=a,this.viewport.style.left="-99999em",this.viewport.appendChild(this.element),this.container.appendChild(this.viewport),this.img?this.doLog("Add to homescreen: not displaying callout because waiting for img to load"):this._delayedShow()},_delayedShow:function(){setTimeout(this._show.bind(this),1e3*this.options.startDelay+500)},_show:function(){var i=this;this.updateViewport(),e.addEventListener("resize",this,!1),e.addEventListener("scroll",this,!1),e.addEventListener("orientationchange",this,!1),this.options.modal&&t.addEventListener("touchmove",this,!0),this.options.mandatory||setTimeout(function(){i.element.addEventListener("click",i,!0)},1e3),setTimeout(function(){i.element.style.webkitTransitionDuration="1.2s",i.element.style.transitionDuration="1.2s",i.element.style.webkitTransform="translate3d(0,0,0)",i.element.style.transform="translate3d(0,0,0)"},0),this.options.lifespan&&(this.removeTimer=setTimeout(this.remove.bind(this),1e3*this.options.lifespan)),this.options.onShow&&this.options.onShow.call(this)},remove:function(){clearTimeout(this.removeTimer),this.img&&(this.img.removeEventListener("load",this,!1),this.img.removeEventListener("error",this,!1)),e.removeEventListener("resize",this,!1),e.removeEventListener("scroll",this,!1),e.removeEventListener("orientationchange",this,!1),t.removeEventListener("touchmove",this,!0),this.element.removeEventListener("click",this,!0),this.element.addEventListener("transitionend",this,!1),this.element.addEventListener("webkitTransitionEnd",this,!1),this.element.addEventListener("MSTransitionEnd",this,!1),this.element.style.webkitTransitionDuration="0.3s",this.element.style.opacity="0"},_removeElements:function(){this.element.removeEventListener("transitionend",this,!1),this.element.removeEventListener("webkitTransitionEnd",this,!1),this.element.removeEventListener("MSTransitionEnd",this,!1),this.container.removeChild(this.viewport),this.shown=!1,this.options.onRemove&&this.options.onRemove.call(this)},updateViewport:function(){if(this.shown){this.viewport.style.width=e.innerWidth+"px",this.viewport.style.height=e.innerHeight+"px",this.viewport.style.left=e.scrollX+"px",this.viewport.style.top=e.scrollY+"px";var i=t.documentElement.clientWidth;this.orientation=i>t.documentElement.clientHeight?"landscape":"portrait";var o="ios"==n.OS?"portrait"==this.orientation?screen.width:screen.height:screen.width;this.scale=screen.width>i?1:o/e.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(){n.hasLocalStorage!==!1&&localStorage&&localStorage.setItem(this.options.appID,JSON.stringify(this.session))},clearSession:function(){this.session=u,this.updateSession()},getItem:function(e){try{if(!localStorage)throw new Error("localStorage is not defined");return localStorage.getItem(e)}catch(t){n.hasLocalStorage=!1}},optOut:function(){this.session.optedout=!0,this.updateSession()},optIn:function(){this.session.optedout=!1,this.updateSession()},clearDisplayCount:function(){this.session.displayCount=0,this.updateSession()},_preventDefault:function(e){e.preventDefault(),e.stopPropagation()}},e.addToHomescreen=n}(window,document); +!function(e,t){"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?module.exports=t():e.returnExports=t()}(this,function(){function e(){window.removeEventListener("load",e,!1),s=!0}function t(e){return a=a||new t.Class(e)}function n(e,t){for(var n in t)e[n]=t[n];return e}function i(){"#ath"==document.location.hash&&history.replaceState("",window.document.title,document.location.href.split("#")[0]),r.test(document.location.href)&&history.replaceState("",window.document.title,document.location.href.replace(r,"$1")),l.test(document.location.search)&&history.replaceState("",window.document.title,document.location.href.replace(l,"$2"))}var o="addEventListener"in window,s=!1;"complete"===document.readyState?s=!0:o&&window.addEventListener("load",e,!1);var a,r=/\/ath(\/)?$/,l=/([\?&]ath=[^&]*$|&ath=[^&]*(&))/;t.intl={de_de:{ios:"Um diese Web-App zum Home-Bildschirm hinzuzufügen, tippen Sie auf %icon und dann Zum Home-Bildschirm.",android:'Um diese Web-App zum Home-Bildschirm hinzuzufügen, öffnen Sie das Menü und tippen dann auf Zum Startbildschirm hinzufügen. Wenn Ihr Gerät eine Menütaste hat, lässt sich das Browsermenü über diese öffnen. Ansonsten tippen Sie auf icon.'},da_dk:{ios:"For at tilføje denne web app til hjemmeskærmen: Tryk %icon og derefter Føj til hjemmeskærm.",android:'For at tilføje denne web app til hjemmeskærmen, åbn browser egenskaber menuen og tryk på Føj til hjemmeskærm. Denne menu kan tilgås ved at trykke på menu knappen, hvis din enhed har en, eller ved at trykke på det øverste højre menu ikon icon.'},en_us:{ios:"To add this web app to the home screen: tap %icon and then Add to Home Screen.",android:'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.'},es_es:{ios:"Para añadir esta aplicación web a la pantalla de inicio: pulsa %icon y selecciona Añadir a pantalla de inicio.",android:'Para añadir esta aplicación web a la pantalla de inicio, abre las opciones y pulsa Añadir a pantalla inicio. El menú se puede acceder pulsando el botón táctil en caso de tenerlo, o bien el icono de la parte superior derecha de la pantalla icon.'},fi_fi:{ios:"Liitä tämä sovellus kotivalikkoon: klikkaa %icon ja tämän jälkeen Lisää kotivalikkoon.",android:'Lisätäksesi tämän sovelluksen aloitusnäytölle, avaa selaimen valikko ja klikkaa tähti -ikonia tai Lisää aloitusnäytölle tekstiä. Valikkoon pääsee myös painamalla menuvalikkoa, jos laitteessasi on sellainen tai koskettamalla oikealla yläkulmassa menu ikonia icon.'},fr_fr:{ios:"Pour ajouter cette application web sur l'écran d'accueil : Appuyez %icon et sélectionnez Ajouter sur l'écran d'accueil.",android:'Pour ajouter cette application web sur l\'écran d\'accueil : Appuyez sur le bouton "menu", puis sur Ajouter sur l\'écran d\'accueil. Le menu peut-être accessible en appyant sur le bouton "menu" du téléphone s\'il en possède un . Sinon, il se trouve probablement dans la coin supérieur droit du navigateur %icon.'},he_il:{ios:'להוספת האפליקציה למסך הבית: ללחוץ על %icon ואז הוסף למסך הבית.',android:'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.'},it_it:{ios:"Per aggiungere questa web app alla schermata iniziale: premi %icon e poi Aggiungi a Home.",android:'Per aggiungere questa web app alla schermata iniziale, apri il menu opzioni del browser e premi su Aggiungi alla homescreen. Puoi accedere al menu premendo il pulsante hardware delle opzioni se la tua device ne ha uno, oppure premendo l\'icona icon in alto a destra.'},ja_jp:{ios:"このウェプアプリをホーム画面に追加するために%iconを押してホーム画面に追加。",android:'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.'},ko_kr:{ios:"홈 화면에 바로가기 생성: %icon 을 클릭한 후 홈 화면에 추가.",android:'브라우저 옵션 메뉴의 홈 화면에 추가를 클릭하여 홈화면에 바로가기를 생성할 수 있습니다. 옵션 메뉴는 장치의 메뉴 버튼을 누르거나 오른쪽 상단의 메뉴 아이콘 icon을 클릭하여 접근할 수 있습니다.'},nb_no:{ios:"For å installere denne appen på hjem-skjermen: trykk på %icon og deretter Legg til på Hjem-skjerm.",android:'For å legge til denne webappen på startsiden åpner en nettlesermenyen og velger Legg til på startsiden. Menyen åpnes ved å trykke på den fysiske menyknappen hvis enheten har det, eller ved å trykke på menyikonet øverst til høyre icon.'},pt_br:{ios:"Para adicionar este app à tela de início: clique %icon e então Tela de início.",android:'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.'},pt_pt:{ios:"Para adicionar esta app ao ecrã principal: clique %icon e depois Ecrã principal.",android:'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.'},nl_nl:{ios:"Om deze webapp op je telefoon te installeren, klik op %icon en dan Zet in beginscherm.",android:'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.'},ru_ru:{ios:'Чтобы добавить этот сайт на свой домашний экран, нажмите на иконку %icon и затем На экран "Домой".',android:'Чтобы добавить сайт на свой домашний экран, откройте меню браузера и нажмите на Добавить на главный экран. Меню можно вызвать, нажав на кнопку меню вашего телефона, если она есть. Или найдите иконку сверху справа иконка.'},sv_se:{ios:"För att lägga till denna webbapplikation på hemskärmen: tryck på %icon och därefter Lägg till på hemskärmen.",android:'För att lägga till den här webbappen på hemskärmen öppnar du webbläsarens alternativ-meny och väljer Lägg till på startskärmen. Man hittar menyn genom att trycka på hårdvaruknappen om din enhet har en sådan, eller genom att trycka på menyikonen högst upp till höger icon.'},zh_cn:{ios:"如要把应用程序加至主屏幕,请点击%icon, 然后添加到主屏幕",android:'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.'},zh_tw:{ios:"如要把應用程式加至主屏幕, 請點擊%icon, 然後加至主屏幕.",android:'To add this web app to the home screen open the browser option menu and tap on Add to homescreen. The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon icon.'}};for(var d in t.intl)t.intl[d.substr(0,2)]=t.intl[d];t.defaults={appID:"org.cubiq.addtohome",fontSize:15,debug:!1,logging:!1,modal:!1,mandatory:!1,autostart:!0,skipFirstVisit:!1,startDelay:1,lifespan:15,displayPace:1440,maxDisplayCount:0,icon:!0,message:"",validLocation:[],onInit:null,onShow:null,onRemove:null,onAdd:null,onPrivate:null,privateModeOverride:!1,detectHomescreen:!1};var h=window.navigator.userAgent,c=window.navigator;n(t,{hasToken:"#ath"==document.location.hash||r.test(document.location.href)||l.test(document.location.search),isRetina:window.devicePixelRatio&&window.devicePixelRatio>1,isIDevice:/iphone|ipod|ipad/i.test(h),isMobileChrome:h.indexOf("Android")>-1&&/Chrome\/[.0-9]*/.test(h)&&-1==h.indexOf("Version"),isMobileIE:h.indexOf("Windows Phone")>-1,language:c.language&&c.language.toLowerCase().replace("-","_")||""}),t.language=t.language&&t.language in t.intl?t.language:"en_us",t.isMobileSafari=t.isIDevice&&h.indexOf("Safari")>-1&&h.indexOf("CriOS")<0,t.OS=t.isIDevice?"ios":t.isMobileChrome?"android":t.isMobileIE?"windows":"unsupported",t.OSVersion=h.match(/(OS|Android) (\d+[_\.]\d+)/),t.OSVersion=t.OSVersion&&t.OSVersion[2]?+t.OSVersion[2].replace("_","."):0,t.isStandalone="standalone"in window.navigator&&window.navigator.standalone,t.isTablet=t.isMobileSafari&&h.indexOf("iPad")>-1||t.isMobileChrome&&h.indexOf("Mobile")<0,t.isCompatible=t.isMobileSafari&&t.OSVersion>=6||t.isMobileChrome;var p={lastDisplayTime:0,returningVisitor:!1,displayCount:0,optedout:!1,added:!1};t.removeSession=function(e){try{if(!localStorage)throw new Error("localStorage is not defined");localStorage.removeItem(e||t.defaults.appID)}catch(n){}},t.doLog=function(e){this.options.logging&&console.log(e)},t.Class=function(e){if(this.doLog=t.doLog,this.options=n({},t.defaults),n(this.options,e),e&&e.debug&&"undefined"==typeof e.logging&&(this.options.logging=!0),o){if(this.options.mandatory=this.options.mandatory&&("standalone"in window.navigator||this.options.debug),this.options.modal=this.options.modal||this.options.mandatory,this.options.mandatory&&(this.options.startDelay=-.5),this.options.detectHomescreen=this.options.detectHomescreen===!0?"hash":this.options.detectHomescreen,this.options.debug&&(t.isCompatible=!0,t.OS="string"==typeof this.options.debug?this.options.debug:"unsupported"==t.OS?"android":t.OS,t.OSVersion="ios"==t.OS?"8":"4"),this.container=document.documentElement,this.session=this.getItem(this.options.appID),this.session=this.session?JSON.parse(this.session):void 0,!t.hasToken||t.isCompatible&&this.session||(t.hasToken=!1,i()),!t.isCompatible)return void this.doLog("Add to homescreen: not displaying callout because device not supported");this.session=this.session||p;try{if(!localStorage)throw new Error("localStorage is not defined");localStorage.setItem(this.options.appID,JSON.stringify(this.session)),t.hasLocalStorage=!0}catch(s){t.hasLocalStorage=!1,this.options.onPrivate&&this.options.onPrivate.call(this)}for(var a=!this.options.validLocation.length,r=this.options.validLocation.length;r--;)if(this.options.validLocation[r].test(document.location.href)){a=!0;break}if(this.getItem("addToHome")&&this.optOut(),this.session.optedout)return void this.doLog("Add to homescreen: not displaying callout because user opted out");if(this.session.added)return void this.doLog("Add to homescreen: not displaying callout because already added to the homescreen");if(!a)return void this.doLog("Add to homescreen: not displaying callout because not a valid location");if(t.isStandalone)return this.session.added||(this.session.added=!0,this.updateSession(),this.options.onAdd&&t.hasLocalStorage&&this.options.onAdd.call(this)),void this.doLog("Add to homescreen: not displaying callout because in standalone mode");if(this.options.detectHomescreen){if(t.hasToken)return i(),this.session.added||(this.session.added=!0,this.updateSession(),this.options.onAdd&&t.hasLocalStorage&&this.options.onAdd.call(this)),void this.doLog("Add to homescreen: not displaying callout because URL has token, so we are likely coming from homescreen");"hash"==this.options.detectHomescreen?history.replaceState("",window.document.title,document.location.href+"#ath"):"smartURL"==this.options.detectHomescreen?history.replaceState("",window.document.title,document.location.href.replace(/(\/)?$/,"/ath$1")):history.replaceState("",window.document.title,document.location.href+(document.location.search?"&":"?")+"ath=")}if(!this.session.returningVisitor&&(this.session.returningVisitor=!0,this.updateSession(),this.options.skipFirstVisit))return void this.doLog("Add to homescreen: not displaying callout because skipping first visit");if(!this.options.privateModeOverride&&!t.hasLocalStorage)return void this.doLog("Add to homescreen: not displaying callout because browser is in private mode");this.ready=!0,this.options.onInit&&this.options.onInit.call(this),this.options.autostart&&(this.doLog("Add to homescreen: autostart displaying callout"),this.show())}},t.Class.prototype={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 t=this.events[e.type];t&&this[t](e)},show:function(e){if(this.options.autostart&&!s)return void setTimeout(this.show.bind(this),50);if(this.shown)return void this.doLog("Add to homescreen: not displaying callout because already shown on screen");var n=Date.now(),i=this.session.lastDisplayTime;if(e!==!0){if(!this.ready)return void this.doLog("Add to homescreen: not displaying callout because not ready");if(n-i<6e4*this.options.displayPace)return void this.doLog("Add to homescreen: not displaying callout because displayed recently");if(this.options.maxDisplayCount&&this.session.displayCount>=this.options.maxDisplayCount)return void this.doLog("Add to homescreen: not displaying callout because displayed too many times already")}this.shown=!0,this.session.lastDisplayTime=n,this.session.displayCount++,this.updateSession(),this.applicationIcon||(this.applicationIcon=document.querySelector("ios"==t.OS?'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]':'head link[rel^="shortcut icon"][sizes="196x196"],head link[rel^=apple-touch-icon]'));var o="";"object"==typeof this.options.message&&t.language in this.options.message?o=this.options.message[t.language][t.OS]:"object"==typeof this.options.message&&t.OS in this.options.message?o=this.options.message[t.OS]:this.options.message in t.intl?o=t.intl[this.options.message][t.OS]:""!==this.options.message?o=this.options.message:t.OS in t.intl[t.language]&&(o=t.intl[t.language][t.OS]),o="

"+o.replace("%icon",'icon')+"

",this.viewport=document.createElement("div"),this.viewport.className="ath-viewport",this.options.modal&&(this.viewport.className+=" ath-modal"),this.options.mandatory&&(this.viewport.className+=" ath-mandatory"),this.viewport.style.position="absolute",this.element=document.createElement("div"),this.element.className="ath-container ath-"+t.OS+" ath-"+t.OS+(t.OSVersion+"").substr(0,1)+" ath-"+(t.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)",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,!1),this.img.addEventListener("error",this,!1),this.img.src=this.applicationIcon.href,this.element.appendChild(this.img)),this.element.innerHTML+=o,this.viewport.style.left="-99999em",this.viewport.appendChild(this.element),this.container.appendChild(this.viewport),this.img?this.doLog("Add to homescreen: not displaying callout because waiting for img to load"):this._delayedShow()},_delayedShow:function(){setTimeout(this._show.bind(this),1e3*this.options.startDelay+500)},_show:function(){var e=this;this.updateViewport(),window.addEventListener("resize",this,!1),window.addEventListener("scroll",this,!1),window.addEventListener("orientationchange",this,!1),this.options.modal&&document.addEventListener("touchmove",this,!0),this.options.mandatory||setTimeout(function(){e.element.addEventListener("click",e,!0)},1e3),setTimeout(function(){e.element.style.webkitTransitionDuration="1.2s",e.element.style.transitionDuration="1.2s",e.element.style.webkitTransform="translate3d(0,0,0)",e.element.style.transform="translate3d(0,0,0)"},0),this.options.lifespan&&(this.removeTimer=setTimeout(this.remove.bind(this),1e3*this.options.lifespan)),this.options.onShow&&this.options.onShow.call(this)},remove:function(){clearTimeout(this.removeTimer),this.img&&(this.img.removeEventListener("load",this,!1),this.img.removeEventListener("error",this,!1)),window.removeEventListener("resize",this,!1),window.removeEventListener("scroll",this,!1),window.removeEventListener("orientationchange",this,!1),document.removeEventListener("touchmove",this,!0),this.element.removeEventListener("click",this,!0),this.element.addEventListener("transitionend",this,!1),this.element.addEventListener("webkitTransitionEnd",this,!1),this.element.addEventListener("MSTransitionEnd",this,!1),this.element.style.webkitTransitionDuration="0.3s",this.element.style.opacity="0"},_removeElements:function(){this.element.removeEventListener("transitionend",this,!1),this.element.removeEventListener("webkitTransitionEnd",this,!1),this.element.removeEventListener("MSTransitionEnd",this,!1),this.container.removeChild(this.viewport),this.shown=!1,this.options.onRemove&&this.options.onRemove.call(this)},updateViewport:function(){if(this.shown){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 e=document.documentElement.clientWidth;this.orientation=e>document.documentElement.clientHeight?"landscape":"portrait";var n="ios"==t.OS?"portrait"==this.orientation?screen.width:screen.height:screen.width;this.scale=screen.width>e?1:n/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(){t.hasLocalStorage!==!1&&localStorage&&localStorage.setItem(this.options.appID,JSON.stringify(this.session))},clearSession:function(){this.session=p,this.updateSession()},getItem:function(e){try{if(!localStorage)throw new Error("localStorage is not defined");return localStorage.getItem(e)}catch(n){t.hasLocalStorage=!1}},optOut:function(){this.session.optedout=!0,this.updateSession()},optIn:function(){this.session.optedout=!1,this.updateSession()},clearDisplayCount:function(){this.session.displayCount=0,this.updateSession()},_preventDefault:function(e){e.preventDefault(),e.stopPropagation()}},window.addToHomescreen=t});