Skip to content

Commit

Permalink
Using the block element to check whether it's sitting inside an ifram…
Browse files Browse the repository at this point in the history
…e now before we load.

Abstracting the element copier to be more generic.
  • Loading branch information
ramonjd committed Apr 22, 2021
1 parent 79333a8 commit 68eda5a
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 4 deletions.
24 changes: 20 additions & 4 deletions projects/plugins/jetpack/extensions/blocks/podcast-player/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { debounce, noop } from 'lodash';
/**
* WordPress dependencies
*/
import { useCallback, useEffect, useRef, useReducer } from '@wordpress/element';
import { useCallback, useEffect, useState, useRef, useReducer } from '@wordpress/element';
import {
Button,
ExternalLink,
Expand Down Expand Up @@ -45,11 +45,12 @@ import { queueMusic } from './icons/';
import { isAtomicSite, isSimpleSite } from '../../shared/site-type-utils';
import attributesValidation from './attributes';
import PodcastPlayer from './components/podcast-player';
import { makeCancellable, __maybeInjectStylesIntoSiteEditor } from './utils';
import { makeCancellable } from './utils';
import { fetchPodcastFeed } from './api';
import { podcastPlayerReducer, actions } from './state';
import { applyFallbackStyles } from '../../shared/apply-fallback-styles';
import { PODCAST_FEED, EMBED_BLOCK } from './constants';
import { maybeCopyElementsToSiteEditorContext } from '../../shared/block-editor-asset-loader';

const DEFAULT_MIN_ITEMS = 1;
const DEFAULT_MAX_ITEMS = 10;
Expand Down Expand Up @@ -94,6 +95,9 @@ const PodcastPlayerEdit = ( {

const playerId = `jetpack-podcast-player-block-${ instanceId }`;

const podCastPlayerRef = useRef();
const [ hasMigratedStyles, setHasMigratedStyles ] = useState( false );

// State.
const cancellableFetch = useRef();
const [ { selectedGuid, checkUrl, ...state }, dispatch ] = useReducer( podcastPlayerReducer, {
Expand Down Expand Up @@ -156,13 +160,25 @@ const PodcastPlayerEdit = ( {
[ replaceWithEmbedBlock, setAttributes ]
);

// Call once on mount or unmount (the return callback).
useEffect( () => {
__maybeInjectStylesIntoSiteEditor();
return () => {
cancellableFetch?.current?.cancel?.();
};
}, [] );

// The Podcast player audio element requires wpmedialement styles.
// These aren't available in the Site Editor context, so we have to copy them in.
useEffect( () => {
if ( ! hasMigratedStyles && podCastPlayerRef.current ) {
maybeCopyElementsToSiteEditorContext(
[ 'link#mediaelement-css', 'link#wp-mediaelement-css' ],
podCastPlayerRef.current
);
setHasMigratedStyles( true );
}
}, [ hasMigratedStyles ] );

// Load RSS feed initially and when the feed or selected episode changes.
useEffect( () => {
// Don't do anything if no url is set.
Expand Down Expand Up @@ -375,7 +391,7 @@ const PodcastPlayerEdit = ( {
</PanelColorSettings>
</InspectorControls>

<div id={ playerId } className={ className }>
<div id={ playerId } className={ className } ref={ podCastPlayerRef }>
<PodcastPlayer
playerId={ playerId }
attributes={ validatedAttributes }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* Returns the current document and window contexts for `elementRef`.
* Use to retrieve the correct context for elements that may be within an iframe.
*
* @param {HTMLElement} elementRef - The element whose context we want to return.
* @returns {Object} - The current document (`currentDoc`) and window (`currentWindow`) contexts.
*/
export function getLoadContext( elementRef ) {
const currentDoc = elementRef.ownerDocument;
const currentWindow = currentDoc.defaultView || currentDoc.parentWindow;

return { currentDoc, currentWindow };
}

/**
* Returns whether a given element is contained within an iframe.
* Useful to check if a block sits inside the Site Editor.
*
* @param {HTMLElement} elementRef - The element whose context we want to return.
* @returns {boolean} - Whether `elementRef` is contained within an iframe.
*/
export function isElementInIframe( elementRef ) {
const { currentWindow } = getLoadContext( elementRef );
return currentWindow.self !== currentWindow.top;
}

/**
* This function will check if the current element (e.g., a block) sits inside an Iframe (e.g., the Site Editor)
* and tries to move elements from the parent window to the iframe.
*
* It's a temporary work-around to inject the styles we need for the media player into the site editor.
* For use until Gutenberg offers a standardized way of including enqueued/3rd-party assets.
* Target usage is the Podcast Playerblock: projects/plugins/jetpack/extensions/blocks/podcast-player/.
*
* @param {Array} elementSelectors - An array of selectors, e.g., [ '#conan', '#robocop' ]
* @param {HTMLElement} elementRef - The current element.
* @returns {Array} - An array of successfully migrated selectors;
*/
export function maybeCopyElementsToSiteEditorContext( elementSelectors = [], elementRef ) {
// Check to see if we're in an iframe, e.g., the Site Editor.
// If not, do nothing.
if ( ! elementRef || ! elementSelectors.length || ! isElementInIframe( elementRef ) ) {
return;
}

const { currentDoc, currentWindow } = getLoadContext( elementRef );
const parentDoc = currentWindow?.parent?.document;
let results = [];

if ( currentDoc && parentDoc ) {
results = elementSelectors.filter( selector => {
const parentElementToCopy = parentDoc.querySelector( selector );
const isElementAlreadyPresentInCurrentWindow = !! currentDoc.querySelector( selector );
if ( parentElementToCopy && ! isElementAlreadyPresentInCurrentWindow ) {
currentDoc.head.appendChild( parentElementToCopy.cloneNode() );
parentElementToCopy.remove();
return true;
}
return false;
} );

return results;
}
}

0 comments on commit 68eda5a

Please sign in to comment.