简体   繁体   中英

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?

I came up with this JSFiddle that serves as a template of what I'm trying to do: 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.

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.

  • 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.

  • 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

  • Also, I'm using 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 . 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.

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/

As per jsfiddel link you want to achieve drag and drop feature. jQuery Draggable UI already provides this feature why you can not use that?

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(). 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. 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. 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:

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.

The hook stores the current click count in the data object, so multiclick handlers on different elements don't interfere with each other. It changes the event type to the original multiclick type before calling the handler and restores it to the mapped "click" type before returning:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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