( function () { /* global sas */ /* global wa_smart */ sas.cmd.push( function () { sas.setup( { networkid: wa_smart.network_id, domain: 'https://www15.smartadserver.com', async: true, } ); } ); sas.cmd.push( function () { sas.call( 'onecall', { siteId: wa_smart.site_id, pageId: wa_smart.page_id, formats: wa_smart.formats, content_source_id: wa_smart.blog_id, target: wa_smart.target, } ); } ); sas.cmd.push( function () { sas.events.on( 'noad', function ( data ) { var el = document.getElementById( data.tagId ); if ( ! el ) { return; } var target = el.closest( '.wordads-ad-wrapper' ); var slotType = el.classList.contains( 'wordads-ad-inline' ) ? 'inline' : 'belowpost'; wordads.insertFallbackAd( target, slotType ); } ); } ); sas.cmd.push( function () { sas.events.on( 'load', function ( data ) { var el = document.getElementById( data.tagId ); if ( ! el ) { return; } el.closest( '.wordads-ad-wrapper' ).style.display = 'inherit'; } ); } ); // Process commands. wa_smart.cmd.forEach( ( cmd ) => { sas.cmd.push( cmd ); } ); wa_smart.cmd = { push: function ( cmd ) { sas.cmd.push( cmd ); }, }; var wordads = wordads || {}; wordads.trackStat = function ( stat ) { window._stq = window._stq || []; window._stq.push( [ 'extra', { x_wordads_smart: stat, }, ] ); }; wordads.createInlineAdSnippet = function ( tagId ) { var wrapper = document.createElement( 'div' ); var ad = document.createElement( 'div' ); var title = document.createElement( 'div' ); var content = document.createElement( 'div' ); var controls = document.createElement( 'div' ); wrapper.classList.add( 'wordads-ad-wrapper' ); ad.classList.add( 'wordads-ad' ); title.classList.add( 'wordads-ad-title' ); content.classList.add( 'wordads-ad-content' ); content.classList.add( 'wordads-ad-inline' ); controls.classList.add( 'wordads-ad-controls' ); title.innerText = wa_smart.inline.title; content.id = tagId; controls.innerHTML = wa_smart.inline.gdpr; ad.appendChild( title ); ad.appendChild( content ); ad.appendChild( controls ); wrapper.appendChild( ad ); return wrapper; }; wordads.insertInlineAdBefore = function ( element ) { var tagId = 'wordads-ad-' + parseInt( Math.random() * 1000000 ); var snippet = wordads.createInlineAdSnippet( tagId ); element.insertAdjacentElement( 'beforebegin', snippet ); sas.cmd.push( function () { sas.call( 'std', { siteId: wa_smart.site_id, pageId: wa_smart.page_id, formatId: wa_smart.inline.format_id, tagId: tagId, content_source_id: wa_smart.blog_id, target: wa_smart.target, } ); } ); }; wordads.insertFallbackAd = function ( target, slotType ) { var sas_fallback = window.sas_fallback || []; var slot_fallback = sas_fallback.filter( function ( fallback ) { return fallback.type === slotType; } ); if ( slot_fallback.length === 0 ) { target.remove(); return; } // Replace the macro to have a div with a unique id. var slot_fallback_tag = slot_fallback[ 0 ].tag.replaceAll( '{{unique_id}}', parseInt( Math.random() * 1000000 ) ); // Unescape the tag markup. var e = document.createElement( 'div' ); e.innerHTML = slot_fallback_tag; slot_fallback_tag = e.childNodes[ 0 ].nodeValue; // Insert the fallback tag into a parent for helping to find the script tags. var parent = document.createElement( 'div' ); parent.innerHTML = slot_fallback_tag; // Make our ad visible. Needed by IPONWEB to calculate the width of the container. target.style.display = 'inherit'; // Inserting into target. target.innerHTML = parent.innerHTML; // Process any scripts in the tag. var scripts = parent.querySelectorAll( 'script' ); scripts.forEach( function ( script ) { script.parentNode.removeChild( script ); var scriptTag = document.createElement( 'script' ); if ( script.src ) { scriptTag.src = script.src; } else if ( script.textContent ) { scriptTag.textContent = script.textContent; } else if ( script.innerText ) { scriptTag.innerText = script.innerText; } document.body.appendChild( scriptTag ); } ); }; wordads.getChildrenByTag = function ( el, tag ) { var children = []; el.childNodes.forEach( ( child ) => { if ( child.nodeName === tag.toUpperCase() ) { children.push( child ); } } ); return children; }; wordads.getFloatingElements = function ( el ) { var floating = []; // Get child nodes recursive. var children = el.getElementsByTagName( '*' ); for ( var i = 0; i < children.length; i++ ) { var child = children[ i ]; var computed = getComputedStyle( child ); var position = computed.getPropertyValue( 'position' ); var float = computed.getPropertyValue( 'float' ); if ( position === 'relative' || position === 'absolute' || float !== 'none' ) { floating.push( child ); } } return floating; }; wordads.getElementGlobalPosition = function ( el ) { var rect = el.getBoundingClientRect(); return { top: rect.top + window.scrollY, left: rect.left + window.scrollX, bottom: rect.top + window.scrollY + rect.height, right: rect.left + window.scrollX + rect.width, }; }; wordads.collidesWithElements = function ( target, elements ) { var targetRect = wordads.getElementGlobalPosition( target ); var collides = false; elements.forEach( ( el ) => { var collideRect = wordads.getElementGlobalPosition( el ); if ( ! ( targetRect.bottom < collideRect.top || targetRect.top > collideRect.bottom || targetRect.right < collideRect.left || targetRect.left > collideRect.left ) ) { collides = true; } } ); return collides; }; wordads.initializeInlineAds = function () { // Check if feature is enabled. if ( ! wa_smart.inline.enabled ) { return; } // Check for inline ads marker. var marker = document.getElementById( 'wordads-inline-marker' ); // Stop if no marker is found. if ( ! marker ) { wordads.trackStat( 'inline_no_marker' ); return; } // Get the post content area element based on marker position. var post = marker.parentElement; // Remove marker, we don't need it anymore. marker.remove(); // Set threshold for maximum slots. var maxSlots = wa_smart.inline.max_slots; var maxBlazeSlots = wa_smart.inline.max_blaze_slots; var slotCount = 0; // Calculate insertion intervals based on ratio of viewport height. var viewportHeight = window.innerHeight; var initialViewportRatio = 1.35; var initialInsertionInterval = Math.ceil( viewportHeight * initialViewportRatio ); var viewportRatio = 1.35; var insertionInterval = Math.ceil( viewportHeight * viewportRatio ); // Calculate initial threshold. var postOffset = post.getBoundingClientRect().top + window.scrollY; var minThreshold = postOffset + initialInsertionInterval; // Loop through content to find slots to insert. var paras = wordads.getChildrenByTag( post, 'p' ); // Get floating elements. var floating = wordads.getFloatingElements( post ); paras.forEach( ( p ) => { var offset = p.getBoundingClientRect().top + window.scrollY; var previous = p.previousElementSibling; if ( offset > minThreshold && slotCount < maxSlots && previous.nodeName === 'P' && ! wordads.collidesWithElements( p, floating ) ) { if ( maxBlazeSlots > slotCount ) { wordads.insertInlineAdBefore( p ); wordads.trackStat( 'render_inline' ); } else { // Need to wrap first. var target = document.createElement( 'div' ); target.className = 'wordads-ad-wrapper'; p.insertAdjacentElement( 'beforebegin', target ); wordads.insertFallbackAd( target, 'inline' ); wordads.trackStat( 'render_inline_fallback' ); } minThreshold = offset + insertionInterval; slotCount++; } } ); if ( slotCount === 0 ) { wordads.trackStat( 'inline_no_insert' ); } }; document.addEventListener( 'DOMContentLoaded', function () { wordads.initializeInlineAds(); } ); } )(); ; ( function() { var cookieValue = document.cookie.replace( /(?:(?:^|.*;\s*)eucookielaw\s*\=\s*([^;]*).*$)|^.*$/, '$1' ); var overlay = document.querySelector( '#eu-cookie-law' ); var container = document.querySelector( '.widget_eu_cookie_law_widget' ); var initialScrollPosition, scrollFunction; function remove( el ) { return el && el.parentElement && el.parentElement.removeChild( el ); } function triggerDismissEvent() { try { const dismissEvent = new Event( 'eucookielaw-dismissed' ); document.dispatchEvent( dismissEvent ); } catch ( err ) { } } function removeOverlay() { remove( overlay ); triggerDismissEvent(); } function fade( el, type, fn ) { var duration = 400; el.style.display = 'block'; el.style.transitionProperty = 'opacity'; el.style.transitionDuration = duration + 'ms'; el.style.opacity = type === 'in' ? 0 : 1; // Double rAF to ensure styles are applied cross-browser. requestAnimationFrame( function () { requestAnimationFrame( function() { el.style.opacity = type === 'in' ? 1 : 0; // Wait for animation. setTimeout( function () { // Clean up. el.style.removeProperty( 'opacity' ); el.style.removeProperty( 'transition-property' ); el.style.removeProperty( 'transition-duration' ); if ( type === 'out' ) { el.style.display = 'none'; } if ( typeof fn === 'function' ) { fn(); } }, duration + 50 ); } ); } ); } function appendWidget() { document.body.appendChild( container ); overlay.style.display = 'block'; fade( container, 'in' ); } if ( typeof wp !== 'undefined' && !! wp.customize ) { appendWidget(); return; } if ( ! overlay || ! container ) { return; } if ( overlay.classList.contains( 'ads-active' ) ) { var adsCookieValue = document.cookie.replace( /(?:(?:^|.*;\s*)personalized-ads-consent\s*\=\s*([^;]*).*$)|^.*$/, '$1' ); if ( cookieValue !== '' && adsCookieValue !== '' ) { removeOverlay(); } } else if ( cookieValue !== '' ) { removeOverlay(); } appendWidget(); overlay.querySelector( 'form' ).addEventListener( 'submit', accept ); if ( overlay.classList.contains( 'hide-on-scroll' ) ) { initialScrollPosition = window.pageYOffset; scrollFunction = function() { if ( Math.abs( window.pageYOffset - initialScrollPosition ) > 50 ) { accept(); } }; window.addEventListener( 'scroll', scrollFunction ); } else if ( overlay.classList.contains( 'hide-on-time' ) ) { var timeout = parseInt( overlay.getAttribute( 'data-hide-timeout' ), 10 ) || 0; setTimeout( accept, timeout * 1000 ); } var accepted = false; function accept( event ) { if ( accepted ) { return; } accepted = true; if ( event && event.preventDefault ) { event.preventDefault(); } if ( overlay.classList.contains( 'hide-on-scroll' ) ) { window.removeEventListener( 'scroll', scrollFunction ); } var expireTime = new Date(); var consentExpiration = parseInt( overlay.getAttribute( 'data-consent-expiration' ), 10 ) || 0; expireTime.setTime( expireTime.getTime() + ( consentExpiration * 24 * 60 * 60 * 1000 ) ); document.cookie = 'eucookielaw=' + expireTime.getTime() + ';path=/;expires=' + expireTime.toGMTString(); if ( overlay.classList.contains( 'ads-active' ) && overlay.classList.contains( 'hide-on-button' ) ) { document.cookie = 'personalized-ads-consent=' + expireTime.getTime() + ';path=/;expires=' + expireTime.toGMTString(); } fade( overlay, 'out', function() { removeOverlay(); remove( container ); } ); } } )(); ; /* global wpcom_reblog */ var jetpackLikesWidgetBatch = []; var jetpackLikesMasterReady = false; // Due to performance problems on pages with a large number of widget iframes that need to be loaded, // we are limiting the processing at any instant to unloaded widgets that are currently in viewport, // plus this constant that will allow processing of widgets above and bellow the current fold. // This aim of it is to improve the UX and hide the transition from unloaded to loaded state from users. var jetpackLikesLookAhead = 2000; // pixels // Keeps track of loaded comment likes widget so we can unload them when they are scrolled out of view. var jetpackCommentLikesLoadedWidgets = []; var jetpackLikesDocReadyPromise = new Promise( resolve => { if ( document.readyState !== 'loading' ) { resolve(); } else { window.addEventListener( 'DOMContentLoaded', () => resolve() ); } } ); function JetpackLikesPostMessage( message, target ) { if ( typeof message === 'string' ) { try { message = JSON.parse( message ); } catch ( e ) { return; } } if ( target && typeof target.postMessage === 'function' ) { try { target.postMessage( JSON.stringify( { type: 'likesMessage', data: message, } ), '*' ); } catch ( e ) { return; } } } function JetpackLikesBatchHandler() { const requests = []; document.querySelectorAll( 'div.jetpack-likes-widget-unloaded' ).forEach( widget => { if ( jetpackLikesWidgetBatch.indexOf( widget.id ) > -1 ) { return; } if ( ! jetpackIsScrolledIntoView( widget ) ) { return; } jetpackLikesWidgetBatch.push( widget.id ); var regex = /like-(post|comment)-wrapper-(\d+)-(\d+)-(\w+)/, match = regex.exec( widget.id ), info; if ( ! match || match.length !== 5 ) { return; } info = { blog_id: match[ 2 ], width: widget.width, }; if ( 'post' === match[ 1 ] ) { info.post_id = match[ 3 ]; } else if ( 'comment' === match[ 1 ] ) { info.comment_id = match[ 3 ]; } info.obj_id = match[ 4 ]; requests.push( info ); } ); if ( requests.length > 0 ) { JetpackLikesPostMessage( { event: 'initialBatch', requests: requests }, window.frames[ 'likes-master' ] ); } } function JetpackLikesMessageListener( event ) { let message = event && event.data; if ( typeof message === 'string' ) { try { message = JSON.parse( message ); } catch ( err ) { return; } } const type = message && message.type; const data = message && message.data; if ( type !== 'likesMessage' || typeof data.event === 'undefined' ) { return; } // We only allow messages from one origin const allowedOrigin = 'https://widgets.wp.com'; if ( allowedOrigin !== event.origin ) { return; } switch ( data.event ) { case 'masterReady': jetpackLikesDocReadyPromise.then( () => { jetpackLikesMasterReady = true; const stylesData = { event: 'injectStyles', }; const sdTextColor = document.querySelector( '.sd-text-color' ); const sdLinkColor = document.querySelector( '.sd-link-color' ); const sdTextColorStyles = ( sdTextColor && getComputedStyle( sdTextColor ) ) || {}; const sdLinkColorStyles = ( sdLinkColor && getComputedStyle( sdLinkColor ) ) || {}; if ( document.querySelectorAll( 'iframe.admin-bar-likes-widget' ).length > 0 ) { JetpackLikesPostMessage( { event: 'adminBarEnabled' }, window.frames[ 'likes-master' ] ); const bgSource = document.querySelector( '#wpadminbar .quicklinks li#wp-admin-bar-wpl-like > a' ); const wpAdminBar = document.querySelector( '#wpadminbar' ); stylesData.adminBarStyles = { background: bgSource && getComputedStyle( bgSource ).background, isRtl: wpAdminBar && getComputedStyle( wpAdminBar ).direction === 'rtl', }; } // enable reblogs if they are enabled for the page if ( document.body.classList.contains( 'jetpack-reblog-enabled' ) ) { JetpackLikesPostMessage( { event: 'reblogsEnabled' }, window.frames[ 'likes-master' ] ); } stylesData.textStyles = { color: sdTextColorStyles[ 'color' ], fontFamily: sdTextColorStyles[ 'font-family' ], fontSize: sdTextColorStyles[ 'font-size' ], direction: sdTextColorStyles[ 'direction' ], fontWeight: sdTextColorStyles[ 'font-weight' ], fontStyle: sdTextColorStyles[ 'font-style' ], textDecoration: sdTextColorStyles[ 'text-decoration' ], }; stylesData.linkStyles = { color: sdLinkColorStyles[ 'color' ], fontFamily: sdLinkColorStyles[ 'font-family' ], fontSize: sdLinkColorStyles[ 'font-size' ], textDecoration: sdLinkColorStyles[ 'text-decoration' ], fontWeight: sdLinkColorStyles[ 'font-weight' ], fontStyle: sdLinkColorStyles[ 'font-style' ], }; JetpackLikesPostMessage( stylesData, window.frames[ 'likes-master' ] ); JetpackLikesBatchHandler(); } ); break; case 'showLikeWidget': { const placeholder = document.querySelector( `#${ data.id } .likes-widget-placeholder` ); if ( placeholder ) { placeholder.style.display = 'none'; } break; } case 'showCommentLikeWidget': { const placeholder = document.querySelector( `#${ data.id } .likes-widget-placeholder` ); if ( placeholder ) { placeholder.style.display = 'none'; } break; } case 'killCommentLikes': // If kill switch for comment likes is enabled remove all widgets wrappers and `Loading...` placeholders. document .querySelectorAll( '.jetpack-comment-likes-widget-wrapper' ) .forEach( wrapper => wrapper.remove() ); break; case 'clickReblogFlair': if ( wpcom_reblog && typeof wpcom_reblog.toggle_reblog_box_flair === 'function' ) { wpcom_reblog.toggle_reblog_box_flair( data.obj_id, data.post_id ); } break; case 'showOtherGravatars': { const container = document.querySelector( '#likes-other-gravatars' ); if ( ! container ) { break; } const list = container.querySelector( 'ul' ); container.style.display = 'none'; list.innerHTML = ''; container .querySelectorAll( '.likes-text span' ) .forEach( item => ( item.textContent = data.total ) ); ( data.likers || [] ).forEach( async liker => { if ( liker.profile_URL.substr( 0, 4 ) !== 'http' ) { // We only display gravatars with http or https schema return; } try { const response = await fetch( liker.avatar_URL, { method: 'HEAD' } ); if ( !response.ok ) { // Image doesn't exist, don't create the element return; } } catch ( error ) { // Error occurred while checking image existence, don't create the element return; } const element = document.createElement( 'li' ); element.innerHTML = ` `; list.append( element ); // Add some extra attributes through native methods, to ensure strings are sanitized. element.classList.add( liker.css_class ); element.querySelector( 'img' ).alt = liker.name; } ); const el = document.querySelector( `*[name='${ data.parent }']` ); const rect = el.getBoundingClientRect(); const win = el.ownerDocument.defaultView; const offset = { top: rect.top + win.pageYOffset, left: rect.left + win.pageXOffset, }; container.style.left = offset.left + data.position.left - 10 + 'px'; container.style.top = offset.top + data.position.top - 33 + 'px'; // Container width - padding const initContainerWidth = data.width - 20; const rowLength = Math.floor( initContainerWidth / 37 ); // # of rows + (avatar + avatar padding) + text above + container padding let height = Math.ceil( data.likers.length / rowLength ) * 37 + 17 + 22; if ( height > 204 ) { height = 204; } // Avatars + padding const containerWidth = rowLength * 37 + 13; container.style.height = height + 'px'; container.style.width = containerWidth + 'px'; const listWidth = rowLength * 37; list.style.width = listWidth + 'px'; container.style.display = 'block'; } } } window.addEventListener( 'message', JetpackLikesMessageListener ); document.addEventListener( 'click', e => { const container = document.querySelector( '#likes-other-gravatars' ); if ( container && ! container.contains( e.target ) ) { container.style.display = 'none'; } } ); function JetpackLikesWidgetQueueHandler() { var wrapperID; if ( ! jetpackLikesMasterReady ) { setTimeout( JetpackLikesWidgetQueueHandler, 500 ); return; } // Restore widgets to initial unloaded state when they are scrolled out of view. jetpackUnloadScrolledOutWidgets(); var unloadedWidgetsInView = jetpackGetUnloadedWidgetsInView(); if ( unloadedWidgetsInView.length > 0 ) { // Grab any unloaded widgets for a batch request JetpackLikesBatchHandler(); } for ( var i = 0, length = unloadedWidgetsInView.length; i <= length - 1; i++ ) { wrapperID = unloadedWidgetsInView[ i ].id; if ( ! wrapperID ) { continue; } jetpackLoadLikeWidgetIframe( wrapperID ); } } function jetpackLoadLikeWidgetIframe( wrapperID ) { if ( typeof wrapperID === 'undefined' ) { return; } const wrapper = document.querySelector( '#' + wrapperID ); wrapper.querySelectorAll( 'iframe' ).forEach( iFrame => iFrame.remove() ); const placeholder = wrapper.querySelector( '.likes-widget-placeholder' ); // Post like iframe if ( placeholder && placeholder.classList.contains( 'post-likes-widget-placeholder' ) ) { const postLikesFrame = document.createElement( 'iframe' ); postLikesFrame.classList.add( 'post-likes-widget', 'jetpack-likes-widget' ); postLikesFrame.name = wrapper.dataset.name; postLikesFrame.src = wrapper.dataset.src; postLikesFrame.height = '55px'; postLikesFrame.width = '100%'; postLikesFrame.frameBorder = '0'; postLikesFrame.scrolling = 'no'; postLikesFrame.title = wrapper.dataset.title; placeholder.after( postLikesFrame ); } // Comment like iframe if ( placeholder.classList.contains( 'comment-likes-widget-placeholder' ) ) { const commentLikesFrame = document.createElement( 'iframe' ); commentLikesFrame.class = 'comment-likes-widget-frame jetpack-likes-widget-frame'; commentLikesFrame.name = wrapper.dataset.name; commentLikesFrame.src = wrapper.dataset.src; commentLikesFrame.height = '18px'; commentLikesFrame.width = '100%'; commentLikesFrame.frameBorder = '0'; commentLikesFrame.scrolling = 'no'; wrapper.querySelector( '.comment-like-feedback' ).after( commentLikesFrame ); jetpackCommentLikesLoadedWidgets.push( commentLikesFrame ); } wrapper.classList.remove( 'jetpack-likes-widget-unloaded' ); wrapper.classList.add( 'jetpack-likes-widget-loading' ); wrapper.querySelector( 'iframe' ).addEventListener( 'load', e => { JetpackLikesPostMessage( { event: 'loadLikeWidget', name: e.target.name, width: e.target.width }, window.frames[ 'likes-master' ] ); wrapper.classList.remove( 'jetpack-likes-widget-loading' ); wrapper.classList.add( 'jetpack-likes-widget-loaded' ); } ); } function jetpackGetUnloadedWidgetsInView() { const unloadedWidgets = document.querySelectorAll( 'div.jetpack-likes-widget-unloaded' ); return [ ...unloadedWidgets ].filter( item => jetpackIsScrolledIntoView( item ) ); } function jetpackIsScrolledIntoView( element ) { const top = element.getBoundingClientRect().top; const bottom = element.getBoundingClientRect().bottom; // Allow some slack above and bellow the fold with jetpackLikesLookAhead, // with the aim of hiding the transition from unloaded to loaded widget from users. return top + jetpackLikesLookAhead >= 0 && bottom <= window.innerHeight + jetpackLikesLookAhead; } function jetpackUnloadScrolledOutWidgets() { for ( let i = jetpackCommentLikesLoadedWidgets.length - 1; i >= 0; i-- ) { const currentWidgetIframe = jetpackCommentLikesLoadedWidgets[ i ]; if ( ! jetpackIsScrolledIntoView( currentWidgetIframe ) ) { const widgetWrapper = currentWidgetIframe && currentWidgetIframe.parentElement && currentWidgetIframe.parentElement.parentElement; // Restore parent class to 'unloaded' so this widget can be picked up by queue manager again if needed. widgetWrapper.classList.remove( 'jetpack-likes-widget-loaded' ); widgetWrapper.classList.remove( 'jetpack-likes-widget-loading' ); widgetWrapper.classList.add( 'jetpack-likes-widget-unloaded' ); // Bring back the loading placeholder into view. widgetWrapper .querySelectorAll( '.comment-likes-widget-placeholder' ) .forEach( item => ( item.style.display = 'block' ) ); // Remove it from the list of loaded widgets. jetpackCommentLikesLoadedWidgets.splice( i, 1 ); // Remove comment like widget iFrame. currentWidgetIframe.remove(); } } } var jetpackWidgetsDelayedExec = function ( after, fn ) { var timer; return function () { clearTimeout( timer ); timer = setTimeout( fn, after ); }; }; var jetpackOnScrollStopped = jetpackWidgetsDelayedExec( 250, JetpackLikesWidgetQueueHandler ); // Load initial batch of widgets, prior to any scrolling events. JetpackLikesWidgetQueueHandler(); // Add event listener to execute queue handler after scroll. window.addEventListener( 'scroll', jetpackOnScrollStopped, true ); ; /** * Comment Likes - JavaScript * * This handles liking and unliking comments, as well as viewing who has * liked a particular comment. * * @dependency Swipe (dynamically loaded when needed) * * @package Comment_Likes * @subpackage JavaScript */ (function () { function init() { let extWin; let extWinCheck; let commentLikeEvent; // Only run once. if (window.comment_likes_loaded) { return; } window.comment_likes_loaded = true; // Client-side cache of who liked a particular comment to avoid // having to hit the server multiple times for the same data. const commentLikeCache = {}; let swipeLibPromise; // Load the Swipe library, if it's not already loaded. function swipeLibLoader() { if (!swipeLibPromise) { swipeLibPromise = new Promise((resolve, reject) => { if (window.Swipe) { resolve(window.Swipe); } else { const swipeScript = document.createElement('script'); swipeScript.src = comment_like_text.swipeUrl; swipeScript.async = true; document.body.appendChild(swipeScript); swipeScript.addEventListener('load', () => resolve(window.Swipe)); swipeScript.addEventListener('error', error => reject(error)); } }); } return swipeLibPromise; } /** * Parse the comment ID from a comment like link. */ function getCommentId(link) { const commentId = link && link.getAttribute('href') && link.getAttribute('href').split('like_comment='); return commentId[1].split('&_wpnonce=')[0]; } /** * Handle an ajax action on the comment like link. */ function handleLinkAction(link, action, commentId, callback) { const nonce = link && link.getAttribute('href') && link.getAttribute('href').split('_wpnonce=')[1]; fetch('/wp-admin/admin-ajax.php', { method: 'POST', body: new URLSearchParams({ action: action, _wpnonce: nonce, like_comment: commentId, blog_id: Number(link.dataset.blog), }), headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'X-Requested-With': 'XMLHttpRequest', Accept: 'application/json', 'cache-control': 'no-cache', pragma: 'no-cache', }, }) .then(response => response.json()) .then(callback); } function startPolling() { // Append cookie polling login iframe to this window to wait for user to finish logging in (or cancel) const loginIframe = document.createElement('iframe'); loginIframe.id = 'wp-login-polling-iframe'; loginIframe.src = 'https://wordpress.com/public.api/connect/?iframe=true'; document.body.appendChild(loginIframe); loginIframe.style.display = 'none'; } function stopPolling() { const iframe = document.querySelector('#wp-login-polling-iframe'); if (iframe) { iframe.remove(); } } function hide(el) { if (el && el.style) { el.style.display = 'none'; } } function show(el) { if (el && el.style) { el.style.removeProperty('display'); } } // Overlay used for displaying comment like info. class Overlay { constructor() { // Overlay element. this.el = document.createElement('div'); this.el.classList.add('comment-likes-overlay'); document.body.appendChild(this.el); hide(this.el); this.el.addEventListener('mouseenter', () => { // Don't hide the overlay if the user is mousing over it. overlay.cancelHide(); }); this.el.addEventListener('mouseleave', () => overlay.requestHide()); // Inner contents of overlay. this.innerEl = null; // Instance of the Swipe library. this.swipe = null; // Timeout used for hiding the overlay. this.hideTimeout = null; } // Initialise the overlay for use, removing any old content. clear() { // Unload any previous instance of Swipe (to avoid leaking a global // event handler). This is done before clearing the contents of the // overlay because Swipe expects the slides to still be present. if (this.swipe) { this.swipe.kill(); this.swipe = null; } this.el.innerHTML = ''; this.innerEl = document.createElement('div'); this.innerEl.classList.add('inner'); this.el.appendChild(this.innerEl); } /** * Construct a list (