The image in drag and drop ghost preview is not appearing on Firefox

I want to show a ghost element instead of the default browser preview while dragging and dropping. However, in Firefox, the image inside the ghost element is not displayed during dragging. Oddly enough, if I drop it and then drag again, the image does appear.

It seems like this could be a cache-related issue, but I'm unsure how to pre-cache the image in this scenario.

Here's the code snippet:

//html:

<div class="parent container">
<img class="element" src="http://www.thekrausemouse.com/wp-content/uploads/2016/03/Sample.jpg" draggable="true" />
</div>

//js:

document.querySelector(".element").addEventListener("dragstart", function(e) {
    var img = document.createElement("img");
    var div = document.createElement('div');
    div.style.width = '100px';
    div.style.height = '100px';
    div.style.position = 'fixed';
    div.style.top = '-1000000px';
    div.style.left = '-1000000px';
    div.style.border = '2px solid red';

    img.src = "http://www.thekrausemouse.com/wp-content/uploads/2016/03/Sample.jpg";
    img.style.width = '100px';
    img.style.height = '100px';
    div.appendChild(img);
    document.body.appendChild(div);
    e.dataTransfer.setData('text/plain', 'test');
    e.dataTransfer.setDragImage(div, 0, 0);
}, false);

Fiddle: https://jsfiddle.net/etseq5cg/5/

Follow these steps to recreate the issue:

1) Open the fiddle or run the snippet

2) Try to drag the sample image

Actual: You will only see an empty square with red border

Expected: You should see a square with the image inside

To reproduce the issue, you may need to force-reload the page (Ctrl+F5). This suggests that the problem might be related to caching.

Note: Removing the ghost element from the DOM in the dragend handler is not relevant to this case.

Update:

1) The real use-case involves a view with a large number of images (~500), so pre-caching images with JS is not a viable solution.

2) For those who couldn't replicate the issue, here's a screenshot: the initial preview after a hard reload (Ctrl+F5) and then the second drag attempt. It's worth noting that no HTTP requests are shown in the network tab of the web inspector in either case. https://i.stack.imgur.com/tAgRW.png

Answer №1

When testing your jsfiddle in Firefox 53 on Windows 7, I didn't encounter any issues with the ghost image and dragged image having the same URL. However, a problem arises when using a ghost image with a different URL.

To preload the ghost image, you can add a hidden img element like this:

<div class="container">
    <img class="element" draggable="true" src="http://the.element.image" />
    <img class="hiddenGhost" src="http://the.ghost.image" />
</div>

In my tests, I found that hiding the image using visibility: hidden worked better than other techniques such as display: none, null size, or moving it out of the viewport.

You can experiment with this method using two draggable images in this updated jsfiddle. Remember to adjust the ghost image names (e.g. 225x225) to ensure no caching issues.

If preloading the image is not an option for you, consider checking this resource for troubleshooting tips. Additionally, forcing a repaint after adding the div control to the body in the dragstart event handler might help. You can achieve this by calling div.offsetHeight:

div.appendChild(img);
document.body.appendChild(div);
div.offsetHeight; // Trigger repaint

Answer №2

When using CSS, apply the pseudo-class :hover to the .parent element and set the background of the .element element to url("/path/to/image") when hovered over. This will fetch the image at hover for the parent element. Additionally, during the dragstart event, set the className of the div to "element".

.element {
  width: 100px;
  height: 100px;
  background: url("http://www.thekrausemouse.com/wp-content/uploads/2016/03/Sample.jpg");
  background-size: 100px 100px;
  
}

.parent:hover {
  background: url("http://www.thekrausemouse.com/wp-content/uploads/2016/03/Sample.jpg");
  background-size: 0px 0px;
}
<div class="parent container">

  <img class="element" src="http://www.thekrausemouse.com/wp-content/uploads/2016/03/Sample.jpg" draggable="true" />

</div>
    <script>
    function handleImage(e) {
      var div = document.createElement('div');
      div.style.width = '100px';
      div.style.height = '100px';
      div.style.position = 'fixed';
      div.style.top = '-1000000px';
      div.style.left = '-1000000px';
      div.style.border = '2px solid red';
      div.className = "element";
      document.body.appendChild(div);
      e.dataTransfer.setData('text/plain', 'test');
      e.dataTransfer.setDragImage(div, 0, 0);
    }
 document.querySelector(".element")
 .addEventListener("dragstart", handleImage, false);
  </script>

Check out the code on jsfiddle here.

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

loading dynamic content into an appended div in HTML using Angular

Here is the HTML code from my app.component.html file: <button mat-raised-button color="primary" mat-button class="nextButton" (click)="calculatePremium()"> Calculate </button> <div id="calcul ...

"Is there a way to ensure that jPlayer plays the same song even after a page refresh

I have been working on integrating jPlayer with Ajax to ensure that when the page of my website is refreshed, jPlayer will continue playing its current song seamlessly. I have successfully stored track information and the current track during refresh, ho ...

