How to add event on mouse scroll and right click? - javascript

Trying to create a minesweeper game, where a right click would add a flag. The right click event, however, is currently not working, i.e, not able get the value of event.which for right and middle mouse button. Just getting contextMenu.
Sample JS:
var trig = function (event) {
if(event.which==1){
//do something on left click
}
else if(event.which === 3)
{
event.preventDefault();
console.log(event.isDefaultPrevented());
//Do something on right click.
}
}
$('.block').click(trig);
Can anyone please tell, a plausible reason why that is happening?
preventDefault was only added as the conextmenu was becoming annoying.

MouseEvent.button
0 for Left mouse button, 1 for Wheel button or middle button (if present) and
2 for Right mouse button.
Internet Explorer 8 and earlier has different values:
1 for Left mouse button, 2 for Right mouse button and
4 for Wheel button or middle button (if present).
Change
else if(event.which === 3)
To
else if(event.which === 2 || event.which === 3)
OR: For IE <= 8
else if(event.which === 2 || event.which === 4)

Related

How can I replicate key presses with click handlers?

I have a game I made with HTML5, CSS, and JavaScript. I have images of joystick arrows. I would like users to be able to click my joystick arrows and have it work as if the arrows on the keyboard were pressed. I wrote the code like this but it doesn't work:
var $rt_arrow = $('.rt_arrow')
$rt_arrow.on('click' , function (e) {
e.keyCode == 39
}
How do I make keyCode 39 fire when the image of the right arrow is clicked?
Maybe it would be a clearer approach to write a callback function and assign it to the keyboard right arrow and to the right arrow.
function goRight() { console.log('I go right');}
$('.rt_arrow').on('click', goRight);
$(document).on('keydown', function(e) {
if ( e.key === 'ArrowRight' ) {
goRight();
}
});

How to prevent page from scrolling when a JQuery button is focused and space-bar is pressed

When focus is on a button in a JQuery dialog, the space bar does two things: it selects the button and it scrolls the window. People who are familiar with space bar as a tool for selecting buttons will expect the first but find the second jarring and inappropriate.
So the question: how do I prevent the page from scrolling? I had thought that it was just a matter of returning false from the button handler but that does not appear to be true.
I've tried the solution suggested here and elsewhere and none of them worked for me. What finally worked was a document-wide keydown handler like this:
$(document).keydown(function (e) {
var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
if ((key == 32) && (e.target.className != null) && (e.target.className.indexOf("ui-button") != -1))
e.preventDefault();
});
The key == 32 is obviously a check for the space bar. The className is a check for whether the UI (User Interface) element in question is a JQuery button. Without the button check, the space bar is disabled everywhere.

Detect whether scroll event was created by user

Is it possible to tell whether a scroll event was done by the browser or by the user? Specifically, when using the back button a browser may jump to the last known scroll position. If I bind to scroll event how can I tell whether this was caused by user or browser?
$(document).scroll( function(){
//who did this?!
});
I see three types of situations that cause scrolling in a browser.
The user performs some action. For example, uses mousewheel, arrow keys, page up/down keys, home/end keys, clicks the scrollbar or drags its thumb.
The browser scrolls automatically. For example, when using the back button in your browser it will jump to the last known scroll position automatically.
Javascript scrolls. For example, element.scrollTo(x,y).
Unfortunately, there is no direct way of telling that.
I would say if you can redesign your app so that it doesn't depend on this type of flow, go for that.
If not, a workaround I can think of is to keep track of user initiated scrolls and check that to see if the scroll was triggered by the browser or by the user.
Here's an example that I put together which does this pretty well (except for browsers where jQuery history has problems with).
You need to run this locally to be able to test it fully (jsFiddle/jsbin are not good fits as they iFrame the contents).
Here's the test cases that I validated:
Page loads - userScroll is false
Scroll using mouse/keyboard - userScroll becomes true
Click on the link to jump to page bottom - userScroll becomes false
Click Back/Forward - userScroll becomes false;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
<script type="text/javascript" src="https://raw.github.com/tkyk/jquery-history-plugin/master/jquery.history.js"></script>
</head>
<body>
<span> hello there </span><br/>
click here to go down
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<a name="bottom"> just sitting </a>
</body>
<script type="text/javascript">
var userScroll = false;
function mouseEvent(e) {
userScroll = true;
}
$(function() {
// reset flag on back/forward
$.history.init(function(hash){
userScroll = false;
});
$(document).keydown(function(e) {
if(e.which == 33 // page up
|| e.which == 34 // page dn
|| e.which == 32 // spacebar
|| e.which == 38 // up
|| e.which == 40 // down
|| (e.ctrlKey && e.which == 36) // ctrl + home
|| (e.ctrlKey && e.which == 35) // ctrl + end
) {
userScroll = true;
}
});
// detect user scroll through mouse
// Mozilla/Webkit
if(window.addEventListener) {
document.addEventListener('DOMMouseScroll', mouseEvent, false);
}
//for IE/OPERA etc
document.onmousewheel = mouseEvent;
// to reset flag when named anchors are clicked
$('a[href*=#]').click(function() {
userScroll = false;
});
// detect browser/user scroll
$(document).scroll( function(){
console.log('Scroll initiated by ' + (userScroll == true ? "user" : "browser"));
});
});
</script>
</html>
Notes:
This doesn't track scrolling when the user drags the scrollbar with mouse. This can be added with some more code, which I left as an exercise for you.
event.keyCodes may vary by OS, so you may have to change that appropriately.
Hope this helps!
Rather than trying to catch all the user events, it's much easier to do the opposite and handle only the programmatic events - and ignore those.
For example, this kind of code would work:
// Element that needs to be scrolled
var myElement = document.getElementById('my-container');
// Flag to tell if the change was programmatic or by the user
var ignoreNextScrollEvent = false;
function setScrollTop(scrollTop) {
ignoreNextScrollEvent = true;
myElement.scrollTop = scrollTop
}
myElement.addEventListener('scroll', function() {
if (ignoreNextScrollEvent) {
// Ignore this event because it was done programmatically
ignoreNextScrollEvent = false;
return;
}
// Process user-initiated event here
});
Then when you call setScrollTop(), the scroll event will be ignored, while if the user scroll with the mouse, keyboard or any other way, the event will be processed.
As far as I know it is impossible (without any work) to tell whenever scroll event has been issued by "user" or by other means.
You could try (as others mentioned) catch mousewheel events, then probably trying to catch keydown event on any keys that can trigger scroll (arrows, space etc.) while checking what element is currently focused, since you for example can't scroll using arrow keys while typing in an input field.
In general that would be complex and messy script.
Depending on situation you're dealing with you could I guess "revert the logic", and instead of detecting user issued scroll events just hook in into any scrolls made programatically and treat any scroll events not made by your code as made by an user.
Like I said it depends on a situation, and what you're trying to achive.
Yes, it is 100% possible. I'm current using this in an application where IE is not a requirement - client facing only. When my Backbone app initiates an animation where scroll is changed - scroll occurs but does not trigger these event captures. This is tested in FF, Safari & Chrome latest.
$('html, body').bind('scroll mousedown wheel DOMMouseScroll mousewheel keyup', function(evt) {
// detect only user initiated, not by an .animate though
if (evt.type === 'DOMMouseScroll' || evt.type === 'keyup' || evt.type === 'mousewheel') {
// up
if (evt.originalEvent.detail < 0 || (evt.originalEvent.wheelDelta && evt.originalEvent.wheelDelta > 0)) {
// down.
} else if (evt.originalEvent.detail > 0 || (evt.originalEvent.wheelDelta && evt.originalEvent.wheelDelta < 0)) {
}
}
});
Try using the Mousewheel and DOMMouseScroll events instead. See http://www.quirksmode.org/dom/events/scroll.html
You can check the scroll position on ready. When you fire the on scroll event check to make sure the scroll position is different than it was when the page loaded. Lastly be sure to clear out the stored value once the page is scrolled.
$(function () {
var loadScrollTop = ($(document).scrollTop() > 0 ? $(document).scrollTop() : null);
$(document).scroll(function (e) {
if ( $(document).scrollTop() !== loadScrollTop) {
// scroll code here!
}
loadScrollTop = null;
});
});
Regarding to:
Specifically, when using the back button a browser may jump to the last known scroll position.
That fires very soon, after the page is rendered. You can just delay listenting to the scroll event by 1 second or so.
There is one more way to separate the user-created scroll: you can use the alternative event handlers, for example 'mousewheel', 'touchmove', 'keydown' with codes 38 and 40 for arrow scrolling, for scrolling with scroll bar - if 'scroll' event is fired simultaneously with 'mousedown' until 'mouseup' event.
Found this very useful. Here's a coffeescript version for those so inclined.
$ ->
S.userScroll = false
# reset flag on back/forward
if $.history?
$.history.init (hash) ->
S.userScroll = false
mouseEvent = (e)->
S.userScroll = true
$(document).keydown (e) ->
importantKey = (e.which == 33 or # page up
e.which == 34 or # page dn
e.which == 32 or # spacebar
e.which == 38 or # up
e.which == 40 or # down
(e.ctrlKey and e.which == 36) or # ctrl + home
(e.ctrlKey and e.which == 35) # ctrl + end
)
if importantKey
S.userScroll = true;
# Detect user scroll through mouse
# Mozilla/Webkit
if window.addEventListener
document.addEventListener('DOMMouseScroll', mouseEvent, false);
# for IE/OPERA etc
document.onmousewheel = mouseEvent;
if you're using JQuery than there's a better answer, apparently - i'm just trying it out myself.
see: Detect jquery event trigger by user or call by code
It might not help with your application, but I needed to fire an event on user scroll but not programatic scroll and posting incase it helps anyone else.
Listen to the wheel event instead of scroll,
It is triggered whenever a user uses the mouse wheel or tracker pad( which I feel is how most people scroll anyway) and isn't fired when you programatically scroll. I used it to differentiate between a user scroll action and scrolling functions.
https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event
element.addEventListener('wheel', (event) => {
//do user scroll stuff here
})
One caveat is that wheel doesn't fire on scroll on mobile, so I checked whether the device was mobile and used similar functions
if(this.mobile){
element.addEventListener('scroll', (event) => {
//do mobile scroll stuff here
})
}

jQuery click() event; how to prevent this event on right mouse btn click?

<script>
$("#test_img").click(function() {
alert("Hello");
});
</script>
But it doesn't matter what mouse button I'm pressing - right or left. I see absolutely the same result. I want alert to be shown only on left mouse button click.
Thank you and sorry; I'm little new to javascript.
Thank you.
You can evaluate the event.which attribute to determine which button has been pressed.
$("#test_img").mouseup(function(e) {
// e.which is 1, 2 or 3 for left / middle / right mouse button
if (e.which === 1) {
//continue
}
});
Furthermore, to safely detect a mousebutton, you cannot use the click-event! Use mousedown or mouseup instead.
Try it out here!

Setting focus using left and right arrows (HTML + JS)

Is there any to make the left arrow behave like the tab button (set focus to the next focusable item) and the right arrow behave like a shift+tab (set focus to the previous focusable item)?
I've gotten this far:
$().keypress(function(e) {
if (e.keyCode == 37) {
alert('I want to do a shift-tab');
}
else if (e.keyCode == 39) {
alert('I want to do a tab');
}
});
But google isn't being that helpful so I thought I'd put a quick post up here while I google some more.
Thanks!
Oh, and it's purely for FF3.0 so I don't need to worry about other browser nuisances.
What you have so far seems fine.
You could keep a list of 'focusable' items and just iterate through the list keeping a pointer to the current one:
// or $('input')..depends what you want to focus on
var nodes = $('.focusable'), idx = -1;
$().keypress( function(e) {
if (e.keyCode === 37) {
nodes.get(++idx).focus();
}
else if (e.keyCode === 39) {
nodes.get(--idx).focus();
}
});
This is just a rough outline though. You'd need to check the idx before doing something to make sure you don't slip past the beginning or end of the focusable elements array. You'll also need to be careful about calling this when the user is inside of a textbox.

Categories

Resources