wp-embed-template.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /**
  2. * @output wp-includes/js/wp-embed-template.js
  3. */
  4. (function ( window, document ) {
  5. 'use strict';
  6. var supportedBrowser = ( document.querySelector && window.addEventListener ),
  7. loaded = false,
  8. secret,
  9. secretTimeout,
  10. resizing;
  11. function sendEmbedMessage( message, value ) {
  12. window.parent.postMessage( {
  13. message: message,
  14. value: value,
  15. secret: secret
  16. }, '*' );
  17. }
  18. /**
  19. * Send the height message to the parent window.
  20. */
  21. function sendHeightMessage() {
  22. sendEmbedMessage( 'height', Math.ceil( document.body.getBoundingClientRect().height ) );
  23. }
  24. function onLoad() {
  25. if ( loaded ) {
  26. return;
  27. }
  28. loaded = true;
  29. var share_dialog = document.querySelector( '.wp-embed-share-dialog' ),
  30. share_dialog_open = document.querySelector( '.wp-embed-share-dialog-open' ),
  31. share_dialog_close = document.querySelector( '.wp-embed-share-dialog-close' ),
  32. share_input = document.querySelectorAll( '.wp-embed-share-input' ),
  33. share_dialog_tabs = document.querySelectorAll( '.wp-embed-share-tab-button button' ),
  34. featured_image = document.querySelector( '.wp-embed-featured-image img' ),
  35. i;
  36. if ( share_input ) {
  37. for ( i = 0; i < share_input.length; i++ ) {
  38. share_input[ i ].addEventListener( 'click', function ( e ) {
  39. e.target.select();
  40. } );
  41. }
  42. }
  43. function openSharingDialog() {
  44. share_dialog.className = share_dialog.className.replace( 'hidden', '' );
  45. // Initial focus should go on the currently selected tab in the dialog.
  46. document.querySelector( '.wp-embed-share-tab-button [aria-selected="true"]' ).focus();
  47. }
  48. function closeSharingDialog() {
  49. share_dialog.className += ' hidden';
  50. document.querySelector( '.wp-embed-share-dialog-open' ).focus();
  51. }
  52. if ( share_dialog_open ) {
  53. share_dialog_open.addEventListener( 'click', function () {
  54. openSharingDialog();
  55. } );
  56. }
  57. if ( share_dialog_close ) {
  58. share_dialog_close.addEventListener( 'click', function () {
  59. closeSharingDialog();
  60. } );
  61. }
  62. function shareClickHandler( e ) {
  63. var currentTab = document.querySelector( '.wp-embed-share-tab-button [aria-selected="true"]' );
  64. currentTab.setAttribute( 'aria-selected', 'false' );
  65. document.querySelector( '#' + currentTab.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'true' );
  66. e.target.setAttribute( 'aria-selected', 'true' );
  67. document.querySelector( '#' + e.target.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'false' );
  68. }
  69. function shareKeyHandler( e ) {
  70. var target = e.target,
  71. previousSibling = target.parentElement.previousElementSibling,
  72. nextSibling = target.parentElement.nextElementSibling,
  73. newTab, newTabChild;
  74. if ( 37 === e.keyCode ) {
  75. newTab = previousSibling;
  76. } else if ( 39 === e.keyCode ) {
  77. newTab = nextSibling;
  78. } else {
  79. return false;
  80. }
  81. if ( 'rtl' === document.documentElement.getAttribute( 'dir' ) ) {
  82. newTab = ( newTab === previousSibling ) ? nextSibling : previousSibling;
  83. }
  84. if ( newTab ) {
  85. newTabChild = newTab.firstElementChild;
  86. target.setAttribute( 'tabindex', '-1' );
  87. target.setAttribute( 'aria-selected', false );
  88. document.querySelector( '#' + target.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'true' );
  89. newTabChild.setAttribute( 'tabindex', '0' );
  90. newTabChild.setAttribute( 'aria-selected', 'true' );
  91. newTabChild.focus();
  92. document.querySelector( '#' + newTabChild.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'false' );
  93. }
  94. }
  95. if ( share_dialog_tabs ) {
  96. for ( i = 0; i < share_dialog_tabs.length; i++ ) {
  97. share_dialog_tabs[ i ].addEventListener( 'click', shareClickHandler );
  98. share_dialog_tabs[ i ].addEventListener( 'keydown', shareKeyHandler );
  99. }
  100. }
  101. document.addEventListener( 'keydown', function ( e ) {
  102. if ( 27 === e.keyCode && -1 === share_dialog.className.indexOf( 'hidden' ) ) {
  103. closeSharingDialog();
  104. } else if ( 9 === e.keyCode ) {
  105. constrainTabbing( e );
  106. }
  107. }, false );
  108. function constrainTabbing( e ) {
  109. // Need to re-get the selected tab each time.
  110. var firstFocusable = document.querySelector( '.wp-embed-share-tab-button [aria-selected="true"]' );
  111. if ( share_dialog_close === e.target && ! e.shiftKey ) {
  112. firstFocusable.focus();
  113. e.preventDefault();
  114. } else if ( firstFocusable === e.target && e.shiftKey ) {
  115. share_dialog_close.focus();
  116. e.preventDefault();
  117. }
  118. }
  119. if ( window.self === window.top ) {
  120. return;
  121. }
  122. // Send this document's height to the parent (embedding) site.
  123. sendHeightMessage();
  124. // Send the document's height again after the featured image has been loaded.
  125. if ( featured_image ) {
  126. featured_image.addEventListener( 'load', sendHeightMessage );
  127. }
  128. /**
  129. * Detect clicks to external (_top) links.
  130. */
  131. function linkClickHandler( e ) {
  132. var target = e.target,
  133. href;
  134. if ( target.hasAttribute( 'href' ) ) {
  135. href = target.getAttribute( 'href' );
  136. } else {
  137. href = target.parentElement.getAttribute( 'href' );
  138. }
  139. // Only catch clicks from the primary mouse button, without any modifiers.
  140. if ( event.altKey || event.ctrlKey || event.metaKey || event.shiftKey ) {
  141. return;
  142. }
  143. // Send link target to the parent (embedding) site.
  144. if ( href ) {
  145. sendEmbedMessage( 'link', href );
  146. e.preventDefault();
  147. }
  148. }
  149. document.addEventListener( 'click', linkClickHandler );
  150. }
  151. /**
  152. * Iframe resize handler.
  153. */
  154. function onResize() {
  155. if ( window.self === window.top ) {
  156. return;
  157. }
  158. clearTimeout( resizing );
  159. resizing = setTimeout( sendHeightMessage, 100 );
  160. }
  161. /**
  162. * Message handler.
  163. *
  164. * @param {MessageEvent} event
  165. */
  166. function onMessage( event ) {
  167. var data = event.data;
  168. if ( ! data ) {
  169. return;
  170. }
  171. if ( event.source !== window.parent ) {
  172. return;
  173. }
  174. if ( ! ( data.secret || data.message ) ) {
  175. return;
  176. }
  177. if ( data.secret !== secret ) {
  178. return;
  179. }
  180. if ( 'ready' === data.message ) {
  181. sendHeightMessage();
  182. }
  183. }
  184. /**
  185. * Re-get the secret when it was added later on.
  186. */
  187. function getSecret() {
  188. if ( window.self === window.top || !!secret ) {
  189. return;
  190. }
  191. secret = window.location.hash.replace( /.*secret=([\d\w]{10}).*/, '$1' );
  192. clearTimeout( secretTimeout );
  193. secretTimeout = setTimeout( function () {
  194. getSecret();
  195. }, 100 );
  196. }
  197. if ( supportedBrowser ) {
  198. getSecret();
  199. document.documentElement.className = document.documentElement.className.replace( /\bno-js\b/, '' ) + ' js';
  200. document.addEventListener( 'DOMContentLoaded', onLoad, false );
  201. window.addEventListener( 'load', onLoad, false );
  202. window.addEventListener( 'resize', onResize, false );
  203. window.addEventListener( 'message', onMessage, false );
  204. }
  205. })( window, document );