tangled
alpha
login
or
join now
yippee.fun
/
morphlex
0
fork
atom
Precise DOM morphing
morphing
typescript
dom
0
fork
atom
overview
issues
pulls
pipelines
Fix new algorithm
joel.drapper.me
4 months ago
532446f3
d13a64c7
+19
-57
1 changed file
expand all
collapse all
unified
split
src
morphlex.ts
+19
-57
src/morphlex.ts
···
286
286
matches.set(node, candidate)
287
287
unmatched.delete(node)
288
288
candidates.delete(candidate)
289
289
+
break
289
290
}
290
291
}
291
292
}
···
301
302
matches.set(node, candidate)
302
303
unmatched.delete(node)
303
304
candidates.delete(candidate)
305
305
+
break
304
306
}
305
307
}
306
308
}
···
319
321
matches.set(node, candidate)
320
322
unmatched.delete(node)
321
323
candidates.delete(candidate)
324
324
+
break
322
325
}
323
326
}
324
327
}
···
336
339
matches.set(node, candidate)
337
340
unmatched.delete(node)
338
341
candidates.delete(candidate)
342
342
+
break
339
343
}
340
344
}
341
345
} else {
342
346
for (const candidate of candidates) {
343
343
-
if (nodeType === candidate.nodeType && node.nodeValue === candidate.nodeValue) {
347
347
+
if (nodeType === candidate.nodeType) {
344
348
matches.set(node, candidate)
345
349
unmatched.delete(node)
346
350
candidates.delete(candidate)
351
351
+
break
347
352
}
348
353
}
349
354
}
350
355
}
351
356
352
352
-
let prevNode: ChildNode | null = null
353
353
-
// remove remaining nodes in reverse order
354
354
-
for (let i = toChildNodes.length - 1; i >= 0; i--) {
357
357
+
// Process nodes in forward order to maintain proper positioning
358
358
+
let insertionPoint: ChildNode | null = parent.firstChild
359
359
+
for (let i = 0; i < toChildNodes.length; i++) {
355
360
const node = toChildNodes[i]!
356
361
const match = matches.get(node)
357
362
if (match) {
358
358
-
moveBefore(parent, match, prevNode)
363
363
+
moveBefore(parent, match, insertionPoint)
359
364
this.morphOneToOne(match, node)
360
360
-
prevNode = match
365
365
+
insertionPoint = match.nextSibling
361
366
} else {
362
362
-
moveBefore(parent, node, prevNode)
363
363
-
prevNode = node
367
367
+
if (this.options.beforeNodeAdded?.(node) ?? true) {
368
368
+
moveBefore(parent, node, insertionPoint)
369
369
+
this.options.afterNodeAdded?.(node)
370
370
+
insertionPoint = node.nextSibling
371
371
+
}
364
372
}
365
373
}
366
374
367
367
-
const numberOfNodesToRemove = from.childNodes.length - toChildNodes.length
368
368
-
for (let i = fromChildNodes.length - 1; i >= numberOfNodesToRemove; i--) {
369
369
-
this.removeNode(from.childNodes[i]!)
375
375
+
// Remove any remaining unmatched candidates
376
376
+
for (const candidate of candidates) {
377
377
+
this.removeNode(candidate)
370
378
}
371
379
}
372
372
-
373
373
-
// private searchSiblingsToMorphChildElement(from: ChildNode, to: Element, parent: ParentNode): void {
374
374
-
// const id = to.id
375
375
-
// const idSet = this.idMap.get(to)
376
376
-
// const idSetArray = idSet ? [...idSet] : []
377
377
-
378
378
-
// let currentNode: ChildNode | null = from
379
379
-
// let bestMatch: Element | null = null
380
380
-
// let idSetMatches: number = 0
381
381
-
382
382
-
// while (currentNode) {
383
383
-
// if (isElement(currentNode) && currentNode.localName === to.localName) {
384
384
-
// // If we found an exact match, this is the best option.
385
385
-
// if (id && id !== "" && id === currentNode.id) {
386
386
-
// bestMatch = currentNode
387
387
-
// break
388
388
-
// }
389
389
-
390
390
-
// // Try to find the node with the best idSet match
391
391
-
// const currentIdSet = this.idMap.get(currentNode)
392
392
-
// if (currentIdSet) {
393
393
-
// const numberOfMatches = idSetArray.filter((id) => currentIdSet.has(id)).length
394
394
-
// if (numberOfMatches > idSetMatches) {
395
395
-
// bestMatch = currentNode
396
396
-
// idSetMatches = numberOfMatches
397
397
-
// }
398
398
-
// }
399
399
-
400
400
-
// // The fallback is to just use the next element with the same localName
401
401
-
// if (!bestMatch) {
402
402
-
// bestMatch = currentNode
403
403
-
// }
404
404
-
// }
405
405
-
406
406
-
// currentNode = currentNode.nextSibling
407
407
-
// }
408
408
-
409
409
-
// if (bestMatch) {
410
410
-
// if (bestMatch !== from) {
411
411
-
// moveBefore(parent, bestMatch, from)
412
412
-
// }
413
413
-
// this.morphOneToOne(bestMatch, to)
414
414
-
// } else {
415
415
-
// this.morphOneToOne(from, to)
416
416
-
// }
417
417
-
// }
418
380
419
381
private updateProperty<N extends Node, P extends keyof N>(node: N, propertyName: P, newValue: N[P]): void {
420
382
const oldValue = node[propertyName]