observeDeep receives array of events
This commit is contained in:
		
							parent
							
								
									c453593ee7
								
							
						
					
					
						commit
						e5f289506f
					
				@ -40,10 +40,16 @@ export default class Type extends Item {
 | 
				
			|||||||
    this._deepEventHandler = new EventHandler()
 | 
					    this._deepEventHandler = new EventHandler()
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  _callEventHandler (event) {
 | 
					  _callEventHandler (event) {
 | 
				
			||||||
 | 
					    const changedParentTypes = this._y._transaction.changedParentTypes
 | 
				
			||||||
    this._eventHandler.callEventListeners(event)
 | 
					    this._eventHandler.callEventListeners(event)
 | 
				
			||||||
    let type = this
 | 
					    let type = this
 | 
				
			||||||
    while (type !== this._y) {
 | 
					    while (type !== this._y) {
 | 
				
			||||||
      type._deepEventHandler.callEventListeners(event)
 | 
					      let events = changedParentTypes.get(type)
 | 
				
			||||||
 | 
					      if (events === undefined) {
 | 
				
			||||||
 | 
					        events = []
 | 
				
			||||||
 | 
					        changedParentTypes.set(type, events)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      events.push(event)
 | 
				
			||||||
      type = type._parent
 | 
					      type = type._parent
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,7 @@ export default class Transaction {
 | 
				
			|||||||
    this.changedTypes = new Map()
 | 
					    this.changedTypes = new Map()
 | 
				
			||||||
    this.deletedStructs = new Set()
 | 
					    this.deletedStructs = new Set()
 | 
				
			||||||
    this.beforeState = new Map()
 | 
					    this.beforeState = new Map()
 | 
				
			||||||
 | 
					    this.changedParentTypes = new Map()
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -98,6 +98,14 @@ export default class YMap extends Type {
 | 
				
			|||||||
      return v._content[v._content.length - 1]
 | 
					      return v._content[v._content.length - 1]
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  has (key) {
 | 
				
			||||||
 | 
					    let v = this._map.get(key)
 | 
				
			||||||
 | 
					    if (v === undefined || v._deleted) {
 | 
				
			||||||
 | 
					      return false
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      return true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  _logString () {
 | 
					  _logString () {
 | 
				
			||||||
    const left = this._left !== null ? this._left._lastId : null
 | 
					    const left = this._left !== null ? this._left._lastId : null
 | 
				
			||||||
    const origin = this._origin !== null ? this._origin._lastId : null
 | 
					    const origin = this._origin !== null ? this._origin._lastId : null
 | 
				
			||||||
 | 
				
			|||||||
@ -135,90 +135,92 @@ export function applyChangesFromDom (dom) {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function reflectChangesOnDom (event) {
 | 
					export function reflectChangesOnDom (events) {
 | 
				
			||||||
  const yxml = event.target
 | 
					  this._mutualExclude(() => {
 | 
				
			||||||
  const dom = yxml._dom
 | 
					    events.forEach(event => {
 | 
				
			||||||
  if (dom != null) {
 | 
					      const yxml = event.target
 | 
				
			||||||
    this._mutualExclude(() => {
 | 
					      const dom = yxml._dom
 | 
				
			||||||
      // TODO: do this once before applying stuff
 | 
					      if (dom != null) {
 | 
				
			||||||
      // let anchorViewPosition = getAnchorViewPosition(yxml._scrollElement)
 | 
					        // TODO: do this once before applying stuff
 | 
				
			||||||
      if (yxml.constructor === YXmlText) {
 | 
					        // let anchorViewPosition = getAnchorViewPosition(yxml._scrollElement)
 | 
				
			||||||
        yxml._dom.nodeValue = yxml.toString()
 | 
					        if (yxml.constructor === YXmlText) {
 | 
				
			||||||
      } else {
 | 
					          yxml._dom.nodeValue = yxml.toString()
 | 
				
			||||||
        // update attributes
 | 
					        } else {
 | 
				
			||||||
        event.attributesChanged.forEach(attributeName => {
 | 
					          // update attributes
 | 
				
			||||||
          const value = yxml.getAttribute(attributeName)
 | 
					          event.attributesChanged.forEach(attributeName => {
 | 
				
			||||||
          if (value === undefined) {
 | 
					            const value = yxml.getAttribute(attributeName)
 | 
				
			||||||
            dom.removeAttribute(attributeName)
 | 
					            if (value === undefined) {
 | 
				
			||||||
          } else {
 | 
					              dom.removeAttribute(attributeName)
 | 
				
			||||||
            dom.setAttribute(attributeName, value)
 | 
					            } else {
 | 
				
			||||||
          }
 | 
					              dom.setAttribute(attributeName, value)
 | 
				
			||||||
        })
 | 
					            }
 | 
				
			||||||
        if (event.childListChanged) {
 | 
					 | 
				
			||||||
          // create fragment of undeleted nodes
 | 
					 | 
				
			||||||
          const fragment = document.createDocumentFragment()
 | 
					 | 
				
			||||||
          yxml.forEach(function (t) {
 | 
					 | 
				
			||||||
            fragment.append(t.getDom())
 | 
					 | 
				
			||||||
          })
 | 
					          })
 | 
				
			||||||
          // remove remainding nodes
 | 
					          if (event.childListChanged) {
 | 
				
			||||||
          let lastChild = dom.lastChild
 | 
					            // create fragment of undeleted nodes
 | 
				
			||||||
          while (lastChild !== null) {
 | 
					            const fragment = document.createDocumentFragment()
 | 
				
			||||||
            dom.removeChild(lastChild)
 | 
					            yxml.forEach(function (t) {
 | 
				
			||||||
            lastChild = dom.lastChild
 | 
					              fragment.append(t.getDom())
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            // remove remainding nodes
 | 
				
			||||||
 | 
					            let lastChild = dom.lastChild
 | 
				
			||||||
 | 
					            while (lastChild !== null) {
 | 
				
			||||||
 | 
					              dom.removeChild(lastChild)
 | 
				
			||||||
 | 
					              lastChild = dom.lastChild
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // insert fragment of undeleted nodes
 | 
				
			||||||
 | 
					            dom.append(fragment)
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          // insert fragment of undeleted nodes
 | 
					 | 
				
			||||||
          dom.append(fragment)
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					        /* TODO: smartscrolling
 | 
				
			||||||
      /* TODO: smartscrolling
 | 
					        .. else if (event.type === 'childInserted' || event.type === 'insert') {
 | 
				
			||||||
      .. else if (event.type === 'childInserted' || event.type === 'insert') {
 | 
					          let nodes = event.values
 | 
				
			||||||
        let nodes = event.values
 | 
					          for (let i = nodes.length - 1; i >= 0; i--) {
 | 
				
			||||||
        for (let i = nodes.length - 1; i >= 0; i--) {
 | 
					            let node = nodes[i]
 | 
				
			||||||
          let node = nodes[i]
 | 
					            node.setDomFilter(yxml._domFilter)
 | 
				
			||||||
          node.setDomFilter(yxml._domFilter)
 | 
					            node.enableSmartScrolling(yxml._scrollElement)
 | 
				
			||||||
          node.enableSmartScrolling(yxml._scrollElement)
 | 
					            let dom = node.getDom()
 | 
				
			||||||
          let dom = node.getDom()
 | 
					            let fixPosition = null
 | 
				
			||||||
          let fixPosition = null
 | 
					            let nextDom = null
 | 
				
			||||||
          let nextDom = null
 | 
					            if (yxml._content.length > event.index + i + 1) {
 | 
				
			||||||
          if (yxml._content.length > event.index + i + 1) {
 | 
					              nextDom = yxml.get(event.index + i + 1).getDom()
 | 
				
			||||||
            nextDom = yxml.get(event.index + i + 1).getDom()
 | 
					            }
 | 
				
			||||||
          }
 | 
					            yxml._dom.insertBefore(dom, nextDom)
 | 
				
			||||||
          yxml._dom.insertBefore(dom, nextDom)
 | 
					            if (anchorViewPosition === null) {
 | 
				
			||||||
          if (anchorViewPosition === null) {
 | 
					              // nop
 | 
				
			||||||
            // nop
 | 
					            } else if (anchorViewPosition.anchor !== null) {
 | 
				
			||||||
          } else if (anchorViewPosition.anchor !== null) {
 | 
					              // no scrolling when current selection
 | 
				
			||||||
            // no scrolling when current selection
 | 
					              if (!dom.contains(anchorViewPosition.anchor) && !anchorViewPosition.anchor.contains(dom)) {
 | 
				
			||||||
            if (!dom.contains(anchorViewPosition.anchor) && !anchorViewPosition.anchor.contains(dom)) {
 | 
					                fixPosition = anchorViewPosition
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            } else if (getBoundingClientRect(dom).top <= 0) {
 | 
				
			||||||
 | 
					              // adjust scrolling if modified element is out of view,
 | 
				
			||||||
 | 
					              // there is no anchor element, and the browser did not adjust scrollTop (this is checked later)
 | 
				
			||||||
              fixPosition = anchorViewPosition
 | 
					              fixPosition = anchorViewPosition
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          } else if (getBoundingClientRect(dom).top <= 0) {
 | 
					            fixScrollPosition(yxml._scrollElement, fixPosition)
 | 
				
			||||||
            // adjust scrolling if modified element is out of view,
 | 
					 | 
				
			||||||
            // there is no anchor element, and the browser did not adjust scrollTop (this is checked later)
 | 
					 | 
				
			||||||
            fixPosition = anchorViewPosition
 | 
					 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          fixScrollPosition(yxml._scrollElement, fixPosition)
 | 
					        } else if (event.type === 'childRemoved' || event.type === 'delete') {
 | 
				
			||||||
        }
 | 
					          for (let i = event.values.length - 1; i >= 0; i--) {
 | 
				
			||||||
      } else if (event.type === 'childRemoved' || event.type === 'delete') {
 | 
					            let dom = event.values[i]._dom
 | 
				
			||||||
        for (let i = event.values.length - 1; i >= 0; i--) {
 | 
					            let fixPosition = null
 | 
				
			||||||
          let dom = event.values[i]._dom
 | 
					            if (anchorViewPosition === null) {
 | 
				
			||||||
          let fixPosition = null
 | 
					              // nop
 | 
				
			||||||
          if (anchorViewPosition === null) {
 | 
					            } else if (anchorViewPosition.anchor !== null) {
 | 
				
			||||||
            // nop
 | 
					              // no scrolling when current selection
 | 
				
			||||||
          } else if (anchorViewPosition.anchor !== null) {
 | 
					              if (!dom.contains(anchorViewPosition.anchor) && !anchorViewPosition.anchor.contains(dom)) {
 | 
				
			||||||
            // no scrolling when current selection
 | 
					                fixPosition = anchorViewPosition
 | 
				
			||||||
            if (!dom.contains(anchorViewPosition.anchor) && !anchorViewPosition.anchor.contains(dom)) {
 | 
					              }
 | 
				
			||||||
 | 
					            } else if (getBoundingClientRect(dom).top <= 0) {
 | 
				
			||||||
 | 
					              // adjust scrolling if modified element is out of view,
 | 
				
			||||||
 | 
					              // there is no anchor element, and the browser did not adjust scrollTop (this is checked later)
 | 
				
			||||||
              fixPosition = anchorViewPosition
 | 
					              fixPosition = anchorViewPosition
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          } else if (getBoundingClientRect(dom).top <= 0) {
 | 
					            dom.remove()
 | 
				
			||||||
            // adjust scrolling if modified element is out of view,
 | 
					            fixScrollPosition(yxml._scrollElement, fixPosition)
 | 
				
			||||||
            // there is no anchor element, and the browser did not adjust scrollTop (this is checked later)
 | 
					 | 
				
			||||||
            fixPosition = anchorViewPosition
 | 
					 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          dom.remove()
 | 
					 | 
				
			||||||
          fixScrollPosition(yxml._scrollElement, fixPosition)
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        */
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      */
 | 
					 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
  }
 | 
					  })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -2,26 +2,32 @@
 | 
				
			|||||||
export default class YEvent {
 | 
					export default class YEvent {
 | 
				
			||||||
  constructor (target) {
 | 
					  constructor (target) {
 | 
				
			||||||
    this.target = target
 | 
					    this.target = target
 | 
				
			||||||
 | 
					    this._path = null
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  get path () {
 | 
					  get path () {
 | 
				
			||||||
    const path = []
 | 
					    if (this._path !== null) {
 | 
				
			||||||
    let type = this.target
 | 
					      return this._path
 | 
				
			||||||
    const y = type._y
 | 
					    } else {
 | 
				
			||||||
    while (type._parent !== y) {
 | 
					      const path = []
 | 
				
			||||||
      let parent = type._parent
 | 
					      let type = this.target
 | 
				
			||||||
      if (type._parentSub !== null) {
 | 
					      const y = type._y
 | 
				
			||||||
        path.push(type._parentSub)
 | 
					      while (type._parent !== y) {
 | 
				
			||||||
      } else {
 | 
					        let parent = type._parent
 | 
				
			||||||
        // parent is array-ish
 | 
					        if (type._parentSub !== null) {
 | 
				
			||||||
        for (let [i, child] of parent) {
 | 
					          path.push(type._parentSub)
 | 
				
			||||||
          if (child === type) {
 | 
					        } else {
 | 
				
			||||||
            path.push(i)
 | 
					          // parent is array-ish
 | 
				
			||||||
            break
 | 
					          for (let [i, child] of parent) {
 | 
				
			||||||
 | 
					            if (child === type) {
 | 
				
			||||||
 | 
					              path.push(i)
 | 
				
			||||||
 | 
					              break
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        type = parent
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      type = parent
 | 
					      this._path = path
 | 
				
			||||||
 | 
					      return path
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return path
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										14
									
								
								src/Y.js
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								src/Y.js
									
									
									
									
									
								
							@ -55,7 +55,19 @@ export default class Y extends NamedEventHandler {
 | 
				
			|||||||
    if (initialCall) {
 | 
					    if (initialCall) {
 | 
				
			||||||
      // emit change events on changed types
 | 
					      // emit change events on changed types
 | 
				
			||||||
      this._transaction.changedTypes.forEach(function (subs, type) {
 | 
					      this._transaction.changedTypes.forEach(function (subs, type) {
 | 
				
			||||||
        type._callObserver(subs, remote)
 | 
					        if (!type._deleted) {
 | 
				
			||||||
 | 
					          type._callObserver(subs, remote)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      this._transaction.changedParentTypes.forEach(function (events, type) {
 | 
				
			||||||
 | 
					        if (!type._deleted) {
 | 
				
			||||||
 | 
					          events = events.filter(event =>
 | 
				
			||||||
 | 
					            !event.target._deleted
 | 
				
			||||||
 | 
					          )
 | 
				
			||||||
 | 
					          // we don't have to check for events.length
 | 
				
			||||||
 | 
					          // because there is no way events is empty..
 | 
				
			||||||
 | 
					          type._deepEventHandler.callEventListeners(events)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
      // when all changes & events are processed, emit afterTransaction event
 | 
					      // when all changes & events are processed, emit afterTransaction event
 | 
				
			||||||
      this.emit('afterTransaction', this, remote)
 | 
					      this.emit('afterTransaction', this, remote)
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user