diff .cms/lib/codemirror/src/util/operation_group.js @ 0:78edf6b517a0 draft

24.10
author Coffee CMS <info@coffee-cms.ru>
date Fri, 11 Oct 2024 22:40:23 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.cms/lib/codemirror/src/util/operation_group.js	Fri Oct 11 22:40:23 2024 +0000
@@ -0,0 +1,72 @@
+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]()
+}