author | Giulio Cesare Solaroli <giulio.cesare@clipperz.com> | 2013-08-30 15:56:53 (UTC) |
---|---|---|
committer | Giulio Cesare Solaroli <giulio.cesare@clipperz.com> | 2013-08-30 21:23:42 (UTC) |
commit | 20bea94ab6b91c85b171dcf86baba0a64169d508 (patch) (unidiff) | |
tree | 6e38e91498dcdb861620eba1e237d1026fe79cc5 /frontend/delta/js/Cubiq/add2home.js | |
parent | bde3c7b98523112ade9c5bbf7390c4ecb494cd2e (diff) | |
download | clipperz-20bea94ab6b91c85b171dcf86baba0a64169d508.zip clipperz-20bea94ab6b91c85b171dcf86baba0a64169d508.tar.gz clipperz-20bea94ab6b91c85b171dcf86baba0a64169d508.tar.bz2 |
First release of /delta version
Diffstat (limited to 'frontend/delta/js/Cubiq/add2home.js') (more/less context) (ignore whitespace changes)
-rw-r--r-- | frontend/delta/js/Cubiq/add2home.js | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/frontend/delta/js/Cubiq/add2home.js b/frontend/delta/js/Cubiq/add2home.js new file mode 100644 index 0000000..7ecb3c0 --- a/dev/null +++ b/frontend/delta/js/Cubiq/add2home.js | |||
@@ -0,0 +1,365 @@ | |||
1 | /* | ||
2 | |||
3 | Copyright 2008-2013 Clipperz Srl | ||
4 | |||
5 | This file is part of Clipperz, the online password manager. | ||
6 | For further information about its features and functionalities please | ||
7 | refer to http://www.clipperz.com. | ||
8 | |||
9 | * Clipperz is free software: you can redistribute it and/or modify it | ||
10 | under the terms of the GNU Affero General Public License as published | ||
11 | by the Free Software Foundation, either version 3 of the License, or | ||
12 | (at your option) any later version. | ||
13 | |||
14 | * Clipperz is distributed in the hope that it will be useful, but | ||
15 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
17 | See the GNU Affero General Public License for more details. | ||
18 | |||
19 | * You should have received a copy of the GNU Affero General Public | ||
20 | License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||
21 | |||
22 | */ | ||
23 | |||
24 | /*! | ||
25 | * Add to Homescreen v2.0.8 ~ Copyright (c) 2013 Matteo Spinelli, http://cubiq.org | ||
26 | * Released under MIT license, http://cubiq.org/license | ||
27 | */ | ||
28 | var addToHome = (function (w) { | ||
29 | var nav = w.navigator, | ||
30 | isIDevice = 'platform' in nav && (/iphone|ipod|ipad/gi).test(nav.platform), | ||
31 | isIPad, | ||
32 | isRetina, | ||
33 | isSafari, | ||
34 | isStandalone, | ||
35 | OSVersion, | ||
36 | startX = 0, | ||
37 | startY = 0, | ||
38 | lastVisit = 0, | ||
39 | isExpired, | ||
40 | isSessionActive, | ||
41 | isReturningVisitor, | ||
42 | balloon, | ||
43 | overrideChecks, | ||
44 | |||
45 | positionInterval, | ||
46 | closeTimeout, | ||
47 | |||
48 | options = { | ||
49 | autostart: true, // Automatically open the balloon | ||
50 | returningVisitor: false,// Show the balloon to returning visitors only (setting this to true is highly recommended) | ||
51 | animationIn: 'drop', // drop || bubble || fade | ||
52 | animationOut: 'fade', // drop || bubble || fade | ||
53 | startDelay: 2000, // 2 seconds from page load before the balloon appears | ||
54 | lifespan: 15000, // 15 seconds before it is automatically destroyed | ||
55 | bottomOffset: 14, // Distance of the balloon from bottom | ||
56 | expire: 0, // Minutes to wait before showing the popup again (0 = always displayed) | ||
57 | message: '', // Customize your message or force a language ('' = automatic) | ||
58 | touchIcon: false, // Display the touch icon | ||
59 | arrow: true, // Display the balloon arrow | ||
60 | hookOnLoad: true, // Should we hook to onload event? (really advanced usage) | ||
61 | closeButton: true, // Let the user close the balloon | ||
62 | iterations: 100 // Internal/debug use | ||
63 | }, | ||
64 | |||
65 | intl = { | ||
66 | ar: '<span dir="rtl">قم بتثبيت هذا التطبيق على <span dir="ltr">%device:</span>انقر<span dir="ltr">%icon</span> ،<strong>ثم اضفه الى الشاشة الرئيسية.</strong></span>', | ||
67 | ca_es: 'Per instal·lar aquesta aplicació al vostre %device premeu %icon i llavors <strong>Afegir a pantalla d\'inici</strong>.', | ||
68 | cs_cz: 'Pro instalaci aplikace na Váš %device, stiskněte %icon a v nabídce <strong>Přidat na plochu</strong>.', | ||
69 | da_dk: 'Tilføj denne side til din %device: tryk på %icon og derefter <strong>Føj til hjemmeskærm</strong>.', | ||
70 | de_de: 'Installieren Sie diese App auf Ihrem %device: %icon antippen und dann <strong>Zum Home-Bildschirm</strong>.', | ||
71 | el_gr: 'Εγκαταστήσετε αυτήν την Εφαρμογή στήν συσκευή σας %device: %icon μετά πατάτε <strong>Προσθήκη σε Αφετηρία</strong>.', | ||
72 | en_us: 'Install this web app on your %device: tap %icon and then <strong>Add to Home Screen</strong>.', | ||
73 | es_es: 'Para instalar esta app en su %device, pulse %icon y seleccione <strong>Añadir a pantalla de inicio</strong>.', | ||
74 | fi_fi: 'Asenna tämä web-sovellus laitteeseesi %device: paina %icon ja sen jälkeen valitse <strong>Lisää Koti-valikkoon</strong>.', | ||
75 | fr_fr: 'Ajoutez cette application sur votre %device en cliquant sur %icon, puis <strong>Ajouter à l\'écran d\'accueil</strong>.', | ||
76 | he_il: '<span dir="rtl">התקן אפליקציה זו על ה-%device שלך: הקש %icon ואז <strong>הוסף למסך הבית</strong>.</span>', | ||
77 | hr_hr: 'Instaliraj ovu aplikaciju na svoj %device: klikni na %icon i odaberi <strong>Dodaj u početni zaslon</strong>.', | ||
78 | hu_hu: 'Telepítse ezt a web-alkalmazást az Ön %device-jára: nyomjon a %icon-ra majd a <strong>Főképernyőhöz adás</strong> gombra.', | ||
79 | it_it: 'Installa questa applicazione sul tuo %device: premi su %icon e poi <strong>Aggiungi a Home</strong>.', | ||
80 | ja_jp: 'このウェブアプリをあなたの%deviceにインストールするには%iconをタップして<strong>ホーム画面に追加</strong>を選んでください。', | ||
81 | ko_kr: '%device에 웹앱을 설치하려면 %icon을 터치 후 "홈화면에 추가"를 선택하세요', | ||
82 | nb_no: 'Installer denne appen på din %device: trykk på %icon og deretter <strong>Legg til på Hjem-skjerm</strong>', | ||
83 | nl_nl: 'Installeer deze webapp op uw %device: tik %icon en dan <strong>Voeg toe aan beginscherm</strong>.', | ||
84 | pl_pl: 'Aby zainstalować tę aplikacje na %device: naciśnij %icon a następnie <strong>Dodaj jako ikonę</strong>.', | ||
85 | pt_br: 'Instale este aplicativo em seu %device: aperte %icon e selecione <strong>Adicionar à Tela Inicio</strong>.', | ||
86 | pt_pt: 'Para instalar esta aplicação no seu %device, prima o %icon e depois em <strong>Adicionar ao ecrã principal</strong>.', | ||
87 | ru_ru: 'Установите это веб-приложение на ваш %device: нажмите %icon, затем <strong>Добавить в «Домой»</strong>.', | ||
88 | sv_se: 'Lägg till denna webbapplikation på din %device: tryck på %icon och därefter <strong>Lägg till på hemskärmen</strong>.', | ||
89 | th_th: 'ติดตั้งเว็บแอพฯ นี้บน %device ของคุณ: แตะ %icon และ <strong>เพิ่มที่หน้าจอโฮม</strong>', | ||
90 | tr_tr: 'Bu uygulamayı %device\'a eklemek için %icon simgesine sonrasında <strong>Ana Ekrana Ekle</strong> düğmesine basın.', | ||
91 | uk_ua: 'Встановіть цей веб сайт на Ваш %device: натисніть %icon, а потім <strong>На початковий екран</strong>.', | ||
92 | zh_cn: '您可以将此应用程式安装到您的 %device 上。请按 %icon 然后点选<strong>添加至主屏幕</strong>。', | ||
93 | zh_tw: '您可以將此應用程式安裝到您的 %device 上。請按 %icon 然後點選<strong>加入主畫面螢幕</strong>。' | ||
94 | }; | ||
95 | |||
96 | function init () { | ||
97 | // Preliminary check, all further checks are performed on iDevices only | ||
98 | if ( !isIDevice ) return; | ||
99 | |||
100 | var now = Date.now(), | ||
101 | i; | ||
102 | |||
103 | // Merge local with global options | ||
104 | if ( w.addToHomeConfig ) { | ||
105 | for ( i in w.addToHomeConfig ) { | ||
106 | options[i] = w.addToHomeConfig[i]; | ||
107 | } | ||
108 | } | ||
109 | if ( !options.autostart ) options.hookOnLoad = false; | ||
110 | |||
111 | isIPad = (/ipad/gi).test(nav.platform); | ||
112 | isRetina = w.devicePixelRatio && w.devicePixelRatio > 1; | ||
113 | isSafari = (/Safari/i).test(nav.appVersion) && !(/CriOS/i).test(nav.appVersion); | ||
114 | isStandalone = nav.standalone; | ||
115 | OSVersion = nav.appVersion.match(/OS (\d+_\d+)/i); | ||
116 | OSVersion = OSVersion && OSVersion[1] ? +OSVersion[1].replace('_', '.') : 0; | ||
117 | |||
118 | lastVisit = +w.localStorage.getItem('addToHome'); | ||
119 | |||
120 | isSessionActive = w.sessionStorage.getItem('addToHomeSession'); | ||
121 | isReturningVisitor = options.returningVisitor ? lastVisit && lastVisit + 28*24*60*60*1000 > now : true; | ||
122 | |||
123 | if ( !lastVisit ) lastVisit = now; | ||
124 | |||
125 | // If it is expired we need to reissue a new balloon | ||
126 | isExpired = isReturningVisitor && lastVisit <= now; | ||
127 | |||
128 | if ( options.hookOnLoad ) w.addEventListener('load', loaded, false); | ||
129 | else if ( !options.hookOnLoad && options.autostart ) loaded(); | ||
130 | } | ||
131 | |||
132 | function loaded () { | ||
133 | w.removeEventListener('load', loaded, false); | ||
134 | |||
135 | if ( !isReturningVisitor ) w.localStorage.setItem('addToHome', Date.now()); | ||
136 | else if ( options.expire && isExpired ) w.localStorage.setItem('addToHome', Date.now() + options.expire * 60000); | ||
137 | |||
138 | if ( !overrideChecks && ( !isSafari || !isExpired || isSessionActive || isStandalone || !isReturningVisitor ) ) return; | ||
139 | |||
140 | var touchIcon = '', | ||
141 | platform = nav.platform.split(' ')[0], | ||
142 | language = nav.language.replace('-', '_'); | ||
143 | |||
144 | balloon = document.createElement('div'); | ||
145 | balloon.id = 'addToHomeScreen'; | ||
146 | balloon.style.cssText += 'left:-9999px;-webkit-transition-property:-webkit-transform,opacity;-webkit-transition-duration:0;-webkit-transform:translate3d(0,0,0);position:' + (OSVersion < 5 ? 'absolute' : 'fixed'); | ||
147 | |||
148 | // Localize message | ||
149 | if ( options.message in intl ) { // You may force a language despite the user's locale | ||
150 | language = options.message; | ||
151 | options.message = ''; | ||
152 | } | ||
153 | if ( options.message === '' ) { // We look for a suitable language (defaulted to en_us) | ||
154 | options.message = language in intl ? intl[language] : intl['en_us']; | ||
155 | } | ||
156 | |||
157 | if ( options.touchIcon ) { | ||
158 | touchIcon = isRetina ? | ||
159 | document.querySelector('head link[rel^=apple-touch-icon][sizes="114x114"],head link[rel^=apple-touch-icon][sizes="144x144"],head link[rel^=apple-touch-icon]') : | ||
160 | document.querySelector('head link[rel^=apple-touch-icon][sizes="57x57"],head link[rel^=apple-touch-icon]'); | ||
161 | |||
162 | if ( touchIcon ) { | ||
163 | touchIcon = '<span style="background-image:url(' + touchIcon.href + ')" class="addToHomeTouchIcon"></span>'; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | balloon.className = (isIPad ? 'addToHomeIpad' : 'addToHomeIphone') + (touchIcon ? ' addToHomeWide' : ''); | ||
168 | balloon.innerHTML = touchIcon + | ||
169 | options.message.replace('%device', platform).replace('%icon', OSVersion >= 4.2 ? '<span class="addToHomeShare' + (OSVersion >= 7 ? ' addToHomeShareOS7' : '') + '"></span>' : '<span class="addToHomePlus">+</span>') + | ||
170 | (options.arrow ? '<span class="addToHomeArrow"></span>' : '') + | ||
171 | (options.closeButton ? '<span class="addToHomeClose">\u00D7</span>' : ''); | ||
172 | |||
173 | document.body.appendChild(balloon); | ||
174 | |||
175 | // Add the close action | ||
176 | if ( options.closeButton ) balloon.addEventListener('click', clicked, false); | ||
177 | |||
178 | if ( !isIPad && OSVersion >= 6 ) window.addEventListener('orientationchange', orientationCheck, false); | ||
179 | |||
180 | setTimeout(show, options.startDelay); | ||
181 | } | ||
182 | |||
183 | function show () { | ||
184 | var duration, | ||
185 | iPadXShift = 208; | ||
186 | |||
187 | // Set the initial position | ||
188 | if ( isIPad ) { | ||
189 | if ( OSVersion < 5 ) { | ||
190 | startY = w.scrollY; | ||
191 | startX = w.scrollX; | ||
192 | } else if ( OSVersion < 6 ) { | ||
193 | iPadXShift = 160; | ||
194 | } | ||
195 | |||
196 | balloon.style.top = startY + options.bottomOffset + 'px'; | ||
197 | balloon.style.left = startX + iPadXShift - Math.round(balloon.offsetWidth / 2) + 'px'; | ||
198 | |||
199 | switch ( options.animationIn ) { | ||
200 | case 'drop': | ||
201 | duration = '0.6s'; | ||
202 | balloon.style.webkitTransform = 'translate3d(0,' + -(w.scrollY + options.bottomOffset + balloon.offsetHeight) + 'px,0)'; | ||
203 | break; | ||
204 | case 'bubble': | ||
205 | duration = '0.6s'; | ||
206 | balloon.style.opacity = '0'; | ||
207 | balloon.style.webkitTransform = 'translate3d(0,' + (startY + 50) + 'px,0)'; | ||
208 | break; | ||
209 | default: | ||
210 | duration = '1s'; | ||
211 | balloon.style.opacity = '0'; | ||
212 | } | ||
213 | } else { | ||
214 | startY = w.innerHeight + w.scrollY; | ||
215 | |||
216 | if ( OSVersion < 5 ) { | ||
217 | startX = Math.round((w.innerWidth - balloon.offsetWidth) / 2) + w.scrollX; | ||
218 | balloon.style.left = startX + 'px'; | ||
219 | balloon.style.top = startY - balloon.offsetHeight - options.bottomOffset + 'px'; | ||
220 | } else { | ||
221 | balloon.style.left = '50%'; | ||
222 | balloon.style.marginLeft = -Math.round(balloon.offsetWidth / 2) - ( w.orientation%180 && OSVersion >= 6 ? 40 : 0 ) + 'px'; | ||
223 | balloon.style.bottom = options.bottomOffset + 'px'; | ||
224 | } | ||
225 | |||
226 | switch (options.animationIn) { | ||
227 | case 'drop': | ||
228 | duration = '1s'; | ||
229 | balloon.style.webkitTransform = 'translate3d(0,' + -(startY + options.bottomOffset) + 'px,0)'; | ||
230 | break; | ||
231 | case 'bubble': | ||
232 | duration = '0.6s'; | ||
233 | balloon.style.webkitTransform = 'translate3d(0,' + (balloon.offsetHeight + options.bottomOffset + 50) + 'px,0)'; | ||
234 | break; | ||
235 | default: | ||
236 | duration = '1s'; | ||
237 | balloon.style.opacity = '0'; | ||
238 | } | ||
239 | } | ||
240 | |||
241 | balloon.offsetHeight;// repaint trick | ||
242 | balloon.style.webkitTransitionDuration = duration; | ||
243 | balloon.style.opacity = '1'; | ||
244 | balloon.style.webkitTransform = 'translate3d(0,0,0)'; | ||
245 | balloon.addEventListener('webkitTransitionEnd', transitionEnd, false); | ||
246 | |||
247 | closeTimeout = setTimeout(close, options.lifespan); | ||
248 | } | ||
249 | |||
250 | function manualShow (override) { | ||
251 | if ( !isIDevice || balloon ) return; | ||
252 | |||
253 | overrideChecks = override; | ||
254 | loaded(); | ||
255 | } | ||
256 | |||
257 | function close () { | ||
258 | clearInterval( positionInterval ); | ||
259 | clearTimeout( closeTimeout ); | ||
260 | closeTimeout = null; | ||
261 | |||
262 | // check if the popup is displayed and prevent errors | ||
263 | if ( !balloon ) return; | ||
264 | |||
265 | var posY = 0, | ||
266 | posX = 0, | ||
267 | opacity = '1', | ||
268 | duration = '0'; | ||
269 | |||
270 | if ( options.closeButton ) balloon.removeEventListener('click', clicked, false); | ||
271 | if ( !isIPad && OSVersion >= 6 ) window.removeEventListener('orientationchange', orientationCheck, false); | ||
272 | |||
273 | if ( OSVersion < 5 ) { | ||
274 | posY = isIPad ? w.scrollY - startY : w.scrollY + w.innerHeight - startY; | ||
275 | posX = isIPad ? w.scrollX - startX : w.scrollX + Math.round((w.innerWidth - balloon.offsetWidth)/2) - startX; | ||
276 | } | ||
277 | |||
278 | balloon.style.webkitTransitionProperty = '-webkit-transform,opacity'; | ||
279 | |||
280 | switch ( options.animationOut ) { | ||
281 | case 'drop': | ||
282 | if ( isIPad ) { | ||
283 | duration = '0.4s'; | ||
284 | opacity = '0'; | ||
285 | posY += 50; | ||
286 | } else { | ||
287 | duration = '0.6s'; | ||
288 | posY += balloon.offsetHeight + options.bottomOffset + 50; | ||
289 | } | ||
290 | break; | ||
291 | case 'bubble': | ||
292 | if ( isIPad ) { | ||
293 | duration = '0.8s'; | ||
294 | posY -= balloon.offsetHeight + options.bottomOffset + 50; | ||
295 | } else { | ||
296 | duration = '0.4s'; | ||
297 | opacity = '0'; | ||
298 | posY -= 50; | ||
299 | } | ||
300 | break; | ||
301 | default: | ||
302 | duration = '0.8s'; | ||
303 | opacity = '0'; | ||
304 | } | ||
305 | |||
306 | balloon.addEventListener('webkitTransitionEnd', transitionEnd, false); | ||
307 | balloon.style.opacity = opacity; | ||
308 | balloon.style.webkitTransitionDuration = duration; | ||
309 | balloon.style.webkitTransform = 'translate3d(' + posX + 'px,' + posY + 'px,0)'; | ||
310 | } | ||
311 | |||
312 | |||
313 | function clicked () { | ||
314 | w.sessionStorage.setItem('addToHomeSession', '1'); | ||
315 | isSessionActive = true; | ||
316 | close(); | ||
317 | } | ||
318 | |||
319 | function transitionEnd () { | ||
320 | balloon.removeEventListener('webkitTransitionEnd', transitionEnd, false); | ||
321 | |||
322 | balloon.style.webkitTransitionProperty = '-webkit-transform'; | ||
323 | balloon.style.webkitTransitionDuration = '0.2s'; | ||
324 | |||
325 | // We reached the end! | ||
326 | if ( !closeTimeout ) { | ||
327 | balloon.parentNode.removeChild(balloon); | ||
328 | balloon = null; | ||
329 | return; | ||
330 | } | ||
331 | |||
332 | // On iOS 4 we start checking the element position | ||
333 | if ( OSVersion < 5 && closeTimeout ) positionInterval = setInterval(setPosition, options.iterations); | ||
334 | } | ||
335 | |||
336 | function setPosition () { | ||
337 | var matrix = new WebKitCSSMatrix(w.getComputedStyle(balloon, null).webkitTransform), | ||
338 | posY = isIPad ? w.scrollY - startY : w.scrollY + w.innerHeight - startY, | ||
339 | posX = isIPad ? w.scrollX - startX : w.scrollX + Math.round((w.innerWidth - balloon.offsetWidth) / 2) - startX; | ||
340 | |||
341 | // Screen didn't move | ||
342 | if ( posY == matrix.m42 && posX == matrix.m41 ) return; | ||
343 | |||
344 | balloon.style.webkitTransform = 'translate3d(' + posX + 'px,' + posY + 'px,0)'; | ||
345 | } | ||
346 | |||
347 | // Clear local and session storages (this is useful primarily in development) | ||
348 | function reset () { | ||
349 | w.localStorage.removeItem('addToHome'); | ||
350 | w.sessionStorage.removeItem('addToHomeSession'); | ||
351 | } | ||
352 | |||
353 | function orientationCheck () { | ||
354 | balloon.style.marginLeft = -Math.round(balloon.offsetWidth / 2) - ( w.orientation%180 && OSVersion >= 6 ? 40 : 0 ) + 'px'; | ||
355 | } | ||
356 | |||
357 | // Bootstrap! | ||
358 | init(); | ||
359 | |||
360 | return { | ||
361 | show: manualShow, | ||
362 | close: close, | ||
363 | reset: reset | ||
364 | }; | ||
365 | })(window); | ||