Skip to content
This repository was archived by the owner on Oct 5, 2019. It is now read-only.

Commit 423161c

Browse files
committed
Import source from react4j
1 parent 5e1a69e commit 423161c

File tree

2 files changed

+123
-0
lines changed

2 files changed

+123
-0
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<module>
2+
<inherits name="react4j.annotations.Annotations"/>
3+
<inherits name="react4j.dom.ReactDOM"/>
4+
5+
<source path=''/>
6+
</module>
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package react4j.windowportal;
2+
3+
import elemental2.dom.DomGlobal;
4+
import elemental2.dom.Element;
5+
import elemental2.dom.HTMLDocument;
6+
import elemental2.dom.Window;
7+
import javax.annotation.Nonnull;
8+
import javax.annotation.Nullable;
9+
import jsinterop.base.Js;
10+
import org.realityforge.anodoc.Unsupported;
11+
import react4j.annotations.Prop;
12+
import react4j.annotations.ReactComponent;
13+
import react4j.core.Component;
14+
import react4j.core.ReactNode;
15+
import react4j.dom.ReactDOM;
16+
17+
/**
18+
* A portal that opens another window.
19+
* This was initially designed to be used so that a single application can be
20+
* split across multiple windows. This would allow a primary window to manage the data and then operate
21+
* across multiple windows. It also makes it possible to add
22+
*
23+
* <p>TODO: In the future we should pass a control in the context that allows the sub-window to close itself.</p>
24+
*/
25+
@ReactComponent
26+
@Unsupported
27+
public abstract class WindowPortal
28+
extends Component
29+
{
30+
@FunctionalInterface
31+
public interface OnCloseCallback
32+
{
33+
/**
34+
* Invoked when the external window is closed.
35+
*/
36+
void onClose();
37+
}
38+
39+
@Nullable
40+
private Window _externalWindow;
41+
@Nullable
42+
private Element _element;
43+
44+
@Prop
45+
protected abstract String windowName();
46+
47+
@Prop
48+
protected abstract int left();
49+
50+
@Prop
51+
protected abstract int top();
52+
53+
@Prop
54+
protected abstract int width();
55+
56+
@Prop
57+
protected abstract int height();
58+
59+
@Prop
60+
protected abstract OnCloseCallback onClose();
61+
62+
@Prop
63+
protected abstract ReactNode[] children();
64+
65+
@Override
66+
protected void postConstruct()
67+
{
68+
_externalWindow = DomGlobal.window.open( "",
69+
windowName(),
70+
"width=" + width() + ",height=" + height() +
71+
",left=" + left() + ",top=" + top() );
72+
_externalWindow.addEventListener( "beforeunload", e -> {
73+
final OnCloseCallback onClose = onClose();
74+
if ( null != onClose )
75+
{
76+
onClose.onClose();
77+
}
78+
} );
79+
final HTMLDocument document = getWindowDocument();
80+
_element = document.createElement( "div" );
81+
while ( document.body.childNodes.length > 0 )
82+
{
83+
//Unchecked cast as it is from a different window.
84+
document.body.removeChild( Js.uncheckedCast( document.body.childNodes.item( 0 ) ) );
85+
}
86+
document.body.appendChild( _element );
87+
}
88+
89+
@Nonnull
90+
private HTMLDocument getWindowDocument()
91+
{
92+
assert null != _externalWindow;
93+
/*
94+
* This needs to be an unchecked cast as the prototype for HTMLDocument is the one derived
95+
* from external window.
96+
*/
97+
return Js.uncheckedCast( Js.asPropertyMap( _externalWindow ).get( "document" ) );
98+
}
99+
100+
@Override
101+
protected void componentWillUnmount()
102+
{
103+
assert null != _externalWindow;
104+
assert null != _element;
105+
getWindowDocument().removeChild( _element );
106+
_externalWindow.close();
107+
}
108+
109+
@Nullable
110+
@Override
111+
protected ReactNode render()
112+
{
113+
assert null != _element;
114+
final ReactNode children = ReactNode.of( children() );
115+
return ReactDOM.createPortal( children, _element );
116+
}
117+
}

0 commit comments

Comments
 (0)