How does browser/HTML decide where focus of cursor should be? - javascript

If we don't manually set any of the HTML elements to be focused using javascript, how does HTML decide which element to be focused?

It is done via tabindex attribute. By default it goes through focusable elements by position in page, but you can modify this behaviour.
From linked article:
Focusing non focusable elements:
tabindex=0
When tabindex is set to 0, the element is inserted into the tab order based on its location in the source code. If the element is focusable by default there’s no need to use tabindex at all, but if you’re repurposing an element like a span or div, then tabindex=0 is the natural way to include it in the tab order.
Ignore some focusable elements:
tabindex=-1
When tabindex is set to a negative integer like -1, it becomes programmatically focusable but it isn’t included in the tab order.
And finally: choose by yourself the order, no matter position of the element:
tabindex=1+
It imposes a tab order on the content that bears no resemblance to the expected tab order.

If you mean "What tells the browser which elements can be focused?" then you are looking for the tabindex attribute. Adding this to an element will allow an input device (i.e. mouse, keyboard) to trigger a focus state on the element.
If your question is basically, "how are things focused on?", this is done using an input device, i.e. mouse, and keyboard.

if you mean when the page loads you can use the autofocus attribute
<input type="text" autofocus>

There is actually no element that gets the focus by default.
We can check this pretty easily by creating a simple site and log
document.querySelectorAll(":focus")
to the console.
You will see that it will return an empty array, meaning that no element is focused.

Related

How to disable focus on specific html elements?

I have custom input component in vue js, and in this component i have input and two buttons.when input loose focus, i want to focus on next input, but now it focus on those buttons.
finally i should press tab key three times to focus on next input.
Is there any html attribute for disabling focus on some elements? or there is a javascript way?
The tabindex attribute controls tabbing. Set it to -1 and the tab key will not stop on that element.
<button tabindex="-1">click me</button>
You could use the blur event which is an equivalent of https://www.w3schools.com/jsref/event_onfocusout.asp
<input v-on:blur="handleBlur">
To trigger something when you lose focus.
You also could create a tabindex tabindex="0" on elements to determine the order of tabbing.
Unfortunately you can't make an element non focus-able unless you want to disable the whole element. Because then you couldn't type anything into that input.

Move to first 'default' focus of web page

