如何使用自定义事件(特别是自定义dataTransfer属性)触发事件?

Ted*_*Ted 7 javascript jquery

我目前正在尝试测试一些使用拖放的代码.我发现了一些与此有关的其他问题,但它们太具体而无法帮助我,或者说不够相关.

这是一个测试,我正在努力尝试在.on('drop',function(e){....}事件中自动执行代码.主要问题不是我不能在里面运行代码,而是因为我无法传输dataTransfer属性,我似乎无法伪造它,因为它是只读的.反正有没有伪造dataTransfer财产或以其他方式绕过它?

我想出了这个JSFiddle,作为我正在尝试做的模板:https://jsfiddle.net/gnq50hsp/53/

基本上如果你能够向我解释(如果这是可能的话)我怎么可能伪造dataTransfer财产,我应该全力以赴.

附注:

  • 我完全接受以某种方式进入代码的其他方式,例如,可能触发事件并使用伪造的dataTransfer对象传递假事件对象.

  • 要查看拖放行为,请将JavaScript加载类型更改no-wrap headon-Load,然后您应该看到我正在尝试模拟的内容.

  • 需要注意的是,我无法修改事件处理程序中的任何代码,只能在外部函数内部修改

  • 使用Karma/Jasmine也可以使用这些工具,就像间谍一样

  • 另外,我正在使用Chrome.

在此先感谢,如有任何问题/澄清,请与我联系!

Jul*_*ire 5

您应该能够使用Object.defineProperty覆盖您想要的所有内容.根据您要测试的内容,它可能非常简单或非常复杂.伪造dataTransfer可能有点棘手,因为它有很多限制和行为,但如果你只是想测试drop函数,那就相当容易了.

这是一种方法,这应该给你一些关于如何伪造一些事件和数据的想法:

//Event stuff
var target = $('#target');
var test = $('#test');

test.on('dragstart', function(e) {
  e.originalEvent.dataTransfer.setData("text/plain", "test");
});
target.on('dragover', function(e) {

  //e.dataTransfer.setData('test');
  e.preventDefault();
  e.stopPropagation();
});
target.on('dragenter', function(e) {
  e.preventDefault();
  e.stopPropagation();
});

//What I want to simulate:
target.on('drop', function(e) {
  console.log(e)
    //Issue is that I can't properly override the dataTransfer property, since its read-only
  document.getElementById('dataTransferDisplay').innerHTML = e.originalEvent.dataTransfer.getData("text");
});

function simulateDrop() {

  // You'll need the original event
  var fakeOriginalEvent = new DragEvent('drop');

  // Using defineProperty you can override dataTransfer property. 
  // The original property works with a getter and a setter,
  // so assigning it won't work. You need Object.defineProperty.
  Object.defineProperty(fakeOriginalEvent.constructor.prototype, 'dataTransfer', {
    value: {}
  });

  // Once dataTransfer is overridden, you can define getData.
  fakeOriginalEvent.dataTransfer.getData = function() {
    return 'test'
  };
  // TO have the same behavior, you need a jquery Event with an original event
  var fakeJqueryEvent = $.Event('drop', {
    originalEvent: fakeOriginalEvent
  });
  target.trigger(fakeJqueryEvent)
}
Run Code Online (Sandbox Code Playgroud)

https://jsfiddle.net/0tbp4wmk/1/