Having trouble changing the cursor for draggables in Chrome while using vue.js?

In my attempt to change the cursor of a draggable item in Chrome, I have encountered difficulties. Despite trying various methods, nothing seems to be working. The solutions I found on Stackoverflow are outdated and incompatible with the current version of Chrome.

During dragging, the item gets copied to a container which serves as the dragimage for the draggable.

My goal is to have a grabbing cursor while dragging. Is there a way to achieve this? Any suggestions?

Please refer to my code snippet for an example:

new Vue({
el: '#app',
data: {
    text_drop: 'Droppable Area',
        text_drag: 'Drag Area',
        drag_elements: [
        {text: 'one', selected: true},
        {text: 'two', selected: false},
        {text: 'three', selected: false},
        {text: 'four', selected: false},
        ]
    },
    computed: {
        selected_elements(){
            let selected = [];
            this.drag_elements.map((drag) => {
                if(drag.selected){
                  selected.push(drag);
                }
            })
            return selected;
        }
    },
    methods: {
    drag_it(event){
        let html = document.getElementById("dragElement");
            let drop_docs = this.selected_elements;
            if(drop_docs.length > 1){
            let multiple = document.createElement('div');
                        multiple.classList.add('dragMultiple');
                        multiple.innerHTML = drop_docs.length + ' items';
                        html.innerHTML = '';
                        html.appendChild(multiple)
            }else{
                        html.innerHTML = event.target.outerHTML;
            }
event.dataTransfer.setData('text/plain', '' );
            event.dataTransfer.setDragImage(html, 0, 0);
            event.dataTransfer.effectAllowed = "move";
        }, 
        drag_over(event){
            document.documentElement.style.cursor="-webkit-grabbing";
        },
        drag_end(event){
            document.documentElement.style.cursor="default";
        },
        select(event, drag_element){
          if(event.metaKey || event.shiftKey){
             drag_element.selected = !drag_element.selected;
          } else {
             this.drag_elements.map((drag) => {
                if(drag === drag_element){
                    drag.selected = true;
                }else{
                    drag.selected = false;
                }
            })
          }
        }
    }
})
#Dragme{
  width: 200px;
  height: 50px;
  margin-left: 20px;
  text-align: center;
  border:1px solid black;
  float:left;
}

#Dragme:hover {
   cursor: -webkit-grab;
}

#Dragme:active {
   cursor: -webkit-grabbing;
}

   
#Dropzone{
  float: left;
  width: 500px;
  height: 100px;
  border: 1px solid;
  margin-bottom: 50px;
}

.selected{
  border: 2px solid yellow !important; 
}

.dragMultiple{
  border: 1px solid black;
  padding: 10px;
  background-color: white;
}

#dragElement{
  position: absolute;
  top: 400px;
}
<script src="https://vuejs.org/js/vue.min.js"></script>
<div id="app">
  <div id="Dropzone">{{text_drop}}</div>
  <div id="drag_elements">
  <div v-for="drag in drag_elements"
       @dragstart="drag_it"
       @dragover="drag_over"
       @dragend="drag_end"
       @mouseup="select($event, drag)"
       draggable="true" 
       :class="{selected: drag.selected}"
       id="Dragme">{{drag.text}}</div>
  </div>
</div>

<div id="dragElement">

</div>

Update I have found a solution that addresses the cursor issue. You can check out the answer here.

Make sure to include the dndclass.

Thank you!

Blockquote

A special thanks to Carr for the helpful hint.

Update After dragging or dropping, the cursor does not revert to its default state. It only changes back when moved again. Any thoughts on how to resolve this?

Update By using the command key on Mac or the shift key, it is possible to select and drag multiple items. A new dragitem is created for this purpose, but sometimes the cursor does not reset after dragging or dropping.

Update Integrating the method from Carr's answer.

Answer №1

It's important to note that the setDragImage api is used to set an image to replace the default document icon that appears next to the cursor during a drag operation, not the cursor itself. The code you provided for '.dragElement' does not work as expected - it proved to be unstable and caused strange effects during testing, so I have excluded it from my answer.

Below is a slightly complex solution that follows correct logic. However, there may be a more elegant approach available.

new Vue({
    el: '#app',
    data: {
        text_drop: 'Droppable Area',
        text_drag: 'Drag Area'
    },
    methods: {
        drag_it(event){
            event.dataTransfer.setData('text/plain', '' );
            event.dataTransfer.effectAllowed = "move";
        },
        drag_over(event){
            document.documentElement.style.cursor="-webkit-grabbing";
        },
        drag_end(event){
            document.documentElement.style.cursor="default";
        }
    }
})
#Dragme{
  width: 200px;
  height: 50px;
  text-align: center;
  border:1px solid black;
  float:left;
}
   
#Dragme:hover {
  cursor: -webkit-grab;
}

#Dragme:active {
  cursor: -webkit-grabbing;
}

#Dropzone{
  float: left;
  width: 300px;
  height: 100px;
  border: 1px solid;
  margin-bottom: 50px;
}
<script src="https://vuejs.org/js/vue.min.js"></script>
<div id="app">
  <div id="Dropzone">{{text_drop}}</div>
  <div @dragstart="drag_it"
       @dragover="drag_over"
       @dragend="drag_end"
       draggable="true" 
       id="Dragme">{{text_drag}}</div>
</div>

Update - Additional Issues Related to Original Question

  • The "dragImage" remains stuck at the bottom, all elements disappear, or flash intermittently.

https://i.sstatic.net/8tyD4.png

  • There is still an odd part where the id attribute should be unique:

https://i.sstatic.net/SFJu5.png

  • Additionally, here is a quote from the MDN documentation regarding setDragImage. I mistakenly mentioned using svg in a comment when it should actually be canvas:

... The image will typically be an <image> element but it can also be a <canvas> or any other image element. ...

  • We could also explore how to draw text on a canvas, which presents another interesting question to delve into.

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

Identifying iOS 5 or above using JavaScript

I've been experimenting with this code snippet to check if the browser is iOS 5 or newer (found on this Stack Overflow thread Detect iOS version less than 5 with JavaScript). function iOSversion() { if (/iP(hone|od|ad)/.test(navigator.platform)) ...

Troubleshooting the Checkbox Oncheck Functionality

Before checking out the following code snippet, I have a requirement. Whenever a specific checkbox (identified by id cfc1) is clicked, it should not show as checked. I have implemented the onCheck function for this purpose, but I'm struggling to fig ...

How can you merge one object with two different mongoose models?

Consider the scenario where I have two mongoose models set up: User Model Business Favorite Model Currently, I'm successfully retrieving the combined result if a user has any favorite businesses. However, I suspect that my current implementation mi ...

Ways to interact with similar dynamic controls in Javascript

I have an aspx page with a Select box control: <select name="selViewPerPage" id="selViewPerPage" style="width:30px"> To ensure consistent styling across all browsers, I am replacing this html control with a dynamic select box using "selectBox.js". ...

Having trouble selecting dropdown options using Selenium with Python?

I'm a beginner in using Selenium with Python and I'm attempting to retrieve index data from the Barclays Live website. After logging in and the page loads, I need to select 'Custom1' from a dropdown menu on the page. The HTML code for t ...

Tips for making a 2D grid on a webpage

Is there a way to implement a 10x10 grid on a webpage where users can click anywhere on the grid and have their (x, y) position recorded with one decimal place accuracy, covering values between 0.0-10.0 or 0.1-9.9? Appreciate any guidance! ...

Adjusting Font Size on a Website: A Quick Guide

I recently started diving into the world of building web pages. To practice, I created a simple site but for some reason, I'm having trouble changing the text size. When I try to remove the background image code, it seems to work fine, but I can&apos ...

Modify the background color when hovering using jquery

In order to have buttons with variable colors and a different hover color, I have to apply inline CSS. Since the hover color cannot be added using inline CSS, I need to use JavaScript. I attempted to achieve this using the .hover() function, but the colors ...

What is the best way to set up an anchor element to execute a JavaScript function when clicked on the left, but open a new page when clicked in

One feature I've come across on certain websites, like the Jira site, is quite interesting. For instance, if we take a look at the timeline page with the following URL - When you click on the name of an issue (which is an anchor element), it triggers ...

Tips for programmatically adding together numerous input entries within a PHP while loop utilizing java-script on the onfocusout event

Currently, I am working on a method to determine the value of the following id: id="salenag<?php echo $a; ?>". This involves fetching multiple values from a database using PHP and then summing them up before injecting the total into an in ...

How can errors for assets on a Vue build be disregarded?

In the process of developing a Vue project that involves static files, I have configured the following in my package.json for local serving: { ... "eslintConfig": { ... "ignorePatterns": [ "**/vendor/*.js" ...

The API for executing Apps Script returns an unauthenticated error

My application is encountering an issue with the Apps Script execution API, while other APIs are functioning properly. The error code 401 is being thrown with the message: "Request is missing required authentication credential. Expected OAuth 2 access toke ...

VueJS datepicker displays correctly on the screen, but is not sending the date in the expected format

We have implemented a datepicker plugin that displays the date in the correct format, but when it is sent to the server or database, it reverts back to the default datepicker format. <datepicker v-model="model.date" placeholder="Choose date" :for ...

Interact with visible elements by automating mouse clicks with puppeteer

When attempting to click on various elements within a page, my goal is to do so only if they are visible. While achieving this in selenium with the is_displayed method was simple, I have struggled to find a similar approach in puppeteer. I attempted to imp ...

What should I do if one of my images fails to load after the previous one has loaded successfully?

My code is designed to create an animation using 3 canvases: one for the base image, one for the streamline wind map drawing, and another for an image covering part of the drawing. The following code displays the uploading of two images. var im ...

Using regex to replace problems with line breaks with BR tags

I have a block of text that I need to modify by replacing BR tags with \n in order to create new lines. D:\HP\ConfigurationServer_3464\log\nvdmr***.log ~ File not found<br>D:\HP\DCSSchedulerAgent_3478\logs&bso ...

Transferring items between different containers without using innerHTML

I've got an embedded <ul> within a (hidden) <aside id="idDetails">. How can I move the ul element from inside the aside and position it in a <div id="projectSide"> without using innerHTML? Any solutions in both plain JavaScript and j ...

Inputting information into a designated field and then showcasing the entered text in a separate location on the webpage

While working on creating a checkout page, I encountered an issue that I could not find a solution for. I want to display the shipping information entered by the customer in a confirmation section further down on the page. However, I do not plan to submit ...

retrieve information at varying intervals through ajax

In my web page, there are two div elements that both fetch server data using AJAX. However, div-a retrieves data every second while div-b retrieves data every minute. How can I adjust the frequency at which each div fetches server data? ...

Implementing long polling for private messaging in PHP's chat functionality

Can you help me with a question I have regarding my chat form on the HTML page? Here is the code for the form: <form action="../addchat.php" method="POST" enctype="multipart/form-data"> <textarea id="textarea" style="border- ...