mirror of
https://github.com/WordPress/WordPress.git
synced 2024-11-01 16:29:31 +01:00
9038612705
* Prevent loading `wp-embed` script unconditionally on every page in favor of conditionally enqueueing when a post embed is detected. The `wp-embed` script is also explicitly marked as being in the footer group. Sites which currently disable post embed scripts from being enqueued via `remove_action( 'wp_head', 'wp_oembed_add_host_js' )` will continue to do so. * Send a `ready` message from the host page to each post embed window in case the `iframe` loads before the `wp-embed` script does. When the `ready` message is received by the post embed window, it sends the same `height` message as it sends when it loads. * Eliminate use of `grunt-include` to inject emoji script and the post embed script. Instead obtain the script contents via `file_get_contents()` (as is done elsewhere in core) and utilize `wp_print_inline_script_tag()`/`wp_get_inline_script_tag()` to construct out the script. This simplifies the logic and allows the running of src without `SCRIPT_DEBUG` enabled. * For the embed code that users are provided to copy for embedding outside of WP, add the `secret` on the `blockquote` and `iframe`. This ensures the `blockquote` will be hidden when the `iframe` loads. The embed code in question is accessed here via `get_post_embed_html()`. Props westonruter, swissspidy, pento, flixos90, ocean90. Fixes #44632, #44306. Built from https://develop.svn.wordpress.org/trunk@52132 git-svn-id: http://core.svn.wordpress.org/trunk@51724 1a063a9b-81f0-0310-95a4-ce76da25c4cd
250 lines
6.6 KiB
JavaScript
250 lines
6.6 KiB
JavaScript
/**
|
|
* @output wp-includes/js/wp-embed-template.js
|
|
*/
|
|
(function ( window, document ) {
|
|
'use strict';
|
|
|
|
var supportedBrowser = ( document.querySelector && window.addEventListener ),
|
|
loaded = false,
|
|
secret,
|
|
secretTimeout,
|
|
resizing;
|
|
|
|
function sendEmbedMessage( message, value ) {
|
|
window.parent.postMessage( {
|
|
message: message,
|
|
value: value,
|
|
secret: secret
|
|
}, '*' );
|
|
}
|
|
|
|
/**
|
|
* Send the height message to the parent window.
|
|
*/
|
|
function sendHeightMessage() {
|
|
sendEmbedMessage( 'height', Math.ceil( document.body.getBoundingClientRect().height ) );
|
|
}
|
|
|
|
function onLoad() {
|
|
if ( loaded ) {
|
|
return;
|
|
}
|
|
loaded = true;
|
|
|
|
var share_dialog = document.querySelector( '.wp-embed-share-dialog' ),
|
|
share_dialog_open = document.querySelector( '.wp-embed-share-dialog-open' ),
|
|
share_dialog_close = document.querySelector( '.wp-embed-share-dialog-close' ),
|
|
share_input = document.querySelectorAll( '.wp-embed-share-input' ),
|
|
share_dialog_tabs = document.querySelectorAll( '.wp-embed-share-tab-button button' ),
|
|
featured_image = document.querySelector( '.wp-embed-featured-image img' ),
|
|
i;
|
|
|
|
if ( share_input ) {
|
|
for ( i = 0; i < share_input.length; i++ ) {
|
|
share_input[ i ].addEventListener( 'click', function ( e ) {
|
|
e.target.select();
|
|
} );
|
|
}
|
|
}
|
|
|
|
function openSharingDialog() {
|
|
share_dialog.className = share_dialog.className.replace( 'hidden', '' );
|
|
// Initial focus should go on the currently selected tab in the dialog.
|
|
document.querySelector( '.wp-embed-share-tab-button [aria-selected="true"]' ).focus();
|
|
}
|
|
|
|
function closeSharingDialog() {
|
|
share_dialog.className += ' hidden';
|
|
document.querySelector( '.wp-embed-share-dialog-open' ).focus();
|
|
}
|
|
|
|
if ( share_dialog_open ) {
|
|
share_dialog_open.addEventListener( 'click', function () {
|
|
openSharingDialog();
|
|
} );
|
|
}
|
|
|
|
if ( share_dialog_close ) {
|
|
share_dialog_close.addEventListener( 'click', function () {
|
|
closeSharingDialog();
|
|
} );
|
|
}
|
|
|
|
function shareClickHandler( e ) {
|
|
var currentTab = document.querySelector( '.wp-embed-share-tab-button [aria-selected="true"]' );
|
|
currentTab.setAttribute( 'aria-selected', 'false' );
|
|
document.querySelector( '#' + currentTab.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'true' );
|
|
|
|
e.target.setAttribute( 'aria-selected', 'true' );
|
|
document.querySelector( '#' + e.target.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'false' );
|
|
}
|
|
|
|
function shareKeyHandler( e ) {
|
|
var target = e.target,
|
|
previousSibling = target.parentElement.previousElementSibling,
|
|
nextSibling = target.parentElement.nextElementSibling,
|
|
newTab, newTabChild;
|
|
|
|
if ( 37 === e.keyCode ) {
|
|
newTab = previousSibling;
|
|
} else if ( 39 === e.keyCode ) {
|
|
newTab = nextSibling;
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
if ( 'rtl' === document.documentElement.getAttribute( 'dir' ) ) {
|
|
newTab = ( newTab === previousSibling ) ? nextSibling : previousSibling;
|
|
}
|
|
|
|
if ( newTab ) {
|
|
newTabChild = newTab.firstElementChild;
|
|
|
|
target.setAttribute( 'tabindex', '-1' );
|
|
target.setAttribute( 'aria-selected', false );
|
|
document.querySelector( '#' + target.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'true' );
|
|
|
|
newTabChild.setAttribute( 'tabindex', '0' );
|
|
newTabChild.setAttribute( 'aria-selected', 'true' );
|
|
newTabChild.focus();
|
|
document.querySelector( '#' + newTabChild.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'false' );
|
|
}
|
|
}
|
|
|
|
if ( share_dialog_tabs ) {
|
|
for ( i = 0; i < share_dialog_tabs.length; i++ ) {
|
|
share_dialog_tabs[ i ].addEventListener( 'click', shareClickHandler );
|
|
|
|
share_dialog_tabs[ i ].addEventListener( 'keydown', shareKeyHandler );
|
|
}
|
|
}
|
|
|
|
document.addEventListener( 'keydown', function ( e ) {
|
|
if ( 27 === e.keyCode && -1 === share_dialog.className.indexOf( 'hidden' ) ) {
|
|
closeSharingDialog();
|
|
} else if ( 9 === e.keyCode ) {
|
|
constrainTabbing( e );
|
|
}
|
|
}, false );
|
|
|
|
function constrainTabbing( e ) {
|
|
// Need to re-get the selected tab each time.
|
|
var firstFocusable = document.querySelector( '.wp-embed-share-tab-button [aria-selected="true"]' );
|
|
|
|
if ( share_dialog_close === e.target && ! e.shiftKey ) {
|
|
firstFocusable.focus();
|
|
e.preventDefault();
|
|
} else if ( firstFocusable === e.target && e.shiftKey ) {
|
|
share_dialog_close.focus();
|
|
e.preventDefault();
|
|
}
|
|
}
|
|
|
|
if ( window.self === window.top ) {
|
|
return;
|
|
}
|
|
|
|
// Send this document's height to the parent (embedding) site.
|
|
sendHeightMessage();
|
|
|
|
// Send the document's height again after the featured image has been loaded.
|
|
if ( featured_image ) {
|
|
featured_image.addEventListener( 'load', sendHeightMessage );
|
|
}
|
|
|
|
/**
|
|
* Detect clicks to external (_top) links.
|
|
*/
|
|
function linkClickHandler( e ) {
|
|
var target = e.target,
|
|
href;
|
|
if ( target.hasAttribute( 'href' ) ) {
|
|
href = target.getAttribute( 'href' );
|
|
} else {
|
|
href = target.parentElement.getAttribute( 'href' );
|
|
}
|
|
|
|
// Only catch clicks from the primary mouse button, without any modifiers.
|
|
if ( event.altKey || event.ctrlKey || event.metaKey || event.shiftKey ) {
|
|
return;
|
|
}
|
|
|
|
// Send link target to the parent (embedding) site.
|
|
if ( href ) {
|
|
sendEmbedMessage( 'link', href );
|
|
e.preventDefault();
|
|
}
|
|
}
|
|
|
|
document.addEventListener( 'click', linkClickHandler );
|
|
}
|
|
|
|
/**
|
|
* Iframe resize handler.
|
|
*/
|
|
function onResize() {
|
|
if ( window.self === window.top ) {
|
|
return;
|
|
}
|
|
|
|
clearTimeout( resizing );
|
|
|
|
resizing = setTimeout( sendHeightMessage, 100 );
|
|
}
|
|
|
|
/**
|
|
* Message handler.
|
|
*
|
|
* @param {MessageEvent} event
|
|
*/
|
|
function onMessage( event ) {
|
|
var data = event.data;
|
|
|
|
if ( ! data ) {
|
|
return;
|
|
}
|
|
|
|
if ( event.source !== window.parent ) {
|
|
return;
|
|
}
|
|
|
|
if ( ! ( data.secret || data.message ) ) {
|
|
return;
|
|
}
|
|
|
|
if ( data.secret !== secret ) {
|
|
return;
|
|
}
|
|
|
|
if ( 'ready' === data.message ) {
|
|
sendHeightMessage();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Re-get the secret when it was added later on.
|
|
*/
|
|
function getSecret() {
|
|
if ( window.self === window.top || !!secret ) {
|
|
return;
|
|
}
|
|
|
|
secret = window.location.hash.replace( /.*secret=([\d\w]{10}).*/, '$1' );
|
|
|
|
clearTimeout( secretTimeout );
|
|
|
|
secretTimeout = setTimeout( function () {
|
|
getSecret();
|
|
}, 100 );
|
|
}
|
|
|
|
if ( supportedBrowser ) {
|
|
getSecret();
|
|
document.documentElement.className = document.documentElement.className.replace( /\bno-js\b/, '' ) + ' js';
|
|
document.addEventListener( 'DOMContentLoaded', onLoad, false );
|
|
window.addEventListener( 'load', onLoad, false );
|
|
window.addEventListener( 'resize', onResize, false );
|
|
window.addEventListener( 'message', onMessage, false );
|
|
}
|
|
})( window, document );
|