73 lines
2.1 KiB
JavaScript
73 lines
2.1 KiB
JavaScript
/**
|
|
* @module bindings/textarea
|
|
*/
|
|
|
|
import { simpleDiff } from '../lib/diff.js'
|
|
import { getRelativePosition, fromRelativePosition } from '../utils/relativePosition.js'
|
|
import { createMutex } from '../lib/mutex.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)
|
|
})
|
|
}
|
|
|
|
/**
|
|
* A binding that binds a YText to a dom textarea.
|
|
*
|
|
* This binding is automatically destroyed when its parent is deleted.
|
|
*
|
|
* @example
|
|
* const textare = document.createElement('textarea')
|
|
* const type = y.define('textarea', Y.Text)
|
|
* const binding = new Y.QuillBinding(type, textarea)
|
|
*
|
|
*/
|
|
export class TextareaBinding {
|
|
constructor (textType, domTextarea) {
|
|
/**
|
|
* The Yjs type that is bound to `target`
|
|
* @type {Type}
|
|
*/
|
|
this.type = textType
|
|
/**
|
|
* The target that `type` is bound to.
|
|
* @type {*}
|
|
*/
|
|
this.target = domTextarea
|
|
/**
|
|
* @private
|
|
*/
|
|
this._mutualExclude = createMutex()
|
|
// 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)
|
|
this.type = null
|
|
this.target = null
|
|
}
|
|
}
|