Firefox fails to trigger HTML drag event

After successfully implementing draggable header columns on a table using Chrome as my browser, I encountered an issue when testing it in Firefox (version 17.0.1). It seems that the drag event does not fire in Firefox, although the dragstart event does. To simplify the problem, I have included the following markup below. In Chrome, the top label updates with each mouse movement during dragging, but in Firefox it remains at 0.

<!DOCTYPE html>
<html>
<head>
<title>TH Drag Test</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<style>
table,td,th {
    border: solid thin black;
}
</style>
<script>
    $(document).ready(function() {
        $("th").bind("drag", function(event) {
            $("#lbl").html(event.originalEvent.offsetX);
        });
    });
</script>
</head>
<body>
    <span id="lbl">0</span>
    <table>
        <thead>
            <tr>
                <th draggable="true">Column A</th>
                <th draggable="true">Column B</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>One</td>
                <td>Two</td>
            </tr>
            <tr>
                <td>Three</td>
                <td>Four</td>
            </tr>
        </tbody>
    </table>
</body>
</html>

Answer №1

Dealing with this particular challenge in Firefox gave me nightmares. I had to drag a div onto a diary and identify the coordinates of the drop to determine the date and time selected by the user.

To trigger the drag event, I included the following line in the dragstart event handler:

event.dataTransfer.setData('Text', this.id);

The most difficult aspect was figuring out how to obtain the x and y coordinates when the dragging ended, as Firefox does not provide this information in the dragend event handler. I experimented with mouse events as suggested earlier, but realized they only work after the dragend event handler is called. Therefore, I decided to use the dragend event to detect when the user released the div, then utilized the subsequent mouse move event to fetch the coordinates and perform any necessary tasks. This method proved effective across IE, Firefox, and Chrome. Here's the HTML/JavaScript code for a demo:

<div>
<div id="todrag" class="testdiv" draggable="true"><p>Please drag me</p></div>

<div id="destination" class="testdiv"><p>To here</p></div>
<p id="coords"></p>
<p id="compareords"></p>
</div>

<script>
    var down = true;
    var m_xcoordDrag = 0;
    var m_ycoordDrag = 0;
    var m_xcoordMove = 0;
    var m_ycoordMove = 0;
    var m_dragReleased = false;
    var m_coordselement = document.getElementById("coords");
    var m_compareordselement = document.getElementById("compareords");

    function OnMouseMove(e) {
        m_xcoordMove = e.x;
        m_ycoordMove = e.y;
        m_coordselement.innerHTML = e.x + "," + e.y;

        if (m_dragReleased) {
            m_compareordselement.innerHTML = "X:" + m_xcoordDrag + ", " + m_xcoordMove + " Y:" + m_ycoordDrag + ", " + m_ycoordMove;

            m_dragReleased = false;
        }
    }

    dragstart = function(event) {
        event.dataTransfer.setData('Text', this.id);
        stop = false;
    }

    dragend = function(event) {
        m_dragReleased = true;

        m_xcoordDrag = event.x;
        m_ycoordDrag = event.y;
    }

    document.onmousemove = OnMouseMove;

    var toDrag = document.getElementById("todrag");

    toDrag.addEventListener('dragstart', dragstart);
    toDrag.addEventListener('dragend', dragend);

</script>

I trust that this explanation proves helpful!

Answer №2

The section that has been removed http://pastebin.com/bD2g3SqL

UPDATE:

This method does function properly, however, I am still unable to access the offsetX and offsetY properties as the Firefox version of the event does not include them for some reason.

<!DOCTYPE html>
<html>
<head>
<title>Drag Test Sample</title>
<style>
table,td,th {
    border: solid thin black;
}
</style>
<script>
    function Initialize(){
        var elements= document.getElementsByTagName("th");
        var counter = 0;

        for (var i=0; i<elements.length; i++){
            elements[i].addEventListener('drag', function (e){
                document.getElementById("lbl").textContent= counter++;
            }, false);
        }

        for (var i=0; i<elements.length; i++){
            elements[i].addEventListener('dragstart', function (e){
                e.dataTransfer.setData('text/plain', 'node');
            }, false);
        }
    }
