HTML onclick button takes two clicks - javascript

I saw the answers from similar questions but they did not help me
I have a button that when clicked, will change the background color of the button and hide/show some content
HTML
<button class="pro-saved-team-btn" id="{{ teams[loop.index0] | replace(' ', '') + 'button' }}"
onclick="show_team('{{ team | replace(' ', '') }}', '{{ team | replace(' ', '') + 'button' }}')">
{{ team.title() }}
</button>
JS in HTML
<script>
function show_team(team, team_btn) {
x = document.getElementById(team);
btn = document.getElementById(team_btn);
if (x.style.display === "none") {
x.style.display = "block";
btn.style.backgroundColor = '#1DA1F2';
} else {
x.style.display = "none";
btn.style.backgroundColor = '#161616';
}
}
</script>
I know the function works but I need to click on the button twice for the background color to change.
Anyone know how to fix this so it works after only one click?

The problem is that when things start up noone has set the style of property display.
Hence the first time round the test x.style.display === "none" fails.
So then the code goes to set x.style.display to 'none'.
So the next time round the test wprks.
To avoid having to set every style display to none at the start change
x.style.display === "none"
to:
x.style.display != "block"

The problem does not reproduce with the code snippet you've given:
<html>
<html>
<head>
</head>
<body>
<div id="teamId"> hee hee hee </div>
<button id="buttonId" onclick="show_team('teamId','buttonId')">
click
</button>
<script>
function show_team(team, team_btn) {
x = document.getElementById(team);
btn = document.getElementById(team_btn);
if (x.style.display === "none") {
x.style.display = "block";
btn.style.backgroundColor = '#1DA1F2';
} else {
x.style.display = "none";
btn.style.backgroundColor = '#161616';
}
}
</script>
</body>
</html>
You can do the following:
add logs (console.log('clicked')) to your function so you are sure that every click you make is received by the button - and investigate the source of interceptions if some clicks never made it to button
find whether there are some other places in your code that do something with these button and team IDs
remove class pro-saved-team-btn from the button and check whether it changes button onclick behavior

Related

How do I make an HTML element hidden by default?

