Ui Add2home
Ui Add2home
var UI = require('./core');
/**
* Add to Homescreen v3.2.2
* (c) 2015 Matteo Spinelli
* @license: http://cubiq.org/license
*/
function loaded() {
window.removeEventListener('load', loaded, false);
_DOMReady = true;
}
// singleton
var _instance;
function ath(options) {
_instance = _instance || new ath.Class(options);
return _instance;
}
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>'
}
};
// 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')
};
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
}
};
ath.doLog = function(logStr) {
if (this.options.logging) {
console.log(logStr);
}
};
ath.Class = function(options) {
// class methods
this.doLog = ath.doLog;
// load session
this.session = this.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();
}
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);
}
}
// 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;
}
// (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.onInit) {
this.options.onInit.call(this);
}
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");
return;
}
this.shown = true;
this.img.src = this.applicationIcon.href;
this.element.appendChild(this.img);
}
this.element.innerHTML += message;
// 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);
},
_show: function() {
var that = this;
// update the viewport size and orientation
this.updateViewport();
if (this.options.modal) {
// lock any other interaction
document.addEventListener('touchmove', this, true);
}
remove: function() {
clearTimeout(this.removeTimer);
_removeElements: function() {
this.element.removeEventListener('transitionend', this, false);
this.element.removeEventListener('webkitTransitionEnd', this, false);
this.element.removeEventListener('MSTransitionEnd', this, false);
this.shown = false;
updateViewport: function() {
if (!this.shown) {
return;
}
resize: function() {
clearTimeout(this.resizeTimer);
this.resizeTimer = setTimeout(this.updateViewport.bind(this), 100);
},
updateSession: function() {
if (ath.hasLocalStorage === false) {
return;
}
if (localStorage) {
localStorage.setItem(this.options.appID, JSON.stringify(this.session));
}
},
clearSession: function() {
this.session = _defaultSession;
this.updateSession();
},
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;
}
},
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'));
}
}
ath.VERSION = '3.2.2';