filter remote changes in YXml*

This commit is contained in:
Kevin Jahns
2017-11-26 14:39:47 -08:00
parent 2e3240b379
commit d0d1015074
7 changed files with 123 additions and 33 deletions

View File

@@ -34,16 +34,15 @@ export default class YXmlElement extends YXmlFragment {
} else {
// tag is already set in constructor
// set attributes
let attrNames = []
let attributes = new Map()
for (let i = 0; i < dom.attributes.length; i++) {
attrNames.push(dom.attributes[i].name)
}
attrNames = this._domFilter(dom, attrNames)
for (let i = 0; i < attrNames.length; i++) {
let attrName = attrNames[i]
let attrValue = dom.getAttribute(attrName)
this.setAttribute(attrName, attrValue)
let attr = dom.attributes[i]
attributes.set(attr.name, attr.value)
}
attributes = this._domFilter(dom, attributes)
attributes.forEach((value, name) => {
this.setAttribute(name, value)
})
this.insertDomElements(0, Array.prototype.slice.call(dom.childNodes), _document)
this._bindToDom(dom, _document)
return dom
@@ -104,7 +103,9 @@ export default class YXmlElement extends YXmlFragment {
getAttributes () {
const obj = {}
for (let [key, value] of this._map) {
obj[key] = value._content[0]
if (!value._deleted) {
obj[key] = value._content[0]
}
}
return obj
}

View File

@@ -15,7 +15,7 @@ function domToYXml (parent, doms, _document) {
if (d._yxml != null && d._yxml !== false) {
d._yxml._unbindFromDom()
}
if (parent._domFilter(d, []) !== null) {
if (parent._domFilter(d.nodeName, new Map()) !== null) {
let type
if (d.nodeType === d.TEXT_NODE) {
type = new YXmlText(d)
@@ -203,6 +203,52 @@ export default class YXmlFragment extends YArray {
}
this._y.on('beforeTransaction', beforeTransactionSelectionFixer)
this._y.on('afterTransaction', afterTransactionSelectionFixer)
const applyFilter = (type) => {
if (type._deleted) {
return
}
// check if type is a child of this
let isChild = false
let p = type
while (p !== this._y) {
if (p === this) {
isChild = true
break
}
p = p._parent
}
if (!isChild) {
return
}
// filter attributes
let attributes = new Map()
if (type.getAttributes !== undefined) {
let attrs = type.getAttributes()
for (let key in attrs) {
attributes.set(key, attrs[key])
}
}
let result = this._domFilter(type.nodeName, new Map(attributes))
if (result === null) {
type._delete(this._y)
} else {
attributes.forEach((value, key) => {
if (!result.has(key)) {
type.removeAttribute(key)
}
})
}
}
this._y.on('beforeObserverCalls', function (y, transaction) {
// apply dom filter to new and changed types
transaction.changedTypes.forEach(function (subs, type) {
if (subs.size > 1 || !subs.has(null)) {
// only apply changes on attributes
applyFilter(type)
}
})
transaction.newTypes.forEach(applyFilter)
})
// Apply Y.Xml events to dom
this.observeDeep(events => {
reflectChangesOnDom.call(this, events, _document)
@@ -240,10 +286,15 @@ export default class YXmlFragment extends YArray {
}
break
case 'attributes':
if (yxml.constructor === YXmlFragment) {
break
}
let name = mutation.attributeName
let val = dom.getAttribute(name)
// check if filter accepts attribute
if (this._domFilter(dom, [name]).length > 0 && yxml.constructor !== YXmlFragment) {
var val = dom.getAttribute(name)
let attributes = new Map()
attributes.set(name, val)
if (this._domFilter(dom.nodeName, attributes).size > 0 && yxml.constructor !== YXmlFragment) {
if (yxml.getAttribute(name) !== val) {
if (val == null) {
yxml.removeAttribute(name)

View File

@@ -54,6 +54,7 @@ export default class Y extends NamedEventHandler {
console.error(e)
}
if (initialCall) {
this.emit('beforeObserverCalls', this, this._transaction, remote)
const transaction = this._transaction
this._transaction = null
// emit change events on changed types
@@ -94,17 +95,10 @@ export default class Y extends NamedEventHandler {
define (name, TypeConstructor) {
let id = new RootID(name, TypeConstructor)
let type = this.os.get(id)
if (type === null) {
type = new TypeConstructor()
type._id = id
type._parent = this
type._integrate(this)
if (this.share[name] !== undefined) {
throw new Error('Type is already defined with a different constructor!')
}
}
if (this.share[name] === undefined) {
this.share[name] = type
} else if (this.share[name] !== type) {
throw new Error('Type is already defined with a different constructor')
}
return type
}