1/** 2 * Plugin Name: jQuery Essentials Main 3 * Version: 1.3 4 * Date: 07-02-2019 5 * License: CC0 1.0 (https://creativecommons.org/publicdomain/zero/1.0/deed) 6 * 7 */ 8 9function isMobile(){ 10 if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) { 11 return true; 12 } else { 13 return false; 14 } 15} 16 17function isIE(){ 18 var ua = window.navigator.userAgent; 19 var msie = ua.indexOf("MSIE "); 20 21 if (msie > 0){ 22 return true; 23 } else { 24 return false; 25 } 26} 27 28function openPopup(popupId){ 29 var popupContent = jQuery('.popup-essential-').find('.popup-essential-content-video'); 30 31 jQuery('.popup-essential-'+popupId).show(); 32 33 jQuery('.popup-essential-'+popupId).on('click',function(){ 34 closePopup(popupId); 35 }); 36 37 jQuery('.popup-essential-'+popupId+' .popup-essential-content-in-content').on('click',function(e){ 38 e.preventDefault(); 39 e.stopPropagation(); 40 }); 41 42 jQuery('.popup-essential-'+popupId+' .popup-essential-close').on('click',function(){ 43 closePopup(popupId); 44 }); 45 46 jQuery('body').addClass('popup-essential-open'); 47 jQuery('body,html').css('overflow',''); 48} 49function closePopup(popupId){ 50 jQuery('.popup-essential-'+popupId).hide(); 51 jQuery('body').removeClass('popup-essential-open'); 52 jQuery('body,html').css('overflow',''); 53} 54 55 56 57 58 59 60function isInViewport(el) { 61 var rect = el.getBoundingClientRect() 62 return ( 63 (rect.height > 0 || rect.width > 0) && 64 rect.bottom >= 0 && 65 rect.right >= 0 && 66 rect.top <= (window.innerHeight || document.documentElement.clientHeight) && 67 rect.left <= (window.innerWidth || document.documentElement.clientWidth) 68 ) 69} 70 71function animationElementInViewport(el,extraPercentageHeight) { 72 var top = el.offsetTop; 73 var left = el.offsetLeft; 74 var width = el.offsetWidth; 75 var height = el.offsetHeight; 76 var extraPercentageHeight = extraPercentageHeight; 77 var container = jQuery(window); 78 var extraHeightInPixels = (container.innerHeight()/100)*extraPercentageHeight; 79 80 while (el.offsetParent) { 81 el = el.offsetParent; 82 top += el.offsetTop; 83 left += el.offsetLeft; 84 } 85 86 return ( 87 top < (container.scrollTop() + extraHeightInPixels + container.innerHeight()) && 88 left < (container.scrollLeft() + container.innerWidth()) && 89 (top + height) > (container.scrollTop() - extraHeightInPixels) && 90 (left + width) > container.scrollLeft() 91 ); 92} 93 94/* 95 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ 96 * 97 * Uses the built in easing capabilities added In jQuery 1.1 98 * to offer multiple easing options 99 * 100 * TERMS OF USE - jQuery Easing 101 * 102 * Open source under the BSD License. 103 * 104 * Copyright ̩̉ 2008 George McGinley Smith 105 * All rights reserved. 106 * 107 * Redistribution and use in source and binary forms, with or without modification, 108 * are permitted provided that the following conditions are met: 109 * 110 * Redistributions of source code must retain the above copyright notice, this list of 111 * conditions and the following disclaimer. 112 * Redistributions in binary form must reproduce the above copyright notice, this list 113 * of conditions and the following disclaimer in the documentation and/or other materials 114 * provided with the distribution. 115 * 116 * Neither the name of the author nor the names of contributors may be used to endorse 117 * or promote products derived from this software without specific prior written permission. 118 * 119 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 120 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 121 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 122 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 123 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 124 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 125 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 126 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 127 * OF THE POSSIBILITY OF SUCH DAMAGE. 128 * 129 */ 130 131// t: current time, b: begInnIng value, c: change In value, d: duration 132jQuery.easing['jswing'] = jQuery.easing['swing']; 133 134jQuery.extend( jQuery.easing, 135 { 136 def: 'easeOutQuad', 137 swing: function (x, t, b, c, d) { 138 //alert(jQuery.easing.default); 139 return jQuery.easing[jQuery.easing.def](x, t, b, c, d); 140 }, 141 easeInQuad: function (x, t, b, c, d) { 142 return c*(t/=d)*t + b; 143 }, 144 easeOutQuad: function (x, t, b, c, d) { 145 return -c *(t/=d)*(t-2) + b; 146 }, 147 easeInOutQuad: function (x, t, b, c, d) { 148 if ((t/=d/2) < 1) return c/2*t*t + b; 149 return -c/2 * ((--t)*(t-2) - 1) + b; 150 }, 151 easeInCubic: function (x, t, b, c, d) {
vendor: 5,027 bytes, lines 152-268
152 return c*(t/=d)*t*t + b; 153 }, 154 easeOutCubic: function (x, t, b, c, d) { 155 return c*((t=t/d-1)*t*t + 1) + b; 156 }, 157 easeInOutCubic: function (x, t, b, c, d) { 158 if ((t/=d/2) < 1) return c/2*t*t*t + b; 159 return c/2*((t-=2)*t*t + 2) + b; 160 }, 161 easeInQuart: function (x, t, b, c, d) { 162 return c*(t/=d)*t*t*t + b; 163 }, 164 easeOutQuart: function (x, t, b, c, d) { 165 return -c * ((t=t/d-1)*t*t*t - 1) + b; 166 }, 167 easeInOutQuart: function (x, t, b, c, d) { 168 if ((t/=d/2) < 1) return c/2*t*t*t*t + b; 169 return -c/2 * ((t-=2)*t*t*t - 2) + b; 170 }, 171 easeInQuint: function (x, t, b, c, d) { 172 return c*(t/=d)*t*t*t*t + b; 173 }, 174 easeOutQuint: function (x, t, b, c, d) { 175 return c*((t=t/d-1)*t*t*t*t + 1) + b; 176 }, 177 easeInOutQuint: function (x, t, b, c, d) { 178 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; 179 return c/2*((t-=2)*t*t*t*t + 2) + b; 180 }, 181 easeInSine: function (x, t, b, c, d) { 182 return -c * Math.cos(t/d * (Math.PI/2)) + c + b; 183 }, 184 easeOutSine: function (x, t, b, c, d) { 185 return c * Math.sin(t/d * (Math.PI/2)) + b; 186 }, 187 easeInOutSine: function (x, t, b, c, d) { 188 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; 189 }, 190 easeInExpo: function (x, t, b, c, d) { 191 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; 192 }, 193 easeOutExpo: function (x, t, b, c, d) { 194 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; 195 }, 196 easeInOutExpo: function (x, t, b, c, d) { 197 if (t==0) return b; 198 if (t==d) return b+c; 199 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; 200 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; 201 }, 202 easeInCirc: function (x, t, b, c, d) { 203 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; 204 }, 205 easeOutCirc: function (x, t, b, c, d) { 206 return c * Math.sqrt(1 - (t=t/d-1)*t) + b; 207 }, 208 easeInOutCirc: function (x, t, b, c, d) { 209 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; 210 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; 211 }, 212 easeInElastic: function (x, t, b, c, d) { 213 var s=1.70158;var p=0;var a=c; 214 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 215 if (a < Math.abs(c)) { a=c; var s=p/4; } 216 else var s = p/(2*Math.PI) * Math.asin (c/a); 217 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 218 }, 219 easeOutElastic: function (x, t, b, c, d) { 220 var s=1.70158;var p=0;var a=c; 221 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 222 if (a < Math.abs(c)) { a=c; var s=p/4; } 223 else var s = p/(2*Math.PI) * Math.asin (c/a); 224 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; 225 }, 226 easeInOutElastic: function (x, t, b, c, d) { 227 var s=1.70158;var p=0;var a=c; 228 if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); 229 if (a < Math.abs(c)) { a=c; var s=p/4; } 230 else var s = p/(2*Math.PI) * Math.asin (c/a); 231 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 232 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; 233 }, 234 easeInBack: function (x, t, b, c, d, s) { 235 if (s == undefined) s = 1.70158; 236 return c*(t/=d)*t*((s+1)*t - s) + b; 237 }, 238 easeOutBack: function (x, t, b, c, d, s) { 239 if (s == undefined) s = 1.70158; 240 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; 241 }, 242 easeInOutBack: function (x, t, b, c, d, s) { 243 if (s == undefined) s = 1.70158; 244 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; 245 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; 246 }, 247 easeInBounce: function (x, t, b, c, d) { 248 return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b; 249 }, 250 easeOutBounce: function (x, t, b, c, d) { 251 if ((t/=d) < (1/2.75)) { 252 return c*(7.5625*t*t) + b; 253 } else if (t < (2/2.75)) { 254 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; 255 } else if (t < (2.5/2.75)) { 256 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; 257 } else { 258 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; 259 } 260 }, 261 easeInOutBounce: function (x, t, b, c, d) { 262 if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; 263 return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; 264 } 265 }); 266 267/* 268 *
269 * TERMS OF USE - EASING EQUATIONS 270 * 271 * Open source under the BSD License. 272 * 273 * Copyright ̩̉ 2001 Robert Penner 274 * All rights reserved. 275 * 276 * Redistribution and use in source and binary forms, with or without modification, 277 * are permitted provided that the following conditions are met: 278 * 279 * Redistributions of source code must retain the above copyright notice, this list of 280 * conditions and the following disclaimer. 281 * Redistributions in binary form must reproduce the above copyright notice, this list 282 * of conditions and the following disclaimer in the documentation and/or other materials 283 * provided with the distribution. 284 * 285 * Neither the name of the author nor the names of contributors may be used to endorse 286 * or promote products derived from this software without specific prior written permission. 287 * 288 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 289 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 290 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 291 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 292 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 293 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 294 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 295 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 296 * OF THE POSSIBILITY OF SUCH DAMAGE. 297 * 298 */ 299 300/*! waitForImages jQuery Plugin - v2.4.0 - 2018-02-13 301* https://github.com/alexanderdickson/waitForImages 302* Copyright (c) 2018 Alex Dickson; Licensed MIT */ 303;(function (factory) { 304 if (typeof define === 'function' && define.amd) { 305 // AMD. Register as an anonymous module. 306 define(['jquery'], factory); 307 } else if (typeof exports === 'object') { 308 // CommonJS / nodejs module 309 module.exports = factory(require('jquery')); 310 } else { 311 // Browser globals 312 factory(jQuery); 313 } 314}(function ($) { 315 // Namespace all events. 316 var eventNamespace = 'onImagesLoaded'; 317 318 // Is srcset supported by this browser? 319 var hasSrcset = (function(img) { 320 return img.srcset && img.sizes; 321 })(new Image()); 322 323 // CSS properties which contain references to images. 324 $.onImagesLoaded = { 325 hasImageProperties: [ 326 'backgroundImage', 327 'listStyleImage', 328 'borderImage', 329 'borderCornerImage', 330 'cursor' 331 ], 332 hasImageAttributes: ['srcset'] 333 }; 334 335 // Custom selector to find all `img` elements with a valid `src` attribute. 336 $.expr.pseudos['has-src'] = function (obj) { 337 // Ensure we are dealing with an `img` element with a valid 338 // `src` attribute. 339 return $(obj).is('img[src][src!=""]'); 340 }; 341 342 // Custom selector to find images which are not already cached by the 343 // browser. 344 $.expr.pseudos.uncached = function (obj) { 345 // Ensure we are dealing with an `img` element with a valid 346 // `src` attribute. 347 if (!$(obj).is(':has-src')) { 348 return false; 349 } 350 351 return !obj.complete; 352 }; 353 354 $.fn.onImagesLoaded = function () { 355 356 var allImgsLength = 0; 357 var allImgsLoaded = 0; 358 var deferred = $.Deferred(); 359 var originalCollection = this; 360 var allImgs = []; 361 362 // CSS properties which may contain an image. 363 var hasImgProperties = $.onImagesLoaded.hasImageProperties || []; 364 // Element attributes which may contain an image. 365 var hasImageAttributes = $.onImagesLoaded
vendor: 5,767 bytes, lines 365-528
365.hasImageAttributes || []; 366 // To match `url()` references. 367 // Spec: http://www.w3.org/TR/CSS2/syndata.html#value-def-uri 368 var matchUrl = /url\(\s*(['"]?)(.*?)\1\s*\)/g; 369 370 var finishedCallback; 371 var eachCallback; 372 var waitForAll; 373 374 // Handle options object (if passed). 375 if ($.isPlainObject(arguments[0])) { 376 377 waitForAll = arguments[0].waitForAll; 378 eachCallback = arguments[0].each; 379 finishedCallback = arguments[0].finished; 380 381 } else { 382 383 // Handle if using deferred object and only one param was passed in. 384 if (arguments.length === 1 && $.type(arguments[0]) === 'boolean') { 385 waitForAll = arguments[0]; 386 } else { 387 finishedCallback = arguments[0]; 388 eachCallback = arguments[1]; 389 waitForAll = arguments[2]; 390 } 391 392 } 393 394 // Handle missing callbacks. 395 finishedCallback = finishedCallback || $.noop; 396 eachCallback = eachCallback || $.noop; 397 398 // Convert waitForAll to Boolean. 399 waitForAll = !! waitForAll; 400 401 // Ensure callbacks are functions. 402 if (!$.isFunction(finishedCallback) || !$.isFunction(eachCallback)) { 403 throw new TypeError('An invalid callback was supplied.'); 404 } 405 406 this.each(function () { 407 // Build a list of all imgs, dependent on what images will 408 // be considered. 409 var obj = $(this); 410 411 if (waitForAll) { 412 413 // Get all elements (including the original), as any one of 414 // them could have a background image. 415 obj.find('*').addBack().each(function () { 416 var element = $(this); 417 418 // If an `img` element, add it. But keep iterating in 419 // case it has a background image too. 420 if (element.is('img:has-src') && 421 !element.is('[srcset]')) { 422 allImgs.push({ 423 src: element.attr('src'), 424 element: element[0] 425 }); 426 } 427 428 $.each(hasImgProperties, function (i, property) { 429 var propertyValue = element.css(property); 430 var match; 431 432 // If it doesn't contain this property, skip. 433 if (!propertyValue) { 434 return true; 435 } 436 437 // Get all url() of this element. 438 while (match = matchUrl.exec(propertyValue)) { 439 allImgs.push({ 440 src: match[2], 441 element: element[0] 442 }); 443 } 444 }); 445 446 $.each(hasImageAttributes, function (i, attribute) { 447 var attributeValue = element.attr(attribute); 448 var attributeValues; 449 450 // If it doesn't contain this property, skip. 451 if (!attributeValue) { 452 return true; 453 } 454 455 allImgs.push({ 456 src: element.attr('src'), 457 srcset: element.attr('srcset'), 458 element: element[0] 459 }); 460 }); 461 }); 462 } else { 463 // For images only, the task is simpler. 464 obj.find('img:has-src') 465 .each(function () { 466 allImgs.push({ 467 src: this.src, 468 element: this 469 }); 470 }); 471 } 472 }); 473 474 allImgsLength = allImgs.length; 475 allImgsLoaded = 0; 476 477 // If no images found, don't bother. 478 if (allImgsLength === 0) { 479 finishedCallback.call(originalCollection); 480 deferred.resolveWith(originalCollection); 481 } 482 483 // Now that we've found all imgs in all elements in this, 484 // load them and attach callbacks. 485 $.each(allImgs, function (i, img) { 486 487 var image = new Image(); 488 var events = 489 'load.' + eventNamespace + ' error.' + eventNamespace; 490 491 // Handle the image loading and error with the same callback. 492 $(image).one(events, function me (event) { 493 // If an error occurred with loading the image, set the 494 // third argument accordingly. 495 var eachArguments = [ 496 allImgsLoaded, 497 allImgsLength, 498 event.type == 'load' 499 ]; 500 allImgsLoaded++; 501 502 eachCallback.apply(img.element, eachArguments); 503 deferred.notifyWith(img.element, eachArguments); 504 505 // Unbind the event listeners. I use this in addition to 506 // `one` as one of those events won't be called (either 507 // 'load' or 'error' will be called). 508 $(this).off(events, me); 509 510 if (allImgsLoaded == allImgsLength) { 511 finishedCallback.call(originalCollection[0]); 512 deferred.resolveWith(originalCollection[0]); 513 return false; 514 } 515 516 }); 517 518 if (hasSrcset && img.srcset) { 519 image.srcset = img.srcset; 520 image.sizes = img.sizes; 521 } 522 image.src = img.src; 523 }); 524 525 return deferred.promise(); 526 527 }; 528}));
529 530 531 532/** 533 * Copyright 2016 Google Inc. All Rights Reserved. 534 * 535 * Licensed under the W3C SOFTWARE AND DOCUMENT NOTICE AND LICENSE. 536 * 537 * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document 538 * 539 */ 540 541(function(window, document) { 542'use strict'; 543 544 545// Exits early if all IntersectionObserver and IntersectionObserverEntry 546// features are natively supported. 547if ('IntersectionObserver' in window && 548 'IntersectionObserverEntry' in window && 549 'intersectionRatio' in window.IntersectionObserverEntry.prototype) { 550 551 // Minimal polyfill for Edge 15's lack of `isIntersecting` 552 // See: https://github.com/w3c/IntersectionObserver/issues/211 553 if (!('isIntersecting' in window.IntersectionObserverEntry.prototype)) { 554 Object.defineProperty(window.IntersectionObserverEntry.prototype, 555 'isIntersecting', { 556 get: function () { 557 return this.intersectionRatio > 0; 558 } 559 }); 560 } 561 return; 562} 563 564 565/** 566 * An IntersectionObserver registry. This registry exists to hold a strong 567 * reference to IntersectionObserver instances currently observing a target 568 * element. Without this registry, instances without another reference may be 569 * garbage collected. 570 */ 571var registry = []; 572 573 574/** 575 * Creates the global IntersectionObserverEntry constructor. 576 * https://w3c.github.io/IntersectionObserver/#intersection-observer-entry 577 * @param {Object} entry A dictionary of instance properties. 578 * @constructor 579 */ 580function IntersectionObserverEntry(entry) { 581 this.time = entry.time; 582 this.target = entry.target; 583 this.rootBounds = entry.rootBounds; 584 this.boundingClientRect = entry.boundingClientRect; 585 this.intersectionRect = entry.intersectionRect || getEmptyRect(); 586 this.isIntersecting = !!entry.intersectionRect; 587 588 // Calculates the intersection ratio. 589 var targetRect = this.boundingClientRect; 590 var targetArea = targetRect.width * targetRect.height; 591 var intersectionRect = this.intersectionRect; 592 var intersectionArea = intersectionRect.width * intersectionRect.height; 593 594 // Sets intersection ratio. 595 if (targetArea) { 596 // Round the intersection ratio to avoid floating point math issues: 597 // https://github.com/w3c/IntersectionObserver/issues/324 598 this.intersectionRatio = Number((intersectionArea / targetArea).toFixed(4)); 599 } else { 600 // If area is zero and is intersecting, sets to 1, otherwise to 0 601 this.intersectionRatio = this.isIntersecting ? 1 : 0; 602 } 603} 604 605 606/** 607 * Creates the global IntersectionObserver constructor. 608 * https://w3c.github.io/IntersectionObserver/#intersection-observer-interface 609 * @param {Function} callback The function to be invoked after intersection 610 * changes have queued. The function is not invoked if the queue has 611 * been emptied by calling the `takeRecords` method. 612 * @param {Object=} opt_options Optional configuration options. 613 * @constructor 614 */ 615function IntersectionObserver(callback, opt_options) { 616 617 var options = opt_options || {}; 618 619 if (typeof callback != 'function') { 620 throw new Error('callback must be a function'); 621 } 622 623 if (options.root && options.root.nodeType != 1) { 624 throw new Error('root must be an Element'); 625 } 626 627 // Binds and throttles `this._checkForIntersections`. 628 this._checkForIntersections = throttle( 629 this._checkForIntersections.bind(this), this.THROTTLE_TIMEOUT); 630 631 // Private properties. 632 this._callback = callback; 633 this._observationTargets = []; 634 this._queuedEntries = []; 635 this._rootMarginValues = this._parseRootMargin(options.rootMargin); 636 637 // Public properties. 638 this.thresholds = this._initThresholds(options.threshold); 639 this.root = options.root || null; 640 this.rootMargin = this._rootMarginValues.map(function(margin) { 641 return margin.value + margin.unit; 642 }).join(' '); 643} 644 645 646/** 647 * The minimum interval within which the document will be checked for 648 * intersection changes. 649 */ 650IntersectionObserver.prototype.THROTTLE_TIMEOUT = 100; 651 652 653/** 654 * The frequency in which the polyfill polls for intersection changes. 655 * this can be updated on a per instance basis and must be set prior to 656 * calling `observe` on the first target. 657 */ 658IntersectionObserver.prototype.POLL_INTERVAL = null; 659 660/** 661 * Use a mutation observer on the root element 662 * to detect intersection changes. 663 */ 664IntersectionObserver.prototype.USE_MUTATION_OBSERVER = true; 665 666 667/** 668 * Starts observing a target element for intersection changes based on 669 * the thresholds values. 670 * @param {Element} target The DOM element to observe. 671 */ 672IntersectionObserver.prototype.observe = function(target) { 673 var isTargetAlreadyObserved = this._observationTargets.some(function(item) { 674 return item.element == target; 675 }); 676 677 if (isTargetAlreadyObserved) { 678 return; 679 } 680
vendor: 2,303 bytes, lines 681-756
681 if (!(target && target.nodeType == 1)) { 682 throw new Error('target must be an Element'); 683 } 684 685 this._registerInstance(); 686 this._observationTargets.push({element: target, entry: null}); 687 this._monitorIntersections(); 688 this._checkForIntersections(); 689}; 690 691 692/** 693 * Stops observing a target element for intersection changes. 694 * @param {Element} target The DOM element to observe. 695 */ 696IntersectionObserver.prototype.unobserve = function(target) { 697 this._observationTargets = 698 this._observationTargets.filter(function(item) { 699 700 return item.element != target; 701 }); 702 if (!this._observationTargets.length) { 703 this._unmonitorIntersections(); 704 this._unregisterInstance(); 705 } 706}; 707 708 709/** 710 * Stops observing all target elements for intersection changes. 711 */ 712IntersectionObserver.prototype.disconnect = function() { 713 this._observationTargets = []; 714 this._unmonitorIntersections(); 715 this._unregisterInstance(); 716}; 717 718 719/** 720 * Returns any queue entries that have not yet been reported to the 721 * callback and clears the queue. This can be used in conjunction with the 722 * callback to obtain the absolute most up-to-date intersection information. 723 * @return {Array} The currently queued entries. 724 */ 725IntersectionObserver.prototype.takeRecords = function() { 726 var records = this._queuedEntries.slice(); 727 this._queuedEntries = []; 728 return records; 729}; 730 731 732/** 733 * Accepts the threshold value from the user configuration object and 734 * returns a sorted array of unique threshold values. If a value is not 735 * between 0 and 1 and error is thrown. 736 * @private 737 * @param {Array|number=} opt_threshold An optional threshold value or 738 * a list of threshold values, defaulting to [0]. 739 * @return {Array} A sorted list of unique and valid threshold values. 740 */ 741IntersectionObserver.prototype._initThresholds = function(opt_threshold) { 742 var threshold = opt_threshold || [0]; 743 if (!Array.isArray(threshold)) threshold = [threshold]; 744 745 return threshold.sort().filter(function(t, i, a) { 746 if (typeof t != 'number' || isNaN(t) || t < 0 || t > 1) { 747 throw new Error('threshold must be a number between 0 and 1 inclusively'); 748 } 749 return t !== a[i - 1]; 750 }); 751}; 752 753 754/** 755 * Accepts the rootMargin value from the user configuration object 756 * and returns an array of the four margin values as an object c
756ontaining 757 * the value and unit properties. If any of the values are not properly 758 * formatted or use a unit other than px or %, and error is thrown. 759 * @private 760 * @param {string=} opt_rootMargin An optional rootMargin value, 761 * defaulting to '0px'. 762 * @return {Array<Object>} An array of margin objects with the keys 763 * value and unit. 764 */ 765IntersectionObserver.prototype._parseRootMargin = function(opt_rootMargin) { 766 var marginString = opt_rootMargin || '0px'; 767 var margins = marginString.split(/\s+/).map(function(margin) { 768 var parts = /^(-?\d*\.?\d+)(px|%)$/.exec(margin); 769 if (!parts) { 770 throw new Error('rootMargin must be specified in pixels or percent'); 771 } 772 return {value: parseFloat(parts[1]), unit: parts[2]}; 773 }); 774 775 // Handles shorthand. 776 margins[1] = margins[1] || margins[0]; 777 margins[2] = margins[2] || margins[0]; 778 margins[3] = margins[3] || margins[1]; 779 780 return margins; 781}; 782 783 784/** 785 * Starts polling for intersection changes if the polling is not already 786 * happening, and if the page's visibility state is visible. 787 * @private 788 */ 789IntersectionObserver.prototype._monitorIntersections = function() { 790 if (!this._monitoringIntersections) { 791 this._monitoringIntersections = true; 792 793 // If a poll interval is set, use polling instead of listening to 794 // resize and scroll events or DOM mutations. 795 if (this.POLL_INTERVAL) { 796 this._monitoringInterval = setInterval( 797 this._checkForIntersections, this.POLL_INTERVAL); 798 } 799 else { 800 addEvent(window, 'resize', this._checkForIntersections, true); 801 addEvent(document, 'scroll', this._checkForIntersections, true); 802 803 if (this.USE_MUTATION_OBSERVER && 'MutationObserver' in window) { 804 this._domObserver = new MutationObserver(this._checkForIntersections); 805 this._domObserver.observe(document, { 806 attributes: true, 807 childList: true, 808 characterData: true, 809 subtree: true 810 }); 811 } 812 } 813 } 814}; 815 816 817/** 818 * Stops polling for intersection changes. 819 * @private 820 */ 821IntersectionObserver.prototype._unmonitorIntersections = function() { 822 if (this._monitoringIntersections) { 823 this._monitoringIntersections = false; 824 825 clearInterval(this._monitoringInterval); 826 this._monitoringInterval = null; 827 828 removeEvent(window, 'resize', this._checkForIntersections, true); 829 removeEvent(document, 'scroll', this._checkForIntersections, true); 830 831 if (this._domObserver) { 832 this._domObserver.disconnect(); 833 this._domObserver = null; 834 } 835 } 836}; 837 838 839/** 840 * Scans each observation target for intersection changes and adds them 841 * to the internal entries queue. If new entries are found, it 842 * schedules the callback to be invoked. 843 * @private 844 */ 845IntersectionObserver.prototype._checkForIntersections = function() { 846 var rootIsInDom = this._rootIsInDom(); 847 var rootRect = rootIsInDom ? this._getRootRect() : getEmptyRect(); 848 849 this._observationTargets.forEach(function(item) { 850 var target = item.element; 851 var targetRect = getBoundingClientRect(target); 852 var rootContainsTarget = this._rootContainsTarget(target); 853 var oldEntry = item.entry; 854 var intersectionRect = rootIsInDom && rootContainsTarget && 855 this._computeTargetAndRootIntersection(target, rootRect); 856 857 var newEntry = item.entry = new IntersectionObserverEntry({ 858 time: now(), 859 target: target, 860 boundingClientRect: targetRect, 861 rootBounds: rootRect, 862 intersectionRect: intersectionRect 863 }); 864 865 if (!oldEntry) { 866 this._queuedEntries.push(newEntry); 867 } else if (rootIsInDom && rootContainsTarget) { 868 // If the new entry intersection ratio has crossed any of the 869 // thresholds, add a new entry. 870 if (this._hasCrossedThreshold(oldEntry, newEntry)) { 871 this._queuedEntries.push(newEntry); 872 } 873 } else { 874 // If the root is not in the DOM or target is not contained within 875 // root but the previous entry for this target had an intersection, 876 // add a new record indicating removal. 877 if (oldEntry && oldEntry.isIntersecting) { 878 this._queuedEntries.push(newEntry); 879 } 880 } 881 }, this); 882 883 if (this._queuedEntries.length) { 884 this._callback(this.takeRecords(), this); 885 } 886}; 887 888 889/** 890 * Accepts a target and root rect computes the intersection between then 891 * following the algorithm in the spec. 892 * TODO(philipwalton): at this time clip-path is not considered. 893 * https://w3c.github.io/IntersectionObserver/#calculate-intersection-rect-algo 894 * @param {Element} target The target DOM element 895 * @param {Object} rootRect The bounding rect of the root after being 896 * expanded by the rootMargin value. 897 * @return {?Object} The final intersection rect object or undefined if no 898 * intersection is found. 899 * @private 900 */ 901IntersectionObserver.prototype._computeTargetAndRootIntersection = 902 function(target, rootRect) { 903 904 // If the element isn't displayed, an intersection can't happen. 905 if (window.getComputedStyle(target).display == 'none') return; 906 907 var targetRect = getBoundingClientRect(target); 908 var intersectionRect = targetRect; 909 var parent = getParentNode(target); 910 var atRoot = false;
vendor: 8,268 bytes, lines 911-1181
911 912 while (!atRoot) { 913 var parentRect = null; 914 var parentComputedStyle = parent.nodeType == 1 ? 915 window.getComputedStyle(parent) : {}; 916 917 // If the parent isn't displayed, an intersection can't happen. 918 if (parentComputedStyle.display == 'none') return; 919 920 if (parent == this.root || parent == document) { 921 atRoot = true; 922 parentRect = rootRect; 923 } else { 924 // If the element has a non-visible overflow, and it's not the <body> 925 // or <html> element, update the intersection rect. 926 // Note: <body> and <html> cannot be clipped to a rect that's not also 927 // the document rect, so no need to compute a new intersection. 928 if (parent != document.body && 929 parent != document.documentElement && 930 parentComputedStyle.overflow != 'visible') { 931 parentRect = getBoundingClientRect(parent); 932 } 933 } 934 935 // If either of the above conditionals set a new parentRect, 936 // calculate new intersection data. 937 if (parentRect) { 938 intersectionRect = computeRectIntersection(parentRect, intersectionRect); 939 940 if (!intersectionRect) break; 941 } 942 parent = getParentNode(parent); 943 } 944 return intersectionRect; 945}; 946 947 948/** 949 * Returns the root rect after being expanded by the rootMargin value. 950 * @return {Object} The expanded root rect. 951 * @private 952 */ 953IntersectionObserver.prototype._getRootRect = function() { 954 var rootRect; 955 if (this.root) { 956 rootRect = getBoundingClientRect(this.root); 957 } else { 958 // Use <html>/<body> instead of window since scroll bars affect size. 959 var html = document.documentElement; 960 var body = document.body; 961 rootRect = { 962 top: 0, 963 left: 0, 964 right: html.clientWidth || body.clientWidth, 965 width: html.clientWidth || body.clientWidth, 966 bottom: html.clientHeight || body.clientHeight, 967 height: html.clientHeight || body.clientHeight 968 }; 969 } 970 return this._expandRectByRootMargin(rootRect); 971}; 972 973 974/** 975 * Accepts a rect and expands it by the rootMargin value. 976 * @param {Object} rect The rect object to expand. 977 * @return {Object} The expanded rect. 978 * @private 979 */ 980IntersectionObserver.prototype._expandRectByRootMargin = function(rect) { 981 var margins = this._rootMarginValues.map(function(margin, i) { 982 return margin.unit == 'px' ? margin.value : 983 margin.value * (i % 2 ? rect.width : rect.height) / 100; 984 }); 985 var newRect = { 986 top: rect.top - margins[0], 987 right: rect.right + margins[1], 988 bottom: rect.bottom + margins[2], 989 left: rect.left - margins[3] 990 }; 991 newRect.width = newRect.right - newRect.left; 992 newRect.height = newRect.bottom - newRect.top; 993 994 return newRect; 995}; 996 997 998/** 999 * Accepts an old and new entry and returns true if at least one of the 1000 * threshold values has been crossed. 1001 * @param {?IntersectionObserverEntry} oldEntry The previous entry for a 1002 * particular target element or null if no previous entry exists. 1003 * @param {IntersectionObserverEntry} newEntry The current entry for a 1004 * particular target element. 1005 * @return {boolean} Returns true if a any threshold has been crossed. 1006 * @private 1007 */ 1008IntersectionObserver.prototype._hasCrossedThreshold = 1009 function(oldEntry, newEntry) { 1010 1011 // To make comparing easier, an entry that has a ratio of 0 1012 // but does not actually intersect is given a value of -1 1013 var oldRatio = oldEntry && oldEntry.isIntersecting ? 1014 oldEntry.intersectionRatio || 0 : -1; 1015 var newRatio = newEntry.isIntersecting ? 1016 newEntry.intersectionRatio || 0 : -1; 1017 1018 // Ignore unchanged ratios 1019 if (oldRatio === newRatio) return; 1020 1021 for (var i = 0; i < this.thresholds.length; i++) { 1022 var threshold = this.thresholds[i]; 1023 1024 // Return true if an entry matches a threshold or if the new ratio 1025 // and the old ratio are on the opposite sides of a threshold. 1026 if (threshold == oldRatio || threshold == newRatio || 1027 threshold < oldRatio !== threshold < newRatio) { 1028 return true; 1029 } 1030 } 1031}; 1032 1033 1034/** 1035 * Returns whether or not the root element is an element and is in the DOM. 1036 * @return {boolean} True if the root element is an element and is in the DOM. 1037 * @private 1038 */ 1039IntersectionObserver.prototype._rootIsInDom = function() { 1040 return !this.root || containsDeep(document, this.root); 1041}; 1042 1043 1044/** 1045 * Returns whether or not the target element is a child of root. 1046 * @param {Element} target The target element to check. 1047 * @return {boolean} True if the target element is a child of root. 1048 * @private 1049 */ 1050IntersectionObserver.prototype._rootContainsTarget = function(target) { 1051 return containsDeep(this.root || document, target); 1052}; 1053 1054 1055/** 1056 * Adds the instance to the global IntersectionObserver registry if it isn't 1057 * already present. 1058 * @private 1059 */ 1060IntersectionObserver.prototype._registerInstance = function() { 1061 if (registry.indexOf(this) < 0) { 1062 registry.push(this); 1063 } 1064}; 1065 1066 1067/** 1068 * Removes the instance from the global IntersectionObserver registry. 1069 * @private 1070 */ 1071IntersectionObserver.prototype._unregisterInstance = function() { 1072 var index = registry.indexOf(this); 1073 if (index != -1) registry.splice(index, 1); 1074}; 1075 1076 1077/** 1078 * Returns the result of the performance.now() method or null in browsers 1079 * that don't support the API. 1080 * @return {number} The elapsed time since the page was requested. 1081 */ 1082function now() { 1083 return window.performance && performance.now && performance.now(); 1084} 1085 1086 1087/** 1088 * Throttles a function and delays its execution, so it's only called at most 1089 * once within a given time period. 1090 * @param {Function} fn The function to throttle. 1091 * @param {number} timeout The amount of time that must pass before the 1092 * function can be called again. 1093 * @return {Function} The throttled function. 1094 */ 1095function throttle(fn, timeout) { 1096 var timer = null; 1097 return function () { 1098 if (!timer) { 1099 timer = setTimeout(function() { 1100 fn(); 1101 timer = null; 1102 }, timeout); 1103 } 1104 }; 1105} 1106 1107 1108/** 1109 * Adds an event handler to a DOM node ensuring cross-browser compatibility. 1110 * @param {Node} node The DOM node to add the event handler to. 1111 * @param {string} event The event name. 1112 * @param {Function} fn The event handler to add. 1113 * @param {boolean} opt_useCapture Optionally adds the even to the capture 1114 * phase. Note: this only works in modern browsers. 1115 */ 1116function addEvent(node, event, fn, opt_useCapture) { 1117 if (typeof node.addEventListener == 'function') { 1118 node.addEventListener(event, fn, opt_useCapture || false); 1119 } 1120 else if (typeof node.attachEvent == 'function') { 1121 node.attachEvent('on' + event, fn); 1122 } 1123} 1124 1125 1126/** 1127 * Removes a previously added event handler from a DOM node. 1128 * @param {Node} node The DOM node to remove the event handler from. 1129 * @param {string} event The event name. 1130 * @param {Function} fn The event handler to remove. 1131 * @param {boolean} opt_useCapture If the event handler was added with this 1132 * flag set to true, it should be set to true here in order to remove it. 1133 */ 1134function removeEvent(node, event, fn, opt_useCapture) { 1135 if (typeof node.removeEventListener == 'function') { 1136 node.removeEventListener(event, fn, opt_useCapture || false); 1137 } 1138 else if (typeof node.detatchEvent == 'function') { 1139 node.detatchEvent('on' + event, fn); 1140 } 1141} 1142 1143 1144/** 1145 * Returns the intersection between two rect objects. 1146 * @param {Object} rect1 The first rect. 1147 * @param {Object} rect2 The second rect. 1148 * @return {?Object} The intersection rect or undefined if no intersection 1149 * is found. 1150 */ 1151function computeRectIntersection(rect1, rect2) { 1152 var top = Math.max(rect1.top, rect2.top); 1153 var bottom = Math.min(rect1.bottom, rect2.bottom); 1154 var left = Math.max(rect1.left, rect2.left); 1155 var right = Math.min(rect1.right, rect2.right); 1156 var width = right - left; 1157 var height = bottom - top; 1158 1159 return (width >= 0 && height >= 0) && { 1160 top: top, 1161 bottom: bottom, 1162 left: left, 1163 right: right, 1164 width: width, 1165 height: height 1166 }; 1167} 1168 1169 1170/** 1171 * Shims the native getBoundingClientRect for compatibility with older IE. 1172 * @param {Element} el The element whose bounding rect to get. 1173 * @return {Object} The (possibly shimmed) rect of the element. 1174 */ 1175function getBoundingClientRect(el) { 1176 var rect; 1177 1178 try { 1179 rect = el.getBoundingClientRect(); 1180 } catch (err) { 1181 // Ignore Windows 7 IE11 "Unspecified error"
1182 // https://github.com/w3c/IntersectionObserver/pull/205 1183 } 1184 1185 if (!rect) return getEmptyRect(); 1186 1187 // Older IE 1188 if (!(rect.width && rect.height)) { 1189 rect = { 1190 top: rect.top, 1191 right: rect.right, 1192 bottom: rect.bottom, 1193 left: rect.left, 1194 width: rect.right - rect.left, 1195 height: rect.bottom - rect.top 1196 }; 1197 } 1198 return rect; 1199} 1200 1201 1202/** 1203 * Returns an empty rect object. An empty rect is returned when an element 1204 * is not in the DOM. 1205 * @return {Object} The empty rect. 1206 */ 1207function getEmptyRect() { 1208 return { 1209 top: 0, 1210 bottom: 0, 1211 left: 0, 1212 right: 0, 1213 width: 0, 1214 height: 0 1215 }; 1216} 1217 1218/** 1219 * Checks to see if a parent element contains a child element (including inside 1220 * shadow DOM). 1221 * @param {Node} parent The parent element. 1222 * @param {Node} child The child element. 1223 * @return {boolean} True if the parent node contains the child node. 1224 */ 1225function containsDeep(parent, child) { 1226 var node = child; 1227 while (node) { 1228 if (node == parent) return true; 1229 1230 node = getParentNode(node); 1231 } 1232 return false; 1233} 1234 1235 1236/** 1237 * Gets the parent node of an element or its host element if the parent node 1238 * is a shadow root. 1239 * @param {Node} node The node whose parent to get. 1240 * @return {Node|null} The parent node or null if no parent exists. 1241 */ 1242function getParentNode(node) { 1243 var parent = node.parentNode; 1244 1245 if (parent && parent.nodeType == 11 && parent.host) { 1246 // If the parent is a shadow root, return the host element. 1247 return parent.host; 1248 } 1249 1250 if (parent && parent.assignedSlot) { 1251 // If the parent is distributed in a <slot>, return the parent of a slot. 1252 return parent.assignedSlot.parentNode; 1253 } 1254 1255 return parent; 1256} 1257 1258 1259// Exposes the constructors globally. 1260window.IntersectionObserver = IntersectionObserver; 1261window.IntersectionObserverEntry = IntersectionObserverEntry; 1262 1263}(window, document));
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.