discourse/public/javascripts/embed.js
Rafael dos Santos Silva ce3b528204
FIX: Use iframe style.height for embed resize messages (#39321)
## Summary

When Discourse is loaded in full app embed mode with `dynamicHeight:
true`, the iframe was not resizing in production despite
`discourse-resize` messages arriving correctly.

The full app path sets `iframe.style.height` as an inline style for the
initial height. Inline styles always win over the `height` HTML
attribute, so our resize handler — which set `iframe.height = ...` — had
no visible effect.

This changes the resize handler to set `iframe.style.height` so it
actually overrides the inline style. This also works for the standard
(non-full-app) embed path since no inline style is set there initially.

## Test plan

- [ ] Full app embed with `dynamicHeight: true` — verify iframe height
updates as content loads
- [ ] Standard (non-full-app) embed — verify iframe still resizes
correctly
- [ ] CSS `max-height` on the iframe still wins (inline `height` doesn't
override `max-height`)
2026-04-16 15:17:06 -03:00

124 lines
3 KiB
JavaScript

(function () {
var DE = window.DiscourseEmbed || {};
var comments = document.getElementById("discourse-comments");
var iframe = document.createElement("iframe");
[
"discourseUrl",
"discourseEmbedUrl",
"discourseUserName",
"discourseReferrerPolicy",
].forEach(function (i) {
if (window[i]) {
DE[i] = DE[i] || window[i];
}
});
var queryParams = {};
if (DE.discourseEmbedUrl) {
if (DE.discourseEmbedUrl.startsWith("/")) {
console.error(
"discourseEmbedUrl must be a full URL, not a relative path"
);
}
queryParams.embed_url = encodeURIComponent(DE.discourseEmbedUrl);
}
if (DE.discourseUserName) {
queryParams.discourse_username = DE.discourseUserName;
}
if (DE.topicId) {
queryParams.topic_id = DE.topicId;
}
if (DE.className) {
queryParams.class_name = DE.className;
}
if (DE.fullApp) {
queryParams.full_app = "true";
}
var src = DE.discourseUrl + "embed/comments";
var keys = Object.keys(queryParams);
if (keys.length > 0) {
src += "?";
for (var i = 0; i < keys.length; i++) {
if (i > 0) {
src += "&";
}
var k = keys[i];
src += k + "=" + queryParams[k];
}
}
iframe.src = src;
iframe.id = "discourse-embed-frame";
iframe.width = "100%";
iframe.frameBorder = "0";
iframe.scrolling = DE.fullApp ? "yes" : "no";
if (DE.fullApp) {
iframe.style.height = DE.embedHeight || "600px";
iframe.loading = DE.lazyLoad === false ? "eager" : "lazy";
}
iframe.referrerPolicy =
DE.discourseReferrerPolicy || "no-referrer-when-downgrade";
comments.appendChild(iframe);
// Thanks http://amendsoft-javascript.blogspot.ca/2010/04/find-x-and-y-coordinate-of-html-control.html
function findPosY(obj) {
var top = 0;
if (obj.offsetParent) {
while (1) {
top += obj.offsetTop;
if (!obj.offsetParent) break;
obj = obj.offsetParent;
}
} else if (obj.y) {
top += obj.y;
}
return top;
}
function normalizeUrl(url) {
return url.replace(/^https?(\:\/\/)?/, "");
}
function postMessageReceived(e) {
if (!e) {
return;
}
if (!normalizeUrl(DE.discourseUrl).includes(normalizeUrl(e.origin))) {
return;
}
if (e.data) {
if (e.data.type === "discourse-resize" && e.data.height) {
if (DE.fullApp && !DE.dynamicHeight) {
return;
}
var height = e.data.height;
if (DE.embedMinHeight) {
height = Math.max(height, parseInt(DE.embedMinHeight, 10));
}
if (DE.embedMaxHeight) {
height = Math.min(height, parseInt(DE.embedMaxHeight, 10));
}
iframe.style.height = height + "px";
}
if (e.data.type === "discourse-scroll" && e.data.top) {
// find iframe offset
var destY = findPosY(iframe) + e.data.top;
window.scrollTo(0, destY);
}
}
}
window.addEventListener("message", postMessageReceived, false);
})();