ASP.NET jQuery stop event propogation and bubbling - javascript

I'm using a bit of jQuery mixed in to an ASP.NET page and it doesn't seem to do what it ought to. I'm trying to re-assign the up and down arrows and enter key for text boxes so that the user can navigate up and down through the column (like in Excel). I have the event handler set up OK and it works, but I can't get the following part to work correctly:
e.preventDefault;
e.stopPropogation;
Particularly with the enter key, it is still submitting the form even with those two lines in. The only way I can get it working is with the following:
event.cancelBubble = true;
event.returnValue = false;
But from what I've read you shouldn't use those because the two jQuery methods are browser independant. Any help understanding all of this would be great :-)
UPDATE
I've got the handler in a block like this:
//handles the up/down arrow behaviour of the score boxes
$('.gScoreTB').keydown(function (e) {
if (event.keyCode == 13) {
event.cancelBubble = true;
event.returnValue = false;
}
});
Just a simple example to try and stop the enter key behaviour at the moment: will add keyCode == 38 and 40 for the other arrows once this is nailed.

Both preventDefault and stopPropagation are functions, so you should be doing:
e.preventDefault();
e.stopPropogation();
But it's easier to just return false (which is the same as invoking both):
//handles the up/down arrow behaviour of the score boxes
$('.gScoreTB').keydown(function (e) {
if (e.keyCode == 13) {
return false;
}
});

Related

Opposite of e.prevent default?

I'm making a javascript extension for chrome. It will allow you to edit the page like a word document. Here's the code:
document.body.contentEditable = 'true';
document.designMode='on';
void 0;
document.body.onclick = function(e) {
e.preventDefault()
};
window.addEventListener("keydown", function(e) {
if (e.keyCode == 27) {
document.body.contentEditable = 'false';
document.designMode='off';
void 0;
}
});
The problem is, whenever I'm done and press esc (hence the if (keycode == 27)), sometimes the links don't work. I think that what happens is that e.preventDefault is still going. Can I have a little help?
Make sure you really need the void operator
There's no thing as an event.preventDefault "still going on". It will only be applied once for each event.
You can remove the event listener or create an if statement on your event handler to check it the event default behavior should be prevented or not.

Javascript guide - change onclick to onkeypress-- how can I use the space key for both functions. To close the nav and open

Just started learning HTML/css/javascript within the last 4 days.
I'm having an issue with my page. Right now I have the onlick function on my page on previous user button.
How can I change from onclick button to onkeypress?
Hoping the page can slide on a specific key command instead of a click.
<script>
function openNav() {
document.getElementById("users").style.width = "100%";
}
function closeNav() {
document.getElementById("users").style.width = "0%";
}
</script>
<div id="users" class="loggedusers">
×
<div class="overlay-content">
Previous logged Users
<div id="previoususer">
<span style="font-size:35px;cursor:pointer;" onclick="openNav()">⇒ Previous Users</span>
</div>
You can use the keypress event for this: https://developer.mozilla.org/en-US/docs/Web/Events/keypress
E.g:
const input = document.querySelector('input');
const log = document.getElementById('log');
input.addEventListener('keypress', logKey);
function logKey(e) {
log.textContent += ` ${e.code}`;
if(e.code == 'ArrowLeft') {
//Slide to the left
}
if(e.code == 'ArrowRight') {
//Slide to the right
}
}
With e.code you can query the pressed key. Examples:
ArrowUp
ArrowLeft
ArrowRight
ArrowDown
If you want your whole page to react on a keypress-event instead just a input field, you can use this:
document.onkeypress = keyPressFunction;
function keyPressFunction(e){
// here comes your keypress-code
var charCode = (typeof e.which == "number") ? e.which : e.keyCode
console.log(charCode);
}
Just put this snippet inside your script-tag.
Like onclick there are three kinds of keyboard events. onkeydown, onkeyup and onkeypress.
onkeydownemits when user press a button (the press only)
onkeyup emits when user release the button
onkeypress emits when user press a button
You need to use keypress event on window and call the function inside if statements when user press specific key.
function openNav() {
document.getElementById("users").style.width = "100%";
}
function closeNav() {
document.getElementById("users").style.width = "0%";
}
window.addEventListener("keydown", function(e) {
if(e.keyCode === 38) {
closeNav(); // this function will be executed when user press Arrow Up key
}else if(e.keyCode === 40) {
openNav(); // this function will be executed when user press Arrow Down key
}
});
Here, window.addEventListener execute the function which is inside of it when user presses a key.
And if statements will call the closeNav() function if Arrow Up is pressed and will call openNav() function if Arrow Down is pressed.
if other keys are pressed if statements will not run.
Keyboard Events
In javascript we have three keyboard event
keydown
keypress
keyup
triggered exactly in this order.
in my opinion the best way to work with keyboard navigation is to use the "keydown" event as in the Sandesh's example.
Handling events
To handle these events you have 3 way: (examples for "keydown")
1. in markup
<element onkeydown="myScript">
2. javascript element.onkeydown
object.onkeydown = function(){myScript};
3. javascript element.addEventListener
object.addEventListener("keydown", myScript);
Due to security issue the best way is to use the third. (you can get more information googling 'XSS' or 'cross site scripting') Infact to prevent XSS in your site you need to add some http headers that block inline scripts (CSP).
furthermore you can pass true to the third parameter of addEventListener method to capture the event before being dispatched to any EventTarget beneath it in the DOM tree and then you can stop propagation if the key code matches the reserved one. It depends on the user experience that you want to implement.
Keycodes
Try this site to get keycodes: keycode.info
in my opinion, for your case the best way is to use event.code.
Resources:
MDN - keypress
MDN - addEventListener

