Merge branch 'master' of github.com:y-js/yjs

This commit is contained in:
Kevin Jahns 2018-05-09 16:28:07 +02:00
commit 6ddeb788c7
9 changed files with 60 additions and 27 deletions

View File

@ -1,7 +1,7 @@
/* global Y */
window.onload = function () {
window.domBinding = new Y.DomBinding(window.yXmlType, document.body)
window.domBinding = new Y.DomBinding(window.yXmlType, document.body, { scrollingElement: document.scrollingElement })
}
let y = new Y('htmleditor', {

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "yjs",
"version": "13.0.0-56",
"version": "13.0.0-60",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@ -1,6 +1,6 @@
{
"name": "yjs",
"version": "13.0.0-56",
"version": "13.0.0-60",
"description": "A framework for real-time p2p shared editing on any data",
"main": "./y.node.js",
"browser": "./y.js",
@ -71,8 +71,5 @@
"rollup-watch": "^3.2.2",
"standard": "^10.0.2",
"tag-dist-files": "^0.1.6"
},
"dependencies": {
"debug": "^2.6.8"
}
}

View File

@ -33,6 +33,7 @@ export default class DomBinding extends Binding {
this.opts = opts
opts.document = opts.document || document
opts.hooks = opts.hooks || {}
this.scrollingElement = opts.scrollingElement || null
/**
* Maps each DOM element to the type that it is associated with.
* @type {Map}
@ -105,17 +106,6 @@ export default class DomBinding extends Binding {
createAssociation(this, target, type)
}
/**
* Enables the smart scrolling functionality for a Dom Binding.
* This is useful when YXml is bound to a shared editor. When activated,
* the viewport will be changed to accommodate remote changes.
*
* @param {Element} scrollElement The node that is
*/
enableSmartScrolling (scrollElement) {
// @TODO: implement smart scrolling
}
/**
* NOTE: currently does not apply filter to existing elements!
* @param {FilterFunction} filter The filter function to use from now on.

View File

@ -60,8 +60,8 @@ function applyChangesFromDom (binding, dom, yxml, _document) {
removeAssociation(binding, childNode, childType)
} else {
// child was moved to a different position.
childType._delete(y)
removeAssociation(binding, childNode, childType)
childType._delete(y)
}
prevExpectedType = insertNodeHelper(yxml, prevExpectedType, childNode, _document, binding)
} else {
@ -90,8 +90,19 @@ export default function domObserver (mutations, _document) {
mutations.forEach(mutation => {
const dom = mutation.target
const yxml = this.domToType.get(dom)
if (yxml === false || yxml === undefined || yxml.constructor === YXmlHook) {
// dom element is filtered
if (yxml === undefined) { // In case yxml is undefined, we double check if we forgot to bind the dom
let parent = dom
let yParent
do {
parent = parent.parentElement
yParent = this.domToType.get(parent)
} while (yParent === undefined && parent !== null)
if (yParent !== false && yParent !== undefined && yParent.constructor !== YXmlHook) {
diffChildren.add(parent)
}
return
} else if (yxml === false || yxml.constructor === YXmlHook) {
// dom element is filtered / a dom hook
return
}
switch (mutation.type) {
@ -125,9 +136,6 @@ export default function domObserver (mutations, _document) {
}
})
for (let dom of diffChildren) {
if (dom.yOnChildrenChanged !== undefined) {
dom.yOnChildrenChanged()
}
const yxml = this.domToType.get(dom)
applyChangesFromDom(this, dom, yxml, _document)
}

View File

@ -1,13 +1,49 @@
/* global getSelection */
import YXmlText from '../../Types/YXml/YXmlText.js'
import YXmlHook from '../../Types/YXml/YXmlHook.js'
import { removeDomChildrenUntilElementFound } from './util.js'
function findScrollReference (scrollingElement) {
if (scrollingElement !== null) {
let anchor = getSelection().anchorNode
if (anchor == null) {
let children = scrollingElement.children // only iterate through non-text nodes
for (let i = 0; i < children.length; i++) {
const elem = children[i]
const rect = elem.getBoundingClientRect()
if (rect.top >= 0) {
return { elem, top: rect.top }
}
}
} else {
if (anchor.nodeType === document.TEXT_NODE) {
anchor = anchor.parentElement
}
const top = anchor.getBoundingClientRect().top
return { elem: anchor, top: top }
}
}
return null
}
function fixScroll (scrollingElement, ref) {
if (ref !== null) {
const { elem, top } = ref
const currentTop = elem.getBoundingClientRect().top
const newScroll = scrollingElement.scrollTop + currentTop - top
if (newScroll >= 0) {
scrollingElement.scrollTop = newScroll
}
}
}
/**
* @private
*/
export default function typeObserver (events) {
this._mutualExclude(() => {
const scrollRef = findScrollReference(this.scrollingElement)
events.forEach(event => {
const yxml = event.target
const dom = this.typeToDom.get(yxml)
@ -58,5 +94,6 @@ export default function typeObserver (events) {
}
}
})
fixScroll(this.scrollingElement, scrollRef)
})
}

View File

@ -25,7 +25,7 @@ function _integrateRemoteStructHelper (y, struct) {
if (y.ss.getState(id.user) > id.clock) {
return
}
if (struct.constructor === GC || (struct._parent.constructor !== GC && struct._parent._deleted === false)) {
if (!y.gcEnabled || struct.constructor === GC || (struct._parent.constructor !== GC && struct._parent._deleted === false)) {
// Is either a GC or Item with an undeleted parent
// save to integrate
struct._integrate(y)

View File

@ -217,8 +217,8 @@ export default class Type extends Item {
* collect the children of this type.
*/
_delete (y, createDelete, gcChildren) {
if (gcChildren === undefined) {
gcChildren = y._hasUndoManager === false
if (gcChildren === undefined || !y.gcEnabled) {
gcChildren = y._hasUndoManager === false && y.gcEnabled
}
super._delete(y, createDelete, gcChildren)
y._transaction.changedTypes.delete(this)

View File

@ -28,8 +28,9 @@ export { default as DomBinding } from './Bindings/DomBinding/DomBinding.js'
* @param {AbstractPersistence} persistence Persistence adapter instance
*/
export default class Y extends NamedEventHandler {
constructor (room, opts, persistence) {
constructor (room, opts, persistence, conf = {}) {
super()
this.gcEnabled = conf.gc || false
/**
* The room name that this Yjs instance connects to.
* @type {String}