-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Flickering when dragging over child elements #438
Comments
Nope that's a thing, but you can code around it. See the discussion here: http://stackoverflow.com/questions/14194324/firefox-firing-dragleave-when-dragging-over-text/20596358#20596358 I found "dragout" to be very useful. I've found drag enter to have the same issue (it does not fire for children). Its an issue for small parents with larger children with fast mouse movements. One day I may write its counterpart. Dragon? |
I have solved the issue with Dragster: It is small and it works great, may be it can be included in dropzone. Here what I did: redefined dragenter and dragleave: create dragster class: Add dragster listener document.addEventListener( "dragster:leave", function (e) { That's it. |
Will think about how this could be improved |
If it helps I fix the issue the following way: initialize: function () {
this.dragEnteredEls = [];
},
dragenter: function (e) {
this.dragEnteredEls.push(e.target);
if (this.el === e.target) {
// render hover div
}
},
dragleave: function (e) {
this.dragEnteredEls = _.without(this.dragEnteredEls, e.target);
if (this.dragEnteredEls.length === 0) {
// cleanup, dragging is finished
}
} |
I was able to work around this by using a transparent overlay. Basically a div that is 100% height and width of the drop zone that appears when .dz-drag-hover is present on the drop zone. If you add a z-index to it, it will cover up all of the other child elements. I'm really not sure why the overlay element wasn't causing flickering itself, but it works and is CSS only, so 👍 |
@neiltron Just tried your idea and whilst it works when the hover is not in place the child elements are not clickable. EG: links. Text is selectable though. I need to try something else now. |
Here is some sample code that I'm using to fix this. I've packaged it up so that it should be able to just drop into your projects. ✨ function setupDragon(uploader) {
/* A little closure for handling proper
drag and drop hover behavior */
var dragon = (function (elm) {
var dragCounter = 0;
return {
enter: function (event) {
event.preventDefault();
dragCounter++;
elm.classList.add('dz-drag-hover')
},
leave: function (event) {
dragCounter--;
if (dragCounter === 0) {
elm.classList.remove('dz-drag-hover')
}
}
}
})(uploader.element);
uploader.on('dragenter', dragon.enter);
uploader.on('dragleave', dragon.leave);
}
// You can set it up via the custom intialization
new Dropzone('div#dropzone', {
url: "/upload",
/* overwrite the default behavior */
dragenter: function () {},
dragleave: function () {},
/* setup the new behavior */
init: function () { setupDragon(this) }
});
// Or using the options like this
Dropzone.options.dropzone = {
/* overwrite the default behavior */
dragenter: function () {},
dragleave: function () {},
/* setup the new behavior. 'this' is the uploader */
init: function () { setupDragon(this) }
} Thanks to @mkasson for the name idea. 👍 |
@jhubert Works like a dream! Thanks so much for this. |
If dragged over the child element, the dz-drag-hover class is removed. See dropzone/dropzone#438 for more info. It's unlikely this problem will be fixed in the core of dropzonejs soon, so applied the fix made by @jhubert. Code can be deleted as soon dropzonjs team fixes this.
@jhubert Reference counting will only get you so far with this problem. Depending on browser (firefox) and sophistication of the dropzone (nested elements) it will rapidly break down. I've personally used something very similar to what @malomalo describes, though he's not particularly clear with his description. Basically the idea is that you have an array, and you add e.target for every single dragEnter event you receive. You similarly remove every single e.target you receive within dragLeave. When the array is of length 0 you remove the hover effect within dragLeave. You may unconditionally add the hover effect within dragEnter. You'll note that removing a specific element from an array can be a bit of a pain here, though it's rather easy with underscore or jQuery. The other poster roughly covers the underscore approach, here is how it'd look with jQuery:
|
Thanks @kamelkev ! |
@Ydalb It's worth noting my original post here had a minor error. You want "$()" instead of "new Array" for dragEnteredEls, otherwise there are some cross browser issues. You then want to use the jquery specific array modifiers (because dragEnteredEls is now a jquery object), after which everything works as expected. Apologies. I've fixed my example, you might want to fix up your merge and double check it. |
I’ve been stuck with drag events the entire day, and just realized that my use case is slightly different: I want to show dropzones when a file I’ve modified the source code so that |
Looking at this more closely, it seems more and more like there’s some confusion between stopping event propagation and preventing default browser behaviors, since both are called from a function named I’ve commented out most instances of calls to the It would be nice if someone with deeper insight into and knowledge of the library, and the decisions leading up to it being the way it is, would review this part of the code and see if this could be updated to allow for event propagation. |
For my case @kamelkev solution worked perfectly AND he was exactly right about @jhubert solution causing issues in Firefox (I got bitten). @Haraldson it seems like your proposal would probably make sense as a separate issue and Pull Request. |
|
@sorenfu Such a solution cannot and will not work with Firefox. You likely won’t notice problems elsewhere, but you will note obvious tabulation issues if you test in Firefox. The underlying reason relates to how Firefox decides to treat the enter event. Entering a certain elements may allow multiple enter events to fire, however there won’t be an analogous set of exit events to match. The net result is that your counter can always increase, but won’t necessarily decrease as expected. The solution I have posted is tried and true. My team spent an inordinate amount of time testing the technique, which is now used by multiple other organizations as well. You should retry it. |
@kamelkev you are right. The reason why I still had was the flickering, was because I had a :before element on |
Just figured out a sneaksy way of doing this. .dz-drag-hover {
position: relative;
}
.dz-drag-hover:after {
display: block;
content: "";
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
background-color: transparent;
z-index: 1000;
}
.dz-drag-hover .your-visual-dropzone-upload-message {
/* ... */
} And you style the element that you want shown to the user so the z-index isn't above that 1000, it doesn't flicker. |
@kamelkev your fix didn't work for us initially. However thanks for the tip, good job - I did a simple change and everything works now in any browser:
|
That's interesting. Are we saying that .add does not add the passed item to the collection, but instead returns a whole new collection? That would be incredibly interesting if so... Maybe someone else can comment regarding whether they had similar issues or not? |
Same here @kamelkev. Seems that From https://api.jquery.com/add/
var pdiv = $( "p" );
pdiv.add( "div" ); // WRONG, pdiv will not change |
@micaww Good to know. |
Hi, I'm having this issue, is there a fix now ? |
I had the same problem, here's a simple fix that worked for me. 1- on the 'dragover' event, call a functin that adds a class to the dropzone container (e.g., .no-pointer-events) in your css file
The function:
Basically, this is to keep the class on the dropzone to disable all children pointer events as long as there is a file hovering, when there is none, the children return to normal after half a second |
Here's my approach for case @Haraldson for scenario when I want to see dropzone only when I hovering files. I really think it should be righ inside library
|
I a building a small filemanager with dropzone.js and it works fine with firefox but with ie, chrome and safari there is a lot of flickering of the border when dragging the mouse oer child elements. Is there a way to avoid triggering the dragleave event when themouse enters child elements?
claudio
The text was updated successfully, but these errors were encountered: