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

时间:2016-08-18 23:15:03

标签: javascript jquery

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

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

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

基本上如果你能够向我解释(如果可能的话)我怎么可能伪造dataTransfer属性,我应该全部设定。

附注:

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

    < / LI>
  • 要查看拖放行为,请将JavaScript加载类型从no-wrap head更改为on-Load,然后您应该看到我正在尝试模拟的内容。

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

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

  • 此外,我正在使用Chrome。

提前致谢,如有任何问题/澄清,请与我联系!

2 个答案:

答案 0 :(得分: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)
}

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

答案 1 :(得分:1)

根据jsfiddel链接,您希望实现拖放功能。 jQuery Draggable UI 已经提供了此功能,为什么你不能使用它?

要在途中创建自定义活动,您必须遵循两种替代方式

$('your selector').on( "myCustomEvent", {
    foo: "bar"
}, function( event, arg1, arg2 ) {
    console.log( event.data.foo ); // "bar"
    console.log( arg1 );           // "bim"
    console.log( arg2 );           // "baz"
});

$( document ).trigger( "myCustomEvent", [ "bim", "baz" ] );

以上示例

在自定义事件的世界中,有两个重要的jQuery方法:.on()和.trigger()。在“事件”一章中,我们了解了如何使用这些方法来处理用户事件;对于本章,记住两件事很重要:

.on()方法将事件类型和事件处理函数作为参数。可选地,它还可以接收与事件相关的数据作为其第二个参数,将事件处理函数推送到第三个参数。传递的任何数据都可用于事件对象的data属性中的事件处理函数。事件处理函数总是接收事件对象作为其第一个参数。

.trigger()方法将事件类型作为其参数。或者,它也可以采用一组值。这些值将作为事件对象之后的参数传递给事件处理函数。

以下是在两种情况下使用自定义数据的.on()和.trigger()的使用示例:

jQuery.event.special.multiclick = {
    delegateType: "click",
    bindType: "click",
    handle: function( event ) {
        var handleObj = event.handleObj;
        var targetData = jQuery.data( event.target );
        var ret = null;

        // If a multiple of the click count, run the handler
        targetData.clicks = ( targetData.clicks || 0 ) + 1;

        if ( targetData.clicks % event.data.clicks === 0 ) {
            event.type = handleObj.origType;
            ret = handleObj.handler.apply( this, arguments );
            event.type = handleObj.type;
            return ret;
        }
    }
};

// Sample usage
$( "p" ).on( "multiclick", {
    clicks: 3
}, function( event ) {
    alert( "clicked 3 times" );
});

以上示例

multiclick特殊事件将自身映射到标准点击事件,但使用句柄挂钩,以便它可以监视事件,并且仅在用户单击指定次数的倍数时才传递事件在事件绑定期间。

钩子将当前点击计数存储在数据对象中,因此不同元素上的multiclick处理程序不会相互干扰。它在调用处理程序之前将事件类型更改为原始multiclick类型,并将其还原到映射的&#34;单击&#34;返回前输入: