1;(function(context) { 2 3 var Patches = { 4 String: { 5 reverse: function() { 6 return this.split("").reverse().join(""); 7 } 8 }, 9 Array: { 10 indexOf: function (obj, start) { 11 for (var i = start || 0; i < this.length; i++) 12 if (this[i] === obj) 13 return i; 14 return -1; 15 } 16 } 17 }; 18 19 for (var key in Patches) (function(){ 20 var patch = Patches[key]; 21 var target = context[key]; 22 if (patch && target) { 23 for (var method in patch) { 24 if ( !(method in target) ) { 25 target.prototype[method] = patch[method]; 26 } 27 } 28 } 29 })(); 30 31})(this); 32 33var safetyCheck = false; 34function showFancyLeadboxes() { 35 safetyCheck = true; 36 console.log('We can safely display timed/exit leadboxes.'); 37} 38;(function () { 39 var debugblock = window.location && String(window.location.hash) === '#debugblock'; 40 if (debugblock) { 41 safetyCheck = false; 42 return; 43 } 44 45 var safetyUrl = 'http://my.leadpages.net/static/all/js/can-i-show.js'; 46 var getSegment = function (url) { 47 var segments = url.split('/'); 48 if (!~segments[0].indexOf('http')) { 49 safetyUrl = '//' + segments[0] + '/static/all/js/can-i-show.js'; 50 } else { 51 safetyUrl = '//' + segments[2] + '/static/all/js/can-i-show.js'; 52 } 53 return safetyUrl; 54 }; 55 if (document.currentScript) { 56 safetyUrl = getSegment(document.currentScript.src); 57 } else { 58 var scripts = document.getElementsByTagName("script"); 59 for (var i = 0; i < scripts.length; i++) { 60 var url = scripts[i].getAttribute('data-url'); 61 var match = url && url.match(/(.+\/)leadbox\/([0-9a-fA-F]+%3A[0-9a-fA-F]+)\/([0-9]+)\/$/); 62 if (match) { 63 safetyUrl = getSegment(url); 64 break; 65 } 66 } 67 } 68 69 var script = document.createElement('script'); 70 script.src = safetyUrl; 71 document.getElementsByTagName('head')[0].appendChild(script); 72})(); 73 74;(function() { 75 76 if (window.LEADBOX) return; else window.LEADBOX = {}; 77 78 LEADBOX.debugging = window.location && String(window.location.hash) === '#debugging'; 79 80 // Utilities // 81 82 function getSize(callback) { 83 var body = window.document.body, 84 doc = window.document.documentElement, 85 documentWidth = Math.max(body.scrollWidth, doc.scrollWidth, 86 body.offsetWidth, doc.offsetWidth, 87 doc.clientWidth), 88 documentHeight = Math.max(body.scrollHeight, doc.scrollHeight, 89 body.offsetHeight, doc.offsetHeight, 90 doc.clientHeight), 91 viewportWidth = window.innerWidth || doc.clientWidth || 92 body.clientWidth, 93 viewportHeight = window.innerHeight || doc.clientWidth || 94 body.clientWidth; 95 96 // FB.Canvas may be defined because the host page is using the FB 97 // JS API, but it will never trigger the callback because the page 98 // is not hosted inside Facebook. As such, we give it 100ms to 99 // trigger the callback, and if it doesn't, we'll just use the 100 // default (non-facebook) values 101 var workaround = window.setTimeout(function() { 102 workaround = null; 103 callback(documentWidth, documentHeight, viewportWidth, 104 viewportHeight); 105 }, 100); 106 if (typeof FB != "undefined" && FB.Canvas) { 107 FB.Canvas.getPageInfo(function(info) { 108 if(workaround == null) 109 return; // too late 110 window.clearTimeout(workaround); 111 workaround = null; 112 113 if(info.clientWidth - info.offsetLeft < viewportWidth) 114 viewportWidth = info.clientWidth - info.offsetLeft; 115 if(info.clientHeight - info.offsetTop < viewportHe
115ight) 116 viewportHeight = info.clientHeight - info.offsetTop; 117 callback(documentWidth, documentHeight, viewportWidth, 118 viewportHeight); 119 }); 120 } 121 } 122 123 function getScroll(callback) { 124 var doc = document.documentElement, 125 body = document.body, 126 left = doc && doc.scrollLeft || body && body.scrollLeft || 0, 127 top = doc && doc.scrollTop || body && body.scrollTop || 0; 128 129 // FB.Canvas may be defined because the host page is using the FB 130 // JS API, but it will never trigger the callback because the page 131 // is not hosted inside Facebook. As such, we give it 100ms to 132 // trigger the callback, and if it doesn't, we'll just use the 133 // default (non-facebook) values 134 var workaround = window.setTimeout(function() { 135 workaround = null; 136 callback(left, top, 0, 0); 137 }, 100); 138 139 if (typeof FB != "undefined" && FB.Canvas) { 140 FB.Canvas.getPageInfo(function(info) { 141 if(workaround == null) 142 return; // too late 143 window.clearTimeout(workaround); 144 workaround = null; 145 146 callback(left, top, info.scrollLeft, info.scrollTop); 147 }); 148 } 149 } 150 151 function setScroll(left, top, fb_left, fb_top) { 152 window.scrollTo(left, top); 153 if (typeof FB != "undefined" && FB.Canvas) { 154 FB.Canvas.scrollTo(fb_left, fb_top); 155 } 156 } 157 158 function forEach(array, block, scope) { 159 var set = array.slice(0); 160 for (var i=0, n=array.length; i<n; i++) { 161 if (false === block.call(scope, set[i], i) ) return false; 162 } 163 return true; 164 } 165 166 function addEvent(object, type, handler) { 167 var method; 168 if (object && type && handler) { 169 method = object.addEventListener ? 'addEventListener' : object.attachEvent ? 'attachEvent' : ''; 170 type = method == 'addEventListener' ? type : 'on' + type; 171 if (method) { 172 object[method](type, function(event) { 173 event = event ? event : window.event; 174 handler.apply(object, [event]); 175 }); 176 return true; 177 } 178 } 179 return false; 180 } 181 182 function addInterval(block, delay) { 183 var interval = { id:null, loop:null, delay:delay, block:block }; 184 interval.loop = function(){ 185 interval.block(); 186 interval.id = setTimeout(interval.loop, interval.delay); 187 return interval; 188 }; 189 return interval.loop(); 190 } 191 192 function getIntersection(aStart, aEnd, bStart, bEnd) { 193 194 var i = {}; 195 196 var aDelta = { 197 x : aEnd.x - aStart.x, 198 y : aEnd.y - aStart.y 199 }; 200 201 var bDelta = { 202 x : bEnd.x - bStart.x, 203 y : bEnd.y - bStart.y 204 }; 205 206 var s = (-aDelta.y * (aStart.x - bStart.x) + aDelta.x * (aStart.y - bStart.y)) / (-bDelta.x * aDelta.y + aDelta.x * bDelta.y); 207 var t = ( bDelta.x * (aStart.y - bStart.y) - bDelta.y * (aStart.x - bStart.x)) / (-bDelta.x * aDelta.y + aDelta.x * bDelta.y); 208 209 210 if (s >= 0 && s <= 1 && t >= 0 && t <= 1) { 211 i.x = aStart.x + (t * aDelta.x); 212 i.y = aStart.y + (t * aDelta.y); 213 return i; 214 } 215 216 return null; 217 } 218 219 // Settings // 220 221 var activating = null; 222 var exitor = null; 223 var MouseTracker = (function(debugging) { 224 225 // get a handle on our environment 226 227 var left = navigator.platform.match(/(Mac|iPhone|iPod|iPad)/i) ? 1 : 0; 228 229 // define the button area location 230 231 var buttonWidth = 350; 232 var buttonHeight = 50; 233 var chromeHeight = 0; 234 235 // how far ahead to anticipate mouse movement 236 var seconds = 1/4; 237 238 // how sure to be they're going for the button 239 var sureness = 1; // (0+) 240 241 // account for user aim 242 var userVariance = 150; 243 244 var size = this.size = { x:null, y:null }; 245 var history = this.history = { x:null, y:null }; 246 var position = this.position = { x:null, y:null }; 247 var prediction = this.prediction = { x:null, y:null }; 248 var velocity = this.velocity = { x:0, y:0 }; 249 250 var axis = { 'x':'y', 'y':'x' }; 251 var count = 0;
252 var delay = 100; 253 var sure = 0; 254 var ready = false; 255 var past = []; 256 var back = 3; 257 258 var canvas = document && document.documentElement ? document.documentElement : document.body; 259 260 if (debugging) { 261 document.documentElement.style.cursor = 'none'; 262 document.body.style.cursor = 'none'; 263 } 264 265 function updateSize(event) { 266 getSize(function(dw, dh, width, height){ 267 size.x = width; 268 size.y = height; 269 }); 270 } 271 272 function clearPosition(event) { 273 position.x = null; 274 position.y = null; 275 } 276 277 function updatePosition(event) { 278 if (event) { 279 position.x = event.clientX; 280 position.y = event.clientY; 281 } 282 283 if (debugging) { 284 var markers = document.getElementsByTagName('i'); 285 var marker = markers && markers[0] ? markers[0] : document.createElement('i'); 286 287 document.body.appendChild(marker); 288 // if (!next.x && !next.y) document.body.removeChild(marker); 289 290 marker.style.display = 'block'; 291 marker.style.position = 'fixed'; 292 marker.style.background = '#000'; 293 marker.style.width = '6px'; 294 marker.style.height = '6px'; 295 marker.style.marginLeft = '-3px'; 296 marker.style.marginTop = '-3px'; 297 marker.style.left = '' + position.x + 'px'; 298 marker.style.top = '' + position.y + 'px'; 299 marker.style.cursor = 'none'; 300 marker.style.zIndex = 101; 301 } 302 303 } 304 305 function updateVector() { 306 307 var anticipation = seconds * (1000 / delay); 308 var projection = { x:position.x, y:position.y }; 309 310 for (var a in axis) { 311 if (position[a] !== null) { 312 velocity[a] = history[a] !== null ? position[a] - history[a] : 0; 313 prediction[a] = position[a] + (velocity[a] * anticipation); 314 history[a] = position[a]; 315 } 316 else { 317 history[a] = position[a] = prediction[a] = null; 318 } 319 } 320 321 past = [{ x:velocity.x, y:velocity.y }].concat( past.slice(0, back) ); 322 323 var i = 0; 324 var average = { x:0, y:0 }; 325 forEach(past, function(value, key){ 326 if (key < back) { 327 average.x = average.x + value.x; 328 average.y = average.y + value.y; 329 i++; 330 } 331 }); 332 average.x = Math.round(average.x / i) * anticipation; 333 average.y = Math.round(average.y / i) * anticipation; 334 var next = { x:position.x + average.x, y:position.y + average.y }; 335 336 // show the predicted placement on the page 337 338 if (debugging) { 339 var markers = document.getElementsByTagName('var'); 340 var marker = markers && markers[0] ? markers[0] : document.createElement('var'); 341 342 document.body.appendChild(marker); 343 if (!next.x && !next.y) document.body.removeChild(marker); 344 345 marker.style.display = 'block'; 346 marker.style.position = 'fixed'; 347 marker.style.background = '#AAA'; 348 marker.style.width = '6px'; 349 marker.style.height = '6px'; 350 marker.style.marginLeft = '-3px'; 351 marker.style.marginTop = '-3px'; 352 marker.style.left = '' + next.x + 'px'; 353 marker.style.top = '' + next.y + 'px'; 354 marker.style.zIndex = 100; 355 356 } 357 358 // estimate if we are going for the close buttons 359 360 getSize(function (dw, dh, vw, vh) { 361 362 // left = false; // for debugging 363 364 var closeStart = { 365 x : left ? 0 - userVariance : vw - buttonWidth - userVariance, 366 y : -1 367 }; 368 var closeEnd = { 369 x : left ? 0 + buttonWidth + userVariance : vw + userVariance, 370 y : -1 371 }; 372 373 var intersect = getIntersection(position, next, closeStart, closeEnd); 374 375 if (intersect) { 376 sure++; 377 // console.log(sure, new Date) 378 if (sure >
378 sureness && !velocity.x && !velocity.y) { 379 // if (window.LEADBOX.debugging && window.console && console.log) console.log('exit detected'); 380 if (exitor && safetyCheck) { 381 window.LEADBOX.show(exitor); 382 exitor = null; 383 } 384 } 385 } 386 else { 387 sure = 0; 388 } 389 }); 390 391 }; 392 393 canvas.style.minHeight = '100%'; 394 395 // addEvent(canvas, 'mouseout', clearPosition); clearPosition(); 396 // addEvent(window, 'mouseout', clearPosition); clearPosition(); 397 addEvent(canvas, 'mousemove', updatePosition); updatePosition(); 398 addEvent(window, 'resize', updateSize); updateSize(); 399 400 addInterval(updateVector, 100); 401 }); 402 403 var LeadBoxes = function() { 404 405 var leadboxes = {}; 406 var background = document.createElement("div"); 407 408 background.style.position = "absolute"; 409 background.style.top = background.style.bottom = 410 background.style.left = background.style.right = "0"; 411 background.style.zIndex = "2147483646"; 412 background.style.background = "black"; 413 background.style.width = "100%"; 414 background.style.opacity = "0.5"; 415 background.style.display = "none"; 416 document.body.appendChild(background); 417 418 function init(id, url, stats) { 419 var config = {}; 420 421 if (leadboxes[id]) return; // leadbox already initialized 422 423 // We need to use this to track whether or not the LeadBox 424 // was actually loaded through JS execution or not. This 425 // is so we can prevent it from double tracking the view 426 // event. 427 if (url[url.length - 1] !== "&") { 428 url += "&"; 429 } 430 431 url += "__fromjs=1"; 432 433 if (typeof window.postMessage == "undefined" || 434 /Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) { 435 // mobile device or IE7-; redirect to form 436 leadboxes[id] = [url, stats, config]; 437 } else { 438 // desktop; open iframe in popup window 439 leadboxes[id] = [document.createElement("iframe"), stats, config]; 440 leadboxes[id][0].src = url.replace("lp-in-iframe=0", 441 "lp-in-iframe=1"); 442 leadboxes[id][0].style.position = "absolute"; 443 leadboxes[id][0].style.left = "0"; 444 leadboxes[id][0].style.top = "0"; 445 leadboxes[id][0].style.width = "100%"; 446 leadboxes[id][0].style.display = "none"; 447 leadboxes[id][0].style.border = "none"; 448 leadboxes[id][0].style.zIndex = "2147483647"; 449 450 leadboxes[id][0].onload = function() { 451 if (window.LEADBOX.debugging) { 452 if (window.console && console.log) console.log('resetting leadbox', id); 453 leadboxes[id][0].contentWindow.postMessage({ handler:'reset', data:{id:id}}, '*'); 454 } 455 var msg = JSON.stringify({ handler:'visit', visit:{ id:id } }) 456 leadboxes[id][0].contentWindow.postMessage(msg, '*'); 457 leadboxes[id][0].onload = null; 458 }; 459 460 document.body.appendChild(leadboxes[id][0]); 461 462 getSize(function(documentWidth, documentHeight, width, height) { 463 leadboxes[id][0].style.height = height + "px"; 464 }); 465 } 466 } 467 468 var active = null, 469 overflow = null; 470 471 // hides the most recently shown leadbox 472 function hide() { 473 if (!active) return; 474 475 // hide frame 476 leadboxes[active][0].style.display = "none"; 477 background.style.display = "none"; 478 active = null; 479 480 // restore scroll position and scrolling settings 481 document.body.style.overflow = overflow; 482 overflow = null; 483 } 484 background.onclick = hide; 485 486 // generates a v4 uuid 487 function uuid() { 488 return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) { 489 var r = ((new Date()).getTime() + Math.random() * 16) % 16 | 0; 490 return (c == "x" ? r : (r & 0x7 | 0x8)).toString(16); 491 }); 492 } 493 494 // shows a leadbox by id; if another leadbox is currently shown, it is 495 // hidden before proceeding 496 function show(id, cb) { 497 // call analytics 498 var url = leadboxes[id][1] + "?", 499 data = { 500 "id": id, 501 "uuid": uuid(), 502 "type": "view", 503 "served_by": "leadboxes" 504 }; 505 for(var key in data) { 506 if (data[key] !== undefined) 507 url += encodeURIComponent(key) + "=" + 508 encodeURIComponent(data[key]) + "&"; 509 } 510 511 var image = document.createElement("img"); 512 if (typeof leadboxes[id][0] == "string") 513 // open leadbox in new tab 514 window.open(leadboxes[id][0], "_blank"); 515 else { 516 getScroll(function(left, top, fbLeft, fbTop) { 517 // hide previous leadbox, if any 518 hide(); 519 520 // get scroll position and body overflow settings 521 overflow = document.body.style.overflow; 522 523 setScroll(left, top, fbLeft, fbTop); 524 document.body.style.overflow = "hidden"; 525 526 // show leadbox and update active leadbox reference 527 leadboxes[id][0].style.top = (top + fbTop) + "px"; 528 leadboxes[id][0].style.left = (left + fbLeft) + "px"; 529 leadboxes[id][0].style.display = "block"; 530 background.style.display = "block"; 531 active = id; 532 if (cb) cb(); 533 534 // call analytics handler 535 image.src = url; 536 }); 537 } 538 } 539 540 // called when the leadbox should be resized 541 this.resize = function() { 542 getSize(function(documentWidth, documentHeight, width, height) { 543 background.style.height = documentHeight + "px"; 544 for(var id in leadboxes) { 545 if(typeof(leadboxes[id][0]) == "string") 546 continue; 547 leadboxes[id][0].style.height = height + "px"; 548 } 549 }); 550 }; 551 552 var onMessageHandler = function(event) { 553 if (event && event.data && event.data.handler) switch (event.data.handler) { 554 case 'visited': 555 // console.log('visited', event.data); 556 var id = event.data.visit.id; 557 var config = leadboxes[id][2] || {}; 558 var visit = event.data.visit; 559 560 // console.log('visited ->', config, event.data.visit) 561 562 var show = true; 563 var day = 1000 * 60 * 60 * 24; 564 var last = Number( new Date(visit['display-date'] || 0) ); 565 var now = Number( new Date() ); 566 567 568 569 var visits = visit['visit-count'] || 0; 570 571 last = last ? last / day : 0; 572 now = now / day; 573 574 day = now - last; 575 576 if (config.time) { 577 var time = config.time; 578 var timeout = (time.seconds * 1000) || 0; 579 580 show = true; 581 582 if (time.views) show = show && !(visits % (time.views + 1) ); 583 if (time.days) show = show && time.days < day; 584 if (show) setTimeout(function(){ 585 if(safetyCheck) { 586 window.LEADBOX.show(id); 587 } 588 }, timeout); 589 } 590 if (config.exit) { 591 var exit = config.exit; 592 show = true; 593 if (exit.days) show = show && exit.days < day; 594 if (show) exitor = id; 595 // console.log('exit', config.exit, new Date(visit['display-date'])); 596 } 597 break; 598 case 'displayed': 599 break; 600 } 601 if (event.data == "close") hide(); 602 }; 603 604 // prep leadboxes 605 var scripts = document.getElementsByTagName("script"); 606 var triggers = document.getElementsByTagName("a"), 607 callback = function(event) { 608 var attr = this.getAttribute("data-leadbox"); 609 if (attr) { 610 if (event && event.preventDefault) event.preventDefault(); 611 show(attr); 612 } 613 return false;
614 }; 615 616 for (var i = 0; i < triggers.length; i++) { 617 try { 618 (function(){ 619 var id; 620 var trigger = triggers[i]; 621 var url = trigger.getAttribute("href"); 622 var match = url.match(/(.+\/)leadbox\/([0-9a-fA-F]+%3A[0-9a-fA-F]+)\/([0-9]+)\/$/); 623 624 if (match) { 625 626 id = match[2] = decodeURIComponent(match[2]); 627 init(id, // form-id 628 url + // iframe url 629 ((url.indexOf("?") == -1)?"?": "&") + // query separator 630 "lp-in-iframe=0&" + // position fix 631 window.location.search.replace(/^\?/, ""), // prepopulation 632 match[1] + "forms/pixel/" + match[3] + "/"); // analytics url 633 trigger.setAttribute("data-leadbox", id); 634 trigger.onclick = callback; 635 } 636 637 })(); 638 } 639 catch(e) { 640 // show must go on 641 } 642 } 643 644 for (var i = 0; i < scripts.length; i++) { 645 (function(script){ 646 var id = script.getAttribute('data-leadbox'); 647 var url = script.getAttribute('data-url'); 648 var match = url && url.match(/(.+\/)leadbox\/([0-9a-fA-F]+%3A[0-9a-fA-F]+)\/([0-9]+)\/$/); 649 var config = script.getAttribute('data-config'); 650 config = config && JSON && JSON.parse( unescape( config ) ); 651 652 if (match) { 653 var formUrl = url + // iframe url 654 ((url.indexOf("?") == -1)?"?": "&") + // query separator 655 "lp-in-iframe=0&" + // position fix 656 window.location.search.replace(/^\?/, ""); // prepopulation 657 var statUrl = match[1] + "forms/pixel/" + match[3] + "/"; 658 659 init(id, formUrl, statUrl); 660 661 if (config && config.type) { 662 // console.log(id, config, leadboxes[id]); 663 var settings = leadboxes[id][2] = leadboxes[id] ? leadboxes[id][2] : {}; 664 settings[config.type] = config.settings; 665 // console.log(leadboxes[id]); 666 } 667 668 } 669 670 })(scripts[i]); 671 } 672 673 // setup leadbox close handlers 674 window.formFrameClosed = hide; 675 676 // setup leadbox window handlers 677 addEvent(window, 'message', onMessageHandler); 678 679 // start mouse tracking if exitor has been set 680 // console.log('MouseTracker', exitor, window.LEADBOX.debugging) 681 // setTimeout(function(){ new MouseTracker(window.LEADBOX.debugging) }); 682 setTimeout(function(){ new MouseTracker() }); 683 684 // public controller 685 window.LEADBOX.reset = function(id) { 686 var key; 687 for (key in leadboxes) {}; 688 if (leadboxes && leadboxes[key]) { 689 leadboxes[key][0].contentWindow.postMessage({ 690 'handler':'reset', 691 'data':{ 692 id:id 693 } 694 }, '*'); 695 } 696 }; 697 window.LEADBOX.show = function(id) { 698 // console.log('show?', id) 699 if (id && activating !== id && active !== id) { 700 activating = id; 701 // console.log('post') 702 leadboxes[id][0].contentWindow.postMessage({ 703 handler:'display', 704 display:{ id:id } 705 }, '*'); 706 show(id, function(){ 707 activating = null; 708 // console.log('shown.', id); 709 }); 710 } 711 }; 712 window.LEADBOX.hide = function() { 713 hide(); 714 }; 715 716 if (window.LEADBOX && window.LEADBOX.debugging) { 717 if (window.console && console.log) console.log('debugging detected, resetting active leadboxes'); 718 // window.location.hash = 'debugged'; 719 } 720 721 }; 722 723 var load = function() { 724 if (!window.ae417310535411e38f960800200c9a66) 725 window.ae417310535411e38f960800200c9a66 = new LeadBoxes(); 726 window.ae417310535411e38f960800200c9a66.resize(); 727 }; 728 729 // bind to 'load' and 'resize' (standards) 730 if(window.addEventListener) { 731 window.addEventListener("load", load); 732 window.addEventListener("resize", load); 733 // speed-up load where possible 734 document.addEventListener("DOMContentLoaded", load); 735 } 736 // tender love & care for internet explorer 737 else if(window.attachEvent) { 738 window.attachEvent("onload", load); 739 window.attachEvent("onresize", load); 740 // speed up load event 741 document.attachEvent("onreadystatechange", function() { 742 if(document.readyState === "complete") 743 load(); 744 }); 745 } 746 else { 747 var oldLoad = window.onload, 748 oldResize = window.oldResize; 749 window.onload = function() { 750 load(); 751 if(typeof oldLoad == "function") 752 oldLoad(); 753 }; 754 window.onresize = function(e) { 755 load(); 756 if(typeof oldResize == "function") 757 oldResize(e); 758 }; 759 } 760})();
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.