Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I prevent drag on a child, but allow drag on the parent?

I have a div which the user can drag, inside that div is a span with some text which I want to allow the user to select (thus they cannot drag it). How do I allow the div to drag, but not the span?

The dragstart event is on the div.

I'm probably overlooking something simple. I tried draggable=true on the div, and draggable=false on the span. That didn't work. Tried returning false on dragstart, that didn't work either.

dragstart (roughly):

var jTarget = $(e.target);
if ((jTarget.is('div.header') || (jTarget.parents('div.header')) 
       && !jTarget.is('a, input, span'))) 
{
   e.originalEvent.dataTransfer.setData("Text", "test");
}
else
{
   if(e.preventBubble)
      e.preventBubble();
   if(e.stopPropagation)
      e.stopPropagation();
   return false;//???
}

The if else portion works as I expect, but I cannot get anything to stop the drag and allow the select.

like image 445
aepheus Avatar asked Jul 27 '11 16:07

aepheus


5 Answers

If you want to truly cancel out the drag and make it unnoticeable to parent drag handlers, you need to both preventDefault and stopPropagation:

<div draggable="true" ondragstart="console.log('dragging')">
    <span>Drag me! :)</span>
    <input draggable="true"
           ondragstart="event.preventDefault();
                        event.stopPropagation();"
           value="Don't drag me :(">
</div>

Without the stopPropagation, the parent ondragstart will still be called even if the default behavior will be prevented (event.defaultPrevented == true). If you have code in that handler that doesn't handle this case, you may see subtle bugs.

You can of course put the JavaScript above inside element.addEventListener('dragstart', ...) too.

like image 89
Blixt Avatar answered Nov 13 '22 19:11

Blixt


just posting in case someone searches for it with a similar Problem

element.addEventListener('mousedown', function() { this.parentNode.setAttribute("draggable", false); });
element.addEventListener('mouseup', function() { this.parentNode.setAttribute("draggable", true); });

worked for me

like image 43
mech Avatar answered Nov 13 '22 18:11

mech


You can change the child element to draggable and prevent default when ondragstart, this will leave the regular behavior on the child element and the parent will still be draggable

function drag(e){ if(e.target.type=="range")e.preventDefault();/*rest of your code*/  }

html:

<input type="range" draggable="true" ondragstart="drag(event)">
like image 6
shuji Avatar answered Nov 13 '22 18:11

shuji


Put a mousedown handler on the span and stop the event propagation there.

like image 4
Rob Middleton Avatar answered Nov 13 '22 19:11

Rob Middleton


In my application, I was unable to get any of the other solutions listed here to work. This is what worked for me:

ondragstart="event.preventDefault();" draggable="false"

In my specific case, it was a text input inside a div.

like image 1
Todd Sjolander Avatar answered Nov 13 '22 20:11

Todd Sjolander