Skip to content

Instantly share code, notes, and snippets.

@KevinBatdorf
Last active March 22, 2024 20:00
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save KevinBatdorf/fca19e1f3b749b5c57db8158f4850eff to your computer and use it in GitHub Desktop.
Save KevinBatdorf/fca19e1f3b749b5c57db8158f4850eff to your computer and use it in GitHub Desktop.
WordPress check Gutenberg editor is ready
import { select, subscribe } from '@wordpress/data'
export function whenEditorIsReady() {
return new Promise((resolve) => {
const unsubscribe = subscribe(() => {
// This will trigger after the initial render blocking, before the window load event
// This seems currently more reliable than using __unstableIsEditorReady
if (select('core/editor').isCleanNewPost() || select('core/block-editor').getBlockCount() > 0) {
unsubscribe()
resolve()
}
})
})
}
@strarsis
Copy link

strarsis commented Feb 13, 2023

Instead of my_custom_script you should name that helper script file something like gutenberg-when-editor-is-ready.
Then you would add this script handle to the dependencies array for the admin script that uses whenEditorIsReady:

function test_function( $hook ) {
    wp_enqueue_script( 'gutenberg-when-editor-is-ready', plugin_dir_url( __FILE__ ) . 'js/my-new-script.js', [], null );

   // (or at another place)
    wp_enqueue_script( 'my-admin-script', plugin_dir_url( __FILE__ ) . 'js/my-admin-script.js', ['gutenberg-when-editor-is-ready'], null, true );
}
add_action( 'admin_enqueue_scripts', 'test_function' );

Additionally, the function signature of wp_enqueue_script is,
wp_enqueue_script( string $handle, string $src = '', string[] $deps = array(), string|bool|null $ver = false, bool $in_footer = false ),
so in your code example you probably passed some incorrect arguments to it.

@X-Raym
Copy link

X-Raym commented Feb 13, 2023

so in your code example you probably passed some incorrect arguments to it.

I just quickly renamed things to have more clarity, but on my side it works (the script is loaded etc).

Your code uses two javascripts files, I was expecting to merge the event handler and my custom scripts into one js only, as I dont need the functions to be avalaible for other scripts. That's why I needed a version without import/export. This way to enqueue triggers the import/export error as well, and if I remove these statement, I still dont succeed to trigger my custom functions at editor ready.

I'm a bit confused by the javascript side of thing, I think I would need a full working exemple with console.log call at editor ready, something like that.

Thx for the help and explications anyway!

@KevinBatdorf
Copy link
Author

@X-Raym instead of importing it just copy/paste the function at the start of the file.

@strarsis Thanks for that iframe code. I actually need to convert some cypress to use the upcoming iframe wrapper and I think I'll need just that.

@strarsis
Copy link

strarsis commented Feb 13, 2023

@X-Raym: Well, you can put that code just into a javascript file, together with the code that uses the function, and then enqueue it for editor.

const select = wp.data.select,
   subscribe = wp.data.subscribe;

function whenEditorIsReady() {
    return new Promise((resolve) => {
        const unsubscribe = subscribe(() => {
            // This will trigger after the initial render blocking, before the window load event
            // This seems currently more reliable than using __unstableIsEditorReady
            if (select('core/editor').isCleanNewPost() || select('core/block-editor').getBlockCount() > 0) {
                unsubscribe()
                resolve()
            }
        })
    })
}

async function getEditorIframe() {
  await whenEditorIsReady();

  const editorCanvasIframeElement = document.querySelector('[name="editor-canvas"]');

  return new Promise((resolve) => {
    if(!editorCanvasIframeElement.loading) {
      // somehow the iframe has already loaded,
      // skip waiting for onload event (won't be triggered)
      resolve(editorCanvasIframeElement);
    }

    editorCanvasIframeElement.onload = () => {
      resolve(editorCanvasIframeElement);
    };
  });
}


// Wait for editor iframe becoming available (and editor becoming ready)
await getEditorIframe();
// your code here, when editor became available

@X-Raym
Copy link

X-Raym commented Feb 14, 2023

@strarsis thx you very much for this more detailed code snippet!

It do return an error though:

```Uncaught SyntaxError: await is only valid in async functions, async generators and modules````

@X-Raym
Copy link

X-Raym commented Feb 14, 2023

Ok I had to replace the last async call with

(async() => {
    await getEditorIframe();
    MyFunction()
  })();

And also

document.querySelector('[name="editor-canvas"]');

by

document.querySelector('.edit-post-header-toolbar__left');

(cause the first one was undefined. I needed the toolbar anyway), cause I use this to print custom infos on the Gutenberg toolbar.

Seems to works with these fixes, many thx!

img

@strarsis
Copy link

🤔 In latest Gutenberg it appears that no iframe element is used anymore.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment