angelovcom.net

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

akismet.js (13254B)


      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' ).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 a' ).on( 'click', function ( e ) {
    389 		e.preventDefault();
    390 
    391 		var div = $( '.enter-api-key' );
    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 });