how to re-enable default after doing event.preventDefault() - javascript

I know this exact question was asked here, but the answer didn't work for what I needed to do so I figured I'd give some example code and explain a bit...
$(document).keypress(
function (event) {
// Pressing Up or Right: Advance to next video
if (event.keyCode == 40 || event.keyCode == 39) {
event.preventDefault();
$(".current").next().click();
}
// Pressing Down or Left: Back to previous video
else if (event.keyCode == 38 || event.keyCode == 37) {
event.preventDefault();
$(".current").prev().click();
}
}
);
It basically disables the arrow keys to use them for something else, but doing:
$(document).keypress(function () { });
doesn't enable the default function again... I need it to scroll the page without having to create a scroll function for it...
Any ideas?
Thanks,
Matt

Adding a new handler doesn't replace the previous one, it adds a new one. You may be looking for jQuery#unbind if you're trying to remove the previous handler, but if you're going to be turning this on and off a lot, you probably would be better off with a flag telling you whether to prevent the default or not in your existing handler.
Adding, and later removing, a handler looks like this:
function keypressHandler() { /* ... */};
$('#thingy').keypress(keypressHandler);
// ...elsewhere...
$('#thingy').unbind('keypress', keypressHandler);

I'm not sure this is the right way to handle it.
A better way to approach this problem would be to put some kind of check inside your document.keypress instructions.. like..
var enableKeys = false;
$(document).keypress(
function (event) {
// Pressing Up or Right: Advance to next video
if (event.keyCode == 40 || event.keyCode == 39 && enableKeys) {
event.preventDefault();
$(".current").next().click();
}
// Pressing Down or Left: Back to previous video
else if (event.keyCode == 38 || event.keyCode == 37 && enableKeys) {
event.preventDefault();
$(".current").prev().click();
}
}
);
Then control the enablekeys wherever you feel necessary, either with a hover, or something along those lines.

function(e){ e.preventDefault(); }
and its opposite
function(e){ return true; }

Why not just wrap a condition around event.preventDefault(); in your current code?

Try to unbind the keypress event from document.
I don't know of any other ways to do it.
HTH

Related

Key Navigation with Javascript

