Skip to content

Commit d11363f

Browse files
authored
Don't make assumptions about DOM ordering (#5)
1 parent 41f1f97 commit d11363f

File tree

4 files changed

+42
-33
lines changed

4 files changed

+42
-33
lines changed

src/Halogen/VDom/DOM.js

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,32 +24,26 @@ exports.createElementNS = function (ns, name, doc) {
2424
};
2525
};
2626

27-
exports.replaceChild = function (a, b, c) {
28-
return function () {
29-
c.replaceChild(a, b);
30-
};
31-
};
32-
3327
exports.removeLastChild = function (a) {
3428
return function () {
3529
a.removeChild(a.lastChild);
3630
};
3731
};
3832

39-
exports.appendChild = function (a, b) {
33+
exports.insertChildIx = function (i, a, b) {
4034
return function () {
41-
b.appendChild(a);
35+
b.insertBefore(a, b.childNodes.item(i) || null);
4236
};
4337
};
4438

45-
exports.unsafeInsertChildIx = function (i, a, b) {
39+
exports.unsafeChildIx = function (i, d) {
4640
return function () {
47-
b.insertBefore(a, b.childNodes.item(i));
41+
return d.childNodes.item(i);
4842
};
4943
};
5044

51-
exports.unsafeChildIx = function (i, d) {
45+
exports.nodeLength = function (a) {
5246
return function () {
53-
return d.childNodes.item(i);
47+
return a.childNodes.length | 0;
5448
};
5549
};

src/Halogen/VDom/DOM.purs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ module Halogen.VDom.DOM
1313
import Prelude
1414
import Control.Monad.Eff (Eff, foreachE)
1515

16+
import Data.Array as Array
1617
import Data.Function.Uncurried as Fn
1718
import Data.Maybe (Maybe(..))
1819
import Data.Tuple (Tuple(..), fst)
@@ -23,7 +24,7 @@ import DOM.Node.Types (Element, Node, Document, elementToNode) as DOM
2324
import Halogen.VDom.Machine (Step(..), Machine)
2425
import Halogen.VDom.Machine as Machine
2526
import Halogen.VDom.Types (VDom(..), ElemSpec(..), ElemName, Namespace(..), runGraft)
26-
import Halogen.VDom.Util (forE, forInE, diffWithIxE, diffWithKeyAndIxE, strMapWithIxE, refEq)
27+
import Halogen.VDom.Util (forE, forInE, replicateE, diffWithIxE, diffWithKeyAndIxE, strMapWithIxE, refEq)
2728

2829
data Quaple a b c d = Quaple a b c d
2930

@@ -91,7 +92,7 @@ buildElem (VDomSpec spec) = render
9192
node = DOM.elementToNode el
9293
onChild = Fn.mkFn2 \ix child → do
9394
res@Step n m h ← buildVDom (VDomSpec spec) child
94-
Fn.runFn2 appendChild n node
95+
Fn.runFn3 insertChildIx ix n node
9596
pure res
9697
steps ← Fn.runFn2 forE ch1 onChild
9798
attrs ← spec.buildAttributes el as1
@@ -112,16 +113,17 @@ buildElem (VDomSpec spec) = render
112113
true → pure res
113114
_ → do
114115
halt
115-
Fn.runFn3 replaceChild n' n node
116+
Fn.runFn3 insertChildIx ix n' node
116117
pure res
117118
onThis = Fn.mkFn2 \ix (Step _ _ halt) → do
118119
halt
119-
removeLastChild node
120120
onThat = Fn.mkFn2 \ix vdom → do
121121
res@Step n m h ← buildVDom (VDomSpec spec) vdom
122-
Fn.runFn2 appendChild n node
122+
Fn.runFn3 insertChildIx ix n node
123123
pure res
124124
steps ← Fn.runFn5 diffWithIxE ch1 ch2 onThese onThis onThat
125+
len ← nodeLength node
126+
Fn.runFn2 replicateE (len - Array.length ch2) (removeLastChild node)
125127
attrs' ← Machine.step attrs as2
126128
pure
127129
(Step node
@@ -144,14 +146,14 @@ buildKeyed (VDomSpec spec) = render
144146
where
145147
render es1@(ElemSpec ns1 name1 as1) ch1 = do
146148
el ← Fn.runFn3 createElem ns1 name1 spec.document
147-
attrs ← spec.buildAttributes el as1
148149
let
149150
node = DOM.elementToNode el
150151
onChild = Fn.mkFn3 \k ix (Tuple _ vdom) → do
151152
Step n m h ← buildVDom (VDomSpec spec) vdom
152-
Fn.runFn2 appendChild n node
153+
Fn.runFn3 insertChildIx ix n node
153154
pure (Quaple k ix m h)
154155
steps ← Fn.runFn3 strMapWithIxE ch1 fst onChild
156+
attrs ← spec.buildAttributes el as1
155157
pure
156158
(Step node
157159
(Fn.runFn4 patch node attrs es1 steps)
@@ -161,7 +163,6 @@ buildKeyed (VDomSpec spec) = render
161163
Grafted g →
162164
Fn.runFn4 patch node attrs es1 ch1 (runGraft g)
163165
Keyed es2@(ElemSpec ns2 name2 as2) ch2 | Fn.runFn2 eqElemSpec es1 es2 → do
164-
attrs' ← Machine.step attrs as2
165166
let
166167
onThese = Fn.mkFn4 \k ix (Quaple _ ix' step halt) (Tuple _ vdom) →
167168
if ix == ix'
@@ -174,20 +175,22 @@ buildKeyed (VDomSpec spec) = render
174175
true → pure res
175176
_ → do
176177
halt
177-
Fn.runFn3 replaceChild n' n node
178+
Fn.runFn3 insertChildIx ix n' node
178179
pure res
179180
else do
180181
Step n' m' h' ← step vdom
181-
Fn.runFn3 unsafeInsertChildIx ix n' node
182+
Fn.runFn3 insertChildIx ix n' node
182183
pure (Quaple k ix m' h')
183184
onThis = Fn.mkFn2 \k (Quaple _ _ _ halt) → do
184185
halt
185-
removeLastChild node
186186
onThat = Fn.mkFn3 \k ix (Tuple _ vdom) → do
187187
Step n' m' h' ← buildVDom (VDomSpec spec) vdom
188-
Fn.runFn3 unsafeInsertChildIx ix n' node
188+
Fn.runFn3 insertChildIx ix n' node
189189
pure (Quaple k ix m' h')
190190
steps ← Fn.runFn6 diffWithKeyAndIxE ch1 ch2 fst onThese onThis onThat
191+
len ← nodeLength node
192+
Fn.runFn2 replicateE (len - Array.length ch2) (removeLastChild node)
193+
attrs' ← Machine.step attrs as2
191194
pure
192195
(Step node
193196
(Fn.runFn4 patch node attrs' es2 steps)
@@ -258,22 +261,18 @@ foreign import createElementNS
258261
eff
259262
. Fn.Fn3 Namespace ElemName DOM.Document (Eff (dom DOM | eff) DOM.Element)
260263

261-
foreign import replaceChild
262-
eff
263-
. Fn.Fn3 DOM.Node DOM.Node DOM.Node (Eff (dom DOM | eff) Unit)
264-
265264
foreign import removeLastChild
266265
eff
267266
. DOM.Node (Eff (dom DOM | eff) Unit)
268267

269-
foreign import appendChild
270-
eff
271-
. Fn.Fn2 DOM.Node DOM.Node (Eff (dom DOM | eff) Unit)
272-
273-
foreign import unsafeInsertChildIx
268+
foreign import insertChildIx
274269
eff
275270
. Fn.Fn3 Int DOM.Node DOM.Node (Eff (dom DOM | eff) Unit)
276271

277272
foreign import unsafeChildIx
278273
eff
279274
. Fn.Fn2 Int DOM.Node (Eff (dom DOM | eff) DOM.Node)
275+
276+
foreign import nodeLength
277+
eff
278+
. DOM.Node (Eff (dom DOM | eff) Int)

src/Halogen/VDom/Util.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ exports.forInE = function (o, f) {
2020
};
2121
};
2222

23+
exports.replicateE = function (n, f) {
24+
return function () {
25+
for (var i = 0; i < n; i++) {
26+
f();
27+
}
28+
};
29+
};
30+
2331
exports.diffWithIxE = function (a1, a2, f1, f2, f3) {
2432
return function () {
2533
var a3 = [];

src/Halogen/VDom/Util.purs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module Halogen.VDom.Util
22
( forE
33
, forInE
4+
, replicateE
45
, diffWithIxE
56
, diffWithKeyAndIxE
67
, strMapWithIxE
@@ -26,6 +27,13 @@ foreign import forInE
2627
(Fn.Fn2 String a (Eff eff Unit))
2728
(Eff eff Unit)
2829

30+
foreign import replicateE
31+
eff a
32+
. Fn.Fn2
33+
Int
34+
(Eff eff a)
35+
(Eff eff Unit)
36+
2937
foreign import diffWithIxE
3038
eff b c d
3139
. Fn.Fn5

0 commit comments

Comments
 (0)