Skip to content

Commit

Permalink
Merge pull request #222 from bertomaniac/bugfix/floating-window-styles
Browse files Browse the repository at this point in the history
Fix an issue with copying styles for a floating window
  • Loading branch information
nealus authored Aug 26, 2021
2 parents 85464e2 + 5d90c5d commit 6cb749e
Showing 1 changed file with 30 additions and 13 deletions.
43 changes: 30 additions & 13 deletions src/view/FloatingWindow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ export interface IFloatingWindowProps {
onSetWindow: (id: string, window: Window) => void;
}

interface IStyleSheet {
href: string | null;
type: string;
rules: string[];
}

/** @hidden @internal */
export const FloatingWindow = (props: React.PropsWithChildren<IFloatingWindowProps>) => {
const { title, id, url, rect, onCloseWindow, onSetWindow, children } = props;
Expand All @@ -21,6 +27,24 @@ export const FloatingWindow = (props: React.PropsWithChildren<IFloatingWindowPro

React.useLayoutEffect(() => {
const r = rect;
// Make a local copy of the styles from the current window which will be passed into
// the floating window. window.document.styleSheets is mutable and we can't guarantee
// the styles will exist when 'popoutWindow.load' is called below.
const styles = Array.from(window.document.styleSheets).reduce((result, styleSheet) => {
try {
return [
...result,
{
href: styleSheet.href,
type: styleSheet.type,
rules: Array.from(styleSheet.cssRules).map(rule => rule.cssText),
}
];
} catch (e) {
// styleSheet.cssRules can throw security exception
return result;
}
}, [] as IStyleSheet[]);
popoutWindow.current = window.open(url, id, `left=${r.x},top=${r.y},width=${r.width},height=${r.height}`);
if (popoutWindow.current !== null) {
onSetWindow(id, popoutWindow.current);
Expand All @@ -39,7 +63,7 @@ export const FloatingWindow = (props: React.PropsWithChildren<IFloatingWindowPro
const popoutContent = popoutDocument.createElement("div");
popoutContent.className = CLASSES.FLEXLAYOUT__FLOATING_WINDOW_CONTENT;
popoutDocument.body.appendChild(popoutContent);
copyStyles(popoutDocument).then(() => {
copyStyles(popoutDocument, styles).then(() => {
setContent(popoutContent);
});

Expand Down Expand Up @@ -72,10 +96,10 @@ export const FloatingWindow = (props: React.PropsWithChildren<IFloatingWindowPro
};

/** @hidden @internal */
function copyStyles(doc: Document): Promise<boolean[]> {
function copyStyles(doc: Document, styleSheets: IStyleSheet[]): Promise<boolean[]> {
const head = doc.head;
const promises: Promise<boolean>[] = [];
Array.from(window.document.styleSheets).forEach((styleSheet) => {
styleSheets.forEach((styleSheet) => {
if (styleSheet.href) {
// prefer links since they will keep paths to images etc
const styleElement = doc.createElement("link");
Expand All @@ -89,16 +113,9 @@ function copyStyles(doc: Document): Promise<boolean[]> {
})
);
} else {
try {
const rules = styleSheet.cssRules;
const style = doc.createElement("style");
Array.from(rules).forEach((cssRule) => {
style.appendChild(doc.createTextNode(cssRule.cssText));
});
head.appendChild(style);
} catch (e) {
// styleSheet.cssRules can thro security exception
}
const style = doc.createElement("style");
styleSheet.rules.forEach(rule => style.appendChild(doc.createTextNode(rule)));
head.appendChild(style);
}
});
return Promise.all(promises);
Expand Down

0 comments on commit 6cb749e

Please sign in to comment.