Please Help! I have spent a week to complete this game and this is the final huddle i have been stuck with for a couple of days now. I know some techy out there would probably take a glance and flick something in place. But I'm not very sophisticated with javascript and therefore need some help.
$(document).keydown(function(e){
// left arrow
if (e.keyCode == 37 && currentCell > 0) {
currentCell--;
ChangeCurrentCell();
return false;
}
// up arrow
if (e.keyCode == 38 && currentRow > 0) {
currentRow--;
ChangeCurrentCell();
return false;
}
// right arrow
if (e.keyCode == 39 && currentCell < MAX_CELL) {
currentCell++;
ChangeCurrentCell();
return false;
}
//down arrow
if (e.keyCode == 40 && currentRow < MAX_ROW) {
currentRow++;
ChangeCurrentCell();
return false;
}
// enter key
if (e.keyCode == 13) {
}
});
function ChangeCurrentCell()
{
document.getElementById(Boxes[currentRow + currentCell]).focus();
SimulateMouseOver(document.getElementById(Boxes[currentRow + currentCell]));
}
// function will trigger event of selecting current focus.
function selectElement()
{
}
$(document).ready(function(){
loadDivs()
// will give initial focus to top left element paving way for key navigation
ChangeCurrentCell();
// above gives first element in Boxes the focus when loading.
The div element will not focus despite getting it and calling the focus method, i have tried to trigger mousehover on the element with no luck. Please assist me, i put my masters thesis aside despite already being on a tight schedule to do this game which is a requirement for a job position. I have done whole the whole game logic and it all works well, if i send the code in as it is it will definitely be discarded because it doesnt meet the key navigation requirement ... i am desperate i will even pay if i need to -frustrated Student
Look at this
It's my solution for a test, maybe the same...maybe can help you :) If it is, please use it as a hint and don't copy all my code :D
Regards,
L.
You can bind to the document.keydown event to capture key strokes. Then you can use event.which (normalized by jQuery) to determine which key was pressed.
$(document).on("keydown", function (event) {
if (event.which === 37) {
//code for left arrow
} else if (event.which === 38) {
//code for up arrow
} else if (event.which === 39) {
//code for right arrow
} else if (event.which === 40) {
//code for down arrow
}
});
UPDATE
I just noticed you didn't tag your question with jQuery. To use native JS you'll have to change how you bind to the document.keydown event and how you determine the key that was pressed (different browser implementations store the info under different indexes of the event object).
to make it more convenient () not necessary:
`var LEFT = 37, UP = 38, RIGHT = 39, DOWN = 40, SPACE = 32;`
then bind to keydown, keypress doesn't catch arrow keys
and do something like this:
$(document).bind("keydown", function (e){
var which = e.which;
var navigationKeyWasPressed = which !== undefined && which >= 39 && which <= 40;
//do nothing if no significant key was pressed
if (!navigationKeyWasPressed ) {
return;
}
if ($(".selectedWithKey").length === 1){
switch (which) {
case LEFT:
//...
break;
case UP:
//...
break;
case RIGHT:
//...
break;
case DOWN:
//...
break;
case SPACE:
//turn card
break;
default: //non arrow pressed
//...
}
} else {
// if no card is selected, select one to start arrow navigation
$(".sponsor:first").addClass("selectedWithKey")
}
});

Can't find the bug - too many firings

(edited some spelling errors)
So here's a piece of code that repeats itself with every answer the user gives to an MPC-question:
It fires the question, generates 4 answers, binds 'click' and 'mouseover' to the answers, and waits for the user to actually click on one of them.
When he does, it checks if it was right or wrong, displays that to the user, and then waits for another input (anywhere in the document, this time) before it proceeds and repeats.
Now, the idea is that a user can either click with the cursor, OR use QWER to answer. And as I'm am quite new to manipulation of an event and its data, I found a (flawed, apparently) way to separate the two, as you'll find below.
However, when a user 'answers' by clicking, and 'proceeds' by QWER, it waltzes through the whole thing too fast, by actually firing the question as intended, and then immediately answering it AND firing another question AGAIN. (And after extracting the time it takes for this into an array, I found that it sometimes does this 3-6 times in a row, with no apparent reason for this how many times at all...)
Now, as mentioned, I am new when it comes to events, so there may be redundancies and/or wrong uses of (e), but bear with me. I expect the bug to be related to this, of course. Also, some functions are irrelevant here, because they lead back to whatever function their call is in (right(); for example, does not fire anything after itself).
It's the loop that's the point here.
Thanks in advance!
Here's the code:
function keyAns() {
answered="no";
draw(0);
}
function keyNotAns (A) {
B = $(A).children('.answer');
if ($(B).hasClass('right')) {
// do something
}
else if ($(B).hasClass('wrong')) {
// do something
}
answered = "yes";
}
function waitForInput() {
// MOUSE CLICK
$(document).click(function() {
if (answered == "yes") {
answered = "no";
draw(0);
}
});
$('.answer').click(function(e) {
$('.answer').unbind('click');
if (answered == "no") {
calcTime(1);
e.stopPropagation();
if ($(this).hasClass('right')) {
// do something
}
else if ($(this).hasClass('wrong')) {
// do something
}
answered = "yes";
}
});
// KEYPRESSES
$(document).bind('keyup', function(e){
$(document).unbind('keyup');
if (answered == "yes") {
e.stopPropagation();
keyAns();
}
else if ( answered == "no") {
calcTime(1); // irrelevant
if(e.which == 81 || e.keyCode == 81) { // Q
AAA = '#ansQ';
e.stopPropagation();
keyNotAns(AAA);
}
else if(e.which == 87 || e.keyCode == 87) { // W
AAA = '#ansW';
e.stopPropagation();
keyNotAns(AAA);
}
else if(e.which == 69 || e.keyCode == 69) { // E
AAA = '#ansE';
e.stopPropagation();
keyNotAns(AAA);
}
else if(e.which == 82 || e.keyCode == 82) { // R
AAA = '#ansR';
e.stopPropagation();
keyNotAns(AAA);
}
else {
}
waitForInput();
}
});
}
Every time that there's a keypress event, you rebind everything.
This means that if you push 10 keys, you will have 10 onclick listeners. So when a user then clicks, the callback will run 10 times in a row.
The code that you posted doesn't include the original call to the waitForInput function, but you only need to call it once, so you can delete it from this code.
A quick introduction to jquery events:
When you bind, every time that event occurs (on the element you put it to), the callback function you provided will run.
Another tip is that in more recent versions of jQuery, there in an alternative to bind named one. It does the same, but it will only run the first time. Although in this situation, you don't need it.
Your problem is that inside your keybind, you're calling waitForInput.
Asynchronous programming takes some getting used to, but what the functions do inside waitForInput is set up event listeners, and any time the event happens, those listeners fire.
The problem you're seeing is that after handling an event, you're adding more event listeners, and next time the event fires, the listener will fire multiple times.
Simply take the waitForInput() line out of the function, and put it at the bottom of your code. Then it will run only once, and you'll be fine. (It wouldn't hurt to rename it to something like setupEventListeners, to avoid confusion.)
Found it!
All thanks to Scott Mermelstein and ColBeseder, both equally invaluable to my solution! Not only did they find the flaws, they made me understand how events and binds work. So thanks a million, you two!
Indeed:
binds were being stacked, therefore IF it fired, it would fire excessively, also;
the self-call of waitForinput() was indeed unneeded, however;
one e.stopPropagation() was also needed, to prevent the loop from working with wrong event-data, which lead the function to interpret it as the next answer and fire itself again.
Plus: due to laziness - I didn't feel like too much trial and error - I wanted to stay on the safe side, so I added all unbind()'s as first-thing when the function fires.
The result, which works flawlessly, for those who're interested:
function keyNotAns (A) {
B = $(A).children('.answer');
if ($(B).hasClass('right')) {
// do something
}
else if ($(B).hasClass('wrong')) {
// do something
}
answered = "yes";
}
function waitForInput() {
$(document).unbind('keyup');
$(document).unbind('click');
$('.answer').unbind('click');
// MOUSE CLICKS
$(document).click(function() {
if (answered == "yes") {
answered = "no";
draw(0);
}
});
$('.answer').click(function(e) {
if (answered == "no") {
calcTime(1);
if ($(this).hasClass('right')) {
// do something
}
else if ($(this).hasClass('wrong')) {
// do something
}
e.stopPropagation();
answered = "yes";
}
});
// KEYPRESSES
$(document).bind('keyup', function(e){
if (answered == "yes") {
answered="no";
draw(0);
}
else if (answered == "no") {
if(e.which == 81 || e.keyCode == 81) { // Q
keyNotAns('#ansQ');
}
else if(e.which == 87 || e.keyCode == 87) { // W
keyNotAns('#ansW');
}
else if(e.which == 69 || e.keyCode == 69) { // E
keyNotAns('#ansE');
}
else if(e.which == 82 || e.keyCode == 82) { // R
keyNotAns('#ansR');
}
}
});
}
There are two ways to find such bugs. The first one is using the debugger - which can be pretty tedious when you have loops.
The second approach is logging: Write a report / log of all the important actions that you can read later to find out why it failed at some point in the past.
Have a look at console.log() or a JavaScript logging framework.

Prevent window scroll jquery

I'm developing a select menu replacement in jquery.
First I've to make the new select menu focusable by just adding tabindex="0" to the container.
Then, I disable focus on the original select menu and give focus to the new one.
When the new one is focused and you press the up and down arrows the options change accordingly but there's a big problem. As you press the arrows the body moves too.
I tried all these solutions so far with no luck:
$(window).unbind('scroll');
$(document).unbind('scroll');
$('body').unbind('scroll');
$(window).unbind('keydown');
$(document).unbind('keydown');
Check the code here http://pastebin.com/pVNMqyui
This code is from the development version of Ideal Forms http://code.google.com/p/idealforms that I'm about to release soon, with keyboard support.
Any ideas why this is not working?
EDIT: Solved!
Found the answer on this post jquery link tag enable disable
var disableScroll = function(e){
if (e.keyCode === 40 || e.keyCode === 38) {
e.preventDefault();
return false;
}
};
// And then...
events.focus: function(){ $(window).on('keydown', disableScroll); }
events.blur: function(){ $(window).off('keydown', disableScroll); }
It works!
In your keydown handler, for up and down keys, return false like this:
'keydown' : function (e) {
if (e.keyCode === 40) { // Down arrow
that.events.moveOne('down');
}
if (e.keyCode === 38) { // Up arrow
that.events.moveOne('up');
}
return false;
}
Also, make sure this return gets propagated to the browser's native onkeydown depending on how/which framework you're using.
Found the answer on this post jquery link tag enable disable
var disableScroll = function(e){
if (e.keyCode === 40 || e.keyCode === 38) {
e.preventDefault();
return false;
}
};
// And then...
events.focus: function(){ $(window).on('keydown', disableScroll); }
events.blur: function(){ $(window).off('keydown', disableScroll); }
You need to cancel the keydown event for arrow keys. Use either e.preventDefault() or return false in your .keydown() handler if an arrow key has been pressed.
Its very simple.you need not even need jQuery for this.
jQuery:
$("body").css("overflow", "hidden");
javascript
<body style="overflow: hidden">
Adding in style:
<style>
body {width:100%; height:100%; overflow:hidden, margin:0}
html {width:100%; height:100%; overflow:hidden}
</style>
if you want to bind the arrow keys,try something like:
$('body').keydown(function(e){
e.preventDefult();
if(e.keyCode == 37) // for left key
{
// implement focus functionality
}
if(e.keyCode == 38) // for up key
{
// implement focus functionality
}
if(e.keyCode == 39) // for right key
{
// implement focus functionality
}
if(e.keyCode == 40) // for doqn key
{
// implement focus functionality
}
});
The Best way to achive the same is to set overflow of the body to hidden
$("body").css("overflow", "hidden");
After the process just do the opposite
`$("body").css("overflow", "hidden");

Overwriting key events

How to overwrite or remove key events, that is on a website? I'm writing a script for GreaseMonkey and I want to make event on Enter button, but when I press the ENTER button, it triggers function on website.
EDIT 1: Here is the website, that I need to do this http://lockerz.com/auth/express_signup
One of these two should do it for you. I used the first one, although someone on SO told me the second one will work also. I went for the hammer.
Sorry, first one wasn't a cut and paste answer. I use using it to return up/down arrow control on a website. I changed it so that it identifies keycode 13 instead.
(function() {
function keykiller(event) {
if (event.keyCode == 13 )
{
event.cancelBubble = true;
event.stopPropagation();
return false;
}
}
window.addEventListener('keypress', keykiller, true);
window.addEventListener('keydown', keykiller, true);
})();
Searching quickly on SO:
jQuery Event Keypress: Which key was pressed?
Code from there:
var code = (e.keyCode ? e.keyCode : e.which);
if(code == 13) { //Enter keycode
//Do something
}
Without a library, use: http://jsfiddle.net/4FBJV/1/.
document.addEventListener('keypress', function(e) {
if(e.keyCode === 13) {
alert('Enter pressed');
return false;
}
});

How can I disabling backspace key press on all browsers?

I'm trying to disable the backspace button on an order page in all cases except when a textarea or text input is an active element to prevent users from accidentally backing out of an order. I have it working fine in most browsers, but in IE (testing in IE9, both regular and compatibility mode) it still allows the user to hit the backspace and go to the previous page.
Here's the code:
$(document).keypress(function(e){
var activeNodeName=document.activeElement.nodeName;
var activeElType=document.activeElement.type;
if (e.keyCode==8 && activeNodeName != 'INPUT' && activeNodeName != 'TEXTAREA'){
return false;
} else {
if (e.keyCode==8 && activeNodeName=='INPUT' && activeElType != 'TEXT' && activeElType != 'text'){
return false;
}
}
});
Any advice on what I'm doing wrong here?
Thanks!
I think you're overcomplicating that. Rather than checking for an active element, find the event target instead. This should give you the information you need. It's also better to use keydown rather than keypress when there is no visible character. Finally, it's better to use e.preventDefault() for better granularity.
$(document).keydown(function(e) {
var nodeName = e.target.nodeName.toLowerCase();
if (e.which === 8) {
if ((nodeName === 'input' && e.target.type === 'text') ||
nodeName === 'textarea') {
// do nothing
} else {
e.preventDefault();
}
}
});
NB I could have done this the other way round, rather than an empty if block and all the code going in the else block, but I think this is more readable.
Instead of keypress, try the keydown function, it will fire before the actual browser based hook. Also, putting in a preventDefault() function will assist in this. IE :
$(document).keydown(function(e){
e.preventDefault();
alert(e.keyCode);
});
Hope this helps.
The most Simple thing you can do is add the following one line in the very first script of you page at very first line
window.history.forward(1);
Most examples seem to be for the JQuery framework - Here an example for ExtJS
(I've been getting a lot of downvotes for this recently as the question now has JQuery tag on it, which it didn't previously. I can remove the answer if you like as isn't for JQuery but it's proven to help others not using that framework).
To use this add this code block to your code base, I recommend adding it inside the applications init function().
/**
* This disables the backspace key in all browsers by listening for it on the keydown press and completely
* preventing any actions if it is not which the event fired from is one of the extjs nodes that it should affect
*/
Ext.EventManager.on(window, 'keydown', function(e, t) {
var nodeName = e.target.nodeName.toLowerCase();
if (e.getKey() == e.BACKSPACE) {
if ((nodeName === 'input' && e.target.type === 'text') ||
nodeName === 'textarea') {
// do nothing
} else {
e.preventDefault();
}
}
});
Use e.which instead of e.keyCode; jQuery normalizes this value across browsers.
http://api.jquery.com/keydown/
To determine which key was pressed,
examine the event object that is
passed to the handler function. While
browsers use differing properties to
store this information, jQuery
normalizes the .which property so you
can reliably use it to retrieve the
key code.
Then, use e.preventDefault(); to prevent the default behaviour of moving to the previous page.
<html>
<head>
<script type="text/javascript">
function stopKey(evt) {
var evt = (evt) ? evt : ((event) ? event : null);
var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
if ((evt.keyCode == 8) && (node.type!="text")) {return false;}
}
document.onkeypress = stopKey;
</script>
</head>
<body onkeydown="return stopKey()">
<form>
<input type="TEXTAREA" name="var1" >
<input type="TEXT" name="var2" >
</form>
</body>
</html
I had to add the onDownKey attribute to the body in order to get editing keys to go to the functions.
$(document).keydown(function(e) {
var elid = $(document.activeElement).is('input');
if (e.keyCode === 8 && !elid) {
return false;
}
});
Hope this might help you
Seems like the "backspace" will also act as "navigation back" if you have selected radio buttons, check-boxes and body of document as well. Really annoying for forms - especially when using post. All the form could be lost with one slip of the "backspace" key -_- ...
Honestly... who's idea was it to allow the "backspace as a navigational "back" button!!! really bad idea in my opinion.
I disable the "backspace" default on anything that is not a text area or text field - like this:
$(document).keydown(function(e){
console.log(e.keyCode+"\n");
var typeName = e.target.type;//typeName should end up being things like 'text', 'textarea', 'radio', 'undefined' etc.
console.log(typeName+"\n");
// Prevent Backspace as navigation backbutton
if(e.keyCode == 8 && typeName != "text" && typeName != "textarea"){
console.log("Prevent Backbutton as Navigation Back"+typeName+"\n");
e.preventDefault();
}
//
})
Not sure where else one would want the normal behavior of a back-button other than in these two areas.
document.onkeydown = KeyPress;
function KeyPress(e) {
if (!e.metaKey){
e.preventDefault();
}
}

Categories