keydown event in drop down list

I am trying to create a Drop down list, that when a user holds the SHIFT key, it will select the same index on all other drop down lists.
Currently, I am doing the following:
$(document).on('keyup keydown', function (e) { shifted = e.shiftKey });
$(document).on('change', '.report_info select', function (e) {
if (shifted) {
//Code to change other drop down lists.
}
});
This only works if you press and hold the shift key before you enter the drop down list. If you are inside the DDL and press the shift key, the keyup/keydown event will not fire and shifted will remain false
Is there any way to catch the keyup/keydown event while a dropdownlist is focused?
Edit:
Looks like it might be an issue with Chrome only, Just tried adding the following, and it works in Firefox and IE, but not Chrome:
$(document).on('keyup keydown', 'select', function (e) {
shifted = e.shiftKey;
});
Here is a fiddle of it not working in chrome: http://jsfiddle.net/ue6xqm1q/4
I think #judgeja's response may be your best bet. I'm posting this as an "answer" instead of a comment, because I've done my own research to determine that absolutely no event gets fired when a select element is open in Chrome.
See Fiddle: http://jsfiddle.net/m4tndtu4/6/
I've attached all possible event handlers (I think) to the input element and both select elements.
In Chrome, you'll see many events fire when working with the input element, but you'll see no events fire when working in the first select element when it is open.
Interestingly, events do fire in Chrome if the select element has the multiple attribute or size>1.
In Firefox, you'll see events firing on all three elements.
Outside #judgeja's suggestion, your best bet may be to simulate the select element.
UPDATE
Warning: Chrome (mis)behavior differs on different platforms! In Chrome Windows a keydown event is triggered right after the select is released, while on OsX it is not. This explains why #judgeja solution worked for some, and didn't for me, while mine worked on OsX and not on Windows.
So I created an updated fiddle to merge my OsX solution with his Windows one.
http://jsfiddle.net/0fz5vcq6/5/
On platforms where the keydown is triggered uses #judgeja solution, if it is not triggered it tests for a keyup event without the previous keydown (my previous solution). It is ugly as it works only after RELEASE of the shift key, but ugly only on Chrome OsX.
var shifted = false;
var hackytimer = 0;
var lastval=null;
$(document).keydown(function(e){
if(e.which == 16){
if(Date.now() - hackytimer <200){
alert("you pressed shift inside the select (Win)");
changeAllSelects($(this).val());
} shifted = true;
}
});
$(document).keyup(function(e){
if(e.which == 16) {
if(!shifted && lastval!=null) {
alert("you pressed shift inside the select (OsX)");
$('.report_info select').each(function () {
changeAllSelects(lastval);
});
}
shifted = false;
}
});
$(document).on('change', '.report_info select', function (e) {
hackytimer = Date.now();
if (shifted) {
changeAllSelects($(this).val());
} else {
lastval=$(this).val();
}
});
function changeAllSelects(cr){
hackytimer = 0;
$('.report_info select').each(function () {
$(this).val(cr);
});
}
Credit goes mainly to #judgeja for his timer solution with some added workaround for the Mac (and other platforms that behave the same)
I still think emulating the selects with something HTML like http://gregfranko.com/jquery.selectBoxIt.js/ is cleaner as they should not interfere with keydown/keyups.
PREVIOUS SOLUTION (OsX only)
The only solution I could think of, in the total absence of any event, is to test if a shift up occurred without the previous shift down. This may work if you don't have other elements that behave the same way as the selects
http://jsfiddle.net/6jkkgx5e/
It is a bit tricky and dirty, will work AFTER the user releases the shift key
var shifted = false;
var lastval=null;
$(document).keydown(function(e){
if(e.which == 16){
shifted = true;
}
});
$(document).keyup(function(e){
if(e.which == 16){
if(!shifted && lastval!=null) {
alert("you pressed shift inside the select");
$('.report_info select').each(function () {
$(this).val(lastval);
});
}
shifted = false;
}
});
$(document).on('change', '.report_info select', function (e) {
var cr = $(this).val();
if (shifted) {
$('.report_info select').each(function () {
$(this).val(cr);
});
} else {
lastval=cr;
}
});
Should behave normally on non buggy browsers. Anyway I agree emulating the selects with something HTML like http://gregfranko.com/jquery.selectBoxIt.js/ might be the cleaner way.
Your syntax looks incorrect.
$("#target").keydown(function() {
alert( "Handler for .keydown() called." );
});
This is a pretty hacky solution to be honest, but it's a means to an ends until you hopefully find something better.
Since the problem is chrome doesn't register the keydown/keyup events on the select elements until after the dropdownlist has disappeared, we need to either
a) figure out how to make the event fire (I've no idea)
or
b) check if our conditions were met in a different order.
Chrome will fire the shift keypress event after click, so we can simply check if click was pressed immediately before this event. Since other browsers behave more expectedly we'll also leave the previous code in place.
To do this we set a timer on the click event, and then when the shift event for the select is fired, if the click event timer was also just set we should run our code here so that chrome will fire it. We reset the timer then so that it isn't fired multiple times.
NOTE: if you press shift immediately after setting the values (within whatever limit from the click you specify), it will also set them all. I don't think this is unreasonable as it actually feels quite natural when it happens.
I used the following code:
var shifted = false;
var hackytimer = 0;
$(document).on('keyup keydown', function (e) {
shifted = e.shiftKey;
});
$(document).on('keyup keydown', 'select', function (e) {
shifted = e.shiftKey;
if(Date.now() - hackytimer <200){
changeAllSelects($(this).val());
}
});
$(document).on('change', '.report_info select', function (e) {
hackytimer = Date.now();
if (shifted) {
changeAllSelects($(this).val());
}
});
function changeAllSelects(cr){
hackytimer = 0;
$('.report_info select').each(function () {
$(this).val(cr);
});
}
See working example here: http://jsfiddle.net/0fz5vcq6/2/
First of all. You should pick an event to register. Don't register to keyup and keydown the same time. You give the browser a hard time, because they affect your end result. To see what I mean, just edit the plunk, add a keyup event. The end result behaves a little sloppy.
keyup: Event fired when a key is released on the keyboard.
keydown: Event fired when a key is pressed on the keyboard.
keypress: Event fired when a key is pressed on the keyboard.
They have their differences, better stick to one, I prefer for this example to use keydown, just plays better with me, you can use keyup.
Edit: A quick note. The keyup for my example doesn't play well, because it seems, change in the selectedIndex, comes first and then the binded event. On keydown, first the event fires, does it's work and then the selectedIndex changes. To play with keyup, the code below needs some modification, that means the step is not needed, when you use keyup
I have a plnkr demo here.
I've tested it on IE10, Opera, Safari, Firefox and Chrome. As you might expect, webkit browsers, don't fire the keydown/keyup/keypress event when a select list has focus. Reason unknown for me, at the moment. In Firefox works great. On IE works partially. So, in order to achieve your goal, custom code to the rescue! I just binded a change event to the document, i hear for kewdown and change. If the event type is change, then the workaround comes into play. Here some code:
$(document).ready(function(){
$(document).on('keydown change', 'select', function(evt){
var shiftKey = evt.shiftKey;
var code = evt.keyCode || evt.which;
//if it's a change event and i dont have any shiftKey or code
//set the to a default value of true
if(evt.type === 'change' && !shiftKey && !code){
//special! only when change is fired
shiftKey = true;
code = true;
}
//if shift key
if(shiftKey && (code === 40 || code === 38 || code === true)){
var target = $(evt.target);
//if code is not true means it is not a change event, go ahead and set
//a step value, else no step value
var step = (code !== true) ? (code === 40) ? 1 : -1 : 0;
var index = target[0].selectedIndex + step;
//just to keep the lower and upper bound of the select list
if(index < 0){
index = 0;
}else if(index >= target[0].length){
index = target[0].length - 1;
}
//get all other select lists
var allOtherSelects = target.closest('div').siblings('div').children('select');
//foreach select list, set its selectedIndex
$.each(allOtherSelects, function(i, el){
el.selectedIndex = index;
});
}
});
});
Chrome hack: You can set custom event for document. And firing this event when press the shift key inside the DDL. Jquery firing trigger can pass custom params.
Check the working JS FIDDLER
Try the following script for your scenario
<script type="text/javascript" language="javascript">
window.shifted = false;
$(document).on('keyup keydown', function (e) { shifted = e.shiftKey; });
$(document).on('change', 'select.report_info', function (e) {
var cr = $(this).val();
if (shifted) {
$('.report_info').each(function () {
$(this).val(cr);
});
}
});
</script>
Bryan,
you can try the following way to do this. I tested on Jsfiddle it working in your way If I got your question correctly.
var shifted = false;
$(document).on('keyup keydown', function (e) { shifted = e.shiftKey; });
$("select").on('keyup keydown', function (e) {
shifted = e.shiftKey;
});
$('.report_info select').on('change', function (e) {
var cr = $(this).val();
if (shifted) {
$('.report_info select').each(function () {
$(this).val(cr);
});
}
});
Please let me know if it works for you.
Hello that was not working because of no focus on your select which has keydown bound
try this
http://jsfiddle.net/t8fsuy33/
$('select').first().focus();
Hop this thing help you out.. :)
var onkeydown = (function (ev) {
var key;
var isShift;
if (window.event) {
key = window.event.keyCode;
isShift = window.event.shiftKey ? true : false;
} else {
key = ev.which;
isShift = ev.shiftKey ? true : false;
}
if ( isShift ) {
switch (key) {
case 16: // ignore shift key
break;
default:
alert(key);
// do stuff here?
break;
}
}
});
I found a very unique solution to this issue specifically for Chrome. It appears Chrome shifts outside the normal dom for select elements when they have focus so you never get the onkey(down|press|up) events to capture the keycode. However if the size of the select box is >1 then it works. But anyone who wants an actual drop down box instead of what looks like a combo box can solve this issue with this code. In my case I was trying to prevent the backspace key from going back to the previous browser page.
Javascript looks like this:
$(document).ready(function() {
$('select').keypress(function(event)
{ return cancelBackspace(event) });
$('select').keydown(function(event)
{ return cancelBackspace(event) });
});
function cancelBackspace(event) {
if (event.keyCode == 8) {
return false;
}
}
Then HTML looks like this:
<select id="coaacct" style="border:none;width:295px;" onclick="if (this.size){this.size=''}else{this.size='20'};">
I use the onclick event to change the size of the select box to 20 if it has no size and change it back to nothing if it has a size. This way it functions like a normal select dropdown but because it has a size greater than 1 when you are selecting the option it will detect keycodes. I didn't see this answered adequately anywhere else so I thought I would share my solution.
If you need to do things with a dropdown that are this granular, it's likely not worth it to use the native <select> element as-is. In this thread alone, numerous implementation differences are discussed, and there are plenty more that are outside the scope of this discussion but will also likely affect you. There are several JS libraries that can wrap this control, leaving it as-is on mobile (where the native control is actually needed) but emulating it on desktop, where the control doesn't really do much that can't be emulated in JS.
bootstrap - doesn't automatically wrap native control for mobile
dropdown.js
dropdown.dot.js

