mirror of
https://github.com/moebooru/moebooru
synced 2025-08-22 09:57:31 +00:00
Merge branch 'dup'
This commit is contained in:
commit
c473cef239
125
app/javascript/src/classes/responsive_single_click.coffee
Normal file
125
app/javascript/src/classes/responsive_single_click.coffee
Normal file
@ -0,0 +1,125 @@
|
||||
import EmulateDoubleClick from 'src/classes/emulate_double_click'
|
||||
import { maintainUrlHash } from 'src/utils/maintain_url_hash'
|
||||
import { distanceSquared } from 'src/utils/math'
|
||||
###
|
||||
# This file implements several helpers for fixing up full-page web apps on touchscreen
|
||||
# browsers:
|
||||
#
|
||||
# EmulateDoubleClick
|
||||
# ResponsiveSingleClick
|
||||
# PreventDragScrolling
|
||||
#
|
||||
# Most of these are annoying hacks to work around the fact that WebKit on browsers was
|
||||
# designed with displaying scrolling webpages in mind, apparently without consideration
|
||||
# for full-screen applications: pages that should fill the screen at all times. Most
|
||||
# of the browser mobile hacks no longer make sense: separate display viewports, touch
|
||||
# dragging, double-click zooming and their associated side-effects.
|
||||
###
|
||||
|
||||
###
|
||||
# Mobile WebKit has serious problems with the click event: it delays them for the
|
||||
# entire double-click timeout, and if a double-click happens it doesn't deliver the
|
||||
# click at all. This makes clicks unresponsive, and it has this behavior even
|
||||
# when the page can't be zoomed, which means nothing happens at all.
|
||||
#
|
||||
# Generate click events from touchend events to bypass this mess.
|
||||
###
|
||||
|
||||
window.ResponsiveSingleClick = ->
|
||||
@click_event = @click_event.bindAsEventListener(this)
|
||||
@touchstart_event = @touchstart_event.bindAsEventListener(this)
|
||||
@touchend_event = @touchend_event.bindAsEventListener(this)
|
||||
@last_touch = null
|
||||
window.addEventListener 'touchstart', @touchstart_event, false
|
||||
window.addEventListener 'touchend', @touchend_event, false
|
||||
|
||||
### This is a capturing listener, so we can intercept clicks before they're
|
||||
# delivered to anyone.
|
||||
###
|
||||
|
||||
window.addEventListener 'click', @click_event, true
|
||||
return
|
||||
|
||||
ResponsiveSingleClick::touchstart_event = (event) ->
|
||||
|
||||
### If we get a touch while we already have a touch, it's multitouch, which is never
|
||||
# a click, so cancel the click.
|
||||
###
|
||||
|
||||
if @last_touch?
|
||||
console.debug 'Cancelling click (multitouch)'
|
||||
@last_touch = null
|
||||
return
|
||||
|
||||
### Watch out: in older versions of WebKit, the event.touches array and the items inside
|
||||
# it are actually modified in-place when the user drags. That means that we can't just
|
||||
# save the entire array for comparing in touchend.
|
||||
###
|
||||
|
||||
touch = event.changedTouches[0]
|
||||
@last_touch = [
|
||||
touch.screenX
|
||||
touch.screenY
|
||||
]
|
||||
return
|
||||
|
||||
ResponsiveSingleClick::touchend_event = (event) ->
|
||||
last_touch = @last_touch
|
||||
if !last_touch?
|
||||
return
|
||||
@last_touch = null
|
||||
touch = event.changedTouches[0]
|
||||
this_touch = [
|
||||
touch.screenX
|
||||
touch.screenY
|
||||
]
|
||||
|
||||
# Don't trigger a click if the point has moved too far.
|
||||
distance = distanceSquared(this_touch[0], this_touch[1], last_touch[0], last_touch[1])
|
||||
if distance > 50
|
||||
return
|
||||
e = document.createEvent('MouseEvent')
|
||||
e.initMouseEvent 'click', true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null
|
||||
e.synthesized_click = true
|
||||
|
||||
### If we dispatch the click immediately, EmulateDoubleClick won't receive a
|
||||
# touchstart for the next click. Defer dispatching it until we return.
|
||||
###
|
||||
|
||||
(->
|
||||
event.target.dispatchEvent e
|
||||
return
|
||||
).defer()
|
||||
return
|
||||
|
||||
### Capture and cancel all clicks except the ones we generate. ###
|
||||
|
||||
ResponsiveSingleClick::click_event = (event) ->
|
||||
if !event.synthesized_click
|
||||
event.stop()
|
||||
return
|
||||
|
||||
### Stop all touchmove events on the document, to prevent dragging the window around. ###
|
||||
|
||||
window.PreventDragScrolling = ->
|
||||
Element.observe document, 'touchmove', (event) ->
|
||||
event.preventDefault()
|
||||
return
|
||||
return
|
||||
|
||||
window.InitializeFullScreenBrowserHandlers = ->
|
||||
# These handlers deal with heavily browser-specific issues. Only install them
|
||||
# on browsers that have been tested to need them.
|
||||
if navigator.userAgent.indexOf('Android') != -1 and navigator.userAgent.indexOf('WebKit') != -1
|
||||
new ResponsiveSingleClick
|
||||
new EmulateDoubleClick
|
||||
else if (navigator.userAgent.indexOf('iPhone') != -1 or navigator.userAgent.indexOf('iPad') != -1 or navigator.userAgent.indexOf('iPod') != -1) and navigator.userAgent.indexOf('WebKit') != -1
|
||||
new ResponsiveSingleClick
|
||||
new EmulateDoubleClick
|
||||
|
||||
### In web app mode only: ###
|
||||
|
||||
if window.navigator.standalone
|
||||
maintainUrlHash()
|
||||
PreventDragScrolling()
|
||||
return
|
Loading…
x
Reference in New Issue
Block a user