.focus() not working, browser keeps focusing the body - html

I am currently working on the accessibility for the React modules at our company.
Although I am just a hobby webdev I would still really like to solve this.
What's going on is:
We have a module with 6 steps, after clicking a next button it should hop to the top of the next step after being mounted, this does not seem to work in any kind of way and it keeps focusing the body.
What I've tried:
I have made use of useRef() and when I log the referred element it
works like it should, but when I use focusRef.current.focus()
nothing is happening.
In document.activeElement within the console it shows body as the active element after the new element is mounted.
NerdeFocus (a focus plugin) also shows the body as focussed
I also tried just selecting the element with document.getElementById("focusRef") with no result
The code of step 1:
export default function Step1(props) {
const focusRef = useRef();
useEffect(() => {
focusRef.current.focus();
}, []);
const {
reservationItems,
setStep,
setSelectedReservation,
step,
setAddresses,
setSelectedAddress,
} = props;
const classes = useStyles();
function onSelectReservation(reservation) {
setSelectedReservation(reservation);
setStep(2);
}
return (
<>
<Typography variant="srOnly">
Stap 2, kies waar u wilt reserveren
</Typography>
<h1 ref={focusRef} className={classes.title}>
Kies waar u wilt reserveren
</h1>
<div className={classes.addressButtons}>
{reservationItems?.map((reservation, i) => {
return (
<div
key={i}
className={classes.addressButton}
onClick={() => onSelectReservation(reservation)}
>
<span>{reservation.Description}</span>
<span>
{reservation.Street +
' ' +
reservation.Housenumber +
' ' +
reservation.City}
</span>
</div>
);
})}
</div>
<Button
className={classes.buttonPrev}
variant="contained"
startIcon={<KeyboardArrowLeftIcon />}
onClick={() => {
setStep(step - 1);
setAddresses([]);
setSelectedAddress([]);
}}
>
Terug
</Button>
</>
);
}
I hope someone can help me with this issue, thanks in advance Tom.

I can't speak to the React side but in general with single page applications (SPA) when you go to the next step, you want to move the focus to the new heading on the next step. It sounds like that's what you are attempting to do.
With non-React applications, this works fine. Perhaps there's a timing issue with React? Does the element you're trying to move the focus to exist in the DOM when you call focus()?
In some browsers, you can't move the focus to a non-interactive element unless that element has tabindex="-1". I didn't see a tabindex in your sample code so perhaps that's the issue.
For example, if I have:
<h1 id="myID">Step 2 of the process</h1>
and I try to call
document.getElementById('myID').focus();
some browsers will not move the focus to the heading. But if I change my HTML to:
<h1 id="myID" tabindex="-1">Step 2 of the process</h1>
then it works.

Related

Exclude child components from <div onclick>

I render multiple 'div' which the user can select by clicking on it with a simple onClick:
<div onClick={() => this.handleTrackerCardClick()}>
However the user can also edit a field displayed on the 'div' by clicking on a button. In this case I don't want the 'div onClick' to be called, because obviously the user wants to use the Edit function and not to select the 'div'.
See the following example:
The user can click on the green area to select the 'div'
If the pencil (in red area) is clicked, I don't want the call the 'div onClick'
Is this possible?
Thank you!
There are two approaches you can take to this.
Handle it on the div
Test to see if the click was on the edit function
(event) => {
const div = event.currentTarget;
const edit = div.querySelector('.edit');
if (edit === event.target) {
return;
}
return this.handleTrackerCardClick();
}
This code example makes assumptions about the DOM structure. Adjust as needed.
One of the assumptions is that the edit control is a single element with no element children. If it isn't, then you need to test to see if the click was any of the children too. Generally you would recursively check parentNode starting on event.target until you reached a match for div or edit.
Handle it on the edit control
Call the method that stops the event from propagating up the DOM and reaching the div.
(event) => {
event.stopPropagation();
this.do_edit_thing();
}
I would simply place the inner, editable field as a sibling to the "parent". This way you can have a click handler for the outer div and the editable field with no overlap in terms of hierarchy.
Something like this:
function App() {
return (
<div style={{ border: "1px dashed red" }}>
<div onClick={() => console.log("outer clicked")}>Outer click</div>
<span
style={{ border: "1px dashed blue" }}
onClick={() => console.log("inner clicked")}
>
Inner click
</span>
</div>
);
}
Check out a working example here

React renderDOM in multiple spots on same page?

