当前位置: 首页 > 知识库问答 >
问题:

如何在Firefox中在窗口外拖动时检测dragleave事件

湛鸿
2023-03-14

Firefox 在将拖动到窗口外时无法正确触发 dragleave 事件:

https://bugzilla.mozilla.org/show_bug.cgi?id=665704

https://bugzilla.mozilla.org/show_bug.cgi?id=656164

我正试图开发一个解决办法(我知道这是可能的,因为Gmail正在做),但我能想到的唯一一件事似乎真的很黑客。

了解在窗口外拖动时发生的一种方法是等待拖动事件停止触发(因为在拖放操作期间拖动会不断触发)。我是这样做的:

var timeout;

function dragleaveFunctionality() {
  // do stuff
}

function firefoxTimeoutHack() {
  clearTimeout(timeout);
  timeout = setTimeout(dragleaveFunctionality, 200);
}

$(document).on('dragover', firefoxTimeoutHack);

这段代码本质上是一次又一次地创建和清除超时。除非< code>dragover事件停止触发,否则不会达到200毫秒超时。

虽然这是可行的,但我不喜欢为此目的使用超时的想法。感觉不对。这也意味着在“dropzone”样式消失之前会有一个轻微的延迟。

我的另一个想法是检测鼠标何时离开窗口,但在拖放操作期间,正常的方法似乎不起作用。

有人有更好的方法吗?

更新:

这是我使用的代码:

 $(function() {
          var counter = 0;
          $(document).on('dragenter', function(e) {
            counter += 1;
            console.log(counter, e.target);
          });
          $(document).on('dragleave', function(e) {
            counter -= 1;
            console.log(counter, e.target);
          });
        });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Open up the console and look at what number is reporting when dragging files in and out of the window. The number should always be 0 when leaving the window, but in Firefox it's not.</p>

共有3个答案

微生翼
2023-03-14

受@Philip Walton代码的启发,我简化了jQuery插件代码。

$.fn.draghover = function(fnIn, fnOut) {
    return this.each(function() {
        var n = 0;
        $(this).on('dragenter', function(e) {
            (++n, n==1) && fnIn && fnIn.call(this, e);
        }).on('dragleave drop', function(e) {
            (--n, n==0) && fnOut && fnOut.call(this, e);
        });
    });
};

现在您可以使用jQuery插件,如jQuery hover方法:

// Testing code 1
$(window).draghover(function() {
    console.log('into window');
}, function() {
    console.log('out of window');
});

// Testing code 2
$('#d1').draghover(function() {
    console.log('into #d1');
}, function() {
    console.log('out of #d1');
});
龙俊美
2023-03-14

根据您希望完成的任务,您可以使用仅在Firefox中可用的:-moz-draad-over伪类来解决此问题,该类可让您对文件拖过一个元素。

看看这个简单的演示http://codepen.io/ryanseddon/pen/Ccsua

.dragover {
    background: red;
    width: 500px;
    height: 300px;
}
.dragover:-moz-drag-over {
    background: green;
}
海嘉赐
2023-03-14

我找到了解决办法。问题不在于< code>dragleave事件没有触发;相反,< code>dragenter事件在第一次将文件拖动到窗口中时触发了两次(有时在某些元素上拖动时也会触发)。我最初的解决方案是使用一个计数器来跟踪最后的< code>dragleave事件何时发生,但是< code>dragenter事件的两次触发打乱了计数。(为什么我就不能听听你问的< code>dragleave?因为< code>dragleave的功能与< code>mouseout非常相似,它不仅在离开元素时触发,而且在进入子元素时也触发。因此,当< code>dragleave触发时,您的鼠标很可能仍在原始元素的范围内。)

我想出的解决方案是跟踪触发了哪些元素dragenterdragoff。由于事件向上传播到文档,因此侦听特定元素上的dragenterdragoff不仅会捕获该元素上的事件,还会捕获其子元素上的事件。

