Do something on key hold and on keyup - javascript

I need to call function:
Every second when key is hold (e.g. for five seconds of holding it should fire 5 times every second).
When user releases key (keyup) and if less then one second passed.
Events should be binded on document, not on text input.
If second statement "kinda" works, with first I have problems as keypress event isn't working on some browsers and keydown fires event all the time.
var interval;
$(document).on('keypress', function(e) {
console.log('keypress');
interval = setInterval(function() {
doSomething(e.keyCode);
}, 1000);
}).on('keyup', function(e) {
console.log('keyup');
if(interval === 0) {
doSomething(e.keyCode);
}
clearInterval(interval);
interval = 0;
});
function doSomething(keyCode) {
console.log(keyCode);
}
jsFiddle: http://jsfiddle.net/kWFUA/
Thank you for help!

I've updated the fiddle http://jsfiddle.net/kWFUA/3/
var interval;
var called = false;
$(document).on('keydown', function(e) {
if(interval == null) {
console.log('keydown');
called = false;
interval = setInterval(function() {
doSomething(e.keyCode);
called = true;
}, 1000);
}
}).on('keyup', function(e) {
console.log('keyup');
clearInterval(interval);
interval = null;
if(!called)
doSomething(e.keyCode);
});
function doSomething(keyCode) {
console.log(keyCode);
}

Related

how to prevent tab in jquery?

can we stop prevent blur or tabbing for 5 second in input field.then after 5 second user can tab from one field to another.I use off and on function but it is not working .here is my code
http://jsfiddle.net/GV3YY/99/
$("input").off("blur");
setTimeout(function(){
$("input").on("blur");
},5000)
You need to "lock" the inputs when they is focused and use setTimeout to "unlock" it after 5 seconds. A naive implementation could look something like this: https://jsfiddle.net/my7wk6gj/2/
Update: Now pseudo prevents bluring by click. The blur still happens, but focus is returned to the original input until the 5 seconds have passed. I couldn't get event.stopImmediatePropagation to work for blur, so this is the next best thing...
var lockInput = false;
var focusTarget = null;
var lockTimeout = null;
$('input').on('focus', function (e) {
if (lockTimeout) {
return;
}
lockInput = true;
lockTimeout = setTimeout(function () { lockInput = false; lockTimeout = null }, 5000)
}).on('keydown', function (e) {
if (e.keyCode === 9 && lockInput) {
e.preventDefault();
return false;
}
}).on('blur', function (e) {
console.log('blur')
if (lockInput && focusTarget === null) {
focusTarget = e.target;
setTimeout(function () {
focusTarget.focus();
focusTarget = null;
});
}
});
The global variables are used only for the example, i'd advice against that.
Also, if you have a large number of inputs, i'd suggest using event delegation, instead of adding a listener to every one of them.

Accessing window.event.altkey in a setInterval

I have the following code:
function optionkey()
{
e = window.event;
if( e.altKey )
{
return "down";
}
else
{
return "up";
}
}
interval = setInterval(function(){
if( optionkey() == "down" ) {
clearInterval(interval);
alert( 5 );
}
}, 100);
Basically the code should run alert(5) when the user presses the optionkey, but instead I get a load of errors: Uncaught TypeError: Cannot read property 'altKey' of undefined
Can anyone tell me why it does this and how to fix it?
Thanks.
jsfiddle
Please let me know if I have misinterpreted your needs, but if you want an alert to fire when pressing the key you need to create an event listener for onkeydown like so
window.onkeydown = function ( e ) {
if(e.altKey){
alert(5);
}
}
First of all event.altKey can only be detected on keypress (input) events like keydown and keyup. However calling a function from setInterval will not trigger the altkey. You will need to catch that in a event handler and pass it on.
function optionkey()
{
if( window['globalAltKey'])
{
return "down";
}
else
{
return "up";
}
}
interval = setInterval(function(){
if( optionkey() == "down" ) {
clearInterval(interval);
alert( 5 );
}
}, 100);
window.addEventListener("keydown", function(e){
if (e.altKey)
{
globalAltKey = true;
}
else
{
globalAltKey = false;
}
}, false)
Now the interval will still test if the optionkey() will return down or up. Only when the user clicks alt this will fire the alert.
I don't know why you have chosen this approach, you can simply attach a click handler to a button and use the keydown event I provided to check if the alt key is globally pressed.

How to write custom event which gets fired when user click three times

