0

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?

Community
  • 1
  • 1
Phrogz
  • 296,393
  • 112
  • 651
  • 745
  • 1
    Put `evt.preventDefault();` to `drop` listener. – Teemu Feb 01 '16 at 06:40
  • OMG. Late night eyes. I kept seeing `stopPropagation` as `preventDefault`. @Teemu Post as answer for rep. – Phrogz Feb 01 '16 at 06:57
  • 1
    Looks like ashan_SL has the same answer already. Btw. If you've used `addEventListener`, it shouldn't be necessary to check if `evt.stopPropagation` or `evt.preventDefault` exist, afaik they will exist, if `addEventListener` exists. – Teemu Feb 01 '16 at 07:12

1 Answers1

1

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

Ashan
  • 479
  • 7
  • 28