因此,我创建了一个jQuery集合$()来跟踪在哪些元素上触发了哪些事件。我添加了<code>事件。每当触发dragenter时,将指向集合,我删除了事件。每当发生DRAGEAVE时,从集合中获取目标。其想法是,如果集合为空,这意味着我实际上已经离开了原始元素,因为如果我输入一个子元素,那么jQuery集合中至少还有一个元素(子元素)。最后,当触发<code>drop</code>事件时,我想将集合重置为空,以便在下一个<code>dragenter</code>事件发生时准备好。

jQuery还节省了大量额外的工作,因为它自动执行重复检查,所以<code>事件。目标不会被添加两次,即使Firefox错误地两次调用<code>dragenter。

嘿,不管怎样,这是我最终使用的代码的基本版本。如果其他人对使用它感兴趣,我已经将它放入了一个简单的jQuery插件中。基本上,您调用<code>。在任何元素上拖动,当第一次拖动到元素中时,draghoverstart将被触发,拖动实际离开元素后,draghoverend将被触发。

// The plugin code
$.fn.draghover = function(options) {
  return this.each(function() {

    var collection = $(),
        self = $(this);

    self.on('dragenter', function(e) {
      if (collection.length === 0) {
        self.trigger('draghoverstart');
      }
      collection = collection.add(e.target);
    });

    self.on('dragleave drop', function(e) {
      collection = collection.not(e.target);
      if (collection.length === 0) {
        self.trigger('draghoverend');
      }
    });
  });
};

// Now that we have a plugin, we can listen for the new events 
$(window).draghover().on({
  'draghoverstart': function() {
    console.log('A file has been dragged into the window.');
  },
  'draghoverend': function() {
    console.log('A file has been dragged out of window.');
  }
});

没有jQuery

要在没有jQuery的情况下处理这个问题,你可以做这样的事情:

// I want to handle drag leaving on the document
let count = 0
onDragEnter = (event) => {
  if (event.currentTarget === document) {
    count += 1
  }
}

onDragLeave = (event) => {
  if (event.currentTarget === document) {
     count += 0
  }

  if (count === 0) {
    // Handle drag leave.
  }
}
 类似资料:
  • 当使用jquery ui sortable小部件并在浏览器中的可见区域下方拖动项目时,窗口不会滚动,以便您可以将其放置在该区域下方可能有其他项目的区域中。对于Firefox,我还没有找到答案——我已经看到了Chrome的一个解决方案,在该解决方案中,您向可排序函数添加了一个helper属性,该属性可以执行以下操作: ...但是,这只能在Chrome解决同样的问题,而不是火狐。

  • 我想开发一个带有div和一些样式的文件拖放组件: dragenter:更改div边框颜色 dragleave:还原为原始div边框颜色 在Firefox 35(Ubuntu)上,当div有一个滚动条(水平或垂直)并且在滚动条中移动文件时,我会发生以下事件: < li>dragenter:移过div边框 < li>dragenter:在滚动条上移动 < li>dragleave:离开滚动条 所以我在

  • 我对Java还很陌生,我试着查了一下,但没有找到任何有用的东西。我想知道我怎么能检测到一个特定的窗口关闭了?我一直在使用windowClosing(),但这适用于关闭的任何窗口,因此如果窗口B关闭,我希望由于窗口a关闭而发生的事件也会发生。我如何只在窗口A关闭的情况下进行检测?抱歉,如果这是一个糟糕的措辞,我不知道那么多Java术语。提前致谢:)

  • 本文向大家介绍对于HTML5拖放事件,dragLeave事件在放置之前触发,包括了对于HTML5拖放事件,dragLeave事件在放置之前触发的使用技巧和注意事项,需要的朋友参考一下 要解决拖放事件的这一问题,有时在拖动之前将dragLeave触发: 在下拉菜单中,您可以设置以下内容:

  • 有人能举一个简单的例子来说明如何设置EventHandler以在窗格(JavaFX)上拖动图像视图。对于拖动,我的意思是在图像上按下鼠标,拖动和图像应该跟随,然后释放鼠标,图像视图将停止在该位置。

  • 基于此注释https://stackoverflow.com/a/29530135/1387524,我添加了一个ScrollPane,以便在画布移到可见区域之外时使用滚动。