HTML5 dragleave fired when hovering a child element
Solution 1
You just need to keep a reference counter, increment it when you get a dragenter, decrement when you get a dragleave. When the counter is at 0 - remove the class.
var counter = 0;
$('#drop').bind({
dragenter: function(ev) {
ev.preventDefault(); // needed for IE
counter++;
$(this).addClass('red');
},
dragleave: function() {
counter--;
if (counter === 0) {
$(this).removeClass('red');
}
}
});
Note: In the drop event, reset counter to zero, and clear the added class.
You can run it here
Solution 2
Is it possible to prevent dragleave from firing when dragging into a child element?
Yes.
#drop * {pointer-events: none;}
That CSS seem to be enough for Chrome.
While using it with Firefox, the #drop shouldn't have text nodes directly (else there's a strange issue where a element "leave it to itself"), so I suggest to leave it with only one element (e.g., use a div inside #drop to put everything inside)
Here's a jsfiddle solving the original question (broken) example.
I've also made a simplified version forked from the @Theodore Brown example, but based only in this CSS.
Not all browsers have this CSS implemented, though: http://caniuse.com/pointer-events
Seeing the Facebook source code I could find this pointer-events: none;
several times, however it's probably used together with graceful degradation fallbacks. At least it's so simple and solves the problem for a lot of environments.
Solution 3
It has been quite some time after this question is asked and a lot of solutions (including ugly hacks) are provided.
I managed to fix the same problem I had recently thanks to the answer in this answer and thought it may be helpful to someone who comes through to this page.
The whole idea is to store the evenet.target
in ondrageenter
everytime it is called on any of the parent or child elements. Then in ondragleave
check if the current target (event.target
) is equal to the object you stored in ondragenter
.
The only case these two are matched is when your drag is leaving the browser window.
The reason that this works fine is when the mouse leaves an element (say el1
) and enters another element (say el2
), first the el2.ondragenter
is called and then el1.ondragleave
. Only when the drag is leaving/entering the browser window, event.target
will be ''
in both el2.ondragenter
and el1.ondragleave
.
Here is my working sample. I have tested it on IE9+, Chrome, Firefox and Safari.
(function() {
var bodyEl = document.body;
var flupDiv = document.getElementById('file-drop-area');
flupDiv.onclick = function(event){
console.log('HEy! some one clicked me!');
};
var enterTarget = null;
document.ondragenter = function(event) {
console.log('on drag enter: ' + event.target.id);
enterTarget = event.target;
event.stopPropagation();
event.preventDefault();
flupDiv.className = 'flup-drag-on-top';
return false;
};
document.ondragleave = function(event) {
console.log('on drag leave: currentTarget: ' + event.target.id + ', old target: ' + enterTarget.id);
//Only if the two target are equal it means the drag has left the window
if (enterTarget == event.target){
event.stopPropagation();
event.preventDefault();
flupDiv.className = 'flup-no-drag';
}
};
document.ondrop = function(event) {
console.log('on drop: ' + event.target.id);
event.stopPropagation();
event.preventDefault();
flupDiv.className = 'flup-no-drag';
return false;
};
})();
And here is a simple html page:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Multiple File Uploader</title>
<link rel="stylesheet" href="my.css" />
</head>
<body id="bodyDiv">
<div id="cntnr" class="flup-container">
<div id="file-drop-area" class="flup-no-drag">blah blah</div>
</div>
<script src="my.js"></script>
</body>
</html>
With proper styling what I have done is to make the inner div (#file-drop-area) much bigger whenever a file is dragged into the screen so that the user can easily drop the files into the proper place.
Solution 4
Here, the simplest Cross-Browser solution (seriously):
jsfiddle <-- try dragging some file inside the box
You can do something like that:
var dropZone= document.getElementById('box');
var dropMask = document.getElementById('drop-mask');
dropZone.addEventListener('dragover', drag_over, false);
dropMask.addEventListener('dragleave', drag_leave, false);
dropMask.addEventListener('drop', drag_drop, false);
In a few words, you create a "mask" inside the dropzone, with width & height inherited, position absolute, that will just show when the dragover starts.
So, after showing that mask, you can do the trick by attaching the others dragleave & drop events on it.
After leaving or dropping, you just hide the mask again.
Simple and without complications.
(Obs.: Greg Pettit advice -- You must be sure that the mask hover the entire box, including the border)
Solution 5
The "right" way to solve this issue is to disable pointer events on child elements of the drop target (as in @H.D.'s answer). Here's a jsFiddle I created which demonstrates this technique. Unfortunately, this doesn't work in versions of Internet Explorer prior to IE11, since they didn't support pointer events.
Luckily, I was able to come up with a workaround which does work in old versions of IE. Basically, it involves identifying and ignoring dragleave
events which occur when dragging over child elements. Because the dragenter
event is fired on child nodes before the dragleave
event on the parent, separate event listeners can be added to each child node which add or remove an "ignore-drag-leave" class from the drop target. Then the drop target's dragleave
event listener can simply ignore calls which occur when this class exists. Here's a jsFiddle demonstrating this workaround. It is tested and working in Chrome, Firefox, and IE8+.
Update:
I created a jsFiddle demonstrating a combined solution using feature detection, where pointer events are used if supported (currently Chrome, Firefox, and IE11), and the browser falls back to adding events to child nodes if pointer event support isn't available (IE8-10).
pimvdb
Updated on July 08, 2022Comments
-
pimvdb almost 2 years
The problem I'm having is that the
dragleave
event of an element is fired when hovering a child element of that element. Also,dragenter
is not fired when hovering back the parent element again.I made a simplified fiddle: http://jsfiddle.net/pimvdb/HU6Mk/1/.
HTML:
<div id="drag" draggable="true">drag me</div> <hr> <div id="drop"> drop here <p>child</p> parent </div>
with the following JavaScript:
$('#drop').bind({ dragenter: function() { $(this).addClass('red'); }, dragleave: function() { $(this).removeClass('red'); } }); $('#drag').bind({ dragstart: function(e) { e.allowedEffect = "copy"; e.setData("text/plain", "test"); } });
What it is supposed to do is notifying the user by making the drop
div
red when dragging something there. This works, but if you drag into thep
child, thedragleave
is fired and thediv
isn't red anymore. Moving back to the dropdiv
also doesn't make it red again. It's necessary to move completely out of the dropdiv
and drag back into it again to make it red.Is it possible to prevent
dragleave
from firing when dragging into a child element?2017 Update: TL;DR, Look up CSS
pointer-events: none;
as described in @H.D.'s answer below that works in modern browsers and IE11. -
pimvdb almost 13 yearsThanks a lot, but indeed it's Chrome I'm trying to solve this problem in.
-
robertc almost 13 years@pimvdb I see you've logged a bug, I'll just leave a reference to it here in case anyone else comes across this answer.
-
pimvdb almost 13 yearsI did indeed, but I forgot to add a link to it here. Thanks for doing that.
-
pimvdb almost 12 yearsThanks! I can't get this to work in Chrome however. Could you provide a working fiddle of your hack?
-
Aldekein over 11 yearsDoes it go into «if (typeof event.clientX === 'undefined')»?
-
Greg Pettit almost 11 yearsNot sure why, but it's not working consistently with Chrome. Sometimes leaving the area keeps the mask visible.
-
Greg Pettit almost 11 yearsActually, it's the border. Have the mask overlapping the border, with no border of its own, and it should work OK.
-
Christof almost 11 yearsI was thinking of doing it by checking the coords too. You did most of the work for me, thx :). I had to make some adjustments though:
if (e.x >= (rect.left + rect.width) || e.x <= rect.left || e.y >= (rect.top + rect.height) || e.y <= rect.top)
-
H.D. almost 11 yearsWorked nicely but there could be another window over the browser, so getting the mouse location and comparing it to the rectangular screen area isn't enough.
-
Hengjie over 10 yearsIt won't work in Chrome because it's event doesn't have
e.x
ande.y
. -
Hengjie over 10 yearsThis doesn't appear to always work in Chrome. I would on occasion receive
clientX
above 0 when the mouse is outside of the box. Granted, my elements areposition:absolute
-
Profet over 10 yearsDoes it happens all the time or only sometimes ? Because if the mouse is moving too fast (ig. outside the window), you might get wrong values.
-
Hengjie over 10 yearsIt happens 90% of the time. There are rare cases (1 out of 10 times) where I can make it reach 0. I'll try again moving the mouse slower, but I couldn't say I was moving quickly (perhaps what you'd call normal speed).
-
H.D. over 10 yearsThis answer shows a workaround for the undesirable firing but neglects the question "Is it possible to prevent dragleave from firing when dragging into a child element?" entirely.
-
H.D. over 10 yearsBehaviour can get strange when dragging a file from outside the browser. In Firefox I've got "Entering child -> Entering Parent -> Leaving child -> Entering child -> Leaving child" without leaving the parent, which left with the "over" class. Old IE would need an attachEvent replacement for the addEventListener.
-
H.D. over 10 yearsThat solution depends strongly on the bubbling, the "false" in all addEventListener should be emphasized as essential (although that's the default behaviour), since many people may not know about that.
-
H.D. over 10 yearsThat single draggable adds an effect to the dropzone that doesn't appear when the dropzone is used for other draggable objects that doesn't trigger the dragstart event. Perhaps using everything as a dropzone for the effect of dragging while keeping the real dropzone with other handlers would do that.
-
Theodore Brown over 10 years@H.D. I updated my answer with info on using the pointer-events CSS property to prevent the
dragleave
event from firing in Chrome, Firefox, and IE11+. I also updated my other workaround to support IE8 and IE9, in addition to IE10. It is intentional that the dropzone effect is only added when dragging the "Drag me" link. Others can feel free to change this behavior as needed to support their use cases. -
Theodore Brown over 10 yearsThe pointer-events property is the right solution going forward, but unfortunately it doesn't work in IE8-IE10, which are still widely used. Also, I should point out that your current jsFiddle doesn't even work in IE11, since it doesn't add the necessary event listeners and default behavior prevention.
-
null over 10 yearsOnly thing this snippet does is preventing the 'hovered' class to be removed by reapplying it the next tick cycle (making the 'dragleave' event useless).
-
Marcin Raczkowski over 10 yearsIt's not useless. If you leave parent it'll work as expected. The power of this solution is it's simplicity, it's not ideal or best there is. Better solution would be to mark an enter on a child, in onleave check if we just entered child, and if so not trigger leave event. It'll hovever need testing, extra guards, checing for grandchildren, etc.
-
Nicole Stutz over 10 yearsI like this solution. Didn't work in Firefox first. But if you replace e.x with e.clientX and e.y with e.clientY it works. Also works in Chrome.
-
entropy over 10 yearsNote, your jsfiddle has a bug in it, in drag_drop, you should remove the hover class on "#box" not "#box-a"
-
Timo Huovinen about 10 yearsDid not work in chrome for me, neither did what Chris or Daniel Stuts suggested
-
Timo Huovinen about 10 yearsOccasionally does not work on chrome (does not catch dragleave properly)
-
standac about 10 yearsThis will prevent childs from triggering "click" event.
-
bingjie2680 almost 10 yearsThis is a nice solution, but somehow it did not work for me. I finally figure out a workaround. For those of you who are looking for something else. you could try this: github.com/bingjie2680/jquery-draghover
-
Arthur Corenzan almost 10 yearsOMG this is the most obvious solution and only had ONE vote... Come on people, you can do better. I was thinking about that but after seeing the level of sophistication of the first few answers I almost discarded it. Did you have any drawbacks ?
-
floribon almost 10 yearsUsing pointer-events is indeed a good answer, I struggled a bit before finding out by myself, that answer should be higher.
-
Woody over 9 yearsHi @ArthurCorenzan - thanks. No - it works fine, actually i figured out an even simpler way to do it, shown above.
-
Arthur Corenzan over 9 yearsOh no, you just blew my first comment :P I liked the previous solution better (preventing the bubbling of dragleave event of child elements).
-
Woody over 9 yearsThe first solution did not work generically e.g. if you had nested child elements, this way does and it's less code, a "win win" :)
-
Woody over 9 yearsCheckout this useful library for html5 drag and drop : github.com/stevendwood/html5-dropzone
-
Arthur Corenzan about 9 yearsThis didn't work when the edge of the element being dragged touches the edge of another draggable element. For instance a sortable list; dragging the element downwards, over the next draggable item does not decrement the counter back to 0, instead it gets stucked at 1. But if I drag it sideways, out of any other draggable element, it works. I went with the
pointer-events: none
on the children. When I start dragging I append a class that has this property, when drag's over I remove the class. Worked nicely on Safari and Chrome, but not on Firefox. -
Damien about 9 yearsThat worked for me with Firefox 37 and Chromium 39, but not with IE11 (there are more dragenter than dragleave events). Actually, even the fiddle does not work with IE11.
-
Damien about 9 yearsAdding e.preventDefault() in dragenter(e) seemed to fix it for IE11. I got the idea while reading this: The HTML5 drag and drop disaster
-
Woody about 9 yearsI updated the link. The reason it doesn't work on IE is because of the "text/plain" content type in the drag start once that's fixed it then refuses to fire any dragleave events if you don't cancel the dragenter event...another quirk
-
Luca Fagioli about 9 yearsDangerous hack. I've made a jQuery plugin that do the job simply. Check my answer
-
Luca Fagioli about 9 yearsNo. I do not want to lose the control over the child elements. I've made a simple jQuery plugin that deals with the problem doing the job for us. Check my answer.
-
Woody about 9 years@LucaFagioli - in what way is it a hack, and why would it be dangerous ?
-
Luca Fagioli about 9 years@Woody It's a hack because to make it work in IE you need to add a special condition. Moreover you need a global variable for each selector you want to be firing the dragenter event, which mess your code. Finally, it's dangerous because if for some reason you need to call stopPropagation() on a child element this solution breaks.
-
Woody about 9 yearsFirst of all, if you think you have a better answer to the posted problem, then write an answer, not a comment against the highest voted answer trying to tell everyone how smart you are and how dumb the answer and everyone who thinks it's the best answer is. Second of all, your fiddle obviously doesn't work since it only uses one counter to track the events on two elements, i mean how would you expect the code in the answer to work in that instance !? Clearly you need to track the events per element you want to listen on, which is what the questions asks.
-
ZachB about 9 yearsIf the user changes their mind and drags the file back out of the browser, this will remain red.
-
cupcakekid almost 9 yearsHacky but clever. I like. Worked for me.
-
M Katz almost 9 yearsVery useful (at least for me where I only care about Chrome).
-
stonea almost 9 yearsIn chrome use e.originalEvent.x and e.originalEvent.y in place of e.x and e.y.
-
Kirby over 8 yearsOh, how I wish this answer had more votes! Thank you
-
Luke Hansford over 8 yearsFantastic option for those of us lucky enough to not have to support old browsers.
-
Fred over 8 yearsThis is the best solution, it's better than the counter (especially if you delegate events) and it works with draggable children as well.
-
caub over 8 yearsdoesn't work when leaving by the left side (when you have no margin)
-
Pipo over 8 yearsThis worked for me in all browsers, but Firefox. I have a new solution which works everywhere in my case. On the first
dragenter
I saveevent.currentTarget
in a new variabledragEnterTarget
. As long asdragEnterTarget
is set, I ignore furtherdragenter
events, because they are from children. In alldragleave
events I checkdragEnterTarget === event.target
. If this is false the event will be ignored as it was fired by a child. If this is true I resetdragEnterTarget
toundefined
. -
Liam Johnston over 8 yearsGreat solution. I needed to reset the counter to 0 in the function that handles accepting the drop though, otherwise subsequent drags didn't work as expected.
-
mpen over 8 yearsThis is what I ended up doing too, but it's still sketchy.
-
marcelj over 8 yearsNote that this does not work if any child stops propagation of the events. Here's my solution with document.elementFromPoint, which is even simpler: stackoverflow.com/a/35117158/1620264 (I haven't really used elementFromPoint before, so not 100% sure my solution is correct)
-
David about 8 yearsWhat if your children is a Button? o.O
-
BurninLeo almost 8 yearsWorks great - and you can still add the counter solution for older browsers. Thanks!
-
Jon Abrams almost 8 yearsThis didn't work for me out of the box. I needed to use
event.clientX, event.clientY
instead, since they're relative to the viewport and not the page. I hope that helps another lost soul out there. -
B T almost 8 yearsThis won't work if you've already dropped something. The counters will become out of sync - you need a way to determine if its a new drag or a continuation of an old drag.
-
B T almost 8 yearsThis doesn't help tho for the problem of duplicate dragenter events
-
Woody almost 8 years@BT didn't Liam Johnston's reset in the drop function help ? If not you could try adding a dragend listener that resets the counter. I think that dragend should fire on the thing being dragged, but the event should propagate so that you can catch it at the body.
-
B T almost 8 years@Woody I didn't see his comment in the huge list of comments here, but yes, that's the fix. Why not incorporate that into your answer?
-
phk almost 7 yearsThe Chrome bug has been fixed in the mean time.
-
BobTheBuilder over 6 yearsIn order to support Firefox I've also added "ondragexit" listener to decrement counter if not 0.
-
Woody over 6 years@BobTheBuilder, @B T can you suggest an edit and I'll add it to the example ?
-
Josh Bleecher Snyder over 6 yearsDoes this work for "children" that are css pseudo-elements or pseudo-classes? I couldn't get it to, but maybe I was doing it wrong.
-
Josh Bleecher Snyder over 6 yearsTo get this to work reliably, I had to (a) store the counter per-element rather than globally and (b) abandon the old counters when a new drag began. To do this, I used a global generation counter
var dragRefCountGen = 0;
, increment it in dragstart:dragRefCountGen++;
, and reset the counter in dragenter when we're in a new drag:if (this.dragRefCountGen != dragRefCountGen) { this.dragRefCount = 0; this.dragRefCountGen = dragRefCountGen; }
. From there, as before--incrementthis.dragRefCount
in dragenter, decrement and checkthis.dragRefCount
in dragleave. -
Josh Bleecher Snyder over 6 years@Woody happy to suggest this as an edit if you'd like.
-
broc.seib over 6 yearsExcellent answer.
-
Francesco Marchetti-Stasi over 6 yearsLooks like the most simple solution to me, and it solved my problem. Thanks!
-
Alan Deep about 6 yearsthis is the best solution so far, just assign an id to the parent element (e.g "parent_element") and in the css file
#parent_element * {pointer-events: none;}
-
Zoltán Süle over 5 yearsit works only if you do not have other controller elements (edit, delete) inside the area, because this solution blocks them too..
-
Scaramouche over 5 yearsI had this same problem and your solution works great. Tip for others, this was my case: if the child element you're trying to make ignore the drag event is the clone of the element being dragged (trying to achieve a visual preview), you can use this inside dragstart when creating the clone:
dragged = event.target;clone = dragged.cloneNode();clone.style.pointerEvents = 'none';
-
le hollandais volant over 5 yearsThis solutions works nice when the actual mask is the
#drop::before
or::after
. Also, beware that sometimes, when dragging fast, the "dragleave" fires before the "dragenter" has finished. If the dragenter add the class/pseudoelement, and the dragleave removes then, this can cause problem. -
Chin about 5 years@JoshBleecherSnyder can you post the full code as an answer please
-
Adam Taylor about 5 yearsThis doesn't seem to work in Safari 12.1: jsfiddle.net/6d0qc87m
-
Max about 5 yearsNice solution but it does not work properly if
e.currentTarget
outlines is not a rectangle. -
Matt Leonowicz about 5 yearsThis solution is not very reliable, because when you drag things fast, not all the elements in the tree will actually fire the event, which might result in the sum different then 0 after dragging in and out. This happens more often if you have a lot of other elements in the dom tree between the most external and the most internal element.
-
Tim Gerhard almost 5 yearsThanks buddy, i like the plain javascript approach.
-
Peter Moore over 4 years@MattLeonowicz I tried this solution with very complex elements and your concern did not manifest.
-
Jay Dadhania over 4 yearsWhen using on elements having
border-radius
, moving the pointer close to the corner would actually leave the element, but this code would still think we are inside (we have left the element but we are still in the bounding rectangle). Then thedragleave
event handler won't be called at all. -
Jay Dadhania over 4 yearsI agree with @H.D. Also, this will cause problems when element has large
border-radius
as I explained in my comment on @azlar's answer above. -
Bersan over 4 years@Pipo What is
event.currentTarget
, is this a thing? I seeexplicitOriginalTarget
,originalTarget
,relatedTarget
, but nocurrentTarget
, at least on Firefox. -
antoni over 4 yearsThis is great! thanks for sharing @kenneth, you saved my day! A lot of the other answers only apply if you have a single droppable zone.
-
Alex about 4 yearsAs of March 2020 I've had the best luck with this solution as well. Note: some linters may complain about the use of
==
over===
. You are comparing the event target object references, so===
works fine too. -
iwis about 4 yearsFor me, it works in Chrome and Firefox, but id doesn't work in Edge. Please see: jsfiddle.net/iwiss/t9pv24jo
-
iwis about 4 yearsI use even simpler modification of @Christof code:
if (e.x <= rect.left || e.x >= rect.right || e.y <= rect.top || e.y >= rect.bottom)
-
Konstantin Kozirev about 4 yearsThis should be an accepted answer. Or answer in the top.
-
sudoqux almost 4 yearsFor interactive child elements inside the drop target, such as a button: Add
pointer-events: none;
to a class. Apply the class to the drop target, using ondragenter. Then remove the class from the drop target in ondragleave. -
Tod over 3 yearsFollowing on from le hollandais volant's comment, I was STILL getting issues with flashing due to dropleave and dropenter even with Pointer-events: none . So I basically set a timeout on dropleave that's cleared by dropenter. Sorted.
-
sw1337 over 3 years@sudoqux You mean apply the task the children of the drop target using
.droptarget *
-
leosok over 3 yearsUsing dropzone.js a similiar aproach worked for me:
console.log(e.clientX + "/" + e.clientY ); if (e.clientX == 0 && e.clientY == 0 ) { console.log('REAL leave'); }
-
Rob over 3 yearsNice, simple solution. Folks may want to consider just creating a class,
.no-pointer-events {pointer-events: none;}
then addno-pointer-events
to each child element. Done. -
tlorens over 3 yearsThis answer is like magic! It just works. Used this method for DropZone and a HTML table for highlighting rows (The dropzones) for file uploads.
-
Ambrus Tóth about 3 yearsThis should be the accepted answer, it's the most simple and there are no hacks involved. :D
-
Robo Robok almost 3 yearsBut I want to keep my child elements interactive :(
-
mar10 almost 3 yearsI tried this solution, but it should be noted it has a limitation: when pressing Esc to cancel the drag&drop action, no one will remove the "over" class from your dropzone element. If you are trying to use "dragleave" event for this, you just go to the first problem the original author asked about. So both hovering a child element and pressing Esc key while dragging will raise "dragleave" event on the dropzone. Maybe we also need to listen for the Esc key to remove the "over" class from the dropzone...
-
Abubakar Azeem almost 3 yearshi @mar10, thanks for pointing this issue, i will update my answer. i think we can use
dragend
event to handle this, but i will need to test that. -
Abubakar Azeem almost 3 yearsI haven't found a way to detect if the
dragend
event is triggered by releasing a mouse button or pressing the Esc key, so going with thedragend
event will complicate the logic, so the simple solution is to detect the Escape key as you said. I've updated the answer. -
IWonderWhatThisAPIDoes almost 3 yearsWelcome to Stack Overflow! Make sure to take the tour as it should point you in the right direction. I'd also like to ask You not to use nonpermanent indicators to refer to a post (Could You please fix that one yourself? Even now I'm not certain which answers You were refering to).
-
Miguel almost 3 yearsThis worked for me, both Chrome and Firefox (as of 92.0). A workaround for the disadvantages is to toggle this CSS conditionally to it being dragged over.
-
Ayyash over 2 yearsbut what if the child component is a link?
-
nephiw over 2 years#box must be position relative for this to work correctly; but I was able to get this solution working very cleanly. Thanks!
-
Jack_Hu about 2 yearsThis is ALMOST perfect... With one exception: If the children are
input
s of typecheckbox
orradio
, thenpointer-events: none
will have no effect. This is becausepointer-events
are only those that result in a change of VALUE on an element. In the case ofcheckbox
andradio
, these change their STATE, not their value. -
Justin K about 2 yearsExcellent solution - using React was as simple as tracking a new state to reference
onDragEnter
and check against inonDragLeave
. This should be the accepted answer. -
Peter Moore about 2 yearsThis solution is brilliant and works great on modern browsers. No one cares about IE. Not sure why there seem to be so many detractors. If you are doing proper component state management almost all the criticisms become moot. And to echo others - don't forget to reset on drop!
-
sdvnksv almost 2 yearsLooks like the only viable solution among those listed. In React don't forget to store the variable in a
useRef
hook to make sure it's not reset on rerender (also don't forget to reset itonDrop
as @PeterMoore suggested!