Prevent Enter key works as mouse click

I noticed that if you focus on an element that mouse clic can be triggered, the Enter keys acts like as you left click the mouse. I want to avoid this running since it comes into conflict in other pieces of my code.
In the following example if I focus on this imageButton and I clic once, the next clicks can be "done" with the Enter key, so I don't want this because this button fires a slideToggle() and shows a hidden div, so IMO it's pointless toggle this div with the keyboard.
Is there any way to make it global way?
Thank you.
Try this:
$(".myElements").keypress(function(e) {
if (e.which == 13) {
e.preventDefault();
}
});
It will stop the enter key behaviour only, allowing the other key functions to work as usual.
Listen for "keypress" and .preventDefault()
ex. with <myelm class="nokey"/>
function noKeyPressing(){
var elms = document.getElementsByClassName('nokey'),
stop = function stop(e){ return e.preventDefault(), false; },
i = elms.length;
while(--i >= 0){
elms[i].addEventListener('keypress', stop, true);
}
}
noKeyPressing()
If you just want to prevent Enter then the keyCode to look for is 13.
try
.unbind('keydown');
to disable all key events on your element
You can return false to prevent the default action.
<input type="submit" onkeypress="return false;" value="Submit" />
An other possible way i think:
$('.elems').on('click',function(){$(this).blur()});
try this code
$('body *').keypress(function (e) {
if (e.which == 13) {
e.preventDefault();
}
});
the above code will prevent pressing enter for every element in page
,You can change the selector $('body *') to something else depending to your case