I want react to render a DOM at multiple spots on my page. For example, if there's the class (.react-container), I want it to render the react component.
How can I do this if there are multiple spots on the page?
IMPORTANT: ArrayOne amount changes depending on where it's rendered.
APP.JS FILE
const App = () => {
return (
<div>
<div className="react-container">
{
ArrayOne.map(item=> (
<div className={
clsx({
'card': true,
'card-visible': state
})} >
<h2>{item.title}</h2>
<p>{item.text}</p>
</div>
))
}
</div>
</div>
);
};
INDEX.JS FILE
for (const el of document.querySelectorAll(".react-container")) {
ReactDOM.render(<App/>, el);
}
Code above is not running how I would like it to. It gives me two rows of only 1 card. When it should be 4 cards on row one and 1 card on row two. Console shows:
run query selector
running (4)
run query selector
running(1)
run query selector
running(1)
When I want it to do.
run query selector
running(4)
run query selector
running(1)
Interesting code. But i believe you are mixing some stuff.
get the layout working first, since seems you are not using React to do the layout.
<div>
<div className="react-container"></div>
<div className="react-container"></div>
<div className="react-container"></div>
<div className="react-container"></div>
</div>
render them into it with your lines.
for (const el of document.querySelectorAll(".react-container")) {
ReactDOM.render(<App/>, el);
}
Keep in mind, if you want to use your rest of code, you need to render it into a root, as in a typical React setup.
<div id="root"></div>
So pick one approach, either render once, but let react control everything underneath it, or render multiple times. You can't do both.

How to trigger click event on a div element and show its neighbour element JQUERY

I have a lot of divs, they are the same but the data are differen(I use variable(array of objs) and for loop) but these details aren't important
<div class="item_wrapper">
<div class="item_wrapper_info">
<div class="left-line"></div>
<div class="subject">1</div> <== click here
</div>
<div class="additional_info"> <== display this block
some text
</div>
</div>
I want to achieve this:
If I click .item_wrapper_info div then I want to show .additional_info div
It should be probably done using this keyword.
If I click . item_wrapper_info block I want to find a div with the class name of . additional_info and make display = flex but I don't know how to trigger exactly its . additional_info div.
Probably I can click on .item_wrapper_info > . subject and then show its next neighbour
SOLUTION:
$(document).ready(() => {
$(".item_wrapper").click(function(){
var index = $(".item_wrapper").index(this); get index of a certain clicked .item_wrapper element on my page
$('.additional_info').eq(index).toggle(); using .eq toggle that certain element
});
})
It works for me
I haven't tested this code. Feel free to test it in a runnable snippet.
$(document).ready(() => {
$(".item_wrapper").click(function () {
var index = $(".item_wrapper").index(this)
$('.additional_info').eq(index).css("display","flex");
});
});

How to deal with random pop up window in puppeteer js

I have a pop up window that appears on the page randomly. Usually about 20 seconds after I go on a page.
<div class="bluecoreActionScreen" id="bluecoreActionScreen">
<form novalidate="novalidate" class="bluecoreEmailCaptureForm" id="bluecoreEmailCaptureForm" name="bluecoreEmailCaptureForm">
<div class="commonScreenElement" style="width: 550px;height: 500px;display: block;background-color: #181a1cfc;">
<<<< OTHER HTML >>>>
</div>
</form>
</div>
Is the best way to deal with this just to wait for the selector to appear and then click it off?
Or would is there another way to deal with dialogues (popups).
await page.waitForSelector('.bluecoreActionScreen');
Then click it off?
You can use waitForSelector like this:
await page.waitForSelector('.bluecoreActionScreen')
and then remove the element by CSS or DOM after that:
await page.evaluate(() => {
let popupElement = document.querySelector('.bluecoreActionScreen')
// BY CSS DISPLAY NONE
popupElement.style.display = 'none'
// OR BY REMOVE THE ELEMENT DOM
popupElement.parentElement.removeChild(popupElement)
})

"document.getElementbyId" isn't working for me

I have a button in my page
<button onclick="document.getElementById('donation').style.visibility='visible'">Support</button>
That I want to have linked to making a hidden div (donation) visible. I'm not sure if the getElementById works with divs, but I couldn't find out either, because when I changed the Id to h1, with a simple color change for style, it didn't work either.
Is there a problem with my button or syntax?
You can still work this with an inline onclick.
Andrei is correct about the id needing to be an individual.
<button onclick="document.getElementById('donation').style.visibility='visible'">Support</button>
<div style="background-color: gray; width: 50px; height: 50px; visibility: hidden;" id="donation"></div>
Technically though, it's better to keep your css and javascript in the head tag or outside of the html.
In order for document.getElementById('donation') to return a DOM element this condition would need to be true
there should be one html element and only one with id="donation" in your page. For example: <div id="donation"></div>
It's possible that your function works flawlessly (you can easily tell if it is by looking at your browser console after you pushed the button) but your element would still remain not visible. For example, if its display property is set to none. There are many possible reasons why an element might not be rendered by the browser. The fastest way to pinpoint the reason would be for you to create a minimal, complete and verifiable example (using the <> button) where we could experience the issue.
For me, I think separating the codes will keep things clearer and readable.
<button id="donation_btn">Support</button>
The javascript
function enableDonation( button, donationElement ) {
// check if the button is defined
if ( button != undefined
&& button != null ) {
button.addEventListener( "click", function () {
donationElement.style.display = "block";
});
}
// execute the code on document load
window.addEventListener( "load", function () {
enableDonation(
document.getElementById( "donation_btn" ),
document.getElementById( "donation" )
);
});