I'm developing the front-end of an app to track tournaments. In one page, the user needs to update the tournament result by dragging a player from a list on the left inside the final results table on the right, that I'll send to a PHP backend for processing (I'm not developing the backend, just need to send the correct data via POST). My requirements are:
- Have a list of players
- Have a results table with fixed positions in each row (one row for 1st, one row for 2nd).
- Each position will have 4 related inputs, all named
position-1-NAME
, in the same row, but different columns - The user should be able to drag players into each position
- One player can only be in one position, and each position can only have one player
- When a player is placed in the table, he should be removed from the list
I've tried several approaches but the one that came close is using the Dragula JS plugin.
Then, I create the list of players with an ul
with the id
to make it a container in Dragula:
<ul id="players-container">
<li>
Player 1
</li>
</ul>
Then, I have a table
inside a form
tag, and the name of the fields are all named according to the position, like position-1-name-of-the-input
:
<form method="POST" action="file_to_process_form.php">
<thead>
<th>Position</th>
<th>Player</th>
...
</thead>
<tbody>
<tr>
<td>
1st Position
</td>
<td class="target">
<input type="text" name="position-1-player-name" value="" hidden>
</td>
<td>
...other inputs
</td>
</tr>
</tbody>
Then, in JavaScript, I made a hack to grab the text()
from the li
being dragged and put it inside the value
attribute of the input
of the table
, so that I can send the name of the player in the first position to the backend. The code:
dragula([document.querySelector('#players-container'), document.querySelector('.target')], {
isContainer: function(el){
return el.classList.contains('target');
},
revertOnSpill: true
}).on('drop', function(el, target, source, sibling){
elValue = $(el).text();
$(target).find('input').attr('value', elValue);
});
So far, this is working with some bugs:
I can drop two players in the same
td
, and they will show both draggedli
in the UI, but the form will only have the value of the last dropped player.If I drag the player into all positions, one after another, all inputs will have the value of his name until I drag another player into that position.
So, I want to accomplish a couple of things:
Allow only one player inside each
td class="target"
. I've tried to disable thetd
by removing the.target
class but then I can't move the player again after being dropped.Remove the value of the input when I drag the player out.
I know this is a bit of a hack but I don't have a lot of experience with JS/jQuery and this is the only solution that remotely works so far.
My questions:
How can I prevent multiple players form being dragged to the same
td
with Dragula or JS / jQuery code?[SOLVED -- see edit] How can I remove the
value
of theinput
when I drag a player OUT of thetd
?Do you know a better way to implement these requirements to recommend?
EDIT
I've managed to solve the question 2 by adding the following code:
dragulaObject.on('drag', function(el, source) {
$(source).find('input').attr('value', '');
});