File modules/editor/codemirror/src/display/update_display.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 { sawCollapsedSpans } from "../line/saw_special_spans.js" 2 import { heightAtLine, visualLineEndNo, visualLineNo } from "../line/spans.js" 3 import { getLine, lineNumberFor } from "../line/utils_line.js" 4 import { displayHeight, displayWidth, getDimensions, paddingVert, scrollGap } from "../measurement/position_measurement.js" 5 import { mac, webkit } from "../util/browser.js" 6 import { activeElt, removeChildren, contains } from "../util/dom.js" 7 import { hasHandler, signal } from "../util/event.js" 8 import { indexOf } from "../util/misc.js" 9 10 import { buildLineElement, updateLineForChanges } from "./update_line.js" 11 import { startWorker } from "./highlight_worker.js" 12 import { maybeUpdateLineNumberWidth } from "./line_numbers.js" 13 import { measureForScrollbars, updateScrollbars } from "./scrollbars.js" 14 import { updateSelection } from "./selection.js" 15 import { updateHeightsInViewport, visibleLines } from "./update_lines.js" 16 import { adjustView, countDirtyView, resetView } from "./view_tracking.js" 17 18 // DISPLAY DRAWING 19 20 export class DisplayUpdate { 21 constructor(cm, viewport, force) { 22 let display = cm.display 23 24 this.viewport = viewport 25 // Store some values that we'll need later (but don't want to force a relayout for) 26 this.visible = visibleLines(display, cm.doc, viewport) 27 this.editorIsHidden = !display.wrapper.offsetWidth 28 this.wrapperHeight = display.wrapper.clientHeight 29 this.wrapperWidth = display.wrapper.clientWidth 30 this.oldDisplayWidth = displayWidth(cm) 31 this.force = force 32 this.dims = getDimensions(cm) 33 this.events = [] 34 } 35 36 signal(emitter, type) { 37 if (hasHandler(emitter, type)) 38 this.events.push(arguments) 39 } 40 finish() { 41 for (let i = 0; i < this.events.length; i++) 42 signal.apply(null, this.events[i]) 43 } 44 } 45 46 export function maybeClipScrollbars(cm) { 47 let display = cm.display 48 if (!display.scrollbarsClipped && display.scroller.offsetWidth) { 49 display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth 50 display.heightForcer.style.height = scrollGap(cm) + "px" 51 display.sizer.style.marginBottom = -display.nativeBarWidth + "px" 52 display.sizer.style.borderRightWidth = scrollGap(cm) + "px" 53 display.scrollbarsClipped = true 54 } 55 } 56 57 function selectionSnapshot(cm) { 58 if (cm.hasFocus()) return null 59 let active = activeElt() 60 if (!active || !contains(cm.display.lineDiv, active)) return null 61 let result = {activeElt: active} 62 if (window.getSelection) { 63 let sel = window.getSelection() 64 if (sel.anchorNode && sel.extend && contains(cm.display.lineDiv, sel.anchorNode)) { 65 result.anchorNode = sel.anchorNode 66 result.anchorOffset = sel.anchorOffset 67 result.focusNode = sel.focusNode 68 result.focusOffset = sel.focusOffset 69 } 70 } 71 return result 72 } 73 74 function restoreSelection(snapshot) { 75 if (!snapshot || !snapshot.activeElt || snapshot.activeElt == activeElt()) return 76 snapshot.activeElt.focus() 77 if (snapshot.anchorNode && contains(document.body, snapshot.anchorNode) && contains(document.body, snapshot.focusNode)) { 78 let sel = window.getSelection(), range = document.createRange() 79 range.setEnd(snapshot.anchorNode, snapshot.anchorOffset) 80 range.collapse(false) 81 sel.removeAllRanges() 82 sel.addRange(range) 83 sel.extend(snapshot.focusNode, snapshot.focusOffset) 84 } 85 } 86 87 // Does the actual updating of the line display. Bails out 88 // (returning false) when there is nothing to be done and forced is 89 // false. 90 export function updateDisplayIfNeeded(cm, update) { 91 let display = cm.display, doc = cm.doc 92 93 if (update.editorIsHidden) { 94 resetView(cm) 95 return false 96 } 97 98 // Bail out if the visible area is already rendered and nothing changed. 99 if (!update.force && 100 update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo && 101 (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) && 102 display.renderedView == display.view && countDirtyView(cm) == 0) 103 return false 104 105 if (maybeUpdateLineNumberWidth(cm)) { 106 resetView(cm) 107 update.dims = getDimensions(cm) 108 } 109 110 // Compute a suitable new viewport (from & to) 111 let end = doc.first + doc.size 112 let from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first) 113 let to = Math.min(end, update.visible.to + cm.options.viewportMargin) 114 if (display.viewFrom < from && from - display.viewFrom < 20) from = Math.max(doc.first, display.viewFrom) 115 if (display.viewTo > to && display.viewTo - to < 20) to = Math.min(end, display.viewTo) 116 if (sawCollapsedSpans) { 117 from = visualLineNo(cm.doc, from) 118 to = visualLineEndNo(cm.doc, to) 119 } 120 121 let different = from != display.viewFrom || to != display.viewTo || 122 display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth 123 adjustView(cm, from, to) 124 125 display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom)) 126 // Position the mover div to align with the current scroll position 127 cm.display.mover.style.top = display.viewOffset + "px" 128 129 let toUpdate = countDirtyView(cm) 130 if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view && 131 (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo)) 132 return false 133 134 // For big changes, we hide the enclosing element during the 135 // update, since that speeds up the operations on most browsers. 136 let selSnapshot = selectionSnapshot(cm) 137 if (toUpdate > 4) display.lineDiv.style.display = "none" 138 patchDisplay(cm, display.updateLineNumbers, update.dims) 139 if (toUpdate > 4) display.lineDiv.style.display = "" 140 display.renderedView = display.view 141 // There might have been a widget with a focused element that got 142 // hidden or updated, if so re-focus it. 143 restoreSelection(selSnapshot) 144 145 // Prevent selection and cursors from interfering with the scroll 146 // width and height. 147 removeChildren(display.cursorDiv) 148 removeChildren(display.selectionDiv) 149 display.gutters.style.height = display.sizer.style.minHeight = 0 150 151 if (different) { 152 display.lastWrapHeight = update.wrapperHeight 153 display.lastWrapWidth = update.wrapperWidth 154 startWorker(cm, 400) 155 } 156 157 display.updateLineNumbers = null 158 159 return true 160 } 161 162 export function postUpdateDisplay(cm, update) { 163 let viewport = update.viewport 164 165 for (let first = true;; first = false) { 166 if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) { 167 // Clip forced viewport to actual scrollable area. 168 if (viewport && viewport.top != null) 169 viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)} 170 // Updated line heights might result in the drawn area not 171 // actually covering the viewport. Keep looping until it does. 172 update.visible = visibleLines(cm.display, cm.doc, viewport) 173 if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo) 174 break 175 } 176 if (!updateDisplayIfNeeded(cm, update)) break 177 updateHeightsInViewport(cm) 178 let barMeasure = measureForScrollbars(cm) 179 updateSelection(cm) 180 updateScrollbars(cm, barMeasure) 181 setDocumentHeight(cm, barMeasure) 182 update.force = false 183 } 184 185 update.signal(cm, "update", cm) 186 if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) { 187 update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo) 188 cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo 189 } 190 } 191 192 export function updateDisplaySimple(cm, viewport) { 193 let update = new DisplayUpdate(cm, viewport) 194 if (updateDisplayIfNeeded(cm, update)) { 195 updateHeightsInViewport(cm) 196 postUpdateDisplay(cm, update) 197 let barMeasure = measureForScrollbars(cm) 198 updateSelection(cm) 199 updateScrollbars(cm, barMeasure) 200 setDocumentHeight(cm, barMeasure) 201 update.finish() 202 } 203 } 204 205 // Sync the actual display DOM structure with display.view, removing 206 // nodes for lines that are no longer in view, and creating the ones 207 // that are not there yet, and updating the ones that are out of 208 // date. 209 function patchDisplay(cm, updateNumbersFrom, dims) { 210 let display = cm.display, lineNumbers = cm.options.lineNumbers 211 let container = display.lineDiv, cur = container.firstChild 212 213 function rm(node) { 214 let next = node.nextSibling 215 // Works around a throw-scroll bug in OS X Webkit 216 if (webkit && mac && cm.display.currentWheelTarget == node) 217 node.style.display = "none" 218 else 219 node.parentNode.removeChild(node) 220 return next 221 } 222 223 let view = display.view, lineN = display.viewFrom 224 // Loop over the elements in the view, syncing cur (the DOM nodes 225 // in display.lineDiv) with the view as we go. 226 for (let i = 0; i < view.length; i++) { 227 let lineView = view[i] 228 if (lineView.hidden) { 229 } else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet 230 let node = buildLineElement(cm, lineView, lineN, dims) 231 container.insertBefore(node, cur) 232 } else { // Already drawn 233 while (cur != lineView.node) cur = rm(cur) 234 let updateNumber = lineNumbers && updateNumbersFrom != null && 235 updateNumbersFrom <= lineN && lineView.lineNumber 236 if (lineView.changes) { 237 if (indexOf(lineView.changes, "gutter") > -1) updateNumber = false 238 updateLineForChanges(cm, lineView, lineN, dims) 239 } 240 if (updateNumber) { 241 removeChildren(lineView.lineNumber) 242 lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN))) 243 } 244 cur = lineView.node.nextSibling 245 } 246 lineN += lineView.size 247 } 248 while (cur) cur = rm(cur) 249 } 250 251 export function updateGutterSpace(cm) { 252 let width = cm.display.gutters.offsetWidth 253 cm.display.sizer.style.marginLeft = width + "px" 254 } 255 256 export function setDocumentHeight(cm, measure) { 257 cm.display.sizer.style.minHeight = measure.docHeight + "px" 258 cm.display.heightForcer.style.top = measure.docHeight + "px" 259 cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px" 260 }
Downloadmodules/editor/codemirror/src/display/update_display.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'.