</script>
</head>
<body onload="Initialize();">
    <span id="lbl"></span>
    <table>
        <thead>
            <tr>
                <th draggable="true">Column A</th>
                <th draggable="true">Column B</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>One</td>
                <td>Two</td>
            </tr>
            <tr>
                <td>Three</td>
                <td>Four</td>
            </tr>
        </tbody>
    </table>
</body>
</html>

It seems like you need to "initialize" the drag (source.)

UPDATE 2:

There appears to be a bug in the drag event that doesn't update the clientX and clientY properties (source.) They are updated on different events like the dragover event, but that event only occurs when the object is being dragged over a possible drop target. One way to handle this issue would be something as basic as this:

<!DOCTYPE html>
<html>
<head>
<title>Drag Test Sample</title>
<style>
table,td,th {
    border: solid thin black;
}
</style>
<script>    
    var pressed= false;

    document.onmousemove= OnMouseMove;

    function Initialize(){
        var elements= document.getElementsByTagName('th');

        for (var i=0; i<elements.length; i++){
            elements[i].onmousedown= OnMouseDown;
        }

        document.onmouseup= OnMouseUp;
    }

    function OnMouseDown(e){
        pressed= true;
    }

    function OnMouseUp(e){
        pressed= false;
    }

    function OnMouseMove(e){
        if (!pressed) return;

        document.getElementById('lbl').textContent= e.pageX ? ('x: ' + e.pageX + ' y: ' + e.pageY) : ('x: ' + (e.clientX + document.documentElement.scrollLeft + document.body.scrollLeft) + ' y: ' + (e.clientY + document.documentElement.scrollTop + document.body.scrollTop));
    }

</script>
</head>
<body onload="Initialize();">
    <span id="lbl"></span>
    <table>
        <thead>
            <tr>
                <th draggable="true">Column A</th>
                <th draggable="true">Column B</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>One</td>
                <td>Two</td>
            </tr>
            <tr>
                <td>Three</td>
                <td>Four</td>
            </tr>
        </tbody>
    </table>
</body>
</html>

Answer №3

For Firefox to work properly, it is necessary to set 'init' in the dragstart event so that all subsequent drag events can function correctly.

