Нет описания

plugin-search.js 8.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /**
  2. * Handles the activation of a Jetpack feature, dismissing the card, and replacing the bottom row
  3. * of the card with customized content.
  4. */
  5. /* global jetpackPluginSearch, JSON, jpTracksAJAX */
  6. var JetpackPSH = {};
  7. ( function ( $, jpsh ) {
  8. JetpackPSH = {
  9. $pluginFilter: $( '#plugin-filter' ),
  10. /**
  11. * Get parent search hint element.
  12. * @returns {Element | null}
  13. */
  14. getCard: function () {
  15. return document.querySelector( '.plugin-card-jetpack-plugin-search' );
  16. },
  17. /**
  18. * Track user event such as a click on a button or a link.
  19. *
  20. * @param {string} eventName Event identifier.
  21. * @param {object} feature Identifier of feature involved in the event.
  22. * @param {object} target Object where action was performed.
  23. */
  24. trackEvent: function ( eventName, feature, target ) {
  25. jpTracksAJAX
  26. .record_ajax_event( eventName, 'click', { feature: feature } )
  27. .always( function () {
  28. if ( 'undefined' !== typeof target && !! target.getAttribute( 'href' ) ) {
  29. // If it has an href, follow it.
  30. window.location = target.getAttribute( 'href' );
  31. }
  32. } );
  33. },
  34. /**
  35. * Update title of the card to add a mention that the result is from the Jetpack plugin.
  36. */
  37. updateCardTitle: function () {
  38. var hint = JetpackPSH.getCard();
  39. if ( 'object' === typeof hint && null !== hint ) {
  40. var title = hint.querySelector( '.column-name h3' );
  41. title.outerHTML =
  42. title.outerHTML + '<strong>' + jetpackPluginSearch.poweredBy + '</strong>';
  43. }
  44. },
  45. /**
  46. * Move action links below description.
  47. */
  48. moveActionLinks: function () {
  49. var hint = JetpackPSH.getCard();
  50. if ( 'object' === typeof hint && null !== hint ) {
  51. var descriptionContainer = hint.querySelector( '.column-description' );
  52. // Keep only the first paragraph. The second is the plugin author.
  53. var descriptionText = descriptionContainer.querySelector( 'p:first-child' );
  54. var actionLinks = hint.querySelector( '.action-links' );
  55. // Change the contents of the description, to keep the description text and the action links.
  56. descriptionContainer.innerHTML = descriptionText.outerHTML + actionLinks.outerHTML;
  57. // Remove the action links from their default location.
  58. actionLinks.parentNode.removeChild( actionLinks );
  59. }
  60. },
  61. /**
  62. * Replace bottom row of the card to insert logo, text and link to dismiss the card.
  63. */
  64. replaceCardBottom: function () {
  65. var hint = JetpackPSH.getCard();
  66. if ( 'object' === typeof hint && null !== hint ) {
  67. hint.querySelector( '.plugin-card-bottom' ).outerHTML =
  68. '<div class="jetpack-plugin-search__bottom"><img src="' +
  69. jetpackPluginSearch.logo +
  70. '" width="32" />' +
  71. '<p class="jetpack-plugin-search__text">' +
  72. jetpackPluginSearch.legend +
  73. ' <a class="jetpack-plugin-search__support_link" href="' +
  74. jetpackPluginSearch.supportLink +
  75. '" target="_blank" rel="noopener noreferrer" data-track="support_link" >' +
  76. jetpackPluginSearch.supportText +
  77. '</a>' +
  78. '</p>' +
  79. '</div>';
  80. // Remove link and parent li from action links and move it to bottom row
  81. var dismissLink = document.querySelector( '.jetpack-plugin-search__dismiss' );
  82. dismissLink.parentNode.parentNode.removeChild( dismissLink.parentNode );
  83. document.querySelector( '.jetpack-plugin-search__bottom' ).appendChild( dismissLink );
  84. }
  85. },
  86. /**
  87. * Check if plugin card list nodes changed. If there's a Jetpack PSH card, replace the title and the bottom row.
  88. * @param {array} mutationsList
  89. */
  90. replaceOnNewResults: function ( mutationsList ) {
  91. mutationsList.forEach( function ( mutation ) {
  92. if (
  93. 'childList' === mutation.type &&
  94. 1 === document.querySelectorAll( '.plugin-card-jetpack-plugin-search' ).length
  95. ) {
  96. JetpackPSH.updateCardTitle();
  97. JetpackPSH.moveActionLinks();
  98. JetpackPSH.replaceCardBottom();
  99. }
  100. } );
  101. },
  102. dismiss: function ( moduleName ) {
  103. document.getElementById( 'the-list' ).removeChild( JetpackPSH.getCard() );
  104. $.ajax( {
  105. url: jpsh.base_rest_url + '/hints',
  106. method: 'post',
  107. beforeSend: function ( xhr ) {
  108. xhr.setRequestHeader( 'X-WP-Nonce', jpsh.nonce );
  109. },
  110. data: JSON.stringify( {
  111. hint: moduleName,
  112. } ),
  113. contentType: 'application/json',
  114. dataType: 'json',
  115. } ).done( function () {
  116. JetpackPSH.trackEvent( 'wpa_plugin_search_dismiss', moduleName );
  117. } );
  118. },
  119. ajaxActivateModule: function ( moduleName ) {
  120. var $moduleBtn = JetpackPSH.$pluginFilter.find( '#plugin-select-activate' );
  121. $moduleBtn.toggleClass( 'install-now updating-message' );
  122. $moduleBtn.prop( 'disabled', true );
  123. $moduleBtn.text( jpsh.activating );
  124. var data = {};
  125. data[ moduleName ] = true;
  126. $.ajax( {
  127. url: jpsh.base_rest_url + '/settings',
  128. method: 'post',
  129. beforeSend: function ( xhr ) {
  130. xhr.setRequestHeader( 'X-WP-Nonce', jpsh.nonce );
  131. },
  132. data: JSON.stringify( data ),
  133. contentType: 'application/json',
  134. dataType: 'json',
  135. } )
  136. .done( function () {
  137. JetpackPSH.updateButton( moduleName );
  138. JetpackPSH.trackEvent( 'wpa_plugin_search_activate', moduleName );
  139. } )
  140. .error( function () {
  141. $moduleBtn.toggleClass( 'install-now updating-message' );
  142. } );
  143. },
  144. // Remove onclick handler, disable loading spinner, update button to redirect to module settings.
  145. updateButton: function ( moduleName ) {
  146. $.ajax( {
  147. url: jpsh.base_rest_url + '/module/' + moduleName,
  148. method: 'get',
  149. beforeSend: function ( xhr ) {
  150. xhr.setRequestHeader( 'X-WP-Nonce', jpsh.nonce );
  151. },
  152. dataType: 'json',
  153. } ).done( function ( response ) {
  154. var $moduleBtn = JetpackPSH.$pluginFilter.find( '#plugin-select-activate' );
  155. $moduleBtn.prop( 'onclick', null ).off( 'click' );
  156. $moduleBtn.toggleClass( 'install-now updating-message' );
  157. $moduleBtn.text( jpsh.activated );
  158. setTimeout( function () {
  159. var url = 'https://jetpack.com/redirect/?source=plugin-hint-learn-' + moduleName,
  160. label = jpsh.getStarted,
  161. classes = 'jetpack-plugin-search__primary button',
  162. track = 'configure';
  163. // If the feature has options in Jetpack admin UI, link to them.
  164. if ( response.options && 0 < Object.keys( response.options ).length ) {
  165. url = $moduleBtn.data( 'configure-url' );
  166. label = jpsh.manageSettings;
  167. classes += ' jetpack-plugin-search__configure';
  168. } else {
  169. // If it has no options, the Get started button will be displayed so remove the Learn more link if it's there.
  170. var learnMore = document.querySelector( '.jetpack-plugin-search__learn-more' );
  171. learnMore.parentNode.removeChild( learnMore );
  172. classes += ' jetpack-plugin-search__get-started';
  173. track = 'get_started';
  174. }
  175. $moduleBtn.replaceWith(
  176. '<a id="plugin-select-settings" class="' +
  177. classes +
  178. '" href="' +
  179. url +
  180. '" data-module="' +
  181. moduleName +
  182. '" data-track="' +
  183. track +
  184. '">' +
  185. label +
  186. '</a>'
  187. );
  188. }, 1000 );
  189. } );
  190. },
  191. /**
  192. * Start suggesting.
  193. */
  194. init: function () {
  195. if ( JetpackPSH.$pluginFilter.length < 1 ) {
  196. return;
  197. }
  198. // Update title to show that the suggestion is from Jetpack.
  199. JetpackPSH.updateCardTitle();
  200. // Update the description and action links.
  201. JetpackPSH.moveActionLinks();
  202. // Replace PSH bottom row on page load
  203. JetpackPSH.replaceCardBottom();
  204. // Listen for changes in plugin search results
  205. var resultsObserver = new MutationObserver( JetpackPSH.replaceOnNewResults );
  206. resultsObserver.observe( document.getElementById( 'plugin-filter' ), { childList: true } );
  207. JetpackPSH.$pluginFilter
  208. .on( 'click', '.jetpack-plugin-search__dismiss', function ( event ) {
  209. event.preventDefault();
  210. JetpackPSH.dismiss( $( this ).data( 'module' ) );
  211. } )
  212. .on( 'click', 'button#plugin-select-activate', function ( event ) {
  213. event.preventDefault();
  214. JetpackPSH.ajaxActivateModule( $( this ).data( 'module' ) );
  215. } )
  216. .on( 'click', '.jetpack-plugin-search__primary', function ( event ) {
  217. event.preventDefault();
  218. var $this = $( this );
  219. if ( $this.data( 'track' ) ) {
  220. // This catches Purchase, Configure, and Get started. Feature activation is tracked when it ends successfully, in its callback.
  221. JetpackPSH.trackEvent(
  222. 'wpa_plugin_search_' + $this.data( 'track' ),
  223. $this.data( 'module' ),
  224. $this.get( 0 )
  225. );
  226. }
  227. } )
  228. .on( 'click', '.jetpack-plugin-search__learn-more', function ( event ) {
  229. event.preventDefault();
  230. var $this = $( this );
  231. JetpackPSH.trackEvent(
  232. 'wpa_plugin_search_learn_more',
  233. $this.data( 'module' ),
  234. $this.get( 0 )
  235. );
  236. } )
  237. .on( 'click', '.jetpack-plugin-search__support_link', function ( event ) {
  238. event.preventDefault();
  239. var $this = $( this );
  240. JetpackPSH.trackEvent(
  241. 'wpa_plugin_search_support_link',
  242. $this.data( 'module' ),
  243. $this.get( 0 )
  244. );
  245. } );
  246. },
  247. };
  248. JetpackPSH.init();
  249. } )( jQuery, jetpackPluginSearch );