/* Detect-zoom * ----------- * Cross Browser Zoom and Pixel Ratio Detector * Version 1.0.4 | Apr 1 2013 * dual-licensed under the WTFPL and MIT license * Maintained by https://github/tombigel * Original developer https://github.com/yonran */ //AMD and CommonJS initialization copied from https://github.com/zohararad/audio5js (function (root, ns, factory) { "use strict"; if (typeof (module) !== 'undefined' && module.exports) { // CommonJS module.exports = factory(ns, root); } else if (typeof (define) === 'function' && define.amd) { // AMD define("factory", function () { return factory(ns, root); }); } else { root[ns] = factory(ns, root); } }(window, 'detectZoom', function () { /** * Use devicePixelRatio if supported by the browser * @return {Number} * @private */ var devicePixelRatio = function () { return window.devicePixelRatio || 1; }; /** * Fallback function to set default values * @return {Object} * @private */ var fallback = function () { return { zoom: 1, devicePxPerCssPx: 1 }; }; /** * IE 8 and 9: no trick needed! * TODO: Test on IE10 and Windows 8 RT * @return {Object} * @private **/ var ie8 = function () { var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100) / 100; return { zoom: zoom, devicePxPerCssPx: zoom * devicePixelRatio() }; }; /** * For IE10 we need to change our technique again... * thanks https://github.com/stefanvanburen * @return {Object} * @private */ var ie10 = function () { var zoom = Math.round((document.documentElement.offsetHeight / window.innerHeight) * 100) / 100; return { zoom: zoom, devicePxPerCssPx: zoom * devicePixelRatio() }; }; /** * Mobile WebKit * the trick: window.innerWIdth is in CSS pixels, while * screen.width and screen.height are in system pixels. * And there are no scrollbars to mess up the measurement. * @return {Object} * @private */ var webkitMobile = function () { var deviceWidth = (Math.abs(window.orientation) == 90) ? screen.height : screen.width; var zoom = deviceWidth / window.innerWidth; return { zoom: zoom, devicePxPerCssPx: zoom * devicePixelRatio() }; }; /** * Desktop Webkit * the trick: an element's clientHeight is in CSS pixels, while you can * set its line-height in system pixels using font-size and * -webkit-text-size-adjust:none. * device-pixel-ratio: http://www.webkit.org/blog/55/high-dpi-web-sites/ * * Previous trick (used before http://trac.webkit.org/changeset/100847): * documentElement.scrollWidth is in CSS pixels, while * document.width was in system pixels. Note that this is the * layout width of the document, which is slightly different from viewport * because document width does not include scrollbars and might be wider * due to big elements. * @return {Object} * @private */ var webkit = function () { var important = function (str) { return str.replace(/;/g, " !important;"); }; var div = document.createElement('div'); div.innerHTML = "1
2
3
4
5
6
7
8
9
0"; div.setAttribute('style', important('font: 100px/1em sans-serif; -webkit-text-size-adjust: none; text-size-adjust: none; height: auto; width: 1em; padding: 0; overflow: visible;')); // The container exists so that the div will be laid out in its own flow // while not impacting the layout, viewport size, or display of the // webpage as a whole. // Add !important and relevant CSS rule resets // so that other rules cannot affect the results. var container = document.createElement('div'); container.setAttribute('style', important('width:0; height:0; overflow:hidden; visibility:hidden; position: absolute;')); container.appendChild(div); document.body.appendChild(container); var zoom = 1000 / div.clientHeight; zoom = Math.round(zoom * 100) / 100; document.body.removeChild(container); return{ zoom: zoom, devicePxPerCssPx: zoom * devicePixelRatio() }; }; /** * no real trick; device-pixel-ratio is the ratio of device dpi / css dpi. * (Note that this is a different interpretation than Webkit's device * pixel ratio, which is the ratio device dpi / system dpi). * * Also, for Mozilla, there is no difference between the zoom factor and the device ratio. * * @return {Object} * @private */ var firefox4 = function () { var zoom = mediaQueryBinarySearch('min--moz-device-pixel-ratio', '', 0, 10, 20, 0.0001); zoom = Math.round(zoom * 100) / 100; return { zoom: zoom, devicePxPerCssPx: zoom }; }; /** * Firefox 18.x * Mozilla added support for devicePixelRatio to Firefox 18, * but it is affected by the zoom level, so, like in older * Firefox we can't tell if we are in zoom mode or in a device * with a different pixel ratio * @return {Object} * @private */ var firefox18 = function () { return { zoom: firefox4().zoom, devicePxPerCssPx: devicePixelRatio() }; }; /** * works starting Opera 11.11 * the trick: outerWidth is the viewport width including scrollbars in * system px, while innerWidth is the viewport width including scrollbars * in CSS px * @return {Object} * @private */ var opera11 = function () { var zoom = window.top.outerWidth / window.top.innerWidth; zoom = Math.round(zoom * 100) / 100; return { zoom: zoom, devicePxPerCssPx: zoom * devicePixelRatio() }; }; /** * Use a binary search through media queries to find zoom level in Firefox * @param property * @param unit * @param a * @param b * @param maxIter * @param epsilon * @return {Number} */ var mediaQueryBinarySearch = function (property, unit, a, b, maxIter, epsilon) { var matchMedia; var head, style, div; if (window.matchMedia) { matchMedia = window.matchMedia; } else { head = document.getElementsByTagName('head')[0]; style = document.createElement('style'); head.appendChild(style); div = document.createElement('div'); div.className = 'mediaQueryBinarySearch'; div.style.display = 'none'; document.body.appendChild(div); matchMedia = function (query) { style.sheet.insertRule('@media ' + query + '{.mediaQueryBinarySearch ' + '{text-decoration: underline} }', 0); var matched = getComputedStyle(div, null).textDecoration == 'underline'; style.sheet.deleteRule(0); return {matches: matched}; }; } var ratio = binarySearch(a, b, maxIter); if (div) { head.removeChild(style); document.body.removeChild(div); } return ratio; function binarySearch(a, b, maxIter) { var mid = (a + b) / 2; if (maxIter <= 0 || b - a < epsilon) { return mid; } var query = "(" + property + ":" + mid + unit + ")"; if (matchMedia(query).matches) { return binarySearch(mid, b, maxIter - 1); } else { return binarySearch(a, mid, maxIter - 1); } } }; /** * Generate detection function * @private */ var detectFunction = (function () { var func = fallback; //IE8+ if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { func = ie8; } // IE10+ / Touch else if (window.navigator.msMaxTouchPoints) { func = ie10; } //Mobile Webkit else if ('orientation' in window && typeof document.body.style.webkitMarquee === 'string') { func = webkitMobile; } //WebKit else if (typeof document.body.style.webkitMarquee === 'string') { func = webkit; } //Opera else if (navigator.userAgent.indexOf('Opera') >= 0) { func = opera11; } //Last one is Firefox //FF 18.x else if (window.devicePixelRatio) { func = firefox18; } //FF 4.0 - 17.x else if (firefox4().zoom > 0.001) { func = firefox4; } return func; }()); return ({ /** * Ratios.zoom shorthand * @return {Number} Zoom level */ zoom: function () { return detectFunction().zoom; }, /** * Ratios.devicePxPerCssPx shorthand * @return {Number} devicePxPerCssPx level */ device: function () { return detectFunction().devicePxPerCssPx; } }); })); var wpcom_img_zoomer = { clientHintSupport: { gravatar: false, files: false, photon: false, mshots: false, staticAssets: false, latex: false, imgpress: false, }, useHints: false, zoomed: false, timer: null, interval: 1000, // zoom polling interval in millisecond // Should we apply width/height attributes to control the image size? imgNeedsSizeAtts: function( img ) { // Do not overwrite existing width/height attributes. if ( img.getAttribute('width') !== null || img.getAttribute('height') !== null ) return false; // Do not apply the attributes if the image is already constrained by a parent element. if ( img.width < img.naturalWidth || img.height < img.naturalHeight ) return false; return true; }, hintsFor: function( service ) { if ( this.useHints === false ) { return false; } if ( this.hints() === false ) { return false; } if ( typeof this.clientHintSupport[service] === "undefined" ) { return false; } if ( this.clientHintSupport[service] === true ) { return true; } return false; }, hints: function() { try { var chrome = window.navigator.userAgent.match(/\sChrome\/([0-9]+)\.[.0-9]+\s/) if (chrome !== null) { var version = parseInt(chrome[1], 10) if (isNaN(version) === false && version >= 46) { return true } } } catch (e) { return false } return false }, init: function() { var t = this; try{ t.zoomImages(); t.timer = setInterval( function() { t.zoomImages(); }, t.interval ); } catch(e){ } }, stop: function() { if ( this.timer ) clearInterval( this.timer ); }, getScale: function() { var scale = detectZoom.device(); // Round up to 1.5 or the next integer below the cap. if ( scale <= 1.0 ) scale = 1.0; else if ( scale <= 1.5 ) scale = 1.5; else if ( scale <= 2.0 ) scale = 2.0; else if ( scale <= 3.0 ) scale = 3.0; else if ( scale <= 4.0 ) scale = 4.0; else scale = 5.0; return scale; }, shouldZoom: function( scale ) { var t = this; // Do not operate on hidden frames. if ( "innerWidth" in window && !window.innerWidth ) return false; // Don't do anything until scale > 1 if ( scale == 1.0 && t.zoomed == false ) return false; return true; }, zoomImages: function() { var t = this; var scale = t.getScale(); if ( ! t.shouldZoom( scale ) ){ return; } t.zoomed = true; // Loop through all the elements on the page. var imgs = document.getElementsByTagName("img"); for ( var i = 0; i < imgs.length; i++ ) { // Wait for original images to load if ( "complete" in imgs[i] && ! imgs[i].complete ) continue; // Skip images that have srcset attributes. if ( imgs[i].hasAttribute('srcset') ) { continue; } // Skip images that don't need processing. var imgScale = imgs[i].getAttribute("scale"); if ( imgScale == scale || imgScale == "0" ) continue; // Skip images that have already failed at this scale var scaleFail = imgs[i].getAttribute("scale-fail"); if ( scaleFail && scaleFail <= scale ) continue; // Skip images that have no dimensions yet. if ( ! ( imgs[i].width && imgs[i].height ) ) continue; // Skip images from Lazy Load plugins if ( ! imgScale && imgs[i].getAttribute("data-lazy-src") && (imgs[i].getAttribute("data-lazy-src") !== imgs[i].getAttribute("src"))) continue; if ( t.scaleImage( imgs[i], scale ) ) { // Mark the img as having been processed at this scale. imgs[i].setAttribute("scale", scale); } else { // Set the flag to skip this image. imgs[i].setAttribute("scale", "0"); } } }, scaleImage: function( img, scale ) { var t = this; var newSrc = img.src; var isFiles = false; var isLatex = false; var isPhoton = false; // Skip slideshow images if ( img.parentNode.className.match(/slideshow-slide/) ) return false; // Skip CoBlocks Lightbox images if ( img.parentNode.className.match(/coblocks-lightbox__image/) ) return false; // Scale gravatars that have ?s= or ?size= if ( img.src.match( /^https?:\/\/([^\/]*\.)?gravatar\.com\/.+[?&](s|size)=/ ) ) { if ( this.hintsFor( "gravatar" ) === true ) { return false; } newSrc = img.src.replace( /([?&](s|size)=)(\d+)/, function( $0, $1, $2, $3 ) { // Stash the original size var originalAtt = "originals", originalSize = img.getAttribute(originalAtt); if ( originalSize === null ) { originalSize = $3; img.setAttribute(originalAtt, originalSize); if ( t.imgNeedsSizeAtts( img ) ) { // Fix width and height attributes to rendered dimensions. img.width = img.width; img.height = img.height; } } // Get the width/height of the image in CSS pixels var size = img.clientWidth; // Convert CSS pixels to device pixels var targetSize = Math.ceil(img.clientWidth * scale); // Don't go smaller than the original size targetSize = Math.max( targetSize, originalSize ); // Don't go larger than the service supports targetSize = Math.min( targetSize, 512 ); return $1 + targetSize; }); } // Scale mshots that have width else if ( img.src.match(/^https?:\/\/([^\/]+\.)*(wordpress|wp)\.com\/mshots\/.+[?&]w=\d+/) ) { if ( this.hintsFor( "mshots" ) === true ) { return false; } newSrc = img.src.replace( /([?&]w=)(\d+)/, function($0, $1, $2) { // Stash the original size var originalAtt = 'originalw', originalSize = img.getAttribute(originalAtt); if ( originalSize === null ) { originalSize = $2; img.setAttribute(originalAtt, originalSize); if ( t.imgNeedsSizeAtts( img ) ) { // Fix width and height attributes to rendered dimensions. img.width = img.width; img.height = img.height; } } // Get the width of the image in CSS pixels var size = img.clientWidth; // Convert CSS pixels to device pixels var targetSize = Math.ceil(size * scale); // Don't go smaller than the original size targetSize = Math.max( targetSize, originalSize ); // Don't go bigger unless the current one is actually lacking if ( scale > img.getAttribute("scale") && targetSize <= img.naturalWidth ) targetSize = $2; if ( $2 != targetSize ) return $1 + targetSize; return $0; }); // Update height attribute to match width newSrc = newSrc.replace( /([?&]h=)(\d+)/, function($0, $1, $2) { if ( newSrc == img.src ) { return $0; } // Stash the original size var originalAtt = 'originalh', originalSize = img.getAttribute(originalAtt); if ( originalSize === null ) { originalSize = $2; img.setAttribute(originalAtt, originalSize); } // Get the height of the image in CSS pixels var size = img.clientHeight; // Convert CSS pixels to device pixels var targetSize = Math.ceil(size * scale); // Don't go smaller than the original size targetSize = Math.max( targetSize, originalSize ); // Don't go bigger unless the current one is actually lacking if ( scale > img.getAttribute("scale") && targetSize <= img.naturalHeight ) targetSize = $2; if ( $2 != targetSize ) return $1 + targetSize; return $0; }); } // Scale simple imgpress queries (s0.wp.com) that only specify w/h/fit else if ( img.src.match(/^https?:\/\/([^\/.]+\.)*(wp|wordpress)\.com\/imgpress\?(.+)/) ) { if ( this.hintsFor( "imgpress" ) === true ) { return false; } var imgpressSafeFunctions = ["zoom", "url", "h", "w", "fit", "filter", "brightness", "contrast", "colorize", "smooth", "unsharpmask"]; // Search the query string for unsupported functions. var qs = RegExp.$3.split('&'); for ( var q in qs ) { q = qs[q].split('=')[0]; if ( imgpressSafeFunctions.indexOf(q) == -1 ) { return false; } } // Fix width and height attributes to rendered dimensions. img.width = img.width; img.height = img.height; // Compute new src if ( scale == 1 ) newSrc = img.src.replace(/\?(zoom=[^&]+&)?/, '?'); else newSrc = img.src.replace(/\?(zoom=[^&]+&)?/, '?zoom=' + scale + '&'); } // Scale files.wordpress.com, LaTeX, or Photon images (i#.wp.com) else if ( ( isFiles = img.src.match(/^https?:\/\/([^\/]+)\.files\.wordpress\.com\/.+[?&][wh]=/) ) || ( isLatex = img.src.match(/^https?:\/\/([^\/.]+\.)*(wp|wordpress)\.com\/latex\.php\?(latex|zoom)=(.+)/) ) || ( isPhoton = img.src.match(/^https?:\/\/i[\d]{1}\.wp\.com\/(.+)/) ) ) { if ( false !== isFiles && this.hintsFor( "files" ) === true ) { return false } if ( false !== isLatex && this.hintsFor( "latex" ) === true ) { return false } if ( false !== isPhoton && this.hintsFor( "photon" ) === true ) { return false } // Fix width and height attributes to rendered dimensions. img.width = img.width; img.height = img.height; // Compute new src if ( scale == 1 ) { newSrc = img.src.replace(/\?(zoom=[^&]+&)?/, '?'); } else { newSrc = img.src; var url_var = newSrc.match( /([?&]w=)(\d+)/ ); if ( url_var !== null && url_var[2] ) { newSrc = newSrc.replace( url_var[0], url_var[1] + img.width ); } url_var = newSrc.match( /([?&]h=)(\d+)/ ); if ( url_var !== null && url_var[2] ) { newSrc = newSrc.replace( url_var[0], url_var[1] + img.height ); } var zoom_arg = '&zoom=2'; if ( !newSrc.match( /\?/ ) ) { zoom_arg = '?zoom=2'; } img.setAttribute( 'srcset', newSrc + zoom_arg + ' ' + scale + 'x' ); } } // Scale static assets that have a name matching *-1x.png or *@1x.png else if ( img.src.match(/^https?:\/\/[^\/]+\/.*[-@]([12])x\.(gif|jpeg|jpg|png)(\?|$)/) ) { if ( this.hintsFor( "staticAssets" ) === true ) { return false; } // Fix width and height attributes to rendered dimensions. img.width = img.width; img.height = img.height; var currentSize = RegExp.$1, newSize = currentSize; if ( scale <= 1 ) newSize = 1; else newSize = 2; if ( currentSize != newSize ) newSrc = img.src.replace(/([-@])[12]x\.(gif|jpeg|jpg|png)(\?|$)/, '$1'+newSize+'x.$2$3'); } else { return false; } // Don't set img.src unless it has changed. This avoids unnecessary reloads. if ( newSrc != img.src ) { // Store the original img.src var prevSrc, origSrc = img.getAttribute("src-orig"); if ( !origSrc ) { origSrc = img.src; img.setAttribute("src-orig", origSrc); } // In case of error, revert img.src prevSrc = img.src; img.onerror = function(){ img.src = prevSrc; if ( img.getAttribute("scale-fail") < scale ) img.setAttribute("scale-fail", scale); img.onerror = null; }; // Finally load the new image img.src = newSrc; } return true; } }; wpcom_img_zoomer.init(); ; /* globals infiniteScroll, _wpmejsSettings, ga, _gaq, WPCOM_sharing_counts, MediaElementPlayer */ ( function () { // Open closure. // Local vars. var Scroller, ajaxurl, stats, type, text, totop, loading_text; // IE requires special handling var isIE = -1 != navigator.userAgent.search( 'MSIE' ); if ( isIE ) { var IEVersion = navigator.userAgent.match( /MSIE\s?(\d+)\.?\d*;/ ); IEVersion = parseInt( IEVersion[ 1 ] ); } // HTTP ajaxurl when site is HTTPS causes Access-Control-Allow-Origin failure in Desktop and iOS Safari if ( 'https:' == document.location.protocol ) { infiniteScroll.settings.ajaxurl = infiniteScroll.settings.ajaxurl.replace( 'http://', 'https://' ); } /** * Loads new posts when users scroll near the bottom of the page. */ Scroller = function ( settings ) { var self = this; // Initialize our variables this.id = settings.id; this.body = document.body; this.window = window; this.element = document.getElementById( settings.id ); this.wrapperClass = settings.wrapper_class; this.ready = true; this.disabled = false; this.page = 1; this.offset = settings.offset; this.currentday = settings.currentday; this.order = settings.order; this.throttle = false; this.click_handle = settings.click_handle; this.google_analytics = settings.google_analytics; this.history = settings.history; this.origURL = window.location.href; // Handle element this.handle = document.createElement( 'div' ); this.handle.setAttribute( 'id', 'infinite-handle' ); this.handle.innerHTML = ''; // Footer settings this.footer = { el: document.getElementById( 'infinite-footer' ), wrap: settings.footer, }; // Bind methods used as callbacks this.checkViewportOnLoadBound = self.checkViewportOnLoad.bind( this ); // Core's native MediaElement.js implementation needs special handling this.wpMediaelement = null; // We have two type of infinite scroll // cases 'scroll' and 'click' if ( type == 'scroll' ) { // Bind refresh to the scroll event // Throttle to check for such case every 300ms // On event the case becomes a fact this.window.addEventListener( 'scroll', function () { self.throttle = true; } ); // Go back top method self.gotop(); setInterval( function () { if ( self.throttle ) { // Once the case is the case, the action occurs and the fact is no more self.throttle = false; // Reveal or hide footer self.thefooter(); // Fire the refresh self.refresh(); self.determineURL(); // determine the url } }, 250 ); // Ensure that enough posts are loaded to fill the initial viewport, to compensate for short posts and large displays. self.ensureFilledViewport(); this.body.addEventListener( 'is.post-load', self.checkViewportOnLoadBound ); } else if ( type == 'click' ) { if ( this.click_handle ) { this.element.appendChild( this.handle ); } this.handle.addEventListener( 'click', function () { // Handle the handle if ( self.click_handle ) { self.handle.parentNode.removeChild( self.handle ); } // Fire the refresh self.refresh(); } ); } // Initialize any Core audio or video players loaded via IS this.body.addEventListener( 'is.post-load', self.initializeMejs ); }; /** * Normalize the access to the document scrollTop value. */ Scroller.prototype.getScrollTop = function () { return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; }; /** * Polyfill jQuery.extend. */ Scroller.prototype.extend = function ( out ) { out = out || {}; for ( var i = 1; i < arguments.length; i++ ) { if ( ! arguments[ i ] ) { continue; } for ( var key in arguments[ i ] ) { if ( arguments[ i ].hasOwnProperty( key ) ) { out[ key ] = arguments[ i ][ key ]; } } } return out; }; /** * Check whether we should fetch any additional posts. */ Scroller.prototype.check = function () { var wrapperMeasurements = this.measure( this.element, [ this.wrapperClass ] ); // Fetch more posts when we're less than 2 screens away from the bottom. return wrapperMeasurements.bottom < 2 * this.window.innerHeight; }; /** * Renders the results from a successful response. */ Scroller.prototype.render = function ( response ) { var childrenToAppend = Array.prototype.slice.call( response.fragment.childNodes ); this.body.classList.add( 'infinity-success' ); // Render the retrieved nodes. while ( childrenToAppend.length > 0 ) { var currentNode = childrenToAppend.shift(); this.element.appendChild( currentNode ); } this.trigger( this.body, 'is.post-load', { jqueryEventName: 'post-load', data: response, } ); this.ready = true; }; /** * Returns the object used to query for new posts. */ Scroller.prototype.query = function () { return { page: this.page + this.offset, // Load the next page. currentday: this.currentday, order: this.order, scripts: window.infiniteScroll.settings.scripts, styles: window.infiniteScroll.settings.styles, query_args: window.infiniteScroll.settings.query_args, query_before: window.infiniteScroll.settings.query_before, last_post_date: window.infiniteScroll.settings.last_post_date, }; }; Scroller.prototype.animate = function ( cb, duration ) { var start = performance.now(); requestAnimationFrame( function animate( time ) { var timeFraction = Math.min( 1, ( time - start ) / duration ); cb( timeFraction ); if ( timeFraction < 1 ) { requestAnimationFrame( animate ); } } ); }; /** * Scroll back to top. */ Scroller.prototype.gotop = function () { var blog = document.getElementById( 'infinity-blog-title' ); var self = this; if ( ! blog ) { return; } blog.setAttribute( 'title', totop ); blog.addEventListener( 'click', function ( e ) { var sourceScroll = self.window.pageYOffset; e.preventDefault(); self.animate( function ( progress ) { var currentScroll = sourceScroll - sourceScroll * progress; document.documentElement.scrollTop = document.body.scrollTop = currentScroll; }, 200 ); } ); }; /** * The infinite footer. */ Scroller.prototype.thefooter = function () { var self = this, pageWrapper, footerContainer, width, sourceBottom, targetBottom, footerEnabled = this.footer && this.footer.el; if ( ! footerEnabled ) { return; } // Check if we have an id for the page wrapper if ( 'string' === typeof this.footer.wrap ) { try { pageWrapper = document.getElementById( this.footer.wrap ); width = pageWrapper.getBoundingClientRect(); width = width.width; } catch ( err ) { width = 0; } // Make the footer match the width of the page if ( width > 479 ) { footerContainer = this.footer.el.querySelector( '.container' ); if ( footerContainer ) { footerContainer.style.width = width + 'px'; } } } // Reveal footer sourceBottom = parseInt( self.footer.el.style.bottom || -50, 10 ); targetBottom = this.window.pageYOffset >= 350 ? 0 : -50; if ( sourceBottom !== targetBottom ) { self.animate( function ( progress ) { var currentBottom = sourceBottom + ( targetBottom - sourceBottom ) * progress; self.footer.el.style.bottom = currentBottom + 'px'; if ( 1 === progress ) { sourceBottom = targetBottom; } }, 200 ); } }; /** * Recursively convert a JS object into URL encoded data. */ Scroller.prototype.urlEncodeJSON = function ( obj, prefix ) { var params = [], encodedKey, newPrefix; for ( var key in obj ) { encodedKey = encodeURIComponent( key ); newPrefix = prefix ? prefix + '[' + encodedKey + ']' : encodedKey; if ( 'object' === typeof obj[ key ] ) { if ( ! Array.isArray( obj[ key ] ) || obj[ key ].length > 0 ) { params.push( this.urlEncodeJSON( obj[ key ], newPrefix ) ); } else { // Explicitly expose empty arrays with no values params.push( newPrefix + '[]=' ); } } else { params.push( newPrefix + '=' + encodeURIComponent( obj[ key ] ) ); } } return params.join( '&' ); }; /** * Controls the flow of the refresh. Don't mess. */ Scroller.prototype.refresh = function () { var self = this, query, xhr, loader, customized; // If we're disabled, ready, or don't pass the check, bail. if ( this.disabled || ! this.ready || ! this.check() ) { return; } // Let's get going -- set ready to false to prevent // multiple refreshes from occurring at once. this.ready = false; // Create a loader element to show it's working. if ( this.click_handle ) { if ( ! loader ) { document.getElementById( 'infinite-aria' ).textContent = loading_text; loader = document.createElement( 'div' ); loader.classList.add( 'infinite-loader' ); loader.setAttribute( 'role', 'progress' ); loader.innerHTML = '
'; } this.element.appendChild( loader ); } // Generate our query vars. query = self.extend( { action: 'infinite_scroll', }, this.query() ); // Inject Customizer state. if ( 'undefined' !== typeof wp && wp.customize && wp.customize.settings.theme ) { customized = {}; query.wp_customize = 'on'; query.theme = wp.customize.settings.theme.stylesheet; wp.customize.each( function ( setting ) { if ( setting._dirty ) { customized[ setting.id ] = setting(); } } ); query.customized = JSON.stringify( customized ); query.nonce = wp.customize.settings.nonce.preview; } // Fire the ajax request. xhr = new XMLHttpRequest(); xhr.open( 'POST', infiniteScroll.settings.ajaxurl, true ); xhr.setRequestHeader( 'X-Requested-With', 'XMLHttpRequest' ); xhr.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8' ); xhr.send( self.urlEncodeJSON( query ) ); // Allow refreshes to occur again if an error is triggered. xhr.onerror = function () { if ( self.click_handle && loader.parentNode ) { loader.parentNode.removeChild( loader ); } self.ready = true; }; // Success handler xhr.onload = function () { var response = JSON.parse( xhr.responseText ), httpCheck = xhr.status >= 200 && xhr.status < 300, responseCheck = 'undefined' !== typeof response.html; if ( ! response || ! httpCheck || ! responseCheck ) { if ( self.click_handle && loader.parentNode ) { loader.parentNode.removeChild( loader ); } return; } // On success, let's hide the loader circle. if ( self.click_handle && loader.parentNode ) { loader.parentNode.removeChild( loader ); } // If additional scripts are required by the incoming set of posts, parse them if ( response.scripts && Array.isArray( response.scripts ) ) { response.scripts.forEach( function ( item ) { var elementToAppendTo = item.footer ? 'body' : 'head'; // Add script handle to list of those already parsed window.infiniteScroll.settings.scripts.push( item.handle ); // Output extra data, if present if ( item.extra_data ) { self.appendInlineScript( item.extra_data, elementToAppendTo ); } if ( item.before_handle ) { self.appendInlineScript( item.before_handle, elementToAppendTo ); } // Build script tag and append to DOM in requested location var script = document.createElement( 'script' ); script.type = 'text/javascript'; script.src = item.src; script.id = item.handle; // Dynamically loaded scripts are async by default. // We don't want that, it breaks stuff, e.g. wp-mediaelement init. script.async = false; if ( item.after_handle ) { script.onload = function () { self.appendInlineScript( item.after_handle, elementToAppendTo ); }; } // If MediaElement.js is loaded in by item set of posts, don't initialize the players a second time as it breaks them all if ( 'wp-mediaelement' === item.handle ) { self.body.removeEventListener( 'is.post-load', self.initializeMejs ); } if ( 'wp-mediaelement' === item.handle && 'undefined' === typeof mejs ) { self.wpMediaelement = {}; self.wpMediaelement.tag = script; self.wpMediaelement.element = elementToAppendTo; setTimeout( self.maybeLoadMejs.bind( self ), 250 ); } else { document.getElementsByTagName( elementToAppendTo )[ 0 ].appendChild( script ); } } ); } // If additional stylesheets are required by the incoming set of posts, parse them if ( response.styles && Array.isArray( response.styles ) ) { response.styles.forEach( function ( item ) { // Add stylesheet handle to list of those already parsed window.infiniteScroll.settings.styles.push( item.handle ); // Build link tag var style = document.createElement( 'link' ); style.rel = 'stylesheet'; style.href = item.src; style.id = item.handle + '-css'; // Destroy link tag if a conditional statement is present and either the browser isn't IE, or the conditional doesn't evaluate true if ( item.conditional && ( ! isIE || ! eval( item.conditional.replace( /%ver/g, IEVersion ) ) ) ) { style = false; } // Append link tag if necessary if ( style ) { document.getElementsByTagName( 'head' )[ 0 ].appendChild( style ); } } ); } // Convert the response.html to a fragment element. // Using a div instead of DocumentFragment, because the latter doesn't support innerHTML. response.fragment = document.createElement( 'div' ); response.fragment.innerHTML = response.html; // Increment the page number self.page++; // Record pageview in WP Stats, if available. if ( stats ) { new Image().src = document.location.protocol + '//pixel.wp.com/g.gif?' + stats + '&post=0&baba=' + Math.random(); } // Add new posts to the postflair object if ( 'object' === typeof response.postflair && 'object' === typeof WPCOM_sharing_counts ) { WPCOM_sharing_counts = self.extend( WPCOM_sharing_counts, response.postflair ); // eslint-disable-line no-global-assign } // Render the results self.render.call( self, response ); // If 'click' type and there are still posts to fetch, add back the handle if ( type == 'click' ) { // add focus to new posts, only in button mode as we know where page focus currently is and only if we have a wrapper if ( infiniteScroll.settings.wrapper ) { document .querySelector( '#infinite-view-' + ( self.page + self.offset - 1 ) + ' a:first-of-type' ) .focus( { preventScroll: true, } ); } if ( response.lastbatch ) { if ( self.click_handle ) { // Update body classes self.body.classList.add( 'infinity-end' ); self.body.classList.remove( 'infinity-success' ); } else { self.trigger( this.body, 'infinite-scroll-posts-end' ); } } else { if ( self.click_handle ) { self.element.appendChild( self.handle ); } else { self.trigger( this.body, 'infinite-scroll-posts-more' ); } } } else if ( response.lastbatch ) { self.disabled = true; self.body.classList.add( 'infinity-end' ); self.body.classList.remove( 'infinity-success' ); } // Update currentday to the latest value returned from the server if ( response.currentday ) { self.currentday = response.currentday; } // Fire Google Analytics pageview if ( self.google_analytics ) { var ga_url = self.history.path.replace( /%d/, self.page ); if ( 'object' === typeof _gaq ) { _gaq.push( [ '_trackPageview', ga_url ] ); } if ( 'function' === typeof ga ) { ga( 'send', 'pageview', ga_url ); } } }; return xhr; }; /** * Given JavaScript blob and the name of a parent tag, this helper function will * generate a script tag, insert the JavaScript blob, and append it to the parent. * * It's important to note that the JavaScript blob will be evaluated immediately. If * you need a parent script to load first, use that script element's onload handler. * * @param {string} script The blob of JavaScript to run. * @param {string} parentTag The tag name of the parent element. */ Scroller.prototype.appendInlineScript = function ( script, parentTag ) { var element = document.createElement( 'script' ), scriptContent = document.createTextNode( '//' ); element.type = 'text/javascript'; element.appendChild( scriptContent ); document.getElementsByTagName( parentTag )[ 0 ].appendChild( element ); }; /** * Core's native media player uses MediaElement.js * The library's size is sufficient that it may not be loaded in time for Core's helper to invoke it, so we need to delay until `mejs` exists. */ Scroller.prototype.maybeLoadMejs = function () { if ( null === this.wpMediaelement ) { return; } if ( 'undefined' === typeof mejs ) { setTimeout( this.maybeLoadMejs.bind( this ), 250 ); } else { document .getElementsByTagName( this.wpMediaelement.element )[ 0 ] .appendChild( this.wpMediaelement.tag ); this.wpMediaelement = null; // Ensure any subsequent IS loads initialize the players this.body.addEventListener( 'is.post-load', this.initializeMejs ); } }; /** * Initialize the MediaElement.js player for any posts not previously initialized */ Scroller.prototype.initializeMejs = function ( e ) { // Are there media players in the incoming set of posts? if ( ! e.detail || ! e.detail.html || ( -1 === e.detail.html.indexOf( 'wp-audio-shortcode' ) && -1 === e.detail.html.indexOf( 'wp-video-shortcode' ) ) ) { return; } // Don't bother if mejs isn't loaded for some reason if ( 'undefined' === typeof mejs ) { return; } // Adapted from wp-includes/js/mediaelement/wp-mediaelement.js // Modified to not initialize already-initialized players, as Mejs doesn't handle that well var settings = {}; var audioVideoElements; if ( typeof _wpmejsSettings !== 'undefined' ) { settings.pluginPath = _wpmejsSettings.pluginPath; } settings.success = function ( mejs ) { var autoplay = mejs.attributes.autoplay && 'false' !== mejs.attributes.autoplay; if ( 'flash' === mejs.pluginType && autoplay ) { mejs.addEventListener( 'canplay', function () { mejs.play(); }, false ); } }; audioVideoElements = document.querySelectorAll( '.wp-audio-shortcode, .wp-video-shortcode' ); audioVideoElements = Array.prototype.slice.call( audioVideoElements ); // Only process already unprocessed shortcodes. audioVideoElements = audioVideoElements.filter( function ( el ) { while ( el.parentNode ) { if ( el.classList.contains( 'mejs-container' ) ) { return false; } el = el.parentNode; } return true; } ); for ( var i = 0; i < audioVideoElements.length; i++ ) { new MediaElementPlayer( audioVideoElements[ i ], settings ); } }; /** * Get element measurements relative to the viewport. * * @returns {object} */ Scroller.prototype.measure = function ( element, expandClasses ) { expandClasses = expandClasses || []; var childrenToTest = Array.prototype.slice.call( element.children ); var currentChild, minTop = Number.MAX_VALUE, maxBottom = 0, currentChildRect, i; while ( childrenToTest.length > 0 ) { currentChild = childrenToTest.shift(); for ( i = 0; i < expandClasses.length; i++ ) { // Expand (= measure) child elements of nodes with class names from expandClasses. if ( currentChild.classList.contains( expandClasses[ i ] ) ) { childrenToTest = childrenToTest.concat( Array.prototype.slice.call( currentChild.children ) ); break; } } currentChildRect = currentChild.getBoundingClientRect(); minTop = Math.min( minTop, currentChildRect.top ); maxBottom = Math.max( maxBottom, currentChildRect.bottom ); } var viewportMiddle = Math.round( window.innerHeight / 2 ); // isActive = does the middle of the viewport cross the element? var isActive = minTop <= viewportMiddle && maxBottom >= viewportMiddle; /** * Factor = percentage of viewport above the middle line occupied by the element. * * Negative factors are assigned for elements below the middle line. That's on purpose * to only allow "page 2" to change the URL once it's in the middle of the viewport. */ var factor = ( Math.min( maxBottom, viewportMiddle ) - Math.max( minTop, 0 ) ) / viewportMiddle; return { top: minTop, bottom: maxBottom, height: maxBottom - minTop, factor: factor, isActive: isActive, }; }; /** * Trigger IS to load additional posts if the initial posts don't fill the window. * * On large displays, or when posts are very short, the viewport may not be filled with posts, * so we overcome this by loading additional posts when IS initializes. */ Scroller.prototype.ensureFilledViewport = function () { var self = this, windowHeight = self.window.innerHeight, wrapperMeasurements = self.measure( self.element, [ self.wrapperClass ] ); // Only load more posts once. This prevents infinite loops when there are no more posts. self.body.removeEventListener( 'is.post-load', self.checkViewportOnLoadBound ); // Load more posts if space permits, otherwise stop checking for a full viewport. if ( wrapperMeasurements.bottom !== 0 && wrapperMeasurements.bottom < windowHeight ) { self.ready = true; self.refresh(); } }; /** * Event handler for ensureFilledViewport(), tied to the post-load trigger. * Necessary to ensure that the variable `this` contains the scroller when used in ensureFilledViewport(). Since this function is tied to an event, `this` becomes the DOM element the event is tied to. */ Scroller.prototype.checkViewportOnLoad = function () { this.ensureFilledViewport(); }; function fullscreenState() { return document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement ? 1 : 0; } var previousFullScrenState = fullscreenState(); /** * Identify archive page that corresponds to majority of posts shown in the current browser window. */ Scroller.prototype.determineURL = function () { var self = this, pageNum = -1, currentFullScreenState = fullscreenState(), wrapperEls, maxFactor = 0; // xor - check if the state has changed if ( previousFullScrenState ^ currentFullScreenState ) { // If we just switched to/from fullscreen, // don't do the div clearing/caching or the // URL setting. Doing so can break video playback // if the video goes to fullscreen. previousFullScrenState = currentFullScreenState; return; } previousFullScrenState = currentFullScreenState; wrapperEls = document.querySelectorAll( '.' + self.wrapperClass ); for ( var i = 0; i < wrapperEls.length; i++ ) { var setMeasurements = self.measure( wrapperEls[ i ] ); // If it exists, pick a set that is crossed by the middle of the viewport. if ( setMeasurements.isActive ) { pageNum = parseInt( wrapperEls[ i ].dataset.pageNum, 10 ); break; } // If there is such a set, pick the one that occupies the most space // above the middle of the viewport. if ( setMeasurements.factor > maxFactor ) { pageNum = parseInt( wrapperEls[ i ].dataset.pageNum, 10 ); maxFactor = setMeasurements.factor; } // Otherwise default to -1 } self.updateURL( pageNum ); }; /** * Update address bar to reflect archive page URL for a given page number. * Checks if URL is different to prevent pollution of browser history. */ Scroller.prototype.updateURL = function ( page ) { // IE only supports pushState() in v10 and above, so don't bother if those conditions aren't met. if ( ! window.history.pushState ) { return; } var self = this, pageSlug = self.origURL; if ( -1 !== page ) { pageSlug = window.location.protocol + '//' + self.history.host + self.history.path.replace( /%d/, page ) + self.history.parameters; } if ( window.location.href != pageSlug ) { history.pushState( null, null, pageSlug ); } }; /** * Pause scrolling. */ Scroller.prototype.pause = function () { this.disabled = true; }; /** * Resume scrolling. */ Scroller.prototype.resume = function () { this.disabled = false; }; /** * Emits custom JS events. * * @param {Node} el * @param {string} eventName * @param {*} data */ Scroller.prototype.trigger = function ( el, eventName, opts ) { opts = opts || {}; /** * Emit the event in a jQuery way for backwards compatibility where necessary. */ if ( opts.jqueryEventName && 'undefined' !== typeof jQuery ) { jQuery( el ).trigger( opts.jqueryEventName, opts.data || null ); } /** * Emit the event in a standard way. */ var e; try { e = new CustomEvent( eventName, { bubbles: true, cancelable: true, detail: opts.data || null, } ); } catch ( err ) { e = document.createEvent( 'CustomEvent' ); e.initCustomEvent( eventName, true, true, opts.data || null ); } el.dispatchEvent( e ); }; /** * Ready, set, go! */ var jetpackInfinityModule = function () { var bodyClasses = infiniteScroll.settings.body_class.split( ' ' ); // Check for our variables if ( 'object' !== typeof infiniteScroll ) { return; } bodyClasses.forEach( function ( className ) { if ( className ) { document.body.classList.add( className ); } } ); // Set ajaxurl (for brevity) ajaxurl = infiniteScroll.settings.ajaxurl; // Set stats, used for tracking stats stats = infiniteScroll.settings.stats; // Define what type of infinity we have, grab text for click-handle type = infiniteScroll.settings.type; text = infiniteScroll.settings.text; totop = infiniteScroll.settings.totop; // aria text loading_text = infiniteScroll.settings.loading_text; // Initialize the scroller (with the ID of the element from the theme) infiniteScroll.scroller = new Scroller( infiniteScroll.settings ); /** * Monitor user scroll activity to update URL to correspond to archive page for current set of IS posts */ if ( type == 'click' ) { var timer = null; window.addEventListener( 'scroll', function () { // run the real scroll handler once every 250 ms. if ( timer ) { return; } timer = setTimeout( function () { infiniteScroll.scroller.determineURL(); timer = null; }, 250 ); } ); } }; /** * Ready, set, go! */ if ( document.readyState === 'interactive' || document.readyState === 'complete' ) { jetpackInfinityModule(); } else { document.addEventListener( 'DOMContentLoaded', jetpackInfinityModule ); } } )(); // Close closure ; (function() { var AjaxMonitor, Bar, DocumentMonitor, ElementMonitor, ElementTracker, EventLagMonitor, Evented, Events, NoTargetError, Pace, RequestIntercept, SOURCE_KEYS, Scaler, SocketRequestTracker, XHRRequestTracker, animation, avgAmplitude, bar, cancelAnimation, cancelAnimationFrame, defaultOptions, extend, extendNative, getFromDOM, getIntercept, handlePushState, ignoreStack, init, now, options, requestAnimationFrame, result, runAnimation, scalers, shouldIgnoreURL, shouldTrack, source, sources, uniScaler, _WebSocket, _XDomainRequest, _XMLHttpRequest, _i, _intercept, _len, _pushState, _ref, _ref1, _replaceState, __slice = [].slice, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; defaultOptions = { catchupTime: 500, initialRate: .03, minTime: 500, ghostTime: 500, maxProgressPerFrame: 10, easeFactor: 1.25, startOnPageLoad: true, restartOnPushState: false, restartOnRequestAfter: false, target: 'body', elements: { checkInterval: 100, selectors: ['body'] }, eventLag: { minSamples: 10, sampleCount: 3, lagThreshold: 3 }, ajax: { trackMethods: ['GET'], trackWebSockets: true, ignoreURLs: [] } }; now = function() { var _ref; return (_ref = typeof performance !== "undefined" && performance !== null ? typeof performance.now === "function" ? performance.now() : void 0 : void 0) != null ? _ref : +(new Date); }; requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame; if (requestAnimationFrame == null) { requestAnimationFrame = function(fn) { return setTimeout(fn, 50); }; cancelAnimationFrame = function(id) { return clearTimeout(id); }; } runAnimation = function(fn) { var last, tick; last = now(); tick = function() { var diff; diff = now() - last; if (diff >= 33) { last = now(); return fn(diff, function() { return requestAnimationFrame(tick); }); } else { return setTimeout(tick, 33 - diff); } }; return tick(); }; result = function() { var args, key, obj; obj = arguments[0], key = arguments[1], args = 3 <= arguments.length ? __slice.call(arguments, 2) : []; if (typeof obj[key] === 'function') { return obj[key].apply(obj, args); } else { return obj[key]; } }; extend = function() { var key, out, source, sources, val, _i, _len; out = arguments[0], sources = 2 <= arguments.length ? __slice.call(arguments, 1) : []; for (_i = 0, _len = sources.length; _i < _len; _i++) { source = sources[_i]; if (source) { for (key in source) { if (!__hasProp.call(source, key)) continue; val = source[key]; if ((out[key] != null) && typeof out[key] === 'object' && (val != null) && typeof val === 'object') { extend(out[key], val); } else { out[key] = val; } } } } return out; }; avgAmplitude = function(arr) { var count, sum, v, _i, _len; sum = count = 0; for (_i = 0, _len = arr.length; _i < _len; _i++) { v = arr[_i]; sum += Math.abs(v); count++; } return sum / count; }; getFromDOM = function(key, json) { var data, e, el; if (key == null) { key = 'options'; } if (json == null) { json = true; } el = document.querySelector("[data-pace-" + key + "]"); if (!el) { return; } data = el.getAttribute("data-pace-" + key); if (!json) { return data; } try { return JSON.parse(data); } catch (_error) { e = _error; return typeof console !== "undefined" && console !== null ? console.error("Error parsing inline pace options", e) : void 0; } }; Evented = (function() { function Evented() {} Evented.prototype.on = function(event, handler, ctx, once) { var _base; if (once == null) { once = false; } if (this.bindings == null) { this.bindings = {}; } if ((_base = this.bindings)[event] == null) { _base[event] = []; } return this.bindings[event].push({ handler: handler, ctx: ctx, once: once }); }; Evented.prototype.once = function(event, handler, ctx) { return this.on(event, handler, ctx, true); }; Evented.prototype.off = function(event, handler) { var i, _ref, _results; if (((_ref = this.bindings) != null ? _ref[event] : void 0) == null) { return; } if (handler == null) { return delete this.bindings[event]; } else { i = 0; _results = []; while (i < this.bindings[event].length) { if (this.bindings[event][i].handler === handler) { _results.push(this.bindings[event].splice(i, 1)); } else { _results.push(i++); } } return _results; } }; Evented.prototype.trigger = function() { var args, ctx, event, handler, i, once, _ref, _ref1, _results; event = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; if ((_ref = this.bindings) != null ? _ref[event] : void 0) { i = 0; _results = []; while (i < this.bindings[event].length) { _ref1 = this.bindings[event][i], handler = _ref1.handler, ctx = _ref1.ctx, once = _ref1.once; handler.apply(ctx != null ? ctx : this, args); if (once) { _results.push(this.bindings[event].splice(i, 1)); } else { _results.push(i++); } } return _results; } }; return Evented; })(); Pace = window.Pace || {}; window.Pace = Pace; extend(Pace, Evented.prototype); options = Pace.options = extend({}, defaultOptions, window.paceOptions, getFromDOM()); _ref = ['ajax', 'document', 'eventLag', 'elements']; for (_i = 0, _len = _ref.length; _i < _len; _i++) { source = _ref[_i]; if (options[source] === true) { options[source] = defaultOptions[source]; } } NoTargetError = (function(_super) { __extends(NoTargetError, _super); function NoTargetError() { _ref1 = NoTargetError.__super__.constructor.apply(this, arguments); return _ref1; } return NoTargetError; })(Error); Bar = (function() { function Bar() { this.progress = 0; } Bar.prototype.getElement = function() { var targetElement; if (this.el == null) { targetElement = document.querySelector(options.target); if (!targetElement) { throw new NoTargetError; } this.el = document.createElement('div'); this.el.className = "pace pace-active"; document.body.className = document.body.className.replace(/pace-done/g, ''); document.body.className += ' pace-running'; this.el.innerHTML = '
\n
\n
\n
'; if (targetElement.firstChild != null) { targetElement.insertBefore(this.el, targetElement.firstChild); } else { targetElement.appendChild(this.el); } } return this.el; }; Bar.prototype.finish = function() { var el; el = this.getElement(); el.className = el.className.replace('pace-active', ''); el.className += ' pace-inactive'; document.body.className = document.body.className.replace('pace-running', ''); return document.body.className += ' pace-done'; }; Bar.prototype.update = function(prog) { this.progress = prog; return this.render(); }; Bar.prototype.destroy = function() { try { this.getElement().parentNode.removeChild(this.getElement()); } catch (_error) { NoTargetError = _error; } return this.el = void 0; }; Bar.prototype.render = function() { var el, key, progressStr, transform, _j, _len1, _ref2; if (document.querySelector(options.target) == null) { return false; } el = this.getElement(); transform = "translate3d(" + this.progress + "%, 0, 0)"; _ref2 = ['webkitTransform', 'msTransform', 'transform']; for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { key = _ref2[_j]; el.children[0].style[key] = transform; } if (!this.lastRenderedProgress || this.lastRenderedProgress | 0 !== this.progress | 0) { el.children[0].setAttribute('data-progress-text', "" + (this.progress | 0) + "%"); if (this.progress >= 100) { progressStr = '99'; } else { progressStr = this.progress < 10 ? "0" : ""; progressStr += this.progress | 0; } el.children[0].setAttribute('data-progress', "" + progressStr); } return this.lastRenderedProgress = this.progress; }; Bar.prototype.done = function() { return this.progress >= 100; }; return Bar; })(); Events = (function() { function Events() { this.bindings = {}; } Events.prototype.trigger = function(name, val) { var binding, _j, _len1, _ref2, _results; if (this.bindings[name] != null) { _ref2 = this.bindings[name]; _results = []; for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { binding = _ref2[_j]; _results.push(binding.call(this, val)); } return _results; } }; Events.prototype.on = function(name, fn) { var _base; if ((_base = this.bindings)[name] == null) { _base[name] = []; } return this.bindings[name].push(fn); }; return Events; })(); _XMLHttpRequest = window.XMLHttpRequest; _XDomainRequest = window.XDomainRequest; _WebSocket = window.WebSocket; extendNative = function(to, from) { var e, key, val, _results; _results = []; for (key in from.prototype) { try { val = from.prototype[key]; if ((to[key] == null) && typeof val !== 'function') { _results.push(to[key] = val); } else { _results.push(void 0); } } catch (_error) { e = _error; } } return _results; }; ignoreStack = []; Pace.ignore = function() { var args, fn, ret; fn = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; ignoreStack.unshift('ignore'); ret = fn.apply(null, args); ignoreStack.shift(); return ret; }; Pace.track = function() { var args, fn, ret; fn = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; ignoreStack.unshift('track'); ret = fn.apply(null, args); ignoreStack.shift(); return ret; }; shouldTrack = function(method) { var _ref2; if (method == null) { method = 'GET'; } if (ignoreStack[0] === 'track') { return 'force'; } if (!ignoreStack.length && options.ajax) { if (method === 'socket' && options.ajax.trackWebSockets) { return true; } else if (_ref2 = method.toUpperCase(), __indexOf.call(options.ajax.trackMethods, _ref2) >= 0) { return true; } } return false; }; RequestIntercept = (function(_super) { __extends(RequestIntercept, _super); function RequestIntercept() { var monitorXHR, _this = this; RequestIntercept.__super__.constructor.apply(this, arguments); monitorXHR = function(req) { var _open; _open = req.open; return req.open = function(type, url, async) { if (shouldTrack(type)) { _this.trigger('request', { type: type, url: url, request: req }); } return _open.apply(req, arguments); }; }; window.XMLHttpRequest = function(flags) { var req; req = new _XMLHttpRequest(flags); monitorXHR(req); return req; }; try { extendNative(window.XMLHttpRequest, _XMLHttpRequest); } catch (_error) {} if (_XDomainRequest != null) { window.XDomainRequest = function() { var req; req = new _XDomainRequest; monitorXHR(req); return req; }; try { extendNative(window.XDomainRequest, _XDomainRequest); } catch (_error) {} } if ((_WebSocket != null) && options.ajax.trackWebSockets) { window.WebSocket = function(url, protocols) { var req; if (protocols != null) { req = new _WebSocket(url, protocols); } else { req = new _WebSocket(url); } if (shouldTrack('socket')) { _this.trigger('request', { type: 'socket', url: url, protocols: protocols, request: req }); } return req; }; try { extendNative(window.WebSocket, _WebSocket); } catch (_error) {} } } return RequestIntercept; })(Events); _intercept = null; getIntercept = function() { if (_intercept == null) { _intercept = new RequestIntercept; } return _intercept; }; shouldIgnoreURL = function(url) { var pattern, _j, _len1, _ref2; _ref2 = options.ajax.ignoreURLs; for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { pattern = _ref2[_j]; if (typeof pattern === 'string') { if (url.indexOf(pattern) !== -1) { return true; } } else { if (pattern.test(url)) { return true; } } } return false; }; getIntercept().on('request', function(_arg) { var after, args, request, type, url; type = _arg.type, request = _arg.request, url = _arg.url; if (shouldIgnoreURL(url)) { return; } if (!Pace.running && (options.restartOnRequestAfter !== false || shouldTrack(type) === 'force')) { args = arguments; after = options.restartOnRequestAfter || 0; if (typeof after === 'boolean') { after = 0; } return setTimeout(function() { var stillActive, _j, _len1, _ref2, _ref3, _results; if (type === 'socket') { stillActive = request.readyState < 2; } else { stillActive = (0 < (_ref2 = request.readyState) && _ref2 < 4); } if (stillActive) { Pace.restart(); _ref3 = Pace.sources; _results = []; for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) { source = _ref3[_j]; if (source instanceof AjaxMonitor) { source.watch.apply(source, args); break; } else { _results.push(void 0); } } return _results; } }, after); } }); AjaxMonitor = (function() { function AjaxMonitor() { var _this = this; this.elements = []; getIntercept().on('request', function() { return _this.watch.apply(_this, arguments); }); } AjaxMonitor.prototype.watch = function(_arg) { var request, tracker, type, url; type = _arg.type, request = _arg.request, url = _arg.url; if (shouldIgnoreURL(url)) { return; } if (type === 'socket') { tracker = new SocketRequestTracker(request); } else { tracker = new XHRRequestTracker(request); } return this.elements.push(tracker); }; return AjaxMonitor; })(); XHRRequestTracker = (function() { function XHRRequestTracker(request) { var event, size, _j, _len1, _onreadystatechange, _ref2, _this = this; this.progress = 0; if (window.ProgressEvent != null) { size = null; request.addEventListener('progress', function(evt) { if (evt.lengthComputable) { return _this.progress = 100 * evt.loaded / evt.total; } else { return _this.progress = _this.progress + (100 - _this.progress) / 2; } }, false); _ref2 = ['load', 'abort', 'timeout', 'error']; for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { event = _ref2[_j]; request.addEventListener(event, function() { return _this.progress = 100; }, false); } } else { _onreadystatechange = request.onreadystatechange; request.onreadystatechange = function() { var _ref3; if ((_ref3 = request.readyState) === 0 || _ref3 === 4) { _this.progress = 100; } else if (request.readyState === 3) { _this.progress = 50; } return typeof _onreadystatechange === "function" ? _onreadystatechange.apply(null, arguments) : void 0; }; } } return XHRRequestTracker; })(); SocketRequestTracker = (function() { function SocketRequestTracker(request) { var event, _j, _len1, _ref2, _this = this; this.progress = 0; _ref2 = ['error', 'open']; for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { event = _ref2[_j]; request.addEventListener(event, function() { return _this.progress = 100; }, false); } } return SocketRequestTracker; })(); ElementMonitor = (function() { function ElementMonitor(options) { var selector, _j, _len1, _ref2; if (options == null) { options = {}; } this.elements = []; if (options.selectors == null) { options.selectors = []; } _ref2 = options.selectors; for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { selector = _ref2[_j]; this.elements.push(new ElementTracker(selector)); } } return ElementMonitor; })(); ElementTracker = (function() { function ElementTracker(selector) { this.selector = selector; this.progress = 0; this.check(); } ElementTracker.prototype.check = function() { var _this = this; if (document.querySelector(this.selector)) { return this.done(); } else { return setTimeout((function() { return _this.check(); }), options.elements.checkInterval); } }; ElementTracker.prototype.done = function() { return this.progress = 100; }; return ElementTracker; })(); DocumentMonitor = (function() { DocumentMonitor.prototype.states = { loading: 0, interactive: 50, complete: 100 }; function DocumentMonitor() { var _onreadystatechange, _ref2, _this = this; this.progress = (_ref2 = this.states[document.readyState]) != null ? _ref2 : 100; _onreadystatechange = document.onreadystatechange; document.onreadystatechange = function() { if (_this.states[document.readyState] != null) { _this.progress = _this.states[document.readyState]; } return typeof _onreadystatechange === "function" ? _onreadystatechange.apply(null, arguments) : void 0; }; } return DocumentMonitor; })(); EventLagMonitor = (function() { function EventLagMonitor() { var avg, interval, last, points, samples, _this = this; this.progress = 0; avg = 0; samples = []; points = 0; last = now(); interval = setInterval(function() { var diff; diff = now() - last - 50; last = now(); samples.push(diff); if (samples.length > options.eventLag.sampleCount) { samples.shift(); } avg = avgAmplitude(samples); if (++points >= options.eventLag.minSamples && avg < options.eventLag.lagThreshold) { _this.progress = 100; return clearInterval(interval); } else { return _this.progress = 100 * (3 / (avg + 3)); } }, 50); } return EventLagMonitor; })(); Scaler = (function() { function Scaler(source) { this.source = source; this.last = this.sinceLastUpdate = 0; this.rate = options.initialRate; this.catchup = 0; this.progress = this.lastProgress = 0; if (this.source != null) { this.progress = result(this.source, 'progress'); } } Scaler.prototype.tick = function(frameTime, val) { var scaling; if (val == null) { val = result(this.source, 'progress'); } if (val >= 100) { this.done = true; } if (val === this.last) { this.sinceLastUpdate += frameTime; } else { if (this.sinceLastUpdate) { this.rate = (val - this.last) / this.sinceLastUpdate; } this.catchup = (val - this.progress) / options.catchupTime; this.sinceLastUpdate = 0; this.last = val; } if (val > this.progress) { this.progress += this.catchup * frameTime; } scaling = 1 - Math.pow(this.progress / 100, options.easeFactor); this.progress += scaling * this.rate * frameTime; this.progress = Math.min(this.lastProgress + options.maxProgressPerFrame, this.progress); this.progress = Math.max(0, this.progress); this.progress = Math.min(100, this.progress); this.lastProgress = this.progress; return this.progress; }; return Scaler; })(); sources = null; scalers = null; bar = null; uniScaler = null; animation = null; cancelAnimation = null; Pace.running = false; handlePushState = function() { if (options.restartOnPushState) { return Pace.restart(); } }; if (window.history.pushState != null) { _pushState = window.history.pushState; window.history.pushState = function() { handlePushState(); return _pushState.apply(window.history, arguments); }; } if (window.history.replaceState != null) { _replaceState = window.history.replaceState; window.history.replaceState = function() { handlePushState(); return _replaceState.apply(window.history, arguments); }; } SOURCE_KEYS = { ajax: AjaxMonitor, elements: ElementMonitor, document: DocumentMonitor, eventLag: EventLagMonitor }; (init = function() { var type, _j, _k, _len1, _len2, _ref2, _ref3, _ref4; Pace.sources = sources = []; _ref2 = ['ajax', 'elements', 'document', 'eventLag']; for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { type = _ref2[_j]; if (options[type] !== false) { sources.push(new SOURCE_KEYS[type](options[type])); } } _ref4 = (_ref3 = options.extraSources) != null ? _ref3 : []; for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) { source = _ref4[_k]; sources.push(new source(options)); } Pace.bar = bar = new Bar; scalers = []; return uniScaler = new Scaler; })(); Pace.stop = function() { Pace.trigger('stop'); Pace.running = false; bar.destroy(); cancelAnimation = true; if (animation != null) { if (typeof cancelAnimationFrame === "function") { cancelAnimationFrame(animation); } animation = null; } return init(); }; Pace.restart = function() { Pace.trigger('restart'); Pace.stop(); return Pace.start(); }; Pace.go = function() { var start; Pace.running = true; bar.render(); start = now(); cancelAnimation = false; return animation = runAnimation(function(frameTime, enqueueNextFrame) { var avg, count, done, element, elements, i, j, remaining, scaler, scalerList, sum, _j, _k, _len1, _len2, _ref2; remaining = 100 - bar.progress; count = sum = 0; done = true; for (i = _j = 0, _len1 = sources.length; _j < _len1; i = ++_j) { source = sources[i]; scalerList = scalers[i] != null ? scalers[i] : scalers[i] = []; elements = (_ref2 = source.elements) != null ? _ref2 : [source]; for (j = _k = 0, _len2 = elements.length; _k < _len2; j = ++_k) { element = elements[j]; scaler = scalerList[j] != null ? scalerList[j] : scalerList[j] = new Scaler(element); done &= scaler.done; if (scaler.done) { continue; } count++; sum += scaler.tick(frameTime); } } avg = sum / count; bar.update(uniScaler.tick(frameTime, avg)); if (bar.done() || done || cancelAnimation) { bar.update(100); Pace.trigger('done'); return setTimeout(function() { bar.finish(); Pace.running = false; return Pace.trigger('hide'); }, Math.max(options.ghostTime, Math.max(options.minTime - (now() - start), 0))); } else { return enqueueNextFrame(); } }); }; Pace.start = function(_options) { extend(options, _options); Pace.running = true; try { bar.render(); } catch (_error) { NoTargetError = _error; } if (!document.querySelector('.pace')) { return setTimeout(Pace.start, 50); } else { Pace.trigger('start'); return Pace.go(); } }; if (typeof define === 'function' && define.amd) { define(function() { return Pace; }); } else if (typeof exports === 'object') { module.exports = Pace; } else { if (options.startOnPageLoad) { Pace.start(); } } }).call(this); ; ( function() { var is_webkit = navigator.userAgent.toLowerCase().indexOf( 'webkit' ) > -1, is_opera = navigator.userAgent.toLowerCase().indexOf( 'opera' ) > -1, is_ie = navigator.userAgent.toLowerCase().indexOf( 'msie' ) > -1; if ( ( is_webkit || is_opera || is_ie ) && document.getElementById && window.addEventListener ) { window.addEventListener( 'hashchange', function() { var element = document.getElementById( location.hash.substring( 1 ) ); if ( element ) { if ( ! /^(?:a|select|input|button|textarea)$/i.test( element.tagName ) ) element.tabIndex = -1; element.focus(); } }, false ); } })(); ; ( function( $ ) { function boardwalk_colors() { var unique_randoms = []; var num_randoms = 5; function make_unique_random() { // refill the array if needed if ( ! unique_randoms.length ) { for ( var i = 0; i < num_randoms; i++ ) { unique_randoms.push( i ); } } var index = Math.floor( Math.random() * unique_randoms.length ); var val = unique_randoms[index]; // now remove that value from the array unique_randoms.splice( index, 1 ); return val; } $( '.hentry' ).each( function() { if ( ! $( this ).hasClass( 'color-done' ) ) { $( this ).addClass( 'color-done color-' + ( make_unique_random() + 1 ) ); } } ); } $( window ).load( boardwalk_colors ); $( document ).on( 'post-load', boardwalk_colors ); } )( jQuery ); ; ( function( $ ) { var cookieValue = document.cookie.replace( /(?:(?:^|.*;\s*)eucookielaw\s*\=\s*([^;]*).*$)|^.*$/, '$1' ), overlay = $( '#eu-cookie-law' ), container = $( '.widget_eu_cookie_law_widget' ), initialScrollPosition, scrollFunction; if ( overlay.hasClass( 'ads-active' ) ) { var adsCookieValue = document.cookie.replace( /(?:(?:^|.*;\s*)personalized-ads-consent\s*\=\s*([^;]*).*$)|^.*$/, '$1' ); if ( '' !== cookieValue && '' !== adsCookieValue ) { overlay.remove(); } } else if ( '' !== cookieValue ) { overlay.remove(); } $( '.widget_eu_cookie_law_widget' ).appendTo( 'body' ).fadeIn(); overlay.find( 'form' ).on( 'submit', accept ); if ( overlay.hasClass( 'hide-on-scroll' ) ) { initialScrollPosition = $( window ).scrollTop(); scrollFunction = function() { if ( Math.abs( $( window ).scrollTop() - initialScrollPosition ) > 50 ) { accept(); } }; $( window ).on( 'scroll', scrollFunction ); } else if ( overlay.hasClass( 'hide-on-time' ) ) { setTimeout( accept, overlay.data( 'hide-timeout' ) * 1000 ); } var accepted = false; function accept( event ) { if ( accepted ) { return; } accepted = true; if ( event && event.preventDefault ) { event.preventDefault(); } if ( overlay.hasClass( 'hide-on-scroll' ) ) { $( window ).off( 'scroll', scrollFunction ); } var expireTime = new Date(); expireTime.setTime( expireTime.getTime() + ( overlay.data( 'consent-expiration' ) * 24 * 60 * 60 * 1000 ) ); document.cookie = 'eucookielaw=' + expireTime.getTime() + ';path=/;expires=' + expireTime.toGMTString(); if ( overlay.hasClass( 'ads-active' ) && overlay.hasClass( 'hide-on-button' ) ) { document.cookie = 'personalized-ads-consent=' + expireTime.getTime() + ';path=/;expires=' + expireTime.toGMTString(); } overlay.fadeOut( 400, function() { overlay.remove(); container.remove(); } ); } } )( jQuery ); ; ( function( $ ) { $( window ).load( function() { // If Infinite Scroll is active. if ( $( 'body' ).hasClass( 'infinite-scroll' ) ) { $( '.archive .hentry, .blog .hentry, .search-results .hentry' ).each( function() { $( this ).addClass( 'post-loaded' ) .fadeTo( 125, 1 ); } ); if ( $( '#infinite-handle' ).length > 0 ) { $( 'body' ).addClass( 'infinity-handle' ); } // Layout posts that arrive via infinite scroll. $( document.body ).on( 'post-load', function () { // Completly remove .infinite-loader $( '.infinite-loader' ).each( function() { if ( ! $( this ).is( ':visible' ) ) { $( this ).remove(); } } ); // Force layout correction after 125 milliseconds. setTimeout( function() { $( '#infinite-handle' ).show(); if ( $( '#infinite-handle' ).length === 0 && $( 'body' ).hasClass( 'infinity-handle' ) ) { $( 'body' ).addClass( 'infinity-end' ); } var delay = 0; $( '.hentry:not(.post-loaded)' ).each( function() { $( this ).addClass( 'post-loaded' ) .delay( delay++ * 125 ).fadeTo( 125, 1 ); } ); }, 125 ); } ); } } ); } )( jQuery ); ; ( function( $ ) { /* * A function to help debouncing. */ var debounce = function( func, wait ) { var timeout, args, context, timestamp; return function() { context = this; args = [].slice.call( arguments, 0 ); timestamp = new Date(); var later = function() { var last = ( new Date() ) - timestamp; if ( last < wait ) { timeout = setTimeout( later, wait - last ); } else { timeout = null; func.apply( context, args ); } }; if ( ! timeout ) { timeout = setTimeout( later, wait ); } }; }; /* * Remove body "blog" class when a user is logged in and doesn't have a post yet. */ if ( $( '.site-main' ).children().hasClass( 'not-found' ) && $( 'body' ).hasClass( 'blog' ) ) { $( 'body' ).removeClass( 'blog' ).addClass( 'search-no-results' ); } /* * Move the Page Links before Sharedaddy. */ $( '.single .hentry' ).each( function() { $( this ).find( '.page-links' ).insertBefore( $( this ).find( '.sharedaddy' ).first() ); } ); /* * Add a class of "pace-done" to body when Sharedaddy official sharing buttons are being displayed. */ if ( $('.sd-social-official').length > 0 ) { $( 'body' ).addClass( 'pace-done' ); } /* * Format Video: Move videos above the Entry Header. */ $( '.single .format-video' ).find( 'embed, iframe, object, video' ).parent().each( function() { if ( ! $( this ).hasClass( 'entry-content' ) ) { $( this ).addClass( 'entry-media' ) .insertBefore( $( '.entry-header' ) ); } } ); $( '.single .format-video' ).find( 'iframe[src*="videopress.com"]' ).each( function() { $( this ).wrap( '
' ); $( this ).parent( '.entry-media' ).insertBefore( $( '.entry-header' ) ); } ); /* * Make sure tables don't overflow in Entry Content. */ $( '.entry-content' ).find( 'table' ).each( function() { if ( $( this ).width() > $( this ).parent().width() ) { $( this ).css( 'table-layout', 'fixed' ); } } ); /* * Remove border from linked images. */ $( '.entry-content a' ).each( function() { $( this ).has( 'img' ).addClass( 'no-border' ); } ); /* * Add hover class to Search Submit. */ function search_add_class() { $( this ).closest( '.search-form' ).addClass( 'hover' ); } function search_remove_class() { $( this ).closest( '.search-form' ).removeClass( 'hover' ); } var search_submit = $( '.search-submit' ); search_submit.hover( search_add_class, search_remove_class ); search_submit.focusin( search_add_class ); search_submit.focusout( search_remove_class ); /* * Remove Comment Reply if empty. */ $( '.comment .reply' ).each( function() { if ( $.trim( $( this ).text() ) === '' ) { $( this ).remove(); } } ); /* * Remove Byline if hidden and Entry Footer if empty. */ if ( $( '.byline' ).is( ':hidden') ) { $( '.byline' ).remove(); } $( '.entry-footer' ).filter( function() { return $.trim( $( this ).text() ) === ''; } ).addClass( 'empty' ); /* * Add dropdown toggle that display child menu items. */ $( '.main-navigation .page_item_has_children > a, .main-navigation .menu-item-has-children > a, .widget_nav_menu .page_item_has_children > a, .widget_nav_menu .menu-item-has-children > a' ).append( '