1(function(root, factory) { 2 if (typeof define == 'function' && define.amd) { 3 define(['jquery'], factory); 4 } else { 5 factory(root.jQuery); 6 } 7})(this, function($) { 8 var UA = navigator.userAgent; 9 var isEdge = /Edge/i.test(UA); 10 11 var SmartBanner = function(options) { 12 // Get the original margin-top of the HTML element so we can take that into account. 13 this.origHtmlMargin = parseFloat($('html').css('margin-top')); 14 this.options = $.extend({}, $.smartbanner.defaults, options); 15 16 // Check if it's already a standalone web app or running within a webui view of an app (not mobile safari). 17 var standalone = navigator.standalone; 18 19 // Detect banner type (iOS or Android). 20 if (this.options.force) { 21 this.type = this.options.force; 22 } 23 else if (UA.match(/Windows Phone/i) !== null && UA.match(/Edge|Touch/i) !== null) { 24 this.type = 'windows'; 25 } 26 else if (UA.match(/iPhone|iPod/i) !== null || (UA.match(/iPad/) && this.options.iOSUniversalApp)) { 27 if (UA.match(/Safari/i) !== null && 28 (UA.match(/CriOS/i) !== null || 29 UA.match(/FxiOS/i) != null || 30 window.Number(UA.substr(UA.indexOf('OS ') + 3, 3).replace('_', '.')) < 6)) { 31 // Check webview and native smart banner support (iOS 6+). 32 this.type = 'ios'; 33 } 34 } 35 else if (UA.match(/\bSilk\/(.*\bMobile Safari\b)?/) || UA.match(/\bKF\w/) || UA.match('Kindle Fire')) { 36 this.type = 'kindle'; 37 } 38 else if (UA.match(/Android/i) !== null) { 39 this.type = 'android'; 40 } 41 // Don't show banner if device isn't iOS or Android, website is loaded in app or user dismissed banner. 42 if (!this.type || standalone || this.getCookie('sb-closed') || this.getCookie('sb-installed')) { 43 return; 44 } 45 // Calculate scale. 46 this.scale = this.options.scale == 'auto' ? $(window).width() / window.screen.width : this.options.scale; 47 if (this.scale < 1) { 48 this.scale = 1; 49 } 50 // Get info from meta data. 51 var meta = $( 52 this.type == 'android' 53 ? 'meta[name="google-play-app"]' 54 : (this.type == 'ios' 55 ? 'meta[name="apple-itunes-app"]' 56 : (this.type == 'kindle' 57 ? 'meta[name="kindle-fire-app"]' 58 : 'meta[name="msApplication-ID"]' 59 ) 60 ) 61 ); 62 63 if (!meta.length) { 64 return; 65 } 66 // For Windows Store apps, get the PackageFamilyName for protocol launch. 67 if (this.type == 'windows') { 68 if (isEdge) { 69 this.appId = $('meta[name="msApplication-PackageEdgeName"]').attr('content'); 70 } 71 if (!this.appId) { 72 this.appId = $('meta[name="msApplication-PackageFamilyName"]').attr('content'); 73 } 74 } 75 else { 76 // Try to pull the appId out of the meta tag and store the result. 77 var parsedMetaContent = /app-id=([^\s,]+)/.exec(meta.attr('content')); 78 if (parsedMetaContent) { 79 this.appId = parsedMetaContent[1]; 80 } else { 81 return; 82 } 83 } 84 this.title = this.options.title 85 ? this.options.title 86 : (meta.data('title') || $('title').text().replace(/\s*[|\-·].*$/, '')); 87 88 this.author = this.options.author 89 ? this.options.author 90 : (meta.data('author') || ($('meta[name="author"]').length ? $('meta[name="author"]').attr('content') : window.location.hostname)); 91 92 this.iconUrl = meta.data('icon-url'); 93 this.price = meta.data('price'); 94 95 // Set default onInstall callback if not set in options. 96 if (typeof this.options.onInstall == 'function') { 97 this.options.onInstall = this.options.onInstall; 98 } else { 99 this.options.onInstall = function() {}; 100 } 101 // Set default onClose callback if not set in options. 102 if (typeof this.options.onClose == 'function') { 103 this.options.onClose = this.options.onClose; 104 } else { 105 this.options.onClose = function() {}; 106 } 107 // Create banner. 108 this.create(); 109 this.show(); 110 this.listen(); 111 }; 112 113 SmartBanner.prototype = { 114 115 constructor: SmartBanner, 116 117 create: function() { 118 var iconURL; 119 var price = this.price || this.options.price; 120 121 var link = this.options.url || (function() { 122 switch (this.type) { 123 case 'android': 124 return 'market://details?id='; 125 case 'kindle': 126 return 'amzn://apps/android?asin='; 127 case 'windows': 128 return isEdge 129 ? 'ms-windows-store://pdp/?productid=' 130 : 'ms-windows-store:navigate?appid='; 131 } 132 return 'https://itunes.apple.com/' + this.options.appStoreLanguage + '/app/id'; 133 }.call(this) + this.appId); 134 135 var inStore = !price ? '' : (function() { 136 var result = price + ' - '; 137 switch (this.type) { 138 case 'android': 139 return result + this.options.inGooglePlay; 140 case 'kindle': 141 return result + this.options.inAmazonAppStore; 142 case 'windows': 143 return result + this.options.inWindowsStore; 144 } 145 return result + this.options.inAppStore 146 }.call(this)); 147
148 var gloss = this.options.iconGloss == null 149 ? (this.type=='ios') 150 : this.options.iconGloss; 151 152 if (this.type == 'android' && this.options.GooglePlayParams) { 153 link += '&referrer=' + this.options.GooglePlayParams; 154 } 155 var banner = ( 156 '<div id="smartbanner" class="' + this.type + '">' + 157 '<div class="sb-container">' + 158 '<a href="#" class="sb-close">×</a>' + 159 '<span class="sb-icon"><img src="https://cdn.qukasoft.com/f/484211/bzR6WmFtNG0vcUp3ZUdFOVU1NG5hQT09/l/logo-78076820.webp"></span>' + 160 '<div class="sb-info">' + 161 '<strong>' + this.title + '</strong>' + 162 '<span>' + this.author + '</span>' + 163 '<span>' + inStore + '</span>' + 164 '</div>' + 165 '<a href="' + link + '" class="sb-button">' + 166 '<span>' + this.options.button + '</span>' + 167 '</a>' + 168 '</div>' + 169 '</div>' 170 ); 171 if (this.options.layer) { 172 $(this.options.appendToSelector).append(banner); 173 } else { 174 $(this.options.appendToSelector).prepend(banner); 175 } 176 if (this.options.icon) { 177 iconURL = this.options.icon; 178 } else if(this.iconUrl) { 179 iconURL = this.iconUrl; 180 } else if ($('link[rel="apple-touch-icon-precomposed"]').length > 0) { 181 iconURL = $('link[rel="apple-touch-icon-precomposed"]').attr('href'); 182 if (this.options.iconGloss == null) { 183 gloss = false; 184 } 185 } else if ($('link[rel="apple-touch-icon"]').length > 0) { 186 iconURL = $('link[rel="apple-touch-icon"]').attr('href'); 187 } else if ($('meta[name="msApplication-TileImage"]').length > 0) { 188 iconURL = $('meta[name="msApplication-TileImage"]').attr('content'); 189 } else if ($('meta[name="msapplication-TileImage"]').length > 0) { 190 // Redundant because ms docs show two case usages. 191 iconURL = $('meta[name="msapplication-TileImage"]').attr('content'); 192 } 193 if (iconURL) { 194 $('#smartbanner .sb-icon').css('background-image', 'url(' + iconURL + ')'); 195 if (gloss) { 196 $('#smartbanner .sb-icon').addClass('gloss'); 197 } 198 } else{ 199 $('#smartbanner').addClass('no-icon'); 200 } 201 this.bannerHeight = $('#smartbanner').outerHeight() + 2; 202 203 if (this.scale > 1) { 204 $('#smartbanner') 205 .css('top', parseFloat($('#smartbanner').css('top')) * this.scale) 206 .css('height', parseFloat($('#smartbanner').css('height')) * this.scale) 207 .hide(); 208 $('#smartbanner .sb-container') 209 .css('-webkit-transform', 'scale(' + this.scale + ')') 210 .css('-msie-transform', 'scale(' + this.scale + ')') 211 .css('-moz-transform', 'scale(' + this.scale + ')') 212 .css('width', $(window).width() / this.scale); 213 } 214 $('#smartbanner') 215 .css('position', this.options.layer ? 'absolute' : 'static'); 216 }, 217 218 listen: function() { 219 $('#smartbanner .sb-close').on('click', $.proxy(this.close, this)); 220 $('#smartbanner .sb-button').on('click', $.proxy(this.install, this)); 221 }, 222 223 show: function(callback) { 224 var banner = $('#smartbanner'); 225 banner.stop(); 226 227 if (this.options.layer) { 228 banner 229 .animate({ top: 0, display: 'block' }, this.options.speedIn) 230 .addClass('shown') 231 .show(); 232 $(this.pushSelector) 233 .animate({ 234 paddingTop: this.origHtmlMargin + (this.bannerHeight * this.scale) 235 }, this.options.speedIn, 'swing', callback); 236 } 237 else { 238 if ($.support.transition) { 239 banner.animate({ top: 0 }, this.options.speedIn).addClass('shown'); 240 var transitionCallback = function() { 241 $('html').removeClass('sb-animation'); 242 if (callback) { 243 callback(); 244 } 245 }; 246 $(this.pushSelector) 247 .addClass('sb-animation') 248 .one($.support.transition.end, transitionCallback) 249 .emulateTransitionEnd(this.options.speedIn) 250 .css('margin-top', this.origHtmlMargin + (this.bannerHeight * this.scale)); 251 } 252 else { 253 banner 254 .slideDown(this.options.speedIn) 255 .addClass('shown'); 256 } 257 } 258 }, 259 260 hide: function(callback) { 261 var banner = $('#smartbanner'); 262 banner.stop(); 263 264 if (this.options.layer) { 265 banner.animate({ 266 top: -1 * this.bannerHeight * this.scale, 267 display: 'block' 268 }, this.options.speedIn) 269 .removeClass('shown'); 270 271 $(this.pushSelector) 272 .animate({ 273 paddingTop: this.origHtmlMargin 274 }, this.options.speedIn, 'swing', callback); 275 } 276 else {
277 if ($.support.transition) { 278 if (this.type !== 'android') { 279 banner 280 .css('top', -1 * this.bannerHeight * this.scale) 281 .removeClass('shown'); 282 } 283 else { 284 banner 285 .css({display:'none'}) 286 .removeClass('shown'); 287 } 288 var transitionCallback = function() { 289 $('html').removeClass('sb-animation'); 290 if (callback) { 291 callback(); 292 } 293 }; 294 $(this.pushSelector) 295 .addClass('sb-animation') 296 .one($.support.transition.end, transitionCallback) 297 .emulateTransitionEnd(this.options.speedOut) 298 .css('margin-top', this.origHtmlMargin); 299 } 300 else { 301 banner.slideUp(this.options.speedOut).removeClass('shown'); 302 } 303 } 304 }, 305 306 close: function(e) { 307 e.preventDefault(); 308 this.hide(); 309 this.setCookie('sb-closed', 'true', this.options.daysHidden); 310 this.options.onClose(e); 311 }, 312 313 install: function(e) { 314 if (this.options.hideOnInstall) { 315 this.hide(); 316 } 317 this.setCookie('sb-installed', 'true', this.options.daysReminder); 318 this.options.onInstall(e); 319 }, 320
321 setCookie: function(name, value, exdays) { 322 var exdate = new Date(); 323 exdate.setDate(exdate.getDate() + exdays); 324 value = encodeURI(value) + ((exdays == null) ? '' : '; expires=' + exdate.toUTCString()); 325 document.cookie = name + '=' + value + '; path=/;'; 326 }, 327 328 getCookie: function(name) { 329 var i, x, y, ARRcookies = document.cookie.split(';'); 330 for (i = 0; i < ARRcookies.length; i++) { 331 x = ARRcookies[i].substr(0, ARRcookies[i].indexOf('=')); 332 y = ARRcookies[i].substr(ARRcookies[i].indexOf('=') + 1); 333 x = x.replace(/^\s+|\s+$/g, ''); 334 if (x == name) { 335 return decodeURI(y); 336 } 337 } 338 return null; 339 }, 340 341 // Demo only. 342 switchType: function() { 343 var that = this; 344 345 this.hide(function() { 346 that.type = that.type == 'android' ? 'ios' : 'android'; 347 var meta = $(that.type == 'android' ? 'meta[name="google-play-app"]' : 'meta[name="apple-itunes-app"]').attr('content'); 348 that.appId = /app-id=([^\s,]+)/.exec(meta)[1]; 349 350 $('#smartbanner').detach(); 351 that.create(); 352 that.show(); 353 }); 354 } 355 }; 356 357 $.smartbanner = function(option) { 358 var $window = $(window); 359 var data = $window.data('smartbanner'); 360 var options = typeof option == 'object' && option; 361 if (!data) { 362 $window.data('smartbanner', (data = new SmartBanner(options))); 363 } 364 if (typeof option == 'string') { 365 data[option](); 366 } 367 }; 368 369 // override these globally if you like (they are all optional) 370 $.smartbanner.defaults = { 371 title: null, // What the title of the app should be in the banner (defaults to <title>) 372 author: null, // What the author of the app should be in the banner (defaults to <meta name="author"> or hostname) 373 price: 'ÃCRETSİZ', // Price of the app 374 appStoreLanguage: 'tr', // Language code for App Store 375 inAppStore: 'App Store', // Text of price for iOS 376 inGooglePlay: 'Google Play', // Text of price for Android 377 inAmazonAppStore: 'In the Amazon Appstore', 378 inWindowsStore: 'In the Windows Store', //Text of price for Windows 379 GooglePlayParams: null, // Aditional parameters for the market 380 icon: null, // The URL of the icon (defaults to <meta name="apple-touch-icon">) 381 iconGloss: null, // Force gloss effect for iOS even for precomposed 382 button: 'İNDİR', // Text for the install button 383 url: null, // The URL for the button. Keep null if you want the button to link to the app store. 384 scale: 'auto', // Scale based on viewport size (set to 1 to disable) 385 speedIn: 300, // Show animation speed of the banner 386 speedOut: 400, // Close animation speed of the banner 387 daysHidden: 15, // Duration to hide the banner after being closed (0 = always show banner) 388 daysReminder: 90, // Duration to hide the banner after "VIEW" is clicked *separate from when the close button is clicked* (0 = always show banner) 389 force: null, // Choose 'ios', 'android' or 'windows'. Don't do a browser check, just always show this banner 390 hideOnInstall: true, // Hide the banner after "VIEW" is clicked. 391 layer: false, // Display as overlay layer or slide down the page 392 iOSUniversalApp: true, // If the iOS App is a universal app for both iPad and iPhone, display Smart Banner to iPad users, too. 393 appendToSelector: 'body', //Append the banner to a specific selector 394 pushSelector: 'html' // What element is going to push the site content down; this is where the banner append animation will start. 395 }; 396 397 $.smartbanner.Constructor = SmartBanner; 398 399 400 function transitionEnd () { 401 var el = document.createElement('smartbanner'); 402 403 var transEndEventNames = { 404 WebkitTransition: 'webkitTransitionEnd', 405 MozTransition: 'transitionend', 406 OTransition: 'oTransitionEnd otransitionend', 407 transition: 'transitionend' 408 }; 409 410 for (var name in transEndEventNames) { 411 if (el.style[name] !== undefined) { 412 return {end: transEndEventNames[name]}; 413 } 414 } 415 // Explicit for ie8. 416 return false; 417 }
418 if ($.support.transition !== undefined) { 419 // Prevent conflict with Twitter Bootstrap. 420 return; 421 } 422 423 // http://blog.alexmaccaw.com/css-transitions 424 $.fn.emulateTransitionEnd = function(duration) { 425 var called = false, $el = this; 426 $(this).one($.support.transition.end, function() { 427 called = true; 428 }); 429 var callback = function() { 430 if (!called) { 431 $($el).trigger($.support.transition.end); 432 } 433 }; 434 setTimeout(callback, duration); 435 return this; 436 }; 437 438 $(function() { 439 $.support.transition = transitionEnd(); 440 }); 441 // ============================================================ 442});
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.