I am new to javascript and am stuck with an issue
I am not able to prevent click on an element while dragging. What do i need to do in my event handlers to prevent click on dragging/ note click should work as normal while element is not being dragged
I tried prevent default and stop propagation inside the dragstart event handler, but this seems to disable the drag action and not the click action
this.message_list
.addEventListener('initrow', function(o) { ref.init_message_row(o); })
.addEventListener('dblclick', function(o) { ref.msglist_dbl_click(o); })
.addEventListener('keypress', function(o) { ref.msglist_keypress(o); })
.addEventListener('select', function(o) { ref.msglist_select(o); })
.addEventListener('dragstart', function(o) {alert('33'); ref.drag_start(o);})
.addEventListener('dragstart', function(e) {alert('44'); ref.drag_start(e); })
alerts 33 and 44 fire on dragstart , but adding stuff like stopping event propagation or preventing default action, disables the drag and not the click.
Once again click action is needed on the same element when it is not being dragged
Related
Repro: https://jsfiddle.net/ssabc/cL6qxn1r/13/
I have a background element and a foreground element (you can think of it as a dialog popup on top of a canvas). When the user right-clicks on the foreground I would like to prevent the context menu from appearing in the background.
I tried binding a handler for the foreground's context menu and returning false from it to no avail:
document.getElementById('above').oncontextmenu = function(e) {
e.preventDefault();
return false;
}
As you can see in the JSFiddle, the oncontextmenu-event triggers on both elements. Here's a screenshot showing event firing in the background no matter which element is right-clicked
Is there any way to prevent the background event from firing?
You just need to add
e.stopPropagation();
to your child element right click event handler. With the change, it would look like this:
document.getElementById('above').oncontextmenu = function(e) {
e.preventDefault();
e.stopPropagation(); // <=== add this
getResultP().innerHTML += '<li>Dialog oncontextmenu called</li>';
return false;
}
This prevents the event from bubbling up the DOM tree. Read more about it here.
I have a website that does not allow to open up the context menu by clicking the right button on a mouse.
It seems like the website does blocking it by using preventDefault on the event oncontextmenu.
I was able to bypass it by
window.addEventListener('contextmenu', (event) => {
event.stopPropagation();
}, true)
I know that preventDefault blocks the default action of an event and stopPropagtion prevents an event from firing bubble to its parent element. But how does stopPropagation cancel preventDefault?
By calling stopPropagation you stop other attached event listeners from capturing the event. Thus, the event listener that would call preventDefault would not capture it and thus would not prevent the context menu from opening.
See in the example below. The listener that tries to prevent the context menu from opening is not executed because stopPropagation is called:
window.addEventListener('contextmenu', (event) => {
console.log('stopPropagation')
event.stopPropagation();
}, true)
document.body.addEventListener('contextmenu', (event) => {
console.log('stop context menu')
event.preventDefault();
})
Right click
<br/>
<br/>
Notice that 'stop context menu' is not logged
I have a click event handler and a mousedrag event handler for a Paper.js Item.
item.on('click', function(event) {
event.stopPropagation();
event.preventDefault();
//...
});
item.on('mousedrag', function(event) {
event.stopPropagation();
event.preventDefault();
//...
});
Whenever I cause a mousedrag event a click event is also generated. How can I prevent this?
When the mouse is clicked then released a click event is generated. When the mouse is held down and dragged, drag events are generated. I generally implement this by setting events on 'mousedown' and 'mouseup' in addition to 'mousedrag'.
Playing around I've found that if you return false from your 'mousedrag' event handler it will suppress further events, i.e., neither 'mouseup' nor 'click' will be invoked. Here's a sketch illustrating mouse events. If you uncomment the return false in the 'mousedrag' handler you will not get the 'mouseup' or 'click' events.
The following is example code for how I usually implement it - I didn't discover that returning false from the handler suppressed further processing until looking at the code tonight.
var drag;
view.on('mousedown', function(e) {
drag = false;
});
view.on('mousedrag', function(e) {
drag = true;
// do whatever else you need to when dragging the mouse
});
view.on('mouseup', function(e) {
// see if it was just a click and handle that
if (drag) {
// handle the end of a drag
} else {
// do whatever a click down/up without drag needs to do
}
});
Here's a JSFiddle of the behavior I'm seeing, relating to middle-click and the click event in Chrome and FF.
'click' kinda sorta works
Approach 1: Bind a click handler directly to an a element and a middle-click will trigger the handler in Chrome but not in FF.
$('div a').on('click', function(ev) {
// middle click triggers this handler
});
Approach 2: Bind a delegated click handler to a div which contains one or more a. Middle click will not trigger this handler in Chrome or FF.
$('div').on('click', 'a', function(ev) {
// middle click doesn't trigger this handler
});
This approach is extremely valuable if the div starts out empty and the a elements are filled in later by an AJAX call, or as a result of some user input.
'mouseup' works
Using mouseup instead of click causes both approach 1 and 2 to work in both browsers.
// Approach 1 w/ mouseup
$('div a').on('mouseup', function(ev) {
// middle click **does** trigger this handler in Chrome and FF
});
// Approach 2 w/ mouseup
$('div').on('mouseup', 'a', function(ev) {
// middle click **does** trigger this handler in Chrome and FF
});
Here's the JSFiddle with mouseup.
This is interesting and might be useful in some cases, because mouseup is almost click. But mouseup isn't click, and I'm after the behavior of click. I do not want to create a hacky mousedown; setTimeout; mouseup simulation of click.
I'm pretty sure the answer is "nope", but is there a cross-browser way to cause middle-click to trigger click handlers? If not, what are the reasons why?
The click event is generally fired for the left mouse button, however, depending on the browser, the click event may or may not occur for the right and/or middle button.
In Internet Explorer and Firefox the click event is not fired for the right or middle buttons.
Therefore, we cannot reliably use the click event for event handlers on the middle or right button.
Instead, to distinguish between the mouse buttons we have to use the mousedown and mouseup events as most browsers do fire mousedown and mouseup events for any mouse button.
in Firefox and Chrome event.which should contain a number indicating what mouse button was pressed (1 is left, 2 is middle, 3 is right).
In Internet Explorer on the other hand, event.button indicates what mouse button was clicked (1 is left, 4 is middle, 2 is right);
event.button should also work in Firefox and other browsers, but the numbers can be slightly different (0 is left, 1 is middle, 2 is right).
So to put that together we usually do something like this :
document.onmousedown = function(e) {
var evt = e==null ? event : e;
if (evt.which) { // if e.which, use 2 for middle button
if (evt.which === 2) {
// middle button clicked
}
} else if (evt.button) { // and if e.button, use 4
if (evt.button === 4) {
// middle button clicked
}
}
}
As jQuery normalizes event.which, you should only have to use that in jQuery event handlers, and as such be doing:
$('div a').on('mousedown', function(e) {
if (e.which === 2) {
// middle button clicked
}
});
In other words you can't use the onclick event, so to simulate it you can use both mousedown and mouseup.
You can add a timer to limit the time allowed between the mousedown and mouseup event, or even throw in a mousemove handler to limit the movement between a mousedown and mouseup event, and make the event handler not fire if the mouse pointer moved more than ten pixels etc. the possibilites are almost endless, so that shouldn't really be an issue.
$('#test').on({
mousedown: function(e) {
if (e.which === 2) {
$(this).data('down', true);
}
},
mouseup: function(e) {
if (e.which === 2 && $(this).data('down')) {
alert('middle button clicked');
$(this).data('down', false);
}
}
});
Short answer: Nope.
The question is, what do you want to capture the middle clicks for? A middle click isn't meant to interact with the current page but rather to open a link in a new tab.
Chrome is also currently working on droping this behavior: https://code.google.com/p/chromium/issues/detail?id=255
And there is currently a general discussion on the w3c mailing list about this topic: http://lists.w3.org/Archives/Public/www-dom/2013JulSep/0203.html
Yet for now, you can catch middleclicks in Firefox on a document-level:
$(document).on('click', function(e){
console.log(e);
});
I've build a factory for creating Middle mouse click handlers using vanilla JS and working in latest Firefox and Chrome:
const MiddleClickHandlerFactory = (node, handlerFn) => {
node.addEventListener('mousedown', e => {
if (e.button !== 1) return;
e.preventDefault(); // stop default scrolling crap! Instead install ScrollAnywhere!
const originalTarget = e.target;
document.addEventListener('mouseup', e => { // register on DOCUMENT to be sure it will fire even if we release it somewhere else
if (e.target.isSameNode(originalTarget)) handlerFn(e);
}, {capture: true, once: true, passive: true});
}, true)
};
I have a CSS button that has normal, pressed and hover states. Everything works fine except that when the click has happened, I need to somehow know whether the style should be set to normal or hover. That is, I need a way of knowing if the mouse cursor is still hovering the element. How would one achieve this with JavaScript?
If you're concerned about the user doing a mousedown, then moving the pointer off (and perhaps on again) the button, you could do something like this:
EXAMPLE: http://jsfiddle.net/7zUaj/1/
var mouseIsDown = false; // Track/remember mouse up/down state for the button
// Handle mouseenter and mouseleave
$('div').hover(function() {
$(this).addClass('hover');
if (mouseIsDown)
$(this).addClass('pressed'); // If mouse button was down, and user exited
// and reentered the button, add "pressed"
}, function() {
$(this).removeClass('hover pressed'); // Remove both hover and pressed when
// the pointer leaves the button
})
// Handle the mousedown, track that it is down, and add "pressed" class
.mousedown(function() {
mouseIsDown = true;
$(this).addClass('pressed');
})
// Handle the mouseup, track that it is now up, and remove the "pressed" class
.mouseup(function() {
mouseIsDown = false;
$(this).removeClass('pressed');
});
// If user does mousedown, leaves the button, and does mouseup,
// track that it is now up
$(document).mouseup(function() {
mouseIsDown = false;
});
The state of the mouse is tracked in a variable and set in the button's handlers for mousedown and mouseup. The mouseup is also tracked at the document level. This will help the mouseenter part of the .hover() to know if it should set the pressed class or not.
(Note that because the mouseup is also tracked on the document, if there are any other elements on the page that stop the event from bubbling, the mouseup would not be detected by the document.)
EDIT: Made it so the document only tracks mouseup, and the button tracks both.
You don't have a :visited state in your CSS? As for Javascript, OnMouseOver or JQuery mouseover, hover or mouseenter (depending on what you want to do) will tell you when the hover is happening.