i am trying to write a custom event which should get fire when user click three times on any html node.
i know that i can create even using
var evt = document.createEvent("Event");
evt.initEvent("myEvent",true,true);
but i am not getting how i will capture that three times click event.
I will be appreciated if some one can suggest me the write approach for this.
Thanks!!!
You can create a special event
Code and example - here is your problem solvation :)
Just create a variable that stores the number of clicks.
var clickTimes = 0;
element.addEventListener('click', function(event) {
clickTimes++;
if(clickTimes==3) {
clickTimes = 0;
/* do something like dispatch my custom event */
}
});
This will count the clicks for any specific element and trigger Event on every third click.
$('selector').on('click',function(e){
Event_threshold = 500;
var clicked_times = $(this).data('Event-clicked-times');
if(clicked_times == '')
clicked_times = 0;
if(clicked_times == 0)
$(this).data('Event-first-click-timestamp',e.timeStamp);
clicked_times++;
if(e.timeStamp-$(this).data('Event-first-click-timestamp')<Event_threshold)
{
if(clicked_times == 3)
{
$(this).data('Event-clicked-times',0);
$(this).trigger('Event');
}
else
$(this).data('Event-clicked-times',clicked_times);
}
else
$(this).data('Event-clicked-times',0);
});
EDIT:
Fixed and added threshold control.
You can create iteration variable and check if element was three times clicked.
For example:
var clickTimer = 0;
document.body.addEventListener('click', function() {
clickTimer++;
if(clickTimer == 3) {
clickTimer = 0;
// fire your event
}
}, true);
To make this behavior like dbclick you can compare timestamp with first click.
For example:
var clickTimes = 0;
var fisrtClickTime = 0;
element.addEventListener('click', function(event) {
clickTimes++;
if(clickTimes == 1) {
fisrtClickTime = +new Date();
}
if(clickTimes == 3) {
clickTimes = 0;
firstClickTime = 0;
if((+new Date() - fisrtClickTime) < 1000) {
/* do something like dispatch my custom event */
}
}
});
This works without using external variables, using the HTML5 "data-" attribute for storage, so you will work on multiple elements.
$('#yourLink').click(function() {
window.setTimeout(function() {$(this).data("count",1)},300)
if(typeof $(this).data("count")=='undefined') {
$(this).data("count",1)
}
else {
var myCount = parseInt($(this).data("count"))
myCount++
if(myCount==3) {
alert("3!")
$(this).data("count",0)
}
else {
$(this).data("count",myCount)
}
}
})

having trouble with the slideUp method in jquery

