I wanted to know which event is triggered when I go on a page and press TAB which results in going through the links.
I want to whenever someone uses the tab to go through the page <a> tags it will force the hover event on the link, or will do any other code for instance, the element is visibility:hidden but when the user is using the tab, the browser is actually going through the hidden <a> tag and therefore cause it to be visibility:visible.
To stop the browser from "tabbing" to your hidden links, you can try setting a negative tab index on the links: How to ignore HTML element from tabindex?
The "event" that occurs when a link is tabbed over is the "focus" event, styled via the pseudo-class :focus.
Related
Background
I have an iframe widget which will be embedded in other pages - I have no prior knowledge of the host page's structure and code, and the iframe will be cross-domain and likely sandboxed.
My goal is to give the iframe widget a single tab stop - after focusing on it there's a dedicated key combination to "enter" the widget, but normal tabbing should skip forward to the next focusable element in the host page.
Question: After the iframe receives focus and a new tab keypress is detected, how can I pass the focus to the host page's next focusable element?
Simple example:
<!-- host page -->
<button> first button </button>
<iframe src="myIframeWidget.com"/>
<button> second button </button>
In the above, if the first button is focused, then the expected behavior is that on first tab the iframe will receive focus, and on the next tab the second button will receive focus (skipping all focusable elements inside the iframe).
Once the iframe is focused and tab is pressed, I need to pass the focus from my iframe to the second button.
Notes
Since my iframe DOM is rather large, I don't want to set tabindex=-1 to all internal focusable elements.
At the time of writing, aria-hidden="true" does not remove an element or its descendants from the focus sequence. I'm not aware of any other aria attribute which removes an entire subtree from the focus sequence.
A pure JS solution is preferred to one relaying on external packages.
I'll also need to handle reverse-tabbing, but I assume that the same approach for forward-tabbing will apply - if there are any crucial differences, please mention them in your answer if possible.
There's an edge case where there isn't anything focusable after the widget - typically in those cases the browser will focus on the address bar buttons - if there's a way to handle that it'll be great to know, but this probably should be handled in a separate question.
Thanks!
Let's say, this is the content of the host page
<button>Main button 1</button>
<button>Main button 2</button>
<iframe id="frame1" name="frame1" src="iframe.html"></iframe>
<button>Main Button 3</button>
Now, when you receive the focus on the iframe, which is iframe.html, on the next tab press, you want to pass the focus to the Main Button 3 button. You might have a lot of focusable content on your iframe.html like,
<button>I frame button 1</button>
<button>I frame button 2</button>
that you want to skip. To do that, you can write a simple javascript inside your iframe.html Which is,
let go_next = false;
document.body.addEventListener('keyup', (e)=> {
if( e.which == 9 ) {
if(go_next){
window.parent.document.getElementById('frame1').nextElementSibling.focus()
go_next=false
}else{
go_next =true;
}
}
});
Code Explanation
We don't want the focus to immediately pass to the next element, as the user should be able to focus on the iframe as well. For that reason, the script is assuming that the user has focused on the iframe for the first time by declaring variable go_next = false
Note: Focusing from Main Button 2 to iframe is counted as a tab press inside the iframe.html. That's why we have to ignore the first tab press inside the iframe.html
So, just after the user has focused on the iframe, we're making our variable go_next = true. Now on the next tab press, we can proceed to pass the focus to the next element of the host page.
To do that, we are grabbing the host page using window.parent and selecting the iframe from the host page using document.getElementById('frame1') and the next element of the iframe using nextElementSibling and focusing the next element using the focus function. And after passing the focus, we're making the go_next = false again for the next time.
I've prepared a small demonstration for you to test here
Alternative Solution For Cross Domains
Cross domains often block access to the parent host using Content Script Policy.
To overcome this issue, we have to play a bit tricky.
We're are going to create an invisible button at the end of our iframe.html page. Eg:
<button id="last_element" style="opacity:0;filter:alpha(opacity=0);">Hello</button>
Remember we said the tab press that was used to focus the iframe can be accessed inside the iframe.html?
Well, we're going to take that advantage and focus on the last button of our iframe.html. To do that, add this script at the end of the iframe.html
document.body.addEventListener('keyup', (e)=> {
if( e.which == 9 ) {
document.querySelector("#last_element").focus()
}
});
Now, as the last element of the iframe is focused, the next focus will be always the next element of the host page.
Here's a demo on codepen
This approach of moving focus around iframe content essentially traps keyboard-only users on one side of the iframe which results in a WCAG violation (2.1.1 and 2.1.2). From an accessibility point of view, this method should be avoided.
If you want to provide users with the means to bypass an iframe, ideally you would provide "skip" links before and after the iframe that allows users to skip the iframe content. You want to "bookend" the iframe with skip links so keyboard-only users can use TAB or SHIFT-TAB navigation.
There is a much simpler solution.
Search for the last element inside the iframe, and focus it without using the prevent default.
Not using prevent default will cause it to focus on the next focusable element.
// event.preventDefault();
lastFocusableElement.focus();
I want to after pressing tab button move to certain position in my website I have event listener (keydown.Tab)="onKey($event) which should trigger function after pressing tab, but I haven't got any idea how to make same effect as clicking on href but with tab.
You should consider using Anchor links:
Button
<div id="Target"> The target element you want to jump to</div>
How to detect text change or href change of an anchor tag in js/jquery
i've tried plenty of event handlers in both jquery and vanilla js but it doesn't seem to be working for me, any simply/clever suggestions? am i missing something?
i made sure that those event handlers doesn't really support anchor tags before posting, i'm not sure what i am missing here
https://www.w3schools.com/jsref/event_onchange.asp
The text inside an anchor and its href link don't change spontaneously. There is always some javascript code that's listening to some event in order to change it. You should detect where this listener is, and to do this you can use google developer tools.
Open google chrome, go to your page and click on the top left arrow, select the element and then click on the "Event Listeners" tab. A menu with all the event listeners will appear.
Once you detected where's the function that's changing your anchor, so just append some extra code to it in order to execute actions.
I am working on a nav menu which contains some external url links, There are focus styles associated with the navigation menu , like the menu item gets a background when it is focused. If an item, that is an anchor which points to an external link, is clicked, it opens a new tab and displays the page that is represented by that external link. My problem is that, even though a new tab is opened when the user comes back to the original tab, he can still see the background behind the clicked nav menu item. There are no :active styles associated with that menuitem.
I created this example in js fiddle to enumerate the problem:
https://jsfiddle.net/bc5yu44v/2/
<body>
<a id="selectMe" href="www.google.com" target="_blank" onblur="changeText()">clcik here</a>
</body>
Here you can see that even after a new tab is opened by clicking the anchor tag , the anchor tag does not loose its :focus style, but you can see that text was changed , indicating that onblur event was fired.
can any body point me on how to remove :hover style?, is this possible by only using pseudo selector or it can only be achieved by writing js and toggling the classes?. I have a restriction of not using jquery too. I have tested it in chrome and firefox only.
This happens because navigating away from a page causes the page to lose focus, which takes the focus away from any element within the page that may have been in focus at the time, which is why the element's blur event is fired.
Once you navigate back to the page (or in this case the tab/window containing the page), focus is returned to the element that was in focus at the time, and if you had an onfocus event handler on the element, that would fire as well. The element does not lose its focus permanently between page or window focus/blur events. Similar behavior can be observed simply by switching windows, switching tabs, or opening and closing Start if you're on Windows.
You can force the element to lose its own focus by explicitly calling .blur() at the end of the event handler, but I would not do this with an onblur event handler but an onclick event handler instead, because otherwise the element would defocus itself when you switch tabs, etc.
I have notification drop down just like that of facebook. when clicked on link, this drop down is shown, which is positioned as absolute. problem is, when the drop down is opened, the page is getting scrolled to top. Unfortunately I cant paste code as its huge. can you guess what could be the problem.
Ok here is what I have. http://jsfiddle.net/testtracker/uuQf3/1/
first scroll down then click on black link, and see that, it scrolls up first then shows notification drop down.
As above said, anchor tag with # href attribute will take you to the top of page, the solution to this is
catch the onclick event and do this
$('a').click(function(e){
e.preventDefault();
//OR
return false;
});
this will restrict its default behavior.
or you can directly write it in your anchor element like this
link
Problem here is that your link is trying to find an anchor tag called #. This doesnt exist, so it scrolls to the top of the page. What you need is to tell the event handler to not do the default action of loading the href="#".
The solution is to add e.preventDefault() to your event handler.
See demo here:
http://jsfiddle.net/ksokhan/uuQf3/2/