1/** 2 * Copyright 2016 Google Inc. All Rights Reserved. 3 * 4 * Licensed under the W3C SOFTWARE AND DOCUMENT NOTICE AND LICENSE. 5 * 6 * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document 7 * 8 */ 9 10(function(window, document) { 11'use strict'; 12 13// Exits early if all IntersectionObserver and IntersectionObserverEntry 14// features are natively supported. 15if ('IntersectionObserver' in window && 16 'IntersectionObserverEntry' in window && 17 'intersectionRatio' in window.IntersectionObserverEntry.prototype) { 18 19 // Minimal polyfill for Edge 15's lack of `isIntersecting` 20 // See: https://github.com/w3c/IntersectionObserver/issues/211 21 if (!('isIntersecting' in window.IntersectionObserverEntry.prototype)) { 22 Object.defineProperty(window.IntersectionObserverEntry.prototype, 23 'isIntersecting', { 24 get: function () { 25 return this.intersectionRatio > 0; 26 } 27 }); 28 } 29 return; 30} 31 32 33/** 34 * An IntersectionObserver registry. This registry exists to hold a strong 35 * reference to IntersectionObserver instances currently observering a target 36 * element. Without this registry, instances without another reference may be 37 * garbage collected. 38 */ 39var registry = []; 40 41 42/** 43 * Creates the global IntersectionObserverEntry constructor. 44 * https://w3c.github.io/IntersectionObserver/#intersection-observer-entry 45 * @param {Object} entry A dictionary of instance properties. 46 * @constructor 47 */ 48function IntersectionObserverEntry(entry) { 49 this.time = entry.time; 50 this.target = entry.target; 51 this.rootBounds = entry.rootBounds; 52 this.boundingClientRect = entry.boundingClientRect; 53 this.intersectionRect = entry.intersectionRect || getEmptyRect(); 54 this.isIntersecting = !!entry.intersectionRect; 55 56 // Calculates the intersection ratio. 57 var targetRect = this.boundingClientRect; 58 var targetArea = targetRect.width * targetRect.height; 59 var intersectionRect = this.intersectionRect; 60 var intersectionArea = intersectionRect.width * intersectionRect.height; 61 62 // Sets intersection ratio. 63 if (targetArea) { 64 this.intersectionRatio = intersectionArea / targetArea; 65 } else { 66 // If area is zero and is intersecting, sets to 1, otherwise to 0 67 this.intersectionRatio = this.isIntersecting ? 1 : 0; 68 } 69} 70 71 72/** 73 * Creates the global IntersectionObserver constructor. 74 * https://w3c.github.io/IntersectionObserver/#intersection-observer-interface 75 * @param {Function} callback The function to be invoked after intersection 76 * changes have queued. The function is not invoked if the queue has 77 * been emptied by calling the `takeRecords` method. 78 * @param {Object=} opt_options Optional configuration options. 79 * @constructor 80 */ 81function IntersectionObserver(callback, opt_options) { 82 83 var options = opt_options || {}; 84 85 if (typeof callback != 'function') { 86 throw new Error('callback must be a function'); 87 } 88 89 if (options.root && options.root.nodeType != 1) { 90 throw new Error('root must be an Element'); 91 } 92 93 // Binds and throttles `this._checkForIntersections`. 94 this._checkForIntersections = throttle( 95 this._checkForIntersections.bind(this), this.THROTTLE_TIMEOUT); 96 97 // Private properties. 98 this._callback = callback; 99 this._observationTargets = []; 100 this._queuedEntries = []; 101 this._rootMarginValues = this._parseRootMargin(options.rootMargin); 102 103 // Public properties. 104 this.thresholds = this._initThresholds(options.threshold); 105 this.root = options.root || null; 106 this.rootMargin = this._rootMarginValues.map(function(margin) { 107 return margin.value + margin.unit; 108 }).join(' '); 109} 110 111 112/** 113 * The minimum interval within which the document will be checked for 114 * intersection changes. 115 */ 116IntersectionObserver.prototype.THROTTLE_TIMEOUT = 100; 117 118 119/** 120 * The frequency in which the polyfill polls for intersection changes. 121 * this can be updated on a per instance basis and must be set prior to 122 * calling `observe` on the first target. 123 */ 124IntersectionObserver.prototype.POLL_INTERVAL = null; 125 126/** 127 * Use a mutation observer on the root element 128 * to detect intersection changes. 129 */ 130IntersectionObserver.prototype.USE_MUTATION_OBSERVER = true; 131 132 133/** 134 * Starts observing a target element for intersection changes based on 135 * the thresholds values. 136 * @param {Element} target The DOM element to observe. 137 */ 138IntersectionObserver.prototype.observe = function(target) { 139 var isTargetAlreadyObserved = this._observationTargets.some(function(item) { 140 return item.element == target; 141 }); 142 143 if (isTargetAlreadyObserved) { 144 return; 145 } 146
vendor: 2,303 bytes, lines 147-222
147 if (!(target && target.nodeType == 1)) { 148 throw new Error('target must be an Element'); 149 } 150 151 this._registerInstance(); 152 this._observationTargets.push({element: target, entry: null}); 153 this._monitorIntersections(); 154 this._checkForIntersections(); 155}; 156 157 158/** 159 * Stops observing a target element for intersection changes. 160 * @param {Element} target The DOM element to observe. 161 */ 162IntersectionObserver.prototype.unobserve = function(target) { 163 this._observationTargets = 164 this._observationTargets.filter(function(item) { 165 166 return item.element != target; 167 }); 168 if (!this._observationTargets.length) { 169 this._unmonitorIntersections(); 170 this._unregisterInstance(); 171 } 172}; 173 174 175/** 176 * Stops observing all target elements for intersection changes. 177 */ 178IntersectionObserver.prototype.disconnect = function() { 179 this._observationTargets = []; 180 this._unmonitorIntersections(); 181 this._unregisterInstance(); 182}; 183 184 185/** 186 * Returns any queue entries that have not yet been reported to the 187 * callback and clears the queue. This can be used in conjunction with the 188 * callback to obtain the absolute most up-to-date intersection information. 189 * @return {Array} The currently queued entries. 190 */ 191IntersectionObserver.prototype.takeRecords = function() { 192 var records = this._queuedEntries.slice(); 193 this._queuedEntries = []; 194 return records; 195}; 196 197 198/** 199 * Accepts the threshold value from the user configuration object and 200 * returns a sorted array of unique threshold values. If a value is not 201 * between 0 and 1 and error is thrown. 202 * @private 203 * @param {Array|number=} opt_threshold An optional threshold value or 204 * a list of threshold values, defaulting to [0]. 205 * @return {Array} A sorted list of unique and valid threshold values. 206 */ 207IntersectionObserver.prototype._initThresholds = function(opt_threshold) { 208 var threshold = opt_threshold || [0]; 209 if (!Array.isArray(threshold)) threshold = [threshold]; 210 211 return threshold.sort().filter(function(t, i, a) { 212 if (typeof t != 'number' || isNaN(t) || t < 0 || t > 1) { 213 throw new Error('threshold must be a number between 0 and 1 inclusively'); 214 } 215 return t !== a[i - 1]; 216 }); 217}; 218 219 220/** 221 * Accepts the rootMargin value from the user configuration object 222 * and returns an array of the four margin values as an object c
222ontaining 223 * the value and unit properties. If any of the values are not properly 224 * formatted or use a unit other than px or %, and error is thrown. 225 * @private 226 * @param {string=} opt_rootMargin An optional rootMargin value, 227 * defaulting to '0px'. 228 * @return {Array<Object>} An array of margin objects with the keys 229 * value and unit. 230 */ 231IntersectionObserver.prototype._parseRootMargin = function(opt_rootMargin) { 232 var marginString = opt_rootMargin || '0px'; 233 var margins = marginString.split(/\s+/).map(function(margin) { 234 var parts = /^(-?\d*\.?\d+)(px|%)$/.exec(margin); 235 if (!parts) { 236 throw new Error('rootMargin must be specified in pixels or percent'); 237 } 238 return {value: parseFloat(parts[1]), unit: parts[2]}; 239 }); 240 241 // Handles shorthand. 242 margins[1] = margins[1] || margins[0]; 243 margins[2] = margins[2] || margins[0]; 244 margins[3] = margins[3] || margins[1]; 245 246 return margins; 247}; 248 249 250/** 251 * Starts polling for intersection changes if the polling is not already 252 * happening, and if the page's visibilty state is visible. 253 * @private 254 */ 255IntersectionObserver.prototype._monitorIntersections = function() { 256 if (!this._monitoringIntersections) { 257 this._monitoringIntersections = true; 258 259 // If a poll interval is set, use polling instead of listening to 260 // resize and scroll events or DOM mutations. 261 if (this.POLL_INTERVAL) { 262 this._monitoringInterval = setInterval( 263 this._checkForIntersections, this.POLL_INTERVAL); 264 } 265 else { 266 addEvent(window, 'resize', this._checkForIntersections, true); 267 addEvent(document, 'scroll', this._checkForIntersections, true); 268 269 if (this.USE_MUTATION_OBSERVER && 'MutationObserver' in window) { 270 this._domObserver = new MutationObserver(this._checkForIntersections); 271 this._domObserver.observe(document, { 272 attributes: true, 273 childList: true, 274 characterData: true, 275 subtree: true 276 }); 277 } 278 } 279 } 280}; 281 282 283/** 284 * Stops polling for intersection changes. 285 * @private 286 */ 287IntersectionObserver.prototype._unmonitorIntersections = function() { 288 if (this._monitoringIntersections) { 289 this._monitoringIntersections = false; 290 291 clearInterval(this._monitoringInterval); 292 this._monitoringInterval = null; 293 294 removeEvent(window, 'resize', this._checkForIntersections, true); 295 removeEvent(document, 'scroll', this._checkForIntersections, true); 296 297 if (this._domObserver) { 298 this._domObserver.disconnect(); 299 this._domObserver = null; 300 } 301 } 302}; 303 304 305/** 306 * Scans each observation target for intersection changes and adds them 307 * to the internal entries queue. If new entries are found, it 308 * schedules the callback to be invoked. 309 * @private 310 */ 311IntersectionObserver.prototype._checkForIntersections = function() { 312 var rootIsInDom = this._rootIsInDom(); 313 var rootRect = rootIsInDom ? this._getRootRect() : getEmptyRect(); 314 this._observationTargets.forEach(function(item) { 315 var target = item.element; 316 var targetRect = getBoundingClientRect(target); 317 var rootContainsTarget = this._rootContainsTarget(target); 318 var oldEntry = item.entry; 319 var intersectionRect = rootIsInDom && rootContainsTarget && 320 this._computeTargetAndRootIntersection(target, rootRect); 321 322 var newEntry = item.entry = new IntersectionObserverEntry({ 323 time: now(), 324 target: target, 325 boundingClientRect: targetRect, 326 rootBounds: rootRect, 327 intersectionRect: intersectionRect 328 }); 329 330 if (!oldEntry) { 331 this._queuedEntries.push(newEntry); 332 } else if (rootIsInDom && rootContainsTarget) { 333 // If the new entry intersection ratio has crossed any of the 334 // thresholds, add a new entry. 335 if (this._hasCrossedThreshold(oldEntry, newEntry)) { 336 this._queuedEntries.push(newEntry); 337 } 338 } else { 339 // If the root is not in the DOM or target is not contained within 340 // root but the previous entry for this target had an intersection, 341 // add a new record indicating removal. 342 if (oldEntry && oldEntry.isIntersecting) { 343 this._queuedEntries.push(newEntry); 344 } 345 } 346 }, this); 347 348 if (this._queuedEntries.length) { 349 this._callback(this.takeRecords(), this); 350 } 351}; 352 353 354/** 355 * Accepts a target and root rect computes the intersection between then 356 * following the algorithm in the spec. 357 * TODO(philipwalton): at this time clip-path is not considered. 358 * https://w3c.github.io/IntersectionObserver/#calculate-intersection-rect-algo 359 * @param {Element} target The target DOM element 360 * @param {Object} rootRect The bounding rect of the root after being 361 * expanded by the rootMargin value. 362 * @return {?Object} The final intersection rect object or undefined if no 363 * intersection is found. 364 * @private 365 */ 366IntersectionObserver.prototype._computeTargetAndRootIntersection = 367 function(target, rootRect) { 368 369 // If the element isn't displayed, an intersection can't happen. 370 if (window.getComputedStyle(target).display == 'none') return; 371 372 var targetRect = getBoundingClientRect(target); 373 var intersectionRect = targetRect; 374 var parent = getParentNode(target); 375 var atRoot = false;
vendor: 8,500 bytes, lines 376-652
376 377 while (!atRoot) { 378 var parentRect = null; 379 var parentComputedStyle = parent.nodeType == 1 ? 380 window.getComputedStyle(parent) : {}; 381 382 // If the parent isn't displayed, an intersection can't happen. 383 if (parentComputedStyle.display == 'none') return; 384 385 if (parent == this.root || parent == document) { 386 atRoot = true; 387 parentRect = rootRect; 388 } else { 389 // If the element has a non-visible overflow, and it's not the <body> 390 // or <html> element, update the intersection rect. 391 // Note: <body> and <html> cannot be clipped to a rect that's not also 392 // the document rect, so no need to compute a new intersection. 393 if (parent != document.body && 394 parent != document.documentElement && 395 parentComputedStyle.overflow != 'visible') { 396 parentRect = getBoundingClientRect(parent); 397 } 398 } 399 400 // If either of the above conditionals set a new parentRect, 401 // calculate new intersection data. 402 if (parentRect) { 403 intersectionRect = computeRectIntersection(parentRect, intersectionRect); 404 405 if (!intersectionRect) break; 406 } 407 parent = getParentNode(parent); 408 } 409 return intersectionRect; 410}; 411 412 413/** 414 * Returns the root rect after being expanded by the rootMargin value. 415 * @return {Object} The expanded root rect. 416 * @private 417 */ 418IntersectionObserver.prototype._getRootRect = function() { 419 var rootRect; 420 if (this.root) { 421 rootRect = getBoundingClientRect(this.root); 422 } else { 423 // Use <html>/<body> instead of window since scroll bars affect size. 424 var html = document.documentElement; 425 var body = document.body; 426 rootRect = { 427 top: 0, 428 left: 0, 429 right: html.clientWidth || body.clientWidth, 430 width: html.clientWidth || body.clientWidth, 431 bottom: html.clientHeight || body.clientHeight, 432 height: html.clientHeight || body.clientHeight 433 }; 434 } 435 return this._expandRectByRootMargin(rootRect); 436}; 437 438 439/** 440 * Accepts a rect and expands it by the rootMargin value. 441 * @param {Object} rect The rect object to expand. 442 * @return {Object} The expanded rect. 443 * @private 444 */ 445IntersectionObserver.prototype._expandRectByRootMargin = function(rect) { 446 var margins = this._rootMarginValues.map(function(margin, i) { 447 return margin.unit == 'px' ? margin.value : 448 margin.value * (i % 2 ? rect.width : rect.height) / 100; 449 }); 450 var newRect = { 451 top: rect.top - margins[0], 452 right: rect.right + margins[1], 453 bottom: rect.bottom + margins[2], 454 left: rect.left - margins[3] 455 }; 456 newRect.width = newRect.right - newRect.left; 457 newRect.height = newRect.bottom - newRect.top; 458 459 return newRect; 460}; 461 462 463/** 464 * Accepts an old and new entry and returns true if at least one of the 465 * threshold values has been crossed. 466 * @param {?IntersectionObserverEntry} oldEntry The previous entry for a 467 * particular target element or null if no previous entry exists. 468 * @param {IntersectionObserverEntry} newEntry The current entry for a 469 * particular target element. 470 * @return {boolean} Returns true if a any threshold has been crossed. 471 * @private 472 */ 473IntersectionObserver.prototype._hasCrossedThreshold = 474 function(oldEntry, newEntry) { 475 476 // To make comparing easier, an entry that has a ratio of 0 477 // but does not actually intersect is given a value of -1 478 var oldRatio = oldEntry && oldEntry.isIntersecting ? 479 oldEntry.intersectionRatio || 0 : -1; 480 var newRatio = newEntry.isIntersecting ? 481 newEntry.intersectionRatio || 0 : -1; 482 483 // Ignore unchanged ratios 484 if (oldRatio === newRatio) return; 485 486 for (var i = 0; i < this.thresholds.length; i++) { 487 var threshold = this.thresholds[i]; 488 489 // Return true if an entry matches a threshold or if the new ratio 490 // and the old ratio are on the opposite sides of a threshold. 491 if (threshold == oldRatio || threshold == newRatio || 492 threshold < oldRatio !== threshold < newRatio) { 493 return true; 494 } 495 } 496}; 497 498 499/** 500 * Returns whether or not the root element is an element and is in the DOM. 501 * @return {boolean} True if the root element is an element and is in the DOM. 502 * @private 503 */ 504IntersectionObserver.prototype._rootIsInDom = function() { 505 return !this.root || containsDeep(document, this.root); 506}; 507 508 509/** 510 * Returns whether or not the target element is a child of root. 511 * @param {Element} target The target element to check. 512 * @return {boolean} True if the target element is a child of root. 513 * @private 514 */ 515IntersectionObserver.prototype._rootContainsTarget = function(target) { 516 return containsDeep(this.root || document, target); 517}; 518 519 520/** 521 * Adds the instance to the global IntersectionObserver registry if it isn't 522 * already present. 523 * @private 524 */ 525IntersectionObserver.prototype._registerInstance = function() { 526 if (registry.indexOf(this) < 0) { 527 registry.push(this); 528 } 529}; 530 531 532/** 533 * Removes the instance from the global IntersectionObserver registry. 534 * @private 535 */ 536IntersectionObserver.prototype._unregisterInstance = function() { 537 var index = registry.indexOf(this); 538 if (index != -1) registry.splice(index, 1); 539}; 540 541 542/** 543 * Returns the result of the performance.now() method or null in browsers 544 * that don't support the API. 545 * @return {number} The elapsed time since the page was requested. 546 */ 547function now() { 548 return window.performance && performance.now && performance.now(); 549} 550 551 552/** 553 * Throttles a function and delays its executiong, so it's only called at most 554 * once within a given time period. 555 * @param {Function} fn The function to throttle. 556 * @param {number} timeout The amount of time that must pass before the 557 * function can be called again. 558 * @return {Function} The throttled function. 559 */ 560function throttle(fn, timeout) { 561 var timer = null; 562 return function () { 563 if (!timer) { 564 timer = setTimeout(function() { 565 fn(); 566 timer = null; 567 }, timeout); 568 } 569 }; 570} 571 572 573/** 574 * Adds an event handler to a DOM node ensuring cross-browser compatibility. 575 * @param {Node} node The DOM node to add the event handler to. 576 * @param {string} event The event name. 577 * @param {Function} fn The event handler to add. 578 * @param {boolean} opt_useCapture Optionally adds the even to the capture 579 * phase. Note: this only works in modern browsers. 580 */ 581function addEvent(node, event, fn, opt_useCapture) { 582 if (typeof node.addEventListener == 'function') { 583 node.addEventListener(event, fn, opt_useCapture || false); 584 } 585 else if (typeof node.attachEvent == 'function' ) { 586 node.attachEvent('on'+event, fn); 587 }else if (typeof node.attachEvent == 'object'){ 588 //chen edit, for ie8 589 window.attachEvent('on'+event, fn); 590 } 591} 592 593 594/** 595 * Removes a previously added event handler from a DOM node. 596 * @param {Node} node The DOM node to remove the event handler from. 597 * @param {string} event The event name. 598 * @param {Function} fn The event handler to remove. 599 * @param {boolean} opt_useCapture If the event handler was added with this 600 * flag set to true, it should be set to true here in order to remove it. 601 */ 602function removeEvent(node, event, fn, opt_useCapture) { 603 if (typeof node.removeEventListener == 'function') { 604 node.removeEventListener(event, fn, opt_useCapture || false); 605 } 606 else if (typeof node.detatchEvent == 'function') { 607 node.detatchEvent('on' + event, fn); 608 }else if (typeof node.detatchEvent == 'object'){ 609 //chen edit, for ie8 610 window.detatchEvent('on'+event, fn); 611 } 612} 613 614 615/** 616 * Returns the intersection between two rect objects. 617 * @param {Object} rect1 The first rect. 618 * @param {Object} rect2 The second rect. 619 * @return {?Object} The intersection rect or undefined if no intersection 620 * is found. 621 */ 622function computeRectIntersection(rect1, rect2) { 623 var top = Math.max(rect1.top, rect2.top); 624 var bottom = Math.min(rect1.bottom, rect2.bottom); 625 var left = Math.max(rect1.left, rect2.left); 626 var right = Math.min(rect1.right, rect2.right); 627 var width = right - left; 628 var height = bottom - top; 629 630 return (width >= 0 && height >= 0) && { 631 top: top, 632 bottom: bottom, 633 left: left, 634 right: right, 635 width: width, 636 height: height 637 }; 638} 639 640 641/** 642 * Shims the native getBoundingClientRect for compatibility with older IE. 643 * @param {Element} el The element whose bounding rect to get. 644 * @return {Object} The (possibly shimmed) rect of the element. 645 */ 646function getBoundingClientRect(el) { 647 var rect; 648 649 try { 650 rect = el.getBoundingClientRect(); 651 } catch (err) { 652 // Ignore Windows 7 IE11 "Unspecified error"
653 // https://github.com/w3c/IntersectionObserver/pull/205 654 } 655 656 if (!rect) return getEmptyRect(); 657 658 // Older IE 659 if (!(rect.width && rect.height)) { 660 rect = { 661 top: rect.top, 662 right: rect.right, 663 bottom: rect.bottom, 664 left: rect.left, 665 width: rect.right - rect.left, 666 height: rect.bottom - rect.top 667 }; 668 } 669 return rect; 670} 671 672 673/** 674 * Returns an empty rect object. An empty rect is returned when an element 675 * is not in the DOM. 676 * @return {Object} The empty rect. 677 */ 678function getEmptyRect() { 679 return { 680 top: 0, 681 bottom: 0, 682 left: 0, 683 right: 0, 684 width: 0, 685 height: 0 686 }; 687} 688 689/** 690 * Checks to see if a parent element contains a child elemnt (including inside 691 * shadow DOM). 692 * @param {Node} parent The parent element. 693 * @param {Node} child The child element. 694 * @return {boolean} True if the parent node contains the child node. 695 */ 696function containsDeep(parent, child) { 697 var node = child; 698 while (node) { 699 if (node == parent) return true; 700 701 node = getParentNode(node); 702 } 703 return false; 704} 705 706 707/** 708 * Gets the parent node of an element or its host element if the parent node 709 * is a shadow root. 710 * @param {Node} node The node whose parent to get. 711 * @return {Node|null} The parent node or null if no parent exists. 712 */ 713function getParentNode(node) { 714 var parent = node.parentNode; 715 716 if (parent && parent.nodeType == 11 && parent.host) { 717 // If the parent is a shadow root, return the host element. 718 return parent.host; 719 } 720 return parent; 721} 722 723 724// Exposes the constructors globally. 725window.IntersectionObserver = IntersectionObserver; 726window.IntersectionObserverEntry = IntersectionObserverEntry; 727 728}(window, document)); 729 730(function(){ 731 //ie8 bind 732 if (!Function.prototype.bind) { 733 Function.prototype.bind = function (oThis) { 734 if (typeof this !== "function") { 735 throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); 736 } 737 var aArgs = Array.prototype.slice.call(arguments, 1), 738 fToBind = this, 739 fNOP = function () {}, 740 fBound = function () { 741 return fToBind.apply(this instanceof fNOP && oThis 742 ? this 743 : oThis, 744 aArgs.concat(Array.prototype.slice.call(arguments))); 745 }; 746 fNOP.prototype = this.prototype; 747 fBound.prototype = new fNOP(); 748 return fBound; 749 }; 750 } 751 752 //map 753 if (!Array.prototype.map) { 754 Array.prototype.map = function(callback, thisArg) { 755 var T, A, k; 756 if (this == null) { 757 throw new TypeError(" this is null or not defined"); 758 } 759 var O = Object(this); 760 var len = O.length >>> 0; 761 if (typeof callback !== "function") { 762 throw new TypeError(callback + " is not a function"); 763 } 764 if (thisArg) { 765 T = thisArg; 766 } 767 A = new Array(len); 768 k = 0; 769 while(k < len) { 770 var kValue, mappedValue; 771 if (k in O) { 772 kValue = O[ k ]; 773 mappedValue = callback.call(T, kValue, k, O); 774 A[ k ] = mappedValue; 775 } 776 k++; 777 } 778 return A; 779 }; 780 } 781 782 //ie8 isArray 783 if (!Array.isArray) { 784 Array.isArray = function(arg) { 785 return Object.prototype.toString.call(arg) === '[object Array]'; 786 }; 787 } 788 789 //ie8 filter 790 if (!Array.prototype.filter) 791 { 792 Array.prototype.filter = function(fun /*, thisp */) 793 { 794 "use strict"; 795 796 if (this === void 0 || this === null) 797 throw new TypeError(); 798 799 var t = Object(this); 800 var len = t.length >>> 0; 801 if (typeof fun !== "function") 802 throw new TypeError(); 803 804 var res = []; 805 var thisp = arguments[1]; 806 for (var i = 0; i < len; i++) 807 { 808 if (i in t) 809 { 810 var val = t[i]; // in case fun mutates this 811 if (fun.call(thisp, val, i, t)) 812 res.push(val); 813 } 814 } 815 816 return res; 817 }; 818 } 819 820 // Production steps of ECMA-262, Edition 5, 15.4.4.17 821// Reference: http://es5.github.io/#x15.4.4.17 822 if (!Array.prototype.some) { 823 Array.prototype.some = function(fun/*, thisArg*/) { 824 'use strict'; 825 826 if (this == null) { 827 throw new TypeError('Array.prototype.some called on null or undefined'); 828 } 829 830 if (typeof fun !== 'function') { 831 throw new TypeError(); 832 } 833 834 var t = Object(this); 835 var len = t.length >>> 0; 836 837 var thisArg = arguments.length >= 2 ? arguments[1] : void 0; 838 for (var i = 0; i < len; i++) { 839 if (i in t && fun.call(thisArg, t[i], i, t)) { 840 return true; 841 } 842 } 843 844 return false;
845 }; 846 } 847 848 //æ·»å æ°ç»IndexOfæ¹æ³ 849 if (!Array.prototype.indexOf){ 850 Array.prototype.indexOf = function(elt /*, from*/){ 851 var len = this.length >>> 0; 852 853 var from = Number(arguments[1]) || 0; 854 from = (from < 0) 855 ? Math.ceil(from) 856 : Math.floor(from); 857 if (from < 0) 858 from += len; 859 860 for (; from < len; from++){ 861 if (from in this && this[from] === elt) 862 return from; 863 } 864 return -1; 865 }; 866 } 867 868 if ( !Array.prototype.forEach ) { 869 Array.prototype.forEach = function forEach( callback, thisArg ) { 870 var T, k; 871 if ( this == null ) { 872 throw new TypeError( "this is null or not defined" ); 873 } 874 var O = Object(this); 875 var len = O.length >>> 0; 876 if ( typeof callback !== "function" ) { 877 throw new TypeError( callback + " is not a function" ); 878 } 879 if ( arguments.length > 1 ) { 880 T = thisArg; 881 } 882 k = 0; 883 while( k < len ) { 884 var kValue; 885 if ( k in O ) { 886 kValue = O[ k ]; 887 callback.call( T, kValue, k, O ); 888 } 889 k++; 890 } 891 }; 892 } 893 894 895 if (!window.getComputedStyle) { 896 window.getComputedStyle = function(el, pseudo) { 897 this.el = el; 898 this.getPropertyValue = function(prop) { 899 var re = /(\-([a-z]){1})/g; 900 if (prop == 'float') prop = 'styleFloat'; 901 if (re.test(prop)) { 902 prop = prop.replace(re, function () { 903 return arguments[2].toUpperCase(); 904 }); 905 } 906 return el.currentStyle[prop] ? el.currentStyle[prop] : null; 907 } 908 this.display = this.getPropertyValue('display'); 909 this.overflow = this.getPropertyValue('overflow'); 910 return this; 911 } 912 } 913 914}())
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.