Compare commits

..

1 Commits

Author SHA1 Message Date
Kevin Jahns
10d0c7b951 v13.0.0-46 -- distribution files 2018-01-10 00:20:34 +01:00
49 changed files with 6194 additions and 6320 deletions

View File

@@ -24,8 +24,7 @@
<body> <body>
<div id="aceContainer"></div> <div id="aceContainer"></div>
<script src="../../y.js"></script> <script src="../bower_components/yjs/y.js"></script>
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
<script src="../bower_components/ace-builds/src/ace.js"></script> <script src="../bower_components/ace-builds/src/ace.js"></script>
<script src="./index.js"></script> <script src="./index.js"></script>

View File

@@ -1,17 +1,24 @@
/* global Y, ace */ /* global Y, ace */
let y = new Y('ace-example', { Y({
db: {
name: 'memory'
},
connector: { connector: {
name: 'websockets-client', name: 'websockets-client',
url: 'http://127.0.0.1:1234' room: 'ace-example'
},
sourceDir: '/bower_components',
share: {
ace: 'Text' // y.share.textarea is of type Y.Text
} }
}).then(function (y) {
window.yAce = y
// bind the textarea to a shared text element
var editor = ace.edit('aceContainer')
editor.setTheme('ace/theme/chrome')
editor.getSession().setMode('ace/mode/javascript')
y.share.ace.bindAce(editor)
}) })
window.yAce = y
// bind the textarea to a shared text element
var editor = ace.edit('aceContainer')
editor.setTheme('ace/theme/chrome')
editor.getSession().setMode('ace/mode/javascript')
y.define('ace', Y.Text).bindAce(editor)

View File

@@ -13,7 +13,7 @@
<input type="submit" value="Send"> <input type="submit" value="Send">
</form> </form>
<script src="../../y.js"></script> <script src="../../y.js"></script>
<script src='../../../y-websockets-client/y-websockets-client.js'></script> <script src="../../../y-websockets-client/dist/y-websockets-client.js"></script>
<script src="./index.js"></script> <script src="./index.js"></script>
</body> </body>
</html> </html>

View File

@@ -1,9 +1,10 @@
/* global Y */ /* global Y */
let y = new Y('chat-example', { // initialize a shared object. This function call returns a promise!
var y = new Y({
connector: { connector: {
name: 'websockets-client', name: 'websockets-client',
url: 'http://127.0.0.1:1234' room: 'chat-example'
} }
}) })
@@ -22,7 +23,6 @@ function appendMessage (message, position) {
p.appendChild(document.createTextNode(message.message)) p.appendChild(document.createTextNode(message.message))
chatcontainer.insertBefore(p, chatcontainer.children[position] || null) chatcontainer.insertBefore(p, chatcontainer.children[position] || null)
} }
// This function makes sure that only 7 messages exist in the chat history. // This function makes sure that only 7 messages exist in the chat history.
// The rest is deleted // The rest is deleted
function cleanupChat () { function cleanupChat () {
@@ -30,17 +30,23 @@ function cleanupChat () {
chatprotocol.delete(0, chatprotocol.length - 7) chatprotocol.delete(0, chatprotocol.length - 7)
} }
} }
cleanupChat()
// Insert the initial content // Insert the initial content
chatprotocol.toArray().forEach(appendMessage) chatprotocol.toArray().forEach(appendMessage)
cleanupChat()
// whenever content changes, make sure to reflect the changes in the DOM // whenever content changes, make sure to reflect the changes in the DOM
chatprotocol.observe(function (event) { chatprotocol.observe(function (event) {
if (event.type === 'insert') {
for (let i = 0; i < event.length; i++) {
appendMessage(event.values[i], event.index + i)
}
} else if (event.type === 'delete') {
for (let i = 0; i < event.length; i++) {
chatcontainer.children[event.index].remove()
}
}
// concurrent insertions may result in a history > 7, so cleanup here // concurrent insertions may result in a history > 7, so cleanup here
cleanupChat() cleanupChat()
chatcontainer.innerHTML = ''
chatprotocol.toArray().forEach(appendMessage)
}) })
document.querySelector('#chatform').onsubmit = function (event) { document.querySelector('#chatform').onsubmit = function (event) {
// the form is submitted // the form is submitted

View File

@@ -5,8 +5,7 @@
<body> <body>
<div id="codeMirrorContainer"></div> <div id="codeMirrorContainer"></div>
<script src="../../y.js"></script> <script src="../bower_components/yjs/y.js"></script>
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
<script src="../bower_components/codemirror/lib/codemirror.js"></script> <script src="../bower_components/codemirror/lib/codemirror.js"></script>
<script src="../bower_components/codemirror/mode/javascript/javascript.js"></script> <script src="../bower_components/codemirror/mode/javascript/javascript.js"></script>
<link rel="stylesheet" href="../bower_components/codemirror/lib/codemirror.css"> <link rel="stylesheet" href="../bower_components/codemirror/lib/codemirror.css">

View File

@@ -1,16 +1,24 @@
/* global Y, CodeMirror */ /* global Y, CodeMirror */
let y = new Y('codemirror-example', { // initialize a shared object. This function call returns a promise!
Y({
db: {
name: 'memory'
},
connector: { connector: {
name: 'websockets-client', name: 'websockets-client',
url: 'http://127.0.0.1:1234' room: 'codemirror-example'
},
sourceDir: '/bower_components',
share: {
codemirror: 'Text' // y.share.codemirror is of type Y.Text
} }
}) }).then(function (y) {
window.yCodeMirror = y
window.yCodeMirror = y var editor = CodeMirror(document.querySelector('#codeMirrorContainer'), {
mode: 'javascript',
var editor = CodeMirror(document.querySelector('#codeMirrorContainer'), { lineNumbers: true
mode: 'javascript', })
lineNumbers: true y.share.codemirror.bindCodeMirror(editor)
}) })
y.define('codemirror', Y.Text).bindCodeMirror(editor)

View File

@@ -12,8 +12,7 @@
</style> </style>
<button type="button" id="clearDrawingCanvas">Clear Drawing</button> <button type="button" id="clearDrawingCanvas">Clear Drawing</button>
<svg id="drawingCanvas" viewbox="0 0 100 100" width="100%"></svg> <svg id="drawingCanvas" viewbox="0 0 100 100" width="100%"></svg>
<script src="../../y.js"></script> <script src="../yjs-dist.js"></script>
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
<script src="../bower_components/d3/d3.min.js"></script> <script src="../bower_components/d3/d3.min.js"></script>
<script src="./index.js"></script> <script src="./index.js"></script>
</body> </body>

View File

@@ -1,9 +1,11 @@
/* globals Y, d3 */ /* globals Y, d3 */
let y = new Y('drawing-example', { let y = new Y({
connector: { connector: {
name: 'websockets-client', name: 'websockets-client',
url: 'http://127.0.0.1:1234' url: 'http://127.0.0.1:1234',
room: 'drawing-example'
// maxBufferLength: 100
} }
}) })

View File

@@ -1,8 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
</head> </head>
<script src="../../y.js"></script> <script src="../yjs-dist.js"></script>
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
<script src="../bower_components/d3/d3.min.js"></script> <script src="../bower_components/d3/d3.min.js"></script>
<script src="./index.js"></script> <script src="./index.js"></script>
<style> <style>

View File

@@ -107,13 +107,15 @@ Y.XmlHook.addHook('magic-drawing', {
} }
}) })
let y = new Y('html-editor-drawing-hook-example', { // initialize a shared object. This function call returns a promise!
let y = new Y({
connector: { connector: {
name: 'websockets-client', name: 'websockets-client',
url: 'http://127.0.0.1:1234' url: 'http://127.0.0.1:1234',
room: 'html-editor-example6'
// maxBufferLength: 100
} }
}) })
window.yXml = y window.yXml = y
window.yXmlType = y.define('xml', Y.XmlFragment) window.yXmlType = y.define('xml', Y.XmlFragment)
window.undoManager = new Y.utils.UndoManager(window.yXmlType, { window.undoManager = new Y.utils.UndoManager(window.yXmlType, {

View File

@@ -1,8 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
</head> </head>
<script src="../../y.js"></script> <script src="../yjs-dist.js"></script>
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
<script src="./index.js"></script> <script src="./index.js"></script>
</head> </head>
<body contenteditable="true"> <body contenteditable="true">

View File

@@ -4,14 +4,18 @@ window.onload = function () {
window.yXmlType.bindToDom(document.body) window.yXmlType.bindToDom(document.body)
} }
let y = new Y('htmleditor', { let persistence = null // new Y.IndexedDBPersistence()
// initialize a shared object. This function call returns a promise!
let y = new Y({
connector: { connector: {
name: 'websockets-client', name: 'websockets-client',
url: 'http://127.0.0.1:1234' url: 'http://127.0.0.1:1234',
room: 'x'
// maxBufferLength: 100
} }
}) }, persistence)
window.yXml = y
window.y = y
window.yXmlType = y.define('xml', Y.XmlFragment) window.yXmlType = y.define('xml', Y.XmlFragment)
window.undoManager = new Y.utils.UndoManager(window.yXmlType, { window.undoManager = new Y.utils.UndoManager(window.yXmlType, {
captureTimeout: 500 captureTimeout: 500

View File

@@ -16,9 +16,6 @@
width: 100%; width: 100%;
} }
</style> </style>
<script src="../../y.js"></script> <script type="module" src="./index.js"></script>
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
<script src='../../../y-indexeddb/y-indexeddb.js'></script>
<script src="./index.js"></script>
</body> </body>
</html> </html>

View File

@@ -1,19 +1,24 @@
/* global Y, CodeMirror */ /* global Y, CodeMirror */
const persistence = new Y.IndexedDB() // initialize a shared object. This function call returns a promise!
const connector = { Y({
db: {
name: 'memory'
},
connector: { connector: {
name: 'websockets-client', name: 'websockets-client',
room: 'codemirror-example' room: 'codemirror-example'
},
sourceDir: '/bower_components',
share: {
codemirror: 'Text' // y.share.codemirror is of type Y.Text
} }
} }).then(function (y) {
window.yCodeMirror = y
const y = new Y('codemirror-example', connector, persistence) var editor = CodeMirror(document.querySelector('#codeMirrorContainer'), {
window.yCodeMirror = y mode: 'javascript',
lineNumbers: true
var editor = CodeMirror(document.querySelector('#codeMirrorContainer'), { })
mode: 'javascript', y.share.codemirror.bindCodeMirror(editor)
lineNumbers: true
}) })
y.define('codemirror', Y.Text).bindCodeMirror(editor)

View File

@@ -10,7 +10,7 @@
.one { .one {
grid-column: 1 ; grid-column: 1 ;
} }
.two { .two {
grid-column: 2; grid-column: 2;
} }
.three { .three {
@@ -49,7 +49,10 @@
</div> </div>
</div> </div>
<script src="../../y.js"></script> <script src="../../y.js"></script>
<script src='../../../y-websockets-client/y-websockets-client.js'></script> <script src="../../../y-array/y-array.js"></script>
<script src="../../../y-text/dist/y-text.js"></script>
<script src="../../../y-memory/y-memory.js"></script>
<script src="../../../y-websockets-client/y-websockets-client.js"></script>
<script src="./index.js"></script> <script src="./index.js"></script>
</body> </body>
</html> </html>

View File

@@ -1,38 +1,64 @@
/* global Y */ /* global Y */
function bindYjsInstance (y, suffix) { Y({
y.define('textarea', Y.Text).bind(document.getElementById('textarea' + suffix)) db: {
name: 'memory'
},
connector: {
name: 'websockets-client',
room: 'Textarea-example',
url: 'https://yjs-v13.herokuapp.com/'
},
share: {
textarea: 'Text'
}
}).then(function (y) {
window.y1 = y
y.share.textarea.bind(document.getElementById('textarea1'))
})
Y({
db: {
name: 'memory'
},
connector: {
name: 'websockets-client',
room: 'Textarea-example',
url: 'https://yjs-v13-second.herokuapp.com/'
},
share: {
textarea: 'Text'
}
}).then(function (y) {
window.y2 = y
y.share.textarea.bind(document.getElementById('textarea2'))
y.connector.socket.on('connection', function () { y.connector.socket.on('connection', function () {
document.getElementById('container' + suffix).removeAttribute('disconnected') document.getElementById('container2').removeAttribute('disconnected')
}) })
y.connector.socket.on('disconnect', function () { y.connector.socket.on('disconnect', function () {
document.getElementById('container' + suffix).setAttribute('disconnected', true) document.getElementById('container2').setAttribute('disconnected', true)
}) })
} })
let y1 = new Y('infinite-example', { Y({
db: {
name: 'memory'
},
connector: { connector: {
name: 'websockets-client', name: 'websockets-client',
url: 'http://127.0.0.1:1234' room: 'Textarea-example',
url: 'https://yjs-v13-third.herokuapp.com/'
},
share: {
textarea: 'Text'
} }
}).then(function (y) {
window.y3 = y
y.share.textarea.bind(document.getElementById('textarea3'))
y.connector.socket.on('connection', function () {
document.getElementById('container3').removeAttribute('disconnected')
})
y.connector.socket.on('disconnect', function () {
document.getElementById('container3').setAttribute('disconnected', true)
})
}) })
window.y1 = y1
bindYjsInstance(y1, '1')
let y2 = new Y('infinite-example', {
connector: {
name: 'websockets-client',
url: 'http://127.0.0.1:1234'
}
})
window.y2 = y2
bindYjsInstance(y2, '2')
let y3 = new Y('infinite-example', {
connector: {
name: 'websockets-client',
url: 'http://127.0.0.1:1234'
}
})
window.y3 = y3
bindYjsInstance(y1, '3')

View File

@@ -17,7 +17,9 @@
</g> </g>
</svg> </svg>
<script src="../../y.js"></script> <script src="../../y.js"></script>
<script src='../../../y-websockets-client/y-websockets-client.js'></script> <script src="../../../y-map/dist/y-map.js"></script>
<script src="../../../y-memory/y-memory.js"></script>
<script src="../../../y-websockets-client/y-websockets-client.js"></script>
<script src="../bower_components/d3/d3.js"></script> <script src="../bower_components/d3/d3.js"></script>
<script src="./index.js"></script> <script src="./index.js"></script>
</body> </body>

View File

@@ -1,67 +1,74 @@
/* @flow */
/* global Y, d3 */ /* global Y, d3 */
let y = new Y('jigsaw-example', { // initialize a shared object. This function call returns a promise!
Y({
db: {
name: 'memory'
},
connector: { connector: {
name: 'websockets-client', name: 'websockets-client',
url: 'http://127.0.0.1:1234' room: 'Puzzle-example',
url: 'http://localhost:1234'
},
share: {
piece1: 'Map',
piece2: 'Map',
piece3: 'Map',
piece4: 'Map'
} }
}) }).then(function (y) {
window.yJigsaw = y
var origin // mouse start position - translation of piece
var drag = d3.behavior.drag()
.on('dragstart', function (params) {
// get the translation of the element
var translation = d3
.select(this)
.attr('transform')
.slice(10, -1)
.split(',')
.map(Number)
// mouse coordinates
var mouse = d3.mouse(this.parentNode)
origin = {
x: mouse[0] - translation[0],
y: mouse[1] - translation[1]
}
})
.on('drag', function () {
var mouse = d3.mouse(this.parentNode)
var x = mouse[0] - origin.x // =^= mouse - mouse at dragstart + translation at dragstart
var y = mouse[1] - origin.y
d3.select(this).attr('transform', 'translate(' + x + ',' + y + ')')
})
.on('dragend', function (piece, i) {
// save the current translation of the puzzle piece
var mouse = d3.mouse(this.parentNode)
var x = mouse[0] - origin.x
var y = mouse[1] - origin.y
piece.set('translation', {x: x, y: y})
})
let jigsaw = y.define('jigsaw', Y.Map) var data = [y.share.piece1, y.share.piece2, y.share.piece3, y.share.piece4]
window.yJigsaw = y var pieces = d3.select(document.querySelector('#puzzle-example')).selectAll('path').data(data)
var origin // mouse start position - translation of piece pieces
var drag = d3.behavior.drag() .classed('draggable', true)
.on('dragstart', function (params) { .attr('transform', function (piece) {
// get the translation of the element var translation = piece.get('translation') || {x: 0, y: 0}
var translation = d3 return 'translate(' + translation.x + ',' + translation.y + ')'
.select(this) }).call(drag)
.attr('transform')
.slice(10, -1)
.split(',')
.map(Number)
// mouse coordinates
var mouse = d3.mouse(this.parentNode)
origin = {
x: mouse[0] - translation[0],
y: mouse[1] - translation[1]
}
})
.on('drag', function () {
var mouse = d3.mouse(this.parentNode)
var x = mouse[0] - origin.x // =^= mouse - mouse at dragstart + translation at dragstart
var y = mouse[1] - origin.y
d3.select(this).attr('transform', 'translate(' + x + ',' + y + ')')
})
.on('dragend', function (piece, i) {
// save the current translation of the puzzle piece
var mouse = d3.mouse(this.parentNode)
var x = mouse[0] - origin.x
var y = mouse[1] - origin.y
jigsaw.set(piece, {x: x, y: y})
})
var data = ['piece1', 'piece2', 'piece3', 'piece4'] data.forEach(function (piece) {
var pieces = d3.select(document.querySelector('#puzzle-example')).selectAll('path').data(data) piece.observe(function () {
// whenever a property of a piece changes, update the translation of the pieces
pieces pieces
.classed('draggable', true) .transition()
.attr('transform', function (piece) { .attr('transform', function (piece) {
var translation = piece.get('translation') || {x: 0, y: 0} var translation = piece.get('translation') || {x: 0, y: 0}
return 'translate(' + translation.x + ',' + translation.y + ')' return 'translate(' + translation.x + ',' + translation.y + ')'
}).call(drag) })
})
data.forEach(function (piece) {
jigsaw.observe(function () {
// whenever a property of a piece changes, update the translation of the pieces
pieces
.transition()
.attr('transform', function (piece) {
var translation = piece.get(piece)
if (translation == null || typeof translation.x !== 'number' || typeof translation.y !== 'number') {
translation = { x: 0, y: 0 }
}
return 'translate(' + translation.x + ',' + translation.y + ')'
})
}) })
}) })

View File

@@ -13,8 +13,8 @@
width: 100%; width: 100%;
} }
</style> </style>
<script src="../../y.js"></script> <script src="../bower_components/yjs/y.js"></script>
<script src='../../../y-websockets-client/y-websockets-client.js'></script> <script src="../bower_components/y-websockets-client/y-websockets-client.js"></script>
<script src="../node_modules/monaco-editor/min/vs/loader.js"></script> <script src="../node_modules/monaco-editor/min/vs/loader.js"></script>
<script src="./index.js"></script> <script src="./index.js"></script>
</body> </body>

View File

@@ -2,21 +2,29 @@
require.config({ paths: { 'vs': '../node_modules/monaco-editor/min/vs' } }) require.config({ paths: { 'vs': '../node_modules/monaco-editor/min/vs' } })
let y = new Y('monaco-example', {
connector: {
name: 'websockets-client',
url: 'http://127.0.0.1:1234'
}
})
require(['vs/editor/editor.main'], function () { require(['vs/editor/editor.main'], function () {
window.yMonaco = y // Initialize a shared object. This function call returns a promise!
Y({
db: {
name: 'memory'
},
connector: {
name: 'websockets-client',
room: 'monaco-example'
},
sourceDir: '/bower_components',
share: {
monaco: 'Text' // y.share.monaco is of type Y.Text
}
}).then(function (y) {
window.yMonaco = y
// Create Monaco editor // Create Monaco editor
var editor = monaco.editor.create(document.getElementById('monacoContainer'), { var editor = monaco.editor.create(document.getElementById('monacoContainer'), {
language: 'javascript' language: 'javascript'
})
// Bind to y.share.monaco
y.share.monaco.bindMonaco(editor)
}) })
// Bind to y.share.monaco
y.define('monaco', Y.Text).bindMonaco(editor)
}) })

View File

@@ -26,7 +26,10 @@
<script src="../bower_components/quill/dist/quill.js"></script> <script src="../bower_components/quill/dist/quill.js"></script>
--> -->
<script src="../../y.js"></script> <script src="../../y.js"></script>
<script src='../../../y-websockets-client/y-websockets-client.js'></script> <script src="../../../y-array/y-array.js"></script>
<script src="../../../y-richtext/dist/y-richtext.js"></script>
<script src="../../../y-memory/y-memory.js"></script>
<script src="../../../y-websockets-client/y-websockets-client.js"></script>
<script src="./index.js"></script> <script src="./index.js"></script>
</body> </body>
</html> </html>

View File

@@ -1,9 +1,11 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<body> <body>
<textarea style="width:80%;" rows=40 autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea> <textarea style="width:80%;" rows=40 id="textfield" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>
<script src="../../y.js"></script> <script src="../../y.js"></script>
<script src='../../../y-websockets-client/y-websockets-client.js'></script> <script src="../../../y-array/y-array.js"></script>
<script src="../../../y-text/y-text.js"></script>
<script src="../../../y-websockets-client/y-websockets-client.js"></script>
<script src="./index.js"></script> <script src="./index.js"></script>
</body> </body>
</html> </html>

View File

@@ -1,15 +1,23 @@
/* global Y */ /* global Y */
let y = new Y('textarea-example', { // initialize a shared object. This function call returns a promise!
Y({
db: {
name: 'memory'
},
connector: { connector: {
name: 'websockets-client', name: 'websockets-client',
url: 'http://127.0.0.1:1234' room: 'Textarea-example2',
} // url: '//localhost:1234',
url: 'https://yjs-v13.herokuapp.com/'
},
share: {
textarea: 'Text'
},
timeout: 5000 // reject if no connection was established within 5 seconds
}).then(function (y) {
window.yTextarea = y
// bind the textarea to a shared text element
y.share.textarea.bind(document.getElementById('textfield'))
}) })
window.yTextarea = y
// bind the textarea to a shared text element
let type = y.define('textarea', Y.Text)
let textarea = document.querySelector('textarea')
window.binding = new Y.TextareaBinding(type, textarea)

View File

@@ -3,8 +3,7 @@
</head> </head>
<!-- jquery is not required for y-xml. It is just here for convenience, and to test batch operations. --> <!-- jquery is not required for y-xml. It is just here for convenience, and to test batch operations. -->
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="../../y.js"></script> <script src="../yjs-dist.js"></script>
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
<script src="./index.js"></script> <script src="./index.js"></script>
</head> </head>
<body> <body>

View File

@@ -1,13 +1,23 @@
/* global Y */ /* global Y */
let y = new Y('xml-example', { // initialize a shared object. This function call returns a promise!
Y({
db: {
name: 'memory'
},
connector: { connector: {
name: 'websockets-client', name: 'websockets-client',
url: 'http://127.0.0.1:1234' // url: 'http://127.0.0.1:1234',
url: 'http://192.168.178.81:1234',
room: 'Xml-example'
},
sourceDir: '/bower_components',
share: {
xml: 'Xml("p")' // y.share.xml is of type Y.Xml with tagname "p"
} }
}).then(function (y) {
window.yXml = y
// bind xml type to a dom, and put it in body
window.sharedDom = y.share.xml.getDom()
document.body.appendChild(window.sharedDom)
}) })
window.yXml = y
// bind xml type to a dom, and put it in body
window.sharedDom = y.define('xml', Y.XmlElement).getDom()
document.body.appendChild(window.sharedDom)

View File

@@ -1,9 +1,9 @@
import Y from '../src/Y.js' import Y from '../src/Y.js'
import yWebsocketsClient from '../../y-websockets-client/src/y-websockets-client.js' import yWebsocketsClient from '../../y-websockets-client/src/y-websockets-client.js'
import extendYIndexedDBPersistence from '../../y-indexeddb/src/y-indexeddb.js' import IndexedDBPersistence from '../../y-indexeddb/src/y-indexeddb.js'
Y.extend(yWebsocketsClient) Y.extend(yWebsocketsClient)
extendYIndexedDBPersistence(Y) Y.IndexedDBPersistence = IndexedDBPersistence
export default Y export default Y

2
package-lock.json generated
View File

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

View File

@@ -1,6 +1,6 @@
{ {
"name": "yjs", "name": "yjs",
"version": "13.0.0-49", "version": "13.0.0-46",
"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

@@ -1,14 +0,0 @@
import { createMutualExclude } from '../Util/mutualExclude.js'
export default class Binding {
constructor (type, target) {
this.type = type
this.target = target
this._mutualExclude = createMutualExclude()
}
destroy () {
this.type = null
this.target = null
}
}

View File

@@ -1,45 +0,0 @@
import Binding from './Binding.js'
import simpleDiff from '../Util/simpleDiff.js'
import { getRelativePosition, fromRelativePosition } from '../Util/relativePosition.js'
function typeObserver () {
this._mutualExclude(() => {
const textarea = this.target
const textType = this.type
const relativeStart = getRelativePosition(textType, textarea.selectionStart)
const relativeEnd = getRelativePosition(textType, textarea.selectionEnd)
textarea.value = textType.toString()
const start = fromRelativePosition(textType._y, relativeStart)
const end = fromRelativePosition(textType._y, relativeEnd)
textarea.setSelectionRange(start, end)
})
}
function domObserver () {
this._mutualExclude(() => {
let diff = simpleDiff(this.type.toString(), this.target.value)
this.type.delete(diff.pos, diff.remove)
this.type.insert(diff.pos, diff.insert)
})
}
export default class TextareaBinding extends Binding {
constructor (textType, domTextarea) {
// Binding handles textType as this.type and domTextarea as this.target
super(textType, domTextarea)
// set initial value
domTextarea.value = textType.toString()
// Observers are handled by this class
this._typeObserver = typeObserver.bind(this)
this._domObserver = domObserver.bind(this)
textType.observe(this._typeObserver)
domTextarea.addEventListener('input', this._domObserver)
}
destroy () {
// Remove everything that is handled by this class
this.type.unobserve(this._typeObserver)
this.target.unobserve(this._domObserver)
super.destroy()
}
}

View File

@@ -25,55 +25,32 @@ export default class AbstractPersistence {
if (cnf === undefined) { if (cnf === undefined) {
cnf = getFreshCnf() cnf = getFreshCnf()
this.ys.set(y, cnf) this.ys.set(y, cnf)
return this.init(y).then(() => { this.init(y)
y.on('afterTransaction', (y, transaction) => { y.on('afterTransaction', (y, transaction) => {
let cnf = this.ys.get(y) let cnf = this.ys.get(y)
if (cnf.len > 0) { if (cnf.len > 0) {
cnf.buffer.setUint32(0, cnf.len) cnf.buffer.setUint32(0, cnf.len)
this.saveUpdate(y, cnf.buffer.createBuffer(), transaction) this.saveUpdate(y, cnf.buffer.createBuffer(), transaction)
let _cnf = getFreshCnf() let _cnf = getFreshCnf()
for (let key in _cnf) { for (let key in _cnf) {
cnf[key] = _cnf[key] cnf[key] = _cnf[key]
}
} }
}) }
return this.retrieve(y)
}).then(function () {
return Promise.resolve(cnf)
}) })
} else {
return Promise.resolve(cnf)
} }
return this.retrieve(y).then(function () {
return Promise.resolve(cnf)
})
} }
deinit (y) { deinit (y) {
this.ys.delete(y) this.ys.delete(y)
y.persistence = null
} }
destroy () { destroy () {
this.ys = null this.ys = null
} }
/**
* Remove all persisted data that belongs to a room.
* Automatically destroys all Yjs all Yjs instances that persist to
* the room. If `destroyYjsInstances = false` the persistence functionality
* will be removed from the Yjs instances.
*
* ** Must be overwritten! **
*/
removePersistedData (room, destroyYjsInstances = true) {
this.ys.forEach((cnf, y) => {
if (y.room === room) {
if (destroyYjsInstances) {
y.destroy()
} else {
this.deinit(y)
}
}
})
}
/* overwrite */ /* overwrite */
saveUpdate (buffer) { saveUpdate (buffer) {
} }
@@ -98,17 +75,17 @@ export default class AbstractPersistence {
y.transact(function () { y.transact(function () {
if (model != null) { if (model != null) {
fromBinary(y, new BinaryDecoder(new Uint8Array(model))) fromBinary(y, new BinaryDecoder(new Uint8Array(model)))
y._setContentReady()
} }
if (updates != null) { if (updates != null) {
for (let i = 0; i < updates.length; i++) { for (let i = 0; i < updates.length; i++) {
integrateRemoteStructs(y, new BinaryDecoder(new Uint8Array(updates[i]))) integrateRemoteStructs(y, new BinaryDecoder(new Uint8Array(updates[i])))
y._setContentReady()
} }
} }
}) })
y.emit('persistenceReady')
}) })
} }
/* overwrite */ /* overwrite */
persist (y) { persist (y) {
return toBinary(y).createBuffer() return toBinary(y).createBuffer()

View File

@@ -55,16 +55,14 @@ export default class Item {
/** /**
* Copy the effect of struct * Copy the effect of struct
*/ */
_copy (undeleteChildren, copyPosition) { _copy () {
let struct = new this.constructor() let struct = new this.constructor()
if (copyPosition) { struct._origin = this._left
struct._origin = this._left struct._left = this._left
struct._left = this._left struct._right = this
struct._right = this struct._right_origin = this
struct._right_origin = this struct._parent = this._parent
struct._parent = this._parent struct._parentSub = this._parentSub
struct._parentSub = this._parentSub
}
return struct return struct
} }
get _lastId () { get _lastId () {
@@ -115,11 +113,9 @@ export default class Item {
* - Check if this is struct deleted * - Check if this is struct deleted
*/ */
_integrate (y) { _integrate (y) {
y._transaction.newTypes.add(this)
const parent = this._parent const parent = this._parent
const selfID = this._id const selfID = this._id
const user = selfID === null ? y.userID : selfID.user const userState = selfID === null ? 0 : y.ss.getState(selfID.user)
const userState = y.ss.getState(user)
if (selfID === null) { if (selfID === null) {
this._id = y.ss.getNextID(this._length) this._id = y.ss.getNextID(this._length)
} else if (selfID.user === RootFakeUserID) { } else if (selfID.user === RootFakeUserID) {

View File

@@ -6,8 +6,8 @@ export default class ItemJSON extends Item {
super() super()
this._content = null this._content = null
} }
_copy (undeleteChildren, copyPosition) { _copy () {
let struct = super._copy(undeleteChildren, copyPosition) let struct = super._copy()
struct._content = this._content struct._content = this._content
return struct return struct
} }

View File

@@ -6,8 +6,8 @@ export default class ItemString extends Item {
super() super()
this._content = null this._content = null
} }
_copy (undeleteChildren, copyPosition) { _copy () {
let struct = super._copy(undeleteChildren, copyPosition) let struct = super._copy()
struct._content = this._content struct._content = this._content
return struct return struct
} }

View File

@@ -79,16 +79,15 @@ export default class Type extends Item {
type = type._parent type = type._parent
} }
} }
_copy (undeleteChildren, copyPosition) { _copy (undeleteChildren) {
let copy = super._copy(undeleteChildren, copyPosition) let copy = super._copy()
let map = new Map() let map = new Map()
copy._map = map copy._map = map
for (let [key, value] of this._map) { for (let [key, value] of this._map) {
if (undeleteChildren.has(value) || !value.deleted) { if (undeleteChildren.has(value) || !value.deleted) {
let _item = value._copy(undeleteChildren, false) let _item = value._copy(undeleteChildren)
_item._parent = copy _item._parent = copy
_item._parentSub = key map.set(key, value._copy(undeleteChildren))
map.set(key, _item)
} }
} }
let prevUndeleted = null let prevUndeleted = null
@@ -96,7 +95,7 @@ export default class Type extends Item {
let item = this._start let item = this._start
while (item !== null) { while (item !== null) {
if (undeleteChildren.has(item) || !item.deleted) { if (undeleteChildren.has(item) || !item.deleted) {
let _item = item._copy(undeleteChildren, false) let _item = item._copy(undeleteChildren)
_item._left = prevUndeleted _item._left = prevUndeleted
_item._origin = prevUndeleted _item._origin = prevUndeleted
_item._right = null _item._right = null
@@ -134,6 +133,7 @@ export default class Type extends Item {
this._deepEventHandler.removeEventListener(f) this._deepEventHandler.removeEventListener(f)
} }
_integrate (y) { _integrate (y) {
y._transaction.newTypes.add(this)
super._integrate(y) super._integrate(y)
this._y = y this._y = y
// when integrating children we must make sure to // when integrating children we must make sure to

View File

@@ -9,21 +9,17 @@ class YArrayEvent extends YEvent {
super(yarray) super(yarray)
this.remote = remote this.remote = remote
this._transaction = transaction this._transaction = transaction
this._addedElements = null
} }
get addedElements () { get addedElements () {
if (this._addedElements === null) { const target = this.target
const target = this.target const transaction = this._transaction
const transaction = this._transaction const addedElements = new Set()
const addedElements = new Set() transaction.newTypes.forEach(function (type) {
transaction.newTypes.forEach(function (type) { if (type._parent === target && !transaction.deletedStructs.has(type)) {
if (type._parent === target && !transaction.deletedStructs.has(type)) { addedElements.add(type)
addedElements.add(type) }
} })
}) return addedElements
this._addedElements = addedElements
}
return this._addedElements
} }
get removedElements () { get removedElements () {
const target = this.target const target = this.target

View File

@@ -20,8 +20,8 @@ export default class YXmlElement extends YXmlFragment {
this._domFilter = arg2 this._domFilter = arg2
} }
} }
_copy (undeleteChildren, copyPosition) { _copy (undeleteChildren) {
let struct = super._copy(undeleteChildren, copyPosition) let struct = super._copy(undeleteChildren)
struct.nodeName = this.nodeName struct.nodeName = this.nodeName
return struct return struct
} }

View File

@@ -152,20 +152,18 @@ export default class YXmlFragment extends YArray {
attributes.set(key, attrs[key]) attributes.set(key, attrs[key])
} }
} }
this._y.transact(() => { let result = this._domFilter(this.nodeName, new Map(attributes))
let result = this._domFilter(this.nodeName, new Map(attributes)) if (result === null) {
if (result === null) { this._delete(this._y)
this._delete(this._y) } else {
} else { attributes.forEach((value, key) => {
attributes.forEach((value, key) => { if (!result.has(key)) {
if (!result.has(key)) { this.removeAttribute(key)
this.removeAttribute(key) }
}
})
}
this.forEach(xml => {
xml.setDomFilter(f)
}) })
}
this.forEach(xml => {
xml.setDomFilter(f)
}) })
} }
_callObserver (transaction, parentSubs, remote) { _callObserver (transaction, parentSubs, remote) {

View File

@@ -14,11 +14,6 @@ export default class YXmlHook extends YMap {
getHook(hookName).fillType(dom, this) getHook(hookName).fillType(dom, this)
} }
} }
_copy (undeleteChildren, copyPosition) {
const struct = super._copy(undeleteChildren, copyPosition)
struct.hookName = this.hookName
return struct
}
getDom (_document) { getDom (_document) {
_document = _document || document _document = _document || document
if (this._dom === null) { if (this._dom === null) {

View File

@@ -1,7 +1,6 @@
export default class NamedEventHandler { export default class NamedEventHandler {
constructor () { constructor () {
this._eventListener = new Map() this._eventListener = new Map()
this._stateListener = new Map()
} }
_getListener (name) { _getListener (name) {
let listeners = this._eventListener.get(name) let listeners = this._eventListener.get(name)
@@ -22,20 +21,6 @@ export default class NamedEventHandler {
let listeners = this._getListener(name) let listeners = this._getListener(name)
listeners.on.add(f) listeners.on.add(f)
} }
_initStateListener (name) {
let state = this._stateListener.get(name)
if (state === undefined) {
state = {}
state.promise = new Promise(function (resolve) {
state.resolve = resolve
})
this._stateListener.set(name, state)
}
return state
}
when (name) {
return this._initStateListener(name).promise
}
off (name, f) { off (name, f) {
if (name == null || f == null) { if (name == null || f == null) {
throw new Error('You must specify event name and function!') throw new Error('You must specify event name and function!')
@@ -47,7 +32,6 @@ export default class NamedEventHandler {
} }
} }
emit (name, ...args) { emit (name, ...args) {
this._initStateListener(name).resolve()
const listener = this._eventListener.get(name) const listener = this._eventListener.get(name)
if (listener !== undefined) { if (listener !== undefined) {
listener.on.forEach(f => f.apply(null, args)) listener.on.forEach(f => f.apply(null, args))

View File

@@ -50,7 +50,7 @@ function applyReverseOperation (y, scope, reverseBuffer) {
) )
) { ) {
performedUndo = true performedUndo = true
op = op._copy(undoOp.deletedStructs, true) op = op._copy(undoOp.deletedStructs)
op._integrate(y) op._integrate(y)
} }
} }

View File

@@ -5,7 +5,6 @@ import { generateUserID } from './Util/generateUserID.js'
import RootID from './Util/RootID.js' import RootID from './Util/RootID.js'
import NamedEventHandler from './Util/NamedEventHandler.js' import NamedEventHandler from './Util/NamedEventHandler.js'
import UndoManager from './Util/UndoManager.js' import UndoManager from './Util/UndoManager.js'
import { integrateRemoteStructs } from './MessageHandler/integrateRemoteStructs.js'
import { messageToString, messageToRoomname } from './MessageHandler/messageToString.js' import { messageToString, messageToRoomname } from './MessageHandler/messageToString.js'
@@ -22,10 +21,6 @@ import { addStruct as addType } from './Util/structReferences.js'
import debug from 'debug' import debug from 'debug'
import Transaction from './Transaction.js' import Transaction from './Transaction.js'
import TextareaBinding from './Binding/TextareaBinding.js'
import { toBinary, fromBinary } from './MessageHandler/binaryEncode.js'
export default class Y extends NamedEventHandler { export default class Y extends NamedEventHandler {
constructor (room, opts, persistence) { constructor (room, opts, persistence) {
super() super()
@@ -66,15 +61,6 @@ export default class Y extends NamedEventHandler {
this.emit('content') this.emit('content')
} }
} }
whenContentReady () {
if (this._contentReady) {
return Promise.resolve()
} else {
return new Promise(resolve => {
this.once('content', resolve)
})
}
}
_beforeChange () {} _beforeChange () {}
transact (f, remote = false) { transact (f, remote = false) {
let initialCall = this._transaction === null let initialCall = this._transaction === null
@@ -201,17 +187,12 @@ Y.XmlFragment = YXmlFragment
Y.XmlText = YXmlText Y.XmlText = YXmlText
Y.XmlHook = YXmlHook Y.XmlHook = YXmlHook
Y.TextareaBinding = TextareaBinding
Y.utils = { Y.utils = {
BinaryDecoder, BinaryDecoder,
UndoManager, UndoManager,
getRelativePosition, getRelativePosition,
fromRelativePosition, fromRelativePosition,
addType, addType
integrateRemoteStructs,
toBinary,
fromBinary
} }
Y.debug = debug Y.debug = debug

8
y.js

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

241
y.node.js
View File

@@ -1,7 +1,7 @@
/** /**
* yjs - A framework for real-time p2p shared editing on any data * yjs - A framework for real-time p2p shared editing on any data
* @version v13.0.0-49 * @version v13.0.0-46
* @license MIT * @license MIT
*/ */
@@ -1344,16 +1344,14 @@ class Item {
/** /**
* Copy the effect of struct * Copy the effect of struct
*/ */
_copy (undeleteChildren, copyPosition) { _copy () {
let struct = new this.constructor(); let struct = new this.constructor();
if (copyPosition) { struct._origin = this._left;
struct._origin = this._left; struct._left = this._left;
struct._left = this._left; struct._right = this;
struct._right = this; struct._right_origin = this;
struct._right_origin = this; struct._parent = this._parent;
struct._parent = this._parent; struct._parentSub = this._parentSub;
struct._parentSub = this._parentSub;
}
return struct return struct
} }
get _lastId () { get _lastId () {
@@ -1404,11 +1402,9 @@ class Item {
* - Check if this is struct deleted * - Check if this is struct deleted
*/ */
_integrate (y) { _integrate (y) {
y._transaction.newTypes.add(this);
const parent = this._parent; const parent = this._parent;
const selfID = this._id; const selfID = this._id;
const user = selfID === null ? y.userID : selfID.user; const userState = selfID === null ? 0 : y.ss.getState(selfID.user);
const userState = y.ss.getState(user);
if (selfID === null) { if (selfID === null) {
this._id = y.ss.getNextID(this._length); this._id = y.ss.getNextID(this._length);
} else if (selfID.user === RootFakeUserID) { } else if (selfID.user === RootFakeUserID) {
@@ -1720,16 +1716,15 @@ class Type extends Item {
type = type._parent; type = type._parent;
} }
} }
_copy (undeleteChildren, copyPosition) { _copy (undeleteChildren) {
let copy = super._copy(undeleteChildren, copyPosition); let copy = super._copy();
let map = new Map(); let map = new Map();
copy._map = map; copy._map = map;
for (let [key, value] of this._map) { for (let [key, value] of this._map) {
if (undeleteChildren.has(value) || !value.deleted) { if (undeleteChildren.has(value) || !value.deleted) {
let _item = value._copy(undeleteChildren, false); let _item = value._copy(undeleteChildren);
_item._parent = copy; _item._parent = copy;
_item._parentSub = key; map.set(key, value._copy(undeleteChildren));
map.set(key, _item);
} }
} }
let prevUndeleted = null; let prevUndeleted = null;
@@ -1737,7 +1732,7 @@ class Type extends Item {
let item = this._start; let item = this._start;
while (item !== null) { while (item !== null) {
if (undeleteChildren.has(item) || !item.deleted) { if (undeleteChildren.has(item) || !item.deleted) {
let _item = item._copy(undeleteChildren, false); let _item = item._copy(undeleteChildren);
_item._left = prevUndeleted; _item._left = prevUndeleted;
_item._origin = prevUndeleted; _item._origin = prevUndeleted;
_item._right = null; _item._right = null;
@@ -1775,6 +1770,7 @@ class Type extends Item {
this._deepEventHandler.removeEventListener(f); this._deepEventHandler.removeEventListener(f);
} }
_integrate (y) { _integrate (y) {
y._transaction.newTypes.add(this);
super._integrate(y); super._integrate(y);
this._y = y; this._y = y;
// when integrating children we must make sure to // when integrating children we must make sure to
@@ -1817,8 +1813,8 @@ class ItemJSON extends Item {
super(); super();
this._content = null; this._content = null;
} }
_copy (undeleteChildren, copyPosition) { _copy () {
let struct = super._copy(undeleteChildren, copyPosition); let struct = super._copy();
struct._content = this._content; struct._content = this._content;
return struct return struct
} }
@@ -1879,8 +1875,8 @@ class ItemString extends Item {
super(); super();
this._content = null; this._content = null;
} }
_copy (undeleteChildren, copyPosition) { _copy () {
let struct = super._copy(undeleteChildren, copyPosition); let struct = super._copy();
struct._content = this._content; struct._content = this._content;
return struct return struct
} }
@@ -1948,21 +1944,17 @@ class YArrayEvent extends YEvent {
super(yarray); super(yarray);
this.remote = remote; this.remote = remote;
this._transaction = transaction; this._transaction = transaction;
this._addedElements = null;
} }
get addedElements () { get addedElements () {
if (this._addedElements === null) { const target = this.target;
const target = this.target; const transaction = this._transaction;
const transaction = this._transaction; const addedElements = new Set();
const addedElements = new Set(); transaction.newTypes.forEach(function (type) {
transaction.newTypes.forEach(function (type) { if (type._parent === target && !transaction.deletedStructs.has(type)) {
if (type._parent === target && !transaction.deletedStructs.has(type)) { addedElements.add(type);
addedElements.add(type); }
} });
}); return addedElements
this._addedElements = addedElements;
}
return this._addedElements
} }
get removedElements () { get removedElements () {
const target = this.target; const target = this.target;
@@ -2915,20 +2907,18 @@ class YXmlFragment extends YArray {
attributes.set(key, attrs[key]); attributes.set(key, attrs[key]);
} }
} }
this._y.transact(() => { let result = this._domFilter(this.nodeName, new Map(attributes));
let result = this._domFilter(this.nodeName, new Map(attributes)); if (result === null) {
if (result === null) { this._delete(this._y);
this._delete(this._y); } else {
} else { attributes.forEach((value, key) => {
attributes.forEach((value, key) => { if (!result.has(key)) {
if (!result.has(key)) { this.removeAttribute(key);
this.removeAttribute(key); }
}
});
}
this.forEach(xml => {
xml.setDomFilter(f);
}); });
}
this.forEach(xml => {
xml.setDomFilter(f);
}); });
} }
_callObserver (transaction, parentSubs, remote) { _callObserver (transaction, parentSubs, remote) {
@@ -3133,8 +3123,8 @@ class YXmlElement extends YXmlFragment {
this._domFilter = arg2; this._domFilter = arg2;
} }
} }
_copy (undeleteChildren, copyPosition) { _copy (undeleteChildren) {
let struct = super._copy(undeleteChildren, copyPosition); let struct = super._copy(undeleteChildren);
struct.nodeName = this.nodeName; struct.nodeName = this.nodeName;
return struct return struct
} }
@@ -3272,11 +3262,6 @@ class YXmlHook extends YMap {
getHook(hookName).fillType(dom, this); getHook(hookName).fillType(dom, this);
} }
} }
_copy (undeleteChildren, copyPosition) {
const struct = super._copy(undeleteChildren, copyPosition);
struct.hookName = this.hookName;
return struct
}
getDom (_document) { getDom (_document) {
_document = _document || document; _document = _document || document;
if (this._dom === null) { if (this._dom === null) {
@@ -3606,7 +3591,6 @@ function generateUserID () {
class NamedEventHandler { class NamedEventHandler {
constructor () { constructor () {
this._eventListener = new Map(); this._eventListener = new Map();
this._stateListener = new Map();
} }
_getListener (name) { _getListener (name) {
let listeners = this._eventListener.get(name); let listeners = this._eventListener.get(name);
@@ -3627,20 +3611,6 @@ class NamedEventHandler {
let listeners = this._getListener(name); let listeners = this._getListener(name);
listeners.on.add(f); listeners.on.add(f);
} }
_initStateListener (name) {
let state = this._stateListener.get(name);
if (state === undefined) {
state = {};
state.promise = new Promise(function (resolve) {
state.resolve = resolve;
});
this._stateListener.set(name, state);
}
return state
}
when (name) {
return this._initStateListener(name).promise
}
off (name, f) { off (name, f) {
if (name == null || f == null) { if (name == null || f == null) {
throw new Error('You must specify event name and function!') throw new Error('You must specify event name and function!')
@@ -3652,7 +3622,6 @@ class NamedEventHandler {
} }
} }
emit (name, ...args) { emit (name, ...args) {
this._initStateListener(name).resolve();
const listener = this._eventListener.get(name); const listener = this._eventListener.get(name);
if (listener !== undefined) { if (listener !== undefined) {
listener.on.forEach(f => f.apply(null, args)); listener.on.forEach(f => f.apply(null, args));
@@ -3717,7 +3686,7 @@ function applyReverseOperation (y, scope, reverseBuffer) {
) )
) { ) {
performedUndo = true; performedUndo = true;
op = op._copy(undoOp.deletedStructs, true); op = op._copy(undoOp.deletedStructs);
op._integrate(y); op._integrate(y);
} }
} }
@@ -4673,55 +4642,32 @@ class AbstractPersistence {
if (cnf === undefined) { if (cnf === undefined) {
cnf = getFreshCnf(); cnf = getFreshCnf();
this.ys.set(y, cnf); this.ys.set(y, cnf);
return this.init(y).then(() => { this.init(y);
y.on('afterTransaction', (y, transaction) => { y.on('afterTransaction', (y, transaction) => {
let cnf = this.ys.get(y); let cnf = this.ys.get(y);
if (cnf.len > 0) { if (cnf.len > 0) {
cnf.buffer.setUint32(0, cnf.len); cnf.buffer.setUint32(0, cnf.len);
this.saveUpdate(y, cnf.buffer.createBuffer(), transaction); this.saveUpdate(y, cnf.buffer.createBuffer(), transaction);
let _cnf = getFreshCnf(); let _cnf = getFreshCnf();
for (let key in _cnf) { for (let key in _cnf) {
cnf[key] = _cnf[key]; cnf[key] = _cnf[key];
}
} }
}); }
return this.retrieve(y) });
}).then(function () {
return Promise.resolve(cnf)
})
} else {
return Promise.resolve(cnf)
} }
return this.retrieve(y).then(function () {
return Promise.resolve(cnf)
})
} }
deinit (y) { deinit (y) {
this.ys.delete(y); this.ys.delete(y);
y.persistence = null;
} }
destroy () { destroy () {
this.ys = null; this.ys = null;
} }
/**
* Remove all persisted data that belongs to a room.
* Automatically destroys all Yjs all Yjs instances that persist to
* the room. If `destroyYjsInstances = false` the persistence functionality
* will be removed from the Yjs instances.
*
* ** Must be overwritten! **
*/
removePersistedData (room, destroyYjsInstances = true) {
this.ys.forEach((cnf, y) => {
if (y.room === room) {
if (destroyYjsInstances) {
y.destroy();
} else {
this.deinit(y);
}
}
});
}
/* overwrite */ /* overwrite */
saveUpdate (buffer) { saveUpdate (buffer) {
} }
@@ -4746,76 +4692,23 @@ class AbstractPersistence {
y.transact(function () { y.transact(function () {
if (model != null) { if (model != null) {
fromBinary(y, new BinaryDecoder(new Uint8Array(model))); fromBinary(y, new BinaryDecoder(new Uint8Array(model)));
y._setContentReady();
} }
if (updates != null) { if (updates != null) {
for (let i = 0; i < updates.length; i++) { for (let i = 0; i < updates.length; i++) {
integrateRemoteStructs(y, new BinaryDecoder(new Uint8Array(updates[i]))); integrateRemoteStructs(y, new BinaryDecoder(new Uint8Array(updates[i])));
y._setContentReady();
} }
} }
}); });
y.emit('persistenceReady');
}); });
} }
/* overwrite */ /* overwrite */
persist (y) { persist (y) {
return toBinary(y).createBuffer() return toBinary(y).createBuffer()
} }
} }
class Binding {
constructor (type, target) {
this.type = type;
this.target = target;
this._mutualExclude = createMutualExclude();
}
destroy () {
this.type = null;
this.target = null;
}
}
function typeObserver () {
this._mutualExclude(() => {
const textarea = this.target;
const textType = this.type;
const relativeStart = getRelativePosition(textType, textarea.selectionStart);
const relativeEnd = getRelativePosition(textType, textarea.selectionEnd);
textarea.value = textType.toString();
const start = fromRelativePosition(textType._y, relativeStart);
const end = fromRelativePosition(textType._y, relativeEnd);
textarea.setSelectionRange(start, end);
});
}
function domObserver () {
this._mutualExclude(() => {
let diff = simpleDiff(this.type.toString(), this.target.value);
this.type.delete(diff.pos, diff.remove);
this.type.insert(diff.pos, diff.insert);
});
}
class TextareaBinding extends Binding {
constructor (textType, domTextarea) {
// Binding handles textType as this.type and domTextarea as this.target
super(textType, domTextarea);
// set initial value
domTextarea.value = textType.toString();
// Observers are handled by this class
this._typeObserver = typeObserver.bind(this);
this._domObserver = domObserver.bind(this);
textType.observe(this._typeObserver);
domTextarea.addEventListener('input', this._domObserver);
}
destroy () {
// Remove everything that is handled by this class
this.type.unobserve(this._typeObserver);
this.target.unobserve(this._domObserver);
super.destroy();
}
}
class Y$1 extends NamedEventHandler { class Y$1 extends NamedEventHandler {
constructor (room, opts, persistence) { constructor (room, opts, persistence) {
super(); super();
@@ -4856,15 +4749,6 @@ class Y$1 extends NamedEventHandler {
this.emit('content'); this.emit('content');
} }
} }
whenContentReady () {
if (this._contentReady) {
return Promise.resolve()
} else {
return new Promise(resolve => {
this.once('content', resolve);
})
}
}
_beforeChange () {} _beforeChange () {}
transact (f, remote = false) { transact (f, remote = false) {
let initialCall = this._transaction === null; let initialCall = this._transaction === null;
@@ -4991,17 +4875,12 @@ Y$1.XmlFragment = YXmlFragment;
Y$1.XmlText = YXmlText; Y$1.XmlText = YXmlText;
Y$1.XmlHook = YXmlHook; Y$1.XmlHook = YXmlHook;
Y$1.TextareaBinding = TextareaBinding;
Y$1.utils = { Y$1.utils = {
BinaryDecoder, BinaryDecoder,
UndoManager, UndoManager,
getRelativePosition, getRelativePosition,
fromRelativePosition, fromRelativePosition,
addType: addStruct, addType: addStruct
integrateRemoteStructs,
toBinary,
fromBinary
}; };
Y$1.debug = browser; Y$1.debug = browser;

File diff suppressed because one or more lines are too long

11533
y.test.js

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long