I am using a show hide slider which works for the slide down but doesn't respond for the slide up, can anyone explain where Im going wrong with this:
var moreServicesList = $('#more-services-list').hide();
$('#more-services').on('click', function(e) {
var flag = 0;
if( flag === 0) {
flag = 1;
moreServicesList.slideDown('slow');
$(this).html('Hide');
} else {
moreServicesList.slideUp('slow');
$(this).html('Show');
flag = 0;
}
e.preventDefault();
});
Thanks in advance
Kyle
You have to move var flag = 0; outside of the event listener - http://jsfiddle.net/Nnhz8/
var moreServicesList = $('#more-services-list');
var flag = 0;
$('#more-services').on('click', function(e) {
if( flag == 0) {
moreServicesList.slideDown('slow');
flag = 1;
$(this).html('Hide');
} else {
moreServicesList.slideUp('slow');
$(this).html('Show');
flag = 0;
}
e.preventDefault();
});
You're resetting your flag each time the event handler is called:
$('#more-services').on('click', function(e) {
var flag = 0;
}
To fix this, move the flag declaration in front of the event handler:
var flag = 0;
$('#more-services').on('click', function(e) {}
Here's a working example: http://jsfiddle.net/wMNtT/
Because you define your flag inside the function. It resets to zero every time the function is called.
you can use the toggle method for this like
$('#more-services').on('toggle', function(e) {
$('#more-services-list').slideDown('slow');
$(this).html('Hide');
} function(){
$('#more-services-list').slideUp('slow');
$(this).html('Show');
}
});
var flag every time initializes to 0 in your case

Cycle Focus to First Form Element from Last Element & Vice Versa

I have created a form with malsup's Form Plugin wherein it submits on change of the inputs. I have set up my jQuery script to index drop down menus and visible inputs, and uses that index to determine whether keydown of tab should move focus to the next element or the first element, and likewise with shift+tab keydown. However, instead of moving focus to the first element from the last element on tab keydown like I would like it to, it moves focus to the second element. How can I change it to cycle focus to the actual first and last elements? Here is a live link to my form: http://www.presspound.org/calculator/ajax/sample.php. Thanks to anyone that tries to help. Here is my script:
$(document).ready(function() {
var options = {
target: '#c_main',
success: setFocus
};
$('#calculator').live('submit', function() {
$(this).ajaxSubmit(options);
return false;
});
$(this).focusin(function(event) {
var shiftDown = false;
$('input, select').each(function (i) {
$(this).data('initial', $(this).val());
});
$('input, select').keyup(function(event) {
if (event.keyCode==16) {
shiftDown = false;
$('#shiftCatch').val(shiftDown);
}
});
$('input, select').keydown(function(event) {
if (event.keyCode==16) {
shiftDown = true;
$('#shiftCatch').val(shiftDown);
}
if (event.keyCode==13) {
$('#captured').val(event.target.id);
} else if (event.keyCode==9 && shiftDown==false) {
return $(event.target).each(function() {
var fields = $(this).parents('form:eq(0),calculator').find('select, input:visible');
var index = fields.index(this);
var nextEl = fields.eq(index+1).attr('id');
var firstEl = fields.eq(0).attr('id');
var focusEl = '#'+firstEl;
if (index>-1 && (index+1)<fields.length) {
$('#captured').val(nextEl);
} else if(index+1>=fields.length) {
if ($(this).val() != $(this).data('initial')) {
$('#captured').val(firstEl);
} else {
event.preventDefault();
$(focusEl).focus();
}
}
return false;
});
} else if (event.keyCode==9 && shiftDown==true) {
return $(event.target).each(function() {
var fields = $(this).parents('form:eq(0),calculator').find('select, input:visible');
var index = fields.index(this);
var prevEl = fields.eq(index-1).attr('id');
var lastEl = fields.eq(fields.length-1).attr('id');
var focusEl = '#'+lastEl;
if (index<fields.length && (index-1)>-1) {
$('#captured').val(prevEl);
} else if (index==0) {
if ($(this).val() != $(this).data('initial')) {
$('#captured').val(lastEl);
} else {
event.preventDefault();
$(focusEl).select();
}
}
return false;
});
}
});
});
});
function setFocus() {
with (document.calculator)
var recap = document.getElementById(recaptured.value);
if (recap!=null) {
setTimeout(function() {
if (recap.getAttribute('type')=='text') {
recap.select();
} else {
recap.focus();
}
}, 100 );
}
}
Edit #1: I made a few minor changes to the code, which has brought me a little closer to my intended functionality of the script. However, I only made one change to the code pertaining to the focus: I tried to to disable the tab keydown when pressed on the last element (and also the shift+tab keydown on the first element) in an attempt to force the focus on the element I want without skipping over it like it has been doing. This is the code I added:
$(this).one('keydown', function (event) {
return !(event.keyCode==9 && shiftDown==true);
});
This kind of works. After the page loads, If the user presses tab on the last element without making a change to its value, the focus will be set to the second element. However, the second time the user presses tab on the last element without making a change to its value, and every subsequent time thereafter, the focus will be set to the first element, just as I would like it to.
Edit #2: I replaced the code in Edit #1, with code utilizing event.preventDefault(), which works better. While if a user does a shift+tab keydown when in the first element, the focus moves to the last element as it should. However, if the user continues to hold down the shift key and presses tab again, focus will be set back to the first element. And if the user continues to hold the shift key down still yet and hits tab, the focus will move back to the last element. The focus will shift back and forth between the first and last element until the user lifts the shift key. This problem does not occur when only pressing tab. Here is the new code snippet:
event.preventDefault();
$(focusEl).focus();
You have a lot of code I didn't get full overview over, so I don't know if I missed some functionality you wanted integrated, but for the tabbing/shift-tabbing through form elements, this should do the work:
var elements = $("#container :input:visible");
var n = elements.length;
elements
.keydown(function(event){
if (event.keyCode == 9) { //if tab
var currentIndex = elements.index(this);
var newIndex = event.shiftKey ? (currentIndex - 1) % n : (currentIndex + 1) % n;
var el = elements.eq(newIndex);
if (el.attr("type") == "text")
elements.eq(newIndex).select();
else
elements.eq(newIndex).focus();
event.preventDefault();
}
});
elements will be the jQuery object containing all the input fields, in my example it's all the input fields inside the div #container
Here's a demo: http://jsfiddle.net/rA3L9/
Here is the solution, which I couldn't have reached it without Simen's help. Thanks again, Simen.
$(document).ready(function() {
var options = {
target: '#c_main',
success: setFocus
};
$('#calculator').live('submit', function() {
$(this).ajaxSubmit(options);
return false;
});
$(this).focusin(function(event) {
$('#calculator :input:visible').each(function (i) {
$(this).data('initial', $(this).val());
});
return $(event.target).each(function() {
$('#c_main :input:visible').live(($.browser.opera ? 'keypress' : 'keydown'), function(event){
var elements = $("#calculator :input:visible");
var n = elements.length;
var currentIndex = elements.index(this);
if (event.keyCode == 13) { //if enter
var focusElement = elements.eq(currentIndex).attr('id');
$('#captured').val(focusElement);
} else if (event.keyCode == 9) { //if tab
var newIndex = event.shiftKey ? (currentIndex - 1) % n : (currentIndex + 1) % n;
var el = elements.eq(newIndex);
var focusElement = el.attr('id');
if ($(this).val() != $(this).data('initial')) {
$('#captured').val(focusElement);
} else if ((currentIndex==0 && event.shiftKey) || (currentIndex==n-1 && !event.shiftKey)) {
event.preventDefault();
if (el.attr('type')=='text') {
$.browser.msie ? "" : $(window).scrollTop(5000);
el.select().delay(800);
} else {
$.browser.msie ? "" : $(window).scrollTop(-5000);
el.focus().delay(800);
}
} else if (el.is('select')) {
event.preventDefault();
if (el.attr('type')=='text') {
el.select();
} else {
el.focus();
}
}
}
});
});
});
});
function setFocus() {
with (document.calculator)
var recap = document.getElementById(recaptured.value);
if (recap!=null) {
setTimeout(function() {
if (recap.getAttribute('type')=='text') {
recap.select();
} else {
recap.focus();
}
}, 1 );
}
}
I put my files available to download in my live link: http://www.presspound.org/calculator/ajax/sample.php

Categories

Resources