73 lines
2.1 KiB
JavaScript
73 lines
2.1 KiB
JavaScript
|
import { getHandlers } from "./event.js"
|
||
|
|
||
|
let operationGroup = null
|
||
|
|
||
|
export function pushOperation(op) {
|
||
|
if (operationGroup) {
|
||
|
operationGroup.ops.push(op)
|
||
|
} else {
|
||
|
op.ownsGroup = operationGroup = {
|
||
|
ops: [op],
|
||
|
delayedCallbacks: []
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function fireCallbacksForOps(group) {
|
||
|
// Calls delayed callbacks and cursorActivity handlers until no
|
||
|
// new ones appear
|
||
|
let callbacks = group.delayedCallbacks, i = 0
|
||
|
do {
|
||
|
for (; i < callbacks.length; i++)
|
||
|
callbacks[i].call(null)
|
||
|
for (let j = 0; j < group.ops.length; j++) {
|
||
|
let op = group.ops[j]
|
||
|
if (op.cursorActivityHandlers)
|
||
|
while (op.cursorActivityCalled < op.cursorActivityHandlers.length)
|
||
|
op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm)
|
||
|
}
|
||
|
} while (i < callbacks.length)
|
||
|
}
|
||
|
|
||
|
export function finishOperation(op, endCb) {
|
||
|
let group = op.ownsGroup
|
||
|
if (!group) return
|
||
|
|
||
|
try { fireCallbacksForOps(group) }
|
||
|
finally {
|
||
|
operationGroup = null
|
||
|
endCb(group)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let orphanDelayedCallbacks = null
|
||
|
|
||
|
// Often, we want to signal events at a point where we are in the
|
||
|
// middle of some work, but don't want the handler to start calling
|
||
|
// other methods on the editor, which might be in an inconsistent
|
||
|
// state or simply not expect any other events to happen.
|
||
|
// signalLater looks whether there are any handlers, and schedules
|
||
|
// them to be executed when the last operation ends, or, if no
|
||
|
// operation is active, when a timeout fires.
|
||
|
export function signalLater(emitter, type /*, values...*/) {
|
||
|
let arr = getHandlers(emitter, type)
|
||
|
if (!arr.length) return
|
||
|
let args = Array.prototype.slice.call(arguments, 2), list
|
||
|
if (operationGroup) {
|
||
|
list = operationGroup.delayedCallbacks
|
||
|
} else if (orphanDelayedCallbacks) {
|
||
|
list = orphanDelayedCallbacks
|
||
|
} else {
|
||
|
list = orphanDelayedCallbacks = []
|
||
|
setTimeout(fireOrphanDelayed, 0)
|
||
|
}
|
||
|
for (let i = 0; i < arr.length; ++i)
|
||
|
list.push(() => arr[i].apply(null, args))
|
||
|
}
|
||
|
|
||
|
function fireOrphanDelayed() {
|
||
|
let delayed = orphanDelayedCallbacks
|
||
|
orphanDelayedCallbacks = null
|
||
|
for (let i = 0; i < delayed.length; ++i) delayed[i]()
|
||
|
}
|