@@ -72,6 +72,44 @@ function enqueueMeteorStateUpdate(component) {
72
72
} ) ;
73
73
}
74
74
75
+ // Like React.render, but it replaces targetNode, and works even if
76
+ // targetNode.parentNode has children other than targetNode.
77
+ function renderInPlaceOfNode ( reactElement , targetNode ) {
78
+ var container = targetNode . parentNode ;
79
+ var prevSibs = [ ] ;
80
+ var nextSibs = [ ] ;
81
+ var sibs = prevSibs ;
82
+ var child = container . firstChild ;
83
+
84
+ while ( child ) {
85
+ if ( child === targetNode ) {
86
+ sibs = nextSibs ;
87
+ } else {
88
+ sibs . push ( child ) ;
89
+ }
90
+ var next = child . nextSibling ;
91
+ container . removeChild ( child ) ;
92
+ child = next ;
93
+ }
94
+
95
+ var result = React . render ( reactElement , container ) ;
96
+ var rendered = container . firstChild ;
97
+
98
+ if ( prevSibs . length > 0 ) {
99
+ prevSibs . forEach ( function ( sib ) {
100
+ container . insertBefore ( sib , rendered ) ;
101
+ } ) ;
102
+ }
103
+
104
+ if ( nextSibs . length > 0 ) {
105
+ nextSibs . forEach ( function ( sib ) {
106
+ container . appendChild ( sib ) ;
107
+ } ) ;
108
+ }
109
+
110
+ return result ;
111
+ }
112
+
75
113
ReactMeteor = {
76
114
Mixin : ReactMeteorMixin ,
77
115
@@ -87,17 +125,17 @@ ReactMeteor = {
87
125
var template = new Template (
88
126
spec . templateName ,
89
127
function ( ) {
90
- // A placeholder HTML element whose parentNode will serve as the
91
- // container into which React.render renders the component.
128
+ // A placeholder HTML element that will serve as the mounting
129
+ // point for the React component. May have siblings!
92
130
return new HTML . SPAN ;
93
131
}
94
132
) ;
95
133
96
134
template . onRendered ( function ( ) {
97
- React . render (
135
+ renderInPlaceOfNode (
98
136
// Equivalent to <Cls {...this.data} />:
99
137
React . createElement ( Cls , this . data || { } ) ,
100
- this . find ( "span" ) . parentNode
138
+ this . find ( "span" )
101
139
) ;
102
140
} ) ;
103
141
0 commit comments