1 2// make sure all variables are defined 3if (typeof(functionCallAfterWindowLoad) == "undefined") var functionCallAfterWindowLoad = false; 4if (typeof(is_mobile_skin) == "undefined") var is_mobile_skin = false; 5if (typeof(app_ios_id) == "undefined") var app_ios_id = ''; 6if (typeof(app_android_id) == "undefined") var app_android_id = ''; 7if (typeof(app_kindle_url) == "undefined") var app_kindle_url = ''; 8if (typeof(app_board_url) == "undefined") var app_board_url = ''; 9if (typeof(app_forum_name) == "undefined" || !app_forum_name) var app_forum_name = "this forum"; 10if (typeof(app_banner_message) == "undefined" || !app_banner_message) var app_banner_message = "Follow {your_forum_name} <br /> with {app_name} for [os_platform]"; 11if (typeof(app_location_url) == "undefined" || !app_location_url) var app_location_url = "tapatalk://"; 12var app_location_url_byo = app_location_url.replace('tapatalk://', 'tapatalk-byo://'); 13 14// set default iOS app for native smart banner 15var app_ios_id_default = '307880732'; // Tapatalk Free, 585178888 for Tapatalk Pro 16var app_ios_hd_id_default = '307880732'; // Tapatalk Free, 481579541 for Tapatalk HD 17 18// Support native iOS Smartbanner 19var native_ios_banner = false; 20if (app_ios_id != '-1' && navigator.userAgent.match(/Safari/i) != null && 21 (navigator.userAgent.match(/CriOS/i) == null && window.Number(navigator.userAgent.
21substr(navigator.userAgent.indexOf('OS ') + 3, 3).replace('_', '.')) >= 6)) 22{ 23 banner_location_url = app_ios_id ? app_location_url_byo : app_location_url; 24 25 if (navigator.userAgent.match(/iPad/i) != null) 26 { 27 document.write('<meta name="apple-itunes-app" content="app-id='+(app_ios_id ? app_ios_id : app_ios_hd_id_default)+', app-argument='+banner_location_url+', affiliate-data=partnerId=30&siteID=w5J2vu1UnxA" />'); 28 native_ios_banner = true; 29 } 30 else if (navigator.userAgent.match(/iPod|iPhone/i) != null) 31 { 32 document.write('<meta name="apple-itunes-app" content="app-id='+(app_ios_id ? app_ios_id : app_ios_id_default)+', app-argument='+banner_location_url+', affiliate-data=partnerId=30&siteID=w5J2vu1UnxA" />'); 33 native_ios_banner = true; 34 } 35} 36 37// initialize app download url 38var app_install_url = 'https://tapatalk.com/m/?id=6'; 39if (app_ios_id) app_install_url = app_install_url+'&app_ios_id='+app_ios_id; 40if (app_android_id) app_install_url = app_install_url+'&app_android_id='+app_android_id; 41if (app_kindle_url) app_install_url = app_install_url+'&app_kindle_url='+app_kindle_url; 42if (app_board_url) app_install_url = app_install_url+'&referer='+app_board_url; 43 44 45// for those forum system which can not add js in html body 46if (functionCallAfterWindowLoad) addWindowOnload(tapatalkDetect) 47 48var bannerLoaded = false 49 50function tapatalkDetect() 51{ 52 var standalone = navigator.standalone // Check if it's already a standalone web app or running within a web ui view of an app (not mobile safari) 53 54 // work only when browser support cookie 55 if (!navigator.cookieEnabled 56 || bannerLoaded 57 || standalone 58 || document.cookie.indexOf("banner-closed=true") >= 0 59 || native_ios_banner) 60 return 61 62 bannerLoaded = true 63 64 app_banner_message = app_banner_message.replace(/\{your_forum_name\}/gi, app_forum_name); 65 app_banner_message = app_banner_message.replace(/\{app_name\}/gi, "Tapatalk"); 66 67 if (navigator.userAgent.match(/iPhone|iPod/i)) { 68 if (app_ios_id == '-1') return; 69 app_banner_message = app_banner_message.replace(/\[os_platform\]/gi, 'iPhone'); 70 banner_location_url = app_ios_id ? app_location_url_byo : app_location_url; 71 } 72 else if (navigator.userAgent.match(/iPad/i)) { 73 if (app_ios_id == '-1') return; 74 app_banner_message = app_banner_message.replace(/\[os_platform\]/gi, 'iPad'); 75 banner_location_url = app_ios_id ? app_location_url_byo : app_location_url; 76 } 77 else if (navigator.userAgent.match(/Silk|KFOT|KFTT|KFJWI|KFJWA/)) { 78 if (app_kindle_url == '-1') return; 79 app_banner_message = app_banner_message.replace(/\[os_platform\]/gi, 'Kindle'); 80 banner_location_url = app_kindle_url ? app_location_url_byo : app_location_url; 81 } 82 else if (navigator.userAgent.match(/Android/i)) { 83 if (app_android_id == '-1') return; 84 app_banner_message = app_banner_message.replace(/\[os_platform\]/gi, 'Android'); 85 banner_location_url = app_android_id ? app_location_url_byo : app_location_url; 86 } 87 else if (navigator.userAgent.match(/IEMobile|Windows Phone/i)) { 88 app_banner_message = app_banner_message.replace(/\[os_platform\]/gi, 'Windows Phone'); 89 banner_location_url = app_location_url; 90 } 91 else if (navigator.userAgent.match(/BlackBerry/i)) { 92 app_banner_message = app_banner_message.replace(/\[os_platform\]/gi, 'BlackBerry'); 93 banner_location_url = app_location_url; 94 } 95 else 96 return 97 98 99 htmlElement = document.getElementsByTagName("html")[0] 100 origHtmlMargin = parseFloat(htmlElement.style.marginTop) 101 if ( isNaN(origHtmlMargin)) origHtmlMargin = 0 102 103 var bannerScale = document.body.clientWidth / window.screen.width 104 105 if (bannerScale < 1 || (is_mobile_skin && navigator.userAgent.match(/mobile/i))) bannerScale = 1; 106 107 // mobile portrait mode may need bigger scale 108 if (window.innerWidth < window.innerHeight) 109 { 110 if (bannerScale < 2 && !is_mobile_skin && document.body.clientWidth > 600) { 111 bannerScale = 2 112 } else if (bannerScale > 2.8) { 113 bannerScale = 2.8 114 } 115 } 116 else 117 { 118 if (navigator.userAgent.match(/mobile/i) && bannerScale < 1.5 && !is_mobile_skin && document.body.clientWidth > 600) { 119 bannerScale = 1.5 120 } else if (bannerScale > 2) { 121 bannerScale = 2 122 } 123 } 124 125 126 bodyItem = document.body 127 appBanner = document.createElement("div") 128 appBanner.id = "mobile_banner" 129 appBanner.className = "mobile_banner banner_format_handset banner_device_android banner_theme_light mobile_banner_animate" 130 appBanner.innerHTML = 131 '<div class="mobile_banner_inner">'+ 132 '<span class="mobile_banner_icon"></span>'+ 133 '<div class="mobile_banner_body">'+ 134 '<h3 class="mobile_banner_heading">'+app_banner_message+'</h3>'+ 135 '</div>'+ 136 '<div class="mobile_banner_controls">'+ 137 '<a class="mobile_banner_button chrome white mobile_banner_open" href="'+banner_location_url+'" id="mobile_banner_open">
137'+'Open in app'+'</a>'+ 138 '<a class="mobile_banner_button chrome blue mobile_banner_install" href="'+app_install_url+'" id="mobile_banner_install">'+'Install'+'</a>'+ 139 '<a class="mobile_banner_close" href="#" onclick="closeBanner()" id="mobile_banner_close">x</a>'+ 140 '</div>'+ 141 '</div>' 142 bodyItem.insertBefore(appBanner, bodyItem.firstChild) 143 144 if (bannerScale > 1) { 145 appBanner.style.fontSize = (8*bannerScale)+"px" 146 } 147 148 bannerHeight = getWH(appBanner, 'height', true) 149 bannerTop = (origHtmlMargin+bannerHeight)+"px" 150 htmlElement.style.marginTop = bannerTop 151 152 if (getComputedStyle(bodyItem, null).position !== 'static') 153 appBanner.style.top = '-'+bannerTop 154 155 addWindowOnload(resetBannerTop) 156} 157 158function addWindowOnload(func) 159{ 160 if (typeof window.onload != 'function') { 161 window.onload = func; 162 } else { 163 var oldonload = window.onload; 164 window.onload = function() { 165 oldonload(); 166 func(); 167 } 168 } 169} 170 171function resetBannerTop() 172{ 173 if (getComputedStyle(bodyItem, null).position !== 'static' || document.getElementById('google_translate_element')) 174 appBanner.style.top = '-'+bannerTop 175} 176 177function closeBanner() 178{ 179 bodyItem.removeChild( appBanner ) 180 htmlElement.style.marginTop = origHtmlMargin+"px" 181 setBannerCookies('banner-closed', 'true', 90) 182} 183 184function setBannerCookies(name, value, exdays) 185{ 186 var exdate = new Date(); 187 exdate.setDate(exdate.getDate()+exdays); 188 value=escape(value)+((exdays==null)?'':'; expires='+exdate.toUTCString()); 189 document.cookie=name+'='+value+'; path=/;'; 190} 191 192 193/* to get element outer height */ 194 195var defView = document.defaultView; 196 197var getStyle = defView && defView.getComputedStyle ? 198 function( elem ) { 199 return defView.getComputedStyle( elem, null ); 200 } 201 : 202 function( elem ) { 203 return elem.currentStyle; 204 }; 205 206function hackPercentMargin( elem, computedStyle, marginValue ) { 207 if ( marginValue.indexOf('%') === -1 ) { 208 return marginValue; 209 } 210 211 var elemStyle = elem.style, 212 originalWidth = elemStyle.width, 213 ret; 214 215 // get measure by setting it on elem's width 216 elemStyle.width = marginValue; 217 ret = computedStyle.width; 218 elemStyle.width = originalWidth; 219 220 return ret; 221} 222 223function getWH( elem, measure, isOuter ) 224{ 225 // Start with offset property 226 var isWidth = measure !== 'height', 227 val = isWidth ? elem.offsetWidth : elem.offsetHeight, 228 dirA = isWidth ? 'Left' : 'Top', 229 dirB = isWidth ? 'Right' : 'Bottom', 230 computedStyle = getStyle( elem ), 231 paddingA = parseFloat( computedStyle[ 'padding' + dirA ] ) || 0, 232 paddingB = parseFloat( computedStyle[ 'padding' + dirB ] ) || 0, 233 borderA = parseFloat( computedStyle[ 'border' + dirA + 'Width' ] ) || 0, 234 borderB = parseFloat( computedStyle[ 'border' + dirB + 'Width' ] ) || 0, 235 computedMarginA = computedStyle[ 'margin' + dirA ], 236 computedMarginB = computedStyle[ 'margin' + dirB ], 237 marginA, marginB; 238 239 var tmpDiv = document.createElement('div'); 240 tmpDiv.style.marginTop = '1%'; 241 bodyItem.appendChild( tmpDiv ); 242 var supportsPercentMargin = getStyle( tmpDiv ).marginTop !== '1%'; 243 bodyItem.removeChild( tmpDiv ); 244 245 if ( !supportsPercentMargin ) { 246 computedMarginA = hackPercentMargin( elem, computedStyle, computedMarginA ); 247 computedMarginB = hackPercentMargin( elem, computedStyle, computedMarginB ); 248 } 249 250 marginA = parseFloat( computedMarginA ) || 0; 251 marginB = parseFloat( computedMarginB ) || 0; 252 253 if ( val > 0 ) { 254 255 if ( isOuter ) { 256 // outerWidth, outerHeight, add margin 257 val += marginA + marginB; 258 } else { 259 // like getting width() or height(), no padding or border 260 val -= paddingA + paddingB + borderA + borderB; 261 } 262 263 } else { 264 265 // Fall back to computed then uncomputed css if necessary 266 val = computedStyle[ measure ]; 267 if ( val < 0 || val === null ) { 268 val = elem.style[ measure ] || 0; 269 } 270 // Normalize "", auto, and prepare for extra 271 val = parseFloat( val ) || 0; 272 273 if ( isOuter ) { 274 // Add padding, border, margin 275 val += paddingA + paddingB + marginA + marginB + borderA + borderB; 276 } 277 } 278 279 return val; 280}
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.