JS - Activate the ghost element feature by using the preventDefault function

I am currently working on a project where I need to drag elements from a list of img tags to various svg:rect containers.

The process involves using mousedown and mouseup events to track which img is being picked from the list and where it is dropped within the svg:rect containers.

Below is the code snippet:

<body>

<div style="border: 1px solid black">
    <svg width="300" height="100">
        <rect id="container" width="60" height="60"></rect>
        <rect id="container2" x="70" width="60" height="60"  fill="salmon"></rect>
    </svg>
</div>

<div id="list">
    <img id="item" src="img/cat.png" width="64" />
</div>

<script>

    const container = document.getElementById('container');
    const container2 = document.getElementById('container2');
    const item = document.getElementById('item');

    let drag = null

    item.addEventListener('mousedown', function (e) {
        e.preventDefault();
        console.log('mouse down from IMG');
        drag = e.target;
    });

    container.addEventListener('mouseup', function (e) {
        e.preventDefault();
        console.log('Container 1', drag);
        drag = null;
    });

    container2.addEventListener('mouseup', function (e) {
        e.preventDefault();
        console.log('Container 2', drag);
        drag = null;
    });
</script>

My issue lies in the fact that by using e.preventDefault() in the img event listener, the ghost element effect is lost when dragging the image. Is there a way to maintain this effect while still utilizing the preventDefault() call?

Answer №1

The mysterious occurrence of the ghost element is due to the inherent draggable property of the <img> tag

To achieve the desired effect, one can utilize the ondragstart event on the image and pair it with the ondrop event on another element. You can refer to this example for guidance.

Regrettably, this method does not work with rect elements. One alternative solution could involve utilizing the onmouseover event on the rect elements, although the user would need to move the mouse after dropping for it to function correctly.

const container = document.getElementById('container');
const container2 = document.getElementById('container2');
const item = document.getElementById('item');

    let drag = null

function dragImg (e) {
        //e.preventDefault();
        console.log('ondrag IMG');
        drag = e.target;
    };

// Not working
function ondrop1 (e) {
        //e.preventDefault();
        console.log('Container 1', drag);
        drag = null;
    };

// Not working
function ondrop2 (e) {
        //e.preventDefault();
        console.log('Container 2', drag);
        drag = null;
    };
<div style="border: 1px solid black">
    <svg width="300" height="100">
        <rect id="container" onmouseover="ondrop1(event)" width="60" height="60"></rect>
        <rect id="container2" onmouseover="ondrop2(event)" x="70" width="60" height="60"  fill="salmon"></rect>
    </svg>
</div>

<div id="list">
    <img ondragstart="dragImg(event)" id="item" src="https://ddragon.leagueoflegends.com/cdn/8.22.1/img/champion/Velkoz.png" width="64" />
</div>

[EDIT] For a more seamless experience using rect elements, consider incorporating the ondrop event on the svg, then locate the rect element under event.target. Refer to documentation here for further details.

Best of luck!

Answer №2

Through thorough research and experimentation, I have identified two potential solutions:

Initial approach: Avoid using HTML5 drag and drop altogether.

Instead, utilize the mousedown event on the draggable element and mouseup event on the droppable element. Within the mousedown event, be sure to include a preventDefault() call to eliminate the ghost element effect during dragging. To recreate this effect, construct your own ghost element with CSS properties such as pointer-events: none and position: absolute.

Alternative solution: Employ the HTML5 drag and drop feature partially.

Add a dragstart event to the draggable element (image) and drop and dragover events to the droppable element (SVG). Within the drop event, check for e.target to obtain a reference to the svg:rect element.

An example can be found here: https://gist.github.com/EduBic/49e36485c70c5a6d15df7db1861333de

Note: Be sure to incorporate additional events and handle various scenarios accordingly.

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

Experiencing a surge in requests with LazyLoad enabled?

My website contains numerous images, most of which are displayed within a slider using SlickSlider.js with Lazyload. Although the page load time is 3.87 seconds, there are over 134 requests being made for these images. Upon closer inspection, I noticed th ...

Is it possible to configure node js to send an array instead of a string?

