Lajos Arpad
Lajos Arpad

Reputation: 76490

How to issue a dragstart event with jQuery?

I have an event like this:

        $(document).on('dragstart', '#' + gridID + ' tr.rgRow, #' + gridID + ' tr.rgAltRow ', function (ev) {
            console.log(ev);
        });

I would like to issue a dragstart event, like this:

$(".rgRow > td, .rgAltRow > td").filter(function() {
    return $(this).text().trim() === "UTT000000899103";
}).parent().dragstart();

parent() finds the right tr, but dragstart is undefined. So, how should I proceed instead?

EDIT:

Based on a comment by A. Wolff I have tried .parent().trigger('dragstart') but I get an error. Now I try it like this:

    $(document).on('dragstart', '#' + gridID + ' tr.rgRow, #' + gridID + ' tr.rgAltRow ', function (ev) {
        console.log(ev);
        var e = ev.originalEvent;
        e.dataTransfer.effectAllowed = 'move';
    });

and

$(".rgRow > td, .rgAltRow > td").filter(function() {
    return $(this).text().trim() === "UTT000000899103";
}).parent().trigger("dragstart");

But I get an error, as ev.originalEvent.dataTransfer is undefined. So I wonder how should I define the originalEvent.

EDIT2:

I have been trying with this code:

$(".rgRow > td, .rgAltRow > td").filter(function() {
    return $(this).text().trim() === "UTT000000899103";
}).parent()[0].dispatchEvent(new Event("dragstart"));

it returns true, but does not run the handler defined in the .on().

EDIT3:

I have managed to call dispatchEvent() which will be executed by the handler like this:

$(".rgRow > td, .rgAltRow > td").filter(function() {
    return $(this).text().trim() === "UTT000000899103";
}).parent()[0].dispatchEvent(new CustomEvent("dragstart", {
    bubbles: true,
    dataTransfer: {}
}));

It is executed because of bubbles: true. However, the error is:

Uncaught TypeError: Cannot set property 'effectAllowed' of undefined

EDIT4:

Based on A. Wolff's comment I have tried this code:

var dragEvent = document.createEvent("HTMLEvents"); dragEvent.initEvent("dragstart", true, true); 
dragEvent = $.extend(dragEvent, {dataTransfer: {effectAllowed: null}}); 
$(".rgRow > td, .rgAltRow > td").filter(function() { return $(this).text().trim() === "UTT000000899103"; }).parent().each(function(){ this.dispatchEvent(dragEvent); });

which almost solves the problem. The only missing piece of the puzzle is that I need to call dataTransfer.setData inside the handler like this:

            e.dataTransfer.setData('text', JSON.stringify(data));

where data is an initialized JSON.

Upvotes: 2

Views: 1224

Answers (1)

Lajos Arpad
Lajos Arpad

Reputation: 76490

I have solved my problem using this function:

TT.CustomEvent = function () {
    var me = this;
    var overrideMode = false;
    var customEvents = [];
    this.getEvent = function(type, data) {
        if ((!customEvents[type]) || (overrideMode)) {
            var event = document.createEvent("HTMLEvents");
            event.initEvent(type, true, true);
            event = $.extend(event, {
                dataTransfer: {
                    effectAllowed: null,
                    setData: function (key, value) {
                        if (!event.data) {
                            event.data = {};
                        }
                        event.data[key] = value;
                    },
                    getData: function (key) {
                        if (event.data) {
                            return event.data[key];
                        }
                    }
                }
            });
            customEvents[type] = event;
        }
        if (data) {
            customEvents[type].dataTransfer.setData(data.key, data.value);
        }
        return customEvents[type];
    }

    this.dispatchEvent = function (target, event, data) {
        overrideMode = true;
        var currentEvent = me.getEvent(event, data);
        target.each(function () {
            this.dispatchEvent(me.getEvent(event, data));
        });
        overrideMode = false;
    }

};

Using this I can call getEvent, which returns the last event of a certain type or dispatchEvent, which will generate a new event of a certain type and will dispatch it. I have a dragstart event, which will write an element with key 'text' and value of a certain JSON into dataTransfer, using setData. Example usage:

                    customEvent.dispatchEvent(woContext, "dragstart");
                    techListWindow.dispatchEvent(selectedTech["Tech Name"], "drop", {key: "text", value: customEvent.getEvent("dragstart").dataTransfer.getData("text")});
                    customEvent.dispatchEvent(woContext, "dragend");

where woContext is a jquery result, techListWindow is inside an iframe or a separate tab and has a function like this:

function dispatchEvent(target, event, data) {
    customEvent.dispatchEvent($("#techTable .row .tooltip-link").filter(function() {
        return $(this).text().trim() === target.trim(); 
    }).parent(), event, data);
}

It works well.

Upvotes: 2

Related Questions