I’ve been working on an oEmbed endpoint for consider.it that returns HTML that can be Oneboxed in a Discourse thread. Currently, the oEmbed html snippet is mostly just an iframe, along with a small javascript library injected into the containing window. This javascript library is capable of communicating with the iframe to dynamically adjust its height. This library is designed to play nicely with the containing window.
The javascript in the above code is unfortunately not consistently executing in a Discourse thread, and I’m at a loss as to why. I’ve observed the following bizarre but replicable behavior from Discourse:
javascript DOES NOT run if I just load a thread containing a Oneboxed considerit link
javascript DOES run if I have the post editor open with the link, but only for the Oneboxed link in the thread, not in the preview window.
This behavior is consistent when refreshing the page. I recorded this riveting 40 second video to demonstrate the behavior.
I can’t tell if:
Discourse intends to disable javascript for Onebox’d html oEmbeds (and the edit post behavior is a bug), or
Discourse intends to enable javascript but there is a bug in Discourse or my own code that is preventing it from happening.
If (1), is there a recommended method for the provider to enable dynamically resizing Oneboxed content? Or is it impossible to dynamically resize Oneboxed content in Discourse?
If (2), is there a workaround or recommended course of action?
@rxhector: That runs into the same problem that I described, namely that the containing window has to be allowed to execute javascript.
I think, but am not sure, that Discourse/Onebox has a policy that javascript cannot be injected by an oEmbed provider. It is hard to tell though because sometimes Discourse allows injected javascript to execute. I’m having a hard time getting an answer on what Discourse’s intention is!
I think the short video I recorded above demonstrates a situation where my non-whitelisted javascript is executed against Discourse’s policy. So it might be a bug. If you think it is worthwhile, I’d be happy to file a report.
Is it possible for me to create a custom onebox where I can get the above javascript whitelisted? If so, a little hint about how I could get started would be appreciated!
Reviving an old thread: I’d like the same functionality, dynamically resized iframes. Since it seems allowing oembed providers to include script tags isn’t likely to happen (which I completely understand), a reasonable alternative would be for Discourse to implement a pretty simple hook.
Embed.ly provides this functionality by just sending a fairly simple postMessage, and on the host page, their library includes essentially this snippet:
window.addEventListener('message', function(e) {
var data;
try {
data = JSON.parse(e.data);
} catch (e) {
return false;
}
if (data.context !== 'iframe.resize') {
return false;
}
var iframe = document.querySelector('iframe[src="' + data.src + '"]');
if (!iframe) {
return false;
}
if (data.height) {
iframe.height = data.height;
}
});
Discourse could implement something compatible with this same message and a lot of things that work with embed.ly would just automatically work. From the implementor’s perspective, it’s as simple as sending this JSON whenever your iframe needs to be resized:
The problem with this is that Discourse really wants to know the vertical size of things when it lays out posts. Otherwise you can be looking at a post, and something above it forces the document to layout again, again and you lose the spot you’re reading because everything’s been pushed down.
But the size of something can change once you’ve interacted with it, which negates that argument – I’m not trying to keep my reading spot, I’m trying to interact with a widget.
For a specific example, look at how my product, RunKit, works once you click “run”:
I think that is the argument, cause the embed would raise an event to discourse telling it to resize when you click run.
However, it is an abuse vector cause the embed could just do it anyway if it was allowed to, and wreak havoc on initial render, so we would probably have to ignore the event for N seconds or something.