This requirement may be due to the fact that all DOM elements are automatically set as draggable in XUL. (source: https://bugzilla.mozilla.org/show_bug.cgi?id=646823#c4)

Here's an example:

<div id="something" draggable="true" ondragstart="event.dataTransfer.setData('text/plain', 'node');">Drag me</div>

Unlike Firefox, Chrome does not require this type of initialization.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Classify JavaScript Array Elements based on their Value

Organize array items in JavaScript based on their values If you have a JSON object similar to the following: [ { prNumber: 20000401, text: 'foo' }, { prNumber: 20000402, text: 'bar' }, { prNumber: 2000040 ...

How can Bootstrap's Collapse be activated without relying on buttons or anchor tags?

Is there a way to activate Bootstrap's Collapse feature when a user selects a Radio button, like this: <input type="radio" name="radios" value="More" data-toggle="collapse" href="#collapseExample"> <div class="collapse" id="collapseExample" ...

I'm having trouble removing an element from an array. The splice() method doesn't seem to be working properly

I start by creating an array like this: let myArray = []; Next, I add Number elements to the array: myArray.push(myNumber); When I call myArray.toString(), the array looks like this: 1,4,3,9 I have been attempting to remove certain elements using t ...

Performing asynchronous operations in React with axios using loops

On the backend, I have a socket set up to handle continuous requests from the server. Now, my goal is to send requests to the backend API continuously until a stop button is clicked. Using a loop for this task is considered bad practice as it never checks ...

Utilizing Jquery to enhance slide image transitions with navigational links

As a newcomer to jQuery, I am attempting to create a slider using jQuery. Here is the script I have so far: $(function() { var bgCounter = 0, text = [ 'some html code here', 'some html code here', 'some ...

Exploring the idea of how a Node.js server works

Although I have a good understanding of jQuery, I am new to modern JavaScript frameworks that have been introduced in the past few years. In the example provided, I can see how index.html functions and how server.js handles requests from it. However, I am ...

The video.play() function encountered an unhandled rejection with a (notallowederror) on IOS

Using peer.js to stream video on a React app addVideoStream(videoElement: HTMLVideoElement, stream: MediaStream) { videoElement.srcObject = stream videoElement?.addEventListener('loadedmetadata', () => { videoElement.play() ...

Activate Keyboard and Background in the Bootstrap Modal

I have set up my modal to disable the escape key and backdrop by default. $(modal).modal({ backdrop: "static", keyboard: false }); However, at a later time, I want to enable them again. $(modal).modal({ backdrop: true, keyboard: true }); The is ...

Learn the process of dynamically adding components with data to a list of objects using React JS

In my current project, I am working with a component list that consists of MUI chips. These chips have specific props such as 'label' and 'callback', which I need to incorporate into the list when an onClick event occurs. Each chip shou ...

The functionality of ellipsis, which consists of three dots, allows the text to expand

I am trying to implement a feature where the extra text is represented by three dots (...) as an ellipsis, and upon clicking the dots, the text should expand and contract. However, the current code only contracts the text and does not expand it upon clicki ...

Is it possible to utilize Angular's $http.get method with a dynamic route

I recently started working with Angular and I'm trying to figure out how to retrieve data from a REST API using a scope variable to determine the URI for the GET request. Imagine that I have an array of numbers being generated by a service in my app ...

Transform nested entities into a single entity where any properties that are objects inherit from their parent as prototypes

Exploring a new concept. Consider an object like: T = { a: 2, b: 9, c: { a: 3, d: 6, e: { f: 12 } } } The goal is to modify it so that every value that is an object becomes the same object, with the parent object as prototy ...

Pass the values of both buttons to a different page using PHP

I am currently developing a system for a hospital. The data is sourced from an array and I need to pass the values from two buttons to another page. For example, on the initial page: 1 xyz First 2017-04-08 11:35:00 body checkup Generate Presc ...

Set up a targeted version of the winston software package for installation

Can I download a specific version of winston through npm by using the command: npm install winston=2.2.0 The reason I am asking is because I am encountering an issue with my existing code written in version 2.2.0 when I download the latest version. The ...

Incorporating external CSS links in the metadata of Next.js 13

A recent update in Nextjs 13 introduced a new feature known as Metadata (https://nextjs.org/docs/app/api-reference/functions/generate-metadata), causing the removal of Head.js. Previously, I would import a CSS file using the <Head> tag as shown below ...

Tips for customizing bootstrap's fixed navbar-default to ensure that the list items align downwards:

Is it possible to customize the bootstrap fixed navbar-default so that the li elements align downward instead of at the top? If you have any corrections or custom solutions, I'd love to see them! Feel free to share your code on platforms like CodePen, ...

Would it be considered acceptable practice to implement a setTimeout on the loading state to ensure that the log in page does not momentarily appear before the user has completed the authentication process?

Currently, I am developing a React Native application and encountered a situation where the login page was flashing before the user authentication. To solve this issue, I added a setTimeout function as shown below: export default function App() { const [ ...

how to properly position an image using javascript

I have two tilesheet images and I have successfully rendered them, but I am struggling to figure out how to place the character in front of the map. https://i.stack.imgur.com/n1a3Q.png I have placed these images in two different JavaScript files. This i ...

AngularJS is not displaying the interface changes as expected

I have a list that is unordered, and whenever I click on a ListItem, it triggers the setActive() function. <li ng-repeat="slide in data" ng-click="setActive(slide.slideIndex)"> <span class="listItemText"> <b>{{slide.slideIndex + 1} ...

Jquery panoramic slider - Dynamically adjusting image width to fit screen size

Currently, I am attempting to implement a popular panning slider called Jquery Panning Slider for a website. The details regarding the markup structure, CSS, and jQuery can be found here: Slider Details. However, I encountered an issue with this slider. ...