Reputation: 6402
I'm trying to implement a simple drag and drop effect on a div. I'm using the native HTML5 API. Basically, I'm trying to drag the left pink box to the dark gray area. See the fiddle: All seems to be ok, however, I'm not able to drop the box in the dark gray area.
https://jsfiddle.net/pablodarde/2wy1s2vn/
I'm using this documentation as support.
This is my code:
HTML
<div class="container">
<div class="side-bar">
<div class="box" draggable='true'></div>
</div>
<div class="drop-zone"></div>
</div>
JavaScript
const box = document.querySelector('.box');
const dropZone = document.querySelector('.drop-zone');
const handleDragStart = (e) => {
console.log(e.dataTransfer);
e.dataTransfer.effectAllowed = 'move';
};
const handleDragEnter = (e) => {
e.target.className += ' active-drop';
e.dataTransfer.dropEffect = 'move';
console.log(e.dataTransfer);
e.preventDefault();
e.stopPropagation();
}
const handleDragLeave = (e) => {
e.target.className = 'drop-zone';
}
const handleDrop = (e) => {
console.log('Drop!!');
e.preventDefault();
e.stopPropagation();
}
box.addEventListener('dragstart', handleDragStart);
box.addEventListener('drop', handleDrop);
dropZone.addEventListener('dragenter', handleDragEnter);
dropZone.addEventListener('dragleave', handleDragLeave);
Upvotes: 1
Views: 443
Reputation: 6402
Although I accepted the above answer, I'm leaving here an option with React. I found out how to explore React state feature to easily build a simple drag and drop solution
Codepen https://codepen.io/pablodarde/pen/gGoQYo
JavaScript
class Square extends React.Component {
constructor() {
super();
this.state = {
posx: 10,
posy: 10,
};
this.setDrag = this.setDrag.bind(this);
this.startDrag = this.startDrag.bind(this);
this.stopDrag = this.stopDrag.bind(this);
}
componentDidMount() {
this.sq.addEventListener('mousedown', this.setDrag);
}
startDrag(e) {
console.log('posx: ', this.state.posx);
console.log('startPosX: ', this.startPosX);
this.setState({
posx: parseInt(e.clientX - this.startPosX, 10),
posy: parseInt(e.clientY - this.startPosY, 10),
});
this.startPosX = e.clientX - this.state.posx;
this.startPosY = e.clientY - this.state.posy;
}
stopDrag() {
document.documentElement.removeEventListener('mousemove', this.startDrag);
document.documentElement.removeEventListener('mouseup', this.stopDrag);
this.sq.addEventListener('mousedown', this.setDrag);
}
setDrag(e) {
console.log('mouse down');
this.sq.removeEventListener('mousedown', this.setDrag);
this.startPosX = e.clientX - this.state.posx;
this.startPosY = e.clientY - this.state.posy;
document.documentElement.addEventListener('mousemove', this.startDrag);
document.documentElement.addEventListener('mouseup', this.stopDrag);
}
render() {
return (
<div
className='square'
style={{
left: this.state.posx,
top: this.state.posy,
}}
ref={(sq) => { this.sq = sq; }}
>
{this.state.posx}
</div>
);
}
}
ReactDOM.render(
<Square />,
document.getElementById('app')
);
CSS
.square {
position: absolute;
width: 100px;
height: 100px;
background: #900;
border: 1px solid #333;
}
Upvotes: 0
Reputation: 4912
The following 4 things should solve your browser/event related issues and handle the drop for you:
drop
event has to be attached to the dropZone
div.dragover
event handler. You don't have one, add it.For Firefox:
Add the following line to your dragstart
handler:
e.dataTransfer.setData('sourceId', '<id of the source>');
This could be any key-value, but it has to be set for drag drop to work in Firefox. I have set the ID of the box since I want to use it in the drop handler.
Final working code with the drop handled: https://jsfiddle.net/kyqr1o6b/6/
Update: Added support for Firefox.
Update 2: Drop handled.
Update 3: Positions captured.
Upvotes: 1