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