File modules/editor/codemirror/src/display/operations.min.js
Last commit: Tue May 22 22:39:54 2018 +0200 Jan Dankert Fix für PHP 7.2: 'Object' darf nun nicht mehr als Klassennamen verwendet werden. AUCH NICHT IN EINEM NAMESPACE! WTF, wozu habe ich das in einen verfickten Namespace gepackt? Wozu soll der sonst da sein??? Amateure. Daher nun notgedrungen unbenannt in 'BaseObject'.
1 import { clipPos } from "../line/pos.js" 2 import { findMaxLine } from "../line/spans.js" 3 import { displayWidth, measureChar, scrollGap } from "../measurement/position_measurement.js" 4 import { signal } from "../util/event.js" 5 import { activeElt } from "../util/dom.js" 6 import { finishOperation, pushOperation } from "../util/operation_group.js" 7 8 import { ensureFocus } from "./focus.js" 9 import { measureForScrollbars, updateScrollbars } from "./scrollbars.js" 10 import { restartBlink } from "./selection.js" 11 import { maybeScrollWindow, scrollPosIntoView, setScrollLeft, setScrollTop } from "./scrolling.js" 12 import { DisplayUpdate, maybeClipScrollbars, postUpdateDisplay, setDocumentHeight, updateDisplayIfNeeded } from "./update_display.js" 13 import { updateHeightsInViewport } from "./update_lines.js" 14 15 // Operations are used to wrap a series of changes to the editor 16 // state in such a way that each change won't have to update the 17 // cursor and display (which would be awkward, slow, and 18 // error-prone). Instead, display updates are batched and then all 19 // combined and executed at once. 20 21 let nextOpId = 0 22 // Start a new operation. 23 export function startOperation(cm) { 24 cm.curOp = { 25 cm: cm, 26 viewChanged: false, // Flag that indicates that lines might need to be redrawn 27 startHeight: cm.doc.height, // Used to detect need to update scrollbar 28 forceUpdate: false, // Used to force a redraw 29 updateInput: null, // Whether to reset the input textarea 30 typing: false, // Whether this reset should be careful to leave existing text (for compositing) 31 changeObjs: null, // Accumulated changes, for firing change events 32 cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on 33 cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already 34 selectionChanged: false, // Whether the selection needs to be redrawn 35 updateMaxLine: false, // Set when the widest line needs to be determined anew 36 scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet 37 scrollToPos: null, // Used to scroll to a specific position 38 focus: false, 39 id: ++nextOpId // Unique ID 40 } 41 pushOperation(cm.curOp) 42 } 43 44 // Finish an operation, updating the display and signalling delayed events 45 export function endOperation(cm) { 46 let op = cm.curOp 47 finishOperation(op, group => { 48 for (let i = 0; i < group.ops.length; i++) 49 group.ops[i].cm.curOp = null 50 endOperations(group) 51 }) 52 } 53 54 // The DOM updates done when an operation finishes are batched so 55 // that the minimum number of relayouts are required. 56 function endOperations(group) { 57 let ops = group.ops 58 for (let i = 0; i < ops.length; i++) // Read DOM 59 endOperation_R1(ops[i]) 60 for (let i = 0; i < ops.length; i++) // Write DOM (maybe) 61 endOperation_W1(ops[i]) 62 for (let i = 0; i < ops.length; i++) // Read DOM 63 endOperation_R2(ops[i]) 64 for (let i = 0; i < ops.length; i++) // Write DOM (maybe) 65 endOperation_W2(ops[i]) 66 for (let i = 0; i < ops.length; i++) // Read DOM 67 endOperation_finish(ops[i]) 68 } 69 70 function endOperation_R1(op) { 71 let cm = op.cm, display = cm.display 72 maybeClipScrollbars(cm) 73 if (op.updateMaxLine) findMaxLine(cm) 74 75 op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null || 76 op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom || 77 op.scrollToPos.to.line >= display.viewTo) || 78 display.maxLineChanged && cm.options.lineWrapping 79 op.update = op.mustUpdate && 80 new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate) 81 } 82 83 function endOperation_W1(op) { 84 op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update) 85 } 86 87 function endOperation_R2(op) { 88 let cm = op.cm, display = cm.display 89 if (op.updatedDisplay) updateHeightsInViewport(cm) 90 91 op.barMeasure = measureForScrollbars(cm) 92 93 // If the max line changed since it was last measured, measure it, 94 // and ensure the document's width matches it. 95 // updateDisplay_W2 will use these properties to do the actual resizing 96 if (display.maxLineChanged && !cm.options.lineWrapping) { 97 op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3 98 cm.display.sizerWidth = op.adjustWidthTo 99 op.barMeasure.scrollWidth = 100 Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth) 101 op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm)) 102 } 103 104 if (op.updatedDisplay || op.selectionChanged) 105 op.preparedSelection = display.input.prepareSelection() 106 } 107 108 function endOperation_W2(op) { 109 let cm = op.cm 110 111 if (op.adjustWidthTo != null) { 112 cm.display.sizer.style.minWidth = op.adjustWidthTo + "px" 113 if (op.maxScrollLeft < cm.doc.scrollLeft) 114 setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true) 115 cm.display.maxLineChanged = false 116 } 117 118 let takeFocus = op.focus && op.focus == activeElt() 119 if (op.preparedSelection) 120 cm.display.input.showSelection(op.preparedSelection, takeFocus) 121 if (op.updatedDisplay || op.startHeight != cm.doc.height) 122 updateScrollbars(cm, op.barMeasure) 123 if (op.updatedDisplay) 124 setDocumentHeight(cm, op.barMeasure) 125 126 if (op.selectionChanged) restartBlink(cm) 127 128 if (cm.state.focused && op.updateInput) 129 cm.display.input.reset(op.typing) 130 if (takeFocus) ensureFocus(op.cm) 131 } 132 133 function endOperation_finish(op) { 134 let cm = op.cm, display = cm.display, doc = cm.doc 135 136 if (op.updatedDisplay) postUpdateDisplay(cm, op.update) 137 138 // Abort mouse wheel delta measurement, when scrolling explicitly 139 if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos)) 140 display.wheelStartX = display.wheelStartY = null 141 142 // Propagate the scroll position to the actual DOM scroller 143 if (op.scrollTop != null) setScrollTop(cm, op.scrollTop, op.forceScroll) 144 145 if (op.scrollLeft != null) setScrollLeft(cm, op.scrollLeft, true, true) 146 // If we need to scroll a specific position into view, do so. 147 if (op.scrollToPos) { 148 let rect = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from), 149 clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin) 150 maybeScrollWindow(cm, rect) 151 } 152 153 // Fire events for markers that are hidden/unidden by editing or 154 // undoing 155 let hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers 156 if (hidden) for (let i = 0; i < hidden.length; ++i) 157 if (!hidden[i].lines.length) signal(hidden[i], "hide") 158 if (unhidden) for (let i = 0; i < unhidden.length; ++i) 159 if (unhidden[i].lines.length) signal(unhidden[i], "unhide") 160 161 if (display.wrapper.offsetHeight) 162 doc.scrollTop = cm.display.scroller.scrollTop 163 164 // Fire change events, and delayed event handlers 165 if (op.changeObjs) 166 signal(cm, "changes", cm, op.changeObjs) 167 if (op.update) 168 op.update.finish() 169 } 170 171 // Run the given function in an operation 172 export function runInOp(cm, f) { 173 if (cm.curOp) return f() 174 startOperation(cm) 175 try { return f() } 176 finally { endOperation(cm) } 177 } 178 // Wraps a function in an operation. Returns the wrapped function. 179 export function operation(cm, f) { 180 return function() { 181 if (cm.curOp) return f.apply(cm, arguments) 182 startOperation(cm) 183 try { return f.apply(cm, arguments) } 184 finally { endOperation(cm) } 185 } 186 } 187 // Used to add methods to editor and doc instances, wrapping them in 188 // operations. 189 export function methodOp(f) { 190 return function() { 191 if (this.curOp) return f.apply(this, arguments) 192 startOperation(this) 193 try { return f.apply(this, arguments) } 194 finally { endOperation(this) } 195 } 196 } 197 export function docMethodOp(f) { 198 return function() { 199 let cm = this.cm 200 if (!cm || cm.curOp) return f.apply(this, arguments) 201 startOperation(cm) 202 try { return f.apply(this, arguments) } 203 finally { endOperation(cm) } 204 } 205 }
Downloadmodules/editor/codemirror/src/display/operations.min.js
History Tue, 22 May 2018 22:39:54 +0200 Jan Dankert Fix für PHP 7.2: 'Object' darf nun nicht mehr als Klassennamen verwendet werden. AUCH NICHT IN EINEM NAMESPACE! WTF, wozu habe ich das in einen verfickten Namespace gepackt? Wozu soll der sonst da sein??? Amateure. Daher nun notgedrungen unbenannt in 'BaseObject'.