Is there a way to control the quantity of items that can be dragged to the drop area with dragula?

I'm struggling with a drag-and-drop issue that involves limiting the number of elements in a drop-area to two. I am using the dragula library for this task:

  • If there are fewer than two elements in the drop-area, allow adding a new element from the draggable;
  • If there are already two elements in the drop-area, the user should only be able to add another element if they return one of the existing elements back to the draggable.

Below is the code snippet I have been working on:

  function $(id) {
  return document.getElementById(id);
}

dragula([$('draggable'), $('drop-area')], {
  revertOnSpill: true
});
#chart, #chart tr {
    border: solid 3px;
    width: 1000px;
    border-collapse: collapse;
    font-family: "Almarai";
    font-size: 20px;
}
#chart {
    position: relative;
    left: 200px;
}
#chart #drop-area {
    height: 100px;
}
.gu-mirror {
  position: fixed !important;
  margin: 0 !important;
  z-index: 9999 !important;
  padding: 1em;
}
.gu-hide {
  display: none !important;
}
.gu-unselectable {
  user-select: none !important;
}
.gu-transit {
  opacity: 0;
}
.gu-mirror {
  opacity: 1;
}
<script src="https://rawgit.com/bevacqua/dragula/master/dist/dragula.js"></script>
<table id="chart">
<tr>
<td id="drop-area">
</td>
</tr>
</table><br>
<div id="draggable">
<div id="a1">option 1</div>
<div id="a2">option 2</div>
<div id="a3">option 3</div>
<div id="a4">option 4</div>
<div id="text"></div>

Answer №1

Exploring the dragula API opens up a range of possibilities for handling events in different ways.

One approach is to utilize the on('drop', callback) event to monitor children length and incorporate cancel() when necessary.

In addition, leveraging the on('over') event can facilitate class changes on the drop zone, while on('cancel') helps remove any unwanted changes.

The abundance of available events provides ample room for experimenting and enhancing the user interface as needed.

function $(id) {
  return document.getElementById(id);
}

const dropContainer = $('drop-area');

const drake = dragula([$('draggable'), dropContainer], {
  revertOnSpill: true
});

drake.on('drop', function(el, target, source, sibling) {
  if (target.matches('#drop-area') && target.children.length > 2) {
    drake.cancel()
  }
});

drake.on('cancel', function(el, container, source) {
  console.log('Cancelled')
  dropContainer.classList.remove('invalid')

})

drake.on('over', function(el, container, source) {
  if (container !== source && container.matches('#drop-area')) {
    // moved from source to dropzone
    if (container.children.length === 2) {
      container.classList.add('invalid')
    }
  }
})
#chart,
#chart tr {
  border: solid 3px;
  width: 1000px;
  border-collapse: collapse;
  font-family: "Almarai";
  font-size: 20px;
}

#drop-area.invalid {
  background: yellow;
  color: red
}

#chart {
  position: relative;
  left: 200px;
}

#chart #drop-area {
  height: 100px;
}

.gu-mirror {
  position: fixed !important;
  margin: 0 !important;
  z-index: 9999 !important;
  padding: 1em;
}

.gu-hide {
  display: none !important;
}

.gu-unselectable {
  user-select: none !important;
}

.gu-transit {
  opacity: 0;
}

.gu-mirror {
  opacity: 1;
}
<script src="https://rawgit.com/bevacqua/dragula/master/dist/dragula.js"></script>
<table id="chart">
  <tr>
    <td id="drop-area">
    </td>
  </tr>
</table><br>
<div id="draggable">
  <div id="a1">option 1</div>
  <div id="a2">option 2</div>
  <div id="a3">option 3</div>
  <div id="a4">option 4</div>
  <div id="text"></div>

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

Bring in a collection of classes of various types from one TypeScript file to another

In my code file exampleA.ts, I define an object as follows: import { ExampleClass } from 'example.ts'; export const dynamicImportations = { ExampleClass }; Later, in another file named exampleB.ts, I import an array that includes class types and ...

Guide on importing all exported functions from a directory dynamically in Node.js

In my file main.ts, I am looking to efficiently call imported functions: import * as funcs from './functions'; funcs.func1(); funcs.func2(); // and so forth... In the same directory as main.ts, there is a functions directory containing an index ...

Failure to transfer form input values to PHP script

