In my simple application canvas wrapped by hyperlink. Some objects, which are placed on canvas stage have special mouse interaction on click event. Is there any possible solutions to prevent hyperlink jumping by clicking on objects with my mouse click event listeners?
Normally you can just call preventDefault on the generated mouse event, and it will stop the link event from firing.
element.addEventListener("click", function(e) {
e.preventDefault();
}, false);
This is not possible using EaselJS because although you can access the nativeEvent on any EaselJS mouse event, EaselJS doesn't use the "click" event at all (and instead uses a combination of "mousedown" and "mouseup"). So preventing default on a click event will do nothing.
Doesn't work
// You would expect this to work.
myShape.on("click", function(e) {
e.nativeEvent.preventDefault(); // Nothing. This cancels a "mouseup" instead.
});
Workaround
However, you can work around this pretty easily. Set a flag on the clicked item (or wherever you would set it in your application) any time it is clicked.
myShape.addEventListener("click", function(event) {
myShape.clicked = true;
}, false);
Then, listen for the canvas click event yourself, check and check the flag. Make sure to reset it after. This is possible because "click" is always fired after "mouseup"
stage.canvas.addEventListener("click", function(event) {
if (myShape.clicked) { event.preventDefault(); }
myShape.clicked = false;
}, false);
Here is a quick fiddle showing it working. http://jsfiddle.net/buqkvb1u/
We are looking to see if this makes sense to handle in EaselJS. Thanks for your report!
Related
i have:
<input type="text" />
and
$('input').blur(function(){
alert('stay focused!');
});
I want to prevent the blur function running when I'm "blurring" by clicking on an anchor element.
I.E. if i tab to another input, click somewhere on the page etc i want the blur to fire, but if i click a link, I don't want it to fire.
Is this easily achievable, or do i need to hack about with delegates and semaphores?
Thanks
I had to solve this problem myself today, too. I found that the mousedown event fires before the blur event, so all you need to do is set a variable that indicates that a mousedown event occurred first, and then manage your blur event appropriately if so.
var mousedownHappened = false;
$('input').blur(function() {
if(mousedownHappened) // cancel the blur event
{
alert('stay focused!');
$('input').focus();
mousedownHappened = false;
}
else // blur event is okay
{
// Do stuff...
}
});
$('a').mousedown(function() {
mousedownHappened = true;
});
Hope this helps you!!
If you want to keep the cursor at its position in a contenteditable element, simply:
$('button').mousedown(function(){return false;});
Delay the blur a bit. If the viewer clicks a link to another page, the page should change before this code gets a chance to run:
$('input').blur(function(){
setTimeout(function() {alert('stay focused!');}, 1000);
});
You can experiment with what delay value for the timeout seems appropriate.
You can get this behavior by calling preventDefault() in the mousedown event of the control being clicked (that would otherwise take focus). For example:
btn.addEventListener('mousedown', function (event) {
event.preventDefault()
})
btn.addEventListener('click', function(ev) {
input.value += '#'
input.setSelectionRange(ta.value.length, ta.value.length)
})
See live example here.
Some clarification that was too long to put in a comment.
The click event represents both pressing the mouse button down, AND releasing it on a particular element.
The blur event fires when an element loses focus, and an element can lose focus when the user "clicks" off of the element. But notice the behavior. An element gets blurred as soon as you press your mouse DOWN. You don't have to release.
That is the reason why blur gets fired before click.
A solution, depending on your circumstances, is to call preventDefault on mousedown and touchstart events. These events always (I can't find concrete documentation on this, but articles/SO posts/testing seem to confirm this) fire before blur.
This is the basis of Jens Jensen's answer.
I'm making a Firefox extension to record user clicks on a website. I'm using eventListener to detect clicks on any elements on the website but for some reason clicks on input elements or dropdown options are not registered. Any idea on why this is? Here's the code for the extension:
alertClick : function(aEvent) {
document.addEventListener('click', function(e) {
window.alert("click");
}, false);
Moving to solution:
Instead of click try mouseup or mousedown. The reason is because click does not fire IF you mousedown then move your mouse too much and/or wait a long time and then do mouseup.
I am wondering if mouseenter and click event can exist together and they can both exist to TRUE when checked with:
if ((evt.type === 'mouseenter') && (evt.type === 'click'))
It is because when I mouse over the link, the mouseenter triggers (set to TRUE) and even when I clicked on it, the hover is still shown. Probably they could exist together but I'm no expert on this.
If someone can give insights, I would appreciate it a lot.
Also how can I trigger the click event during the mouseenter event?
The mouseenter event fires when the mouse enters the control. The click event fires when the mouse is clicked. They are two separate events which call two separate event handlers. If you click just as the mouse enters the element they will be called within a short timespan of one another but they are still two distinct events.
It is also important that you differentiate between the mouseenter and the mouseover events. mouseenter fires when the mouse physically enters an element, whereas mouseover fires continually while the mouse remains over an element.
While you cannot trigger the click event per se, you can call the same function that is called by the click event handler. For example if you have this:
var myfunc = function (e) { ... }
document.getElementById("id").onclick = myfunc;
Then you could simply call myfunc directly and you would get the same result as if the mouse was clicked.
They can 100% exist together, and this is a great question with no good answer... When you're on a mobile device, a mouseenter event will be thrown on tap... If you are also detecting onclick as well as mouseenter, then there will be a discrepancy between mobile devices and desktop machines.
It's kind of hard to solve such a small issue at the moment.
const x = document.getElementById('some_node')
x.onclick=(e)=>{
e.stopPropagation()
// this logic will be triggered on click for both desktop and mobile
}
x.onmouseenter=(e)=>{
e.stopPropagation()
// this logic will be triggered on click for mobile only (but will
//have already been triggered on desktop when cursor entered node)
}
The only workaround I came up for this, and I think it's pretty clever, is using a eventlistener for taps/touches. The order/priority that these events are fired goes: touch > mouseenter > click.
Since the touch event is fired first, you can add a touch event listener (which will only register on a mobile device), and change a variable that prevents the mouseenter event from being triggered (which is the logic that would generally be conflicting with the onclick logic)... like this:
let isMobile = false
x.addEventListener('touchstart',(e)=>{
isMobile = true
}, false);
Then your mouseenter would need to look like this:
x.onmouseenter=(e)=>{
e.stopPropagation()
if(!isMobile){
// this logic will no longer cause a conflict between desktop and mobile
}
}
they can exist on the same object, think a button with a hover state and then a click action. The click event, though will only read the click event since the enter event actually occurred earlier.
You can create a var like mouseIsOverand set it to true when the enter event fires. I can be safely assumed, though that if a click happens the mouse is over the same target.
The two events may happen at the same time, but they will still be processed on after the other. So the if you posted will never evaluate to true.
If you look at your code again you can see that it doesn't make sense. How can something be X and Y at the same time? It can't.
for the first question i think u got an answer....
however, for Also how can I trigger the click event during the mouseenter event?
u can use trigger() function..
http://jsfiddle.net/PDhBW/2/
if u want to read more about trigger
here is the link
http://api.jquery.com/trigger/
With Jquery event delegation, You can use binding multiple events at once
$('#IdElement').on('mouseenter click', function () {
//Your Code
});
http://jqfundamentals.com/chapter/events
for arcane reasons I need to be able to cancel the click event via the mousedown event.
Briefly; I am creating a context menu in the mousedown event, however, when the user clicks on the page the context menu should disappear.
I am not able to use the mousedown event over the click in that scenario as I want the user to be able to click links inside the menu ( a full click would never travel to the <a> based menu elements ).
If it is any help, jQuery can be applied.
I would like to either be able to prevent the click event from happening from within the initial mousedown, or be able to pass information to the click event (via originalEvent or otherwise).
TIA
Seems to be impossible, neither FF nor Opera didnt cancel upcoming click when prevented in mousedown and/or mouseup (as side note: click is dispatched after mouseup if certain conditions met). testcase: http://jsfiddle.net/ksaeU/
I have just had the exact same problem. I fixed my context menu by closing it on mousedown and eating the mousedown event on the menu so that I can still receive clicks on the menu, like so:
$(document).one('mousedown.ct', null, function() { cmenu.hide(); return false; });
cmenu.bind('mousedown', function(e) { e.stopImmediatePropagation(); });
And in the hide() function I unbind the mousedown.ct again, in case it was closed due to a click on an item.
Hey, I think this is what you are trying to do with your code. If not, I apologize, I may have misunderstood the question. I used jQuery to get it done: http://jsfiddle.net/jackrugile/KArRD/
$('a').bind({
mousedown: function(){
// Do stuff
},
click: function(e){
e.preventDefault();
}
});
I have an onclick event attached to a region in my page that causes a certain action to fire when the user clicks in it (naturally). I recently added an image to that region. When the user clicks on that image, I want another action to occur, and I do NOT want the action associated with the entire region to occur. However, I find that both events are, in fact fired when one clicks the image. How do I suppress the region-wide action when the image is clicked?
The issue you are running into is known as event bubbling. The click event of the image bubbles up to all parent elements of that node. You want to cancel bubbling.
The best way to do this that works across all browsers is by using a JavaScript framework. jQuery has a very simple way to do this. Other frameworks have similar mechanisms to cancel bubbling, I just happen to be most familiar with jQuery.
For example, you could do something like this in jQuery:
$('img').click(function () {
// Do some stuff
return false;// <- Cancels bubbling to parent elements.
});
Darit is correct, you need to stop the event from bubbling (propagating):
function imgEventHandler(e) {
// ^notice: pass 'e' (W3C event)
// W3C:
e.stopPropagation();
// IE:
if (window.event) {
window.event.cancelBubble = true;
}
}
In the event handler for the image do
event.cancelBubble = true;
and then at the end do
return false;