Change Enter from submission to Tab?

Users don't like the fact that the Enter key submits the page. So I am tasked with preventing the submission and changing the Enter key to a Tab to the next field.
I have tried many javascript snippets found on the net but none have worked so far. The only one that has even come close to having an effect was e.preventDefault() of the jQuery API, which stops the submit, but nothing I have tried emulates the tab behavior.
e.returnValue = false;
e.cancel = true;
Page still submits with the above in the keydown event handler. Same effect with return false in the keydown event handler. The handler is firing, tested by putting a breakpoint in it with firebug.
This needs to work with both IE and Firefox.
Don't say "don't do this".
1) I'm already convinced that I shouldn't do it, but it's not a choice that is mine, so the discussion is mute.
2) It would be an answer to the question "Should I do this?", which is not the question that I am asking.
This just feels icky, but you could use event.preventDefault as you mentioned and then call focus() on the next closest input:
Here's a simple example:
$("input").bind("keydown", function(event) {
if (event.which === 13) {
event.stopPropagation();
event.preventDefault();
$(this).next("input").focus();
}
});
Example: http://jsfiddle.net/andrewwhitaker/Txg65/
Update: If you have elements in between your inputs, using plain next() will not work. Instead, use nextAll():
$("input").bind("keydown", function(event) {
if (event.which === 13) {
event.stopPropagation();
event.preventDefault();
$(this).nextAll("input").eq(0).focus();
}
});
http://jsfiddle.net/andrewwhitaker/GRtQY/
$("input").bind("keydown", function(event) {
if (event.which === 13 && this.type !== 'submit') {
event.preventDefault();
$(this).next("input").focus();
}
});
Based on this post:
http://forum.jquery.com/topic/how-to-find-next-node-in-focus-order
I came up with this. I eventually chose not to use focasables though, and instead use input to get the effect I wanted. The .not is to prevent image buttons and submit buttons from being effected, so that they still have the default action of submit on enter whenever they have focus.
$(document).ready(function() {
var focusables = $(":input").not('[type="image"]').not('[type="submit"]');
focusables.keydown(function(e) {
if (e.keyCode == 13) {
e.preventDefault();
var current = focusables.index(this),
next = focusables.eq(current + 1).length ? focusables.eq(current + 1) : focusables.eq(0);
next.focus();
}
});
});

Categories