Compare commits

..

1 Commits

Author SHA1 Message Date
Kevin Jahns
4e36305245 v13.0.0-30 -- distribution files 2017-11-12 13:37:48 -08:00
12 changed files with 25012 additions and 94 deletions

2
package-lock.json generated
View File

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

View File

@@ -1,6 +1,6 @@
{ {
"name": "yjs", "name": "yjs",
"version": "13.0.0-31", "version": "13.0.0-30",
"description": "A framework for real-time p2p shared editing on any data", "description": "A framework for real-time p2p shared editing on any data",
"main": "./y.node.js", "main": "./y.node.js",
"browser": "./y.js", "browser": "./y.js",

View File

@@ -5,7 +5,7 @@ import YMap from '../YMap.js'
import YXmlFragment from './YXmlFragment.js' import YXmlFragment from './YXmlFragment.js'
export default class YXmlElement extends YXmlFragment { export default class YXmlElement extends YXmlFragment {
constructor (arg1, arg2, _document) { constructor (arg1, arg2) {
super() super()
this.nodeName = null this.nodeName = null
this._scrollElement = null this._scrollElement = null
@@ -13,7 +13,7 @@ export default class YXmlElement extends YXmlFragment {
this.nodeName = arg1.toUpperCase() this.nodeName = arg1.toUpperCase()
} else if (arg1 != null && arg1.nodeType != null && arg1.nodeType === arg1.ELEMENT_NODE) { } else if (arg1 != null && arg1.nodeType != null && arg1.nodeType === arg1.ELEMENT_NODE) {
this.nodeName = arg1.nodeName this.nodeName = arg1.nodeName
this._setDom(arg1, _document) this._setDom(arg1)
} else { } else {
this.nodeName = 'UNDEFINED' this.nodeName = 'UNDEFINED'
} }
@@ -26,12 +26,14 @@ export default class YXmlElement extends YXmlFragment {
struct.nodeName = this.nodeName struct.nodeName = this.nodeName
return struct return struct
} }
_setDom (dom, _document) { _setDom (dom) {
if (this._dom != null) { if (this._dom != null) {
throw new Error('Only call this method if you know what you are doing ;)') throw new Error('Only call this method if you know what you are doing ;)')
} else if (dom._yxml != null) { // TODO do i need to check this? - no.. but for dev purps.. } else if (dom._yxml != null) { // TODO do i need to check this? - no.. but for dev purps..
throw new Error('Already bound to an YXml type') throw new Error('Already bound to an YXml type')
} else { } else {
this._dom = dom
dom._yxml = this
// tag is already set in constructor // tag is already set in constructor
// set attributes // set attributes
let attrNames = [] let attrNames = []
@@ -44,8 +46,8 @@ export default class YXmlElement extends YXmlFragment {
let attrValue = dom.getAttribute(attrName) let attrValue = dom.getAttribute(attrName)
this.setAttribute(attrName, attrValue) this.setAttribute(attrName, attrValue)
} }
this.insertDomElements(0, Array.prototype.slice.call(dom.childNodes), _document) this.insertDomElements(0, Array.prototype.slice.call(dom.childNodes))
this._bindToDom(dom, _document) this._bindToDom(dom)
return dom return dom
} }
} }
@@ -113,6 +115,7 @@ export default class YXmlElement extends YXmlFragment {
let dom = this._dom let dom = this._dom
if (dom == null) { if (dom == null) {
dom = _document.createElement(this.nodeName) dom = _document.createElement(this.nodeName)
this._dom = dom
dom._yxml = this dom._yxml = this
let attrs = this.getAttributes() let attrs = this.getAttributes()
for (let key in attrs) { for (let key in attrs) {
@@ -121,7 +124,7 @@ export default class YXmlElement extends YXmlFragment {
this.forEach(yxml => { this.forEach(yxml => {
dom.appendChild(yxml.getDom(_document)) dom.appendChild(yxml.getDom(_document))
}) })
this._bindToDom(dom, _document) this._bindToDom(dom)
} }
return dom return dom
} }

View File

@@ -9,7 +9,7 @@ import YXmlEvent from './YXmlEvent.js'
import { logID } from '../../MessageHandler/messageToString.js' import { logID } from '../../MessageHandler/messageToString.js'
import diff from 'fast-diff' import diff from 'fast-diff'
function domToYXml (parent, doms, _document) { function domToYXml (parent, doms) {
const types = [] const types = []
doms.forEach(d => { doms.forEach(d => {
if (d._yxml != null && d._yxml !== false) { if (d._yxml != null && d._yxml !== false) {
@@ -20,7 +20,7 @@ function domToYXml (parent, doms, _document) {
if (d.nodeType === d.TEXT_NODE) { if (d.nodeType === d.TEXT_NODE) {
type = new YXmlText(d) type = new YXmlText(d)
} else if (d.nodeType === d.ELEMENT_NODE) { } else if (d.nodeType === d.ELEMENT_NODE) {
type = new YXmlFragment._YXmlElement(d, parent._domFilter, _document) type = new YXmlFragment._YXmlElement(d, parent._domFilter)
} else { } else {
throw new Error('Unsupported node!') throw new Error('Unsupported node!')
} }
@@ -98,9 +98,7 @@ export default class YXmlFragment extends YArray {
} catch (e) { } catch (e) {
console.error(e) console.error(e)
} }
if (this._domObserver !== null) { this._domObserver.takeRecords()
this._domObserver.takeRecords()
}
token = true token = true
} }
} }
@@ -164,116 +162,113 @@ export default class YXmlFragment extends YArray {
this._dom = null this._dom = null
} }
} }
insertDomElementsAfter (prev, doms, _document) { insertDomElementsAfter (prev, doms) {
const types = domToYXml(this, doms, _document) const types = domToYXml(this, doms)
this.insertAfter(prev, types) this.insertAfter(prev, types)
return types return types
} }
insertDomElements (pos, doms, _document) { insertDomElements (pos, doms) {
const types = domToYXml(this, doms, _document) const types = domToYXml(this, doms)
this.insert(pos, types) this.insert(pos, types)
return types return types
} }
getDom () { getDom () {
return this._dom return this._dom
} }
bindToDom (dom, _document) { bindToDom (dom) {
if (this._dom != null) { if (this._dom != null) {
this._unbindFromDom() this._unbindFromDom()
} }
if (dom._yxml != null) { if (dom._yxml != null) {
dom._yxml._unbindFromDom() dom._yxml._unbindFromDom()
} }
if (MutationObserver == null) {
throw new Error('Not able to bind to a DOM element, because MutationObserver is not available!')
}
dom.innerHTML = '' dom.innerHTML = ''
this._dom = dom
dom._yxml = this
this.forEach(t => { this.forEach(t => {
dom.insertBefore(t.getDom(_document), null) dom.insertBefore(t.getDom(), null)
}) })
this._bindToDom(dom, _document) this._bindToDom(dom)
} }
// binds to a dom element // binds to a dom element
// Only call if dom and YXml are isomorph // Only call if dom and YXml are isomorph
_bindToDom (dom, _document) { _bindToDom (dom) {
_document = _document || document if (this._parent === null || this._parent._dom != null || typeof MutationObserver === 'undefined') {
this._dom = dom // only bind if parent did not already bind
dom._yxml = this
// TODO: refine this..
if ((this.constructor !== YXmlFragment && this._parent !== this._y) || this._parent === null) {
// TODO: only top level YXmlFragment can bind. Also allow YXmlElements..
return return
} }
this._y.on('beforeTransaction', () => {
this._domObserverListener(this._domObserver.takeRecords())
})
this._y.on('beforeTransaction', beforeTransactionSelectionFixer) this._y.on('beforeTransaction', beforeTransactionSelectionFixer)
this._y.on('afterTransaction', afterTransactionSelectionFixer) this._y.on('afterTransaction', afterTransactionSelectionFixer)
// Apply Y.Xml events to dom // Apply Y.Xml events to dom
this.observeDeep(events => { this.observeDeep(reflectChangesOnDom.bind(this))
reflectChangesOnDom.call(this, events, _document)
})
// Apply Dom changes on Y.Xml // Apply Dom changes on Y.Xml
if (typeof MutationObserver !== 'undefined') { this._domObserverListener = mutations => {
this._y.on('beforeTransaction', () => { this._mutualExclude(() => {
this._domObserverListener(this._domObserver.takeRecords()) this._y.transact(() => {
}) let diffChildren = new Set()
this._domObserverListener = mutations => { mutations.forEach(mutation => {
this._mutualExclude(() => { const dom = mutation.target
this._y.transact(() => { const yxml = dom._yxml
let diffChildren = new Set() if (yxml == null) {
mutations.forEach(mutation => { // dom element is filtered
const dom = mutation.target return
const yxml = dom._yxml }
if (yxml == null) { switch (mutation.type) {
// dom element is filtered case 'characterData':
return var diffs = diff(yxml.toString(), dom.nodeValue)
} var pos = 0
switch (mutation.type) { for (var i = 0; i < diffs.length; i++) {
case 'characterData': var d = diffs[i]
var diffs = diff(yxml.toString(), dom.nodeValue) if (d[0] === 0) { // EQUAL
var pos = 0 pos += d[1].length
for (var i = 0; i < diffs.length; i++) { } else if (d[0] === -1) { // DELETE
var d = diffs[i] yxml.delete(pos, d[1].length)
if (d[0] === 0) { // EQUAL } else { // INSERT
pos += d[1].length yxml.insert(pos, d[1])
} else if (d[0] === -1) { // DELETE pos += d[1].length
yxml.delete(pos, d[1].length) }
} else { // INSERT }
yxml.insert(pos, d[1]) break
pos += d[1].length case 'attributes':
let name = mutation.attributeName
// check if filter accepts attribute
if (this._domFilter(dom, [name]).length > 0 && this.constructor !== YXmlFragment) {
var val = dom.getAttribute(name)
if (yxml.getAttribute(name) !== val) {
if (val == null) {
yxml.removeAttribute(name)
} else {
yxml.setAttribute(name, val)
} }
} }
break }
case 'attributes': break
let name = mutation.attributeName case 'childList':
// check if filter accepts attribute diffChildren.add(mutation.target)
if (this._domFilter(dom, [name]).length > 0 && this.constructor !== YXmlFragment) { break
var val = dom.getAttribute(name)
if (yxml.getAttribute(name) !== val) {
if (val == null) {
yxml.removeAttribute(name)
} else {
yxml.setAttribute(name, val)
}
}
}
break
case 'childList':
diffChildren.add(mutation.target)
break
}
})
for (let dom of diffChildren) {
if (dom._yxml != null && dom._yxml !== false) {
applyChangesFromDom(dom)
}
} }
}) })
for (let dom of diffChildren) {
if (dom._yxml != null && dom._yxml !== false) {
applyChangesFromDom(dom)
}
}
}) })
}
this._domObserver = new MutationObserver(this._domObserverListener)
this._domObserver.observe(dom, {
childList: true,
attributes: true,
characterData: true,
subtree: true
}) })
} }
this._domObserver = new MutationObserver(this._domObserverListener)
this._domObserver.observe(dom, {
childList: true,
attributes: true,
characterData: true,
subtree: true
})
return dom return dom
} }
_logString () { _logString () {

View File

@@ -135,7 +135,7 @@ export function applyChangesFromDom (dom) {
} }
} }
export function reflectChangesOnDom (events, _document) { export function reflectChangesOnDom (events) {
// Make sure that no filtered attributes are applied to the structure // Make sure that no filtered attributes are applied to the structure
// if they were, delete them // if they were, delete them
/* /*
@@ -183,9 +183,9 @@ export function reflectChangesOnDom (events, _document) {
}) })
if (event.childListChanged) { if (event.childListChanged) {
// create fragment of undeleted nodes // create fragment of undeleted nodes
const fragment = _document.createDocumentFragment() const fragment = document.createDocumentFragment()
yxml.forEach(function (t) { yxml.forEach(function (t) {
fragment.appendChild(t.getDom(_document)) fragment.append(t.getDom())
}) })
// remove remainding nodes // remove remainding nodes
let lastChild = dom.lastChild let lastChild = dom.lastChild
@@ -194,7 +194,7 @@ export function reflectChangesOnDom (events, _document) {
lastChild = dom.lastChild lastChild = dom.lastChild
} }
// insert fragment of undeleted nodes // insert fragment of undeleted nodes
dom.appendChild(fragment) dom.append(fragment)
} }
} }
/* TODO: smartscrolling /* TODO: smartscrolling

View File

@@ -153,7 +153,7 @@ export async function initArrays (t, opts) {
result['array' + i] = y.define('array', Y.Array) result['array' + i] = y.define('array', Y.Array)
result['map' + i] = y.define('map', Y.Map) result['map' + i] = y.define('map', Y.Map)
result['xml' + i] = y.define('xml', Y.XmlElement) result['xml' + i] = y.define('xml', Y.XmlElement)
y.get('xml').setDomFilter(function (d, attrs) { y.get('xml', Y.Xml).setDomFilter(function (d, attrs) {
if (d.nodeName === 'HIDDEN') { if (d.nodeName === 'HIDDEN') {
return null return null
} else { } else {

9
y.js Normal file

File diff suppressed because one or more lines are too long

1
y.js.map Normal file

File diff suppressed because one or more lines are too long

5574
y.node.js Normal file

File diff suppressed because it is too large Load Diff

1
y.node.js.map Normal file

File diff suppressed because one or more lines are too long

19334
y.test.js Normal file

File diff suppressed because one or more lines are too long

1
y.test.js.map Normal file

File diff suppressed because one or more lines are too long