1(function ($, window, undefined) { 2 3 "use strict"; 4 5 // /* ====== SHARED VARS - jQuery ====== */ 6 // These depend on jQuery 7 var $window = $(window), 8 windowHeight = $window.height(), 9 windowWidth = $window.width(); 10 11 /** 12 * Detect browser size and remember it in global variables 13 */ 14 15 function browserSize() { 16 wh = $window.height(); 17 ww = $window.width(); 18 dh = $(document).height(); 19 ar = ww / wh; 20 } 21 22 23 /** 24 * Detect what platform are we on (browser, mobile, etc) 25 */ 26 27 function platformDetect() { 28 $.support.touch = 'ontouchend' in document; 29 var navUA = navigator.userAgent.toLowerCase(), 30 navPlat = navigator.platform.toLowerCase(); 31 32 var isiPhone = navPlat.indexOf("iphone"), 33 isiPod = navPlat.indexOf("ipod"), 34 isAndroidPhone = navPlat.indexOf("android"), 35 safari = (navUA.indexOf('safari') != -1 && navUA.indexOf('chrome') == -1) ? true : false, 36 svgSupport = (window.SVGAngle) ? true : false, 37 svgSupportAlt = (document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")) ? true : false, 38 ff3x = (/gecko/i.test(navUA) && /rv:1.9/i.test(navUA)) ? true : false, 39 40 ieMobile = navigator.userAgent.match(/Windows Phone/i) ? true : false, 41 phone = (isiPhone > -1 || isiPod > -1 || isAndroidPhone > -1) ? true : false, 42 touch = $.support.touch ? true : false; 43 44 if (touch) $html.addClass('touch'); 45 46 if (ieMobile) $html.addClass('is--winmob'); 47 if (is_android) $html.addClass('is--ancient-android'); 48 49 if (safari) $body.addClass('safari'); 50 if (phone) $body.addClass('phone'); 51 } 52 53 // /* ====== SHARED VARS ====== */ 54 // These do not depend on jQuery 55 var phone, touch, wh, ww, dh, ar, fonts; 56 57 var ua = navigator.userAgent; 58 var winLoc = window.location.toString(); 59 60 var is_webkit = ua.match(/webkit/i); 61 var is_firefox = ua.match(/gecko/i); 62 var is_newer_ie = ua.match(/msie (9|([1-9][0-9]))/i); 63 var is_older_ie = ua.match(/msie/i) && !is_newer_ie; 64 var is_ancient_ie = ua.match(/msie 6/i); 65 var is_mobile = ua.match(/mobile/i);
66 var is_OSX = (ua.match(/(iPad|iPhone|iPod|Macintosh)/g) ? true : false); 67 68 var nua = navigator.userAgent; 69 var is_android = ((nua.indexOf('Mozilla/5.0') !== -1 && nua.indexOf('Android ') !== -1 && nua.indexOf('AppleWebKit') !== -1) && nua.indexOf('Chrome') === -1); 70 71 var useTransform = true; 72 var use2DTransform = (ua.match(/msie 9/i) || winLoc.match(/transform\=2d/i)); 73 var transform; 74 75 var $html = $('html'); 76 var $body = $('body'); 77 78 // setting up transform prefixes 79 var prefixes = { 80 webkit: 'webkitTransform', 81 firefox: 'MozTransform', 82 ie: 'msTransform', 83 w3c: 'transform' 84 }; 85 86 if (useTransform) { 87 if (is_webkit) { 88 transform = prefixes.webkit; 89 } else if (is_firefox) { 90 transform = prefixes.firefox; 91 } else if (is_newer_ie) { 92 transform = prefixes.ie; 93 } 94 } 95 // /* ====== Masonry Logic ====== */ 96 (function () { 97 98 var $container = $('.archive__grid'), 99 $blocks = $container.children().addClass('post--animated post--loaded'), 100 slices = $blocks.first().children().length; 101 102 var observerConfig = { attributes: false, childList: true, characterData: true }, 103 observer; 104 105 if ( "MutationObserver" in window ) { 106 observer = new MutationObserver( function( mutations ) { 107 $container.masonry( 'layout' ); 108 } ); 109 } 110 111 // initialize masonry after the images have loaded 112 $container.imagesLoaded(function () { 113 114 // prepare hover animations 115 if (!$html.hasClass('touch')) 116 $blocks.addHoverAnimation(); 117 118 // initialize masonry 119 $container.masonry({ 120 isAnimated: false, 121 itemSelector: '.grid__item', 122 hiddenStyle: { 123 opacity: 0 124 } 125 }); 126 127 /** 128 * function used to display cards with a simple fade in transition 129 */ 130 131 function showBlocks($blocks) { 132 133 // use different delays for each card to stagger them 134 $blocks.each(function (i, obj) { 135 136 var $block = $(obj), 137 duration = 200 + slices * 0.1; 138 139 $block.velocity({ 140 translateY: 40 141 }, { 142 duration: 0 143 }); 144 setTimeout(function () { 145 $block.velocity({ 146 translateY: 0 147 }, { 148 easing: "easeOutQuad", 149 duration: 100 150 }); 151 152 $block.children().each(function (j, child) { 153 var $child = $(child), 154 timeout = (j + 1) * 100; 155 156 $child.velocity({ 157 opacity: 0, 158 translateY: 40 159 }, { 160 duration: 0 161 }); 162 163 $child.velocity({ 164 opacity: 1, 165 translateY: 0 166 }, { 167 duration: 300, 168 delay: timeout 169 }); 170 }); 171 172 setTimeout(function () { 173 $block.toggleClass('sticky--bg', $block.hasClass('sticky')); 174 $block.addClass('post--visible'); 175 }, 300); 176 177 }, i * 200); 178 }); 179 } 180 181 // animate cards in 182 showBlocks($blocks); 183 184 // update the masonry layout on window.resize 185 $(window).smartresize(function () { 186 $container.masonry('layout'); 187 }); 188 189 $(window).on('load', function () { 190 $container.masonry('layout'); 191 }); 192 193 // handle behavior for infinite scroll 194 $(document.body).on('post-load', function () { 195 196 // figure out which are the new loaded posts 197 var $newBlocks = $('.archive__grid').children().not('.post--loaded').addClass('post--loaded'); 198 199 // when images have loaded take care of the layout, prepare hover animations, and animate cards in 200 $newBlocks.imagesLoaded( function() { 201 $container.masonry( 'appended', $newBlocks, true ).masonry( 'layout' ); 202 if ( ! $html.hasClass( 'touch' ) ) { 203 $newBlocks.addHoverAnimation(); 204 } 205 showBlocks( $newBlocks ); 206 } ); 207 208 if ( typeof observer !== "undefined" ) { 209 $newBlocks.each( function(i, obj ) { 210 observer.observe( obj, observerConfig ); 211 } ); 212 } 213 }); 214 }); 215 })(); 216 217 // /* ====== Navigation Logic ====== */ 218 $('.nav--main .menu-item-has-children').children('a').append('<span>+</span>'); 219 220 var $nav = $('.nav--main'), 221 $navTrigger = $('.navigation__trigger'), 222 $navContainer = $('.main-navigation'), 223 navTop = (typeof $navContainer.offset() !== 'undefined') ? $navContainer.offset().top : 0, 224 navLeft = (typeof $navContainer.offset() !== 'undefined') ? $navContainer.offset().left : 0, 225 navWidth = $nav.outerWidth(), 226 containerWidth = $navContainer.outerWidth(), 227 navHeight = $nav.outerHeight(), 228 $toolbar = $('.toolbar'), 229 isOpen = false, 230 pageTop = $('#page').offset().top, 231 pageWidth = $('#page').width(), 232 pageLeft = $('#page').offset().left, 233 pageWidth = $('#page').width(), 234 pageLeft = $('#page').offset().left, 235 sticked = false;
236 237 /** 238 * bind toggling the navigation drawer to click and touchstart 239 *in order to get rid of the 300ms delay on touch devices we use the touchstart event 240 */ 241 var triggerEvents = 'click touchstart'; 242 if (is_android) triggerEvents = 'click'; 243 244 // Set the Navigation Container Height 245 $navContainer.height(navHeight); 246 247 $navTrigger.on(triggerEvents, function (e) { 248 // but we still have to prevent the default behavior of the touchstart event 249 // because this way we're making sure the click event won't fire anymore 250 e.preventDefault(); 251 e.stopPropagation(); 252 253 isOpen = !isOpen; 254 $('body').toggleClass('nav--is-open'); 255 256 var offset; 257 258 navWidth = $nav.outerWidth(); 259 260 if ($('body').hasClass('rtl')) { 261 offset = -1 * navWidth; 262 } else { 263 offset = navWidth; 264 } 265 266 if (!is_android) { 267 if (!isOpen) { 268 269 $([$nav, $navTrigger]).each(function (i, obj) { 270 $(obj).velocity({ 271 translateX: 0, 272 translateZ: 0.01 273 }, { 274 duration: 300, 275 easing: "easeInQuart", 276 begin: function () { 277 $navContainer.removeClass('shadow'); 278 } 279 }); 280 }); 281 282 } else { 283 284 $([$nav, $navTrigger]).each(function (i, obj) { 285 $(obj).velocity({ 286 translateX: offset, 287 translateZ: 0.01 288 }, {
289 easing: "easeOutCubic", 290 duration: 300, 291 complete: function () { 292 $navContainer.addClass('shadow'); 293 } 294 }); 295 }); 296 } 297 } 298 }); 299 300 var HandleParentMenuItems = (function() { 301 // Handle parent menu items on tablet in landscape mode; 302 // use case: normal, horizontal menu, touch events, 303 // sub menus are not visible. 304 function handleParentMenuItems() { 305 // Make sure there are no open menu items 306 $('[class*="has-children"]').removeClass('hover'); 307 308 $('[class*="has-children"] > a').each( function(){ 309 // Add a class so we know the items to handle 310 $(this).addClass('prevent-one').attr('hasbeenclicked', false); 311 }); 312 313 $('a.prevent-one').on('click', function(e) { 314 if( $( this ).attr( 'hasbeenclicked' ) == "false" ) { 315 e.preventDefault(); 316 e.stopPropagation(); 317 318 $(this).attr('hasbeenclicked', true); 319 320 // Open the sub menu of this parent item 321 $(this).parent().addClass('hover') 322 // When a parent menu item is activated, 323 // close other menu items on the same level 324 .siblings().removeClass('hover').find('> a.prevent-one').attr('hasbeenclicked', false); 325 } 326 }); 327 } 328 329 // Restore the original behaviour when in portrait mode; 330 // use case: vertical menu, all menu items are visible. 331 function unHandleParentMenuItems() { 332 $('a.prevent-one').each(function(){ 333 // Unbind te click handler 334 $(this).unbind(); 335 }); 336 } 337 338 // When a sub menu is open, close it by a touch on 339 // any other part of the viewport than navigation. 340 // use case: normal, horizontal menu, touch events, 341 // sub menus are not visible. 342 function bindOuterNavClick() { 343 $('body').on( 'touchstart', function (e) { 344 var container = $('.nav--main'); 345 346 if (!container.is(e.target) // if the target of the click isn't the container... 347 && container.has(e.target).length === 0) // ... nor a descendant of the container 348 { 349 $('[class*="has-children"]').removeClass('hover'); 350 $('a.prevent-one').attr('hasbeenclicked', false); 351 } 352 }); 353 } 354 355 return { 356 handle: handleParentMenuItems, 357 unHandle: unHandleParentMenuItems, 358 bindOuterNavClick: bindOuterNavClick 359 } 360 }()); 361 362 /** 363 * function used to make the navigation bar on big screens 364 * sticky or static depending on the scroll position 365 */ 366 367 function updateStickyMenu() { 368 369 // pin 370 if (latestKnownScrollY + pageTop > navTop && !sticked) { 371 $nav.css({ 372 position: 'fixed', 373 top: pageTop, 374 left: pageLeft, 375 width: pageWidth 376 }); 377 378 sticked = true; 379 return; 380 } 381 382 // unpin 383 if (latestKnownScrollY + pageTop <= navTop && sticked) { 384 385 $nav.css({ 386 position: '', 387 left: '', 388 top: '', 389 width: '' 390 }); 391 392 sticked = false; 393 } 394 395 } 396 397 /** 398 * because we hard-code properties on the navigation bar when we stick it at the top of the window 399 * we need to update some properties on window resize 400 */ 401 402 function refreshNavigation() { 403 navTop = (typeof $navContainer.offset() !== 'undefined') ? $navContainer.offset().top : 0; 404 navLeft = (typeof $navContainer.offset() !== 'undefined') ? $navContainer.offset().left : 0; 405 containerWidth = $navContainer.outerWidth(); 406 navWidth = $nav.outerWidth(); 407 navHeight = $nav.outerHeight(); 408 pageTop = $('#page').offset().top; 409 pageWidth = $('#page').width(); 410 411 $navContainer.height(navHeight); 412 413 if (sticked) { 414 $nav.velocity({ 415 width: pageWidth 416 }, { 417 easing: "easeOutCubic", 418 duration: 200 419 }); 420 } 421 422 if (isOpen) { 423 $([$nav, $navTrigger]).each(function (i, obj) { 424 $(obj).velocity({ 425 translateX: navWidth 426 }, { 427 easing: "easeOutQuint", 428 duration: 200 429 }); 430 }); 431 } 432 433 navWidth = containerWidth; 434 } 435 436 /** 437 * cardHover jQuery plugin 438 * 439 * we need to create a jQuery plugin so we can easily create the hover animations on the archive 440 * both an window.load and on jetpack's infinite scroll 'post-load' 441 */ 442 $.fn.addHoverAnimation = function () { 443 444 return this.each(function (i, obj) { 445 446 var $obj = $(obj), 447 $handler = $obj.find('.hover__handler'), 448 $hover = $obj.find('.hover'); 449 450 // if we don't have have elements that need to be animated return 451 if (!$hover.length) { 452 return; 453 } 454 455 var $letter = $hover.find('.hover__letter'), 456 letterWidth = $letter.outerWidth, 457 letterHeight = $letter.outerHeight; 458 459 $hover.find('.hover__bg').velocity({ 460 opacity: 0 461 }, { 462 duration: 0 463 }); 464 $hover.find('.hover__line').velocity({ 465 height: 0 466 }, { 467 duration: 0 468 }); 469 $hover.find('.hover__more').velocity({ 470 opacity: 0 471 }, { 472 duration: 0 473 }); 474 $hover.find('.hover__letter').velocity({ 475 opacity: 0, 476 translateX: '-50%', 477 translateY: '-50%', 478 scaleX: 1.25, 479 scaleY: 1.25 480 }, { 481 duration: 0 482 }); 483 484 // bind the tweens we created above to mouse events accordingly, through hoverIntent to avoid flickering 485 if ($handler.length) { 486 $handler.hoverIntent({ 487 over: animateHoverIn, 488 out: animateHoverOut, 489 timeout: 100, 490 interval: 50 491 }); 492 } 493 494 function animateHoverIn() { 495 496 $hover.find('.hover__bg').velocity("reverse", { 497 easing: "easeOutQuart", 498 duration: 500 499 }); 500 $hover.find('.hover__line').velocity("reverse", { 501 easing: "easeOutQuart", 502 duration: 350, 503 delay: 150 504 }); 505 $hover.find('.hover__more').velocity("reverse", { 506 easing: "easeOutQuart", 507 duration: 350, 508 delay: 150 509 }); 510 $hover.find('.hover__letter').velocity({ 511 scaleX: 1, 512 scaleY: 1, 513 opacity: 0.2, 514 translateX: '-50%', 515 translateY: '-50%' 516 }, { 517 easing: "easeOutQuart", 518 duration: 350, 519 delay: 150 520 }); 521 522 } 523 524 function animateHoverOut() { 525 526 var letterHeight = $hover.find('.hover__letter-mask').outerHeight(); 527 528 $hover.find('.hover__letter').velocity({ 529 opacity: 0, 530 translateX: '-50%', 531 translateY: '-50%', 532 scaleX: 1.25, 533 scaleY: 1.25 534 }, { 535 easing: "easeOutQuart", 536 duration: 350, 537 delay: 0 538 }); 539 $hover.find('.hover__more').velocity("reverse", { 540 duration: 350, 541 delay: 0 542 }); 543 $hover.find('.hover__line').velocity("reverse", { 544 duration: 350, 545 delay: 0 546 }); 547 $hover.find('.hover__bg').velocity("reverse", { 548 duration: 350, 549 delay: 0 550 }); 551 552 } 553 554 }); 555 }; 556 557 // /* ====== Search Overlay Logic ====== */ 558 (function () { 559 560 var isOpen = false,
561 $overlay = $('.overlay--search'); 562 563 // update overlay position (if it's open) on window.resize 564 $(window).on('smartresize', function () { 565 566 windowWidth = $(window).outerWidth(); 567 568 if (isOpen) { 569 $overlay.velocity({ 570 translateX: -1 * windowWidth 571 }, { 572 duration: 200, 573 easing: "easeInCubic" 574 }); 575 } 576 577 }); 578 579 /** 580 * dismiss overlay 581 */ 582 583 function closeOverlay() { 584 585 if (!isOpen) { 586 return; 587 } 588 589 var offset; 590 591 if ($('body').hasClass('rtl')) { 592 offset = windowWidth 593 } else { 594 offset = -1 * windowWidth 595 } 596 597 // we don't need a timeline for this animations so we'll use a simple tween between two states 598 $overlay.velocity({ 599 translateX: offset 600 }, { 601 duration: 0 602 }); 603 $overlay.velocity({ 604 translateX: 0 605 }, { 606 duration: 300, 607 easing: "easeInCubic" 608 }); 609 610 // remove focus from the search field 611 $overlay.find('input').blur(); 612 613 isOpen = false; 614 } 615 616 function escOverlay(e) { 617 if (e.keyCode == 27) { 618 closeOverlay(); 619 } 620 } 621 622 // create animation and run it on 623 $('.nav__item--search').on('click touchstart', function (e) { 624 // prevent default behavior and stop propagation 625 e.preventDefault(); 626 e.stopPropagation(); 627 628 // if through some kind of sorcery the navigation drawer is already open return 629 if (isOpen) { 630 return; 631 } 632 633 var offset; 634 635 if ($('body').hasClass('rtl')) { 636 offset = windowWidth 637 } else { 638 offset = -1 * windowWidth 639 } 640 641 // automatically focus the search field so the user can type right away 642 $overlay.find('input').focus(); 643 644 $overlay.velocity({ 645 translateX: 0 646 }, { 647 duration: 0 648 }).velocity({ 649 translateX: offset 650 }, { 651 duration: 300, 652 easing: "easeOut", 653 queue: false 654 }); 655 656 $('.search-form').velocity({ 657 translateX: 300, 658 opacity: 0 659 }, { 660 duration: 0 661 }).velocity({ 662 opacity: 1 663 }, { 664 duration: 200, 665 easing: "easeOutQuad", 666 delay: 200, 667 queue: false 668 }).velocity({ 669 translateX: 0 670 }, { 671 duration: 400, 672 easeing: [0.175, 0.885, 0.320, 1.275], 673 delay: 50, 674 queue: false 675 }); 676 677 $('.overlay__wrapper > p').velocity({ 678 translateX: 200, 679 opacity: 0 680 }, { 681 duration: 0 682 }).velocity({ 683 opacity: 1 684 }, { 685 duration: 400, 686 easing: "easeOutQuad", 687 delay: 350, 688 queue: false 689 }).velocity({ 690 translateX: 0 691 }, { 692 duration: 400, 693 easing: [0.175, 0.885, 0.320, 1.275], 694 delay: 250, 695 queue: false 696 }); 697 698 // bind overlay dismissal to escape key 699 $(document).on('keyup', escOverlay); 700 701 isOpen = true; 702 }); 703 704 // create function to hide the search overlay and bind it to the click event 705 $('.overlay__close').on('click touchstart', function (e) { 706 707 e.preventDefault(); 708 e.stopPropagation(); 709 710 closeOverlay(); 711 712 // unbind overlay dismissal from escape key 713 $(document).off('keyup', escOverlay); 714 715 }); 716 717 })(); 718 719 // /* ====== Smart Resize Logic ====== */ 720 // It's best to debounce the resize event to a void performance hiccups 721 (function ($, sr) { 722 723 /** 724 * debouncing function from John Hann 725 * http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/ 726 */ 727 var debounce = function (func, threshold, execAsap) { 728 var timeout; 729 730 return function debounced() { 731 var obj = this, 732 args = arguments; 733 734 function delayed() { 735 if (!execAsap) func.apply(obj, args); 736 timeout = null; 737 } 738 739 if (timeout) clearTimeout(timeout); 740 else if (execAsap) func.apply(obj, args); 741 742 timeout = setTimeout(delayed, threshold || 200); 743 }; 744 } 745 // smartresize 746 jQuery.fn[sr] = function (fn) { 747 return fn ? this.bind('resize', debounce(fn)) : this.trigger(sr); 748 }; 749 750 })(jQuery, 'smartresize'); 751 var latestKnownScrollY = window.scrollY, 752 ticking = false; 753 754 function requestTick() { 755 "use strict"; 756 757 if (!ticking) { 758 requestAnimationFrame(update); 759 } 760 ticking = true; 761 } 762 763 function update() { 764 "use strict"; 765 766 ticking = false; 767 768 if (!is_android) { 769 updateStickyMenu(); 770 } 771 } 772 773 /* ====== INTERNAL FUNCTIONS END ====== */ 774 775 776 /* ====== ONE TIME INIT ====== */ 777
778 function init() { 779 780 // /* GLOBAL VARS */ 781 touch = false; 782 783 // GET BROWSER DIMENSIONS 784 browserSize(); 785 786 // /* DETECT PLATFORM */ 787 platformDetect(); 788 } 789 790 791 /* --- GLOBAL EVENT HANDLERS --- */ 792 793 794 /* ====== ON DOCUMENT READY ====== */ 795 796 $(document).ready(function () { 797 init(); 798 }); 799 800 801 /* ====== ON WINDOW LOAD ====== */ 802 803 $window.on('load', function () { 804 805 if ( !$html.hasClass( 'touch' ) ) { 806 var $nav = $( '.nav--main' ).addClass( 'hover-intent' ); 807 808 $( '.nav--main li' ).hoverIntent({ 809 over: showSubMenu, 810 out: hideSubMenu, 811 timeout: 300 812 }); 813 } else if ( $html.hasClass( 'touch') ) { 814 HandleParentMenuItems.handle(); 815 HandleParentMenuItems.bindOuterNavClick(); 816 } 817 818 function showSubMenu() { 819 $(this).addClass('hover'); 820 } 821 822 function hideSubMenu() { 823 $(this).removeClass('hover'); 824 } 825 826 }); 827 828 /* ====== ON RESIZE ====== */ 829 830 $(window).smartresize(function () { 831 if (!is_android) { 832 refreshNavigation(); 833 } 834 windowWidth = $(window).outerWidth(); 835 windowHeight = $(window).outerHeight(); 836 837 if( $html.hasClass( 'touch' ) ) { 838 if( windowWidth >= 1000 ) { 839 // Handle parent menu items 840 HandleParentMenuItems.handle(); 841 } else if ( windowWidth < 1000 ) { 842 // Remove handlers 843 HandleParentMenuItems.unHandle(); 844 } 845 } 846 }); 847 848 /* ====== ON SCROLL ====== */ 849 850 $window.on('scroll', function (e) { 851 "use strict"; 852 853 latestKnownScrollY = window.scrollY; 854 requestTick(); 855 }); 856 // /* ====== HELPER FUNCTIONS ====== */ 857 /** 858 * function similar to PHP's empty function 859 */ 860 861 function empty(data) { 862 if (typeof(data) == 'number' || typeof(data) == 'boolean') { 863 return false; 864 } 865 if (typeof(data) == 'undefined' || data === null) { 866 return true; 867 } 868 if (typeof(data.length) != 'undefined') { 869 return data.length === 0; 870 } 871 var count = 0; 872 for (var i in data) { 873 // if(data.hasOwnProperty(i)) 874 // 875 // This doesn't work in ie8/ie9 due the fact that hasOwnProperty works only on native objects. 876 // http://stackoverflow.com/questions/8157700/object-has-no-hasownproperty-method-i-e-its-undefined-ie8 877 // 878 // for hosts objects we do this 879 if (Object.prototype.hasOwnProperty.call(data, i)) { 880 count++; 881 } 882 } 883 return count === 0; 884 } 885 886 /** 887 * function to add/modify a GET parameter 888 */ 889 890 function setQueryParameter(uri, key, value) { 891 var re = new RegExp("([?|&])" + key + "=.*?(&|$)", "i"); 892 separator = uri.indexOf('?') !== -1 ? "&" : "?"; 893 if (uri.match(re)) { 894 return uri.replace(re, '$1' + key + "=" + value + '$2'); 895 } 896 else { 897 return uri + separator + key + "=" + value; 898 } 899 } 900 901 /** 902 * requestAnimationFrame polyfill by Erik Möller. 903 * Fixes from Paul Irish, Tino Zijdel, Andrew Mao, Klemen SlaviÄ, Darius Bacon 904 * 905 * MIT license 906 */ 907 908 if (!Date.now) 909 Date.now = function () { 910 return new Date().getTime(); 911 }; 912 913 (function () { 914 'use strict'; 915 916 var vendors = ['webkit', 'moz']; 917 for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) { 918 var vp = vendors[i]; 919 window.requestAnimationFrame = window[vp + 'RequestAnimationFrame']; 920 window.cancelAnimationFrame = (window[vp + 'CancelAnimationFrame'] 921 || window[vp + 'CancelRequestAnimationFrame']); 922 } 923 if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) // iOS6 is buggy 924 || !window.requestAnimationFrame || !window.cancelAnimationFrame) { 925 var lastTime = 0; 926 window.requestAnimationFrame = function (callback) { 927 var now = Date.now(); 928 var nextTime = Math.max(lastTime + 16, now); 929 return setTimeout(function () { 930 callback(lastTime = nextTime); 931 }, 932 nextTime - now); 933 }; 934 window.cancelAnimationFrame = clearTimeout; 935 } 936 }()); 937 938})(jQuery, window);
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.