1$(document).ready(function(){ 2 adjustContentOffset(); 3 LLAppBanner87.init(); 4}); 5 6function adjustContentOffset() { 7 var header = document.getElementById('siteTopContainer'); 8 if (!header) return; // theme has no siteTopContainer, abort 9 10 var spacer = document.getElementById('llHeaderSpacer87'); 11 if (!spacer) { 12 spacer = document.createElement('div'); 13 spacer.id = 'llHeaderSpacer87'; 14 header.parentNode.insertBefore(spacer, header.nextSibling); 15 } 16 var banner = document.getElementById('llMobileAppBanner87'); 17 var bannerHeight = (banner && banner.offsetParent !== null) ? banner.offsetHeight : 0; 18 spacer.style.height = bannerHeight + 'px'; 19} 20 21window.addEventListener('resize', adjustContentOffset); 22 23var LLAppBanner87 = (function() { 24 return { 25 STORAGE_KEY: 'llAppBanner87', 26 BACKOFF_DAYS: [3, 7, 60], 27 28 init: function() { 29 var ua = navigator.userAgent; 30 var isIOS = /iPhone|iPad|iPod/i.test(ua); 31 var isAndroid = /Android/i.test(ua); 32 33 if (!isIOS && !isAndroid) { 34 $("#llMobileAppBanner87").hide(); 35 return; 36 } 37 38 var state = this.loadState(); 39 if (!this.shouldShow(state)) { 40 $("#llMobileAppBanner87").hide(); 41 return; 42 } 43 44 if (isIOS) $("#iOSCta").addClass("llShowCta87"); 45 if (isAndroid) $("#AndroidCta").addClass("llShowCta87"); 46 if ((isIOS) || (isAndroid)) { 47 $("#llMobileAppBanner87").css('display', '').removeClass('hidden'); 48 adjustContentOffset(); 49 } 50 this.bindEvents(state); 51 }, 52 53 bindEvents: function (state) { 54 var self = this; 55 56 $('.llAppBannerDismiss87').on('click', function() { 57 var newCount = (state.dismissCount || 0) + 1; 58 self.saveState({ 59 dismissCount: newCount, 60 lastDismissedAt: new Date().toISOString(), 61 neverShow: newCount >= 4 // once we hit this many dismisses, give up 62 }); 63 $("#llMobileAppBanner87").hide(); 64 adjustContentOffset(); 65 }); 66 67 $('.llAppBannerCta87').on('click', function() { 68 self.saveState({ 69 dismissCount: state.dismissCount || 0, 70 lastDismissedAt: null, 71 neverShow: true 72 }); 73 }); 74 }, 75 76 loadState: function() { 77 try { return JSON.parse(localStorage.getItem(this.STORAGE_KEY)) || {}; } 78 catch (e) { return {}; } 79 }, 80 81 saveState: function(s) { 82 try { localStorage.setItem(this.STORAGE_KEY, JSON.stringify(s)); } 83 catch (e) {} 84 }, 85 86 shouldShow: function(s) { 87 if (s.neverShow) return false; 88 if (!s.dismissCount) return true; 89 var waitDays = this.BACKOFF_DAYS[s.dismissCount - 1]; 90 if (waitDays === undefined) return false; 91 if (!s.lastDismissedAt) return true; 92 return (Date.now() - new Date(s.lastDismissedAt).getTime()) / 86400000 >= waitDays; 93 } 94 }; 95})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.