I made a simple website for a project. Some of the issues are: 1.when you click on a country, the flag will show up, click again and it will keep opening the image. How do I make it show up only once? 2. Once you click a country, the information shows up but when you click another country, the previous one stays open. How do I create a reverse click so that only one shows at a time? I am unsure of what code you need to see to answer this, but I've included my JavaScript for now. Thanks for any help.
var xhttp = new XMLHttpRequest();
var respJSON = [];
xhttp.onreadystatechange = function () {
if(this.readyState == 4 && this.status == 200) {
resp = this.responseText;
respJSON = JSON.parse(resp);
html = document.getElementById("list");
html.innerHTML = "";
for(var i=0; i< respJSON.length; i ){
html.innerHTML = "<li id=" i " onClick='clickMe(" i ")'>" respJSON[i].name "</li>"
}
}
}
xhttp.open("GET", "https://restcountries.com/v2/all", true);
xhttp.send();
//create flag image on website
function clickMe(index) {
li = document.getElementById(index);
img = document.createElement("img")
img.src = respJSON[index].flag;
li.append(img);
let div = document.createElement("div1");
div.innerText = respJSON[index].subregion;
li.append(div);
}
CodePudding user response:
Sticking to your specific problem ther are number of apporaches one could adopt CSS or JS. i would stick Js approach for your code base sake.
You have done all the good expect for when you run the clickme function you need to check if any of the images had already been added to the DOM if so then remove them. It would be the first thing that needs to happen then go to adding anything new into dom
var xhttp = new XMLHttpRequest();
var respJSON = [];
xhttp.onreadystatechange = function () {
if(this.readyState == 4 && this.status == 200) {
resp = this.responseText;
respJSON = JSON.parse(resp);
html = document.getElementById("list");
html.innerHTML = "";
for(var i=0; i< respJSON.length; i ){
html.innerHTML = "<li id=" i " onClick='clickMe(" i ")'>" respJSON[i].name "</li>"
}
}
}
xhttp.open("GET", "https://restcountries.com/v2/all", true);
xhttp.send();
//create flag image on website
function clickMe(index) {
//search and remove all image tags already inserted
document.querySelectorAll('#list img').forEach(
function(item) {
item.remove();
});
//search and remove all div1 tags already inserted
document.querySelectorAll('#list div1').forEach(
function(item) {
item.remove();
});
li = document.getElementById(index);
img = document.createElement("img")
img.src = respJSON[index].flag;
li.append(img);
let div = document.createElement("div1");
div.innerText = respJSON[index].subregion;
li.append(div);
}
<ul id="list">
</ul>
CodePudding user response:
Instead, create all of content and hide whatever you want with CSS and.or JavaScript. Also, don't use on Event attribute handlers.
<li onclick="lameAttributeEventHandler()">...</li>
Details commented in the example below
const xhttp = new XMLHttpRequest();
// Define click handler
const countryList = event => {
// The <ul>
const list = event.currentTarget;
// All <li> of <ul> in an array
const items = [...list.querySelectorAll('li')];
// The actual <li> user clicked
const LI = event.target;
/* if the <tag> clicked was a <li>... */
if (LI.matches('li')) {
// ...remove '.on' class on all <li>...
items.forEach(li => li.classList.remove('on'));
// ...then add '.on' class to yje clicked <li>
LI.classList.add('on');
}
};
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
let resp = this.responseText;
let respJSON = JSON.parse(resp);
const list = document.querySelector("ul");
list.innerHTML = "";
/*
Hide content until it's needed. Create all of
HTML now.
*/
for (var i = 0; i < respJSON.length; i ) {
list.insertAdjacentHTML('beforeEnd', `
<li class='off'>
<h3>${respJSON[i].name}</h3>
<img src='${respJSON[i].flag}'>
<p>${respJSON[i].subregion}</p>
</li>`);
}
}
};
xhttp.open("GET", "https://restcountries.com/v2/all", true);
xhttp.send();
/*
Do not use onEvent attribute handlers, use onEvent property handlers or eventListeners().
Because there are an unknown number of dynamically
created <li>, it's easier to add the eventhandler on
the <ul>. Google Event Delegation
*/
document.querySelector("ul").onclick = countryList;
ul {
list-style: none;
}
li {
display: flex;
justify-content: space-between;
align-items: center;
height: 40px;
}
.off img,
.off p {
visibility: hidden
}
h3 {
pointer-events: none;
}
.on img,
.on p {
visibility: visible;
}
img {
height: 100%
}
<ul></ul>