Spaces:
Sleeping
Sleeping
processmaker-community / processmaker-files /gulliver /js /codemirror /src /display /scroll_events.js
| import { chrome, gecko, ie, mac, presto, safari, webkit } from "../util/browser" | |
| import { e_preventDefault } from "../util/event" | |
| import { startWorker } from "./highlight_worker" | |
| import { alignHorizontally } from "./line_numbers" | |
| import { updateDisplaySimple} from "./update_display" | |
| // Sync the scrollable area and scrollbars, ensure the viewport | |
| // covers the visible area. | |
| export function setScrollTop(cm, val) { | |
| if (Math.abs(cm.doc.scrollTop - val) < 2) return | |
| cm.doc.scrollTop = val | |
| if (!gecko) updateDisplaySimple(cm, {top: val}) | |
| if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val | |
| cm.display.scrollbars.setScrollTop(val) | |
| if (gecko) updateDisplaySimple(cm) | |
| startWorker(cm, 100) | |
| } | |
| // Sync scroller and scrollbar, ensure the gutter elements are | |
| // aligned. | |
| export function setScrollLeft(cm, val, isScroller) { | |
| if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return | |
| val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth) | |
| cm.doc.scrollLeft = val | |
| alignHorizontally(cm) | |
| if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val | |
| cm.display.scrollbars.setScrollLeft(val) | |
| } | |
| // Since the delta values reported on mouse wheel events are | |
| // unstandardized between browsers and even browser versions, and | |
| // generally horribly unpredictable, this code starts by measuring | |
| // the scroll effect that the first few mouse wheel events have, | |
| // and, from that, detects the way it can convert deltas to pixel | |
| // offsets afterwards. | |
| // | |
| // The reason we want to know the amount a wheel event will scroll | |
| // is that it gives us a chance to update the display before the | |
| // actual scrolling happens, reducing flickering. | |
| let wheelSamples = 0, wheelPixelsPerUnit = null | |
| // Fill in a browser-detected starting value on browsers where we | |
| // know one. These don't have to be accurate -- the result of them | |
| // being wrong would just be a slight flicker on the first wheel | |
| // scroll (if it is large enough). | |
| if (ie) wheelPixelsPerUnit = -.53 | |
| else if (gecko) wheelPixelsPerUnit = 15 | |
| else if (chrome) wheelPixelsPerUnit = -.7 | |
| else if (safari) wheelPixelsPerUnit = -1/3 | |
| function wheelEventDelta(e) { | |
| let dx = e.wheelDeltaX, dy = e.wheelDeltaY | |
| if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail | |
| if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail | |
| else if (dy == null) dy = e.wheelDelta | |
| return {x: dx, y: dy} | |
| } | |
| export function wheelEventPixels(e) { | |
| let delta = wheelEventDelta(e) | |
| delta.x *= wheelPixelsPerUnit | |
| delta.y *= wheelPixelsPerUnit | |
| return delta | |
| } | |
| export function onScrollWheel(cm, e) { | |
| let delta = wheelEventDelta(e), dx = delta.x, dy = delta.y | |
| let display = cm.display, scroll = display.scroller | |
| // Quit if there's nothing to scroll here | |
| let canScrollX = scroll.scrollWidth > scroll.clientWidth | |
| let canScrollY = scroll.scrollHeight > scroll.clientHeight | |
| if (!(dx && canScrollX || dy && canScrollY)) return | |
| // Webkit browsers on OS X abort momentum scrolls when the target | |
| // of the scroll event is removed from the scrollable element. | |
| // This hack (see related code in patchDisplay) makes sure the | |
| // element is kept around. | |
| if (dy && mac && webkit) { | |
| outer: for (let cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) { | |
| for (let i = 0; i < view.length; i++) { | |
| if (view[i].node == cur) { | |
| cm.display.currentWheelTarget = cur | |
| break outer | |
| } | |
| } | |
| } | |
| } | |
| // On some browsers, horizontal scrolling will cause redraws to | |
| // happen before the gutter has been realigned, causing it to | |
| // wriggle around in a most unseemly way. When we have an | |
| // estimated pixels/delta value, we just handle horizontal | |
| // scrolling entirely here. It'll be slightly off from native, but | |
| // better than glitching out. | |
| if (dx && !gecko && !presto && wheelPixelsPerUnit != null) { | |
| if (dy && canScrollY) | |
| setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight))) | |
| setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth))) | |
| // Only prevent default scrolling if vertical scrolling is | |
| // actually possible. Otherwise, it causes vertical scroll | |
| // jitter on OSX trackpads when deltaX is small and deltaY | |
| // is large (issue #3579) | |
| if (!dy || (dy && canScrollY)) | |
| e_preventDefault(e) | |
| display.wheelStartX = null // Abort measurement, if in progress | |
| return | |
| } | |
| // 'Project' the visible viewport to cover the area that is being | |
| // scrolled into view (if we know enough to estimate it). | |
| if (dy && wheelPixelsPerUnit != null) { | |
| let pixels = dy * wheelPixelsPerUnit | |
| let top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight | |
| if (pixels < 0) top = Math.max(0, top + pixels - 50) | |
| else bot = Math.min(cm.doc.height, bot + pixels + 50) | |
| updateDisplaySimple(cm, {top: top, bottom: bot}) | |
| } | |
| if (wheelSamples < 20) { | |
| if (display.wheelStartX == null) { | |
| display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop | |
| display.wheelDX = dx; display.wheelDY = dy | |
| setTimeout(() => { | |
| if (display.wheelStartX == null) return | |
| let movedX = scroll.scrollLeft - display.wheelStartX | |
| let movedY = scroll.scrollTop - display.wheelStartY | |
| let sample = (movedY && display.wheelDY && movedY / display.wheelDY) || | |
| (movedX && display.wheelDX && movedX / display.wheelDX) | |
| display.wheelStartX = display.wheelStartY = null | |
| if (!sample) return | |
| wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1) | |
| ++wheelSamples | |
| }, 200) | |
| } else { | |
| display.wheelDX += dx; display.wheelDY += dy | |
| } | |
| } | |
| } | |