Implement YXml element hooks (based on _yjsHook property)
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
import { defaultDomFilter } from './utils.js'
|
||||
|
||||
import YMap from '../YMap.js'
|
||||
import YXmlFragment from './YXmlFragment.js'
|
||||
import { YXmlFragment } from './y-xml.js'
|
||||
|
||||
export default class YXmlElement extends YXmlFragment {
|
||||
constructor (arg1, arg2, _document) {
|
||||
@@ -61,7 +61,7 @@ export default class YXmlElement extends YXmlFragment {
|
||||
if (this.nodeName === null) {
|
||||
throw new Error('nodeName must be defined!')
|
||||
}
|
||||
if (this._domFilter === defaultDomFilter && this._parent instanceof YXmlFragment) {
|
||||
if (this._domFilter === defaultDomFilter && this._parent._domFilter !== undefined) {
|
||||
this._domFilter = this._parent._domFilter
|
||||
}
|
||||
super._integrate(y)
|
||||
|
||||
@@ -4,8 +4,8 @@ import { defaultDomFilter, applyChangesFromDom, reflectChangesOnDom } from './ut
|
||||
import { beforeTransactionSelectionFixer, afterTransactionSelectionFixer } from './selection.js'
|
||||
|
||||
import YArray from '../YArray.js'
|
||||
import YXmlText from './YXmlText.js'
|
||||
import YXmlEvent from './YXmlEvent.js'
|
||||
import { YXmlText, YXmlHook } from './y-xml'
|
||||
import { logID } from '../../MessageHandler/messageToString.js'
|
||||
import diff from 'fast-diff'
|
||||
|
||||
@@ -17,14 +17,17 @@ function domToYXml (parent, doms, _document) {
|
||||
}
|
||||
if (parent._domFilter(d.nodeName, new Map()) !== null) {
|
||||
let type
|
||||
if (d.nodeType === d.TEXT_NODE) {
|
||||
const hookName = d._yjsHook
|
||||
if (hookName !== undefined) {
|
||||
type = new YXmlHook(hookName, d)
|
||||
} else if (d.nodeType === d.TEXT_NODE) {
|
||||
type = new YXmlText(d)
|
||||
} else if (d.nodeType === d.ELEMENT_NODE) {
|
||||
type = new YXmlFragment._YXmlElement(d, parent._domFilter, _document)
|
||||
} else {
|
||||
throw new Error('Unsupported node!')
|
||||
}
|
||||
type.enableSmartScrolling(parent._scrollElement)
|
||||
// type.enableSmartScrolling(parent._scrollElement)
|
||||
types.push(type)
|
||||
} else {
|
||||
d._yxml = false
|
||||
|
||||
49
src/Type/y-xml/YXmlHook.js
Normal file
49
src/Type/y-xml/YXmlHook.js
Normal file
@@ -0,0 +1,49 @@
|
||||
import YMap from '../YMap.js'
|
||||
import { getHook, addHook } from './hooks.js'
|
||||
|
||||
export default class YXmlHook extends YMap {
|
||||
constructor (hookName, dom) {
|
||||
super()
|
||||
this._dom = null
|
||||
this.hookName = null
|
||||
if (hookName !== undefined) {
|
||||
this.hookName = hookName
|
||||
this._dom = dom
|
||||
dom._yjsHook = hookName
|
||||
dom._yxml = this
|
||||
getHook(hookName).fillType(dom, this)
|
||||
}
|
||||
}
|
||||
getDom (_document) {
|
||||
_document = _document || document
|
||||
if (this._dom === null) {
|
||||
const dom = getHook(this.hookName).createDom(this)
|
||||
this._dom = dom
|
||||
dom._yxml = this
|
||||
dom._yjsHook = this.hookName
|
||||
}
|
||||
return this._dom
|
||||
}
|
||||
_fromBinary (y, decoder) {
|
||||
const missing = super._fromBinary(y, decoder)
|
||||
this.hookName = decoder.readVarString()
|
||||
return missing
|
||||
}
|
||||
_toBinary (encoder) {
|
||||
super._toBinary(encoder)
|
||||
encoder.writeVarString(this.hookName)
|
||||
}
|
||||
_integrate (y) {
|
||||
if (this.hookName === null) {
|
||||
throw new Error('hookName must be defined!')
|
||||
}
|
||||
super._integrate(y)
|
||||
}
|
||||
setDomFilter () {
|
||||
// TODO: implement new modfilter method!
|
||||
}
|
||||
enableSmartScrolling () {
|
||||
// TODO: implement new smartscrolling method!
|
||||
}
|
||||
}
|
||||
YXmlHook.addHook = addHook
|
||||
14
src/Type/y-xml/hooks.js
Normal file
14
src/Type/y-xml/hooks.js
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
const xmlHooks = {}
|
||||
|
||||
export function addHook (name, hook) {
|
||||
xmlHooks[name] = hook
|
||||
}
|
||||
|
||||
export function getHook (name) {
|
||||
const hook = xmlHooks[name]
|
||||
if (hook === undefined) {
|
||||
throw new Error(`The hook "${name}" is not specified! You must not access this hook!`)
|
||||
}
|
||||
return hook
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import YXmlText from './YXmlText.js'
|
||||
import { YXmlText, YXmlHook } from './y-xml.js'
|
||||
|
||||
export function defaultDomFilter (node, attributes) {
|
||||
return attributes
|
||||
@@ -84,6 +84,9 @@ function _insertNodeHelper (yxml, prevExpectedNode, child) {
|
||||
*/
|
||||
export function applyChangesFromDom (dom) {
|
||||
const yxml = dom._yxml
|
||||
if (yxml.constructor === YXmlHook) {
|
||||
return
|
||||
}
|
||||
const y = yxml._y
|
||||
let knownChildren =
|
||||
new Set(
|
||||
@@ -181,7 +184,15 @@ export function reflectChangesOnDom (events, _document) {
|
||||
dom.setAttribute(attributeName, value)
|
||||
}
|
||||
})
|
||||
if (event.childListChanged) {
|
||||
/**
|
||||
* TODO: instead of chard-checking the types, it would be best to
|
||||
* specify the type's features. E.g.
|
||||
* - _yxmlHasAttributes
|
||||
* - _yxmlHasChildren
|
||||
* Furthermore, the features shouldn't be encoded in the types,
|
||||
* only in the attributes (above)
|
||||
*/
|
||||
if (event.childListChanged && yxml.constructor !== YXmlHook) {
|
||||
// create fragment of undeleted nodes
|
||||
const fragment = _document.createDocumentFragment()
|
||||
yxml.forEach(function (t) {
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
|
||||
import YXmlFragment from './YXmlFragment.js'
|
||||
import YXmlElement from './YXmlElement.js'
|
||||
import YXmlHook from './YXmlHook.js'
|
||||
|
||||
export { default as YXmlFragment } from './YXmlFragment.js'
|
||||
export { default as YXmlElement } from './YXmlElement.js'
|
||||
export { default as YXmlText } from './YXmlText.js'
|
||||
export { default as YXmlHook } from './YXmlHook.js'
|
||||
|
||||
YXmlFragment._YXmlElement = YXmlElement
|
||||
YXmlFragment._YXmlHook = YXmlHook
|
||||
|
||||
Reference in New Issue
Block a user