fonts
2 years ago
img
1 year ago
rtl
1 year ago
akismet-admin.css
1 year ago
akismet-admin.js
1 year ago
akismet-frontend.js
2 years ago
akismet.css
1 year ago
akismet.js
1 year ago
akismet.js
422 lines
| 1 | jQuery( function ( $ ) { |
| 2 | var mshotRemovalTimer = null; |
| 3 | var mshotRetryTimer = null; |
| 4 | var mshotTries = 0; |
| 5 | var mshotRetryInterval = 1000; |
| 6 | var mshotEnabledLinkSelector = 'a[id^="author_comment_url"], tr.pingback td.column-author a:first-of-type, td.comment p a'; |
| 7 | |
| 8 | var preloadedMshotURLs = []; |
| 9 | |
| 10 | $('.akismet-status').each(function () { |
| 11 | var thisId = $(this).attr('commentid'); |
| 12 | $(this).prependTo('#comment-' + thisId + ' .column-comment'); |
| 13 | }); |
| 14 | $('.akismet-user-comment-count').each(function () { |
| 15 | var thisId = $(this).attr('commentid'); |
| 16 | $(this).insertAfter('#comment-' + thisId + ' .author strong:first').show(); |
| 17 | }); |
| 18 | |
| 19 | akismet_enable_comment_author_url_removal(); |
| 20 | |
| 21 | $( '#the-comment-list' ).on( 'click', '.akismet_remove_url', function () { |
| 22 | var thisId = $(this).attr('commentid'); |
| 23 | var data = { |
| 24 | action: 'comment_author_deurl', |
| 25 | _wpnonce: WPAkismet.comment_author_url_nonce, |
| 26 | id: thisId |
| 27 | }; |
| 28 | $.ajax({ |
| 29 | url: ajaxurl, |
| 30 | type: 'POST', |
| 31 | data: data, |
| 32 | beforeSend: function () { |
| 33 | // Removes "x" link |
| 34 | $("a[commentid='"+ thisId +"']").hide(); |
| 35 | // Show temp status |
| 36 | $("#author_comment_url_"+ thisId).html( $( '<span/>' ).text( WPAkismet.strings['Removing...'] ) ); |
| 37 | }, |
| 38 | success: function (response) { |
| 39 | if (response) { |
| 40 | // Show status/undo link |
| 41 | $("#author_comment_url_"+ thisId) |
| 42 | .attr('cid', thisId) |
| 43 | .addClass('akismet_undo_link_removal') |
| 44 | .html( |
| 45 | $( '<span/>' ).text( WPAkismet.strings['URL removed'] ) |
| 46 | ) |
| 47 | .append( ' ' ) |
| 48 | .append( |
| 49 | $( '<span/>' ) |
| 50 | .text( WPAkismet.strings['(undo)'] ) |
| 51 | .addClass( 'akismet-span-link' ) |
| 52 | ); |
| 53 | } |
| 54 | } |
| 55 | }); |
| 56 | |
| 57 | return false; |
| 58 | }).on( 'click', '.akismet_undo_link_removal', function () { |
| 59 | var thisId = $(this).attr('cid'); |
| 60 | var thisUrl = $(this).attr('href'); |
| 61 | var data = { |
| 62 | action: 'comment_author_reurl', |
| 63 | _wpnonce: WPAkismet.comment_author_url_nonce, |
| 64 | id: thisId, |
| 65 | url: thisUrl |
| 66 | }; |
| 67 | $.ajax({ |
| 68 | url: ajaxurl, |
| 69 | type: 'POST', |
| 70 | data: data, |
| 71 | beforeSend: function () { |
| 72 | // Show temp status |
| 73 | $("#author_comment_url_"+ thisId).html( $( '<span/>' ).text( WPAkismet.strings['Re-adding...'] ) ); |
| 74 | }, |
| 75 | success: function (response) { |
| 76 | if (response) { |
| 77 | // Add "x" link |
| 78 | $("a[commentid='"+ thisId +"']").show(); |
| 79 | // Show link. Core strips leading http://, so let's do that too. |
| 80 | $("#author_comment_url_"+ thisId).removeClass('akismet_undo_link_removal').text( thisUrl.replace( /^http:\/\/(www\.)?/ig, '' ) ); |
| 81 | } |
| 82 | } |
| 83 | }); |
| 84 | |
| 85 | return false; |
| 86 | }); |
| 87 | |
| 88 | // Show a preview image of the hovered URL. Applies to author URLs and URLs inside the comments. |
| 89 | if ( "enable_mshots" in WPAkismet && WPAkismet.enable_mshots ) { |
| 90 | $( '#the-comment-list' ).on( 'mouseover', mshotEnabledLinkSelector, function () { |
| 91 | clearTimeout( mshotRemovalTimer ); |
| 92 | |
| 93 | if ( $( '.akismet-mshot' ).length > 0 ) { |
| 94 | if ( $( '.akismet-mshot:first' ).data( 'link' ) == this ) { |
| 95 | // The preview is already showing for this link. |
| 96 | return; |
| 97 | } |
| 98 | else { |
| 99 | // A new link is being hovered, so remove the old preview. |
| 100 | $( '.akismet-mshot' ).remove(); |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | clearTimeout( mshotRetryTimer ); |
| 105 | |
| 106 | var linkUrl = $( this ).attr( 'href' ); |
| 107 | |
| 108 | if ( preloadedMshotURLs.indexOf( linkUrl ) !== -1 ) { |
| 109 | // This preview image was already preloaded, so begin with a retry URL so the user doesn't see the placeholder image for the first second. |
| 110 | mshotTries = 2; |
| 111 | } |
| 112 | else { |
| 113 | mshotTries = 1; |
| 114 | } |
| 115 | |
| 116 | var mShot = $( '<div class="akismet-mshot mshot-container"><div class="mshot-arrow"></div><img src="' + akismet_mshot_url( linkUrl, mshotTries ) + '" width="450" height="338" class="mshot-image" /></div>' ); |
| 117 | mShot.data( 'link', this ); |
| 118 | mShot.data( 'url', linkUrl ); |
| 119 | |
| 120 | mShot.find( 'img' ).on( 'load', function () { |
| 121 | $( '.akismet-mshot' ).data( 'pending-request', false ); |
| 122 | } ); |
| 123 | |
| 124 | var offset = $( this ).offset(); |
| 125 | |
| 126 | mShot.offset( { |
| 127 | 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. |
| 128 | top: offset.top + ( $( this ).height() / 2 ) - 101 // 101 = top offset of the arrow plus the top border thickness |
| 129 | } ); |
| 130 | |
| 131 | $( 'body' ).append( mShot ); |
| 132 | |
| 133 | mshotRetryTimer = setTimeout( retryMshotUntilLoaded, mshotRetryInterval ); |
| 134 | } ).on( 'mouseout', 'a[id^="author_comment_url"], tr.pingback td.column-author a:first-of-type, td.comment p a', function () { |
| 135 | mshotRemovalTimer = setTimeout( function () { |
| 136 | clearTimeout( mshotRetryTimer ); |
| 137 | |
| 138 | $( '.akismet-mshot' ).remove(); |
| 139 | }, 200 ); |
| 140 | } ); |
| 141 | |
| 142 | var preloadDelayTimer = null; |
| 143 | |
| 144 | $( window ).on( 'scroll resize', function () { |
| 145 | clearTimeout( preloadDelayTimer ); |
| 146 | |
| 147 | preloadDelayTimer = setTimeout( preloadMshotsInViewport, 500 ); |
| 148 | } ); |
| 149 | |
| 150 | preloadMshotsInViewport(); |
| 151 | } |
| 152 | |
| 153 | /** |
| 154 | * The way mShots works is if there was no screenshot already recently generated for the URL, |
| 155 | * it returns a "loading..." image for the first request. Then, some subsequent request will |
| 156 | * receive the actual screenshot, but it's unknown how long it will take. So, what we do here |
| 157 | * is continually re-request the mShot, waiting a second after every response until we get the |
| 158 | * actual screenshot. |
| 159 | */ |
| 160 | function retryMshotUntilLoaded() { |
| 161 | clearTimeout( mshotRetryTimer ); |
| 162 | |
| 163 | var imageWidth = $( '.akismet-mshot img' ).get(0).naturalWidth; |
| 164 | |
| 165 | if ( imageWidth == 0 ) { |
| 166 | // It hasn't finished loading yet the first time. Check again shortly. |
| 167 | setTimeout( retryMshotUntilLoaded, mshotRetryInterval ); |
| 168 | } |
| 169 | else if ( imageWidth == 400 ) { |
| 170 | // It loaded the preview image. |
| 171 | |
| 172 | if ( mshotTries == 20 ) { |
| 173 | // Give up if we've requested the mShot 20 times already. |
| 174 | return; |
| 175 | } |
| 176 | |
| 177 | if ( ! $( '.akismet-mshot' ).data( 'pending-request' ) ) { |
| 178 | $( '.akismet-mshot' ).data( 'pending-request', true ); |
| 179 | |
| 180 | mshotTries++; |
| 181 | |
| 182 | $( '.akismet-mshot .mshot-image' ).attr( 'src', akismet_mshot_url( $( '.akismet-mshot' ).data( 'url' ), mshotTries ) ); |
| 183 | } |
| 184 | |
| 185 | mshotRetryTimer = setTimeout( retryMshotUntilLoaded, mshotRetryInterval ); |
| 186 | } |
| 187 | else { |
| 188 | // All done. |
| 189 | } |
| 190 | } |
| 191 | |
| 192 | function preloadMshotsInViewport() { |
| 193 | var windowWidth = $( window ).width(); |
| 194 | var windowHeight = $( window ).height(); |
| 195 | |
| 196 | $( '#the-comment-list' ).find( mshotEnabledLinkSelector ).each( function ( index, element ) { |
| 197 | var linkUrl = $( this ).attr( 'href' ); |
| 198 | |
| 199 | // Don't attempt to preload an mshot for a single link twice. |
| 200 | if ( preloadedMshotURLs.indexOf( linkUrl ) !== -1 ) { |
| 201 | // The URL is already preloaded. |
| 202 | return true; |
| 203 | } |
| 204 | |
| 205 | if ( typeof element.getBoundingClientRect !== 'function' ) { |
| 206 | // The browser is too old. Return false to stop this preloading entirely. |
| 207 | return false; |
| 208 | } |
| 209 | |
| 210 | var rect = element.getBoundingClientRect(); |
| 211 | |
| 212 | if ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= windowHeight && rect.right <= windowWidth ) { |
| 213 | akismet_preload_mshot( linkUrl ); |
| 214 | $( this ).data( 'akismet-mshot-preloaded', true ); |
| 215 | } |
| 216 | } ); |
| 217 | } |
| 218 | |
| 219 | $( '.checkforspam.enable-on-load' ).on( 'click', function( e ) { |
| 220 | if ( $( this ).hasClass( 'ajax-disabled' ) ) { |
| 221 | // Akismet hasn't been configured yet. Allow the user to proceed to the button's link. |
| 222 | return; |
| 223 | } |
| 224 | |
| 225 | e.preventDefault(); |
| 226 | |
| 227 | if ( $( this ).hasClass( 'button-disabled' ) ) { |
| 228 | window.location.href = $( this ).data( 'success-url' ).replace( '__recheck_count__', 0 ).replace( '__spam_count__', 0 ); |
| 229 | return; |
| 230 | } |
| 231 | |
| 232 | $('.checkforspam').addClass('button-disabled').addClass( 'checking' ); |
| 233 | $('.checkforspam-spinner').addClass( 'spinner' ).addClass( 'is-active' ); |
| 234 | |
| 235 | akismet_check_for_spam(0, 100); |
| 236 | }).removeClass( 'button-disabled' ); |
| 237 | |
| 238 | var spam_count = 0; |
| 239 | var recheck_count = 0; |
| 240 | |
| 241 | function akismet_check_for_spam(offset, limit) { |
| 242 | var check_for_spam_buttons = $( '.checkforspam' ); |
| 243 | |
| 244 | var nonce = check_for_spam_buttons.data( 'nonce' ); |
| 245 | |
| 246 | // We show the percentage complete down to one decimal point so even queues with 100k |
| 247 | // pending comments will show some progress pretty quickly. |
| 248 | var percentage_complete = Math.round( ( recheck_count / check_for_spam_buttons.data( 'pending-comment-count' ) ) * 1000 ) / 10; |
| 249 | |
| 250 | // Update the progress counter on the "Check for Spam" button. |
| 251 | $( '.checkforspam' ).text( check_for_spam_buttons.data( 'progress-label' ).replace( '%1$s', percentage_complete ) ); |
| 252 | |
| 253 | $.post( |
| 254 | ajaxurl, |
| 255 | { |
| 256 | 'action': 'akismet_recheck_queue', |
| 257 | 'offset': offset, |
| 258 | 'limit': limit, |
| 259 | 'nonce': nonce |
| 260 | }, |
| 261 | function(result) { |
| 262 | if ( 'error' in result ) { |
| 263 | // An error is only returned in the case of a missing nonce, so we don't need the actual error message. |
| 264 | window.location.href = check_for_spam_buttons.data( 'failure-url' ); |
| 265 | return; |
| 266 | } |
| 267 | |
| 268 | recheck_count += result.counts.processed; |
| 269 | spam_count += result.counts.spam; |
| 270 | |
| 271 | if (result.counts.processed < limit) { |
| 272 | window.location.href = check_for_spam_buttons.data( 'success-url' ).replace( '__recheck_count__', recheck_count ).replace( '__spam_count__', spam_count ); |
| 273 | } |
| 274 | else { |
| 275 | // Account for comments that were caught as spam and moved out of the queue. |
| 276 | akismet_check_for_spam(offset + limit - result.counts.spam, limit); |
| 277 | } |
| 278 | } |
| 279 | ); |
| 280 | } |
| 281 | |
| 282 | if ( "start_recheck" in WPAkismet && WPAkismet.start_recheck ) { |
| 283 | $( '.checkforspam:first' ).click(); |
| 284 | } |
| 285 | |
| 286 | if ( typeof MutationObserver !== 'undefined' ) { |
| 287 | // Dynamically add the "X" next the the author URL links when a comment is quick-edited. |
| 288 | var comment_list_container = document.getElementById( 'the-comment-list' ); |
| 289 | |
| 290 | if ( comment_list_container ) { |
| 291 | var observer = new MutationObserver( function ( mutations ) { |
| 292 | for ( var i = 0, _len = mutations.length; i < _len; i++ ) { |
| 293 | if ( mutations[i].addedNodes.length > 0 ) { |
| 294 | akismet_enable_comment_author_url_removal(); |
| 295 | |
| 296 | // Once we know that we'll have to check for new author links, skip the rest of the mutations. |
| 297 | break; |
| 298 | } |
| 299 | } |
| 300 | } ); |
| 301 | |
| 302 | observer.observe( comment_list_container, { attributes: true, childList: true, characterData: true } ); |
| 303 | } |
| 304 | } |
| 305 | |
| 306 | function akismet_enable_comment_author_url_removal() { |
| 307 | $( '#the-comment-list' ) |
| 308 | .find( 'tr.comment, tr[id ^= "comment-"]' ) |
| 309 | .find( '.column-author a[href^="http"]:first' ) // Ignore mailto: links, which would be the comment author's email. |
| 310 | .each(function () { |
| 311 | if ( $( this ).parent().find( '.akismet_remove_url' ).length > 0 ) { |
| 312 | return; |
| 313 | } |
| 314 | |
| 315 | var linkHref = $(this).attr( 'href' ); |
| 316 | |
| 317 | // Ignore any links to the current domain, which are diagnostic tools, like the IP address link |
| 318 | // or any other links another plugin might add. |
| 319 | var currentHostParts = document.location.href.split( '/' ); |
| 320 | var currentHost = currentHostParts[0] + '//' + currentHostParts[2] + '/'; |
| 321 | |
| 322 | if ( linkHref.indexOf( currentHost ) != 0 ) { |
| 323 | var thisCommentId = $(this).parents('tr:first').attr('id').split("-"); |
| 324 | |
| 325 | $(this) |
| 326 | .attr("id", "author_comment_url_"+ thisCommentId[1]) |
| 327 | .after( |
| 328 | $( '<a href="#" class="akismet_remove_url">x</a>' ) |
| 329 | .attr( 'commentid', thisCommentId[1] ) |
| 330 | .attr( 'title', WPAkismet.strings['Remove this URL'] ) |
| 331 | ); |
| 332 | } |
| 333 | }); |
| 334 | } |
| 335 | |
| 336 | /** |
| 337 | * Generate an mShot URL if given a link URL. |
| 338 | * |
| 339 | * @param string linkUrl |
| 340 | * @param int retry If retrying a request, the number of the retry. |
| 341 | * @return string The mShot URL; |
| 342 | */ |
| 343 | function akismet_mshot_url( linkUrl, retry ) { |
| 344 | var mshotUrl = '//s0.wp.com/mshots/v1/' + encodeURIComponent( linkUrl ) + '?w=900'; |
| 345 | |
| 346 | if ( retry > 1 ) { |
| 347 | mshotUrl += '&r=' + encodeURIComponent( retry ); |
| 348 | } |
| 349 | |
| 350 | mshotUrl += '&source=akismet'; |
| 351 | |
| 352 | return mshotUrl; |
| 353 | } |
| 354 | |
| 355 | /** |
| 356 | * Begin loading an mShot preview of a link. |
| 357 | * |
| 358 | * @param string linkUrl |
| 359 | */ |
| 360 | function akismet_preload_mshot( linkUrl ) { |
| 361 | var img = new Image(); |
| 362 | img.src = akismet_mshot_url( linkUrl ); |
| 363 | |
| 364 | preloadedMshotURLs.push( linkUrl ); |
| 365 | } |
| 366 | |
| 367 | $( '.akismet-could-be-primary' ).each( function () { |
| 368 | var form = $( this ).closest( 'form' ); |
| 369 | |
| 370 | form.data( 'initial-state', form.serialize() ); |
| 371 | |
| 372 | form.on( 'change keyup', function () { |
| 373 | var self = $( this ); |
| 374 | var submit_button = self.find( '.akismet-could-be-primary' ); |
| 375 | |
| 376 | if ( self.serialize() != self.data( 'initial-state' ) ) { |
| 377 | submit_button.addClass( 'akismet-is-primary' ); |
| 378 | } |
| 379 | else { |
| 380 | submit_button.removeClass( 'akismet-is-primary' ); |
| 381 | } |
| 382 | } ); |
| 383 | } ); |
| 384 | |
| 385 | /** |
| 386 | * Shows the Enter API key form |
| 387 | */ |
| 388 | $( '.akismet-enter-api-key-box__reveal' ).on( 'click', function ( e ) { |
| 389 | e.preventDefault(); |
| 390 | |
| 391 | var div = $( '.akismet-enter-api-key-box__form-wrapper' ); |
| 392 | div.show( 500 ); |
| 393 | div.find( 'input[name=key]' ).focus(); |
| 394 | |
| 395 | $( this ).hide(); |
| 396 | } ); |
| 397 | |
| 398 | /** |
| 399 | * Hides the Connect with Jetpack form | Shows the Activate Akismet Account form |
| 400 | */ |
| 401 | $( 'a.toggle-ak-connect' ).on( 'click', function ( e ) { |
| 402 | e.preventDefault(); |
| 403 | |
| 404 | $( '.akismet-ak-connect' ).slideToggle('slow'); |
| 405 | $( 'a.toggle-ak-connect' ).hide(); |
| 406 | $( '.akismet-jp-connect' ).hide(); |
| 407 | $( 'a.toggle-jp-connect' ).show(); |
| 408 | } ); |
| 409 | |
| 410 | /** |
| 411 | * Shows the Connect with Jetpack form | Hides the Activate Akismet Account form |
| 412 | */ |
| 413 | $( 'a.toggle-jp-connect' ).on( 'click', function ( e ) { |
| 414 | e.preventDefault(); |
| 415 | |
| 416 | $( '.akismet-jp-connect' ).slideToggle('slow'); |
| 417 | $( 'a.toggle-jp-connect' ).hide(); |
| 418 | $( '.akismet-ak-connect' ).hide(); |
| 419 | $( 'a.toggle-ak-connect' ).show(); |
| 420 | } ); |
| 421 | }); |
| 422 |