Javascript Firefox:以编程方式触发autoscroll

Javascript Firefox:以编程方式触发autoscroll,javascript,firefox,dom-events,autoscroll,Javascript,Firefox,Dom Events,Autoscroll,我想听到中键按下(mousedown事件),然后有条件地采取行动(与具体内容无关)或恢复到默认状态,即进入“自动滚动模式”,并显示自动滚动图标,直到用户释放中键 我的代码侦听mousedown事件,并检查按下的按钮是否为中间按钮。然后确定是否执行默认操作,如果不执行,则通过调用event.preventDefault来阻止默认操作。问题是在实际按下鼠标和执行操作之间有延迟,因此当用户按下并按住按钮时,操作不会立即执行。相反,会在短时间内观察鼠标移动,根据此移动,释放按钮后会执行自定义操作,或者立

我想听到中键按下(
mousedown
事件),然后有条件地采取行动(与具体内容无关)或恢复到默认状态,即进入“自动滚动模式”,并显示自动滚动图标,直到用户释放中键

我的代码侦听
mousedown
事件,并检查按下的按钮是否为中间按钮。然后确定是否执行默认操作,如果不执行,则通过调用
event.preventDefault
来阻止默认操作。问题是在实际按下鼠标和执行操作之间有延迟,因此当用户按下并按住按钮时,操作不会立即执行。相反,会在短时间内观察鼠标移动,根据此移动,释放按钮后会执行自定义操作,或者立即执行
mousedown
的默认操作。在采取默认操作的情况下,我希望Firefox表现得像用户按下中间按钮一样,例如启动autoscroll。这不会发生,因为不会对合成事件(以编程方式生成的事件)作出反应

如何以编程方式在Firefox中触发autoscroll?是否有方法使用更改行为(例如,使autoscroll侦听合成事件)


编辑:更多信息 我为YouTube制作了一个Greasemonkey插件,它实现了以下功能:

  • 单击中间按钮(不拖动)时,切换全屏模式
  • 当我按下中间按钮向左/向右拖动时,它会向后/向前搜索视频
  • 当我向上/向下拖动时,我想要滚动

因此,必须阻止默认操作,当鼠标被拖过一定距离时,我们可以决定是搜索还是滚动。一旦拖动“移动”了一定数量的像素,就会计算和评估轨迹的角度。如果拖动是垂直的,那么我想激活滚动,否则等待按钮被释放,然后搜索。只有在释放按钮后才能搜索视频,例如,拖动时没有“实时预览”

据我所知,无法从JavaScript中触发Firefox的自动滚动模式。但是,显然可以在它处于活动状态时中断它,例如通过调用
window.scrollTo()

此外,如果页面实际上没有水平滚动,则在autoscroll模式处于活动状态时水平拖动鼠标光标不会产生任何效果。大多数网页都没有

根据这些观察,这里有一个替代解决方案(草图):

  • 让鼠标中键单击“传播”并触发其默认操作,从而启用自动滚动模式

  • 像平常一样进行水平阻力检测

  • 如果检测到水平拖动,请调用
    window.scrollTo(window.scrollX,window.scrollY)
    ,这将关闭Firefox的自动滚动模式,然后继续视频搜索

  • 这种方法的主要缺点是:a)在检测拖动方向时,autoscroll指示器将短暂可见;b)如果用户稍微沿对角线拖动鼠标,他们可能仍然会将页面上下滚动几个像素。(这可能取决于用户的谨慎和协调程度。autoscroll功能本身似乎有一个小的内置“死区”,因此在页面实际开始垂直滚动之前,您需要将鼠标光标上下移动至少十几个像素。)


    前者似乎是一个不可避免但很小的界面怪癖;您的用户甚至可能没有真正注意到它。为了缓解后一个问题,您可能希望在步骤1中保存
    window.scrollX
    window.scrollY
    的值,并在步骤3中使用保存的值,从而将页面恢复到拖动开始前的滚动位置。这可能仍然会导致令人恼火的“抖动”,因为页面会滚动一点,然后又弹回来,但这可能比让页面永久向下移动更令人恼火。

    您能否提供更多有关触发自定义行为的条件的详细信息?我猜你可能在做手势识别之类的事情?根据点击前观察到的鼠标移动来决定是否可行?或者让默认行为触发,然后(不知何故?)在几毫秒后取消它,如果它看起来像用户试图执行手势而不是滚动?@IlmariKaronen我添加了一些更多的信息。您是否尝试过创建鼠标事件而不是鼠标事件?(这只是一个建议,你可能想研究一下,不确定这是否能解决你的问题)。不,这不符合我的要求。听起来很合理,但不幸的是,这并没有回答“如何以编程方式触发autoscroll”的问题,所以我不太愿意接受这个答案。但是谢谢你的建议,我会尝试一下。我想这个答案是想说“你不能用编程的方式触发它,但下面是如何实现类似的最终结果”。您基本上需要做与您正在做的相反的事情:1)允许事件冒泡,从而在短时间内触发autoscroll。2) 然后翻转
    shouldTakeDefaultAction
    方法内部的逻辑。我将其重命名为
    shouldPreventAutoScroll
    ,它将调用
    window.scrollTo()
    ,从而禁用自动滚动。
    var elem = document.getElementById('watchedElement')
    var active = false
    
    elem.onmousedown = function(event) {
      if (event.button !== MIDDLE_BUTTON || active) { return }
      event.preventDefault()
    
      startParams = getStartParams()
      active = true
    }
    
    elem.onmousemove = function(event) {
      if (!active) { return }
    
      if (shouldTakeDefaultAction()) {
        elem.dispatchEvent(new MouseEvent('mousedown',
                               {'button': MIDDLE_BUTTON, 'which': MIDDLE_BUTTON}))
        active = false
      }
    }
    
    elem.onmouseup = function(event) {
      if (event.button !== MIDDLE_BUTTON || !active) { return }
      event.preventDefault()
    
      takeCustomAction()
      active = false
    }