Stop HTML5 drop from redirecting Firefox

461 Views Asked by At

I have an HTML table with draggable rows. Per this answer I am 'cancelling' the dragover event.

dest.addEventListener( 'dragover', function(evt){
  evt.dataTransfer.dropEffect = 'copy';
  if (evt.preventDefault) evt.preventDefault();
  return false;
}, false );

Per MDN I am calling preventDefault() in (I think) all the right places.

dest.addEventListener( 'drop', function(evt) {
  this.classList.remove('over');
  ...
  if (evt.stopPropagation) evt.stopPropagation();
  return false;
}, false );

The drag/drop works perfectly in Chrome and Safari. In Firefox, the drag/drop works, and then Firefox redirects to a new URL.

var src  = document.querySelector('#src tbody'),
    dest = document.querySelector('#dest tbody');

var people = [
  {name:'Gavin', age:42},
  {name:'Bjørn', age:17},
  {name:'Leyla', age:24}
];

people.forEach(function(person,i){
  var tr = rowFor(person);
  src.appendChild(tr);

  tr.draggable = true;
  tr.addEventListener( 'dragstart', function(evt){
    this.classList.add('drag','selected');
    evt.dataTransfer.dropEffect = 'copy';
    evt.dataTransfer.setData( 'text', i );
    return false;
  }, false );

  tr.addEventListener( 'dragend', function(evt){
    if (evt.preventDefault) evt.preventDefault();
    this.classList.remove('drag');
    return false;
  }, false );
});

dest.addEventListener( 'dragenter', function(evt){
  this.classList.add('over');
  return false;
}, false );

dest.addEventListener( 'dragover', function(evt){
  evt.dataTransfer.dropEffect = 'copy';
  this.classList.add('over');
  if (evt.preventDefault) evt.preventDefault();
  return false;
}, false );

dest.addEventListener( 'dragleave', function(evt){
  this.classList.remove('over');
  return false;
}, false );

dest.addEventListener( 'drop', function(evt) {
  this.classList.remove('over');
  var index = evt.dataTransfer.getData('Text');
  var dup = rowFor( people[index] );
  dest.appendChild( dup );
  if (evt.stopPropagation) evt.stopPropagation();
  return false;
}, false );

function rowFor(obj){
  var tr = document.createElement('tr');
  tr.innerHTML = "<td>"+obj.name+"</td><td>"+obj.age+"</td>";
  return tr;
}
body { background:#eee }
#wrap {
  display:flex;
  flex-direction:row;
  justify-content:space-between;
  align-items:flex-start;
  flex-grow:1;
  height:400px;
  padding:1em
}
table { width:200px; border-collapse:collapse; border:1px solid #ccc }
tbody { background:#fff }
th,td { padding:0 5px }
th { text-align:left; background:#ddd }
caption { background:#ccc }

table.over { border:2px solid yellow }
tr.selected td { background:lightblue }

table { display:flex; flex-flow:column; height:100%; margin-right:4px; overflow:hidden }
table caption { flex:0 0 auto; width:100%; display:block }
table thead { flex:0 0 auto; width:calc(100% + 1px) }
table tbody { flex:1 1 auto; display:block; overflow-y:auto }
table tbody tr { width:100% }
table thead,
table tbody tr { display:table; table-layout:fixed }
tbody tr { cursor:default }
thead th:last-child,
tbody td:last-child { width:33%; }
<div id="wrap">

<table id="src">
  <caption>drag from here</caption>
  <thead><tr><th>name</th><th>age</th></tr></thead>
  <tbody></tbody>
</table>

<table id="dest">
  <caption>drag to here</caption>
  <thead><tr><th>name</th><th>age</th></tr></thead>
  <tbody></tbody>
</table>

</div>

Snippet also available at jsfiddle.net/8d96vpws/3/

How do I stop Firefox from changing location?

1

There are 1 best solutions below

0
On

I think first you need when drop, stop action without checking condition. this happen condition not true at this point. after you can find some issues in this code.

dest.addEventListener( 'drop', function(evt) {
  evt.preventDefault();
  evt.stopPropagation();
  this.classList.remove('over');
  ...
}, false );

see below