Using one function to toggle text of two button

Hello,
I am pulling in data from a weather api, and displaying on a webpage, I have two buttons that when pressed make the text appear/disappear but I have two different functions that basically do the same thing, is it possible to do it with just one function and how do I do it ?

function weather1(){
    fetch('https://api.openweathermap.org/data/2.5/weather?lat=53.270962&lon=-9.062691&appid=')
    .then(response => response.json())
    .then(data => {
        let temp1 = document.getElementById("t")
        temp1.textContent = data.main.temp
        console.log(data.main.temp)
        //console.log(data)
    }) 
}

weather1()


function weather2(){
    fetch('https://api.openweathermap.org/data/2.5/forecast?lat=53.270962&lon=-9.062691&appid=')
    .then(response => response.json())
    .then(data => {
        //console.log(data)
        let temp2 = document.getElementById("pop")
        temp2.textContent = data.city.population
        console.log(data.city.population)
    })
} 

weather2()

function toggleText(){
    let text = document.getElementById('heading1')
    if(text.style.display === 'none'){
        text.style.display = 'block'
    }else{
        text.style.display = 'none'
    }
}

function toggleText1(){
    let text1 = document.getElementById('heading2')
    if(text1.style.display === 'none'){
        text1.style.display = 'block'
    }else{
        text1.style.display = 'none'
    }
}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="styles.css">
    <title>Document</title>
</head>
<body>
    <div id="heading1">Temp:<span id="t"></span></div>
    <div id="btn1">
        <button type="button" onclick="toggleText()">Cork</button>
    </div>
    
    <div id="heading2">Population:<span id="pop"></span></div>

    <div id="btn2">
        <button type="button" onclick="toggleText1()">Galway</button>
    </div>
   
    <script src="script.js"></script>
</body>
</html>
#heading1{
    display: none;
}

#heading2{
    display: none;
}

cheers.

The key to reusing general-purpose code is to let it operate on the current element, at call-time and not reference elements using specific ids. See the following -

function toggleText(e){
	let text = e.closest('.parent').querySelector('.heading');
    if(text.style.display === 'none'){
        text.style.display = 'block'
    }else{
        text.style.display = 'none'
    }
}
	<div class='parent'>
		<div class='heading'>Temp:<span id="t"></span></div>
		<div id="btn1">
			<button type="button" onclick="toggleText(this)">Cork</button>
		</div>
	</div>
    
	<div class='parent'>
		<div class="heading">Population:<span id="pop"></span></div>
		<div id="btn2">
			<button type="button" onclick="toggleText(this)">Galway</button>
		</div>
	</div>
.heading{
    display: none;
}
1 Like

You can, but it’s probably a slight step up in logic :slight_smile:

So there are two ways to do this. The simple parameter, or the relative lookaround.

The Simple Parameter

Rather than coding the two functions “hard”, we’re going to code them variable-based If we look at your toggleText functions, they are word-for-word identical except for the ID of the element you’re manipulating. So we’re going to use a parameter to replace that word, and the toggleText function can handle all the texts you want.

First, we need to tell the function to expect a parameter (the ID to manipulate).

function toggleText() {
becomes
function toggleText(id) {

Next, we tell the getElementById function to use that variable:
let text = document.getElementById('heading1')
=>
let text = document.getElementById(id)

And finally, we tell both of our buttons to use the same function, but pass it different ID’s…
<button type="button" onclick="toggleText()">Cork</button>
=>
<button type="button" onclick="toggleText('heading1')">Cork</button>
(and do likewise to the second button, and any subsequent buttons. They should all be calling toggleText.)

Relative Lookaround

This one’s a little more complex; instead of passing a parameter, we’ll use the relative position of the button to the header to define which div to play with. Note that this requires the format to remain the same for every instance.

Instead of looking by ID, we’re going to walk from the button to the header. We do this by means of two functions related to elements: .parent() and .previousElementSibling().

We only need to manipulate one line this time, though, the let text line.
let text = document.getElementById('heading1')
=>
let text = this.parent().previousElementSibling();
This will go from the button, “up” one level (to the btn div), and then “back” one sibling to the heading div immediately above the button div. You can then manipulate the style as before.

2 Likes

Thank you both for your in depth replies , much appreciated.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.