big documentation update - all public functions and classes are documented now
This commit is contained in:
@@ -1,22 +1,56 @@
|
||||
|
||||
/**
|
||||
* General event handler implementation.
|
||||
*/
|
||||
export default class EventHandler {
|
||||
constructor () {
|
||||
this.eventListeners = []
|
||||
}
|
||||
|
||||
/**
|
||||
* To prevent memory leaks, call this method when the eventListeners won't be
|
||||
* used anymore.
|
||||
*/
|
||||
destroy () {
|
||||
this.eventListeners = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an event listener that is called when
|
||||
* {@link EventHandler#callEventListeners} is called.
|
||||
*
|
||||
* @param {Function} f The event handler.
|
||||
*/
|
||||
addEventListener (f) {
|
||||
this.eventListeners.push(f)
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an event listener.
|
||||
*
|
||||
* @param {Function} f The event handler that was added with
|
||||
* {@link EventHandler#addEventListener}
|
||||
*/
|
||||
removeEventListener (f) {
|
||||
this.eventListeners = this.eventListeners.filter(function (g) {
|
||||
return f !== g
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all event listeners.
|
||||
*/
|
||||
removeAllEventListeners () {
|
||||
this.eventListeners = []
|
||||
}
|
||||
|
||||
/**
|
||||
* Call all event listeners that were added via
|
||||
* {@link EventHandler#addEventListener}.
|
||||
*
|
||||
* @param {Transaction} transaction The transaction object // TODO: do we need this?
|
||||
* @param {YEvent} event An event object that describes the change on a type.
|
||||
*/
|
||||
callEventListeners (transaction, event) {
|
||||
for (var i = 0; i < this.eventListeners.length; i++) {
|
||||
try {
|
||||
|
||||
@@ -1,8 +1,19 @@
|
||||
|
||||
/**
|
||||
* Handles named events.
|
||||
*/
|
||||
export default class NamedEventHandler {
|
||||
constructor () {
|
||||
this._eventListener = new Map()
|
||||
this._stateListener = new Map()
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Returns all listeners that listen to a specified name.
|
||||
*
|
||||
* @param {String} name The query event name.
|
||||
*/
|
||||
_getListener (name) {
|
||||
let listeners = this._eventListener.get(name)
|
||||
if (listeners === undefined) {
|
||||
@@ -14,14 +25,34 @@ export default class NamedEventHandler {
|
||||
}
|
||||
return listeners
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a named event listener. The listener is removed after it has been
|
||||
* called once.
|
||||
*
|
||||
* @param {String} name The event name to listen to.
|
||||
* @param {Function} f The function that is executed when the event is fired.
|
||||
*/
|
||||
once (name, f) {
|
||||
let listeners = this._getListener(name)
|
||||
listeners.once.add(f)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a named event listener.
|
||||
*
|
||||
* @param {String} name The event name to listen to.
|
||||
* @param {Function} f The function that is executed when the event is fired.
|
||||
*/
|
||||
on (name, f) {
|
||||
let listeners = this._getListener(name)
|
||||
listeners.on.add(f)
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Init the saved state for an event name.
|
||||
*/
|
||||
_initStateListener (name) {
|
||||
let state = this._stateListener.get(name)
|
||||
if (state === undefined) {
|
||||
@@ -33,9 +64,20 @@ export default class NamedEventHandler {
|
||||
}
|
||||
return state
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Promise that is resolved when the event name is called.
|
||||
* The Promise is immediately resolved when the event name was called in the
|
||||
* past.
|
||||
*/
|
||||
when (name) {
|
||||
return this._initStateListener(name).promise
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an event listener that was registered with either
|
||||
* {@link EventHandler#on} or {@link EventHandler#once}.
|
||||
*/
|
||||
off (name, f) {
|
||||
if (name == null || f == null) {
|
||||
throw new Error('You must specify event name and function!')
|
||||
@@ -46,6 +88,14 @@ export default class NamedEventHandler {
|
||||
listener.once.delete(f)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit a named event. All registered event listeners that listen to the
|
||||
* specified name will receive the event.
|
||||
*
|
||||
* @param {String} name The event name.
|
||||
* @param {Array} args The arguments that are applied to the event listener.
|
||||
*/
|
||||
emit (name, ...args) {
|
||||
this._initStateListener(name).resolve()
|
||||
const listener = this._eventListener.get(name)
|
||||
|
||||
@@ -64,7 +64,15 @@ function applyReverseOperation (y, scope, reverseBuffer) {
|
||||
return performedUndo
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a history of locally applied operations. The UndoManager handles the
|
||||
* undoing and redoing of locally created changes.
|
||||
*/
|
||||
export default class UndoManager {
|
||||
/**
|
||||
* @param {YType} scope The scope on which to listen for changes.
|
||||
* @param {Object} options Optionally provided configuration.
|
||||
*/
|
||||
constructor (scope, options = {}) {
|
||||
this.options = options
|
||||
options.captureTimeout = options.captureTimeout == null ? 500 : options.captureTimeout
|
||||
@@ -101,12 +109,20 @@ export default class UndoManager {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Undo the last locally created change.
|
||||
*/
|
||||
undo () {
|
||||
this._undoing = true
|
||||
const performedUndo = applyReverseOperation(this.y, this._scope, this._undoBuffer)
|
||||
this._undoing = false
|
||||
return performedUndo
|
||||
}
|
||||
|
||||
/**
|
||||
* Redo the last locally created change.
|
||||
*/
|
||||
redo () {
|
||||
this._redoing = true
|
||||
const performedRedo = applyReverseOperation(this.y, this._scope, this._redoBuffer)
|
||||
|
||||
@@ -1,9 +1,27 @@
|
||||
|
||||
/**
|
||||
* YEvent describes the changes on a YType.
|
||||
*/
|
||||
export default class YEvent {
|
||||
/**
|
||||
* @param {YType} target The changed type.
|
||||
*/
|
||||
constructor (target) {
|
||||
this.target = target
|
||||
this.currentTarget = target
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the path from `y` to the changed type.
|
||||
*
|
||||
* The following property holds:
|
||||
* @example
|
||||
* let type = y
|
||||
* event.path.forEach(function (dir) {
|
||||
* type = type.get(dir)
|
||||
* })
|
||||
* type === event.target // => true
|
||||
*/
|
||||
get path () {
|
||||
const path = []
|
||||
let type = this.target
|
||||
|
||||
@@ -1,7 +1,43 @@
|
||||
import ID from './ID.js'
|
||||
import RootID from './RootID.js'
|
||||
|
||||
/**
|
||||
* A relative position that is based on the Yjs model. In contrast to an
|
||||
* absolute position (position by index), the relative position can be
|
||||
* recomputed when remote changes are received. For example:
|
||||
*
|
||||
* ```Insert(0, 'x')('a|bc') = 'xa|bc'``` Where | is the cursor position.
|
||||
*
|
||||
* A relative cursor position can be obtained with the function
|
||||
* {@link getRelativePosition} and it can be transformed to an absolute position
|
||||
* with {@link fromRelativePosition}.
|
||||
*
|
||||
* Pro tip: Use this to implement shared cursor locations in YText or YXml!
|
||||
* The relative position is {@link encodable}, so you can send it to other
|
||||
* clients.
|
||||
*
|
||||
* @example
|
||||
* // Current cursor position is at position 10
|
||||
* let relativePosition = getRelativePosition(yText, 10)
|
||||
* // modify yText
|
||||
* yText.insert(0, 'abc')
|
||||
* yText.delete(3, 10)
|
||||
* // Compute the cursor position
|
||||
* let absolutePosition = fromRelativePosition(y, relativePosition)
|
||||
* absolutePosition.type // => yText
|
||||
* console.log('cursor location is ' + absolutePosition.offset) // => cursor location is 3
|
||||
*
|
||||
* @typedef {encodable} RelativePosition
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a relativePosition based on a absolute position.
|
||||
*
|
||||
* @param {YType} type The base type (e.g. YText or YArray).
|
||||
* @param {Integer} offset The absolute position.
|
||||
*/
|
||||
export function getRelativePosition (type, offset) {
|
||||
// TODO: rename to createRelativePosition
|
||||
let t = type._start
|
||||
while (t !== null) {
|
||||
if (t._deleted === false) {
|
||||
@@ -15,6 +51,20 @@ export function getRelativePosition (type, offset) {
|
||||
return ['endof', type._id.user, type._id.clock || null, type._id.name || null, type._id.type || null]
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} AbsolutePosition The result of {@link fromRelativePosition}
|
||||
* @property {YType} type The type on which to apply the absolute position.
|
||||
* @property {Integer} offset The absolute offset.r
|
||||
*/
|
||||
|
||||
/**
|
||||
* Transforms a relative position back to a relative position.
|
||||
*
|
||||
* @param {Y} y The Yjs instance in which to query for the absolute position.
|
||||
* @param {RelativePosition} rpos The relative position.
|
||||
* @return {AbsolutePosition} The absolute position in the Yjs model
|
||||
* (type + offset).
|
||||
*/
|
||||
export function fromRelativePosition (y, rpos) {
|
||||
if (rpos[0] === 'endof') {
|
||||
let id
|
||||
|
||||
Reference in New Issue
Block a user