Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

elem instanceof HTMLDivElement fails in iframe editor #53867

Open
andreaslindahl opened this issue Aug 22, 2023 · 7 comments
Open

elem instanceof HTMLDivElement fails in iframe editor #53867

andreaslindahl opened this issue Aug 22, 2023 · 7 comments
Labels
[Feature] Blocks Overall functionality of blocks Needs Testing Needs further testing to be confirmed. [Type] Bug An existing feature does not function as intended

Comments

@andreaslindahl
Copy link

Description

I'm using https://masonry.desandro.com in some of my blocks, both on frontend and in the editor. Trying out the new iframed editor in Wordpress 6.3, I noticed that Masonry in the editor isn't working anymore - no items are added to the masonry and the layout fails.

Turns out that this line hidden in the Masonry code is the reason:

if ( !( elem instanceof HTMLDivElement ) ) {
      return;
}

For some reason, elem instanceof HTMLDivElement always fails when this code is loaded in the iframed editor. Now, if I check the type of elem it indeed is HTMLDivElement. I'm guessing this is some kind of scoping issue, i.e. that the HTMLDivElement type of the iframe is not equal to the type of the HTMLDivElement in the parent document?

Is there a fix for this in Wordpress/Gutenberg, apart from hoping the Masonry will update their code?

Step-by-step reproduction instructions

Run editor javascript code that checks if an html element is an instance of HTMLDivElement

Screenshots, screen recording, code snippet

No response

Environment info

No response

Please confirm that you have searched existing issues in the repo.

Yes

Please confirm that you have tested with all plugins deactivated except Gutenberg.

Yes

@jordesign jordesign added [Type] Bug An existing feature does not function as intended [Feature] Blocks Overall functionality of blocks Needs Testing Needs further testing to be confirmed. labels Aug 23, 2023
@ellatrix
Copy link
Member

ellatrix commented Sep 4, 2023

Are you enqueuing Masonry outside or inside the iframe? In this particular case, you should enqueue it inside the iframe because it's a script that should run both in the editor and front-end. We actually used Masonry in an e2e test:

registerBlockType( 'test/iframed-masonry-block', {
apiVersion: 3,
edit: function Edit() {
const ref = useRefEffect( ( node ) => {
const { ownerDocument } = node;
const { defaultView } = ownerDocument;
if ( ! defaultView.Masonry ) {
return;
}
const masonry = new defaultView.Masonry( node, {
itemSelector: '.grid-item',
} );
return () => {
masonry.destroy();
};
} );
return el( 'div', useBlockProps( { ref } ), ...content );
},
save: function Save() {
return el( 'div', useBlockProps.save(), ...content );
},
} );

@andreaslindahl
Copy link
Author

I'm importing it in my edit.js file:

import Masonry from 'masonry-layout';

@nielsjensen
Copy link

I am having the same issue. I wanted to use keen-slider in my edit function, which also checks for elem instanceof HTMLElement. I agree that this is should be a scoping issue.

import { useEffect, useRef } from '@wordpress/element';

export default function Edit() {
	const myRef = useRef();

	useEffect( () => {
		if ( myRef.current ) {
			console.log( myRef.current.constructor.name ); // => HTMLDivElement
			console.log( myRef.current instanceof HTMLDivElement ); // => false

			const refDocumnent = myRef.current.ownerDocument;
			const refDocumnentParent = refDocumnent.defaultView.parent.document;
			console.log( refDocumnent === window.document ); // => false
			console.log( refDocumnentParent === window.document ); // => true
		}
	}, [ ] );

	return <div ref={ myRef }>Test</div>;
}

@github-actions
Copy link

Hi,
This issue has gone 30 days without any activity. This means it is time for a check-in to make sure it is still relevant. If you are still experiencing this issue with the latest versions, you can help the project by responding to confirm the problem and by providing any updated reproduction steps.
Thanks for helping out.

@github-actions github-actions bot added the [Status] Stale Gives the original author opportunity to update before closing. Can be reopened as needed. label Oct 18, 2023
@ellatrix
Copy link
Member

If you want to use instanceOf HTMLElement, it's always better to check the context you're in:

element instanceOf element.ownerDocument.defaultView.HTMLDivElement

In the case of Masonry it's better to load it in the iframe instead of the editor frame, because it's a front-end script. #53867 (comment)

@github-actions github-actions bot removed the [Status] Stale Gives the original author opportunity to update before closing. Can be reopened as needed. label Oct 21, 2023
@mrleemon
Copy link
Contributor

mrleemon commented Feb 12, 2024

Has anyone managed to make Masonry work in the iFrame editor using the code posted by @ellatrix? In my case, it's not loaded at all.

@mrleemon
Copy link
Contributor

In case anyone is having problems with this, you need to add the Masonry lib to the script prop (instead of the editorScript prop) in block.json. Otherwise it gets loaded outside the iframe. This might be a bug on Gutenberg's side because it makes no sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Blocks Overall functionality of blocks Needs Testing Needs further testing to be confirmed. [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

No branches or pull requests

5 participants