| @@ -10,85 +10,176 @@ | ||
| 10 | 10 | * Text Domain: akismet |
| 11 | 11 | * |
| 12 | 12 | */ |
| 13 | 13 | |
| 14 | - jQuery(document).ready(function ($) { | |
| 14 | +jQuery(function($) { | |
| 15 | + const MSHOT_REFRESH_DELAY = 6000; | |
| 16 | + const MSHOT_REFRESH_QUERY_ARG = 'mainwp_mshot_refresh'; | |
| 15 | 17 | |
| 18 | + function mainwp_preview_append_cache_bust(url, token) { | |
| 19 | + if (!url) { | |
| 20 | + return url; | |
| 21 | + } | |
| 22 | + | |
| 23 | + let separator = url.indexOf('?') === -1 ? '?' : '&'; | |
| 24 | + | |
| 25 | + return url + separator + MSHOT_REFRESH_QUERY_ARG + '=' + encodeURIComponent(token + '-' + Date.now()); | |
| 26 | + } | |
| 27 | + | |
| 28 | + function mainwp_preview_get_button_mshot_url(element, requeue) { | |
| 29 | + let attrName = requeue ? 'data-mainwp-mshot-requeue-src' : 'data-mainwp-mshot-src'; | |
| 30 | + let mshotUrl = $(element).attr(attrName); | |
| 31 | + | |
| 32 | + if (mshotUrl) { | |
| 33 | + return mshotUrl; | |
| 34 | + } | |
| 35 | + | |
| 36 | + let linkUrl = $(element).attr('preview-site-url'); | |
| 37 | + | |
| 38 | + if (!linkUrl) { | |
| 39 | + return ''; | |
| 40 | + } | |
| 41 | + | |
| 42 | + mshotUrl = '//s0.wp.com/mshots/v1/' + encodeURIComponent(linkUrl) + '?w=900'; | |
| 43 | + | |
| 44 | + if (requeue) { | |
| 45 | + mshotUrl += '&requeue=true'; | |
| 46 | + } | |
| 47 | + | |
| 48 | + return mshotUrl; | |
| 49 | + } | |
| 50 | + | |
| 51 | + function mainwp_preview_clear_image_recovery(img) { | |
| 52 | + if (img && img.mainwpMshotRecoveryTimer) { | |
| 53 | + clearTimeout(img.mainwpMshotRecoveryTimer); | |
| 54 | + img.mainwpMshotRecoveryTimer = null; | |
| 55 | + } | |
| 56 | + } | |
| 57 | + | |
| 58 | + function mainwp_preview_queue_image_recovery(img) { | |
| 59 | + if (!img || img.dataset.mainwpMshotRecoveryRequested === '1') { | |
| 60 | + return; | |
| 61 | + } | |
| 62 | + | |
| 63 | + let primarySrc = img.getAttribute('data-mainwp-mshot-src') || img.getAttribute('data-src') || img.getAttribute('src'); | |
| 64 | + let requeueSrc = img.getAttribute('data-mainwp-mshot-requeue-src'); | |
| 65 | + | |
| 66 | + if (!primarySrc || !requeueSrc) { | |
| 67 | + return; | |
| 68 | + } | |
| 69 | + | |
| 70 | + img.dataset.mainwpMshotRecoveryRequested = '1'; | |
| 71 | + mainwp_preview_clear_image_recovery(img); | |
| 72 | + | |
| 73 | + // Ask mShots to regenerate the thumbnail once, then retry the canonical URL. | |
| 74 | + img.setAttribute('src', mainwp_preview_append_cache_bust(requeueSrc, 'requeue')); | |
| 75 | + img.mainwpMshotRecoveryTimer = setTimeout(function () { | |
| 76 | + img.setAttribute('src', mainwp_preview_append_cache_bust(primarySrc, 'reload')); | |
| 77 | + }, MSHOT_REFRESH_DELAY); | |
| 78 | + } | |
| 79 | + | |
| 80 | + if (!window.mainwpPreviewImageRecoveryBound) { | |
| 81 | + document.addEventListener('error', function (event) { | |
| 82 | + let target = event.target; | |
| 83 | + | |
| 84 | + if (target && target.tagName === 'IMG') { | |
| 85 | + mainwp_preview_queue_image_recovery(target); | |
| 86 | + } | |
| 87 | + }, true); | |
| 88 | + | |
| 89 | + window.mainwpPreviewImageRecoveryBound = true; | |
| 90 | + } | |
| 91 | + | |
| 16 | 92 | /** |
| 17 | 93 | * Init site preview function. |
| 18 | 94 | */ |
| 19 | - mainwp_preview_init_event = function() { | |
| 20 | - var mshotRemovalTimer = null; | |
| 21 | - var mshotSecondTryTimer = null | |
| 22 | - var mshotThirdTryTimer = null | |
| 95 | + window.mainwp_preview_init_event = function () { | |
| 96 | + let mshotRemovalTimer = null; | |
| 97 | + let mshotSecondTryTimer = null; | |
| 98 | + let mshotThirdTryTimer = null; | |
| 99 | + let previewTableSelector = '.mainwp-with-preview-table'; | |
| 100 | + let mshotEnabledLinkSelector = 'td span.mainwp-preview-item'; | |
| 23 | 101 | |
| 24 | - var mshotEnabledLinkSelector = 'td span.mainwp-preview-item'; | |
| 25 | - | |
| 26 | 102 | // Show a preview image of the hovered URL. |
| 27 | - $( '.mainwp-with-preview-table' ).on( 'click', mshotEnabledLinkSelector, function () { | |
| 28 | - clearTimeout( mshotRemovalTimer ); | |
| 103 | + $(previewTableSelector).off('.mainwpPreview').on('click.mainwpPreview', mshotEnabledLinkSelector, function () { | |
| 104 | + clearTimeout(mshotRemovalTimer); | |
| 29 | 105 | |
| 30 | - if ( $( '.mainwp-preview-mshot' ).length > 0 ) { | |
| 31 | - if ( $( '.mainwp-preview-mshot:first' ).data( 'link' ) == this ) { | |
| 106 | + if ($('.mainwp-preview-mshot').length > 0) { | |
| 107 | + if ($('.mainwp-preview-mshot:first').data('link') == this) { | |
| 32 | 108 | // The preview is already showing for this link. |
| 33 | 109 | return; |
| 34 | 110 | } |
| 35 | 111 | else { |
| 36 | 112 | // A new link is being hovered, so remove the old preview. |
| 37 | - $( '.mainwp-preview-mshot' ).remove(); | |
| 113 | + let existingImage = $('.mainwp-preview-mshot .mshot-image').get(0); | |
| 114 | + mainwp_preview_clear_image_recovery(existingImage); | |
| 115 | + $('.mainwp-preview-mshot').remove(); | |
| 38 | 116 | } |
| 39 | 117 | } |
| 40 | 118 | |
| 41 | - clearTimeout( mshotSecondTryTimer ); | |
| 42 | - clearTimeout( mshotThirdTryTimer ); | |
| 119 | + clearTimeout(mshotSecondTryTimer); | |
| 120 | + clearTimeout(mshotThirdTryTimer); | |
| 43 | 121 | |
| 44 | - var thisHref = $( this ).attr( 'preview-site-url' ); | |
| 122 | + let primarySrc = mainwp_preview_get_button_mshot_url(this, false); | |
| 123 | + let requeueSrc = mainwp_preview_get_button_mshot_url(this, true); | |
| 124 | + let $image = $('<img />', { | |
| 125 | + src: primarySrc, | |
| 126 | + width: 450, | |
| 127 | + height: 338, | |
| 128 | + class: 'mshot-image' | |
| 129 | + }); | |
| 130 | + let mShot = $('<div class="mainwp-preview-mshot mshot-container"><div class="mshot-arrow"></div></div>'); | |
| 45 | 131 | |
| 46 | - var mShot = $( '<div class="mainwp-preview-mshot mshot-container"><div class="mshot-arrow"></div><img src="' + mainwp_preview_mshot_url( thisHref ) + '" width="450" height="338" class="mshot-image" /></div>' ); | |
| 47 | - mShot.data( 'link', this ); | |
| 132 | + $image.attr('data-mainwp-mshot-src', primarySrc); | |
| 133 | + $image.attr('data-mainwp-mshot-requeue-src', requeueSrc); | |
| 134 | + mShot.append($image); | |
| 135 | + mShot.data('link', this); | |
| 48 | 136 | |
| 49 | - var offset = $( this ).offset(); | |
| 137 | + let offset = $(this).offset(); | |
| 50 | 138 | |
| 51 | - mShot.offset( { | |
| 52 | - left : Math.min( $( window ).width() - 475, offset.left + $( this ).width() + 10 ), // Keep it on the screen if the link is near the edge of the window. | |
| 53 | - top: offset.top + ( $( this ).height() / 2 ) - 101 // 101 = top offset of the arrow plus the top border thickness | |
| 54 | - } ); | |
| 139 | + mShot.offset({ | |
| 140 | + left: Math.min($(window).width() - 475, offset.left + $(this).width() + 10), // Keep it on the screen if the link is near the edge of the window. | |
| 141 | + top: offset.top + ($(this).height() / 2) - 101 // 101 = top offset of the arrow plus the top border thickness | |
| 142 | + }); | |
| 55 | 143 | |
| 56 | 144 | // These retries appear to be superfluous if .mshot-image has already loaded, but it's because mShots |
| 57 | 145 | // can return a "Generating thumbnail..." image if it doesn't have a thumbnail ready, so we need |
| 58 | 146 | // to retry to see if we can get the newly generated thumbnail. |
| 59 | - mshotSecondTryTimer = setTimeout( function () { | |
| 60 | - mShot.find( '.mshot-image' ).attr( 'src', mainwp_preview_mshot_url( thisHref, 2 ) ); | |
| 61 | - }, 6000 ); | |
| 147 | + mshotSecondTryTimer = setTimeout(function () { | |
| 148 | + mShot.find('.mshot-image').attr('src', mainwp_preview_append_cache_bust(primarySrc, 'retry-2')); | |
| 149 | + }, MSHOT_REFRESH_DELAY); | |
| 62 | 150 | |
| 63 | - mshotThirdTryTimer = setTimeout( function () { | |
| 64 | - mShot.find( '.mshot-image' ).attr( 'src', mainwp_preview_mshot_url( thisHref, 3 ) ); | |
| 65 | - }, 12000 ); | |
| 151 | + mshotThirdTryTimer = setTimeout(function () { | |
| 152 | + mShot.find('.mshot-image').attr('src', mainwp_preview_append_cache_bust(primarySrc, 'retry-3')); | |
| 153 | + }, MSHOT_REFRESH_DELAY * 2); | |
| 66 | 154 | |
| 67 | - $( 'body' ).append( mShot ); | |
| 68 | - } ).on( 'mouseover', 'tr', function () { | |
| 155 | + $('body').append(mShot); | |
| 156 | + }).on('mouseover.mainwpPreview', 'tr', function () { | |
| 69 | 157 | // When the mouse hovers over a row, begin preloading mshots for links. |
| 70 | - var linksToPreloadMshotsFor = $( this ).find( mshotEnabledLinkSelector ); | |
| 158 | + let linksToPreloadMshotsFor = $(this).find(mshotEnabledLinkSelector); | |
| 71 | 159 | |
| 72 | - linksToPreloadMshotsFor.each( function () { | |
| 160 | + linksToPreloadMshotsFor.each(function () { | |
| 73 | 161 | // Don't attempt to preload an mshot for a single link twice. Browser caching should cover this, but in case of |
| 74 | 162 | // race conditions, save a flag locally when we've begun trying to preload one. |
| 75 | - if ( ! $( this ).data( 'mainwp-preview-mshot-preloaded' ) ) { | |
| 76 | - mainwp_preview_preload_mshot( $( this ).attr( 'preview-site-url' ) ); | |
| 77 | - $( this ).data( 'mainwp-preview-mshot-preloaded', true ); | |
| 163 | + if (!$(this).data('mainwp-preview-mshot-preloaded')) { | |
| 164 | + mainwp_preview_preload_mshot(this); | |
| 165 | + $(this).data('mainwp-preview-mshot-preloaded', true); | |
| 78 | 166 | } |
| 79 | - } ); | |
| 80 | - } ); | |
| 167 | + }); | |
| 168 | + }); | |
| 81 | 169 | |
| 82 | - $( document ).on( 'mouseup', function () { | |
| 83 | - if ( $( '.mainwp-preview-mshot' ).length > 0 ) { | |
| 84 | - mshotRemovalTimer = setTimeout( function () { | |
| 85 | - clearTimeout( mshotSecondTryTimer ); | |
| 86 | - clearTimeout( mshotThirdTryTimer ); | |
| 87 | - $( '.mainwp-preview-mshot' ).remove(); | |
| 88 | - }, 100 ); | |
| 89 | - } | |
| 90 | - } ); | |
| 170 | + $(document).off('mouseup.mainwpPreview').on('mouseup.mainwpPreview', function () { | |
| 171 | + if ($('.mainwp-preview-mshot').length > 0) { | |
| 172 | + mshotRemovalTimer = setTimeout(function () { | |
| 173 | + clearTimeout(mshotSecondTryTimer); | |
| 174 | + clearTimeout(mshotThirdTryTimer); | |
| 175 | + let previewImage = $('.mainwp-preview-mshot .mshot-image').get(0); | |
| 176 | + | |
| 177 | + mainwp_preview_clear_image_recovery(previewImage); | |
| 178 | + $('.mainwp-preview-mshot').remove(); | |
| 179 | + }, 100); | |
| 180 | + } | |
| 181 | + }); | |
| 91 | 182 | }; |
| 92 | 183 | |
| 93 | 184 | // init preview. |
| 94 | 185 | mainwp_preview_init_event(); |
| @@ -93,30 +184,17 @@ | ||
| 93 | 184 | // init preview. |
| 94 | 185 | mainwp_preview_init_event(); |
| 95 | 186 | |
| 96 | 187 | /** |
| 97 | - * Generate an mShot URL if given a link URL. | |
| 188 | + * Begin loading an mShot preview of a link. | |
| 98 | 189 | * |
| 99 | - * @param string linkUrl | |
| 100 | - * @param int retry If retrying a request, the number of the retry. | |
| 101 | - * @return string The mShot URL; | |
| 190 | + * @param object linkElement Preview trigger element. | |
| 102 | 191 | */ |
| 103 | - function mainwp_preview_mshot_url( linkUrl, retry ) { | |
| 104 | - var mshotUrl = '//s0.wordpress.com/mshots/v1/' + encodeURIComponent( linkUrl ) + '?w=900'; | |
| 192 | + function mainwp_preview_preload_mshot(linkElement) { | |
| 193 | + let img = new Image(); | |
| 194 | + let primarySrc = mainwp_preview_get_button_mshot_url(linkElement, false); | |
| 105 | 195 | |
| 106 | - if ( retry ) { | |
| 107 | - mshotUrl += '&r=' + encodeURIComponent( retry ); | |
| 196 | + if (primarySrc) { | |
| 197 | + img.src = primarySrc; | |
| 108 | 198 | } |
| 109 | - | |
| 110 | - return mshotUrl; | |
| 111 | - } | |
| 112 | - | |
| 113 | - /** | |
| 114 | - * Begin loading an mShot preview of a link. | |
| 115 | - * | |
| 116 | - * @param string linkUrl | |
| 117 | - */ | |
| 118 | - function mainwp_preview_preload_mshot( linkUrl ) { | |
| 119 | - var img = new Image(); | |
| 120 | - img.src = mainwp_preview_mshot_url( linkUrl ); | |
| 121 | 199 | } |
| 122 | 200 | }); |