diff --git a/examples/ace/index.html b/examples/ace/index.html index c1c5242e..3b9404b6 100644 --- a/examples/ace/index.html +++ b/examples/ace/index.html @@ -24,7 +24,8 @@
- + + diff --git a/examples/ace/index.js b/examples/ace/index.js index 8228968a..85487bc2 100644 --- a/examples/ace/index.js +++ b/examples/ace/index.js @@ -1,24 +1,17 @@ /* global Y, ace */ -Y({ - db: { - name: 'memory' - }, +let y = new Y('ace-example', { connector: { name: 'websockets-client', - room: 'ace-example' - }, - sourceDir: '/bower_components', - share: { - ace: 'Text' // y.share.textarea is of type Y.Text + url: 'http://127.0.0.1:1234' } -}).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) diff --git a/examples/chat/index.html b/examples/chat/index.html index 20f5417f..228c7e75 100644 --- a/examples/chat/index.html +++ b/examples/chat/index.html @@ -13,7 +13,7 @@ - + diff --git a/examples/chat/index.js b/examples/chat/index.js index c2cdc8c2..6e040fda 100644 --- a/examples/chat/index.js +++ b/examples/chat/index.js @@ -1,10 +1,9 @@ /* global Y */ -// initialize a shared object. This function call returns a promise! -var y = new Y({ +let y = new Y('chat-example', { connector: { 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)) chatcontainer.insertBefore(p, chatcontainer.children[position] || null) } + // This function makes sure that only 7 messages exist in the chat history. // The rest is deleted function cleanupChat () { @@ -30,23 +30,17 @@ function cleanupChat () { chatprotocol.delete(0, chatprotocol.length - 7) } } +cleanupChat() + // Insert the initial content chatprotocol.toArray().forEach(appendMessage) -cleanupChat() // whenever content changes, make sure to reflect the changes in the DOM 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 cleanupChat() + chatcontainer.innerHTML = '' + chatprotocol.toArray().forEach(appendMessage) }) document.querySelector('#chatform').onsubmit = function (event) { // the form is submitted diff --git a/examples/codemirror/index.html b/examples/codemirror/index.html index eef60f2f..2233240e 100644 --- a/examples/codemirror/index.html +++ b/examples/codemirror/index.html @@ -5,7 +5,8 @@
- + + diff --git a/examples/codemirror/index.js b/examples/codemirror/index.js index b307579b..ff216191 100644 --- a/examples/codemirror/index.js +++ b/examples/codemirror/index.js @@ -1,24 +1,16 @@ /* global Y, CodeMirror */ -// initialize a shared object. This function call returns a promise! -Y({ - db: { - name: 'memory' - }, +let y = new Y('codemirror-example', { connector: { name: 'websockets-client', - room: 'codemirror-example' - }, - sourceDir: '/bower_components', - share: { - codemirror: 'Text' // y.share.codemirror is of type Y.Text + url: 'http://127.0.0.1:1234' } -}).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) diff --git a/examples/drawing/index.html b/examples/drawing/index.html index f2717a12..a9dda2c8 100644 --- a/examples/drawing/index.html +++ b/examples/drawing/index.html @@ -12,7 +12,8 @@ - + + diff --git a/examples/drawing/index.js b/examples/drawing/index.js index ecb323ed..26d9c3f4 100644 --- a/examples/drawing/index.js +++ b/examples/drawing/index.js @@ -1,11 +1,9 @@ /* globals Y, d3 */ -let y = new Y({ +let y = new Y('drawing-example', { connector: { name: 'websockets-client', - url: 'http://127.0.0.1:1234', - room: 'drawing-example' - // maxBufferLength: 100 + url: 'http://127.0.0.1:1234' } }) diff --git a/examples/html-editor-drawing-hook/index.html b/examples/html-editor-drawing-hook/index.html index f30d883b..50166af5 100644 --- a/examples/html-editor-drawing-hook/index.html +++ b/examples/html-editor-drawing-hook/index.html @@ -1,7 +1,8 @@ - + + - + + + + diff --git a/examples/indexeddb/index.js b/examples/indexeddb/index.js index 9567497b..da3947f7 100644 --- a/examples/indexeddb/index.js +++ b/examples/indexeddb/index.js @@ -7,12 +7,13 @@ const connector = { 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 var editor = CodeMirror(document.querySelector('#codeMirrorContainer'), { mode: 'javascript', lineNumbers: true }) -y.share.codemirror.bindCodeMirror(editor) + +y.define('codemirror', Y.Text).bindCodeMirror(editor) diff --git a/examples/infiniteyjs/index.html b/examples/infiniteyjs/index.html index dd4a67a9..7495c9db 100644 --- a/examples/infiniteyjs/index.html +++ b/examples/infiniteyjs/index.html @@ -10,7 +10,7 @@ .one { grid-column: 1 ; } - .two { + .two { grid-column: 2; } .three { @@ -49,10 +49,7 @@ - - - - + diff --git a/examples/infiniteyjs/index.js b/examples/infiniteyjs/index.js index 05e7dc85..f320fa4e 100644 --- a/examples/infiniteyjs/index.js +++ b/examples/infiniteyjs/index.js @@ -1,64 +1,38 @@ /* global Y */ -Y({ - 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')) +function bindYjsInstance (y, suffix) { + y.define('textarea', Y.Text).bind(document.getElementById('textarea' + suffix)) y.connector.socket.on('connection', function () { - document.getElementById('container2').removeAttribute('disconnected') + document.getElementById('container' + suffix).removeAttribute('disconnected') }) y.connector.socket.on('disconnect', function () { - document.getElementById('container2').setAttribute('disconnected', true) + document.getElementById('container' + suffix).setAttribute('disconnected', true) }) -}) +} -Y({ - db: { - name: 'memory' - }, +let y1 = new Y('infinite-example', { connector: { name: 'websockets-client', - room: 'Textarea-example', - url: 'https://yjs-v13-third.herokuapp.com/' - }, - share: { - textarea: 'Text' + url: 'http://127.0.0.1:1234' } -}).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') diff --git a/examples/jigsaw/index.html b/examples/jigsaw/index.html index 61fc6da0..6030ca53 100644 --- a/examples/jigsaw/index.html +++ b/examples/jigsaw/index.html @@ -17,9 +17,7 @@ - - - + diff --git a/examples/jigsaw/index.js b/examples/jigsaw/index.js index 9865267f..2142757d 100644 --- a/examples/jigsaw/index.js +++ b/examples/jigsaw/index.js @@ -1,74 +1,67 @@ -/* @flow */ /* global Y, d3 */ -// initialize a shared object. This function call returns a promise! -Y({ - db: { - name: 'memory' - }, +let y = new Y('jigsaw-example', { connector: { name: 'websockets-client', - room: 'Puzzle-example', - url: 'http://localhost:1234' - }, - share: { - piece1: 'Map', - piece2: 'Map', - piece3: 'Map', - piece4: 'Map' + url: 'http://127.0.0.1:1234' } -}).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] - var pieces = d3.select(document.querySelector('#puzzle-example')).selectAll('path').data(data) +let jigsaw = y.define('jigsaw', Y.Map) +window.yJigsaw = y - pieces - .classed('draggable', true) - .attr('transform', function (piece) { - var translation = piece.get('translation') || {x: 0, y: 0} - return 'translate(' + translation.x + ',' + translation.y + ')' - }).call(drag) +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 + jigsaw.set(piece, {x: x, y: y}) + }) - data.forEach(function (piece) { - piece.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('translation') || {x: 0, y: 0} - return 'translate(' + translation.x + ',' + translation.y + ')' - }) - }) +var data = ['piece1', 'piece2', 'piece3', 'piece4'] +var pieces = d3.select(document.querySelector('#puzzle-example')).selectAll('path').data(data) + +pieces + .classed('draggable', true) + .attr('transform', function (piece) { + var translation = piece.get('translation') || {x: 0, y: 0} + 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 + ')' + }) }) }) diff --git a/examples/monaco/index.html b/examples/monaco/index.html index 151ca7b3..c4ef9e71 100644 --- a/examples/monaco/index.html +++ b/examples/monaco/index.html @@ -13,8 +13,8 @@ width: 100%; } - - + + diff --git a/examples/monaco/index.js b/examples/monaco/index.js index 999fe4a3..37bd3833 100644 --- a/examples/monaco/index.js +++ b/examples/monaco/index.js @@ -2,29 +2,22 @@ require.config({ paths: { 'vs': '../node_modules/monaco-editor/min/vs' } }) -require(['vs/editor/editor.main'], function () { - // 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 - var editor = monaco.editor.create(document.getElementById('monacoContainer'), { - language: 'javascript' - }) - - // Bind to y.share.monaco - y.share.monaco.bindMonaco(editor) - }) +let y = new Y('monaco-example', { + connector: { + name: 'websockets-client', + url: 'http://127.0.0.1:1234' + } +}) + + +require(['vs/editor/editor.main'], function () { + window.yMonaco = y + + // Create Monaco editor + var editor = monaco.editor.create(document.getElementById('monacoContainer'), { + language: 'javascript' + }) + + // Bind to y.share.monaco + y.define('monaco', Y.Text).bindMonaco(editor) }) diff --git a/examples/quill/index.html b/examples/quill/index.html index bec4cccc..4a8128b3 100644 --- a/examples/quill/index.html +++ b/examples/quill/index.html @@ -26,10 +26,7 @@ --> - - - - + diff --git a/examples/textarea/index.html b/examples/textarea/index.html index 939a90c5..36774509 100644 --- a/examples/textarea/index.html +++ b/examples/textarea/index.html @@ -3,9 +3,7 @@ - - - + diff --git a/examples/textarea/index.js b/examples/textarea/index.js index 37922d2b..ab1cbbf8 100644 --- a/examples/textarea/index.js +++ b/examples/textarea/index.js @@ -1,23 +1,17 @@ /* global Y */ -// initialize a shared object. This function call returns a promise! -Y({ - db: { - name: 'memory' - }, +let y = new Y('textarea-example', { connector: { name: 'websockets-client', - 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')) + url: 'http://127.0.0.1:1234' + } }) + +window.yTextarea = y + +// bind the textarea to a shared text element +let type = y.define('textarea', Y.Text) +let textarea = document.getElementById('textfield') +let binding = new Y.TextareaBinding(type, textarea) + +// binding.destroy() diff --git a/examples/xml/index.html b/examples/xml/index.html index 4d3ff03a..366ed69a 100644 --- a/examples/xml/index.html +++ b/examples/xml/index.html @@ -3,7 +3,8 @@ - + + diff --git a/examples/xml/index.js b/examples/xml/index.js index 46edfc05..b6c7596a 100644 --- a/examples/xml/index.js +++ b/examples/xml/index.js @@ -1,23 +1,13 @@ /* global Y */ -// initialize a shared object. This function call returns a promise! -Y({ - db: { - name: 'memory' - }, +let y = new Y('xml-example', { connector: { name: 'websockets-client', - // 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" + url: 'http://127.0.0.1:1234' } -}).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) diff --git a/src/Struct/Item.js b/src/Struct/Item.js index 38c0c1c2..d872482b 100644 --- a/src/Struct/Item.js +++ b/src/Struct/Item.js @@ -113,9 +113,11 @@ export default class Item { * - Check if this is struct deleted */ _integrate (y) { + y._transaction.newTypes.add(this) const parent = this._parent 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) { this._id = y.ss.getNextID(this._length) } else if (selfID.user === RootFakeUserID) { diff --git a/src/Struct/Type.js b/src/Struct/Type.js index 60828f9b..2f02184e 100644 --- a/src/Struct/Type.js +++ b/src/Struct/Type.js @@ -133,7 +133,6 @@ export default class Type extends Item { this._deepEventHandler.removeEventListener(f) } _integrate (y) { - y._transaction.newTypes.add(this) super._integrate(y) this._y = y // when integrating children we must make sure to diff --git a/src/Type/YArray.js b/src/Type/YArray.js index da67de64..16c64034 100644 --- a/src/Type/YArray.js +++ b/src/Type/YArray.js @@ -9,17 +9,21 @@ class YArrayEvent extends YEvent { super(yarray) this.remote = remote this._transaction = transaction + this._addedElements = null } get addedElements () { - const target = this.target - const transaction = this._transaction - const addedElements = new Set() - transaction.newTypes.forEach(function (type) { - if (type._parent === target && !transaction.deletedStructs.has(type)) { - addedElements.add(type) - } - }) - return addedElements + if (this._addedElements === null) { + const target = this.target + const transaction = this._transaction + const addedElements = new Set() + transaction.newTypes.forEach(function (type) { + if (type._parent === target && !transaction.deletedStructs.has(type)) { + addedElements.add(type) + } + }) + this._addedElements = addedElements + } + return this._addedElements } get removedElements () { const target = this.target