I'm trying to simulate a keypress with the below code...
jQuery('input[name=renameCustomForm]').live('keyup', function (e) {
console.log('pressed');
});
jQuery('body').click(function (e) {
console.log(jQuery('input[name=renameCustomForm]'));
var press = jQuery.Event("keypress");
press.which = 13;
jQuery('input[name=renameCustomForm]').trigger(press);
});
I got this code from other posts on SO, but it doesn't work. Anyone know why?
Update
Fixed it... it appears triggering "keypress" doesn't automatically trigger "keyup"
Normally, when a user adds something to an inout field, the following events occur:
keydown (once).
keypress (at least once, additional events uccur while the key is pressed down)
keyup (once)
When a key event is simulated, it's not necessary that all events occur in this order. The event is manually dispatched, so the normal event chain isn't activated.
Hence, if you manually trigger the keypress event, the keyup event won't be fired.
You code will trigger a keypress each time you click anywhere on the page..
For your case it might be better to use the .blur() event of the input box..
jQuery('input[name=renameCustomForm]').live('keyup', function (e) {
console.log('pressed');
}).live('blur', function(){
var self = $(this);
console.log( self );
var press = jQuery.Event("keyup");
press.which = 13;
self.trigger( press );
});
Related
Problem
I have a .keypress() event inside of a .click() event. The first time the user clicks on the element, everything works fine, but subsequent clicks trigger the .keypress() event again without "closing" the first one. I've tried adding event.cancelBubble = true; and an empty return statement to break out of the function, but it hasn't worked because predictably, the rest of the code in that execution doesn't get executed but the event is still active and a key press could still trigger it. Is there a way to close the .keypress() event when foo gets clicked?
Code
$(foo).click(function(){
//Do stuff
$(foo).keypress(function(event) {
//Do stuff
});
});
do you mean keypress called more than once?
in your code, every time you click foo, a new anonymous function will be added to keypress event.
unbind the previous keypress event handler before binding new handler
$(foo).click(function(){
//Do stuff
$(foo).off('keypress').on('keypress', function(event) {
//Do stuff
});
});
I'm not entirely sure what you're asking but I think you want to turn off the keypress after the first click. This should toggle it though you may want to make the pressed var global; maybe.
$(foo).click(function(){
//Do stuff
var pressed = false;
$(foo).keypress(function(event) {
if(!pressed){
//Do stuff
pressed = true;
} else {
event.off();
pressed = false;
}
});
});
The key here is event.off() which will remove the listener.
Is anybody else having problems with the keyup event in iOS 9 not firing?
Just a simple test bed replicates the issue for me.
<input id="txtInput" />
Vanilla JS:
document.getElementById('txtInput').onkeyup = function () {
console.log('keyup triggered');
}
jQuery:
$('#txtInput').on('keyup', function () {
console.log('keyup triggered');
});
Neither fire...
I suggest using the keypress event on browsers with touch screens. I know that you can't really detect touch screen screens, though, so it leaves you with a few options that your situation will likely dictate.
Attach both events keyup and keypress. This would likely be dependent on how much processing is going on and if you are getting double-fires in some browsers.
Attempt to determine whether the browser is a touch screen (like using Modernizr), and then attach a fallback handler like change.
Either way, you end up with two event listeners.
$('#yourid').bind('keypress', function(e) {
// This will work
});
It's not pretty, but a work around is to bind to keydown to capture which key has been pressed, and input if you want to obtain the value, including the key typed:
(function () {
var keyCode;
$('#txtInput')
.on('keydown', function (e) {
// value not updated yet
keyCode = e.keyCode;
// Enter key does not trigger 'input' events; manually trigger it
if (e.keyCode === 13) $(this).trigger('input');
})
.on('input', function (e) {
console.log(keyCode, this.value);
});
}());
If you type 'a' the following occurs:
keydown fires.
e.keyCode is set to the ASCII value of the key pressed.
this.value is '' (i.e. the same before 'a' has been typed).
input fires.
e.keyCode is undefined.
this.value is 'a'.
You can also manually trigger an input event if the enter (13) key is pressed; input isn't fired by this key by default.
There's a site that I want to continue to hit enter on while I'm away. Is it possible to do something like
setInterval(function(){
//have javascript press the button with a certain id
},100);
I was thinking of just putting that in the smart search bar so it would run the code.
Well pressing enter is triggering an event. You would have to figure out which event listener they are listening to. I'll use keyup in the following example:
Assume el is the variable for the element you want enter to be pressed on. I'm not sure how you going to get that element but I'm sure you know.
var evt = new CustomEvent('keyup');
evt.which = 13;
evt.keyCode = 13;
el.dispatchEvent(evt); //This would trigger the event listener.
There's no way to actually simulate a hardware action. It just triggers the event listener.
For example calling el.click() is only calling the callback of the event listener, not actually pressing the key.
So you know how when you add an event listener to an element the first argument is the event object.
el.addEventListener('keyup', function(event) {
//Do Something
});
Above event is equal to evt when calling dispatchEvent on el
If the programmer used:
el.onkeyup = function(event) {
//do whatever.
}
It's surprisingly easy.
Just call el.onkeyup(evt);
Because onkeyup is a function.
Why did I use CustomEvent instead of KeyboardEvent because new KeyboardEvent('keyup') return's an object with the properties which and keyCode that can't be rewritten without the use of Object.defineProperty or Object.defineProperties
I have an input element with 2 events attached: focus and click. They both fire off the same helper function.
When I tab to the input, the focus event fires and my helper is run once. No problems there.
When the element already has focus, and I click on it again, the click event fires and my helper runs once. No problems there either.
But when the element does not have focus, and I click on it, BOTH events fire, and my helper is run TWICE. How can I keep this helper only running once?
I saw a couple similar questions on here, but didn't really follow their answers. I also discovered the .live jQuery handler, which seems like it could work if I had it watch a status class. But seems like there should be a simpler way. The .one handler would work, except I need this to work more than once.
Thanks for any help!
The best answer here would be to come up with a design that isn't trying to trigger the same action on two different events that can both occur on the same user action, but since you haven't really explained the overall problem you're coding, we can't really help you with that approach.
One approach is to keep a single event from triggering the same thing twice is to "debounce" the function call and only call the function from a given element if it hasn't been called very recently (e.g. probably from the same user event). You can do this by recording the time of the last firing for this element and only call the function if the time has been longer than some value.
Here's one way you could do that:
function debounceMyFunction() {
var now = new Date().getTime();
var prevTime = $(this).data("prevActionTime");
$(this).data("prevActionTime", now);
// only call my function if we haven't just called it (within the last second)
if (!prevTime || now - prevTime > 1000) {
callMyFunction();
}
}
$(elem).focus(debounceMyFunction).click(debounceMyFunction);
This worked for me:
http://jsfiddle.net/cjmemay/zN8Ns/1/
$('.button').on('mousedown', function(){
$(this).data("mouseDown", true);
});
$('.button').on('mouseup', function(){
$(this).removeData("mouseDown");
});
$('.button').on('focus', function(){
if (!$(this).data("mouseDown"))
$(this).trigger('click.click');
});
$(".button").on('click.click',evHandler);
Which I stole directly from this:
https://stackoverflow.com/a/9440580/264498
You could use a timeout which get's cleared and set. This would introduce a slight delay but ensures only the last event is triggered.
$(function() {
$('#field').on('click focus', function() {
debounce(function() {
// Your code goes here.
console.log('event');
});
});
});
var debounceTimeout;
function debounce(callback) {
clearTimeout(debounceTimeout);
debounceTimeout = setTimeout(callback, 500);
}
Here's the fiddle http://jsfiddle.net/APEdu/
UPDATE
To address a comment elsewhere about use of a global, you could make the doubleBounceTimeout a collection of timeouts with a key passed in the event handler. Or you could pass the same timeout to any methods handling the same event. This way you could use the same method to handle this for any number of inputs.
Live demo (click).
I'm just simply setting a flag to gate off the click when the element is clicked the first time (focus given). Then, if the element gets focus from tabbing, the flag is also removed so that the first click will work.
var $foo = $('#foo');
var flag = 0;
$foo.click(function() {
if (flag) {
flag = 0;
return false;
}
console.log('clicked');
});
$foo.focus(function() {
flag = 1;
console.log('focused');
});
$(document).keyup(function(e) {
if (e.which === 9) {
var $focused = $('input:focus');
if ($focused.is($foo)) {
flag = 0;
}
}
});
It seems to me that you don't actually need the click handler. It sounds like this event is attached to an element which when clicked gains focus and fires the focus handler. So clicking it is always going to fire your focus handler, so you only need the focus handler.
If this is not the case then unfortunately no, there is no easy way to achieve what you are asking. Adding/removing a class on focus and only firing the click when the class isn't present is about the only way I can think of.
I have it - 2 options
1 - bind the click handler to the element in the focus callback
2 - bind the focus and the click handler to a different class, and use the focus callback to add the click class and use blur to remove the click class
Thanks for the great discussion everybody. Seems like the debouncing solution from #jfriend00, and the mousedown solution from Chris Meyers, are both decent ways to handle it.
I thought some more, and also came up with this solution:
// add focus event
$myInput.focus(function() {
myHelper();
// while focus is active, add click event
setTimeout(function() {
$myInput.click(function() {
myHelper();
});
}, 500); // slight delay seems to be required
});
// when we lose focus, unbind click event
$myInput.blur(function() {
$myInput.off('click');
});
But seems like those others are slightly more elegant. I especially like Chris' because it doesn't involve dealing with the timing.
Thanks again!!
Improving on #Christopher Meyers solution.
Some intro: Before the click event fires, 2 events are preceding it, mousedown & mouseup, if the mousedown is fired, we know that probably the mouseup will fire.
Therefore we probably wouldn't like that the focus event handler would execute its action. One scenario in which the mouseup wouldn't fire is if the user starts clicking the button then drags the cursor away, for that we use the blur event.
let mousedown = false;
const onMousedown = () => {
mousedown = true;
};
const onMouseup = () => {
mousedown = false;
// perform action
};
const onFocus = () => {
if (mousedown) return;
// perform action
};
const onBlur = () => {
mousedown = false;
// perform action if wanted
};
The following events would be attached:
const events = [
{ type: 'focus', handler: onFocus },
{ type: 'blur', handler: onBlur },
{ type: 'mousedown', handler: onMousedown },
{ type: 'mouseup', handler: onMouseup }
];
I have two event handlers, one for keydown and one for keyup. The keydown event handler triggers an alert message, but this prevents the keyup event from firing.
You can see a very simple example here: http://jsfiddle.net/boblauer/jaGwT/ When the keydown opens an alert, the keyup is not fired, but when an alert is not opened, the keyup is fired. Here's the code from the jsfiddle:
var i = 0;
window.addEventListener('keydown', function(e) {
if (i++ % 2) alert('down');
console.log('down');
});
window.addEventListener('keyup', function(e) {
alert('up');
console.log('up');
});
I have a library that supports listening to multiple key combinations (such as 'd + f'), so when a key is pressed, I need to add it to a list of keys that are currently pressed, and when a key is released, I need to remove it from said list. The problem I'm running to is, if I want an alert to show when d + f are pressed at the same time, my code to remove those keys from the 'currently pressed' list never fires, because my keyup handler is never called.
I can't think of a good work around to this problem. Any ideas?
The alert prevents the event from happening. What you could do instead is trigger this function manually, because it happens anyways.
var keyupfunction = function(e){
alert('up');
console.log('up');
}
window.addEventListener('keyup', keyupfunction);
window.addEventListener('keydown', function(e) {
if (i++ % 2) alert('down');
console.log('down');
keyupfunction(e);
});
But really, you shouldn't be using alerts. It prevents these events, but who knows what else it might break. Use something custom instead.