I wrote a function to show my span#note- element when span#note is clicked. I want to make span#note- hidden by default, but I can't.
My code:
<h1>Republic of Labrador<br>Sub-Presidential Elections <span onclick="showOnClick()" id="note" title="Not all candidates are listed, and the vote ratioes for the listed candidates are approximated.
Hover over a candidate's name to see their vote ratio.">ⓘ</span></h1>
<br>
<span id="note-">Not all candidates are listed, and the vote ratioes for the listed candidates
are approximated.<br>Hover over a candidate's name to see their vote ratio.</span>
<script>
function showOnClick() {
var x = document.getElementById("note-");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
</script>
My attempt at hiding span#note- by default:
<span id="note-" onload="hideOnLoad()">Not all candidates are listed, and the vote ratioes for the listed candidates
are approximated.<br>Hover over a candidate's name to see their vote ratio.</span>
<script>
function hideOnLoad() {
var y = document.getElementById("note-");
y.style.display = "none";
}
function showOnClick() {
var x = document.getElementById("note-");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
</script>
I expected span#note- to be hidden by default.
I think you forgot to call your hideOnLoad() function. Either way I think you should hide the element by using CSS by using style="display: none;".
onLoad only works on external resources such as images or the tag. If you want to keep your second example, you'll have to move the onLoad="hideOnLoad()" attribute all the way up to the body tag.
The simpler solution would be to just hide it as part of the initial style of the element style="display:none; in the html. Below is your first example with the element updated.
<h1>Republic of Labrador<br>Sub-Presidential Elections <span onclick="showOnClick()" id="note" title="Not all candidates are listed, and the vote ratioes for the listed candidates are approximated.
Hover over a candidate's name to see their vote ratio.">ⓘ</span></h1>
<br>
<span id="note-" style="display: none;">Not all candidates are listed, and the vote ratioes for the listed candidates
are approximated.<br>Hover over a candidate's name to see their vote ratio.</span>
<script>
function showOnClick() {
var x = document.getElementById("note-");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
</script>
The easiest way to hide an element by default is with the CSS display property
You can simply add a CSS rule inline inside the HTML tag. Or you can follow better practice and create a separate CSS file.
1. Inline Rule:
Simply add a style attribute to your tag.
<span id="note-" style="display:none;">any content here will not be displayed on initial load</span>
2. CSS File:
Create a separate file called styles.css. In that file create a rule:
span#note- {
display: none;
}
Back in your HTML file, in between the head tags atop the file, link your stylesheet:
<head>
<link rel="stylesheet" href="styles.css">
</head>
Read more at CSS display. In addition to display, you can also try the visibility property if you want the content to take up its space on the page but just not show the content.
In your case, once you have used one of these CSS methods to hide the element, it will be hidden on initial load of the page, and then your showOnClick() script should work to toggle the display on and off.
It looks like your code is correct you just need to call each function. I'm getting it to work correctly when I run the code like this.
function hideOnLoad() {
var y = document.getElementById("note-");
y.style.display = "none";
}
function showOnClick() {
var x = document.getElementById("note-");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
showOnClick(); // Call onclick
hideOnLoad(); // Hide Span on default
Your problem is the onload trigger, it won't work on a . You need to set your code like this, after your 2 functions:
document.addEventListener('load', () => {
hideOnLoad();
})
That said, it would probably be better to set it as display: none; via CSS or style, and simply showing it when needed.

Getting a button by it's textContent, and making it hide/show certain divs onclick

I am creating some sort of filter in a webpage section.
when I click on a button, only the relatives divs should be shown.
The first script i made to make this work, was with one function for each button,
but since I'll have to add a lot more of buttons, I'd like to have only one function, and update it once added a new button.
here's a code similar to that part of the webpage.`
<!DOCTYPE html>
<html>
<head>
<title></title>
<script>
function filter1(){
var x = document.getElementsByClassName("fruit");
document.getElementById("all").onclick = function(){
x.style.display = "block"
};
document.getElementById("apples").onclick = function(){
x.style.display = "none"; document.getElementsByClassName(".apples").style.display = "block"
};
document.getElementById("lemons").onclick = function(){
x.style.display = "none"; document.getElementsByClassName(".lemons").style.display = "block"
};
}
function filter2(){
var x = document.getElementsByClassName("btn").onclick.textContent;
var y = document.getElementsByClassName("fruit");
if (x.toLowerCase().includes("all")) {
y.style.display = "block";
} else {
y.style.display = "none";
}
if (x.toLowerCase().includes("apples")) {
document.getElementsByClassName("apples").style.display = "block";
}
if (x.toLowerCase().includes("lemons")) {
document.getElementsByClassName("lemons").style.display = "block";
}
}
</script>
</head>
<body onload="filter1()">
<button id="all" class="btn">All</button>
<button id="apples"class="btn">Apples</button>
<button id="lemons"class="btn">Lemons</button>
<section>
<div class="apples fruit">Green Apple</div>
<div class="apples fruit">Red Apple</div>
<div class="lemons fruit">Yellow Lemon</div>
</section>
</body>
</html>
<style type="text/css">
.btn {
display: block
}
.fruit {
display: block
}
</style>
`As you can see I thought of two different methods for this.
the first one "filter1()" by adding an id for each button;
the second one "filter2()" by cheching the .textContent propriety of the buttons.
None of these functions work,
Can someone please tell me what's the right way to do this using Javascript,
or what's wrong with this code?
I'd like to use the "filter2()" function, but if you can fix both of them, it would be great.
I'm a complete beginner to coding.
Thank you so much.

forEach solution to replace bulk code in Javascript

I have multiple HTML elements on the same page and I only want to show a specified 3 elements at a time. Below, I have some code that I got to work. But I have 2 functions for each button and 9 buttons. So I have been trying to figure out what I can do to reduce the bulk. By my estimate it would be 1008 lines of code for this table of contents of 9 buttons.
function clickInfoCampfer() {
var x = document.getElementById("campferfullcard1");
if (x.style.display === "block") {
x.style.display = "block";
} else {
x.style.display = "block";
}
}
function clickInfoCampferClose() {
var x = document.getElementById("pinefullcard1");
if (x.style.display === "block") {
x.style.display = "none";
} else {
x.style.display = "none";
}
}
This was my best attempt using forEach. It returns an error saying "opencard.forEach is not a function." The first part of the function is working and manages to close all the elements.
const squares = document.querySelectorAll('.table-of-contents-college-all label');
const allwoodcards = document.querySelectorAll('.all-wood-cards');
squares.forEach(square => {
square.addEventListener('click', clickOutcome)
})
function clickOutcome() {
const opencards = this.getAttribute("opencard");
//opencard=".full-card-campfer"//
allwoodcards.forEach(woodcard => {
woodcard.style.display = "none"
});
opencards.forEach(openup => {
openup.style.display = "block";
});
}
Thanks for your thoughts.
Edit
HTML was requested. This HTML is supporting the forEach Java I have above. It was altered slightly from supporting the first HTML I had. There are many more div elements, I just included Pine and Campfer as the examples.
<body>
<div class="tableofcontentscollege1 table-of-contents-college-all">
<label type="button"
id="campfer-table-button"
opencard=".full-card-campfer"
>
Campfer
</label>
<label type="button"
opencard=".full-card-pine"
>
Pine
</label>
</div>
<div class="full-card-campfer all-wood-cards"
id="campferfullcard1">
</div>
<div class="full-card-campfer all-wood-cards"
id="campferfullcard2">
</div>
<div class="full-card-campfer all-wood-cards"
id="campferfullcard3">
</div>
<div class="full-card-pine all-wood-cards"
id="pinefullcard1">
<div class="full-card-pine all-wood-cards"
id="pinefullcard2">
<div class="full-card-pine all-wood-cards"
id="pinefullcard3">
</div>
</body>
The goal here is to open the 3 div elements related (in name only) to the button, while closing any other div elements amongst the wood list.
Campfer button opens the 3 divs for the campfer information
Pine button opens the 3 divs for the pine information
Walnut button opens the 3 divs for the walnut information
and so on.
Hopefully that clears up any confusion.
I'm just guessing what you want. In the future, supply more context such as the effect you intend, your HTML, etc.
You just need to put the code you had repeated in the event listener:
const squares = document.querySelectorAll('.table-of-contents-college-all label');
squares.forEach(square => {
square.addEventListener('click', handleClick)
})
function handleClick() {
if (this.style.display === "block") {
this.style.display = "none";
} else {
this.style.display = "none";
}
}

Triggering a script for multiple similar elements

So let's say I have text:
<div class="text">Here is some text.
In this text there are links here
and there are links there.
And there are probably many more!
They each open their own annotation on the side.</div>
And I have the following annotations which I want to open up:
<div class="annotation" id="an1">I'm the first annotation!</div>
<div class="annotation" id="an2">And I'm another one!</div>
And I use a script like the following:
function myAnnotation() {
var x = document.getElementById("an1");
if (x.style.display === "block") {
x.style.display = "none";
} else {
x.style.display = "block";
}
}
How can I write a script that will grab the ID of my individual links and then open the appropriate annotation?
try this one.
<div class="text">Here is some text.
In this text there are links here
and there are links there.
And there are probably many more!
They each open their own annotation on the side.</div>
<div class="annotation" id="an3" style="display:none">I'm the first annotation!</div>
<div class="annotation" id="an4" style="display:none">And I'm another one!</div>
<script>
$('.link').on('click',function(e){
var id = e.target.attributes.getNamedItem("data-target").value;
var x = document.getElementById(id);
if (x.style.display === "block") {
x.style.display = "none";
} else {
x.style.display = "block";
}
});
</script>
Working Demo
https://jsfiddle.net/0rhnkzuj/1/
function myAnnotation(argument) {
var x = document.getElementById("an" + argument);
if (x.style.display === "block") {
x.style.display = "none";
} else {
x.style.display = "block";
}
}
<div class="text">Here is some text. In this text there are links here and there are links there. And there are probably many more! They each open their own annotation on the side.</div>
<div class="annotation" onclick="myAnnotation(1)">I'm the first annotation!</div>
<div class="annotation" onclick="myAnnotation(2)">And I'm another one!</div>
Note:- You need to create a function and bind that function onClick and pass the parameter there. so you can get dynamic show hide of that function.
Hope this helps !
First: You can't use the same ID twice (or more)
If a understand your question, you want to show up a element on user action (like a click)
I recommend not toggle display.
function myAnnotation(id) {
var x = document.getElementById(id);
x.style.display = "block";
}
<div class="text">Here is some text.
In this text there are links
here
and there are links
there.
And there are probably many more!
They each open their own annotation on the side.</div>
<div class="annotation" style="display:none" id="an1">I'm the first annotation!</div>
<div class="annotation" style="display:none" id="an2">And I'm another one!</div>

Javascript code doesn't fire until the 2nd click for an html button?

I'm learning javascript, and this simple piece of code just won't work the way I need it to.
All I need is to display the main tag at the click of a button. HOWEVER, it doesn't want to display until the SECOND click.
So the first click doesn't display the main. The second click does.
I've tried moving my coding around the html document (before/after body closing tag, etc).
I've looked through stack overflow, and similar questions don't really help my case. Or at least I don't understand how they can help me as a beginner.
var aboutShow = document.getElementById("aboutLink");
aboutShow.addEventListener("click", displayMain);
function displayMain(){
var mainSection = document.getElementsByTagName("main")[0];
if (mainSection.style.display === "none"){
mainSection.style.display = "grid";
}
else{
mainSection.style.display = "none";
}
}
main{display:none;}
<main> ... </main>
<button type="button" id="aboutLink">About</button>
There has to be something I'm missing that prevents that 1st click from firing the code. I mean, it seems simple enough???
if (mainSection.style.display === "none") is looking for an inline style tag, so instead of setting display:none; in your CSS, just set it inline on the element:
var aboutShow = document.getElementById("aboutLink");
aboutShow.addEventListener("click", displayMain);
function displayMain(){
var mainSection = document.getElementsByTagName("main")[0];
if (mainSection.style.display === "none"){
mainSection.style.display = "grid";
}
else{
mainSection.style.display = "none";
}
}
<main style="display:none;"> ... </main>
<button type="button" id="aboutLink">About</button>
As has been answered, mainSection.style.display is empty. Another option is to get the computed style of the element:
var aboutShow = document.getElementById("aboutLink");
aboutShow.addEventListener("click", displayMain);
function displayMain() {
var mainSection = document.getElementsByTagName("main")[0];
if (window.getComputedStyle(mainSection).getPropertyValue('display') === "none") {
mainSection.style.display = "grid";
} else {
mainSection.style.display = "none";
}
}
main {
display: none;
}
<main> ... </main>
<button type="button" id="aboutLink">About</button>
var aboutShow = document.getElementById("aboutLink");
aboutShow.addEventListener("click", displayMain);
function displayMain(){
var mainSection = document.getElementsByTagName("main")[0];
if (mainSection.style.display || "none" === "none"){
mainSection.style.display = "grid";
}
else{
mainSection.style.display = "none";
}
}
main{display:none;}
<main>text</main>
<button type="button" id="aboutLink">About</button>
Initially mainSection.style.display is empty, so it falls on the else part of the if statement and changes the property to none.
On the second click, the property now has the value of none, that's why it works on the second click.
The HTMLElement.style property is used to get as well as set the inline style of an element.

Categories

Resources