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
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.
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)">
I was inspired by a few of the answers here and I think I came up with the cleanest and most reusable solution. I use a mouse down event to check if the element should be draggable or not. I do this by verifying if it has a specific class name that I only assign to draggable elements. On the mouse up event, I go through all of the elements with that class tag and set their draggable values back to true.
This can break if the input node is a deep child of the draggable div, but then you can use the same algorithm as in the mouse up event and set all of the values to false.
document.addEventListener('mousedown', function (event) {
var clickedElem = event.target;
if(!clickedElem.classList.contains("drop_content")){
clickedElem.parentElement.setAttribute("draggable",false);
}
}, false);
document.addEventListener('mouseup', function () {
var boxes = document.querySelectorAll(".drop_content");
for(var i = 0; i < boxes.length; i++){
boxes[i].setAttribute("draggable",true);
}
}, false);
div{
display:block;
background: black;
padding: 5px;
margin: 2px;
}
<html>
<body>
<div class="drop_content" draggable="true">
<input value="Can't drag me">
</div>
<div class="drop_content" draggable="true">
<input value="Can't drag me either">
</div>
</body>
</html>
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.
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
Put a mousedown handler on the span and stop the event propagation there.