* Handles the activation of a Jetpack feature, dismissing the card, and replacing the bottom row
* of the card with customized content.
/* global jetpackPluginSearch, jpTracksAJAX */
$pluginFilter: $( '#plugin-filter' ),
* Get parent search hint element.
* @return {Element | null}
return document.querySelector( '.plugin-card-jetpack-plugin-search' );
* Track user event such as a click on a button or a link.
* @param {string} eventName Event identifier.
* @param {object} feature Identifier of feature involved in the event.
* @param {object} target Object where action was performed.
trackEvent: function ( eventName, feature, target ) {
.record_ajax_event( eventName, 'click', { feature: feature } )
if ( 'undefined' !== typeof target && !! target.getAttribute( 'href' ) ) {
// If it has an href, follow it.
window.location = target.getAttribute( 'href' );
* Replace bottom row of the card to insert logo, text and link to dismiss the card.
replaceCardBottom: function () {
var hint = JetpackPSH.getCard();
if ( 'object' === typeof hint && null !== hint ) {
hint.querySelector( '.plugin-card-bottom' ).outerHTML =
'<div class="jetpack-plugin-search__bottom"><img src="' +
jetpackPluginSearch.logo +
'<p class="jetpack-plugin-search__text">' +
jetpackPluginSearch.legend +
' <a class="jetpack-plugin-search__support_link" href="' +
jetpackPluginSearch.supportLink +
'" target="_blank" rel="noopener noreferrer" data-track="support_link" >' +
jetpackPluginSearch.supportText +
// Remove link and parent li from action links and move it to bottom row
var dismissLink = document.querySelector( '.jetpack-plugin-search__dismiss' );
dismissLink.parentNode.parentNode.removeChild( dismissLink.parentNode );
document.querySelector( '.jetpack-plugin-search__bottom' ).appendChild( dismissLink );
* Check if plugin card list nodes changed. If there's a Jetpack PSH card, replace the bottom row.
* @param {array} mutationsList
replaceOnNewResults: function ( mutationsList ) {
mutationsList.forEach( function ( mutation ) {
'childList' === mutation.type &&
1 === document.querySelectorAll( '.plugin-card-jetpack-plugin-search' ).length
JetpackPSH.replaceCardBottom();
dismiss: function ( moduleName ) {
document.getElementById( 'the-list' ).removeChild( JetpackPSH.getCard() );
url: jpsh.base_rest_url + '/hints',
beforeSend: function ( xhr ) {
xhr.setRequestHeader( 'X-WP-Nonce', jpsh.nonce );
contentType: 'application/json',
JetpackPSH.trackEvent( 'wpa_plugin_search_dismiss', moduleName );
ajaxActivateModule: function ( moduleName ) {
var $moduleBtn = JetpackPSH.$pluginFilter.find( '#plugin-select-activate' );
$moduleBtn.toggleClass( 'install-now updating-message' );
$moduleBtn.prop( 'disabled', true );
$moduleBtn.text( jpsh.activating );
data[ moduleName ] = true;
url: jpsh.base_rest_url + '/settings',
beforeSend: function ( xhr ) {
xhr.setRequestHeader( 'X-WP-Nonce', jpsh.nonce );
data: JSON.stringify( data ),
contentType: 'application/json',
JetpackPSH.updateButton( moduleName );
JetpackPSH.trackEvent( 'wpa_plugin_search_activate', moduleName );
$moduleBtn.toggleClass( 'install-now updating-message' );
// Remove onclick handler, disable loading spinner, update button to redirect to module settings.
updateButton: function ( moduleName ) {
url: jpsh.base_rest_url + '/module/' + moduleName,
beforeSend: function ( xhr ) {
xhr.setRequestHeader( 'X-WP-Nonce', jpsh.nonce );
} ).done( function ( response ) {
var $moduleBtn = JetpackPSH.$pluginFilter.find( '#plugin-select-activate' );
$moduleBtn.prop( 'onclick', null ).off( 'click' );
$moduleBtn.toggleClass( 'install-now updating-message' );
$moduleBtn.text( jpsh.activated );
setTimeout( function () {
var url = 'https://jetpack.com/redirect/?source=plugin-hint-learn-' + moduleName,
classes = 'jetpack-plugin-search__primary button',
// If the feature has options in Jetpack admin UI, link to them.
if ( response.options && 0 < Object.keys( response.options ).length ) {
url = $moduleBtn.data( 'configure-url' );
label = jpsh.manageSettings;
classes += ' jetpack-plugin-search__configure';
// If it has no options, the Get started button will be displayed so remove the Learn more link if it's there.
var learnMore = document.querySelector( '.jetpack-plugin-search__learn-more' );
learnMore.parentNode.removeChild( learnMore );
classes += ' jetpack-plugin-search__get-started';
'<a id="plugin-select-settings" class="' +
if ( JetpackPSH.$pluginFilter.length < 1 ) {
// Replace PSH bottom row on page load
JetpackPSH.replaceCardBottom();
// Listen for changes in plugin search results
var resultsObserver = new MutationObserver( JetpackPSH.replaceOnNewResults );
resultsObserver.observe( document.getElementById( 'plugin-filter' ), { childList: true } );
.on( 'click', '.jetpack-plugin-search__dismiss', function ( event ) {
JetpackPSH.dismiss( $( this ).data( 'module' ) );
.on( 'click', 'button#plugin-select-activate', function ( event ) {
JetpackPSH.ajaxActivateModule( $( this ).data( 'module' ) );
.on( 'click', '.jetpack-plugin-search__primary', function ( event ) {
if ( $this.data( 'track' ) ) {
// This catches Purchase, Configure, and Get started. Feature activation is tracked when it ends successfully, in its callback.
'wpa_plugin_search_' + $this.data( 'track' ),
.on( 'click', '.jetpack-plugin-search__learn-more', function ( event ) {
'wpa_plugin_search_learn_more',
.on( 'click', '.jetpack-plugin-search__support_link', function ( event ) {
'wpa_plugin_search_support_link',
} )( jQuery, jetpackPluginSearch );