So, I have a list of bands that I want to organise into a running order, like so:
<li data-band-id='1' draggable='true' class='band-name'>Metallica</li>
<li data-band-id='2' draggable='true' class='band-name'>Slayer</li>
<li data-band-id='3' draggable='true' class='band-name'>Paradise Lost</li>
<li data-band-id='4' draggable='true' class='band-name'>Gojira</li>
I would like to be able to drag these list items around to change each bands placement within the overall list. So far, I have the following JavaScript to do this:
var dragSatMS = null;
function handleDragStart(e) {
//this.style.color = 'green';
dragSatMS = this;
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text', this.innerHTML);
}
function handleDragOver(e) {
if (e.preventDefault) {
e.preventDefault();
}
e.dataTransfer.dropEffect = 'move';
return false;
}
function handleDragEnter(e) {
this.classList.add('over');
}
function handleDragLeave(e) {
this.classList.remove('over');
//this.style.color = '#333';
}
function handleDrop(e) {
if (e.stopPropagation) {
e.stopPropagation();
}
if (dragSatMS != this) {
dragSatMS.innerHTML = this.innerHTML;
this.innerHTML = e.dataTransfer.getData('text');
}
return false;
}
function handleDragEnd(e) {
[].forEach.call(mssatCols, function (mSatCol) {
mSatCol.classList.remove('over');
//mSatCol.style.color = '#333';
});
}
var mssatCols = document.querySelectorAll('#ms-saturday .band-name');
[].forEach.call(mssatCols, function(msSatCol) {
msSatCol.addEventListener('dragstart', handleDragStart, false);
msSatCol.addEventListener('dragenter', handleDragEnter, false);
msSatCol.addEventListener('dragover', handleDragOver, false);
msSatCol.addEventListener('dragleave', handleDragLeave, false);
msSatCol.addEventListener('drop', handleDrop, false);
msSatCol.addEventListener('dragend', handleDragEnd, false);
});
This works perfectly, I can drag and drop lists to make them change places and the name of the band swaps appropriately. However, the value of the 'data-band-id' attribute stays as it was. I know this is exactly what the code I have does and thats my issue. I'd like to amend the code so that both the name of the band being dragged and dropped and the value of the 'data-band-id' attribute are swapped.
I've Googled a lot but found nothing that can show me how to setData on multiple values, any help much appreciated.
You can query the attributes
property of both items and access the value of data-band-id
. Once you have both two values, you can call setAttribute("name", "value")
to update the data-band-id
. Your updated handleDrop
method would then be:
function handleDrop(e) {
if (e.stopPropagation) {
e.stopPropagation();
}
if (dragSatMS != this) {
dragSatMS.innerHTML = this.innerHTML;
this.innerHTML = e.dataTransfer.getData('text');
//Get the data-band-id of both items.
itemToReplaceAttr = this.attributes["data-band-id"].value;
draggedItemAttr = dragSatMS.attributes["data-band-id"].value;
//Call "setAttribute" to update the attributes.
this.setAttribute("data-band-id", draggedItemAttr);
dragSatMS.setAttribute("data-band-id", itemToReplaceAttr);
}
return false;
}
Here's a demo for good measure: Fiddle