overleaf/services/web/public/coffee/ide/SafariScrollPatcher.coffee

79 lines
3 KiB
CoffeeScript
Raw Normal View History

2016-07-29 16:24:45 +00:00
define [
], () ->
class SafariScrollPatcher
2016-08-01 10:12:50 +00:00
constructor: ($scope) ->
@isOverAce = false # Flag to control if the pointer is over Ace.
2016-07-29 16:24:45 +00:00
@pdfDiv = null
@aceDiv = null
# Start listening to PDF wheel events when the pointer leaves the PDF region.
# P.S. This is the problem in a nutshell: although the pointer is elsewhere,
# wheel events keep being dispatched to the PDF.
@handlePdfDivMouseLeave = () =>
@pdfDiv.addEventListener "wheel", @dispatchToAce
# Stop listening to wheel events when the pointer enters the PDF region. If
# the pointer is over the PDF, native behaviour is adequate.
@handlePdfDivMouseEnter = () =>
@pdfDiv.removeEventListener "wheel", @dispatchToAce
# Set the "pointer over Ace" flag as false, when the mouse leaves its area.
@handleAceDivMouseLeave = () =>
@isOverAce = false
# Set the "pointer over Ace" flag as true, when the mouse enters its area.
@handleAceDivMouseEnter = () =>
@isOverAce = true
# Grab the elements (pdfDiv, aceDiv) and set the "hover" event listeners.
# If elements are already defined, clear existing event listeners and do
# the process again (grab elements, set listeners).
@setListeners = () =>
@isOverAce = false
# If elements aren't null, remove existing listeners.
if @pdfDiv?
@pdfDiv.removeEventListener @handlePdfDivMouseLeave
@pdfDiv.removeEventListener @handlePdfDivMouseEnter
if @aceDiv?
@aceDiv.removeEventListener @handleAceDivMouseLeave
@aceDiv.removeEventListener @handleAceDivMouseEnter
# Grab elements.
@pdfDiv = document.querySelector ".pdfjs-viewer" # Grab the PDF div.
2016-08-01 10:12:50 +00:00
@aceDiv = document.querySelector ".ace_content" # Also the editor.
# Set hover-related listeners.
@pdfDiv.addEventListener "mouseleave", @handlePdfDivMouseLeave
@pdfDiv.addEventListener "mouseenter", @handlePdfDivMouseEnter
@aceDiv.addEventListener "mouseleave", @handleAceDivMouseLeave
@aceDiv.addEventListener "mouseenter", @handleAceDivMouseEnter
# Handler for wheel events on the PDF.
# If the pointer is over Ace, grab the event, prevent default behaviour
# and dispatch it to Ace.
@dispatchToAce = (e) =>
if @isOverAce
# If this is logged, the problem just happened: the event arrived
# here (the PDF wheel handler), but it should've gone to Ace.
# Small timeout - if we dispatch immediately, an exception is thrown.
window.setTimeout(() =>
# Dispatch the exact same event to Ace (this will keep values
# values e.g. `wheelDelta` consistent with user interaction).
@aceDiv.dispatchEvent e
2016-08-01 10:12:50 +00:00
, 1)
# Avoid scrolling the PDF, as we assume this was intended to the
# editor.
e.preventDefault()
2016-08-01 12:35:49 +00:00
# "loaded" event is emitted from the pdfViewer controller $scope. This means
# that the previous PDF DOM element was destroyed and a new one is available,
# so we need to grab the elements and set the listeners again.
2016-07-29 16:24:45 +00:00
$scope.$on "loaded", () =>
@setListeners()
2016-07-29 16:24:45 +00:00