add-to-homescreen-rails 2.0.11 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +5 -5
- data/app/assets/javascripts/addtohomescreen.js +552 -0
- data/app/assets/stylesheets/addtohomescreen.css +236 -0
- data/lib/add-to-homescreen-rails/version.rb +1 -1
- metadata +5 -5
- data/app/assets/javascripts/add2home.js +0 -344
- data/app/assets/stylesheets/add2home.css +0 -180
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 43848950e30ebbafde25389ad2d854996a5bc41c
|
4
|
+
data.tar.gz: c7b0e65e26182693cd08415049890ff67d00860e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 653f4252b0dc5a2f012f7ba277d73c2861dbec2d29764d51c9780c3e2eb64bae53e2450b7eebe81107f0bb34578bac1c034f488677af0496efdc2ec977c5deb9
|
7
|
+
data.tar.gz: 03321d356ed81b371acfa3df6193b4b44f92131f5395f80cad3cc75e07e45fdb851a3f280c5724dcf1f2c9773c12968da9ec71d28250146c13fb677ef41bc18d
|
data/README.md
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
*IMPORTANT:* If you are upgrading please note that there are major changes to the way version 3 works. Make sure you read the updated documentation and also update your rails require statement as shown below.
|
2
|
+
|
1
3
|
# 'Add to Home screen' for Rails
|
2
4
|
|
3
5
|
This gem vendors the 'Add to Home screen' assets for Rails 3.1 and greater.
|
@@ -16,21 +18,19 @@ For the orignal javascript and css file go to his [Github repository](https://gi
|
|
16
18
|
In your Gemfile, add:
|
17
19
|
|
18
20
|
```ruby
|
19
|
-
|
20
|
-
gem 'add-to-homescreen-rails'
|
21
|
-
end
|
21
|
+
gem 'add-to-homescreen-rails'
|
22
22
|
```
|
23
23
|
|
24
24
|
You can include it by adding the following to your javascript file:
|
25
25
|
|
26
26
|
```javascript
|
27
|
-
//= require
|
27
|
+
//= require addtohomescreen
|
28
28
|
```
|
29
29
|
|
30
30
|
And to the css file:
|
31
31
|
|
32
32
|
```css
|
33
33
|
/*
|
34
|
-
*= require
|
34
|
+
*= require addtohomescreen
|
35
35
|
*/
|
36
36
|
```
|
@@ -0,0 +1,552 @@
|
|
1
|
+
/* Add to Homescreen v3.0.0 ~ (c) 2014 Matteo Spinelli ~ @license: http://cubiq.org/license */
|
2
|
+
(function (window, document) {
|
3
|
+
/*
|
4
|
+
_ _ _____ _____
|
5
|
+
___ _| |_| |_ _|___| | |___ _____ ___ ___ ___ ___ ___ ___ ___
|
6
|
+
| .'| . | . | | | | . | | . | | -_|_ -| _| _| -_| -_| |
|
7
|
+
|__,|___|___| |_| |___|__|__|___|_|_|_|___|___|___|_| |___|___|_|_|
|
8
|
+
by Matteo Spinelli ~ http://cubiq.org
|
9
|
+
*/
|
10
|
+
|
11
|
+
// Check if document is loaded, needed by autostart
|
12
|
+
var _DOMReady = false;
|
13
|
+
window.addEventListener('load', loaded, false);
|
14
|
+
function loaded () {
|
15
|
+
window.removeEventListener('load', loaded, false);
|
16
|
+
_DOMReady = true;
|
17
|
+
}
|
18
|
+
|
19
|
+
// regex used to detect if app has been added to the homescreen
|
20
|
+
var _reSmartURL = /\/ath(\/)?$/;
|
21
|
+
var _reQueryString = /([\?&]ath=[^&]*$|&ath=[^&]*(&))/;
|
22
|
+
|
23
|
+
// singleton
|
24
|
+
var _instance;
|
25
|
+
function ath (options) {
|
26
|
+
_instance = _instance || new ath.Class(options);
|
27
|
+
|
28
|
+
return _instance;
|
29
|
+
}
|
30
|
+
|
31
|
+
// message in all supported languages
|
32
|
+
ath.intl = {
|
33
|
+
en_us: {
|
34
|
+
message: 'To add this web app to the home screen: tap %icon and then <strong>%action</strong>.',
|
35
|
+
action: { ios: 'Add to Home Screen', android: 'Add to homescreen', windows: 'pin to start' }
|
36
|
+
},
|
37
|
+
|
38
|
+
it_it: {
|
39
|
+
message: 'Per Aggiungere questa web app alla schermata iniziale: premi %icon e poi <strong>%action</strong>.',
|
40
|
+
action: { ios: 'Aggiungi a Home', android: 'Aggiungi alla homescreen', windows: 'pin to start' }
|
41
|
+
}
|
42
|
+
};
|
43
|
+
|
44
|
+
// default options
|
45
|
+
ath.defaults = {
|
46
|
+
appID: 'org.cubiq.addtohome', // local storage name (no need to change)
|
47
|
+
fontSize: 15, // base font size, used to properly resize the popup based on viewport scale factor
|
48
|
+
debug: false, // override browser checks
|
49
|
+
modal: false, // prevent further actions until the message is closed
|
50
|
+
mandatory: false, // you can't proceed if you don't add the app to the homescreen
|
51
|
+
autostart: true, // show the message automatically
|
52
|
+
skipFirstVisit: false, // show only to returning visitors (ie: skip the first time you visit)
|
53
|
+
startDelay: 1, // display the message after that many seconds from page load
|
54
|
+
lifespan: 15, // life of the message in seconds
|
55
|
+
displayPace: 1440, // minutes before the message is shown again (0: display every time, default 24 hours)
|
56
|
+
maxDisplayCount: 0, // absolute maximum number of times the message will be shown to the user (0: no limit)
|
57
|
+
icon: true, // add touch icon to the message
|
58
|
+
message: '', // the message can be customized
|
59
|
+
validLocation: [], // list of pages where the message will be shown (array of regexes)
|
60
|
+
onInit: null, // executed on instance creation
|
61
|
+
onShow: null, // executed when the message is shown
|
62
|
+
onRemove: null, // executed when the message is removed
|
63
|
+
onAdd: null, // when the application is launched the first time from the homescreen (guesstimate)
|
64
|
+
onPrivate: null, // executed if user is in private mode
|
65
|
+
detectHomescreen: false // try to detect if the site has been added to the homescreen (false | true | 'hash' | 'queryString' | 'smartURL')
|
66
|
+
};
|
67
|
+
|
68
|
+
// browser info and capability
|
69
|
+
var _ua = window.navigator.userAgent;
|
70
|
+
var _nav = window.navigator;
|
71
|
+
_extend(ath, {
|
72
|
+
hasToken: document.location.hash == '#ath' || _reSmartURL.test(document.location.href) || _reQueryString.test(document.location.search),
|
73
|
+
isRetina: window.devicePixelRatio && window.devicePixelRatio > 1,
|
74
|
+
isIDevice: (/iphone|ipod|ipad/i).test(_ua),
|
75
|
+
isMobileChrome: _ua.indexOf('Android') > -1 && (/Chrome\/[.0-9]*/).test(_ua),
|
76
|
+
isMobileIE: _ua.indexOf('Windows Phone') > -1,
|
77
|
+
language: _nav.language && _nav.language.toLowerCase().replace('-', '_')
|
78
|
+
});
|
79
|
+
|
80
|
+
ath.isMobileSafari = ath.isIDevice && _ua.indexOf('Safari') > -1 && _ua.indexOf('CriOS') < 0;
|
81
|
+
ath.OS = ath.isIDevice ? 'ios' : ath.isMobileChrome ? 'android' : ath.isMobileIE ? 'windows' : 'unsupported';
|
82
|
+
|
83
|
+
ath.OSVersion = _ua.match(/(OS|Android) (\d+[_\.]\d+)/);
|
84
|
+
ath.OSVersion = ath.OSVersion && ath.OSVersion[2] ? +ath.OSVersion[2].replace('_', '.') : 0;
|
85
|
+
|
86
|
+
ath.isStandalone = window.navigator.standalone || ( ath.isMobileChrome && ( screen.height - document.documentElement.clientHeight < 40 ) ); // TODO: check the lame polyfill
|
87
|
+
ath.isTablet = (ath.isMobileSafari && _ua.indexOf('iPad') > -1) || (ath.isMobileChrome && _ua.indexOf('Mobile') < 0);
|
88
|
+
|
89
|
+
ath.isCompatible = (ath.isIDevice && ath.OSVersion >= 6) || ath.isMobileChrome; // TODO: add winphone
|
90
|
+
|
91
|
+
// falls back to en_us if language is unsupported
|
92
|
+
ath.language = ath.language && ath.language in ath.intl ? ath.language : 'en_us';
|
93
|
+
|
94
|
+
var _defaultSession = {
|
95
|
+
lastDisplayTime: 0, // last time we displayed the message
|
96
|
+
returningVisitor: false, // is this the first time you visit
|
97
|
+
displayCount: 0, // number of times the message has been shown
|
98
|
+
optedout: false, // has the user opted out
|
99
|
+
added: false // has been actually added to the homescreen
|
100
|
+
};
|
101
|
+
|
102
|
+
ath.removeSession = function (appID) {
|
103
|
+
try {
|
104
|
+
localStorage.removeItem(appID || ath.defaults.appID);
|
105
|
+
} catch (e) {
|
106
|
+
// we are most likely in private mode
|
107
|
+
}
|
108
|
+
};
|
109
|
+
|
110
|
+
ath.Class = function (options) {
|
111
|
+
// merge default options with user config
|
112
|
+
this.options = _extend({}, ath.defaults);
|
113
|
+
_extend(this.options, options);
|
114
|
+
|
115
|
+
// normalize some options
|
116
|
+
this.options.mandatory = this.options.mandatory && ( 'standalone' in window.navigator || this.options.debug );
|
117
|
+
this.options.modal = this.options.modal || this.options.mandatory;
|
118
|
+
if ( this.options.mandatory ) {
|
119
|
+
this.options.startDelay = -0.5; // make the popup hasty
|
120
|
+
}
|
121
|
+
this.options.detectHomescreen = this.options.detectHomescreen === true ? 'hash' : this.options.detectHomescreen;
|
122
|
+
|
123
|
+
// setup the debug environment
|
124
|
+
if ( this.options.debug ) {
|
125
|
+
ath.isCompatible = true;
|
126
|
+
ath.OS = typeof this.options.debug == 'string' ? this.options.debug : ath.OS == 'unsupported' ? 'android' : ath.OS;
|
127
|
+
ath.OSVersion = ath.OS == 'ios' ? '7' : '4';
|
128
|
+
}
|
129
|
+
|
130
|
+
// the element the message will be appended to
|
131
|
+
this.container = document.documentElement;
|
132
|
+
|
133
|
+
// load session
|
134
|
+
this.session = JSON.parse(localStorage.getItem(this.options.appID));
|
135
|
+
|
136
|
+
// user most likely came from a direct link containing our token, we don't need it and we remove it
|
137
|
+
if ( ath.hasToken && ( !ath.isCompatible || !this.session ) ) {
|
138
|
+
ath.hasToken = false;
|
139
|
+
_removeToken();
|
140
|
+
}
|
141
|
+
|
142
|
+
// the device is not supported
|
143
|
+
if ( !ath.isCompatible ) {
|
144
|
+
return;
|
145
|
+
}
|
146
|
+
|
147
|
+
this.session = this.session || _defaultSession;
|
148
|
+
|
149
|
+
// check if we can use the local storage
|
150
|
+
try {
|
151
|
+
localStorage.setItem(this.options.appID, JSON.stringify(this.session));
|
152
|
+
ath.hasLocalStorage = true;
|
153
|
+
} catch (e) {
|
154
|
+
// we are most likely in private mode
|
155
|
+
ath.hasLocalStorage = false;
|
156
|
+
|
157
|
+
if ( this.options.onPrivate ) {
|
158
|
+
this.options.onPrivate.call(this);
|
159
|
+
}
|
160
|
+
}
|
161
|
+
|
162
|
+
// check if this is a valid location
|
163
|
+
var isValidLocation = !this.options.validLocation.length;
|
164
|
+
for ( var i = this.options.validLocation.length; i--; ) {
|
165
|
+
if ( this.options.validLocation[i].test(document.location.href) ) {
|
166
|
+
isValidLocation = true;
|
167
|
+
break;
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
171
|
+
// check compatibility with old versions of add to homescreen. Opt-out if an old session is found
|
172
|
+
if ( localStorage.getItem('addToHome') ) {
|
173
|
+
this.optOut();
|
174
|
+
}
|
175
|
+
|
176
|
+
// critical errors:
|
177
|
+
// user opted out, already added to the homescreen, not a valid location
|
178
|
+
if ( this.session.optedout || this.session.added || !isValidLocation ) {
|
179
|
+
return;
|
180
|
+
}
|
181
|
+
|
182
|
+
// check if the app is in stand alone mode
|
183
|
+
if ( ath.isStandalone ) {
|
184
|
+
// execute the onAdd event if we haven't already
|
185
|
+
if ( !this.session.added ) {
|
186
|
+
this.session.added = true;
|
187
|
+
this.updateSession();
|
188
|
+
|
189
|
+
if ( this.options.onAdd && ath.hasLocalStorage ) { // double check on localstorage to avoid multiple calls to the custom event
|
190
|
+
this.options.onAdd.call(this);
|
191
|
+
}
|
192
|
+
}
|
193
|
+
|
194
|
+
return;
|
195
|
+
}
|
196
|
+
|
197
|
+
// (try to) check if the page has been added to the homescreen
|
198
|
+
if ( this.options.detectHomescreen ) {
|
199
|
+
// the URL has the token, we are likely coming from the homescreen
|
200
|
+
if ( ath.hasToken ) {
|
201
|
+
_removeToken(); // we don't actually need the token anymore, we remove it to prevent redistribution
|
202
|
+
|
203
|
+
// this is called the first time the user opens the app from the homescreen
|
204
|
+
if ( !this.session.added ) {
|
205
|
+
this.session.added = true;
|
206
|
+
this.updateSession();
|
207
|
+
|
208
|
+
if ( this.options.onAdd && ath.hasLocalStorage ) { // double check on localstorage to avoid multiple calls to the custom event
|
209
|
+
this.options.onAdd.call(this);
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
return;
|
214
|
+
}
|
215
|
+
|
216
|
+
// URL doesn't have the token, so add it
|
217
|
+
if ( this.options.detectHomescreen == 'hash' ) {
|
218
|
+
history.replaceState('', window.document.title, document.location.href + '#ath');
|
219
|
+
} else if ( this.options.detectHomescreen == 'smartURL' ) {
|
220
|
+
history.replaceState('', window.document.title, document.location.href.replace(/(\/)?$/, '/ath$1'));
|
221
|
+
} else {
|
222
|
+
history.replaceState('', window.document.title, document.location.href + (document.location.search ? '&' : '?' ) + 'ath=');
|
223
|
+
}
|
224
|
+
}
|
225
|
+
|
226
|
+
// check if this is a returning visitor
|
227
|
+
if ( !this.session.returningVisitor ) {
|
228
|
+
this.session.returningVisitor = true;
|
229
|
+
this.updateSession();
|
230
|
+
|
231
|
+
// we do not show the message if this is your first visit
|
232
|
+
if ( this.options.skipFirstVisit ) {
|
233
|
+
return;
|
234
|
+
}
|
235
|
+
}
|
236
|
+
|
237
|
+
// we do no show the message in private mode
|
238
|
+
if ( !ath.hasLocalStorage ) {
|
239
|
+
return;
|
240
|
+
}
|
241
|
+
|
242
|
+
// all checks passed, ready to display
|
243
|
+
this.ready = true;
|
244
|
+
|
245
|
+
if ( this.options.onInit ) {
|
246
|
+
this.options.onInit.call(this);
|
247
|
+
}
|
248
|
+
|
249
|
+
if ( this.options.autostart ) {
|
250
|
+
this.show();
|
251
|
+
}
|
252
|
+
};
|
253
|
+
|
254
|
+
ath.Class.prototype = {
|
255
|
+
// event type to method conversion
|
256
|
+
events: {
|
257
|
+
load: '_delayedShow',
|
258
|
+
error: '_delayedShow',
|
259
|
+
orientationchange: 'resize',
|
260
|
+
resize: 'resize',
|
261
|
+
scroll: 'resize',
|
262
|
+
click: 'remove',
|
263
|
+
touchmove: '_preventDefault',
|
264
|
+
transitionend: '_removeElements',
|
265
|
+
webkitTransitionEnd: '_removeElements',
|
266
|
+
MSTransitionEnd: '_removeElements'
|
267
|
+
},
|
268
|
+
|
269
|
+
handleEvent: function (e) {
|
270
|
+
var type = this.events[e.type];
|
271
|
+
if ( type ) {
|
272
|
+
this[type](e);
|
273
|
+
}
|
274
|
+
},
|
275
|
+
|
276
|
+
show: function (force) {
|
277
|
+
// in autostart mode wait for the document to be ready
|
278
|
+
if ( this.options.autostart && !_DOMReady ) {
|
279
|
+
setTimeout(this.show.bind(this), 50);
|
280
|
+
return;
|
281
|
+
}
|
282
|
+
|
283
|
+
// message already on screen
|
284
|
+
if ( this.shown ) {
|
285
|
+
return;
|
286
|
+
}
|
287
|
+
|
288
|
+
var now = Date.now();
|
289
|
+
var lastDisplayTime = this.session.lastDisplayTime;
|
290
|
+
|
291
|
+
if ( force !== true ) {
|
292
|
+
// this is needed if autostart is disabled and you programmatically call the show() method
|
293
|
+
if ( !this.ready ) {
|
294
|
+
return;
|
295
|
+
}
|
296
|
+
|
297
|
+
// we obey the display pace (prevent the message to popup too often)
|
298
|
+
if ( now - lastDisplayTime < this.options.displayPace * 60000 ) {
|
299
|
+
return;
|
300
|
+
}
|
301
|
+
|
302
|
+
// obey the maximum number of display count
|
303
|
+
if ( this.options.maxDisplayCount && this.session.displayCount >= this.options.maxDisplayCount ) {
|
304
|
+
return;
|
305
|
+
}
|
306
|
+
}
|
307
|
+
|
308
|
+
this.shown = true;
|
309
|
+
|
310
|
+
// increment the display count
|
311
|
+
this.session.lastDisplayTime = now;
|
312
|
+
this.session.displayCount++;
|
313
|
+
this.updateSession();
|
314
|
+
|
315
|
+
// try to get the highest resolution application icon
|
316
|
+
if ( !this.applicationIcon ) {
|
317
|
+
if ( ath.OS == 'ios' ) {
|
318
|
+
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]');
|
319
|
+
} else {
|
320
|
+
this.applicationIcon = document.querySelector('head link[rel^="shortcut icon"][sizes="196x196"],head link[rel^=apple-touch-icon]');
|
321
|
+
}
|
322
|
+
}
|
323
|
+
|
324
|
+
var message = '';
|
325
|
+
|
326
|
+
if ( this.options.message in ath.intl ) { // you can force the locale
|
327
|
+
message = ath.intl[this.options.message].message.replace('%action', ath.intl[this.options.message].action[ath.OS]);
|
328
|
+
} else if ( this.options.message !== '' ) { // or use a custom message
|
329
|
+
message = this.options.message;
|
330
|
+
} else { // otherwise we use our message
|
331
|
+
message = ath.intl[ath.language].message.replace('%action', ath.intl[ath.language].action[ath.OS]);
|
332
|
+
}
|
333
|
+
|
334
|
+
// add the action icon
|
335
|
+
message = '<p>' + message.replace('%icon', '<span class="ath-action-icon">icon</span>') + '</p>';
|
336
|
+
|
337
|
+
// create the message container
|
338
|
+
this.viewport = document.createElement('div');
|
339
|
+
this.viewport.className = 'ath-viewport';
|
340
|
+
if ( this.options.modal ) {
|
341
|
+
this.viewport.className += ' ath-modal';
|
342
|
+
}
|
343
|
+
if ( this.options.mandatory ) {
|
344
|
+
this.viewport.className += ' ath-mandatory';
|
345
|
+
}
|
346
|
+
this.viewport.style.position = 'absolute';
|
347
|
+
|
348
|
+
// create the actual message element
|
349
|
+
this.element = document.createElement('div');
|
350
|
+
this.element.className = 'ath-container ath-' + ath.OS + ' ath-' + ath.OS + (ath.OSVersion + '').substr(0,1) + ' ath-' + (ath.isTablet ? 'tablet' : 'phone');
|
351
|
+
this.element.style.cssText = '-webkit-transition-property:-webkit-transform,opacity;-webkit-transition-duration:0;-webkit-transform:translate3d(0,0,0);transition-property:transform,opacity;transition-duration:0;transform:translate3d(0,0,0);-webkit-transition-timing-function:ease-out';
|
352
|
+
this.element.style.webkitTransform = 'translate3d(0,-' + window.innerHeight + 'px,0)';
|
353
|
+
this.element.style.webkitTransitionDuration = '0s';
|
354
|
+
|
355
|
+
// add the application icon
|
356
|
+
if ( this.options.icon && this.applicationIcon ) {
|
357
|
+
this.element.className += ' ath-icon';
|
358
|
+
this.img = document.createElement('img');
|
359
|
+
this.img.className = 'ath-application-icon';
|
360
|
+
this.img.addEventListener('load', this, false);
|
361
|
+
this.img.addEventListener('error', this, false);
|
362
|
+
|
363
|
+
this.img.src = this.applicationIcon.href;
|
364
|
+
this.element.appendChild(this.img);
|
365
|
+
}
|
366
|
+
|
367
|
+
this.element.innerHTML += message;
|
368
|
+
|
369
|
+
// we are not ready to show, place the message out of sight
|
370
|
+
this.viewport.style.left = '-99999em';
|
371
|
+
|
372
|
+
// attach all elements to the DOM
|
373
|
+
this.viewport.appendChild(this.element);
|
374
|
+
this.container.appendChild(this.viewport);
|
375
|
+
|
376
|
+
// if we don't have to wait for an image to load, show the message right away
|
377
|
+
if ( !this.img ) {
|
378
|
+
this._delayedShow();
|
379
|
+
}
|
380
|
+
},
|
381
|
+
|
382
|
+
_delayedShow: function (e) {
|
383
|
+
setTimeout(this._show.bind(this), this.options.startDelay * 1000 + 500);
|
384
|
+
},
|
385
|
+
|
386
|
+
_show: function () {
|
387
|
+
var that = this;
|
388
|
+
|
389
|
+
// update the viewport size and orientation
|
390
|
+
this.updateViewport();
|
391
|
+
|
392
|
+
// reposition/resize the message on orientation change
|
393
|
+
window.addEventListener('resize', this, false);
|
394
|
+
window.addEventListener('scroll', this, false);
|
395
|
+
window.addEventListener('orientationchange', this, false);
|
396
|
+
|
397
|
+
if ( this.options.modal ) {
|
398
|
+
// lock any other interaction
|
399
|
+
document.addEventListener('touchmove', this, true);
|
400
|
+
}
|
401
|
+
|
402
|
+
// Enable closing after 1 second
|
403
|
+
if ( !this.options.mandatory ) {
|
404
|
+
setTimeout(function () {
|
405
|
+
that.element.addEventListener('click', that, true);
|
406
|
+
}, 1000);
|
407
|
+
}
|
408
|
+
|
409
|
+
// kick the animation
|
410
|
+
setTimeout(function () {
|
411
|
+
that.element.style.webkitTransform = 'translate3d(0,0,0)';
|
412
|
+
that.element.style.webkitTransitionDuration = '1.2s';
|
413
|
+
}, 0);
|
414
|
+
|
415
|
+
// set the destroy timer
|
416
|
+
if ( this.options.lifespan ) {
|
417
|
+
this.removeTimer = setTimeout(this.remove.bind(this), this.options.lifespan * 1000);
|
418
|
+
}
|
419
|
+
|
420
|
+
// fire the custom onShow event
|
421
|
+
if ( this.options.onShow ) {
|
422
|
+
this.options.onShow.call(this);
|
423
|
+
}
|
424
|
+
},
|
425
|
+
|
426
|
+
remove: function () {
|
427
|
+
clearTimeout(this.removeTimer);
|
428
|
+
|
429
|
+
// clear up the event listeners
|
430
|
+
if ( this.img ) {
|
431
|
+
this.img.removeEventListener('load', this, false);
|
432
|
+
this.img.removeEventListener('error', this, false);
|
433
|
+
}
|
434
|
+
|
435
|
+
window.removeEventListener('resize', this, false);
|
436
|
+
window.removeEventListener('scroll', this, false);
|
437
|
+
window.removeEventListener('orientationchange', this, false);
|
438
|
+
document.removeEventListener('touchmove', this, true);
|
439
|
+
this.element.removeEventListener('click', this, true);
|
440
|
+
|
441
|
+
// remove the message element on transition end
|
442
|
+
this.element.addEventListener('transitionend', this, false);
|
443
|
+
this.element.addEventListener('webkitTransitionEnd', this, false);
|
444
|
+
this.element.addEventListener('MSTransitionEnd', this, false);
|
445
|
+
|
446
|
+
// start the fade out animation
|
447
|
+
this.element.style.webkitTransitionDuration = '0.3s';
|
448
|
+
this.element.style.opacity = '0';
|
449
|
+
},
|
450
|
+
|
451
|
+
_removeElements: function () {
|
452
|
+
this.element.removeEventListener('transitionend', this, false);
|
453
|
+
this.element.removeEventListener('webkitTransitionEnd', this, false);
|
454
|
+
this.element.removeEventListener('MSTransitionEnd', this, false);
|
455
|
+
|
456
|
+
// remove the message from the DOM
|
457
|
+
this.container.removeChild(this.viewport);
|
458
|
+
|
459
|
+
this.shown = false;
|
460
|
+
|
461
|
+
// fire the custom onRemove event
|
462
|
+
if ( this.options.onRemove ) {
|
463
|
+
this.options.onRemove.call(this);
|
464
|
+
}
|
465
|
+
},
|
466
|
+
|
467
|
+
updateViewport: function () {
|
468
|
+
if ( !this.shown ) {
|
469
|
+
return;
|
470
|
+
}
|
471
|
+
|
472
|
+
this.viewport.style.width = window.innerWidth + 'px';
|
473
|
+
this.viewport.style.height = window.innerHeight + 'px';
|
474
|
+
this.viewport.style.left = window.scrollX + 'px';
|
475
|
+
this.viewport.style.top = window.scrollY + 'px';
|
476
|
+
|
477
|
+
var clientWidth = document.documentElement.clientWidth;
|
478
|
+
|
479
|
+
this.orientation = clientWidth > document.documentElement.clientHeight ? 'landscape' : 'portrait';
|
480
|
+
|
481
|
+
var screenWidth = ath.OS == 'ios' ? this.orientation == 'portrait' ? screen.width : screen.height : screen.width;
|
482
|
+
this.scale = screen.width > clientWidth ? 1 : screenWidth / window.innerWidth;
|
483
|
+
|
484
|
+
this.element.style.fontSize = this.options.fontSize / this.scale + 'px';
|
485
|
+
},
|
486
|
+
|
487
|
+
resize: function () {
|
488
|
+
clearTimeout(this.resizeTimer);
|
489
|
+
this.resizeTimer = setTimeout(this.updateViewport.bind(this), 100);
|
490
|
+
},
|
491
|
+
|
492
|
+
updateSession: function () {
|
493
|
+
if ( ath.hasLocalStorage === false ) {
|
494
|
+
return;
|
495
|
+
}
|
496
|
+
|
497
|
+
localStorage.setItem(this.options.appID, JSON.stringify(this.session));
|
498
|
+
},
|
499
|
+
|
500
|
+
clearSession: function () {
|
501
|
+
this.session = _defaultSession;
|
502
|
+
this.updateSession();
|
503
|
+
},
|
504
|
+
|
505
|
+
optOut: function () {
|
506
|
+
this.session.optedout = true;
|
507
|
+
this.updateSession();
|
508
|
+
},
|
509
|
+
|
510
|
+
optIn: function () {
|
511
|
+
this.session.optedout = false;
|
512
|
+
this.updateSession();
|
513
|
+
},
|
514
|
+
|
515
|
+
clearDisplayCount: function () {
|
516
|
+
this.session.displayCount = 0;
|
517
|
+
this.updateSession();
|
518
|
+
},
|
519
|
+
|
520
|
+
_preventDefault: function (e) {
|
521
|
+
e.preventDefault();
|
522
|
+
e.stopPropagation();
|
523
|
+
}
|
524
|
+
};
|
525
|
+
|
526
|
+
// utility
|
527
|
+
function _extend (target, obj) {
|
528
|
+
for ( var i in obj ) {
|
529
|
+
target[i] = obj[i];
|
530
|
+
}
|
531
|
+
|
532
|
+
return target;
|
533
|
+
}
|
534
|
+
|
535
|
+
function _removeToken () {
|
536
|
+
if ( document.location.hash == '#ath' ) {
|
537
|
+
history.replaceState('', window.document.title, document.location.href.split('#')[0]);
|
538
|
+
}
|
539
|
+
|
540
|
+
if ( _reSmartURL.test(document.location.href) ) {
|
541
|
+
history.replaceState('', window.document.title, document.location.href.replace(_reSmartURL, '$1'));
|
542
|
+
}
|
543
|
+
|
544
|
+
if ( _reQueryString.test(document.location.search) ) {
|
545
|
+
history.replaceState('', window.document.title, document.location.href.replace(_reQueryString, '$2'));
|
546
|
+
}
|
547
|
+
}
|
548
|
+
|
549
|
+
// expose to the world
|
550
|
+
window.addToHomescreen = ath;
|
551
|
+
|
552
|
+
})(window, document);
|