implemented tree-walker
This commit is contained in:
@@ -212,6 +212,6 @@ export default class YArray extends Type {
|
||||
_logString () {
|
||||
const left = this._left !== null ? this._left._lastId : null
|
||||
const origin = this._origin !== null ? this._origin._lastId : null
|
||||
return `YArray(id:${logID(this._id)},start:${logID(this._start)},left:${logID(left)},origin:${logID(origin)},right:${logID(this._right)},parent:${logID(this._parent)},parentSub:${logID(this._parentSub)})`
|
||||
return `YArray(id:${logID(this._id)},start:${logID(this._start)},left:${logID(left)},origin:${logID(origin)},right:${logID(this._right)},parent:${logID(this._parent)},parentSub:${this._parentSub})`
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +109,6 @@ export default class YMap extends Type {
|
||||
_logString () {
|
||||
const left = this._left !== null ? this._left._lastId : null
|
||||
const origin = this._origin !== null ? this._origin._lastId : null
|
||||
return `YMap(id:${logID(this._id)},mapSize:${this._map.size},left:${logID(left)},origin:${logID(origin)},right:${logID(this._right)},parent:${logID(this._parent)},parentSub:${logID(this._parentSub)})`
|
||||
return `YMap(id:${logID(this._id)},mapSize:${this._map.size},left:${logID(left)},origin:${logID(origin)},right:${logID(this._right)},parent:${logID(this._parent)},parentSub:${this._parentSub})`
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,6 @@ export default class YText extends YArray {
|
||||
_logString () {
|
||||
const left = this._left !== null ? this._left._lastId : null
|
||||
const origin = this._origin !== null ? this._origin._lastId : null
|
||||
return `YText(id:${logID(this._id)},start:${logID(this._start)},left:${logID(left)},origin:${logID(origin)},right:${logID(this._right)},parent:${logID(this._parent)},parentSub:${logID(this._parentSub)})`
|
||||
return `YText(id:${logID(this._id)},start:${logID(this._start)},left:${logID(left)},origin:${logID(origin)},right:${logID(this._right)},parent:${logID(this._parent)},parentSub:${this._parentSub})`
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,54 @@ function domToYXml (parent, doms) {
|
||||
return types
|
||||
}
|
||||
|
||||
class YXmlTreeWalker {
|
||||
constructor (root, f) {
|
||||
this._filter = f || (() => true)
|
||||
this._root = root
|
||||
this._currentNode = root
|
||||
this._firstCall = true
|
||||
}
|
||||
[Symbol.iterator] () {
|
||||
return this
|
||||
}
|
||||
next () {
|
||||
let n = this._currentNode
|
||||
if (this._firstCall) {
|
||||
this._firstCall = false
|
||||
if (!n._deleted && this._filter(n)) {
|
||||
return { value: n, done: false }
|
||||
}
|
||||
}
|
||||
do {
|
||||
if (!n._deleted && n.constructor === YXmlFragment._YXmlElement && n._start !== null) {
|
||||
// walk down in the tree
|
||||
n = n._start
|
||||
} else {
|
||||
// walk right or up in the tree
|
||||
while (n !== this._root) {
|
||||
if (n._right !== null) {
|
||||
n = n._right
|
||||
break
|
||||
}
|
||||
n = n._parent
|
||||
}
|
||||
if (n === this._root) {
|
||||
n = null
|
||||
}
|
||||
}
|
||||
if (n === this._root) {
|
||||
break
|
||||
}
|
||||
} while (n !== null && (n._deleted || !this._filter(n)))
|
||||
this._currentNode = n
|
||||
if (n === null) {
|
||||
return { done: true }
|
||||
} else {
|
||||
return { value: n, done: false }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default class YXmlFragment extends YArray {
|
||||
constructor () {
|
||||
super()
|
||||
@@ -55,6 +103,33 @@ export default class YXmlFragment extends YArray {
|
||||
}
|
||||
}
|
||||
}
|
||||
createTreeWalker (filter) {
|
||||
return new YXmlTreeWalker(this, filter)
|
||||
}
|
||||
/**
|
||||
* Retrieve first element that matches *query*
|
||||
* Similar to DOM's querySelector, but only accepts a subset of its queries
|
||||
*
|
||||
* Query support:
|
||||
* - tagname
|
||||
* TODO:
|
||||
* - id
|
||||
* - attribute
|
||||
*/
|
||||
querySelector (query) {
|
||||
query = query.toUpperCase()
|
||||
const iterator = new YXmlTreeWalker(this, element => element.nodeName === query)
|
||||
const next = iterator.next()
|
||||
if (next.done) {
|
||||
return null
|
||||
} else {
|
||||
return next.value
|
||||
}
|
||||
}
|
||||
querySelectorAll (query) {
|
||||
query = query.toUpperCase()
|
||||
return Array.from(new YXmlTreeWalker(this, element => element.nodeName === query))
|
||||
}
|
||||
enableSmartScrolling (scrollElement) {
|
||||
this._scrollElement = scrollElement
|
||||
this.forEach(xml => {
|
||||
|
||||
Reference in New Issue
Block a user