How can I modify the code to return a 2D array of the results? For example: clothes = [[1, "name", "desc"], [2, "name2", "desc2]] Can the 'res' variable send a list directly or do I need to create a list after returning it? app.get('/post&ap ...

What is the best way to update a targeted component in React when triggered by an event handler?

Your goal may seem straightforward, but getting a reference to a specific component using this is proving to be tricky. Here we have our App.js file: import React, { Component } from 'react'; import CoolBox from './coolBox.js'; import ...

How can I programmatically trigger a change event for a dropdown in Vue.js?

I am looking to trigger a dropdown change event within a Vue.js method. <select id="idDropdown" v-model="Result.Value" v-on:change.prevent="changeSelection($event, 'somevalue')"> How can I call the above `cha ...

Curved lines on canvas

I am currently using the stroke and path features in the canvas to create two lines, with the intention of giving them a curved, wave-like effect. I would like to achieve this without having to create an actual image in Photoshop. Is there anyone who can ...

React - Struggling to render an image received as a prop within a React component

Just starting out with React. I'm trying to figure out how to properly display an image from the props of my CheckoutProduct component inside an image HTML tag. Image displaying the Product item but failing to do so. Here's the code snippet: i ...

Assigning a JavaScript code block to execute exclusively on designated pages

I have implemented webpack to bundle all my .js files into one app.js, which is utilized across all pages in my project. However, I have encountered an issue where code intended for one page is impacting another page where it is not required. For example, ...

Integrating Whatsapp cloud API with a React web application allows for seamless communication between

I'm currently in the process of integrating my web application with the WhatsApp cloud API. While I've had success sending test messages, I am now looking to incorporate variables as outlined in the API documentation. However, I seem to be encoun ...

Modifying the input field value in React

I've been attempting to modify the value of an input field after selecting an item from the SelectField in the MaterialUI library. Despite my efforts, I have not yet succeeded. However, based on my research, everything I have written appears to be cor ...

What is the best way to continuously monitor MongoDB for updates and sync them with my user interface?

Looking to continuously monitor a user's notifications in MongoDB, updating them on specific actions and displaying updates on my React frontend without reloading every time the user logs in. I am currently utilizing Node and Mongoose models for datab ...

Using Beautiful Soup and Selenium to click on an SVG path in order to navigate to the subsequent page and extract information

I'm currently facing a challenge with a project that involves extracting data from a website table spanning across 7 pages. The specific table can be found on this website: . Navigating to the next page is done through an svg path, but I'm strugg ...

Optimizing TypeScript/JavaScript for both browser and Node environments through efficient tree-shaking

I am currently tackling a TypeScript project that includes multiple modules shared between a browser client and a Node-based server. Our goal is to bundle and tree-shake these modules using webpack/rollup for the browser, but this requires configuring the ...

Tips for detecting when a browser is closing in a web application that is integrated with a master page

Currently, I am working on a web application that uses a master page. I need to be able to detect when the user is closing the browser so that I can raise an event to clean up session variables. I attempted using the unload JavaScript event, but it seems ...

Issue with Bootstrap carousel - the carousel.on method is not recognized

I have implemented a standard Bootstrap carousel in my project: <div id="myCarousel" class="carousel slide" data-ride="carousel"> <ol class="carousel-indicators"> <li data-target="#myCarousel" data-slide-to="0" class="active"> ...

Is it possible to schedule a periodic GET request on the server-side without utilizing the client-side or frontend?

I am currently implementing a GET request to retrieve data from a third-party API. I want to regularly check for new data every 5-10 minutes on my backend. exports.get_alerts = async (req, res) => { const alertsUrl = `https://www.g2smart.com/g2smart/a ...

Changing a particular field value within an array of objects in Angular 4

I have a scenario where I created a class called security: class security { public id:number; public name:string; } Next, I initialized an array of security objects: let s:security[]=[{id:1,name:'Alex'},{id:2,name:'John'},{id:3,nam ...

Enhancing UI design with Vue.js

I'm attempting to customize elements using data from a JSON file in Vue.js: <div v-for="(item, index) in json._items" class="help-inner-callout" v-html="item.text" style="top:item.top; left: item.left;">&l ...

Is it possible for a memory leak to occur in node.js when using new Date()?

For this particular case, when updating an existing MongoDB document with new Date() causing a potential memory leak is a question that arises. One might wonder if allocating a new object with the new keyword necessitates manual deallocation to prevent lea ...

"Exploring the Dynamic Duo of AngularJS ngAnimate and animate.css

I've been working on getting my animation to function correctly with AngularJS and animate.css. In order to achieve this, I set up the SASS in the following way: .slide-animate { &.ng-enter, &.ng-leave{ } &.ng-enter { ...

Apply a border to the input field when the user enters or leaves the field, only if the value is

I am managing a few input fields and storing their information in an object. My goal is to click on an input field to focus on it, and if the field is empty or has a length greater than or equal to 0, I want it to display a red border. If I type somethin ...