From 94f6a0fd9cca1f54b727592780c659ada76f3116 Mon Sep 17 00:00:00 2001 From: Kevin Jahns Date: Mon, 29 Jan 2018 10:30:21 -0800 Subject: [PATCH] implement Y.*Binding approach --- examples/textarea/index.html | 2 +- examples/textarea/index.js | 4 +-- src/Binding/Binding.js | 15 ++++++++++++ src/Binding/DomBinding.js | 0 src/Binding/TextareaBinding.js | 45 ++++++++++++++++++++++++++++++++++ src/Y.js | 4 +++ 6 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 src/Binding/Binding.js create mode 100644 src/Binding/DomBinding.js create mode 100644 src/Binding/TextareaBinding.js diff --git a/examples/textarea/index.html b/examples/textarea/index.html index 36774509..0aaf8cc4 100644 --- a/examples/textarea/index.html +++ b/examples/textarea/index.html @@ -1,7 +1,7 @@ - + diff --git a/examples/textarea/index.js b/examples/textarea/index.js index ab1cbbf8..7ca18f62 100644 --- a/examples/textarea/index.js +++ b/examples/textarea/index.js @@ -11,7 +11,5 @@ window.yTextarea = y // bind the textarea to a shared text element let type = y.define('textarea', Y.Text) -let textarea = document.getElementById('textfield') +let textarea = document.querySelector('textarea') let binding = new Y.TextareaBinding(type, textarea) - -// binding.destroy() diff --git a/src/Binding/Binding.js b/src/Binding/Binding.js new file mode 100644 index 00000000..976b3b02 --- /dev/null +++ b/src/Binding/Binding.js @@ -0,0 +1,15 @@ + +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 + } +} diff --git a/src/Binding/DomBinding.js b/src/Binding/DomBinding.js new file mode 100644 index 00000000..e69de29b diff --git a/src/Binding/TextareaBinding.js b/src/Binding/TextareaBinding.js new file mode 100644 index 00000000..ab59f0f7 --- /dev/null +++ b/src/Binding/TextareaBinding.js @@ -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() + } +} diff --git a/src/Y.js b/src/Y.js index 03829b8a..282f234f 100644 --- a/src/Y.js +++ b/src/Y.js @@ -22,6 +22,8 @@ import { addStruct as addType } from './Util/structReferences.js' import debug from 'debug' import Transaction from './Transaction.js' +import TextareaBinding from './Binding/TextareaBinding.js' + export default class Y extends NamedEventHandler { constructor (room, opts, persistence) { super() @@ -197,6 +199,8 @@ Y.XmlFragment = YXmlFragment Y.XmlText = YXmlText Y.XmlHook = YXmlHook +Y.TextareaBinding = TextareaBinding + Y.utils = { BinaryDecoder, UndoManager,