Say you have website, and when you refresh it, if you check which element has focus, using this code:
setInterval(function () {
console.log('ID: ', $(document.activeElement).attr('id') + ' Tag: ' + $(document.activeElement).prop('tagName')
+ ' C: ' + $(document.activeElement).attr('class'));
}, 2000);
You will see that tag of element is 'BODY' element. How do you restore focus to the same element using javascript because, things like $('body').focus(); doesn't work.
EDIT: It should also reset the 'focus' flow of document. So after you click TAB it will focus the same element as if you would refresh page then click TAB.
EDIT 2: I need to reset focus on some action like keyDown, to default state - the state after you load page. From my research I know that element focused after you load page is 'body', and then after you click Tab, the first element in focus flow of your website is focused. I can't do that using $('body').focus(); - it doesn't focus body and doesn't reset current flow of focus of document.
EDIT 3: So far We have managed to somehow reset focus to body element of website using this code: document.activeElement.blur(); so my above script would say that body is focused, but it doesn't reset the actual flow of current focus, when you use keyboard to navigate website (TAB button). It's possible to have workaround and select specified element you want, but that's not answer to question. What is general purpose mechanism to reset flow of keyboard navigation of website to default state, without refreshing a page?
EDIT 4: https://jsfiddle.net/4qjb5asw/5/
Rather than specifically focusing the <body>, you can clear the focus of the active element by doing document.activeElement.blur(); This should restore focus to the <body> element and reset the focus flow.
Click around in the snippet below to see what the current document.activeElement is.
$("#reset").on("click", function() {
document.activeElement.blur();
logActiveElement();
});
$("form").children().on("focus", logActiveElement);
function logActiveElement() {
console.log("The active element is now: " + $(document.activeElement).prop('tagName'));
}
.blur {
padding: 5px;
border: 2px solid blue;
margin-top: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<input type="text" />
<textarea></textarea>
<button type="button">Test Button</button>
</form>
<div class="blur">
<button id="reset">RESET ACTIVE ELEMENT</button>
</div>
If you want granular control of focus, consider using the tabIndex [1] property. Basically, it allows you to specify tab order by assigning numbers to each of the elements which can have focus. An added benefit is that tabIndex enables you to specify elements to take which may not be by default--exactly what you need.
Tab order and focus is extremely important for accessibility, since User does not have a pointing device. So, this tag is designed to give you precise control of focus. It enables you to specify all focus-able elements on your page. In your case, it provides a handle to all focus-able elements, enabling you to specifically set focus where you need it, when you need it.
Not sure which framework you're using, but jQuery is a candidate for cross-browser compatibility.
From the jQuery .focus() page:
In recent browser versions, the event can be extended to include all
element types by explicitly setting the element's tabindex property. [2]
Perhaps .focus() based on tabindex; Something like this:
$('input[tabindex='+ntabindex+']').focus(); // [3]
https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex
https://api.jquery.com/focus/
https://forum.jquery.com/topic/how-to-focus-on-next-object-according-to-tab-index-not-object-order-on-page
Just be sure to check your tab order if using this feature. Tab through your page and make sure you've got all the focus-able elements properly ordered.
Sounds like you are just looking to reset the default focus for the document on certain events like keydown on a particular key so that the user can begin tabbing through the document from the top after triggering the event.
You can reset the default focus for the document with:
document.activeElement.blur()
You can add any event listener you want to trigger the function. For the keydown event on the escape key it would be:
document.addEventListener('keydown', (event) => {
if (event.key === 'Escape') {
document.activeElement.blur()
}
});
IMPORTANT: Note that if you are testing this in an embedded tool like an SO snippet or jsfiddle, you will need to add a little more code to set the focus to the element wrapper for that tool to emulate what would happen if the display area represented the entire document (otherwise, you will reset the focus to the main document and in the case of SO you will start tabbing through the menus, question, answers, comments, and other elements on the page before you get to the snippet).
Example snippet for testing that will reset the focus to the wrapper element in the snippet so that tabbing will restart from the beginning of the snippet (and not from the beginning of the document for this SO page):
/*
* All code below referencing the "snippet" variable is only
* here to help us pretend that the snippet result
* represents the entire document (not needed in a
* regular implementation).
*/
const snippet = document.querySelector('#snippet');
snippet.focus();
const btn = document.querySelector('#button1');
const resetFocus = () => {
document.activeElement.blur();
snippet.focus();
}
document.addEventListener('keydown', (event) => {
if (event.key === 'Escape') {
resetFocus();
}
});
btn.addEventListener('click', (event) => {
resetFocus();
});
<!--
The "snippet" wrapper div with tabindex attribute
is only here to help us pretend that the snippet result
represents the entire document (not needed in a regular
implementation). The tabindex helps ensure that the
wrapper div is focusable.
-->
<div id="snippet" tabindex="0">
<div>Tab to or select input to focus. To reset focus:
</div>
<ul>
<li>Press escape key.</li>
<li>Or, click "Reset" button.</li>
</ul>
<div>
<input id="input1" type="text" name="input1" />
</div>
<div>
<input id="input2" type="text" name="input2" />
</div>
<button id="button1">Reset</button>
</div>
Your question can be splitted into three parts
find the default focus element of a website.
focus on a element
control of next focus element
If you have control to the element on screen, or if it is predictable static. a simple document.querySelector("#id").focus() will focus the default element.
If it is not the case, you need some detection which could be complicated.
Browser will first find element with smallest positive non-zero [tabIndex] number.
Than if #anchor is present, it use first focusable element after it.
Otherwise first focusable element a[href],button,input,object,area[href] from body.
As you might not want to focus on the element, but want it to be focus next.
You can inject a invisible element just before it, with anoptional tabIndex hack, and focus on your invisible element.
and dismiss the injected element on blur.
I have a header div element at the top of the page. Each time new content is loaded onto the page, I want to move focus back to the header, given it is at the top of the document,
<div tabindex="-1" role="header">
I always want this to be tabbed first
</div>
The important point is setting tabindex to -1 which removes it from the default focus flow of the browser and allows me to then programmatically set focus using javascript.
document.querySelector('div[role="header"]').focus();
This snippet is ran every time new content is shown and means people using keyboards get a consistent start point for each page in a single page application.
Now when I hit the tab key, the <a> tag is always focussed first.
this will keep your specified element focused
$(document).ready(function(){
setInterval(function(){
var focusbox = document.getElementById("element_to_focus");
focusbox.focus();
});
})
The "snippet" wrapper div with a tabindex attribute
is only here to help us pretend that the snippet result represents the entire document (not needed in a regular implementation). The tab index helps ensure that the wrapper div is focusable.
Create a link with href="#" and style="display: none; position: absolute;" at the beginning of your body.
When you want to reset the focus: show the element, focus it and hide it back.

How can I determine what elements have an inactive selection in a page with multiple browsing contexts (parent, iframe, optionally more iframes)?

The document.activeElement attribute:
Returns the currently focused element, that is, the element that will get keystroke events if the user types any
This is clear for a single browsing context (single document + window). If a focusable element (input, textarea contenteditable element) has a visible selection, it will be the document.activeElement element.
When you have one or more iframes on the page and they have focusable elements, the behavior changes.
If an input in an iframe is focused, the parent document’s activeElement property will point to that iframe’s iframe element (the actual <iframe> node). However, any previously selected text in focusable elements will stay visibly selected, though it visually appears inactive (greyed-out):
If you then focus back to the input in the parent document, the iframe’s input will no longer be the iframe document’s activeElement, and it will also appear visibly selected though inactive:
How can I check for any focusable elements in a document with a visible selection, even when it isn’t the document’s activeElement?
Edit
I’ve made a demo playground to illustrate the behavior: http://codepen.io/acusti/pen/PGakzY?editors=0010
You can store the .activeElement or selection in an array; for example at an event, then select the element or selection at index array.length - 2 of the array.
See also How to clear the contents of an iFrame from another iFrame , How to pass css :active pseudo class to javascript?
#guest271314 pointed me in the right direction for solving this issue. As illustrated in this demo, using document.getSelection() allows you to find any focusable elements in a browsing context with a visible selection, even when they are “inactive” because a different browsing context (or another browser window or part of the browser) is active. The getSelection() API does require a bit of extra logic to deal with the different kind of things it can return. But for the purposes of identifying a selection with a focusable element (input, textarea), after using document.getSelection() and then checking anchorNode in the returned selection object for childNodes && childNodes.length, you can reliably get the element with the selection by accessing selection.anchorNode.childNodes[selection.anchorOffset].

jQuery or Javascript: detecting if the text caret has left an element?

Is there a way, via jQuery or regular Javascript, to detect if the user's text caret has moved out of an element (such as a td, div, span, etc.)?
The scenario is this: I have a table of textboxes which are grouped in pairs inside a span element. I am performing validation on the entries in the pair but I do not want validation errors to pop up until the user has switched to another pair of textboxes (i.e. another span).
Perhaps I'm going about this the wrong way, but in my mind I'm thinking perform validation on the pair once the user has switched out. But I need to know when the caret has moved over into another span element. I can't rely on the mouse position since a user could easily flick the mouse pointer to some other location while making entries.
you can use loses focus event
<input type="text" onblur="myFunction()">
or
$("input").focusout(function(){
//do Somthing;
});

What can affect keyboard focus html?

I am trying to put together some accessibility examples for work. One of the checkpoints I need to present is key board focus.
I know how assure controls gain keyboard focus, but I can not figure out what would cause a control to be non-focusable.
The only thing I have had success with is using an invalid index for tabIndex. (TabIndex = "-2"). I would prefer not to use this because this is not really an true example of keyboard trap.
I know how to make a field non focusable. What I am trying to find, is something that causes a field to be non focusable unintentionally.
Explicitly setting it to be outside sequential focus navigation by using a negative number (as per HTML 5)
Calling AnHTMLElementNode.blur() on the target element or an element before it
Calling AnHTMLElementNode.focus() in such a way that another element gets the focus as a reaction to something that has to be done to reach the target element in sequential navigation
Using an element that doesn't normally do something (such as a <span>) and adding an onclick event to it.
Just add disabled:
<input type='text' disabled="disabled" />

Categories