Skip to content
Permalink
Browse files

#226 - Code changes for consistency

  • Loading branch information...
estruyf committed Feb 7, 2019
1 parent a1a98e6 commit 873bb781c8cd8efe1ad6a34fef0542b4466a363b
@@ -1,6 +1,6 @@
# IFrameDialog control

This control renders a Dialog with an iframe as a content.
This control renders a Dialog with an iframe as content.

Here is an example of the control in action:

@@ -58,4 +58,4 @@ The IFrameDialog component can be configured with the following properties:
| scrolling | string | no | Specifies whether or not to display scrollbars in an iframe |
| seamless | string | no | When present, it specifies that the iframe should look like it is a part of the containing document (no borders or scrollbars) |

![](https://telemetry.sharepointpnp.com/sp-dev-fx-controls-react/wiki/controls/FileTypeIcon)
![](https://telemetry.sharepointpnp.com/sp-dev-fx-controls-react/wiki/controls/IFrameDialog)
@@ -1,6 +1,6 @@
# IFramePanel control

This control renders a Panel with an iframe as a content.
This control renders a Panel with an iframe as content.

Here is an example of the control in action:

@@ -21,15 +21,13 @@ import { IFramePanel } from "@pnp/spfx-controls-react/lib/IFramePanel";


```TypeScript
<IFramePanel
url={this.state.iFrameUrl}
type={PanelType.medium}
headerText="Panel Title"
closeButtonAriaLabel="Close"
isOpen={this.state.iFramePanelOpened}
onDismiss={this._onDismiss.bind(this)}
iframeOnLoad={this._onIframeLoaded.bind(this)}
/>
<IFramePanel url={this.state.iFrameUrl}
type={PanelType.medium}
headerText="Panel Title"
closeButtonAriaLabel="Close"
isOpen={this.state.iFramePanelOpened}
onDismiss={this._onDismiss.bind(this)}
iframeOnLoad={this._onIframeLoaded.bind(this)} />
```

## Implementation
@@ -1,63 +1,21 @@
import * as React from 'react';
import { Guid } from "@microsoft/sp-core-library";
import styles from './IFramePanelContent.module.scss';
import { Panel, IPanelProps } from 'office-ui-fabric-react/lib/Panel';
import { Panel } from 'office-ui-fabric-react/lib/Panel';
import omit = require('lodash/omit');
import { IFramePanelContent } from './IFramePanelContent';

export interface IIFramePanelProps extends IPanelProps {
/**
* iframe Url
*/
url: string;
/**
* iframe height, if null then hight is calculated
*/
height?: string;
/**
* Specifies if iframe content can be displayed in a full screen.
* Usage: <IFrameDialog allowFullScreen />
*/
allowFullScreen?: boolean;
/**
* iframe's onload event handler
*/
iframeOnLoad?: (iframe: any) => void;
/**
* Specifies if transparency is allowed in iframe
*/
allowTransparency?: boolean;
/**
* Specifies the name of an <iframe>
*/
name?: string;
/**
* Enables an extra set of restrictions for the content in an <iframe>
*/
sandbox?: string;
/**
* Specifies whether or not to display scrollbars in an <iframe>
*/
scrolling?: string;
/**
* When present, it specifies that the <iframe> should look like it is a part of the containing document (no borders or scrollbars)
*/
seamless?: boolean;
}

export interface IIFramePanelState {
}
import { IIFramePanelProps, IIFramePanelState } from '.';

export class IFramePanel extends React.Component<IIFramePanelProps, IIFramePanelState> {

constructor(props: IIFramePanelProps) {
super(props);

this.state = {
};
this.state = {};
}

/**
* Default React render
*/
public render(): React.ReactElement<IIFramePanelProps> {

const {
height,
allowFullScreen,
@@ -68,21 +26,19 @@ export class IFramePanel extends React.Component<IIFramePanelProps, IIFramePanel
scrolling,
seamless
} = this.props;

return (
<Panel
{...omit(this.props, 'className')}
>
<Panel {...omit(this.props, 'className')} >
<IFramePanelContent src={this.props.url}
iframeOnLoad={iframeOnLoad}
close={this.props.onDismiss}
height={height}
allowFullScreen={allowFullScreen}
allowTransparency={allowTransparency}
name={name}
sandbox={sandbox}
scrolling={scrolling}
seamless={seamless}
/>
iframeOnLoad={iframeOnLoad}
close={this.props.onDismiss}
height={height}
allowFullScreen={allowFullScreen}
allowTransparency={allowTransparency}
name={name}
sandbox={sandbox}
scrolling={scrolling}
seamless={seamless} />
</Panel>
);
}
@@ -2,15 +2,7 @@ import * as React from "react";
import styles from './IFramePanelContent.module.scss';
import { Spinner, SpinnerSize } from 'office-ui-fabric-react/lib/Spinner';
import omit = require('lodash/omit');

export interface IIFramePanelContentProps extends React.IframeHTMLAttributes<HTMLIFrameElement> {
close: () => void;
iframeOnLoad?: (iframe: any) => void;
}

export interface IIFramePanelContentState {
isContentVisible?: boolean;
}
import { IIFramePanelContentProps, IIFramePanelContentState } from ".";

/**
* IFrame Panel content
@@ -27,29 +19,47 @@ export class IFramePanelContent extends React.Component<IIFramePanelContentProps
window.onresize = this.resizeIframe;
}

/**
* Resize the iframe element
*/
private resizeIframe = () => {
if (!this.props.height) {
if (this._iframe) {
let mainDiv = this._iframe.parentElement.parentElement.parentElement.parentElement as HTMLDivElement;
let commandsDiv = mainDiv.getElementsByClassName("ms-Panel-commands")[0] as HTMLDivElement;
let headerDiv = mainDiv.getElementsByClassName("ms-Panel-header")[0] as HTMLDivElement;
let footerDiv = mainDiv.getElementsByClassName("ms-Panel-footer")[0] as HTMLDivElement;
const mainDiv = this.findParent(this._iframe, "ms-Panel-main");
const commandsDiv = mainDiv.querySelector(".ms-Panel-commands") as HTMLDivElement;
const headerDiv = mainDiv.querySelector("ms-Panel-header") as HTMLDivElement;
const footerDiv = mainDiv.querySelector("ms-Panel-footer") as HTMLDivElement;

let height = this.getTrueHeight(mainDiv);
height = height - this.getTrueHeight(commandsDiv);
height = height - this.getTrueHeight(headerDiv);
height = height - this.getTrueHeight(footerDiv);
height = height - 20; // padding on content div


this._iframe.height = height.toString() + 'px';
}
}
}

private getTrueHeight(element): number {
if (element) {
let style = element.currentStyle || window.getComputedStyle(element);
/**
* Find the parent element
*
* @param elm
* @param className
*/
private findParent(elm: HTMLElement, className: string) {
while ((elm = elm.parentElement) && !elm.classList.contains(className));
return elm;
}

/**
* Get the element its height
*
* @param elm
*/
private getTrueHeight(elm: HTMLElement): number {
if (elm) {
const style = elm.style || window.getComputedStyle(elm);
let marginTop = parseInt((style.marginTop as string).replace("px", ""));
let marginBottom = parseInt((style.marginTop as string).replace("px", ""));
if (isNaN(marginTop)) {
@@ -58,24 +68,16 @@ export class IFramePanelContent extends React.Component<IIFramePanelContentProps
if (isNaN(marginBottom)) {
marginBottom = 0;
}
return element.offsetHeight + marginTop + marginBottom;
}
else {
return elm.offsetHeight + marginTop + marginBottom;
} else {
return 0;
}
}

public render(): JSX.Element {
return (<div className={styles.iFrameDialog}>
<iframe ref={(iframe) => { this._iframe = iframe; }} frameBorder={0} onLoad={this._iframeOnLoad} style={{ width: '100%', height: this.props.height, visibility: this.state.isContentVisible ? 'visible' : 'hidden' }} {...omit(this.props, 'height')} />
{!this.state.isContentVisible &&
<div className={styles.spinnerContainer}>
<Spinner size={SpinnerSize.large} />
</div>}
</div>);
}

private _iframeOnLoad = () => {
/**
* On iframe load event
*/
private iframeOnLoad = () => {
try { // for cross origin requests we can have issues with accessing frameElement
this._iframe.contentWindow.frameElement.cancelPopUp = this.props.close;
}
@@ -95,4 +97,23 @@ export class IFramePanelContent extends React.Component<IIFramePanelContentProps
isContentVisible: true
});
}

/**
* Default React render
*/
public render(): JSX.Element {
return (
<div className={styles.iFrameDialog}>
<iframe ref={(iframe) => { this._iframe = iframe; }} frameBorder={0} onLoad={this.iframeOnLoad} style={{ width: '100%', height: this.props.height, visibility: this.state.isContentVisible ? 'visible' : 'hidden' }} {...omit(this.props, 'height')} />

{
!this.state.isContentVisible && (
<div className={styles.spinnerContainer}>
<Spinner size={SpinnerSize.large} />
</div>
)
}
</div>
);
}
}
@@ -0,0 +1,4 @@
export interface IIFramePanelContentProps extends React.IframeHTMLAttributes<HTMLIFrameElement> {
close: () => void;
iframeOnLoad?: (iframe: any) => void;
}
@@ -0,0 +1,3 @@
export interface IIFramePanelContentState {
isContentVisible?: boolean;
}
@@ -0,0 +1,41 @@
import { IPanelProps } from "office-ui-fabric-react/lib/Panel";

export interface IIFramePanelProps extends IPanelProps {
/**
* iframe Url
*/
url: string;
/**
* iframe height, if null then hight is calculated
*/
height?: string;
/**
* Specifies if iframe content can be displayed in a full screen.
* Usage: <IFrameDialog allowFullScreen />
*/
allowFullScreen?: boolean;
/**
* iframe's onload event handler
*/
iframeOnLoad?: (iframe: any) => void;
/**
* Specifies if transparency is allowed in iframe
*/
allowTransparency?: boolean;
/**
* Specifies the name of an <iframe>
*/
name?: string;
/**
* Enables an extra set of restrictions for the content in an <iframe>
*/
sandbox?: string;
/**
* Specifies whether or not to display scrollbars in an <iframe>
*/
scrolling?: string;
/**
* When present, it specifies that the <iframe> should look like it is a part of the containing document (no borders or scrollbars)
*/
seamless?: boolean;
}
@@ -0,0 +1,2 @@
export interface IIFramePanelState {
}
@@ -1,3 +1,7 @@
export * from './IFramePanelContent.module.scss';
export * from './IFramePanelContent';
export * from './IFramePanelContentProps';
export * from './IFramePanelContentState';
export * from './IFramePanel';
export * from './IFramePanelProps';
export * from './IFramePanelState';

0 comments on commit 873bb78

Please sign in to comment.
You can’t perform that action at this time.