Currently, I am developing an email form that utilizes AJAX to connect to an external PHP file using PHPMailer for sending emails. In the beginning of the PHP file, I have the following code: if(count($_POST) > 0){ $message= 'Full Name: & ...

Experience the magic of Materialize CSS SideNav

I'm currently attempting to implement the mobile side navigation provided by Materialize. I've managed to display the menu icon, but when I click on it, nothing happens. It seems like the function is not being triggered, and there are no errors s ...

What are the steps for creating a standalone build in nextJS?

Currently, I am undertaking a project in which nextJS was chosen as the client-side tool. However, I am interested in deploying the client as static code on another platform. Upon generating a build, a folder with all the proprietary server elements of ne ...

Is it possible for the outcome of a component to be passed to render and actually show up as undefined

I am currently working on creating a wrapper component for an API call in order to display "loading" if the API hasn't updated yet. As I am new to React, I am struggling with passing the state to the ApiResp component: After checking the console.log ...

Slider Adjusts Properly on Chrome, but Not on Firefox

Visit this URL This link will take you to the QA version of a homepage I've been developing. While testing, I noticed that the slider on the page works perfectly in Chrome and IE, but has layout issues in Firefox where it gets cutoff and moved to th ...

When attempting to retrieve information, the variable is displaying as undefined, although the console log is indicating that data

Here is the code I am currently using: function get_last_chat_time(steamid){ if(!db_connect) { return 0; } chat_db.aggregate( [ {"$match":{"name":"chat-msg",steamid: steamid}}, { "$sort" : { date : -1 } }, {"$limit" : 1} ...

Tips for connecting 2 Bootstrap 5 carousels

I currently have 2 Bootstrap 5 carousels (carousel-a & carousel-b) on the same page and I want them to be synchronized with each other. I believe this can be achieved using JavaScript, but I am not very familiar with it. Below is the structure of carousel- ...

Error: Attempting to append a child to a non-existent property

I am currently learning Java Script and this is the code I have been working on. <!doctype html> <html> <head> <style> div {position:absolute; width:500px; height:500px} img {position:absolute} ...

What is the process for sending body data through Swagger in a Node.js/Express environment?

Below is the configuration for my swagger: /** * @swagger * /api/addData: * post: * consumes: * - text/html * produces: * - text/html * parameters: * - name: author * in: body * required: true * ...

A malfunction report stemming from an HTTP error code while using react.js/javascript

In my react.js application, I have a Component that displays an error code. It currently looks like this: https://i.stack.imgur.com/2usiy.png Now, in addition to displaying just the code, I also want to show the reason for the error. Similar to how this ...

Dynamic display without AJAX

I need assistance with two drop-down lists where the second list's values should change based on the selection made in the first list. The current set up of the drop-down lists is as follows: <select name="first"> <option name="a" va ...

Identifying an Android device using Javascript or jQuery

Is there a way to identify an Android device for styling a mobile website? I want to add specific CSS styles for users on the Android platform. Appreciate any help! ...

Is the side tab overflowing the window due to its absolute positioning?

My browser window has a side tab that slides in when clicked using jQuery. The issue I'm facing is that the tab overflows the body due to its absolute positioning. However, the overflow stops when the tab is pulled in by jQuery. It only happens when t ...

Is it possible to have the cursor rotate or animate by 45 degrees when clicked

Do you know how to create a unique custom cursor using CSS? Say, for example, we have this code: cursor: url(images/cursor.png) 15 15, auto; Now, what if we wanted to take it up a notch and make the cursor rotate -45 degrees when clicked, and then revert ...

Display a label upon hovering over an image

Is there a way to create an effect where upon hovering over an image, a pop-up image is displayed like this: https://i.sstatic.net/OloUH.png Any suggestions on how I can achieve this using HTML and CSS? Thanks in advance! ...

Tips for extracting HTML tags directly from JSON data

In my dataset, I have a JSON illustration [{ "Field1": "<header class=\"main-header dark-bg\">\n\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-xl-3\">\n< ...

Enhance the php query limit using javascript when loading additional content

Hey there, currently working on implementing a reverse infinite scroll feature for a private messaging module. Everything seems to be functioning well, except for one issue I'm facing - struggling to update the query limit. I set the maximum and lim ...

various issues with fonts and Uncaught Eval error

I've been encountering multiple font/style errors and an uncaught eval. I have attached a picture for reference. My Angular application is not functioning properly, and I suspect these errors may be the reason. However, I am unsure of their significan ...