add-to-homescreen-rails 2.0.11 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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);
|