Switching the markLine in vega lite to a markBar causes it to lose its sorting arrangement

I have created the following data visualization: data = [{"student_name": "student 0", "e": "100.15", "d": "127.81"}, {"student_name": "student 1", "e": "100.30", "d": "189.94"}, {"student_name": "student 2", "e": "100.15", "d": "105.33"}, {"student_nam ...

I am having trouble retrieving the content-length from the response headers within the app.use() middleware function

Can anyone help with retrieving the content-length from response headers within the app.use() middleware function? const app = express(); app.use((req, res, next) => { // Need to find a way to access content-length of res console.log("co ...

The CSS attribute selector is unable to target dynamically appended class names

Utilizing React's CSS animations add-on has been a seamless process, with everything running smoothly when using the provided classnames. .quote-enter { opacity: 0.01; transition: opacity .25s ease-in; } .quote-enter.quote-enter-active { opaci ...

Issue with JQuery: Logo only becomes visible after scrolling

Recently, I added a jQuery script to modify the header as we scroll on our website. Everything is functioning smoothly except for one issue - the large logo on the left side doesn't appear when visitors first land on the page; it only shows up after t ...

To make the down arrow image scroll to the end of the page after the 2nd click, simply follow these steps. Initially, the first click

After setting up the image icon and utilizing Javascript and jQuery, I encountered an issue with the down arrow functionality. The first click successfully takes me to the second row grid box downwards, but I am struggling to implement a second click actio ...

Is there a way to simulate a minified module for testing purposes?

For my project, I developed a component intended to function as a module. The implementation involves the utilization of third-party code provided in the form of a config file (initOpinionLab.js) and a .min.js file (opinionlab.min.js). As part of the devel ...

What is the best way to save the raw text or event-stream data from a JavaScript get request when the server is continuously loading?

Currently, I'm attempting to fetch some basic data from an API. Here is the URL for the request: The issue lies in the fact that the server appears to keep refreshing the page constantly. This endless loading occurs both when using a browser and with ...

Challenges with the height of the calendar component in Vuetify

I need assistance with preventing the appearance of two scroll bars while working with Vuetify's sheet and calendar components. https://i.stack.imgur.com/yBfhj.png Below is my code snippet: <template> <v-app> <v-main> & ...

Using values from an appsettings.json file as href variables in an AMP html: a complete guide

Currently developing an AMP website with the URL www-dev.example.com, directing users to a sign-up page. The sign-up page is hosted on an identity server under the subdomain auth.www-dev.example.com. Now, the goal is to deploy the AMP website to a staging ...

Error encountered when attempting to add document to Firebase database: admin:1. An unexpected FirebaseError occurred, stating that the expected type was 'Na', but it was actually a custom object

I am encountering an error when trying to add a document to my collection in Firebase. I have successfully uploaded an image to Storage and obtained the URL, but this specific step is causing issues. I have followed the code implementation similar to how F ...

The communication between the child and parent components is failing to function correctly

I'm trying to send data from a child component to a parent component, but the function isn't being invoked correctly. It doesn't seem to work as expected. <router-outlet (activeElement)='getActive($event)'></router-outlet ...

Determine the current iteration index within recurring tasks using BullJS

When working with repeatable job callbacks, I often need to perform specific actions at a certain point in the script. For instance: const Bull = require('bull'); const queue = new Bull('payment'); // This task should run every 5 minut ...

What is the method for formatting within the <textarea> element?

While working on developing a comment system, I recently made the discovery that text areas cannot be formatted to retain paragraphs, line breaks, etc. This was particularly noticeable when comparing sites like StackOverflow, which uses a text editor inste ...

Failure to trigger success function during ajax upload

My upload script features a progress bar to track file uploads. The file successfully uploads to the server and the progress bar is functioning as expected. However, the success function is not being triggered and I am unsure why. There are no errors in ...

Having difficulty using JavaScript regex to replace the middle of content?

I am working with a text name[one][1][two][45][text] Through this pattern, I am able to extract the number "45" /(.*?)rows\]\[([0-9]*)(.*)/; Now, my challenge is how can I change the only 45 to a different digit? Using the same pattern and re ...

Retrieve data from an API and store it in a JSON array

My website is having an issue where it's fetching data from an API and displaying it in a table, but all the cells are returning undefined values. The data in the API is structured as an array with multiple datasets inside curly braces that I am unsu ...

Generate several different elements

Is it possible to use Vue.js to render a component multiple times based on a variable? For instance, I have a size variable set to 5 and I want to display the Widget component 5 times. Here is my current code snippet: Template : <template> &l ...

An error popped up: "argument list is missing) after"

Encountered an issue: Error message: missing ) after the argument list $('.next-btn').append("<a class="actionsubmit" ng-click="onSubmit('hello.html')">Check</a>"); ...