Imagine that I have many div in display: none; and just the first one is in visible.
In the view, you can navigate through each one pressing a ENTER or GO (in an iPad). So when you want to advance, change the current div to none, and the next one change it to visible. But right now I wanna also set the focus in an input element where has a focusable class. But it does not set the focus.
Here is my code:
var setFocus = function () {
$("#question-container2").find("#question:visible").find('.focusable')[0].focus();
$("#question-container2").find("#question:visible").find('.focusable')[0].setSelectionRange(0, 0);
};
var nextPage = function () {
if ($currentPage < $totalPages) {
$currentPage++;
$("#question-container2").find("#question:visible").hide().next().show();
}
};
$(".input-area").keypress(function (e) {
if (e.keyCode == 13) {
// Do something
nextPage();
setFocus();
return false;
}
});
Specify a tab index in your elements. This is a browser accessibility attribute which will tell the browser where to navigate to next when you are done with the current field.
See: http://reference.sitepoint.com/html/a/tabindex
Related
I am using following code to move to next element. Code is working fine except for the tabindex=-1. It does not skip elements with tabindex set to -1.
$('body').on('keydown', 'input, select', function(e) {
if (e.key === "Enter") {
var self = $(this), form = self.parents('form:eq(0)'), focusable, next;
focusable = form.find('input,a,select,button,textarea').filter(':visible');
next = focusable.eq(focusable.index(this)+1);
if (next.length) {
next.focus();
} else {
form.submit();
}
return false;
}
});
I have been searching for the solution but could not find one.
Can anyone please help.
You focus specificly the next element, you don't let the browser handle it. Therefor the tabindex=-1 is not working.
To use the tabindex you specified in the HTML you have to specify it in the Javascript aswell ( :not([tabindex="-1"]) ) :
focusable = form.find('input,a,select,button,textarea').filter(':not([tabindex="-1"]):visible');
I have a mobile menu that opens when the open menu button is clicked. I am trying to add a trap focus functionality to the menu when it is open so that users cannot access outside of my menu with a keyboard when tabbing.
I have used an event listener to listen for tab and shift tab keydown events in the menu. The logic is that if the active element does not have a class that only my menu items have then to lock focus back onto the close button of my menu.
Problem is that the focus gets stuck on my close button instantly and I cannot move it (even though it has the class "in-listview"). I realise that my code may not be the best way to implement this feature but for now I would just like to know why my class does not seem to be recognised and I can tidy up after. My app is built using ReactJS.
openNav = () => {
const listView = document.querySelector(".listview");
listView.classList.remove('closeMobMenu');
listView.style.visibility = "visible";
listView.classList.add('openMobMenu');
document.addEventListener('keydown', this.trapTabMobMenu)//Maybe move this to componentDidMount()?
}
trapTabMobMenu = (event) => {
if(event.keyCode === 9) { // if the tab key is pressed in the mobile menu
const closeBtn = this.closeBtn;
let activeElement = document.activeElement;
if(event.shiftKey) { // shift-tab
event.preventDefault();
//if focused element does not have class in-list-view
if(!activeElement.classList.contains("in-listview")) {
closeBtn.focus();
}
} else { // normal tab
event.preventDefault();
if(!activeElement.classList.contains("in-listview")) {
closeBtn.focus();
}
}
}
if(event.keyCode === 27) {
this.closeNav();
}
}
<button ref={(close) => { this.closeBtn = close; }} className="closebtn in-listview" onClick={closeNav} onKeyPress={handleKeyPress} tabIndex="2">×</button>
document.activeElement is not set until after the focus event has been completed, so the above code is not performing your logic on the new element that is firing the onFocus event.
You need to change document.activeElement to be event.target then perform your logic.
https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/activeElement
I have a div which contains an input element to enter some values. These values are added just above the div as a list element upon pressing enter or onFocusOut event. To this point it is fine. But if user types some value and does not press enter and directly clicks on save button, the onFocusOut function for that div should not be called. Instead it should take that typed value and call some save function. Do you have any suggestion on how to detect it?
My code snippet is here
JS:
divInput.onkeypress = function (event){
return someTestFunc();
}
divInput.tabIndex="-1";
$(divInput).focusout(function (e) {
if ($(this).find(e.relatedTarget).length == 0) {
addToList();
}
});
It is not a very delicate solution, but you could use a setTimeout before adding the item to the list and clear the setTimeout on save.button click.
Try this:
var $saveButton = $('#exampleButton')[0],
$divInput = $('#exampleInput')[0],
timedEvent = -1;
$($saveButton).on('click', function(event){
if(timedEvent) {
clearTimeout(timedEvent)
}
alert('not add to list & save');
})
$divInput.tabIndex="-1";
$($divInput).on('focusout', function(e) {
timedEvent = window.setTimeout(function() {
if ($(this).find(e.relatedTarget).length == 0) {
alert('add to list');
}
}, 200);
});
Check this working fiddle
JQUERY
$(".share-drop .dropdown-notif").keydown(function (e) {
e.preventDefault();
$(this).parents('.share').find('.share-drop .dropdown-notif').show();
if ($(this).val() == '') {
$('.share-drop .dropdown-notif').hide();
}
if (e.which == 40) {
var next = $('.selected').removeClass('selected').next('li');
next = next.length > 0 ? next : $('.focus li:eq(0)');
next.addClass('selected').children('a').focus();
} else if (e.which == 38) {
var prev = $('.selected').removeClass('selected').prev('li');
prev = prev.length > 0 ? prev : $('.focus li').last();
prev.addClass('selected').children('a').focus();
}
});
I have a drop-down option which will trigger on a keyup function of input text. I need to select those options using my up and down arrow keys I have been trying this using keydown where i couldn't able to move further. Can anyone help me with this. Thanks in advance.
Here is the DEMO
I made a couple of changes to your fiddle and it started working for the up and down key after you do some typing; eg type 'te' then press up and down:
http://jsfiddle.net/c9U3s/2/
The keydown event binding needs to be on the input element itself, and you need to allow preventDefault:
$(".input-hold input").keydown(function (e) {
//e.preventDefault();
and you need an initial selected class somewhere, for your logic to then sucessfully kick in, so I added this to the HTML:
<li class="selected"><a>testmail#test.com</a>
I think there's a couple more bug to step through, (eg what happens when you reach the end of the list with the down key?), but this will hopefully get you started.
This shows you how you can control the scrollTop of the dropdown, so you can scroll to view selected elements:
http://jsfiddle.net/c9U3s/3/
but again, some work needed to refine it to be truly nice.
I'm writing js for a status update system to be used on various pages throughout a app that I'm working. I am really just starting to get more comfortable with javascript so it has been somewhat of a challenge to get to the point where I have everything now.
The status system is basically a facebook clone. For the most part everything is supposed to function the way that facebook's status updates and status comments do. The intended behavior is that when the user clicks in the status textarea, the div under the status textarea slides out revealing the submit button as well as some other checkboxes.
If the user clicks anywhere else on the page except a link or any element that has the class prevent_slideup the div slides up hiding the submit button and any checkboxes.
I'm using a document.body click function to determine what the user clicked on so I know which form elements to hide if I should even hide them. I do not want this slideup to take place on a textarea if that textarea has focus or the user is selecting a checkbox that goes with that form. Hence the prevent_slideup class. I also do not want to bother running the slideup logic if the user has clicked on a link. I'd prefer they just leave the page without having to wait for the animation.
The code that I was using to accomplish this task can be found in the $(document.body).click(function (e) section below where I'm doing a .is('a') check on the event target.
This code works as expected in chrome and firefox, however in ie when a link is clicked for the first time it seems that the element stored in var target is actually a div instead of an anchor. What ends up happening is that the submit div slides up and the user is not taken to the link that they just clicked on. If a link is clicked a second time the user is taken to the page as you would expect.
It seems to me that there's some kind of a lag in ie as to what the current event being fired is.
The entire status module is working other than this one strange ie bug regarding the users click on the link not being carried out the first time that they click a link after opening the status textarea. Does anything jump out in this script that would explain this behavior or does anyone have any other advice?
Thanks in advance for your help.
$(document).ready(function(){
$("textarea.autoresize").autoResize();
});
$(document.body).click(function (e){
var target = e.target || e.srcElement;
console.log(target);
console.log($(target).is('a'));
if($(target).hasClass('prevent_slideup') || $(target).is('a'))
{
return true;
}
else
{
var active_element = document.activeElement;
var active_status_id = $(active_element).attr('data-status_id');
var active_has_data_status_id = (typeof active_status_id !== 'undefined' && active_status_id !== false) ? true : false;
$('textarea').each(function(){
if($(this).hasClass('status_comment_textarea'))
{
var status_id = $(this).attr('data-status_id');
if($('#comment_textarea_'+status_id).val() === '' && (!active_has_data_status_id || active_status_id !== status_id))
{
hide_status_comment_submit(status_id);
}
}
else if($(this).attr('id') === 'status_textarea')
{
if($('#status_textarea').val() === '' && $(active_element).attr('id') !== 'status_textarea')
{
$('#status_textarea').html($("#status_textarea").attr('placeholder'));
hide_status_submit();
}
}
});
return true;
}
});
$("#status_textarea").live('click', function(){
if($('#status_textarea').val() === $("#status_textarea").attr('placeholder'))
{
$('#status_textarea').html('');
}
show_status_submit();
return false;
});
$(".comment_toggle").live('click', function(){
var status_id = $(this).attr('data-status_id');
show_status_comment_submit(status_id);
return false;
});
$(".status_comment_submit").live('click', function(){
var status_id = $(this).attr('data-status_id');
$('#status_comment_submit_wrapper_'+status_id).addClass('status_comment_submit_successful');
return false;
});
$(".show_hidden_comments").live('click', function(){
var status_id = $(this).attr('data-status_id');
$('#status_hidden_comments_'+status_id).show();
$(this).hide();
return false;
});
function hide_status_submit()
{
$("#status_textarea").removeAttr('style');
$("#status_textarea").blur();
$("#status_block").removeClass('padding_b10');
$("#status_submit_wrapper").slideUp("fast");
return false;
}
function show_status_submit()
{
if ($("#status_submit_wrapper").is(":hidden"))
{
$("#status_block").addClass('padding_b10');
$("#status_submit_wrapper").slideDown('fast');
}
return false;
}
function hide_status_comment_submit(status_id)
{
if(!$('#status_comment_submit_wrapper_'+status_id).is(":hidden"))
{
$('#status_comment_submit_wrapper_'+status_id).hide();
$('#fake_comment_input_'+status_id).show();
$('#comment_textarea_'+status_id).removeAttr('style');
}
return false;
}
function show_status_comment_submit(status_id)
{
if($('#status_comment_submit_wrapper_'+status_id).is(":hidden"))
{
$('#fake_comment_input_'+status_id).hide();
$('#status_comment_submit_wrapper_'+status_id).show();
$('#comment_textarea_'+status_id).focus();
}
return false;
}
function status_comment_submit_successful()
{
hide_status_comment_submit($('.status_comment_submit_successful').attr('data-status_id'));
$('.status_comment_submit_successful').removeClass('status_comment_submit_successful');
return false;
}
I figured out that there were two main issues with my script...
1.) The document.body function and the #status_textarea live click funtioins were conflicting with each other.
2.) After adding the logic for the #status_textarea function into the document.body function I noticed that the script still didn't quite work as expected in internet explorer unless I had an alert in the function. The problem at this point was that the autoresize plugin that I'm using on the textarea was also conflicting with the document.body function.
I was able to rectify the situation by adding a dummy text input and hiding the status textarea. On click of the dummy text input the status textarea is shown and the the dummy text input is hidden. I have no idea why this worked, but it seems to have solved my problems.