I have created two functions. To keep it simple lets take for an example the following:
I got functions firing different events for the same objects. You can activate them using your keyboard arrows
$("body").keydown(function(e) {
if (event.which == 39) open_second_layer();
});
$("body").keydown(function(e) {
if (event.which == 37) open_first_layer();
});
As soon as I have fired one function and press the same key again it fires the animation one more time (unnecessarily).
Because of that as soon as the function open_second_layer has been fired, it should not be able to be fired again, until open_first_layer is fired again. The same should be the case the other way round.
I found .bind and .when as possible solutions, but can't figure out how to use them the right way for that case. I appreciate every suggestions or keywords to google.
You can keep a state variable and track when changes are made to it:
var state_changed = (function() {
var current = null;
return function(state) {
if (state == current) {
return false;
}
current = state;
return true;
};
}());
function open_first_layer()
{
if (!state_changed(1)) {
return;
}
// rest of code
}
function open_second_layer()
{
if (!state_changed(2)) {
return;
}
// rest of code
}
$("body").keydown(function(e) {
if (event.which == 39) {
open_second_layer();
} else if (event.which == 37) {
open_first_layer();
}
});
You can use jQuery's one().
In your first click handler, you bind the second one.
In your second click handler, you bind the first one.
sample
<div id=activate-first>first</div>
<div id=activate-second style="display:none;">second</div>
$(document).ready(function () {
function slide_first(){
$('#activate-first').show();
$('#activate-second').hide();
$('#activate-second').one('click', slide_first);
};
function slide_second(){
$('#activate-first').hide();
$('#activate-second').show();
$('#activate-first').one('click', slide_second);
};
$('#activate-first').one('click', slide_second);
$('#activate-second').one('click', slide_first);
});
Put the other function inside slide_first, like:
function slide_first(){
// other code
$('#activate_second').one('click', slide_second);
}
$('#activate_first').one('click', slide_first);
or use an Anonymous function to do the same:
$('#activate_first').one('click', function(){
// slide_first code here
$('#activate_second').one('click', function(){
// slide_second code here
});
});
Maybe your really want:
function recursiveSlider(){
$('#activate_first').one('click', function(){
// slide_first code here
$('#activate_second').one('click', function(){
// slide_second code here
recursiveSlider();
});
});
}
recursiveSlider();
This is a perfect use case for delegation. You have a single click event, and whenever the event happens, you determine what has been clicked, and you take action accordingly:
$(document.body).on("click", function(ev) {
var $targ = $(ev.target);
if ($targ.is('#button_1')) {
// someone clicked #button_1
}
if ($targ.is('.page-2 *')) {
// something inside of .page-2 was clicked!!
}
});
UPDATE: now the OP has included more code, I'm not sure the issue is - there's no need to bind and unbind events...
http://jsfiddle.net/ryanwheale/uh63rzbp/1/
function open_first_layer() {
$('#first_panel').addClass('active');
$('#second_panel').removeClass('active');
}
function open_second_layer() {
$('#first_panel').removeClass('active');
$('#second_panel').addClass('active');
}
// one event === good
$("body").keydown(function(e) {
if (event.which == 39) open_second_layer();
if (event.which == 37) open_first_layer();
});
... or if you're trying to build a slider, I suggest changing your naming convention:
http://jsfiddle.net/ryanwheale/uh63rzbp/2/
var current_layer = 1,
$all_layers = $('[id^="panel_"]'),
total_layers = $all_layers.length;
function move_layer (dir) {
current_layer += dir;
if (current_layer < 1) current_layer = total_layers;
else if (current_layer > total_layers) current_layer = 1;
$all_layers.removeClass('active');
$('#panel_' + current_layer).addClass('active');
}
// one event === good
$("body").keydown(function(e) {
if (event.which == 39) move_layer(1);
if (event.which == 37) move_layer(-1);
});
move_layer(0);
Related
As I want to unbind(off) the events I wrapped the code inside a function but as I need to see which key is pressed I need to get the event of the event(not sure how this is called.
// normal example
$('body').on('keydown',function( event ){
if(event.keyCode == 37){
// do something
}
});
// my example
function keyDownHandler() {
if(event.keyCode == 39) {
// does not work
}
}
$('body').on('keydown', keyDownHandler);
You need to get the event object, you can get it as callback function argument
function keyDownHandler(event) {
// set it here ----^^^^^^---
if(event.keyCode == 39) {
// works now
}
}
$('body').on('keydown', keyDownHandler);
$(document).ready(function () {
//1st way
$('body').on('keydown', function(event){
keyDownHandler(event);
});
//2nd way ,same as first but shorter use it for send event only
$('body').on('keydown', keyDownHandler);
//3rd way ,this way to send more data
$('body').on('keydown', {example:'hello world'},keyDownHandler2);
});
function keyDownHandler(event) {
console.log(event.keyCode);
}
function keyDownHandler2(event) {
console.log(event.keyCode);
console.log(event.data.example);
}
In a jQuery script I have a function that normally gets called in response to a click, so acts as an event handler, but I also need to call it directly. In both cases it needs some parameters.
So, the situation, simplified, is this:
function go(e) {
console.log(e.data.dir)
}
$("body").keydown(function(e) {
if (e.which == 37) { // left
go({dir: 'forward'});
} else if (e.which == 39) { // right
go({dir: 'forward'});
}
});
$('.forward').on('click', {
dir: 'forward'
}, go);
Here's a fiddle
This clearly doesn't work because when I call the function directly there's no data key.
A workaround would be to call the function like this:
go({data: {dir: 'forward'}});
And it works, but is pretty ugly.
What would it be the right approach in such a case?
In this particular case, you can solve the issue with apply() and just pass along the arguments from the event handler if the condition is truthy
function go(e) {
console.log(e.data.dir)
}
$("body").on('keydown', {dir: 'forward'}, function(e) {
if (e.which === 37 || e.which === 39) {
go.apply(this, arguments);
}
});
$('.forward').on('click', {dir: 'forward'}, go);
FIDDLE
Or you could pass in an object with the matching properties
$("body").on('keydown', {dir: 'forward'}, function(e) {
if (e.which === 37 || e.which === 39)
go({data:{dir: 'forward'}});
});
or trigger the click event with a custom event
$("body").on('keydown', {dir: 'forward'}, function(e) {
if (e.which === 37 || e.which === 39)
$('.forward').trigger('click', [{data: {dir: 'forward'}}] );
});
There are two ways I can see this going.
You could store you parameter object in a variable at the top of your script, and pass the variable to go() when you need to call it outside of a click handler. That would make things a little less ugly.
Or you could check if e is null inside go(), and if it is, use/set some generic default.
Either would be acceptable, depending on what all the method has to do.
I think I would do something like this (unless I need the event):
function go(data) {
console.log(data.dir)
}
$("body").keydown(function(e) {
if (e.which == 37) { // left
go({dir: 'forward'});
} else if (e.which == 39) { // right
go({dir: 'forward'});
}
});
$('.forward').on('click', function(){
go({dir: 'forward'});
});
I am creating an image gallary using owl carousel and php.there mouse click event working perfectly but when click command over keyboard having problem skip one image on prev keyup only and only first time. which code are calling after keyup function when write that code inside that function working perfectly
$(document.documentElement).keyup(function(event) {
// handle cursor keys
if (event.keyCode == 37) {
$(".prev").click();
});
var prevkey = $(".prev");
prevkey.unbind("click").click(function() {
$(".reset").click();
setTimeout(function() {
$(".printable").load(function(){
$(".owl-carousel").myfunction();
});
}, 200);
curEle = $(".item.active").parent();
//console.log(curEle);
if(curEle.find(".item").attr("data-id")==0)
{
$(this).addClass("disabled");
}
else
{
$(this).removeClass("disabled");
prevEle = curEle.prev();
console.log(prevEle);
prevEle.find(".item").addClass("active");
curEle.find(".item").removeClass("active");
prevEle.find(".printable").attr("src",prevEle.find(".printable").attr("data-src"));
carousel.trigger("owl.prev");
curEle.find(".printable").attr("src","");
}
});
Insert preventDefault() to avoid other events than yours...
$(document.documentElement).keyup(function(event) {
// handle cursor keys
event.preventDefault();
if (event.keyCode == 37) {
$(".prev").click();
}
});
EDIT check this answer if you're using IE8
try this using one will prevent a second call
$(".prev").one("click",function(){
//your stuff
});
I want to check the amount of typing characters in an input using keyup and keydown.
I've done it earlier but not as separate function and it was a big mess in a code. I use
event and when I did it without separate function everything worked great, but now I have a problem with send it through the functions. Maybe it's caused by totally wrong method to do this, so please give me some advice, how to do it properly.
This is my separate function:
function char_check($input_id, $div_id, $char_max, event)
{
if(($char_max-$($input_id).val().length)<=0)
{
var key = event.keyCode || event.charCode;
if(key!=8)
{
event.preventDefault();
}
}
if(($char_max-$($input_id).val().length)<0)
{
$($div_id).text("Your data will be cut short!");
}
else
{
$($div_id).text($char_max-$($input_id).val().length);
}
}
And this is the way I call this function:
$('input[name=author]').keydown(function(e){
char_check($(this), "#chars_auth", 50, e);
});
Problem: Event doesn't work.
As I understand it the code does not work, though I am not sure what does not work. Here are some suggestions. First I would create a function that builds your "check function". Something like:
var createCharCheck = function (div_id, char_max) {
return function (event) {
if ((char_max - $(this).val().length) <= 0) {
var key = event.keyCode || event.charCode;
if(key != 8) {
event.preventDefault();
}
}
if((char_max - $(this).val().length) < 0) {
$(div_id).text("Your data will be cut short!");
} else {
$(div_id).text(char_max - $(this).val().length);
}
}
}
$('input[name=author]').keydown(createCharCheck('#chars_auth', 50));
This is not to be fancy, but save you some code and take advantage of closure. Now you have a function that you can use on any input. Hope this helps.
I'm trying to use mouse events in a slideshow in Javascript. How do I use the keyup event to change the image? If I use KeyUp in the text box it's working, but when I use it on the image below it doesn't work.
<script>
var image=document.getElementById("x")
image.addEventListener("keyup",displaykey,false)
image.addEventListener("click",previous,false)
image.addEventListener("contextmenu",next,false)
var step=1;
function previous()
{
step--;
if(step==0)
{
step=3;
}
document.slide.src=eval("show"+step+".src")
}
function next(event)
{
step++;
if(step==4)
{
step=1;
}
document.slide.src=eval("show"+step+".src")
event.preventDefault()
}
function displaykey(event)
{
console.log(e.target)
var unicode=e.keyCode
event.preventDefault();
if((unicode==33)||(unicode==38))
{
previous();
}
else if((unicode==40)||(unicode==34))
{
next();
}
}
</script>
You can try to use JQuery hotkeys plugin that
lets you easily add and remove handlers for keyboard events anywhere in your code supporting almost any key combination.
Since you are wanting to change the image on a keyup event and only use javascript the following code will work :
document.onkeyup = function(e) {
var image = document.getElementById('x');
//Left Key
if (event.keyCode == 37) {
previous();
//Right Key
} else if (event.keyCode == 39) {
next();
}
}
This code will execute the onclick event of the image you have whenever the user lifts the left or right directional keys. You can change the keycodes and add more should you wish.
function displaykey(event) {
console.log(e.target)
var unicode=e.keyCode
event.preventDefault();
if((unicode==33)||(unicode==38)) {
previous();
} else if((unicode==40)||(unicode==34)) {
next();
}
}
I think the error occurs here as you passed event in argument and is then using e instead of event.