Pass focus from an iframe to next focusable element in host page
Khokon M.
Posted on March 24, 2022
This question was originally asked by GOBLiN on Stackoverflow. I quite enjoyed answering this question, so I thought why not share the process with you guys here?
Here's the main snipped from his question
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.
And Here's how I went for the solution.
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
Posted on March 24, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 26, 2024