wp/wp-admin/js/updates.js
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
child 22 8c2e4d02f4ef
equal deleted inserted replaced
20:7b1b88e27a20 21:48c4eec2b7e6
     3  *
     3  *
     4  * @version 4.2.0
     4  * @version 4.2.0
     5  * @output wp-admin/js/updates.js
     5  * @output wp-admin/js/updates.js
     6  */
     6  */
     7 
     7 
     8 /* global pagenow */
     8 /* global pagenow, _wpThemeSettings */
     9 
     9 
    10 /**
    10 /**
    11  * @param {jQuery}  $                                        jQuery object.
    11  * @param {jQuery}  $                                        jQuery object.
    12  * @param {object}  wp                                       WP object.
    12  * @param {object}  wp                                       WP object.
    13  * @param {object}  settings                                 WP Updates settings.
    13  * @param {object}  settings                                 WP Updates settings.
   412 			$( '.subsubsub li:last' ).html( function() { return $( this ).children(); } );
   412 			$( '.subsubsub li:last' ).html( function() { return $( this ).children(); } );
   413 		}
   413 		}
   414 	};
   414 	};
   415 
   415 
   416 	/**
   416 	/**
       
   417 	 * Sends a message from a modal to the main screen to update buttons in plugin cards.
       
   418 	 *
       
   419 	 * @since 6.5.0
       
   420 	 *
       
   421 	 * @param {Object}  data               An object of data to use for the button.
       
   422 	 * @param {string}  data.slug          The plugin's slug.
       
   423 	 * @param {string}  data.text          The text to use for the button.
       
   424 	 * @param {string}  data.ariaLabel     The value for the button's aria-label attribute. An empty string removes the attribute.
       
   425 	 * @param {string=} data.status        Optional. An identifier for the status.
       
   426 	 * @param {string=} data.removeClasses Optional. A space-separated list of classes to remove from the button.
       
   427 	 * @param {string=} data.addClasses    Optional. A space-separated list of classes to add to the button.
       
   428 	 * @param {string=} data.href          Optional. The button's URL.
       
   429 	 * @param {string=} data.pluginName    Optional. The plugin's name.
       
   430 	 * @param {string=} data.plugin        Optional. The plugin file, relative to the plugins directory.
       
   431 	 */
       
   432 	wp.updates.setCardButtonStatus = function( data ) {
       
   433 		var target = window.parent === window ? null : window.parent;
       
   434 
       
   435 		$.support.postMessage = !! window.postMessage;
       
   436 		if ( false !== $.support.postMessage && null !== target && -1 === window.parent.location.pathname.indexOf( 'index.php' ) ) {
       
   437 			target.postMessage( JSON.stringify( data ), window.location.origin );
       
   438 		}
       
   439 	};
       
   440 
       
   441 	/**
   417 	 * Decrements the update counts throughout the various menus.
   442 	 * Decrements the update counts throughout the various menus.
   418 	 *
   443 	 *
   419 	 * This includes the toolbar, the "Updates" menu item and the menu items
   444 	 * This includes the toolbar, the "Updates" menu item and the menu items
   420 	 * for plugins and themes.
   445 	 * for plugins and themes.
   421 	 *
   446 	 *
   450 	 * @return {$.promise} A jQuery promise that represents the request,
   475 	 * @return {$.promise} A jQuery promise that represents the request,
   451 	 *                     decorated with an abort() method.
   476 	 *                     decorated with an abort() method.
   452 	 */
   477 	 */
   453 	wp.updates.updatePlugin = function( args ) {
   478 	wp.updates.updatePlugin = function( args ) {
   454 		var $updateRow, $card, $message, message,
   479 		var $updateRow, $card, $message, message,
   455 			$adminBarUpdates = $( '#wp-admin-bar-updates' );
   480 			$adminBarUpdates = $( '#wp-admin-bar-updates' ),
       
   481 			buttonText = __( 'Updating...' ),
       
   482 			isPluginInstall = 'plugin-install' === pagenow || 'plugin-install-network' === pagenow;
   456 
   483 
   457 		args = _.extend( {
   484 		args = _.extend( {
   458 			success: wp.updates.updatePluginSuccess,
   485 			success: wp.updates.updatePluginSuccess,
   459 			error: wp.updates.updatePluginError
   486 			error: wp.updates.updatePluginError
   460 		}, args );
   487 		}, args );
   465 			message    = sprintf(
   492 			message    = sprintf(
   466 				/* translators: %s: Plugin name and version. */
   493 				/* translators: %s: Plugin name and version. */
   467  				_x( 'Updating %s...', 'plugin' ),
   494  				_x( 'Updating %s...', 'plugin' ),
   468 				$updateRow.find( '.plugin-title strong' ).text()
   495 				$updateRow.find( '.plugin-title strong' ).text()
   469 			);
   496 			);
   470 		} else if ( 'plugin-install' === pagenow || 'plugin-install-network' === pagenow ) {
   497 		} else if ( isPluginInstall ) {
   471 			$card    = $( '.plugin-card-' + args.slug );
   498 			$card    = $( '.plugin-card-' + args.slug + ', #plugin-information-footer' );
   472 			$message = $card.find( '.update-now' ).addClass( 'updating-message' );
   499 			$message = $card.find( '.update-now' ).addClass( 'updating-message' );
   473 			message    = sprintf(
   500 			message    = sprintf(
   474 				/* translators: %s: Plugin name and version. */
   501 				/* translators: %s: Plugin name and version. */
   475  				_x( 'Updating %s...', 'plugin' ),
   502  				_x( 'Updating %s...', 'plugin' ),
   476 				$message.data( 'name' )
   503 				$message.data( 'name' )
   486 			$message.data( 'originaltext', $message.html() );
   513 			$message.data( 'originaltext', $message.html() );
   487 		}
   514 		}
   488 
   515 
   489 		$message
   516 		$message
   490 			.attr( 'aria-label', message )
   517 			.attr( 'aria-label', message )
   491 			.text( __( 'Updating...' ) );
   518 			.text( buttonText );
   492 
   519 
   493 		$document.trigger( 'wp-plugin-updating', args );
   520 		$document.trigger( 'wp-plugin-updating', args );
       
   521 
       
   522 		if ( isPluginInstall && 'plugin-information-footer' === $card.attr( 'id' ) ) {
       
   523 			wp.updates.setCardButtonStatus(
       
   524 				{
       
   525 					status: 'updating-plugin',
       
   526 					slug: args.slug,
       
   527 					addClasses: 'updating-message',
       
   528 					text: buttonText,
       
   529 					ariaLabel: message
       
   530 				}
       
   531 			);
       
   532 		}
   494 
   533 
   495 		return wp.updates.ajax( 'update-plugin', args );
   534 		return wp.updates.ajax( 'update-plugin', args );
   496 	};
   535 	};
   497 
   536 
   498 	/**
   537 	/**
   509 	 * @param {string} response.oldVersion Old version of the plugin.
   548 	 * @param {string} response.oldVersion Old version of the plugin.
   510 	 * @param {string} response.newVersion New version of the plugin.
   549 	 * @param {string} response.newVersion New version of the plugin.
   511 	 */
   550 	 */
   512 	wp.updates.updatePluginSuccess = function( response ) {
   551 	wp.updates.updatePluginSuccess = function( response ) {
   513 		var $pluginRow, $updateMessage, newText,
   552 		var $pluginRow, $updateMessage, newText,
   514 			$adminBarUpdates = $( '#wp-admin-bar-updates' );
   553 			$adminBarUpdates = $( '#wp-admin-bar-updates' ),
       
   554 			buttonText = _x( 'Updated!', 'plugin' ),
       
   555 			ariaLabel = sprintf(
       
   556 				/* translators: %s: Plugin name and version. */
       
   557 				_x( '%s updated!', 'plugin' ),
       
   558 				response.pluginName
       
   559 			);
   515 
   560 
   516 		if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
   561 		if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
   517 			$pluginRow     = $( 'tr[data-plugin="' + response.plugin + '"]' )
   562 			$pluginRow     = $( 'tr[data-plugin="' + response.plugin + '"]' )
   518 				.removeClass( 'update' )
   563 				.removeClass( 'update is-enqueued' )
   519 				.addClass( 'updated' );
   564 				.addClass( 'updated' );
   520 			$updateMessage = $pluginRow.find( '.update-message' )
   565 			$updateMessage = $pluginRow.find( '.update-message' )
   521 				.removeClass( 'updating-message notice-warning' )
   566 				.removeClass( 'updating-message notice-warning' )
   522 				.addClass( 'updated-message notice-success' ).find( 'p' );
   567 				.addClass( 'updated-message notice-success' ).find( 'p' );
   523 
   568 
   526 			$pluginRow.find( '.plugin-version-author-uri' ).html( newText );
   571 			$pluginRow.find( '.plugin-version-author-uri' ).html( newText );
   527 
   572 
   528 			// Clear the "time to next auto-update" text.
   573 			// Clear the "time to next auto-update" text.
   529 			$pluginRow.find( '.auto-update-time' ).empty();
   574 			$pluginRow.find( '.auto-update-time' ).empty();
   530 		} else if ( 'plugin-install' === pagenow || 'plugin-install-network' === pagenow ) {
   575 		} else if ( 'plugin-install' === pagenow || 'plugin-install-network' === pagenow ) {
   531 			$updateMessage = $( '.plugin-card-' + response.slug ).find( '.update-now' )
   576 			$updateMessage = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ).find( '.update-now' )
   532 				.removeClass( 'updating-message' )
   577 				.removeClass( 'updating-message' )
   533 				.addClass( 'button-disabled updated-message' );
   578 				.addClass( 'button-disabled updated-message' );
   534 		}
   579 		}
   535 
   580 
   536 		$adminBarUpdates.removeClass( 'spin' );
   581 		$adminBarUpdates.removeClass( 'spin' );
   537 
   582 
   538 		$updateMessage
   583 		$updateMessage
   539 			.attr(
   584 			.attr( 'aria-label', ariaLabel )
   540 				'aria-label',
   585 			.text( buttonText );
   541 				sprintf(
       
   542 					/* translators: %s: Plugin name and version. */
       
   543 					_x( '%s updated!', 'plugin' ),
       
   544 					response.pluginName
       
   545 				)
       
   546 			)
       
   547 			.text( _x( 'Updated!', 'plugin' ) );
       
   548 
   586 
   549 		wp.a11y.speak( __( 'Update completed successfully.' ) );
   587 		wp.a11y.speak( __( 'Update completed successfully.' ) );
   550 
   588 
   551 		wp.updates.decrementCount( 'plugin' );
   589 		if ( 'plugin_install_from_iframe' !== $updateMessage.attr( 'id' ) ) {
       
   590 			wp.updates.decrementCount( 'plugin' );
       
   591 		} else {
       
   592 			wp.updates.setCardButtonStatus(
       
   593 				{
       
   594 					status: 'updated-plugin',
       
   595 					slug: response.slug,
       
   596 					removeClasses: 'updating-message',
       
   597 					addClasses: 'button-disabled updated-message',
       
   598 					text: buttonText,
       
   599 					ariaLabel: ariaLabel
       
   600 				}
       
   601 			);
       
   602 		}
   552 
   603 
   553 		$document.trigger( 'wp-plugin-update-success', response );
   604 		$document.trigger( 'wp-plugin-update-success', response );
   554 	};
   605 	};
   555 
   606 
   556 	/**
   607 	/**
   565 	 * @param {string=} response.pluginName   Optional. Name of the plugin to be updated.
   616 	 * @param {string=} response.pluginName   Optional. Name of the plugin to be updated.
   566 	 * @param {string}  response.errorCode    Error code for the error that occurred.
   617 	 * @param {string}  response.errorCode    Error code for the error that occurred.
   567 	 * @param {string}  response.errorMessage The error that occurred.
   618 	 * @param {string}  response.errorMessage The error that occurred.
   568 	 */
   619 	 */
   569 	wp.updates.updatePluginError = function( response ) {
   620 	wp.updates.updatePluginError = function( response ) {
   570 		var $card, $message, errorMessage,
   621 		var $pluginRow, $card, $message, errorMessage, buttonText, ariaLabel,
   571 			$adminBarUpdates = $( '#wp-admin-bar-updates' );
   622 			$adminBarUpdates = $( '#wp-admin-bar-updates' );
   572 
   623 
   573 		if ( ! wp.updates.isValidResponse( response, 'update' ) ) {
   624 		if ( ! wp.updates.isValidResponse( response, 'update' ) ) {
   574 			return;
   625 			return;
   575 		}
   626 		}
   583 			__( 'Update failed: %s' ),
   634 			__( 'Update failed: %s' ),
   584 			response.errorMessage
   635 			response.errorMessage
   585 		);
   636 		);
   586 
   637 
   587 		if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
   638 		if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
       
   639 			$pluginRow = $( 'tr[data-plugin="' + response.plugin + '"]' ).removeClass( 'is-enqueued' );
       
   640 
   588 			if ( response.plugin ) {
   641 			if ( response.plugin ) {
   589 				$message = $( 'tr[data-plugin="' + response.plugin + '"]' ).find( '.update-message' );
   642 				$message = $( 'tr[data-plugin="' + response.plugin + '"]' ).find( '.update-message' );
   590 			} else {
   643 			} else {
   591 				$message = $( 'tr[data-slug="' + response.slug + '"]' ).find( '.update-message' );
   644 				$message = $( 'tr[data-slug="' + response.slug + '"]' ).find( '.update-message' );
   592 			}
   645 			}
   604 					);
   657 					);
   605 			} else {
   658 			} else {
   606 				$message.find( 'p' ).removeAttr( 'aria-label' );
   659 				$message.find( 'p' ).removeAttr( 'aria-label' );
   607 			}
   660 			}
   608 		} else if ( 'plugin-install' === pagenow || 'plugin-install-network' === pagenow ) {
   661 		} else if ( 'plugin-install' === pagenow || 'plugin-install-network' === pagenow ) {
   609 			$card = $( '.plugin-card-' + response.slug )
   662 			buttonText = __( 'Update failed.' );
   610 				.addClass( 'plugin-card-update-failed' )
   663 
       
   664 			$card = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' )
   611 				.append( wp.updates.adminNotice( {
   665 				.append( wp.updates.adminNotice( {
   612 					className: 'update-message notice-error notice-alt is-dismissible',
   666 					className: 'update-message notice-error notice-alt is-dismissible',
   613 					message:   errorMessage
   667 					message:   errorMessage
   614 				} ) );
   668 				} ) );
   615 
   669 
       
   670 			if ( $card.hasClass( 'plugin-card-' + response.slug ) ) {
       
   671 				$card.addClass( 'plugin-card-update-failed' );
       
   672 			}
       
   673 
   616 			$card.find( '.update-now' )
   674 			$card.find( '.update-now' )
   617 				.text(  __( 'Update failed.' ) )
   675 				.text( buttonText )
   618 				.removeClass( 'updating-message' );
   676 				.removeClass( 'updating-message' );
   619 
   677 
   620 			if ( response.pluginName ) {
   678 			if ( response.pluginName ) {
   621 				$card.find( '.update-now' )
   679 				ariaLabel = sprintf(
   622 					.attr(
   680 					/* translators: %s: Plugin name and version. */
   623 						'aria-label',
   681 					_x( '%s update failed.', 'plugin' ),
   624 						sprintf(
   682 					response.pluginName
   625 							/* translators: %s: Plugin name and version. */
   683 				);
   626 							_x( '%s update failed.', 'plugin' ),
   684 
   627 							response.pluginName
   685 				$card.find( '.update-now' ).attr( 'aria-label', ariaLabel );
   628 						)
       
   629 					);
       
   630 			} else {
   686 			} else {
       
   687 				ariaLabel = '';
   631 				$card.find( '.update-now' ).removeAttr( 'aria-label' );
   688 				$card.find( '.update-now' ).removeAttr( 'aria-label' );
   632 			}
   689 			}
   633 
   690 
   634 			$card.on( 'click', '.notice.is-dismissible .notice-dismiss', function() {
   691 			$card.on( 'click', '.notice.is-dismissible .notice-dismiss', function() {
   635 
   692 
   647 		}
   704 		}
   648 
   705 
   649 		$adminBarUpdates.removeClass( 'spin' );
   706 		$adminBarUpdates.removeClass( 'spin' );
   650 
   707 
   651 		wp.a11y.speak( errorMessage, 'assertive' );
   708 		wp.a11y.speak( errorMessage, 'assertive' );
       
   709 
       
   710 		if ( 'plugin-information-footer' === $card.attr('id' ) ) {
       
   711 			wp.updates.setCardButtonStatus(
       
   712 				{
       
   713 					status: 'plugin-update-failed',
       
   714 					slug: response.slug,
       
   715 					removeClasses: 'updating-message',
       
   716 					text: buttonText,
       
   717 					ariaLabel: ariaLabel
       
   718 				}
       
   719 			);
       
   720 		}
   652 
   721 
   653 		$document.trigger( 'wp-plugin-update-error', response );
   722 		$document.trigger( 'wp-plugin-update-error', response );
   654 	};
   723 	};
   655 
   724 
   656 	/**
   725 	/**
   664 	 * @param {installPluginError=}   args.error   Optional. Error callback. Default: wp.updates.installPluginError
   733 	 * @param {installPluginError=}   args.error   Optional. Error callback. Default: wp.updates.installPluginError
   665 	 * @return {$.promise} A jQuery promise that represents the request,
   734 	 * @return {$.promise} A jQuery promise that represents the request,
   666 	 *                     decorated with an abort() method.
   735 	 *                     decorated with an abort() method.
   667 	 */
   736 	 */
   668 	wp.updates.installPlugin = function( args ) {
   737 	wp.updates.installPlugin = function( args ) {
   669 		var $card    = $( '.plugin-card-' + args.slug ),
   738 		var $card    = $( '.plugin-card-' + args.slug + ', #plugin-information-footer' ),
   670 			$message = $card.find( '.install-now' );
   739 			$message = $card.find( '.install-now' ),
       
   740 			buttonText = __( 'Installing...' ),
       
   741 			ariaLabel;
   671 
   742 
   672 		args = _.extend( {
   743 		args = _.extend( {
   673 			success: wp.updates.installPluginSuccess,
   744 			success: wp.updates.installPluginSuccess,
   674 			error: wp.updates.installPluginError
   745 			error: wp.updates.installPluginError
   675 		}, args );
   746 		}, args );
   680 
   751 
   681 		if ( $message.html() !== __( 'Installing...' ) ) {
   752 		if ( $message.html() !== __( 'Installing...' ) ) {
   682 			$message.data( 'originaltext', $message.html() );
   753 			$message.data( 'originaltext', $message.html() );
   683 		}
   754 		}
   684 
   755 
       
   756 		ariaLabel = sprintf(
       
   757 			/* translators: %s: Plugin name and version. */
       
   758 			_x( 'Installing %s...', 'plugin' ),
       
   759 			$message.data( 'name' )
       
   760 		);
       
   761 
   685 		$message
   762 		$message
   686 			.addClass( 'updating-message' )
   763 			.addClass( 'updating-message' )
   687 			.attr(
   764 			.attr( 'aria-label', ariaLabel )
   688 				'aria-label',
   765 			.text( buttonText );
   689 				sprintf(
       
   690 					/* translators: %s: Plugin name and version. */
       
   691 					_x( 'Installing %s...', 'plugin' ),
       
   692 					$message.data( 'name' )
       
   693 				)
       
   694 			)
       
   695 			.text( __( 'Installing...' ) );
       
   696 
   766 
   697 		wp.a11y.speak( __( 'Installing... please wait.' ) );
   767 		wp.a11y.speak( __( 'Installing... please wait.' ) );
   698 
   768 
   699 		// Remove previous error messages, if any.
   769 		// Remove previous error messages, if any.
   700 		$card.removeClass( 'plugin-card-install-failed' ).find( '.notice.notice-error' ).remove();
   770 		$card.removeClass( 'plugin-card-install-failed' ).find( '.notice.notice-error' ).remove();
   701 
   771 
   702 		$document.trigger( 'wp-plugin-installing', args );
   772 		$document.trigger( 'wp-plugin-installing', args );
       
   773 
       
   774 		if ( 'plugin-information-footer' === $message.parent().attr( 'id' ) ) {
       
   775 			wp.updates.setCardButtonStatus(
       
   776 				{
       
   777 					status: 'installing-plugin',
       
   778 					slug: args.slug,
       
   779 					addClasses: 'updating-message',
       
   780 					text: buttonText,
       
   781 					ariaLabel: ariaLabel
       
   782 				}
       
   783 			);
       
   784 		}
   703 
   785 
   704 		return wp.updates.ajax( 'install-plugin', args );
   786 		return wp.updates.ajax( 'install-plugin', args );
   705 	};
   787 	};
   706 
   788 
   707 	/**
   789 	/**
   713 	 * @param {string} response.slug        Slug of the installed plugin.
   795 	 * @param {string} response.slug        Slug of the installed plugin.
   714 	 * @param {string} response.pluginName  Name of the installed plugin.
   796 	 * @param {string} response.pluginName  Name of the installed plugin.
   715 	 * @param {string} response.activateUrl URL to activate the just installed plugin.
   797 	 * @param {string} response.activateUrl URL to activate the just installed plugin.
   716 	 */
   798 	 */
   717 	wp.updates.installPluginSuccess = function( response ) {
   799 	wp.updates.installPluginSuccess = function( response ) {
   718 		var $message = $( '.plugin-card-' + response.slug ).find( '.install-now' );
   800 		var $message = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ).find( '.install-now' ),
       
   801 			buttonText = _x( 'Installed!', 'plugin' ),
       
   802 			ariaLabel = sprintf(
       
   803 				/* translators: %s: Plugin name and version. */
       
   804 				_x( '%s installed!', 'plugin' ),
       
   805 				response.pluginName
       
   806 			);
   719 
   807 
   720 		$message
   808 		$message
   721 			.removeClass( 'updating-message' )
   809 			.removeClass( 'updating-message' )
   722 			.addClass( 'updated-message installed button-disabled' )
   810 			.addClass( 'updated-message installed button-disabled' )
   723 			.attr(
   811 			.attr( 'aria-label', ariaLabel )
   724 				'aria-label',
   812 			.text( buttonText );
   725 				sprintf(
       
   726 					/* translators: %s: Plugin name and version. */
       
   727 					_x( '%s installed!', 'plugin' ),
       
   728 					response.pluginName
       
   729 				)
       
   730 			)
       
   731 			.text( _x( 'Installed!', 'plugin' ) );
       
   732 
   813 
   733 		wp.a11y.speak( __( 'Installation completed successfully.' ) );
   814 		wp.a11y.speak( __( 'Installation completed successfully.' ) );
   734 
   815 
   735 		$document.trigger( 'wp-plugin-install-success', response );
   816 		$document.trigger( 'wp-plugin-install-success', response );
   736 
   817 
   737 		if ( response.activateUrl ) {
   818 		if ( response.activateUrl ) {
   738 			setTimeout( function() {
   819 			setTimeout( function() {
   739 
   820 				wp.updates.checkPluginDependencies( {
   740 				// Transform the 'Install' button into an 'Activate' button.
   821 					slug: response.slug
   741 				$message.removeClass( 'install-now installed button-disabled updated-message' )
   822 				} );
   742 					.addClass( 'activate-now button-primary' )
       
   743 					.attr( 'href', response.activateUrl );
       
   744 
       
   745 				if ( 'plugins-network' === pagenow ) {
       
   746 					$message
       
   747 						.attr(
       
   748 							'aria-label',
       
   749 							sprintf(
       
   750 								/* translators: %s: Plugin name. */
       
   751 								_x( 'Network Activate %s', 'plugin' ),
       
   752 								response.pluginName
       
   753 							)
       
   754 						)
       
   755 						.text( __( 'Network Activate' ) );
       
   756 				} else {
       
   757 					$message
       
   758 						.attr(
       
   759 							'aria-label',
       
   760 							sprintf(
       
   761 								/* translators: %s: Plugin name. */
       
   762 								_x( 'Activate %s', 'plugin' ),
       
   763 								response.pluginName
       
   764 							)
       
   765 						)
       
   766 						.text( __( 'Activate' ) );
       
   767 				}
       
   768 			}, 1000 );
   823 			}, 1000 );
       
   824 		}
       
   825 
       
   826 		if ( 'plugin-information-footer' === $message.parent().attr( 'id' ) ) {
       
   827 			wp.updates.setCardButtonStatus(
       
   828 				{
       
   829 					status: 'installed-plugin',
       
   830 					slug: response.slug,
       
   831 					removeClasses: 'updating-message',
       
   832 					addClasses: 'updated-message installed button-disabled',
       
   833 					text: buttonText,
       
   834 					ariaLabel: ariaLabel
       
   835 				}
       
   836 			);
   769 		}
   837 		}
   770 	};
   838 	};
   771 
   839 
   772 	/**
   840 	/**
   773 	 * Updates the UI appropriately after a failed plugin install.
   841 	 * Updates the UI appropriately after a failed plugin install.
   779 	 * @param {string=} response.pluginName   Optional. Name of the plugin to be installed.
   847 	 * @param {string=} response.pluginName   Optional. Name of the plugin to be installed.
   780 	 * @param {string}  response.errorCode    Error code for the error that occurred.
   848 	 * @param {string}  response.errorCode    Error code for the error that occurred.
   781 	 * @param {string}  response.errorMessage The error that occurred.
   849 	 * @param {string}  response.errorMessage The error that occurred.
   782 	 */
   850 	 */
   783 	wp.updates.installPluginError = function( response ) {
   851 	wp.updates.installPluginError = function( response ) {
   784 		var $card   = $( '.plugin-card-' + response.slug ),
   852 		var $card   = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ),
   785 			$button = $card.find( '.install-now' ),
   853 			$button = $card.find( '.install-now' ),
       
   854 			buttonText = __( 'Installation failed.' ),
       
   855 			ariaLabel = sprintf(
       
   856 				/* translators: %s: Plugin name and version. */
       
   857 				_x( '%s installation failed', 'plugin' ),
       
   858 				$button.data( 'name' )
       
   859 			),
   786 			errorMessage;
   860 			errorMessage;
   787 
   861 
   788 		if ( ! wp.updates.isValidResponse( response, 'install' ) ) {
   862 		if ( ! wp.updates.isValidResponse( response, 'install' ) ) {
   789 			return;
   863 			return;
   790 		}
   864 		}
   799 			response.errorMessage
   873 			response.errorMessage
   800 		);
   874 		);
   801 
   875 
   802 		$card
   876 		$card
   803 			.addClass( 'plugin-card-update-failed' )
   877 			.addClass( 'plugin-card-update-failed' )
   804 			.append( '<div class="notice notice-error notice-alt is-dismissible"><p>' + errorMessage + '</p></div>' );
   878 			.append( '<div class="notice notice-error notice-alt is-dismissible" role="alert"><p>' + errorMessage + '</p></div>' );
   805 
   879 
   806 		$card.on( 'click', '.notice.is-dismissible .notice-dismiss', function() {
   880 		$card.on( 'click', '.notice.is-dismissible .notice-dismiss', function() {
   807 
   881 
   808 			// Use same delay as the total duration of the notice fadeTo + slideUp animation.
   882 			// Use same delay as the total duration of the notice fadeTo + slideUp animation.
   809 			setTimeout( function() {
   883 			setTimeout( function() {
   813 			}, 200 );
   887 			}, 200 );
   814 		} );
   888 		} );
   815 
   889 
   816 		$button
   890 		$button
   817 			.removeClass( 'updating-message' ).addClass( 'button-disabled' )
   891 			.removeClass( 'updating-message' ).addClass( 'button-disabled' )
   818 			.attr(
   892 			.attr( 'aria-label', ariaLabel )
   819 				'aria-label',
   893 			.text( buttonText );
   820 				sprintf(
       
   821 					/* translators: %s: Plugin name and version. */
       
   822 					_x( '%s installation failed', 'plugin' ),
       
   823 					$button.data( 'name' )
       
   824 				)
       
   825 			)
       
   826 			.text( __( 'Installation failed.' ) );
       
   827 
   894 
   828 		wp.a11y.speak( errorMessage, 'assertive' );
   895 		wp.a11y.speak( errorMessage, 'assertive' );
   829 
   896 
       
   897 		wp.updates.setCardButtonStatus(
       
   898 			{
       
   899 				status: 'plugin-install-failed',
       
   900 				slug: response.slug,
       
   901 				removeClasses: 'updating-message',
       
   902 				addClasses: 'button-disabled',
       
   903 				text: buttonText,
       
   904 				ariaLabel: ariaLabel
       
   905 			}
       
   906 		);
       
   907 
   830 		$document.trigger( 'wp-plugin-install-error', response );
   908 		$document.trigger( 'wp-plugin-install-error', response );
       
   909 	};
       
   910 
       
   911 	/**
       
   912 	 * Sends an Ajax request to the server to check a plugin's dependencies.
       
   913 	 *
       
   914 	 * @since 6.5.0
       
   915 	 *
       
   916 	 * @param {Object}                          args         Arguments.
       
   917 	 * @param {string}                          args.slug    Plugin identifier in the WordPress.org Plugin repository.
       
   918 	 * @param {checkPluginDependenciesSuccess=} args.success Optional. Success callback. Default: wp.updates.checkPluginDependenciesSuccess
       
   919 	 * @param {checkPluginDependenciesError=}   args.error   Optional. Error callback. Default: wp.updates.checkPluginDependenciesError
       
   920 	 * @return {$.promise} A jQuery promise that represents the request,
       
   921 	 *                     decorated with an abort() method.
       
   922 	 */
       
   923 	wp.updates.checkPluginDependencies = function( args ) {
       
   924 		args = _.extend( {
       
   925 			success: wp.updates.checkPluginDependenciesSuccess,
       
   926 			error: wp.updates.checkPluginDependenciesError
       
   927 		}, args );
       
   928 
       
   929 		wp.a11y.speak( __( 'Checking plugin dependencies... please wait.' ) );
       
   930 		$document.trigger( 'wp-checking-plugin-dependencies', args );
       
   931 
       
   932 		return wp.updates.ajax( 'check_plugin_dependencies', args );
       
   933 	};
       
   934 
       
   935 	/**
       
   936 	 * Updates the UI appropriately after a successful plugin dependencies check.
       
   937 	 *
       
   938 	 * @since 6.5.0
       
   939 	 *
       
   940 	 * @param {Object} response             Response from the server.
       
   941 	 * @param {string} response.slug        Slug of the checked plugin.
       
   942 	 * @param {string} response.pluginName  Name of the checked plugin.
       
   943 	 * @param {string} response.plugin      The plugin file, relative to the plugins directory.
       
   944 	 * @param {string} response.activateUrl URL to activate the just checked plugin.
       
   945 	 */
       
   946 	wp.updates.checkPluginDependenciesSuccess = function( response ) {
       
   947 		var $message = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ).find( '.install-now' ),
       
   948 			buttonText, ariaLabel;
       
   949 
       
   950 		// Transform the 'Install' button into an 'Activate' button.
       
   951 		$message
       
   952 			.removeClass( 'install-now installed button-disabled updated-message' )
       
   953 			.addClass( 'activate-now button-primary' )
       
   954 			.attr( 'href', response.activateUrl );
       
   955 
       
   956 		wp.a11y.speak( __( 'Plugin dependencies check completed successfully.' ) );
       
   957 		$document.trigger( 'wp-check-plugin-dependencies-success', response );
       
   958 
       
   959 		if ( 'plugins-network' === pagenow ) {
       
   960 			buttonText = _x( 'Network Activate', 'plugin' );
       
   961 			ariaLabel  = sprintf(
       
   962 				/* translators: %s: Plugin name. */
       
   963 				_x( 'Network Activate %s', 'plugin' ),
       
   964 				response.pluginName
       
   965 			);
       
   966 
       
   967 			$message
       
   968 				.attr( 'aria-label', ariaLabel )
       
   969 				.text( buttonText );
       
   970 		} else {
       
   971 			buttonText = _x( 'Activate', 'plugin' );
       
   972 			ariaLabel = sprintf(
       
   973 				/* translators: %s: Plugin name. */
       
   974 				_x( 'Activate %s', 'plugin' ),
       
   975 				response.pluginName
       
   976 			);
       
   977 
       
   978 			$message
       
   979 				.attr( 'aria-label', ariaLabel )
       
   980 				.attr( 'data-name', response.pluginName )
       
   981 				.attr( 'data-slug', response.slug )
       
   982 				.attr( 'data-plugin', response.plugin )
       
   983 				.text( buttonText );
       
   984 		}
       
   985 
       
   986 		if ( 'plugin-information-footer' === $message.parent().attr( 'id' ) ) {
       
   987 			wp.updates.setCardButtonStatus(
       
   988 				{
       
   989 					status: 'dependencies-check-success',
       
   990 					slug: response.slug,
       
   991 					removeClasses: 'install-now installed button-disabled updated-message',
       
   992 					addClasses: 'activate-now button-primary',
       
   993 					text: buttonText,
       
   994 					ariaLabel: ariaLabel,
       
   995 					pluginName: response.pluginName,
       
   996 					plugin: response.plugin,
       
   997 					href: response.activateUrl
       
   998 				}
       
   999 			);
       
  1000 		}
       
  1001 	};
       
  1002 
       
  1003 	/**
       
  1004 	 * Updates the UI appropriately after a failed plugin dependencies check.
       
  1005 	 *
       
  1006 	 * @since 6.5.0
       
  1007 	 *
       
  1008 	 * @param {Object}  response              Response from the server.
       
  1009 	 * @param {string}  response.slug         Slug of the plugin to be checked.
       
  1010 	 * @param {string=} response.pluginName   Optional. Name of the plugin to be checked.
       
  1011 	 * @param {string}  response.errorCode    Error code for the error that occurred.
       
  1012 	 * @param {string}  response.errorMessage The error that occurred.
       
  1013 	 */
       
  1014 	wp.updates.checkPluginDependenciesError = function( response ) {
       
  1015 		var $message = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ).find( '.install-now' ),
       
  1016 			buttonText = _x( 'Activate', 'plugin' ),
       
  1017 			ariaLabel = sprintf(
       
  1018 				/* translators: 1: Plugin name, 2. The reason the plugin cannot be activated. */
       
  1019 				_x( 'Cannot activate %1$s. %2$s', 'plugin' ),
       
  1020 				response.pluginName,
       
  1021 				response.errorMessage
       
  1022 			),
       
  1023 			errorMessage;
       
  1024 
       
  1025 		if ( ! wp.updates.isValidResponse( response, 'check-dependencies' ) ) {
       
  1026 			return;
       
  1027 		}
       
  1028 
       
  1029 		errorMessage = sprintf(
       
  1030 			/* translators: %s: Error string for a failed activation. */
       
  1031 			__( 'Activation failed: %s' ),
       
  1032 			response.errorMessage
       
  1033 		);
       
  1034 
       
  1035 		wp.a11y.speak( errorMessage, 'assertive' );
       
  1036 		$document.trigger( 'wp-check-plugin-dependencies-error', response );
       
  1037 
       
  1038 		$message
       
  1039 			.removeClass( 'install-now installed updated-message' )
       
  1040 			.addClass( 'activate-now button-primary' )
       
  1041 			.attr( 'aria-label', ariaLabel )
       
  1042 			.text( buttonText );
       
  1043 
       
  1044 		if ( 'plugin-information-footer' === $message.parent().attr('id' ) ) {
       
  1045 			wp.updates.setCardButtonStatus(
       
  1046 				{
       
  1047 					status: 'dependencies-check-failed',
       
  1048 					slug: response.slug,
       
  1049 					removeClasses: 'install-now installed updated-message',
       
  1050 					addClasses: 'activate-now button-primary',
       
  1051 					text: buttonText,
       
  1052 					ariaLabel: ariaLabel
       
  1053 				}
       
  1054 			);
       
  1055 		}
       
  1056 	};
       
  1057 
       
  1058 	/**
       
  1059 	 * Sends an Ajax request to the server to activate a plugin.
       
  1060 	 *
       
  1061 	 * @since 6.5.0
       
  1062 	 *
       
  1063 	 * @param {Object}                 args         Arguments.
       
  1064 	 * @param {string}                 args.name    The name of the plugin.
       
  1065 	 * @param {string}                 args.slug    Plugin identifier in the WordPress.org Plugin repository.
       
  1066 	 * @param {string}                 args.plugin  The plugin file, relative to the plugins directory.
       
  1067 	 * @param {activatePluginSuccess=} args.success Optional. Success callback. Default: wp.updates.activatePluginSuccess
       
  1068 	 * @param {activatePluginError=}   args.error   Optional. Error callback. Default: wp.updates.activatePluginError
       
  1069 	 * @return {$.promise} A jQuery promise that represents the request,
       
  1070 	 *                     decorated with an abort() method.
       
  1071 	 */
       
  1072 	wp.updates.activatePlugin = function( args ) {
       
  1073 		var $message = $( '.plugin-card-' + args.slug + ', #plugin-information-footer' ).find( '.activate-now, .activating-message' );
       
  1074 
       
  1075 		args = _.extend( {
       
  1076 			success: wp.updates.activatePluginSuccess,
       
  1077 			error: wp.updates.activatePluginError
       
  1078 		}, args );
       
  1079 
       
  1080 		wp.a11y.speak( __( 'Activating... please wait.' ) );
       
  1081 		$document.trigger( 'wp-activating-plugin', args );
       
  1082 
       
  1083 		if ( 'plugin-information-footer' === $message.parent().attr( 'id' ) ) {
       
  1084 			wp.updates.setCardButtonStatus(
       
  1085 				{
       
  1086 					status: 'activating-plugin',
       
  1087 					slug: args.slug,
       
  1088 					removeClasses: 'installed updated-message button-primary',
       
  1089 					addClasses: 'activating-message',
       
  1090 					text: __( 'Activating...' ),
       
  1091 					ariaLabel: sprintf(
       
  1092 						/* translators: %s: Plugin name. */
       
  1093 						_x( 'Activating %s', 'plugin' ),
       
  1094 						args.name
       
  1095 					)
       
  1096 				}
       
  1097 			);
       
  1098 		}
       
  1099 
       
  1100 		return wp.updates.ajax( 'activate-plugin', args );
       
  1101 	};
       
  1102 
       
  1103 	/**
       
  1104 	 * Updates the UI appropriately after a successful plugin activation.
       
  1105 	 *
       
  1106 	 * @since 6.5.0
       
  1107 	 *
       
  1108 	 * @param {Object} response             Response from the server.
       
  1109 	 * @param {string} response.slug        Slug of the activated plugin.
       
  1110 	 * @param {string} response.pluginName  Name of the activated plugin.
       
  1111 	 * @param {string} response.plugin      The plugin file, relative to the plugins directory.
       
  1112 	 */
       
  1113 	wp.updates.activatePluginSuccess = function( response ) {
       
  1114 		var $message = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ).find( '.activating-message' ),
       
  1115 			buttonText = _x( 'Activated!', 'plugin' ),
       
  1116 			ariaLabel = sprintf(
       
  1117 				/* translators: %s: The plugin name. */
       
  1118 				'%s activated successfully.',
       
  1119 				response.pluginName
       
  1120 			);
       
  1121 
       
  1122 		wp.a11y.speak( __( 'Activation completed successfully.' ) );
       
  1123 		$document.trigger( 'wp-plugin-activate-success', response );
       
  1124 
       
  1125 		$message
       
  1126 			.removeClass( 'activating-message' )
       
  1127 			.addClass( 'activated-message button-disabled' )
       
  1128 			.attr( 'aria-label', ariaLabel )
       
  1129 			.text( buttonText );
       
  1130 
       
  1131 		if ( 'plugin-information-footer' === $message.parent().attr( 'id' ) ) {
       
  1132 			wp.updates.setCardButtonStatus(
       
  1133 				{
       
  1134 					status: 'activated-plugin',
       
  1135 					slug: response.slug,
       
  1136 					removeClasses: 'activating-message',
       
  1137 					addClasses: 'activated-message button-disabled',
       
  1138 					text: buttonText,
       
  1139 					ariaLabel: ariaLabel
       
  1140 				}
       
  1141 			);
       
  1142 		}
       
  1143 
       
  1144 		setTimeout( function() {
       
  1145 			$message.removeClass( 'activated-message' )
       
  1146 			.text( _x( 'Active', 'plugin' ) );
       
  1147 
       
  1148 			if ( 'plugin-information-footer' === $message.parent().attr( 'id' ) ) {
       
  1149 				wp.updates.setCardButtonStatus(
       
  1150 					{
       
  1151 						status: 'plugin-active',
       
  1152 						slug: response.slug,
       
  1153 						removeClasses: 'activated-message',
       
  1154 						text: _x( 'Active', 'plugin' ),
       
  1155 						ariaLabel: sprintf(
       
  1156 							/* translators: %s: The plugin name. */
       
  1157 							'%s is active.',
       
  1158 							response.pluginName
       
  1159 						)
       
  1160 					}
       
  1161 				);
       
  1162 			}
       
  1163 		}, 1000 );
       
  1164 	};
       
  1165 
       
  1166 	/**
       
  1167 	 * Updates the UI appropriately after a failed plugin activation.
       
  1168 	 *
       
  1169 	 * @since 6.5.0
       
  1170 	 *
       
  1171 	 * @param {Object}  response              Response from the server.
       
  1172 	 * @param {string}  response.slug         Slug of the plugin to be activated.
       
  1173 	 * @param {string=} response.pluginName   Optional. Name of the plugin to be activated.
       
  1174 	 * @param {string}  response.errorCode    Error code for the error that occurred.
       
  1175 	 * @param {string}  response.errorMessage The error that occurred.
       
  1176 	 */
       
  1177 	wp.updates.activatePluginError = function( response ) {
       
  1178 		var $message = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ).find( '.activating-message' ),
       
  1179 			buttonText = __( 'Activation failed.' ),
       
  1180 			ariaLabel = sprintf(
       
  1181 				/* translators: %s: Plugin name. */
       
  1182 				_x( '%s activation failed', 'plugin' ),
       
  1183 				response.pluginName
       
  1184 			),
       
  1185 			errorMessage;
       
  1186 
       
  1187 		if ( ! wp.updates.isValidResponse( response, 'activate' ) ) {
       
  1188 			return;
       
  1189 		}
       
  1190 
       
  1191 		errorMessage = sprintf(
       
  1192 			/* translators: %s: Error string for a failed activation. */
       
  1193 			__( 'Activation failed: %s' ),
       
  1194 			response.errorMessage
       
  1195 		);
       
  1196 
       
  1197 		wp.a11y.speak( errorMessage, 'assertive' );
       
  1198 		$document.trigger( 'wp-plugin-activate-error', response );
       
  1199 
       
  1200 		$message
       
  1201 			.removeClass( 'install-now installed activating-message' )
       
  1202 			.addClass( 'button-disabled' )
       
  1203 			.attr( 'aria-label', ariaLabel )
       
  1204 			.text( buttonText );
       
  1205 
       
  1206 		if ( 'plugin-information-footer' === $message.parent().attr( 'id' ) ) {
       
  1207 			wp.updates.setCardButtonStatus(
       
  1208 				{
       
  1209 					status: 'plugin-activation-failed',
       
  1210 					slug: response.slug,
       
  1211 					removeClasses: 'install-now installed activating-message',
       
  1212 					addClasses: 'button-disabled',
       
  1213 					text: buttonText,
       
  1214 					ariaLabel: ariaLabel
       
  1215 				}
       
  1216 			);
       
  1217 		}
   831 	};
  1218 	};
   832 
  1219 
   833 	/**
  1220 	/**
   834 	 * Updates the UI appropriately after a successful importer install.
  1221 	 * Updates the UI appropriately after a successful importer install.
   835 	 *
  1222 	 *
   911 					/* translators: %s: Plugin name. */
  1298 					/* translators: %s: Plugin name. */
   912 					_x( 'Install %s now', 'plugin' ),
  1299 					_x( 'Install %s now', 'plugin' ),
   913 					pluginName
  1300 					pluginName
   914 				)
  1301 				)
   915 			)
  1302 			)
   916 			.text( __( 'Install Now' ) );
  1303 			.text( _x( 'Install Now', 'plugin' ) );
   917 
  1304 
   918 		wp.a11y.speak( errorMessage, 'assertive' );
  1305 		wp.a11y.speak( errorMessage, 'assertive' );
   919 
  1306 
   920 		$document.trigger( 'wp-importer-install-error', response );
  1307 		$document.trigger( 'wp-importer-install-error', response );
   921 	};
  1308 	};
  1065 			if ( $itemsCount.length && $currentView.length ) {
  1452 			if ( $itemsCount.length && $currentView.length ) {
  1066 				remainingCount = plugins[ $currentView.parent( 'li' ).attr('class') ].length;
  1453 				remainingCount = plugins[ $currentView.parent( 'li' ).attr('class') ].length;
  1067 				$itemsCount.text(
  1454 				$itemsCount.text(
  1068 					sprintf(
  1455 					sprintf(
  1069 						/* translators: %s: The remaining number of plugins. */
  1456 						/* translators: %s: The remaining number of plugins. */
  1070 						_nx( '%s item', '%s items', 'plugin/plugins', remainingCount ),
  1457 						_nx( '%s item', '%s items', remainingCount, 'plugin/plugins'  ),
  1071 						remainingCount
  1458 						remainingCount
  1072 					)
  1459 					)
  1073 				);
  1460 				);
  1074 			}
  1461 			}
  1075 		} );
  1462 		} );
  1414 								/* translators: %s: Theme name. */
  1801 								/* translators: %s: Theme name. */
  1415 								_x( 'Activate %s', 'theme' ),
  1802 								_x( 'Activate %s', 'theme' ),
  1416 								response.themeName
  1803 								response.themeName
  1417 							)
  1804 							)
  1418 						)
  1805 						)
  1419 						.text( __( 'Activate' ) );
  1806 						.text( _x( 'Activate', 'theme' ) );
  1420 				}
  1807 				}
  1421 			}
  1808 			}
  1422 
  1809 
  1423 			if ( response.customizeUrl ) {
  1810 			if ( response.customizeUrl ) {
  1424 
  1811 
  1610 				themes.all = _.without( themes.all, response.slug );
  1997 				themes.all = _.without( themes.all, response.slug );
  1611 
  1998 
  1612 				// There is always at least one theme available.
  1999 				// There is always at least one theme available.
  1613 				$views.find( '.all .count' ).text( '(' + themes.all.length + ')' );
  2000 				$views.find( '.all .count' ).text( '(' + themes.all.length + ')' );
  1614 			} );
  2001 			} );
       
  2002 		}
       
  2003 
       
  2004 		// DecrementCount from update count.
       
  2005 		if ( 'themes' === pagenow ) {
       
  2006 		    var theme = _.find( _wpThemeSettings.themes, { id: response.slug } );
       
  2007 		    if ( theme.hasUpdate ) {
       
  2008 		        wp.updates.decrementCount( 'theme' );
       
  2009 		    }
  1615 		}
  2010 		}
  1616 
  2011 
  1617 		wp.a11y.speak( _x( 'Deleted!', 'theme' ) );
  2012 		wp.a11y.speak( _x( 'Deleted!', 'theme' ) );
  1618 
  2013 
  1619 		$document.trigger( 'wp-theme-delete-success', response );
  2014 		$document.trigger( 'wp-theme-delete-success', response );
  1863 	wp.updates.showErrorInCredentialsForm = function( message ) {
  2258 	wp.updates.showErrorInCredentialsForm = function( message ) {
  1864 		var $filesystemForm = $( '#request-filesystem-credentials-form' );
  2259 		var $filesystemForm = $( '#request-filesystem-credentials-form' );
  1865 
  2260 
  1866 		// Remove any existing error.
  2261 		// Remove any existing error.
  1867 		$filesystemForm.find( '.notice' ).remove();
  2262 		$filesystemForm.find( '.notice' ).remove();
  1868 		$filesystemForm.find( '#request-filesystem-credentials-title' ).after( '<div class="notice notice-alt notice-error"><p>' + message + '</p></div>' );
  2263 		$filesystemForm.find( '#request-filesystem-credentials-title' ).after( '<div class="notice notice-alt notice-error" role="alert"><p>' + message + '</p></div>' );
  1869 	};
  2264 	};
  1870 
  2265 
  1871 	/**
  2266 	/**
  1872 	 * Handles credential errors and runs events that need to happen in that case.
  2267 	 * Handles credential errors and runs events that need to happen in that case.
  1873 	 *
  2268 	 *
  1958 			case 'install':
  2353 			case 'install':
  1959 				/* translators: %s: Error string for a failed installation. */
  2354 				/* translators: %s: Error string for a failed installation. */
  1960 				errorMessage = __( 'Installation failed: %s' );
  2355 				errorMessage = __( 'Installation failed: %s' );
  1961 				break;
  2356 				break;
  1962 
  2357 
       
  2358 			case 'check-dependencies':
       
  2359 				/* translators: %s: Error string for a failed dependencies check. */
       
  2360 				errorMessage = __( 'Dependencies check failed: %s' );
       
  2361 				break;
       
  2362 
       
  2363 			case 'activate':
       
  2364 				/* translators: %s: Error string for a failed activation. */
       
  2365 				errorMessage = __( 'Activation failed: %s' );
       
  2366 				break;
       
  2367 
  1963 			case 'delete':
  2368 			case 'delete':
  1964 				/* translators: %s: Error string for a failed deletion. */
  2369 				/* translators: %s: Error string for a failed deletion. */
  1965 				errorMessage = __( 'Deletion failed: %s' );
  2370 				errorMessage = __( 'Deletion failed: %s' );
  1966 				break;
  2371 				break;
  1967 		}
  2372 		}
  2013 			return __( 'Updates may not complete if you navigate away from this page.' );
  2418 			return __( 'Updates may not complete if you navigate away from this page.' );
  2014 		}
  2419 		}
  2015 	};
  2420 	};
  2016 
  2421 
  2017 	$( function() {
  2422 	$( function() {
  2018 		var $pluginFilter        = $( '#plugin-filter' ),
  2423 		var $pluginFilter        = $( '#plugin-filter, #plugin-information-footer' ),
  2019 			$bulkActionForm      = $( '#bulk-action-form' ),
  2424 			$bulkActionForm      = $( '#bulk-action-form' ),
  2020 			$filesystemForm      = $( '#request-filesystem-credentials-form' ),
  2425 			$filesystemForm      = $( '#request-filesystem-credentials-form' ),
  2021 			$filesystemModal     = $( '#request-filesystem-credentials-dialog' ),
  2426 			$filesystemModal     = $( '#request-filesystem-credentials-dialog' ),
  2022 			$pluginSearch        = $( '.plugins-php .wp-filter-search' ),
  2427 			$pluginSearch        = $( '.plugins-php .wp-filter-search' ),
  2023 			$pluginInstallSearch = $( '.plugin-install-php .wp-filter-search' );
  2428 			$pluginInstallSearch = $( '.plugin-install-php .wp-filter-search' );
  2218 				$document.on( 'credential-modal-cancel', function() {
  2623 				$document.on( 'credential-modal-cancel', function() {
  2219 					var $message = $( '.install-now.updating-message' );
  2624 					var $message = $( '.install-now.updating-message' );
  2220 
  2625 
  2221 					$message
  2626 					$message
  2222 						.removeClass( 'updating-message' )
  2627 						.removeClass( 'updating-message' )
  2223 						.text( __( 'Install Now' ) );
  2628 						.text( _x( 'Install Now', 'plugin' ) );
  2224 
  2629 
  2225 					wp.a11y.speak( __( 'Update canceled.' ) );
  2630 					wp.a11y.speak( __( 'Update canceled.' ) );
  2226 				} );
  2631 				} );
  2227 			}
  2632 			}
  2228 
  2633 
  2229 			wp.updates.installPlugin( {
  2634 			wp.updates.installPlugin( {
  2230 				slug: $button.data( 'slug' )
  2635 				slug: $button.data( 'slug' )
  2231 			} );
  2636 			} );
  2232 		} );
  2637 		} );
       
  2638 
       
  2639 		/**
       
  2640 		 * Click handler for plugin activations in plugin activation modal view.
       
  2641 		 *
       
  2642 		 * @since 6.5.0
       
  2643 		 * @since 6.5.4 Redirect the parent window to the activation URL.
       
  2644 		 *
       
  2645 		 * @param {Event} event Event interface.
       
  2646 		 */
       
  2647 		$document.on( 'click', '#plugin-information-footer .activate-now', function( event ) {
       
  2648 			event.preventDefault();
       
  2649 			window.parent.location.href = $( event.target ).attr( 'href' );
       
  2650 		});
  2233 
  2651 
  2234 		/**
  2652 		/**
  2235 		 * Click handler for importer plugins installs in the Import screen.
  2653 		 * Click handler for importer plugins installs in the Import screen.
  2236 		 *
  2654 		 *
  2237 		 * @since 4.6.0
  2655 		 * @since 4.6.0
  2261 								/* translators: %s: Plugin name. */
  2679 								/* translators: %s: Plugin name. */
  2262 								_x( 'Install %s now', 'plugin' ),
  2680 								_x( 'Install %s now', 'plugin' ),
  2263 								pluginName
  2681 								pluginName
  2264 							)
  2682 							)
  2265 						)
  2683 						)
  2266 						.text( __( 'Install Now' ) );
  2684 						.text( _x( 'Install Now', 'plugin' ) );
  2267 
  2685 
  2268 					wp.a11y.speak( __( 'Update canceled.' ) );
  2686 					wp.a11y.speak( __( 'Update canceled.' ) );
  2269 				} );
  2687 				} );
  2270 			}
  2688 			}
  2271 
  2689 
  2458 					// Un-check the box.
  2876 					// Un-check the box.
  2459 					$checkbox.prop( 'checked', false );
  2877 					$checkbox.prop( 'checked', false );
  2460 					return;
  2878 					return;
  2461 				}
  2879 				}
  2462 
  2880 
       
  2881 				// Don't add items to the update queue again, even if the user clicks the update button several times.
       
  2882 				if ( 'update-selected' === bulkAction && $itemRow.hasClass( 'is-enqueued' ) ) {
       
  2883 					return;
       
  2884 				}
       
  2885 
       
  2886 				$itemRow.addClass( 'is-enqueued' );
       
  2887 
  2463 				// Add it to the queue.
  2888 				// Add it to the queue.
  2464 				wp.updates.queue.push( {
  2889 				wp.updates.queue.push( {
  2465 					action: action,
  2890 					action: action,
  2466 					data:   {
  2891 					data:   {
  2467 						plugin: $itemRow.data( 'plugin' ),
  2892 						plugin: $itemRow.data( 'plugin' ),
  2486 
  2911 
  2487 				$itemRow.find( 'input[name="checked[]"]:checked' ).prop( 'checked', false );
  2912 				$itemRow.find( 'input[name="checked[]"]:checked' ).prop( 'checked', false );
  2488 
  2913 
  2489 				wp.updates.adminNotice = wp.template( 'wp-bulk-updates-admin-notice' );
  2914 				wp.updates.adminNotice = wp.template( 'wp-bulk-updates-admin-notice' );
  2490 
  2915 
       
  2916 				var successMessage = null;
       
  2917 
       
  2918 				if ( success ) {
       
  2919 					if ( 'plugin' === response.update ) {
       
  2920 						successMessage = sprintf(
       
  2921 							/* translators: %s: Number of plugins. */
       
  2922 							_n( '%s plugin successfully updated.', '%s plugins successfully updated.', success ),
       
  2923 							success
       
  2924 						);
       
  2925 					} else {
       
  2926 						successMessage = sprintf(
       
  2927 							/* translators: %s: Number of themes. */
       
  2928 							_n( '%s theme successfully updated.', '%s themes successfully updated.', success ),
       
  2929 							success
       
  2930 						);
       
  2931 					}
       
  2932 				}
       
  2933 
       
  2934 				var errorMessage = null;
       
  2935 
       
  2936 				if ( error ) {
       
  2937 					errorMessage = sprintf(
       
  2938 						/* translators: %s: Number of failed updates. */
       
  2939 						_n( '%s update failed.', '%s updates failed.', error ),
       
  2940 						error
       
  2941 					);
       
  2942 				}
       
  2943 
  2491 				wp.updates.addAdminNotice( {
  2944 				wp.updates.addAdminNotice( {
  2492 					id:            'bulk-action-notice',
  2945 					id:            'bulk-action-notice',
  2493 					className:     'bulk-action-notice',
  2946 					className:     'bulk-action-notice',
  2494 					successes:     success,
  2947 					successMessage: successMessage,
  2495 					errors:        error,
  2948 					errorMessage:   errorMessage,
  2496 					errorMessages: errorMessages,
  2949 					errorMessages:  errorMessages,
  2497 					type:          response.update
  2950 					type:           response.update
  2498 				} );
  2951 				} );
  2499 
  2952 
  2500 				$bulkActionNotice = $( '#bulk-action-notice' ).on( 'click', 'button', function() {
  2953 				$bulkActionNotice = $( '#bulk-action-notice' ).on( 'click', 'button', function() {
  2501 					// $( this ) is the clicked button, no need to get it again.
  2954 					// $( this ) is the clicked button, no need to get it again.
  2502 					$( this )
  2955 					$( this )
  2533 		$pluginInstallSearch.on( 'keyup input', _.debounce( function( event, eventtype ) {
  2986 		$pluginInstallSearch.on( 'keyup input', _.debounce( function( event, eventtype ) {
  2534 			var $searchTab = $( '.plugin-install-search' ), data, searchLocation;
  2987 			var $searchTab = $( '.plugin-install-search' ), data, searchLocation;
  2535 
  2988 
  2536 			data = {
  2989 			data = {
  2537 				_ajax_nonce: wp.updates.ajaxNonce,
  2990 				_ajax_nonce: wp.updates.ajaxNonce,
  2538 				s:           event.target.value,
  2991 				s:           encodeURIComponent( event.target.value ),
  2539 				tab:         'search',
  2992 				tab:         'search',
  2540 				type:        $( '#typeselector' ).val(),
  2993 				type:        $( '#typeselector' ).val(),
  2541 				pagenow:     pagenow
  2994 				pagenow:     pagenow
  2542 			};
  2995 			};
  2543 			searchLocation = location.href.split( '?' )[ 0 ] + '?' + $.param( _.omit( data, [ '_ajax_nonce', 'pagenow' ] ) );
  2996 			searchLocation = location.href.split( '?' )[ 0 ] + '?' + $.param( _.omit( data, [ '_ajax_nonce', 'pagenow' ] ) );
  2610 		 * @since 4.6.0
  3063 		 * @since 4.6.0
  2611 		 */
  3064 		 */
  2612 		$pluginSearch.on( 'keyup input', _.debounce( function( event ) {
  3065 		$pluginSearch.on( 'keyup input', _.debounce( function( event ) {
  2613 			var data = {
  3066 			var data = {
  2614 				_ajax_nonce:   wp.updates.ajaxNonce,
  3067 				_ajax_nonce:   wp.updates.ajaxNonce,
  2615 				s:             event.target.value,
  3068 				s:             encodeURIComponent( event.target.value ),
  2616 				pagenow:       pagenow,
  3069 				pagenow:       pagenow,
  2617 				plugin_status: 'all'
  3070 				plugin_status: 'all'
  2618 			},
  3071 			},
  2619 			queryArgs;
  3072 			queryArgs;
  2620 
  3073 
  2652 				// Can we just ditch this whole subtitle business?
  3105 				// Can we just ditch this whole subtitle business?
  2653 				var $subTitle    = $( '<span />' ).addClass( 'subtitle' ).html(
  3106 				var $subTitle    = $( '<span />' ).addClass( 'subtitle' ).html(
  2654 					sprintf(
  3107 					sprintf(
  2655 						/* translators: %s: Search query. */
  3108 						/* translators: %s: Search query. */
  2656 						__( 'Search results for: %s' ),
  3109 						__( 'Search results for: %s' ),
  2657 						'<strong>' + _.escape( data.s ) + '</strong>'
  3110 						'<strong>' + _.escape( decodeURIComponent( data.s ) ) + '</strong>'
  2658 					) ),
  3111 					) ),
  2659 					$oldSubTitle = $( '.wrap .subtitle' );
  3112 					$oldSubTitle = $( '.wrap .subtitle' );
  2660 
  3113 
  2661 				if ( ! data.s.length ) {
  3114 				if ( ! data.s.length ) {
  2662 					$oldSubTitle.remove();
  3115 					$oldSubTitle.remove();
  2748 
  3201 
  2749 			target.postMessage( JSON.stringify( update ), window.location.origin );
  3202 			target.postMessage( JSON.stringify( update ), window.location.origin );
  2750 		} );
  3203 		} );
  2751 
  3204 
  2752 		/**
  3205 		/**
  2753 		 * Click handler for installing a plugin from the details modal on `plugin-install.php`.
       
  2754 		 *
       
  2755 		 * @since 4.6.0
       
  2756 		 *
       
  2757 		 * @param {Event} event Event interface.
       
  2758 		 */
       
  2759 		$( '#plugin_install_from_iframe' ).on( 'click', function( event ) {
       
  2760 			var target = window.parent === window ? null : window.parent,
       
  2761 				install;
       
  2762 
       
  2763 			$.support.postMessage = !! window.postMessage;
       
  2764 
       
  2765 			if ( false === $.support.postMessage || null === target || -1 !== window.parent.location.pathname.indexOf( 'index.php' ) ) {
       
  2766 				return;
       
  2767 			}
       
  2768 
       
  2769 			event.preventDefault();
       
  2770 
       
  2771 			install = {
       
  2772 				action: 'install-plugin',
       
  2773 				data:   {
       
  2774 					slug: $( this ).data( 'slug' )
       
  2775 				}
       
  2776 			};
       
  2777 
       
  2778 			target.postMessage( JSON.stringify( install ), window.location.origin );
       
  2779 		} );
       
  2780 
       
  2781 		/**
       
  2782 		 * Handles postMessage events.
  3206 		 * Handles postMessage events.
  2783 		 *
  3207 		 *
  2784 		 * @since 4.2.0
  3208 		 * @since 4.2.0
  2785 		 * @since 4.6.0 Switched `update-plugin` action to use the queue.
  3209 		 * @since 4.6.0 Switched `update-plugin` action to use the queue.
  2786 		 *
  3210 		 *
  2799 				message = JSON.parse( originalEvent.data );
  3223 				message = JSON.parse( originalEvent.data );
  2800 			} catch ( e ) {
  3224 			} catch ( e ) {
  2801 				return;
  3225 				return;
  2802 			}
  3226 			}
  2803 
  3227 
  2804 			if ( ! message || 'undefined' === typeof message.action ) {
  3228 			if ( ! message ) {
       
  3229 				return;
       
  3230 			}
       
  3231 
       
  3232 			if (
       
  3233 				'undefined' !== typeof message.status &&
       
  3234 				'undefined' !== typeof message.slug &&
       
  3235 				'undefined' !== typeof message.text &&
       
  3236 				'undefined' !== typeof message.ariaLabel
       
  3237 			) {
       
  3238 				var $card = $( '.plugin-card-' + message.slug ),
       
  3239 					$message = $card.find( '[data-slug="' + message.slug + '"]' );
       
  3240 
       
  3241 				if ( 'undefined' !== typeof message.removeClasses ) {
       
  3242 					$message.removeClass( message.removeClasses );
       
  3243 				}
       
  3244 
       
  3245 				if ( 'undefined' !== typeof message.addClasses ) {
       
  3246 					$message.addClass( message.addClasses );
       
  3247 				}
       
  3248 
       
  3249 				if ( '' === message.ariaLabel ) {
       
  3250 					$message.removeAttr( 'aria-label' );
       
  3251 				} else {
       
  3252 					$message.attr( 'aria-label', message.ariaLabel );
       
  3253 				}
       
  3254 
       
  3255 				if ( 'dependencies-check-success' === message.status ) {
       
  3256 					$message
       
  3257 						.attr( 'data-name', message.pluginName )
       
  3258 						.attr( 'data-slug', message.slug )
       
  3259 						.attr( 'data-plugin', message.plugin )
       
  3260 						.attr( 'href', message.href );
       
  3261 				}
       
  3262 
       
  3263 				$message.text( message.text );
       
  3264 			}
       
  3265 
       
  3266 			if ( 'undefined' === typeof message.action ) {
  2805 				return;
  3267 				return;
  2806 			}
  3268 			}
  2807 
  3269 
  2808 			switch ( message.action ) {
  3270 			switch ( message.action ) {
  2809 
  3271 
  2813 					wp.updates.decrementCount( message.upgradeType );
  3275 					wp.updates.decrementCount( message.upgradeType );
  2814 					break;
  3276 					break;
  2815 
  3277 
  2816 				case 'install-plugin':
  3278 				case 'install-plugin':
  2817 				case 'update-plugin':
  3279 				case 'update-plugin':
  2818 					/* jscs:disable requireCamelCaseOrUpperCaseIdentifiers */
  3280 					if ( 'undefined' === typeof message.data || 'undefined' === typeof message.data.slug ) {
  2819 					window.tb_remove();
  3281 						return;
  2820 					/* jscs:enable */
  3282 					}
  2821 
  3283 
  2822 					message.data = wp.updates._addCallbacks( message.data, message.action );
  3284 					message.data = wp.updates._addCallbacks( message.data, message.action );
  2823 
  3285 
  2824 					wp.updates.queue.push( message );
  3286 					wp.updates.queue.push( message );
  2825 					wp.updates.queueChecker();
  3287 					wp.updates.queueChecker();