src/Bindings/DomBinding/applyChangesFromDom.js
import YXmlHook from '../../YXml/YXmlHook.js'
import {
iterateUntilUndeleted,
removeAssociation,
insertNodeHelper } from './util.js'
/*
* 1. Check if any of the nodes was deleted
* 2. Iterate over the children.
* 2.1 If a node exists without _yxml property, insert a new node
* 2.2 If _contents.length < dom.childNodes.length, fill the
* rest of _content with childNodes
* 2.3 If a node was moved, delete it and
* recreate a new yxml element that is bound to that node.
* You can detect that a node was moved because expectedId
* !== actualId in the list
*/
export default function applyChangesFromDom (dom, yxml) {
if (yxml == null || yxml === false || yxml.constructor === YXmlHook) {
return
}
const y = yxml._y
const knownChildren = new Set()
for (let child in dom.childNodes) {
const type = knownChildren.get(child)
if (type !== undefined && type !== false) {
knownChildren.add(type)
}
}
// 1. Check if any of the nodes was deleted
yxml.forEach(function (childType) {
if (knownChildren.has(childType) === false) {
childType._delete(y)
}
})
// 2. iterate
const childNodes = dom.childNodes
const len = childNodes.length
let prevExpectedType = null
let expectedType = iterateUntilUndeleted(yxml._start)
for (let domCnt = 0; domCnt < len; domCnt++) {
const childNode = childNodes[domCnt]
const childType = this.domToYXml.get(childNode)
if (childType != null) {
if (childType === false) {
// should be ignored or is going to be deleted
continue
}
if (expectedType !== null) {
if (expectedType !== childType) {
// 2.3 Not expected node
if (childType._parent !== yxml) {
// child was moved from another parent
// childType is going to be deleted by its previous parent
removeAssociation(this, childNode, this.domToYXml(childNode))
} else {
// child was moved to a different position.
childType._delete(y)
}
prevExpectedType = insertNodeHelper(yxml, prevExpectedType, childNode)
} else {
// Found expected node
prevExpectedType = expectedType
expectedType = iterateUntilUndeleted(expectedType._right)
}
} else {
// 2.2 Fill _content with child nodes
prevExpectedType = insertNodeHelper(yxml, prevExpectedType, childNode)
}
} else {
// 2.1 A new node was found
prevExpectedType = insertNodeHelper(yxml, prevExpectedType, childNode)
}
}
}