Cannot trigger resize

Hi

I have the H5P plugin 1.10.3 on a WordPress 4.9.8 (latest version) site.  It also has WP Bakery visual editor on it and if producing tabs for users to click on.  I have looked at https://h5p.org/manipulating-h5p-with-javascript and I can use it to recognise the click of the tab and log this in the console.  I can see from the guide that I need to make sure the panel height is automatic, and then do the H5P resize.  However, I'm not sure what I need to do to get the <pre class="brush: jscript">ui.newPanel.css('height', 'auto');</pre>

part of this to work. How should I modify this line of jQuery to make this happen please? Do I need to target a specific h5p iframe?

Many thanks

Mike

otacke's picture

Hi Mike!

If you already managed to log the click using console.log(something), you should also be able to trigger a resize instead using

H5P.jQuery(window).trigger('resize');

as listed in the example on the page or using

window.dispatchEvent(new Event('resize'));

given that the window object is the correct one in your context.

Cheers,
Oliver

Many thanks, Oliver, that's great.  The second trigger is the one that worked for me!

Regards

Mike

We were showing H5P iframes in JS tabs and had the same issue described.
The 'official' solution didn't seem to work, and we also had to add a timeout so they resized correctly.

setTimeout(() => {
window.dispatchEvent(new Event('resize'));
}, 0);
otacke's picture

Hi!

Whether you need to add a delay or not completely depends on when you're adding the trigger. That has not really something to do with H5P or "the official solution" but with how browsers work - good to know when you work with JavaScript.

Browsers don't add changes to the DOM right away when you modify it via JavaScript, but they have render cycles. If, for instance, your tab is made visible by removing some stylesheetclass and you instantly dispatch the resize event, the new DOM state may still not have been rendered when H5P tries to determine the height and leave it with 0. The timeout callback ensures that the DOM has been redrawn as it's called after the DOM has been re-rendered even if the milliseconds are set to 0.

That's why one commonly wraps calls that should run only after the DOM has been redrawn in a timeout or by using `requestAnimationFrame` like so:

/*
 * Assuming that some container element `element` holding H5P content
 * is hidden by something such as `display: none`. When resizing, H5P
 * will only find a height of 0 px to fill.
 */

/*
 * This will request the browser to render the element with a
 * different value for the CSS `display` property which would allow
 * H5P to use some space.
 */
element.style.display = 'block';

/*
 * When the next line runs, the browser may not have re-rendered the DOM.
 * The resize might not work.
 */
window.dispatchEvent(new Event('resize'));

// This one will ensure triggering after re-rendering the DOM.
window.setTimeout(() => {
  window.dispatchEvent(new Event('resize'));
}, 0);

// This one will also ensure triggering after re-rendering the DOM.
window.requestAnimationFrame(() => {
  window.dispatchEvent(new Event('resize'));
});

 

Best,
Oliver

Thanks for rthe detailed reply! Makes sense, was just sharing our solution in case anyone else found it useful.

Good to have your comprehensive solution for reference.