media.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /**
  2. * Creates a dialog containing posts that can have a particular media attached
  3. * to it.
  4. *
  5. * @since 2.7.0
  6. * @output wp-admin/js/media.js
  7. *
  8. * @namespace findPosts
  9. *
  10. * @requires jQuery
  11. */
  12. /* global ajaxurl, _wpMediaGridSettings, showNotice, findPosts, ClipboardJS */
  13. ( function( $ ){
  14. window.findPosts = {
  15. /**
  16. * Opens a dialog to attach media to a post.
  17. *
  18. * Adds an overlay prior to retrieving a list of posts to attach the media to.
  19. *
  20. * @since 2.7.0
  21. *
  22. * @memberOf findPosts
  23. *
  24. * @param {string} af_name The name of the affected element.
  25. * @param {string} af_val The value of the affected post element.
  26. *
  27. * @return {boolean} Always returns false.
  28. */
  29. open: function( af_name, af_val ) {
  30. var overlay = $( '.ui-find-overlay' );
  31. if ( overlay.length === 0 ) {
  32. $( 'body' ).append( '<div class="ui-find-overlay"></div>' );
  33. findPosts.overlay();
  34. }
  35. overlay.show();
  36. if ( af_name && af_val ) {
  37. // #affected is a hidden input field in the dialog that keeps track of which media should be attached.
  38. $( '#affected' ).attr( 'name', af_name ).val( af_val );
  39. }
  40. $( '#find-posts' ).show();
  41. // Close the dialog when the escape key is pressed.
  42. $('#find-posts-input').trigger( 'focus' ).on( 'keyup', function( event ){
  43. if ( event.which == 27 ) {
  44. findPosts.close();
  45. }
  46. });
  47. // Retrieves a list of applicable posts for media attachment and shows them.
  48. findPosts.send();
  49. return false;
  50. },
  51. /**
  52. * Clears the found posts lists before hiding the attach media dialog.
  53. *
  54. * @since 2.7.0
  55. *
  56. * @memberOf findPosts
  57. *
  58. * @return {void}
  59. */
  60. close: function() {
  61. $('#find-posts-response').empty();
  62. $('#find-posts').hide();
  63. $( '.ui-find-overlay' ).hide();
  64. },
  65. /**
  66. * Binds a click event listener to the overlay which closes the attach media
  67. * dialog.
  68. *
  69. * @since 3.5.0
  70. *
  71. * @memberOf findPosts
  72. *
  73. * @return {void}
  74. */
  75. overlay: function() {
  76. $( '.ui-find-overlay' ).on( 'click', function () {
  77. findPosts.close();
  78. });
  79. },
  80. /**
  81. * Retrieves and displays posts based on the search term.
  82. *
  83. * Sends a post request to the admin_ajax.php, requesting posts based on the
  84. * search term provided by the user. Defaults to all posts if no search term is
  85. * provided.
  86. *
  87. * @since 2.7.0
  88. *
  89. * @memberOf findPosts
  90. *
  91. * @return {void}
  92. */
  93. send: function() {
  94. var post = {
  95. ps: $( '#find-posts-input' ).val(),
  96. action: 'find_posts',
  97. _ajax_nonce: $('#_ajax_nonce').val()
  98. },
  99. spinner = $( '.find-box-search .spinner' );
  100. spinner.addClass( 'is-active' );
  101. /**
  102. * Send a POST request to admin_ajax.php, hide the spinner and replace the list
  103. * of posts with the response data. If an error occurs, display it.
  104. */
  105. $.ajax( ajaxurl, {
  106. type: 'POST',
  107. data: post,
  108. dataType: 'json'
  109. }).always( function() {
  110. spinner.removeClass( 'is-active' );
  111. }).done( function( x ) {
  112. if ( ! x.success ) {
  113. $( '#find-posts-response' ).text( wp.i18n.__( 'An error has occurred. Please reload the page and try again.' ) );
  114. }
  115. $( '#find-posts-response' ).html( x.data );
  116. }).fail( function() {
  117. $( '#find-posts-response' ).text( wp.i18n.__( 'An error has occurred. Please reload the page and try again.' ) );
  118. });
  119. }
  120. };
  121. /**
  122. * Initializes the file once the DOM is fully loaded and attaches events to the
  123. * various form elements.
  124. *
  125. * @return {void}
  126. */
  127. $( function() {
  128. var settings,
  129. $mediaGridWrap = $( '#wp-media-grid' ),
  130. copyAttachmentURLClipboard = new ClipboardJS( '.copy-attachment-url.media-library' ),
  131. copyAttachmentURLSuccessTimeout;
  132. // Opens a manage media frame into the grid.
  133. if ( $mediaGridWrap.length && window.wp && window.wp.media ) {
  134. settings = _wpMediaGridSettings;
  135. var frame = window.wp.media({
  136. frame: 'manage',
  137. container: $mediaGridWrap,
  138. library: settings.queryVars
  139. }).open();
  140. // Fire a global ready event.
  141. $mediaGridWrap.trigger( 'wp-media-grid-ready', frame );
  142. }
  143. // Prevents form submission if no post has been selected.
  144. $( '#find-posts-submit' ).on( 'click', function( event ) {
  145. if ( ! $( '#find-posts-response input[type="radio"]:checked' ).length )
  146. event.preventDefault();
  147. });
  148. // Submits the search query when hitting the enter key in the search input.
  149. $( '#find-posts .find-box-search :input' ).on( 'keypress', function( event ) {
  150. if ( 13 == event.which ) {
  151. findPosts.send();
  152. return false;
  153. }
  154. });
  155. // Binds the click event to the search button.
  156. $( '#find-posts-search' ).on( 'click', findPosts.send );
  157. // Binds the close dialog click event.
  158. $( '#find-posts-close' ).on( 'click', findPosts.close );
  159. // Binds the bulk action events to the submit buttons.
  160. $( '#doaction' ).on( 'click', function( event ) {
  161. /*
  162. * Handle the bulk action based on its value.
  163. */
  164. $( 'select[name="action"]' ).each( function() {
  165. var optionValue = $( this ).val();
  166. if ( 'attach' === optionValue ) {
  167. event.preventDefault();
  168. findPosts.open();
  169. } else if ( 'delete' === optionValue ) {
  170. if ( ! showNotice.warn() ) {
  171. event.preventDefault();
  172. }
  173. }
  174. });
  175. });
  176. /**
  177. * Enables clicking on the entire table row.
  178. *
  179. * @return {void}
  180. */
  181. $( '.find-box-inside' ).on( 'click', 'tr', function() {
  182. $( this ).find( '.found-radio input' ).prop( 'checked', true );
  183. });
  184. /**
  185. * Handles media list copy media URL button.
  186. *
  187. * @since 6.0.0
  188. *
  189. * @param {MouseEvent} event A click event.
  190. * @return {void}
  191. */
  192. copyAttachmentURLClipboard.on( 'success', function( event ) {
  193. var triggerElement = $( event.trigger ),
  194. successElement = $( '.success', triggerElement.closest( '.copy-to-clipboard-container' ) );
  195. // Clear the selection and move focus back to the trigger.
  196. event.clearSelection();
  197. // Handle ClipboardJS focus bug, see https://github.com/zenorocha/clipboard.js/issues/680.
  198. triggerElement.trigger( 'focus' );
  199. // Show success visual feedback.
  200. clearTimeout( copyAttachmentURLSuccessTimeout );
  201. successElement.removeClass( 'hidden' );
  202. // Hide success visual feedback after 3 seconds since last success and unfocus the trigger.
  203. copyAttachmentURLSuccessTimeout = setTimeout( function() {
  204. successElement.addClass( 'hidden' );
  205. }, 3000 );
  206. // Handle success audible feedback.
  207. wp.a11y.speak( wp.i18n.__( 'The file URL has been copied to your clipboard' ) );
  208. } );
  209. });
  210. })( jQuery );