简体   繁体   English

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

[英]How to trigger an event with a custom event (specifically a custom dataTransfer property)?

I'm currently attempting to test some code that uses drag-and-drop. 我目前正在尝试测试一些使用拖放的代码。 I found some other questions that were kinda related to this, but they were way too specific to help me, or not related enough. 我发现了一些与此相关的其他问题,但是它们太具体了而无法帮助我,或者相关性不够。

This being a test, I'm struggling on trying to automatically execute code inside a .on('drop',function(e){....} event. The main issue is not that I can't run the code inside, but it's that I can't transfer the dataTransfer property, and I can't seem to fake it because it's read-only. Is there anyway to fake the dataTransfer property or otherwise get around it? 这是一个测试,我努力尝试在.on('drop',function(e){....}事件中自动执行代码。主要问题不是我无法在其中运行代码,但这是因为我无法传输dataTransfer属性,而且由于它是只读的,因此我似乎无法伪造它。是否总有可能伪造dataTransfer属性或解决它?

I came up with this JSFiddle that serves as a template of what I'm trying to do: https://jsfiddle.net/gnq50hsp/53/ 我想出了这个JSFiddle,它充当了我想要做的事情的模板: https ://jsfiddle.net/gnq50hsp/53/

Essentially if you are able to explain to me (if this is at all possible) how I can possibly fake the dataTransfer property, I should be all set. 本质上,如果您能够向我解释(如果有可能的话)我如何可以伪造dataTransfer属性,那么我应该已经准备dataTransfer

Side notes: 旁注:

  • I'm totally open to other ways of somehow getting inside that code, like for example, maybe its possible to trigger the event and pass in a fake event object with a fake dataTransfer object. 我完全欢迎以其他方式进入该代码的其他方式,例如,也许可以触发事件并使用伪造的dataTransfer对象传递伪造的事件对象。

  • To see the drag-drop behavior, change the JavaScript load type from no-wrap head to on-Load , then you should see what I'm trying to simulate. 要查看拖放行为,请将JavaScript加载类型从no-wrap head更改为on-Load ,然后您应该看到我要模拟的内容。

  • Important to note that I cannot modify any of the code inside the event handlers, only inside the outside function 请注意,我不能修改事件处理程序内部的任何代码,只能在外部函数内部进行修改

  • Using Karma/Jasmine so use of those tools are also possible like spies 使用Karma / Jasmine,因此也可以像间谍一样使用这些工具

  • Also, I'm using Chrome. 另外,我正在使用Chrome。

Thanks in advance, and let me know for any questions/clarifications! 在此先感谢您,如有任何问题/疑问,请通知我!

You should be able to override pretty much everything you want using Object.defineProperty . 您应该能够使用Object.defineProperty覆盖几乎所有您想要的东西 Depending on what you want to test it can be very simple or very complex. 根据您要测试的内容,它可能非常简单也可能非常复杂。 Faking the dataTransfer can be a bit tricky, since there's a lot of restrictions and behaviors linked to it, but if you simply want to test the drop function, it's fairly easy. 伪造dataTransfer可能会有些棘手,因为与它相关的约束和行为很多,但是如果您只想测试drop函数,那将非常容易。

Here's a way, this should give you some ideas as to how to fake some events and data: 这是一种方法,它应该为您提供有关如何伪造某些事件和数据的一些想法:

//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/ https://jsfiddle.net/0tbp4wmk/1/

As per jsfiddel link you want to achieve drag and drop feature. 按照jsfiddel链接,您要实现拖放功能。 jQuery Draggable UI already provides this feature why you can not use that? jQuery的可拖动的UI已经提供了这个功能为什么不能使用?

For create custom event on your way you have to follow two alternative ways 要以自己的方式创建自定义事件,您必须遵循两种替代方式

$('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" ] );

On above example 在上面的例子中

In the world of custom events, there are two important jQuery methods: .on() and .trigger(). 在自定义事件的世界中,有两种重要的jQuery方法:.on()和.trigger()。 In the Events chapter, we saw how to use these methods for working with user events; 在“事件”一章中,我们了解了如何使用这些方法来处理用户事件。 for this chapter, it's important to remember two things: 对于本章,记住两件事很重要:

.on() method takes an event type and an event handling function as arguments. .on()方法将事件类型和事件处理函数作为参数。 Optionally, it can also receive event-related data as its second argument, pushing the event handling function to the third argument. 可选地,它还可以接收与事件相关的数据作为其第二个参数,从而将事件处理功能推到第三个参数。 Any data that is passed will be available to the event handling function in the data property of the event object. 传递的任何数据将提供给在事件对象的数据属性的事件处理函数。 The event handling function always receives the event object as its first argument. 事件处理函数始终将事件对象作为其第一个参数。

.trigger() method takes an event type as its argument. .trigger()方法将事件类型作为其参数。 Optionally, it can also take an array of values. (可选)它也可以采用值数组。 These values will be passed to the event handling function as arguments after the event object. 这些值将作为事件对象之后的参数传递给事件处理函数。

Here is an example of the usage of .on() and .trigger() that uses custom data in both cases: 这是在两种情况下都使用自定义数据的.on()和.trigger()用法的示例:

OR 要么

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" );
});

On above example 在上面的例子中

This multiclick special event maps itself into a standard click event, but uses a handle hook so that it can monitor the event and only deliver it when the user clicks on the element a multiple of the number of times specified during event binding. multiclick特殊事件本身映射到一个标准的click事件,但使用的是手柄挂钩,以便它可以监视活动,只有提供它在元素上的用户点击事件中的指定次数的倍数结合。

The hook stores the current click count in the data object, so multiclick handlers on different elements don't interfere with each other. 钩存储当前点击计数在数据对象,所以multiclick处理程序不同的元件不相互干扰。 It changes the event type to the original multiclick type before calling the handler and restores it to the mapped "click" type before returning: 它改变事件类型为原始multiclick类型返回之前调用处理和恢复它映射的“点击式”前:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM