I want to know the difference of dragover and dragenter events of HTML5 drag &drop.
I'm not clear about the difference.
The dragenter event happens at the moment you drag something in to the target element, and then it stops.
The dragover event happens during the time you are dragging something until you drop it.
Look here:
$('.dropzone').on("dragover", function (event) {
console.log('dragover');
});
$('.dropzone').on("dragenter", function (event) {
console.log('dragenter');
});
Now see the console:
As you can see the dragenter happen once (when you drag element in to the target).
But the dragover event happen every few hundred milliseconds.
The same difference exist between drag and dragstart, dragstart happen once but drag happen every few hundred milliseconds.
Based on the dragenter and dragover MDN doc...
dragover
The dragover event is fired when an element or text selection is being
dragged over a valid drop target (every few hundred milliseconds).
dragenter
The dragenter event is fired when a dragged element or text selection
enters a valid drop target.
The dragover is triggered after a small delay (every 350 ms, I think) while the cursor stays over the element.
dragenter:
dragenter event is fires only when while dragging an draggable element, the cursor enters the area of a DOM element which has the ondragenter event attached to it.
dragover:
On the other hand, dragover event is fired "constantly" while dragging a draggable element, and the cursor happens to be to be on the screen inside an DOM element's area, where this DOM element has the ondragover event attached to it.
The difference is that (while dragging) when the cursor enters a drop-zone, dragover is constantly fired (on mouse move) while
dragenter is only fired once, when the cursor has "entered"
DEMO:
function dragover(e) {
console.log("drag over")
}
function dragenter(e) {
console.log("drag enter!!!")
}
#target{
width: 200px;
height: 200px;
background: lightyellow;
border: 1px solid gold;
}
div[draggable]{
width: 60px;
height: 60px;
background: red;
}
<div draggable="true">Drag Me</div>
<div id="target" ondragover="dragover(event)" ondragenter="dragenter(event)">Drop Zone</div>
Related
I'm having problems with mousein and mouseout events triggering at unexpected times.
I am trying to use a GitHub svg icon and listen to when the mouse enters and leaves the icon. I'm not able to replicate it in Svelte's REPL though. In the REPL, the mouseout event will trigger once however moving my mouse through the element causes 4-5 mouseout in one pass. The mouseout is seemingly triggering when you leave the parent element and enter a child element so going from mousein on the <a> tag will trigger a mouseout when you enter the <svg> and <path> etc.
<a
href="https://github.com/blahblahblah"
target="_blank"
rel="noreferrer"
class="flex"
on:mouseenter={handleGithub}
on:mouseout={handleGithub}
on:blur={handleGithub}
>
<Icon type="github" />
{#if githubHover}
<p>GitHub</p>
{/if}
</a>
There are four mouse events related to this logic:
mouseenter
mouseover
mouseleave
mouseout
(There is no mousein.)
These bubble: mouseover & mouseout
These do not bubble: mouseenter & mouseleave
Bubbling events will trigger for all children in the hierarchy. If you do not want those events, use the non-bubbling versions. I.e. use mouseleave instead of mouseout.
I'm trying to make my own button in flash application. Here is some code:
addEventListener(MouseEvent.MOUSE_OUT, Out);
addEventListener(MouseEvent.MOUSE_OVER, Over);
...
private function Over(event:MouseEvent):void
{
addChild(overImage);
}
private function Out(event:MouseEvent):void
{
removeChild(overImage);
}
When mouse is over this button, overImage is blinking. Looks like Over and Out are calling each frame. What am I doing wrong?
If the mouse is positioned in a point where overImage will appear, then that child object will cause a MOUSE_OVER event on itself and thus a MOUSE_OUT event on its parent. The parent MOUSE_OUT will remove the overImage from the display list and that wil cause again a MOUSE_OVER over the parent, startin the loop once again and making the overImage to blink.
Since you tagged this with Flex; why not use a Flex Button?
The MouseOver event will fire continuously as the mouse moves. I would perform a check before calling the addChild to see if the overImage is already parented:
private function Over(event:MouseEvent):void
{
if(!overImage.parent){
addChild(overImage);
}
}
private function Out(event:MouseEvent):void
{
if(overImage.parent){
removeChild(overImage);
}
}
I suspect that will prevent the "Blinking".
Like the other guy said use ROLL_OVER and ROLL_OUT instead, OR set the button.mouseChildren = false.
The reason it's blinking is because MOUSE_OVER and MOUSE_OUT will for every child of that button. So if you have text, or a bg image / color, or a shine, or other elements inside of it, every time you roll over ANY of those parts, it's firing.
So when you add "overImage", it appears below the mouse, and that fires another mouseOut and mouseOver. Again, just use ROLL_OVER and ROLL_OUT, OR set mouseChildren = false
Just consider using MouseEvent.ROLL_OVER and MouseEvent.ROLL_OUT events. They ignore component's children. Without any additional checks and ugly tricks.
And by the way, buttons support skins and states, so you can just include your image into 'over' state.
I used the :active pseudoclass on my buttons to change the padding and border color when clicked. This visually mimics a button press. See an example.
Works in FF. In Chrome, though, the clicks don't always register. Specifically, if you click-and-hold on the text inside the button, then drag off the text (but still inside the button), the click will not fire. Same goes if you click in the padding, then drag into the text.
I've read weird things about buttons and padding in FF vs. Chrome but I can't figure out how to solve this problem.
Solution: Give it a Single Thing to Click
Adding a position: relative to the button and then overlaying it with a :before pseudo element like so:
button:before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
Seemed to resolve the bug for me. See this fiddle. I imagine it resolves the bug (which I do think it is a bug) by giving a single "element" to focus upon when it is clicked.
Try this one: http://jsfiddle.net/uPZuJ/9/
Instead of checking for both mousedown and mouseup on the same element, check only for mousedown on your button and then check for mouseup on any other element.
Your button works great in Chrome. I have fixed the "click-and-hold on the text inside the button" thing by few lines of CSS and a attribute for IE.
http://jsfiddle.net/uPZuJ/2/
EDIT:
This is a screenshot of the bug I fixed:
Try this: http://jsfiddle.net/uPZuJ/22/ http://jsfiddle.net/uPZuJ/25/
This is how it works:
Initialize 'down' to false
mousedown on button causes 'down' to be true
On mouseup/click, if 'down' is true, append text 'click' and set 'down' to false
Clicking triggers a click.
Dragging the text into the padding triggers a click.
Dragging the padding into the text triggers a click.
Dragging from the inside to the outside does not trigger a click.
Dragging from outside to inside does not trigger a click.
Here is the code:
var down=false;
$("button").mousedown(function() {
down=true;
});
$("button").mouseup(function() {
if(down) {
$("#clicks").append("<div>click</div>");
}
down=false;
});
$("button").click(function() {
if(down) {
$("#clicks").append("<div>click</div>");
}
down=false;
});
After having playing around with your example, I think I got what happen behind the scene. By default click event will check both mousedown and mouseup event to be fired before it fires the callback. The problem is that you click on the text, your current target is the text now(it means mousedown event is already fired inside the text area, and it's waiting for mouseup event to be fired in order to complete a click event). However, you drag cursor out of the text and release mouse outside the text area, and your current target now is the Button, not the text anymore(mouseup event doesn't fire inside text area, but inside button area), so click event won't happen. However, if you click on the text and drag, and release your mouse inside text area, it will works just fine. This is the problem of event bubbling or capturing. In jQuery we have event.stopPropagation() or event.stopImmediatePropagation, but it just works for FF, not in Chrome.
What I suggest is using mousedown and mouseup event instead of click event.
Use "mouseup" instead of "click", it should work in ie, chrome and ff.
var elementName = "";
$("button").mouseup(function() {
if (elementName != "" && elementName == "BUTTON") {
$("#clicks").append("<span>click</span><br/>");
elementName = "";
}
});
$("button").mousedown(function() {
elementName = $(this).get(0).tagName;
});
I have a button with a MouseEvent.CLICK listener. The CLICK event is being triggered when the button is pushed, mouse is down while rolled out, then released when rolled in on the button again. I do not want this to happen, the click event should not occur when the button is being dragged.
My flash file contains a large amount of buttons and click listeners, I would like to solve this problem with as little code as possible. What is the simplest solution to this problem?
you need to add event listeners and handlers when they are required and remove them when they are no longer needed. you will use your own logic for your needs, but here's an example:
button.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownEventHandler);
function mouseDownEventHandler(evt:MouseEvent):void
{
evt.currentTarget.addEventListener(MouseEvent.MOUSE_UP, mouseUpEventHandler);
evt.currentTarget.addEventListener(MouseEvent.ROLL_OUT, rollOutEventHandler);
trace("Mouse Down");
}
function mouseUpEventHandler(evt:MouseEvent):void
{
evt.currentTarget.removeEventListener(MouseEvent.MOUSE_UP, mouseUpEventHandler);
evt.currentTarget.removeEventListener(MouseEvent.ROLL_OUT, rollOutEventHandler);
trace("Mouse Click (Mouse Up)");
}
function rollOutEventHandler(evt:MouseEvent):void
{
evt.currentTarget.removeEventListener(MouseEvent.MOUSE_UP, mouseUpEventHandler);
evt.currentTarget.removeEventListener(MouseEvent.ROLL_OUT, rollOutEventHandler);
trace("Roll Out");
}
if you have a lot of buttons which behave the same way, you should create a custom button class of which all of your buttons would be instances.
On mouse down, record the mouse coordinates, do the same on mouse up and compare the two coordinates. If the distance is more than 10px (or whatever you want) then cancel the click (or set some boolean to false that allows the code in the click listener to run).
or
On mouse down, start recording the mouse coordinates, so you know the clip has been moved, then on mouse up, you know if the clip has been moved even if the user places the clip back on exactly the same spot.
Here's my dilemma:
If I add buttons to a Sprite, I have to listen for the MOUSE_DOWN or CLICK event to make the button work as it should.
However, I want the sprite that contains the button to function like a touchscreen device, and I want the contents of the sprite to scroll up-and-down when you swipe it...
I am afraid the mouse events of the buttons will prevent the events from being captured by the container. This would mean that when I swipe over the button, the button get's clicked instead of the container.
I know Flex passes events down the chain of elements, but I don't believe this is the case for Flash.. ?
You should use MOUSE_UP event instead of MOUSE_DOWN, it's better practice, even if not to consider problems with scrolling. After there's nothing on MOUSE_UP you can hang
function onMouseDown(e: Event) {
flag = true
}
on MOUSE_DOWN. After that
function onMouseDown(e: Event) {
if (flag) {
//scrolling here
}
}
and dont forget to set flag=fasle on MOUSE_UP.