Compare commits
8 Commits
v13.0.0-47
...
v13.0.0-49
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdcc19d8f5 | ||
|
|
bbd3317d62 | ||
|
|
5d3922cb64 | ||
|
|
a81a2cd553 | ||
|
|
c0d24bdba4 | ||
|
|
40e913e9c5 | ||
|
|
94f6a0fd9c | ||
|
|
41a88dbc43 |
@@ -24,7 +24,8 @@
|
|||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div id="aceContainer"></div>
|
<div id="aceContainer"></div>
|
||||||
<script src="../bower_components/yjs/y.js"></script>
|
<script src="../../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>
|
||||||
|
|||||||
@@ -1,24 +1,17 @@
|
|||||||
/* global Y, ace */
|
/* global Y, ace */
|
||||||
|
|
||||||
Y({
|
let y = new Y('ace-example', {
|
||||||
db: {
|
|
||||||
name: 'memory'
|
|
||||||
},
|
|
||||||
connector: {
|
connector: {
|
||||||
name: 'websockets-client',
|
name: 'websockets-client',
|
||||||
room: 'ace-example'
|
url: 'http://127.0.0.1:1234'
|
||||||
},
|
|
||||||
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)
|
||||||
|
|||||||
@@ -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/dist/y-websockets-client.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>
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
/* global Y */
|
/* global Y */
|
||||||
|
|
||||||
// initialize a shared object. This function call returns a promise!
|
let y = new Y('chat-example', {
|
||||||
var y = new Y({
|
|
||||||
connector: {
|
connector: {
|
||||||
name: 'websockets-client',
|
name: 'websockets-client',
|
||||||
room: 'chat-example'
|
url: 'http://127.0.0.1:1234'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -23,6 +22,7 @@ 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,23 +30,17 @@ 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
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
<body>
|
<body>
|
||||||
<div id="codeMirrorContainer"></div>
|
<div id="codeMirrorContainer"></div>
|
||||||
|
|
||||||
<script src="../bower_components/yjs/y.js"></script>
|
<script src="../../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">
|
||||||
|
|||||||
@@ -1,24 +1,16 @@
|
|||||||
/* global Y, CodeMirror */
|
/* global Y, CodeMirror */
|
||||||
|
|
||||||
// initialize a shared object. This function call returns a promise!
|
let y = new Y('codemirror-example', {
|
||||||
Y({
|
|
||||||
db: {
|
|
||||||
name: 'memory'
|
|
||||||
},
|
|
||||||
connector: {
|
connector: {
|
||||||
name: 'websockets-client',
|
name: 'websockets-client',
|
||||||
room: 'codemirror-example'
|
url: 'http://127.0.0.1:1234'
|
||||||
},
|
|
||||||
sourceDir: '/bower_components',
|
|
||||||
share: {
|
|
||||||
codemirror: 'Text' // y.share.codemirror is of type Y.Text
|
|
||||||
}
|
}
|
||||||
}).then(function (y) {
|
|
||||||
window.yCodeMirror = y
|
|
||||||
|
|
||||||
var editor = CodeMirror(document.querySelector('#codeMirrorContainer'), {
|
|
||||||
mode: 'javascript',
|
|
||||||
lineNumbers: true
|
|
||||||
})
|
|
||||||
y.share.codemirror.bindCodeMirror(editor)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
window.yCodeMirror = y
|
||||||
|
|
||||||
|
var editor = CodeMirror(document.querySelector('#codeMirrorContainer'), {
|
||||||
|
mode: 'javascript',
|
||||||
|
lineNumbers: true
|
||||||
|
})
|
||||||
|
y.define('codemirror', Y.Text).bindCodeMirror(editor)
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
</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="../yjs-dist.js"></script>
|
<script src="../../y.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>
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
/* globals Y, d3 */
|
/* globals Y, d3 */
|
||||||
|
|
||||||
let y = new Y({
|
let y = new Y('drawing-example', {
|
||||||
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
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
</head>
|
</head>
|
||||||
<script src="../yjs-dist.js"></script>
|
<script src="../../y.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>
|
||||||
|
|||||||
@@ -107,15 +107,13 @@ Y.XmlHook.addHook('magic-drawing', {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// initialize a shared object. This function call returns a promise!
|
let y = new Y('html-editor-drawing-hook-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: '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, {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
</head>
|
</head>
|
||||||
<script src="../yjs-dist.js"></script>
|
<script src="../../y.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">
|
||||||
|
|||||||
@@ -4,18 +4,14 @@ window.onload = function () {
|
|||||||
window.yXmlType.bindToDom(document.body)
|
window.yXmlType.bindToDom(document.body)
|
||||||
}
|
}
|
||||||
|
|
||||||
const persistence = new Y.IndexedDB()
|
|
||||||
|
|
||||||
// initialize a shared object. This function call returns a promise!
|
|
||||||
let y = new Y('htmleditor', {
|
let y = new Y('htmleditor', {
|
||||||
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'
|
|
||||||
// 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
|
||||||
|
|||||||
@@ -16,6 +16,9 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script type="module" src="./index.js"></script>
|
<script src="../../y.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>
|
||||||
|
|||||||
@@ -7,12 +7,13 @@ const connector = {
|
|||||||
room: 'codemirror-example'
|
room: 'codemirror-example'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// initialize a shared object. This function call returns a promise!
|
|
||||||
const y = Y('codemirror-example', connector, persistence)
|
const y = new Y('codemirror-example', connector, persistence)
|
||||||
window.yCodeMirror = y
|
window.yCodeMirror = y
|
||||||
|
|
||||||
var editor = CodeMirror(document.querySelector('#codeMirrorContainer'), {
|
var editor = CodeMirror(document.querySelector('#codeMirrorContainer'), {
|
||||||
mode: 'javascript',
|
mode: 'javascript',
|
||||||
lineNumbers: true
|
lineNumbers: true
|
||||||
})
|
})
|
||||||
y.share.codemirror.bindCodeMirror(editor)
|
|
||||||
|
y.define('codemirror', Y.Text).bindCodeMirror(editor)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
.one {
|
.one {
|
||||||
grid-column: 1 ;
|
grid-column: 1 ;
|
||||||
}
|
}
|
||||||
.two {
|
.two {
|
||||||
grid-column: 2;
|
grid-column: 2;
|
||||||
}
|
}
|
||||||
.three {
|
.three {
|
||||||
@@ -49,10 +49,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="../../y.js"></script>
|
<script src="../../y.js"></script>
|
||||||
<script src="../../../y-array/y-array.js"></script>
|
<script src='../../../y-websockets-client/y-websockets-client.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>
|
||||||
|
|||||||
@@ -1,64 +1,38 @@
|
|||||||
/* global Y */
|
/* global Y */
|
||||||
|
|
||||||
Y({
|
function bindYjsInstance (y, suffix) {
|
||||||
db: {
|
y.define('textarea', Y.Text).bind(document.getElementById('textarea' + suffix))
|
||||||
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('container2').removeAttribute('disconnected')
|
document.getElementById('container' + suffix).removeAttribute('disconnected')
|
||||||
})
|
})
|
||||||
y.connector.socket.on('disconnect', function () {
|
y.connector.socket.on('disconnect', function () {
|
||||||
document.getElementById('container2').setAttribute('disconnected', true)
|
document.getElementById('container' + suffix).setAttribute('disconnected', true)
|
||||||
})
|
})
|
||||||
})
|
}
|
||||||
|
|
||||||
Y({
|
let y1 = new Y('infinite-example', {
|
||||||
db: {
|
|
||||||
name: 'memory'
|
|
||||||
},
|
|
||||||
connector: {
|
connector: {
|
||||||
name: 'websockets-client',
|
name: 'websockets-client',
|
||||||
room: 'Textarea-example',
|
url: 'http://127.0.0.1:1234'
|
||||||
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')
|
||||||
|
|||||||
@@ -17,9 +17,7 @@
|
|||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
<script src="../../y.js"></script>
|
<script src="../../y.js"></script>
|
||||||
<script src="../../../y-map/dist/y-map.js"></script>
|
<script src='../../../y-websockets-client/y-websockets-client.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>
|
||||||
|
|||||||
@@ -1,74 +1,67 @@
|
|||||||
/* @flow */
|
|
||||||
/* global Y, d3 */
|
/* global Y, d3 */
|
||||||
|
|
||||||
// initialize a shared object. This function call returns a promise!
|
let y = new Y('jigsaw-example', {
|
||||||
Y({
|
|
||||||
db: {
|
|
||||||
name: 'memory'
|
|
||||||
},
|
|
||||||
connector: {
|
connector: {
|
||||||
name: 'websockets-client',
|
name: 'websockets-client',
|
||||||
room: 'Puzzle-example',
|
url: 'http://127.0.0.1:1234'
|
||||||
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})
|
|
||||||
})
|
|
||||||
|
|
||||||
var data = [y.share.piece1, y.share.piece2, y.share.piece3, y.share.piece4]
|
let jigsaw = y.define('jigsaw', Y.Map)
|
||||||
var pieces = d3.select(document.querySelector('#puzzle-example')).selectAll('path').data(data)
|
window.yJigsaw = y
|
||||||
|
|
||||||
pieces
|
var origin // mouse start position - translation of piece
|
||||||
.classed('draggable', true)
|
var drag = d3.behavior.drag()
|
||||||
.attr('transform', function (piece) {
|
.on('dragstart', function (params) {
|
||||||
var translation = piece.get('translation') || {x: 0, y: 0}
|
// get the translation of the element
|
||||||
return 'translate(' + translation.x + ',' + translation.y + ')'
|
var translation = d3
|
||||||
}).call(drag)
|
.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
|
||||||
|
jigsaw.set(piece, {x: x, y: y})
|
||||||
|
})
|
||||||
|
|
||||||
data.forEach(function (piece) {
|
var data = ['piece1', 'piece2', 'piece3', 'piece4']
|
||||||
piece.observe(function () {
|
var pieces = d3.select(document.querySelector('#puzzle-example')).selectAll('path').data(data)
|
||||||
// whenever a property of a piece changes, update the translation of the pieces
|
|
||||||
pieces
|
pieces
|
||||||
.transition()
|
.classed('draggable', true)
|
||||||
.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 + ')'
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script src="../bower_components/yjs/y.js"></script>
|
<script src="../../y.js"></script>
|
||||||
<script src="../bower_components/y-websockets-client/y-websockets-client.js"></script>
|
<script src='../../../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>
|
||||||
|
|||||||
@@ -2,29 +2,21 @@
|
|||||||
|
|
||||||
require.config({ paths: { 'vs': '../node_modules/monaco-editor/min/vs' } })
|
require.config({ paths: { 'vs': '../node_modules/monaco-editor/min/vs' } })
|
||||||
|
|
||||||
require(['vs/editor/editor.main'], function () {
|
let y = new Y('monaco-example', {
|
||||||
// Initialize a shared object. This function call returns a promise!
|
connector: {
|
||||||
Y({
|
name: 'websockets-client',
|
||||||
db: {
|
url: 'http://127.0.0.1:1234'
|
||||||
name: 'memory'
|
}
|
||||||
},
|
})
|
||||||
connector: {
|
|
||||||
name: 'websockets-client',
|
require(['vs/editor/editor.main'], function () {
|
||||||
room: 'monaco-example'
|
window.yMonaco = y
|
||||||
},
|
|
||||||
sourceDir: '/bower_components',
|
// Create Monaco editor
|
||||||
share: {
|
var editor = monaco.editor.create(document.getElementById('monacoContainer'), {
|
||||||
monaco: 'Text' // y.share.monaco is of type Y.Text
|
language: 'javascript'
|
||||||
}
|
})
|
||||||
}).then(function (y) {
|
|
||||||
window.yMonaco = y
|
// Bind to y.share.monaco
|
||||||
|
y.define('monaco', Y.Text).bindMonaco(editor)
|
||||||
// Create Monaco editor
|
|
||||||
var editor = monaco.editor.create(document.getElementById('monacoContainer'), {
|
|
||||||
language: 'javascript'
|
|
||||||
})
|
|
||||||
|
|
||||||
// Bind to y.share.monaco
|
|
||||||
y.share.monaco.bindMonaco(editor)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -26,10 +26,7 @@
|
|||||||
<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-array/y-array.js"></script>
|
<script src='../../../y-websockets-client/y-websockets-client.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>
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
<textarea style="width:80%;" rows=40 id="textfield" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>
|
<textarea style="width:80%;" rows=40 autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>
|
||||||
<script src="../../y.js"></script>
|
<script src="../../y.js"></script>
|
||||||
<script src="../../../y-array/y-array.js"></script>
|
<script src='../../../y-websockets-client/y-websockets-client.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>
|
||||||
|
|||||||
@@ -1,23 +1,15 @@
|
|||||||
/* global Y */
|
/* global Y */
|
||||||
|
|
||||||
// initialize a shared object. This function call returns a promise!
|
let y = new Y('textarea-example', {
|
||||||
Y({
|
|
||||||
db: {
|
|
||||||
name: 'memory'
|
|
||||||
},
|
|
||||||
connector: {
|
connector: {
|
||||||
name: 'websockets-client',
|
name: 'websockets-client',
|
||||||
room: 'Textarea-example2',
|
url: 'http://127.0.0.1:1234'
|
||||||
// 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)
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
</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="../yjs-dist.js"></script>
|
<script src="../../y.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>
|
||||||
|
|||||||
@@ -1,23 +1,13 @@
|
|||||||
/* global Y */
|
/* global Y */
|
||||||
|
|
||||||
// initialize a shared object. This function call returns a promise!
|
let y = new Y('xml-example', {
|
||||||
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)
|
||||||
|
|||||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "yjs",
|
"name": "yjs",
|
||||||
"version": "13.0.0-47",
|
"version": "13.0.0-49",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "yjs",
|
"name": "yjs",
|
||||||
"version": "13.0.0-47",
|
"version": "13.0.0-49",
|
||||||
"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",
|
||||||
|
|||||||
14
src/Binding/Binding.js
Normal file
14
src/Binding/Binding.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
0
src/Binding/DomBinding.js
Normal file
0
src/Binding/DomBinding.js
Normal file
45
src/Binding/TextareaBinding.js
Normal file
45
src/Binding/TextareaBinding.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -55,14 +55,16 @@ export default class Item {
|
|||||||
/**
|
/**
|
||||||
* Copy the effect of struct
|
* Copy the effect of struct
|
||||||
*/
|
*/
|
||||||
_copy () {
|
_copy (undeleteChildren, copyPosition) {
|
||||||
let struct = new this.constructor()
|
let struct = new this.constructor()
|
||||||
struct._origin = this._left
|
if (copyPosition) {
|
||||||
struct._left = this._left
|
struct._origin = this._left
|
||||||
struct._right = this
|
struct._left = this._left
|
||||||
struct._right_origin = this
|
struct._right = this
|
||||||
struct._parent = this._parent
|
struct._right_origin = this
|
||||||
struct._parentSub = this._parentSub
|
struct._parent = this._parent
|
||||||
|
struct._parentSub = this._parentSub
|
||||||
|
}
|
||||||
return struct
|
return struct
|
||||||
}
|
}
|
||||||
get _lastId () {
|
get _lastId () {
|
||||||
@@ -113,9 +115,11 @@ 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 userState = selfID === null ? 0 : y.ss.getState(selfID.user)
|
const user = selfID === null ? y.userID : 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) {
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ export default class ItemJSON extends Item {
|
|||||||
super()
|
super()
|
||||||
this._content = null
|
this._content = null
|
||||||
}
|
}
|
||||||
_copy () {
|
_copy (undeleteChildren, copyPosition) {
|
||||||
let struct = super._copy()
|
let struct = super._copy(undeleteChildren, copyPosition)
|
||||||
struct._content = this._content
|
struct._content = this._content
|
||||||
return struct
|
return struct
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ export default class ItemString extends Item {
|
|||||||
super()
|
super()
|
||||||
this._content = null
|
this._content = null
|
||||||
}
|
}
|
||||||
_copy () {
|
_copy (undeleteChildren, copyPosition) {
|
||||||
let struct = super._copy()
|
let struct = super._copy(undeleteChildren, copyPosition)
|
||||||
struct._content = this._content
|
struct._content = this._content
|
||||||
return struct
|
return struct
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,15 +79,16 @@ export default class Type extends Item {
|
|||||||
type = type._parent
|
type = type._parent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_copy (undeleteChildren) {
|
_copy (undeleteChildren, copyPosition) {
|
||||||
let copy = super._copy()
|
let copy = super._copy(undeleteChildren, copyPosition)
|
||||||
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)
|
let _item = value._copy(undeleteChildren, false)
|
||||||
_item._parent = copy
|
_item._parent = copy
|
||||||
map.set(key, value._copy(undeleteChildren))
|
_item._parentSub = key
|
||||||
|
map.set(key, _item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let prevUndeleted = null
|
let prevUndeleted = null
|
||||||
@@ -95,7 +96,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)
|
let _item = item._copy(undeleteChildren, false)
|
||||||
_item._left = prevUndeleted
|
_item._left = prevUndeleted
|
||||||
_item._origin = prevUndeleted
|
_item._origin = prevUndeleted
|
||||||
_item._right = null
|
_item._right = null
|
||||||
@@ -133,7 +134,6 @@ 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
|
||||||
|
|||||||
@@ -9,17 +9,21 @@ 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 () {
|
||||||
const target = this.target
|
if (this._addedElements === null) {
|
||||||
const transaction = this._transaction
|
const target = this.target
|
||||||
const addedElements = new Set()
|
const transaction = this._transaction
|
||||||
transaction.newTypes.forEach(function (type) {
|
const addedElements = new Set()
|
||||||
if (type._parent === target && !transaction.deletedStructs.has(type)) {
|
transaction.newTypes.forEach(function (type) {
|
||||||
addedElements.add(type)
|
if (type._parent === target && !transaction.deletedStructs.has(type)) {
|
||||||
}
|
addedElements.add(type)
|
||||||
})
|
}
|
||||||
return addedElements
|
})
|
||||||
|
this._addedElements = addedElements
|
||||||
|
}
|
||||||
|
return this._addedElements
|
||||||
}
|
}
|
||||||
get removedElements () {
|
get removedElements () {
|
||||||
const target = this.target
|
const target = this.target
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ export default class YXmlElement extends YXmlFragment {
|
|||||||
this._domFilter = arg2
|
this._domFilter = arg2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_copy (undeleteChildren) {
|
_copy (undeleteChildren, copyPosition) {
|
||||||
let struct = super._copy(undeleteChildren)
|
let struct = super._copy(undeleteChildren, copyPosition)
|
||||||
struct.nodeName = this.nodeName
|
struct.nodeName = this.nodeName
|
||||||
return struct
|
return struct
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,18 +152,20 @@ export default class YXmlFragment extends YArray {
|
|||||||
attributes.set(key, attrs[key])
|
attributes.set(key, attrs[key])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let result = this._domFilter(this.nodeName, new Map(attributes))
|
this._y.transact(() => {
|
||||||
if (result === null) {
|
let result = this._domFilter(this.nodeName, new Map(attributes))
|
||||||
this._delete(this._y)
|
if (result === null) {
|
||||||
} else {
|
this._delete(this._y)
|
||||||
attributes.forEach((value, key) => {
|
} else {
|
||||||
if (!result.has(key)) {
|
attributes.forEach((value, key) => {
|
||||||
this.removeAttribute(key)
|
if (!result.has(key)) {
|
||||||
}
|
this.removeAttribute(key)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.forEach(xml => {
|
||||||
|
xml.setDomFilter(f)
|
||||||
})
|
})
|
||||||
}
|
|
||||||
this.forEach(xml => {
|
|
||||||
xml.setDomFilter(f)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_callObserver (transaction, parentSubs, remote) {
|
_callObserver (transaction, parentSubs, remote) {
|
||||||
|
|||||||
@@ -14,6 +14,11 @@ 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) {
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ function applyReverseOperation (y, scope, reverseBuffer) {
|
|||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
performedUndo = true
|
performedUndo = true
|
||||||
op = op._copy(undoOp.deletedStructs)
|
op = op._copy(undoOp.deletedStructs, true)
|
||||||
op._integrate(y)
|
op._integrate(y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/Y.js
10
src/Y.js
@@ -22,6 +22,10 @@ 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()
|
||||||
@@ -197,13 +201,17 @@ 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
|
integrateRemoteStructs,
|
||||||
|
toBinary,
|
||||||
|
fromBinary
|
||||||
}
|
}
|
||||||
|
|
||||||
Y.debug = debug
|
Y.debug = debug
|
||||||
|
|||||||
158
y.node.js
158
y.node.js
@@ -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-47
|
* @version v13.0.0-49
|
||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -1344,14 +1344,16 @@ class Item {
|
|||||||
/**
|
/**
|
||||||
* Copy the effect of struct
|
* Copy the effect of struct
|
||||||
*/
|
*/
|
||||||
_copy () {
|
_copy (undeleteChildren, copyPosition) {
|
||||||
let struct = new this.constructor();
|
let struct = new this.constructor();
|
||||||
struct._origin = this._left;
|
if (copyPosition) {
|
||||||
struct._left = this._left;
|
struct._origin = this._left;
|
||||||
struct._right = this;
|
struct._left = this._left;
|
||||||
struct._right_origin = this;
|
struct._right = this;
|
||||||
struct._parent = this._parent;
|
struct._right_origin = this;
|
||||||
struct._parentSub = this._parentSub;
|
struct._parent = this._parent;
|
||||||
|
struct._parentSub = this._parentSub;
|
||||||
|
}
|
||||||
return struct
|
return struct
|
||||||
}
|
}
|
||||||
get _lastId () {
|
get _lastId () {
|
||||||
@@ -1402,9 +1404,11 @@ 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 userState = selfID === null ? 0 : y.ss.getState(selfID.user);
|
const user = selfID === null ? y.userID : 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) {
|
||||||
@@ -1716,15 +1720,16 @@ class Type extends Item {
|
|||||||
type = type._parent;
|
type = type._parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_copy (undeleteChildren) {
|
_copy (undeleteChildren, copyPosition) {
|
||||||
let copy = super._copy();
|
let copy = super._copy(undeleteChildren, copyPosition);
|
||||||
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);
|
let _item = value._copy(undeleteChildren, false);
|
||||||
_item._parent = copy;
|
_item._parent = copy;
|
||||||
map.set(key, value._copy(undeleteChildren));
|
_item._parentSub = key;
|
||||||
|
map.set(key, _item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let prevUndeleted = null;
|
let prevUndeleted = null;
|
||||||
@@ -1732,7 +1737,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);
|
let _item = item._copy(undeleteChildren, false);
|
||||||
_item._left = prevUndeleted;
|
_item._left = prevUndeleted;
|
||||||
_item._origin = prevUndeleted;
|
_item._origin = prevUndeleted;
|
||||||
_item._right = null;
|
_item._right = null;
|
||||||
@@ -1770,7 +1775,6 @@ 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
|
||||||
@@ -1813,8 +1817,8 @@ class ItemJSON extends Item {
|
|||||||
super();
|
super();
|
||||||
this._content = null;
|
this._content = null;
|
||||||
}
|
}
|
||||||
_copy () {
|
_copy (undeleteChildren, copyPosition) {
|
||||||
let struct = super._copy();
|
let struct = super._copy(undeleteChildren, copyPosition);
|
||||||
struct._content = this._content;
|
struct._content = this._content;
|
||||||
return struct
|
return struct
|
||||||
}
|
}
|
||||||
@@ -1875,8 +1879,8 @@ class ItemString extends Item {
|
|||||||
super();
|
super();
|
||||||
this._content = null;
|
this._content = null;
|
||||||
}
|
}
|
||||||
_copy () {
|
_copy (undeleteChildren, copyPosition) {
|
||||||
let struct = super._copy();
|
let struct = super._copy(undeleteChildren, copyPosition);
|
||||||
struct._content = this._content;
|
struct._content = this._content;
|
||||||
return struct
|
return struct
|
||||||
}
|
}
|
||||||
@@ -1944,17 +1948,21 @@ 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 () {
|
||||||
const target = this.target;
|
if (this._addedElements === null) {
|
||||||
const transaction = this._transaction;
|
const target = this.target;
|
||||||
const addedElements = new Set();
|
const transaction = this._transaction;
|
||||||
transaction.newTypes.forEach(function (type) {
|
const addedElements = new Set();
|
||||||
if (type._parent === target && !transaction.deletedStructs.has(type)) {
|
transaction.newTypes.forEach(function (type) {
|
||||||
addedElements.add(type);
|
if (type._parent === target && !transaction.deletedStructs.has(type)) {
|
||||||
}
|
addedElements.add(type);
|
||||||
});
|
}
|
||||||
return addedElements
|
});
|
||||||
|
this._addedElements = addedElements;
|
||||||
|
}
|
||||||
|
return this._addedElements
|
||||||
}
|
}
|
||||||
get removedElements () {
|
get removedElements () {
|
||||||
const target = this.target;
|
const target = this.target;
|
||||||
@@ -2907,18 +2915,20 @@ class YXmlFragment extends YArray {
|
|||||||
attributes.set(key, attrs[key]);
|
attributes.set(key, attrs[key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let result = this._domFilter(this.nodeName, new Map(attributes));
|
this._y.transact(() => {
|
||||||
if (result === null) {
|
let result = this._domFilter(this.nodeName, new Map(attributes));
|
||||||
this._delete(this._y);
|
if (result === null) {
|
||||||
} else {
|
this._delete(this._y);
|
||||||
attributes.forEach((value, key) => {
|
} else {
|
||||||
if (!result.has(key)) {
|
attributes.forEach((value, key) => {
|
||||||
this.removeAttribute(key);
|
if (!result.has(key)) {
|
||||||
}
|
this.removeAttribute(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.forEach(xml => {
|
||||||
|
xml.setDomFilter(f);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
this.forEach(xml => {
|
|
||||||
xml.setDomFilter(f);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_callObserver (transaction, parentSubs, remote) {
|
_callObserver (transaction, parentSubs, remote) {
|
||||||
@@ -3123,8 +3133,8 @@ class YXmlElement extends YXmlFragment {
|
|||||||
this._domFilter = arg2;
|
this._domFilter = arg2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_copy (undeleteChildren) {
|
_copy (undeleteChildren, copyPosition) {
|
||||||
let struct = super._copy(undeleteChildren);
|
let struct = super._copy(undeleteChildren, copyPosition);
|
||||||
struct.nodeName = this.nodeName;
|
struct.nodeName = this.nodeName;
|
||||||
return struct
|
return struct
|
||||||
}
|
}
|
||||||
@@ -3262,6 +3272,11 @@ 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) {
|
||||||
@@ -3702,7 +3717,7 @@ function applyReverseOperation (y, scope, reverseBuffer) {
|
|||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
performedUndo = true;
|
performedUndo = true;
|
||||||
op = op._copy(undoOp.deletedStructs);
|
op = op._copy(undoOp.deletedStructs, true);
|
||||||
op._integrate(y);
|
op._integrate(y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4748,6 +4763,59 @@ class AbstractPersistence {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
@@ -4923,13 +4991,17 @@ 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
|
integrateRemoteStructs,
|
||||||
|
toBinary,
|
||||||
|
fromBinary
|
||||||
};
|
};
|
||||||
|
|
||||||
Y$1.debug = browser;
|
Y$1.debug = browser;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user