I am trying to add multiple event listeners to elements that are being dynamically added to a page. I have attempted to use the on() function, as instructed in many posts but none of them seem to work for. When the page is clicked, a new should be added, with formatting determined by the correct CSS class. When a particular is focused, it should be movable using WASD and the jquery animate(). Here is what I have right now:
$(document).ready( function() {
var $index = 0;
$('div').on('keydown', 'div' , function(key) {
switch(parseInt(key.which,10)) {
case 87: //W
$(this).animate({top: '-=10px'}, 'fast');
break;
case 65: //A
$(this).animate({left: '-=10px'}, 'fast');
break;
case 83: //S
$(this).animate({top: '+=10px'}, 'fast');
break;
case 68: //D
$(this).animate({left: '+=10px'}, 'fast');
break;
default:
break;
}
});
$(document).click( function() {
// if(key.which == 13)
{
var $toadd = "<div class='";
switch($index % 4)
{
case 0:
$toadd += "red' tabindex='"+ ($index + 1) + "'></div>";
$index++;
break;
case 1:
$toadd += "green' tabindex='"+ ($index + 1) + "'></div>";
$index++;
break;
case 2:
$toadd += "blue' tabindex='"+ ($index + 1) + "'></div>";
$index++;
break;
case 3:
$toadd += "yellow' tabindex='"+ ($index + 1) + "'></div>";
$index++;
break;
default:
break;
}
$('body').append($toadd);
// $('body').on('click keydown','div', function() {
// $('body').append($toadd);
// });
}
});
});
Currently, the DIVs are added by clicking the page, but cant be moved using WASD. The s are focusable for the animate function to work. If I remove the dynamically adding by clicking and place a few static s, it works great.
Thanks for anything you can offer!
You need to use on() for event delegation in your case.
$(document).on('keydown', '.red, .green, .blue, .yellow' , function(key) //Instead of document use a container that exists in DOM at any given time to have the event delegated to these divs.
With this you attach the event to document head or any container that holds these divs and which inturn will be delegated to any of these divs present now or added for the future.
Related
I need someone to head me to the right direction (I've done mostly back-end stuff and recently my JS experience has involved mostly jQuery, not too many low-level programming in JS, so I'm lacking the JS patterns on how to implement it properly).
https://jsfiddle.net/honesta/4jef9k29/6/
// Keydown
$(this).on('keydown', function(event) {
switch(event.keyCode) {
case 27: // escape
this.hide();
break;
// case 40: // keydown
//
default:
this.request();
break;
}
});
I have this custom autocomplete, trying to make the keyboard KEYUP and KEYDOWN working to navigate the list. Any idea where do I start? What would be the best approach? Or some similar example where I can base my implementation.
It will be a bit complicated because of the bootstrap :hover state on dropdown items.
$(this).on('keydown', function(event){
switch(event.keyCode) {
case 27: // escape
this.hide();
break;
case 40: //Keydown
event.preventDefault();
var active_li = $('.li_active').removeClass('li_active').next();
if(!active_li.length) active_li = $('ul.dropdown-menu li:eq(0)');
active_li.addClass('li_active').find('a').trigger('mouseenter');
break;
case 38: //Keyup
event.preventDefault();
var active_li = $('.li_active').removeClass('li_active').prev();
if(!active_li.length) active_li = $('ul.dropdown-menu li:last-child');
active_li.addClass('li_active').find('a').trigger('mouseenter');
break;
case 13:
var value = $('ul.dropdown-menu .li_active').removeClass('li_active').attr('data-value');
if (value && this.items[value]) {
this.select(this.items[value]);
this.hide();
}
break;
default:
this.request();
break;
}
});
To not interfere with the bootstrap :hover state, you will need to override CSS and add event handlers:
$(this).siblings('ul.dropdown-menu')
.on('click', 'a', $.proxy(this.click, this))
.on('mouseenter', 'a', function(){
$('.li_active').removeClass('li_active');
$(this).parent().addClass('li_active');
})
.on('mouseleave', 'a', function(){
$('.li_active').removeClass('li_active');
});
CSS:
ul.dropdown-menu li a:hover{
background : #ffffff;
}
ul.dropdown-menu .li_active, ul.dropdown-menu .li_active a:hover {
background : #f5f5f5;
}
JSFiddle demo
I found this excellent question about binding the arrow keys with jQuery: Binding arrow keys in JS/jQuery with a great solution from Sygmoral:
$(document).keydown(function(e) {
switch(e.which) {
case 37: // left
break;
case 38: // up
break;
case 39: // right
break;
case 40: // down
break;
default: return; // exit this handler for other keys
}
e.preventDefault(); // prevent the default action (scroll / move caret)
});
EXCEPT: This prevents the arrow keys from working the way they would usually work when the focus is in a text input field.
How would I modify this solution to allow the arrow keys to function normally when the current focus is in an input, text area, or another content editable area?
Put this in a condition:
$(document).keydown(function(e) {
if(!$(e.target).is(':input, [contenteditable]')){
switch(e.which){
// the cases as is
}
e.preventDefault(); // prevent the default action (scroll / move caret)
}
});
You can use event.target to get the target element of event, so you can check
var $target = $(e.target);
if($target.is("input") || $target.is("textarea")) {
//
}
Your editable element may have some common class
$('.input').keypress(function(event) {
var charCode = (evt.which) ? evt.which : event.keyCode
switch(charCode) {
case 37: // left
break;
case 38: // up
break;
case 39: // right
break;
case 40: // down
break;
default: return; // exit this handler for other keys
}
e.preventDefault();
});
I have two very similar function that are called on different events i.e. 1st on 'onmousedown' and 2nd on 'onmouseup' . I am thinking to merge them into one to improve maintainability of my code. My problem is how could I find the current event inside switch statement ?
function update_button_to_idle(id){
var img = 'images/';
switch(id){
case 'abc1':
img += 'enter1.png';
break;
case 'abc2':
case 'abc3':
img += 'play1.png';
break;
}
$('#' + id + ' img').attr('src', img);
}
function update_button_to_active(id){
var img = 'images/';
switch(id){
case 'abc1':
img += 'enter2.png';
break;
case 'abc2':
case 'abc3':
img += 'play2.png';
break;
}
$('#' + id + ' img').attr('src', img);
}
Instead of using onXXX attributes, bind your handlers using jQuery:
$("selector").on("mousedown mouseup", function(event) {
update_button(this.id, event.type);
}
Then combine your functions into one update_button() function that takes two arguments.
Depending on how the event is registered - if you pass in the event to the function you can identify it by calling the event.type. For example:
function (event) {
if (event.type == "mousedown") {
}
}
Without knowing more about how the event is triggered, its hard to give you a complete answer.
I am using reveal.js by Hakim El Hattab to make presentation slides. I have added textarea to a slide. Within the textarea I want to prevent javascript functions from being called when certain keys are pressed, and restore the default behavior of typing. For example, as you can see from the lines of code below from reveal.js, when p is pressed, a function navigatePrev() is called. I want to prevent this function from being called and simply want p to be typed in the textarea when p is pressed. How can I do this using jquery? I tried adding the following script but that does not help.
<script>
$(document).keydown(function (e) {
if ($(e.target).is('textarea')) {
e.stopPropagation();
}
})
</script>
The functions defined in the reveal.js are still called. Using return false in place of e.stopPropagation() does not help either. I am also including the above jQuery lines at the very end on my page (after reveal.js is called).
Thank you.
Relevant lines from reveal.js
function onDocumentKeyDown(event) {
// FFT: Use document.querySelector( ':focus' ) === null
// instead of checking contentEditable?
// Disregard the event if the target is editable or a
// modifier is present
if (event.target.contentEditable != 'inherit' || event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return;
var triggered = false;
switch (event.keyCode) {
// p, page up
case 80: case 33: navigatePrev(); triggered = true; break;
// n, page down
case 78: case 34: navigateNext(); triggered = true; break;
// h, left
case 72: case 37: navigateLeft(); triggered = true; break;
// l, right
case 76: case 39: navigateRight(); triggered = true; break;
// k, up
case 75: case 38: navigateUp(); triggered = true; break;
// j, down
case 74: case 40: navigateDown(); triggered = true; break;
// home
case 36: navigateTo(0); triggered = true; break;
// end
case 35: navigateTo(Number.MAX_VALUE); triggered = true; break;
// space
case 32: overviewIsActive() ? deactivateOverview() : navigateNext(); triggered = true; break;
// return
case 13: if (overviewIsActive()) { deactivateOverview(); triggered = true; } break;
}
}
The problem with your keydown event binding is that it binds to the document, which receives the event LAST (once it's too late to prevent the event from bubbling further up the DOM tree).
Instead, try binding the event directly to the textarea every time it is created:
// create text area & append to slide container
createTextAreaOnSlideContainer();
// bind an event handler to the element
$('textarea.slideTextArea').keydown( function(e) {
e.stopPropagation();
});
This will stop the event before it bubbles (propagates) up to the document that is listening for a key to be pressed
You can do this:
$(document).keydown(function(e){
if(!$('#textarea').is(':focus')){
yourfunction();
}
});
You just simply add an if statement inside and if the textarea is not focused then you call the function.
I am having problems with a jquery slideshow where I want to bind next/right to make the images jump forwards/back.
I used the following code to attempt to do it but it simply refreshes the page.
<script>
$(function() {$(document).keyup(function(e) {
switch(e.keyCode) { case 37 : window.location = $('#prev a').attr('href'); break;
case 39 : window.location = $('#next a').attr('href'); break; }});});
</script>
The I was attempting to call were:
<a href='#' id='prev' onclick='show_image($prev); return false;'>
and
<a href='#' id='next' onclick='show_image($next); return false;'>
Does anyone know an easy way to cut out the middle man and simply bind left/right to the onclick event for each?
Anyhelp would be much appreciated!
This should work:
$(function() {
$(document).keyup(function(e) {
switch (e.keyCode) {
case 37:
$('#prev a')[0].onclick();
break;
case 39:
$('#next a')[0].onclick();
break;
}
});
});
Just call the onclick event handler of the left or right button based on which key you pressed.
$(function() {
$(document).keyup(function(e) {
switch (e.keyCode) {
case 37:
$('#prev').click();
break;
case 39:
$('#next').click();
break;
}
});
});