How to capture data from div by click - javascript

I would like to capture data from selected div(ie. name of country) by click and put in span , additionaly i want to find some way to mark selected divs, but also unmark others div which were selected previously.
https://codepen.io/tatasek/pen/PoojNGL
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="style.css">
<title>Document</title>
</head>
<body>
<div class="div div__first"></div>
<div class="div div__second"></div>
<div class="div div__third"></div>
<p>I have selected:<span class="selectedCountry"></span></p>
<script src="app.js"></script>
</body>
</html>
CSS
body{
display: flex;
height: 100vh;
justify-content: center;
align-items: center;;
}
.div{
margin-left: 10px;
padding: 3px;
border: 2px solid black;
background-color: skyblue;
cursor: pointer;
}
p{
margin-left: 10px;;
}
.active{
background-color: yellow;
}
JS
const countries = ['Lithuania', 'Latvia', 'Estonia'];
const divList = document.querySelectorAll('.div');
divList.forEach(function(div, index){
div.textContent = countries[index];
})
Thanks for your time!
Michal

Building on what you've done so far, I just added some event listeners to check for changes and add the selected items to the list. Let me know if you need any further clarification.
const countries = ['Lithuania', 'Latvia', 'Estonia'];
const divList = document.querySelectorAll('.div');
divList.forEach(function(div, index){
div.textContent = countries[index];
div.addEventListener('click', function(){
divList.forEach(function(el, i) {
el.classList.remove('active')
})
this.classList.toggle('active');
})
})
var choices = document.getElementsByTagName('div')
for(var i = 0; i < choices.length; i++) {
choices[i].addEventListener('click', function() {
document.getElementsByClassName('selectedCountry')[0].innerText =
document.getElementsByClassName('active')[0].innerText;
})
}
body{
display: flex;
height: 100vh;
justify-content: center;
align-items: center;
}
.div{
margin-left: 10px;
padding: 15px;
border: 2px solid black;
background-color: skyblue;
cursor: pointer;
}
p{
margin-left: 10px;
}
.active{
background-color: yellow;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="style.css">
<title>Document</title>
</head>
<body>
<div class="div div__first"></div>
<div class="div div__second"></div>
<div class="div div__third"></div>
<p>I have selected:<span class="selectedCountry"></span></p>
<script src="app.js"></script>
</body>
</html>

Try
for (let i = 0; i < document.getElementsByClassName('div').length; i++) {
document.getElementsByClassName('div')[i].addEventListener('click', appendToSpan, false);
}
function appendToSpan(e) {
document.getElementsByClassName('selectedCountry')[0].innerText += e.target.innerText;
}
Edit:
Change to:
const countries = ['Lithuania', 'Latvia', 'Estonia'];
const divList = document.querySelectorAll('.div');
divList.forEach(function(div, index){
div.textContent = countries[index];
div.addEventListener('click', function() {
this.classList.toggle('active');
if (this.classList.contains('active')) {
document.getElementsByClassName('selectedCountry')[0].classList.add(this.innerText);
} else {
document.getElementsByClassName('selectedCountry')[0].classList.remove(this.innerText);
}
let classes = document.getElementsByClassName('selectedCountry')[0].getAttribute('class').split(' ');
document.getElementsByClassName('selectedCountry')[0].innerText = '';
for (let i = 1; i < classes.length; i++) {
document.getElementsByClassName('selectedCountry')[0].innerText += classes[i]
}
})
})

I've used addEventListener on click event on each div. Also I've created selected variable which is an array and keeps selected items. On click I check if the selected value is in selected variable by indexOf() function which returns -1 if there is not. Then I push() value to the array if it's not selected yet or delete it by splice() and index of value.
Array is printed by join() function which concats each value of array,
const divList = document.querySelectorAll('.div');
const output = document.querySelector('.selectedCountry');
const countries = ['Lithuania', 'Latvia', 'Estonia'];
let selected = [];
divList.forEach((div, index) => {
div.textContent = countries[index];
div.addEventListener('click',()=> {
var indexOfDiv = selected.indexOf(countries[index]);
(indexOfDiv >= 0)
? (selected.splice(indexOfDiv,1) && div.classList.remove('selected'))
: (selected.push(div.textContent) && div.classList.add('selected'))
output.textContent = selected.join(', ');
});
});
.div { border: 1px solid lightgray; margin: 0.5rem; padding: 0.25rem 0.4rem; }
.div.selected { border-color: lightgreen; }
<div class="div div__first"></div>
<div class="div div__second"></div>
<div class="div div__third"></div>
<p>I have selected:<span class="selectedCountry"></span></p>

const countries = ['Lithuania', 'Latvia', 'Estonia'];
const divList = document.querySelectorAll('.div');
const selectedCountry = document.getElementsByClassName('selectedCountry')[0];
function clearSelection() {
divList.forEach(function(div) {
div.classList.remove('active');
})
}
divList.forEach(function(div, index){
div.textContent = countries[index];
div.addEventListener('click', function() {
clearSelection();
this.classList.add('active');
selectedCountry.innerText = document.getElementsByClassName('active')[0].innerText;
})
})
body{
display: flex;
height: 100vh;
justify-content: center;
align-items: center;
}
.div{
margin-left: 10px;
padding: 15px;
border: 2px solid black;
background-color: skyblue;
cursor: pointer;
}
p{
margin-left: 10px;
}
.active{
background-color: yellow;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="style.css">
<title>Document</title>
</head>
<body>
<div class="div"></div>
<div class="div"></div>
<div class="div"></div>
<p>I have selected:<span class="selectedCountry"></span></p>
<script src="app.js"></script>
</body>
</html>

Related

How to use my API data I gathered through a GET request into a separate function

I am tasked with fetching data from an API and storing that data on a card for the game jeopardy I am creating. I am able to successfully fetch my data question from my api but am having a hard time of implementing it into my card. I am trying to access the variable 'res' in my addGenre() function so that I can assign the cards the questions.
const game = document.querySelector("#game");
const scoreDisplay = document.getElementById("score");
// ("https://opentdb.com/api.php?amount=10&category=11&difficulty=easy&type=boolean");
const film = 11;
const levels = ["easy", "medium", "hard"];
function addGenre() {
const column = document.createElement("div");
column.classList.add("genre-column");
column.innerText = "This is a genre";
game.append(column);
levels.forEach((lev) => {
const card = document.createElement("div");
card.classList.add("card");
column.append(card);
getEasy();
});
}
const getEasy = async function (level) {
const res = await axios.get(
`https://opentdb.com/api.php?amount=10&category=11&difficulty=${level}`
);
console.log(res);
return res;
};
addGenre();
body{
margin: 0;
padding: 0;
background-color: dodgerblue;
color: white;
font-family: Arial, Helvetica, sans-serif;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.genre-column{
display: flex;
flex-direction: column;
text-align: center;
}
.card{
width: 200px;
height: 120px;
border-radius: 20px;
background-color: blue;
text-align: center;
padding: 5px;
margin: 10px;
border: 3px solid yellow;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Jeopardy</title>
<link href="https://fonts.googleapis.com/css?family=Copse&display=swap"
rel="stylesheet">
<link rel="stylesheet" href="app.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css">
</head>
<body>
<h1>Let's Play!</h1>
<div id="game">
</div>
<h2>Score : <span id="score">0</span></h2>
<script src="https://unpkg.com/jquery"></script>
<script src="https://unpkg.com/axios/dist/axios.js"></script>
<script src="https://unpkg.com/lodash"></script>
<script src="app.js"></script>
</body>
</html>
You can invoke the getEasy method from inside the addGenre method. If you want to preserve the order you can do the following:
async function addGenre() {
// other code removed for brevity
// Make a request for every level and save it in the "requests" array
const requests = levels.map((lev) => getEasy(lev));
// Wait for all of the requests to finish. We will have a list of "responses" from the API
const responses = await Promise.all(requests);
// For each response, create a card an append it to the DOM
responses.forEach((res) => {
const card = document.createElement("div");
card.classList.add("card");
column.append(card);
// add whatever else you want to the card here
});
}
function addGenre() {
const column = document.createElement("div");
column.classList.add("genre-column");
column.innerText = "This is a genre";
game.append(column);
levels.forEach((lev) => {
const card = document.createElement("div");
card.classList.add("card");
column.append(card);
getEasy(lev).then((value) => {
card.innerText = value;
});
});
}

Is there a way to use the html written by js in addEventListener?

I added 5 buttons in js to html and I want them to be defined with a one second delay, and because of this js, when it reaches the addEventListener line, those buttons are not defined and gives an error.
HTML:
<!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="./style.css">
<title>Document</title>
</head>
<body>
<div id="btn-adder"></div>
<script src="./script.js"></script>
</body>
</html>
CSS:
*{
padding: 0;
margin: 0;
box-sizing: border-box;
font-size: 20px;
}
body{
background: rgb(61, 61, 61);
}
#btn-adder{
margin-top: 40px;
text-align: center;
}
#btn-adder button{
padding: 5px;
margin: 5px;
}
JavaScript:
const btnAdder = document.getElementById("btn-adder");
for (let i = 0; i < 5; i++) {
setTimeout(function () {
btnAdder.innerHTML += `<button id="btn${i}">Button ${i}</button>`;
}, 1000);
}
for (let i = 0; i < 5; i++) {
document.getElementById(`btn${i}`).addEventListener("click", function () {
console.log(`Button ${i} clicked`);
});
}
Is there a way to make the addEventListener recognize the new variables?
Yes it's possible and you don't even need the second loop, which is slowing down your code. (even though you probably won't notice it)
Instead of adding the HTML directly to the btn-adder, you can create a new button and directly attach the eventlistener to it.
You can create a new HTML element with document.createElement() and then add all attributes, eventlisteners and everything else you need to the button.
Finally you'll add the newly created button with appendChild() as a new child element to your btn-adder element.
const btnAdder = document.getElementById("btn-adder");
for (let i = 0; i < 5; i++) {
setTimeout(function () {
// create button
const buttonElement = document.createElement('button');
buttonElement.id = `btn${i}`;
buttonElement.textContent = `Button ${i}`
// add eventlistener to the created button
buttonElement.addEventListener("click", function () {
console.log(`Button ${i} clicked`);
});
// add button to their parent
btnAdder.appendChild(buttonElement);
}, 1000);
}
*{
padding: 0;
margin: 0;
box-sizing: border-box;
font-size: 20px;
}
body{
background: rgb(61, 61, 61);
}
#btn-adder{
margin-top: 40px;
text-align: center;
}
#btn-adder button{
padding: 5px;
margin: 5px;
}
<!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="./style.css">
<title>Document</title>
</head>
<body>
<div id="btn-adder"></div>
<script src="./script.js"></script>
</body>
</html>
An approach close to what billyonecan mentioned but with use of appendChild instead of innerHTML which can lead to unwanted behaviour.
<!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="./style.css">
<style>
*{
padding: 0;
margin: 0;
box-sizing: border-box;
font-size: 20px;
}
body{
background: rgb(61, 61, 61);
}
#btn-adder{
margin-top: 40px;
text-align: center;
}
#btn-adder button{
padding: 5px;
margin: 5px;
}
</style>
<title>Document</title>
</head>
<body>
<div id="btn-adder"></div>
<script>
const btnAdder = document.getElementById("btn-adder");
for (let i = 0; i < 5; i++) {
setTimeout(function () {
let b = document.createElement('button');
b.id = "btn" + i;
b.textContent = "Button " + i;
btnAdder.appendChild(b);
document.getElementById("btn"+i).addEventListener("click", function () {
console.log(`Button ${i} clicked`);
});
},1000 );
}
</script>
</body>
</html>

Why the div element is not appearing Infront of the current div but its only visible at the static div?

The problem is when I click the Option (button) that appears on every div after I fetch the data using the While loop it only appears the top div but not the current div that I am viewing. This is the picture when I click the Option it only appears the one place:
<?php
$connect = mysqli_connect('localhost','root','','users_data_allocation');
$feeder = "SELECT * FROM `trade_feed_post`";
$runfeed = mysqli_query($connect,$feeder);
while ($showfeed = mysqli_fetch_assoc($runfeed)) {
# code...
$feedAcc = $showfeed['OwnerACC'];
$feedDate = $showfeed['Date and time'];
$feedQuote = $showfeed['quote'];
$feedBuys = $showfeed['No.of buys'];
echo "
<div class=\"border\">
<p>".$feedAcc."</p>
<button onclick=\"showOpt()\">Option</button>
<div class=\"menu\">
This is menu.
</div>
</div>
";
}
?>
<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">
<title>ShowData</title>
<style>
.border{
background-color: black;
color: white;
border: 2px solid red;
height: 220px;
width: 400px;
font-family: ebrima;
font-size: 25px;
padding-left: 10px;
}
.menu{
display: none;
}
</style>
<script>
function showOpt() {
document.querySelector('.menu').style.display = 'block';
}
</script>
</head>
<body>
</body>
</html>
I would add this element parameter to <button onclick=\"showOpt(this)\">Option</button>.
Then change function so that will find correct .menu for button (using common parent .border)
function showOpt(elem) {
elem.closest(".border").querySelector(".menu").style.display = 'block';
}

How can I rotate only single target element jQuery?

I'm try to rotate an element but when choosing another element it's all rotate at the same time.
So I need to know how to rotate an element and it would be nice if you guys have a similar system. Because I want to learn more about this kind of system. Which is very necessary and important to me to study and work.
$(document).ready(function() {
var container = document.querySelector(".container");
var rotate = document.createElement("div");
rotate.className = "rotate";
//create Element
$("#add").click(function() {
container.appendChild(addElement());
addEvent();
});
const addElement = () => {
var element = document.createElement("div");
element.className = "resizable";
return element;
}
//add event
function addEvent() {
$(".resizable").click(function(e) {
if (e.currentTarget === this) {
$(this).append(rotate);
$(this).resizable({
handles: 'ne, se, sw, nw'
});
$(this).draggable().rotatable({
handle: $('.rotate')
});
}
});
}
});
.resizable {
width: 100px;
height: 100px;
border: 1px solid #000;
position: relative;
user-select: none;
z-index: 0;
}
.rotate {
width: 10px;
height: 10px;
border: 1px solid #000;
border-radius: 50%;
position: absolute;
top: -30px;
left: calc(50% - 5px);
cursor: move;
}
<!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">
<title>jquery</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="//code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/jquery.ui.rotatable/1.0.1/jquery.ui.rotatable.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<button class="add" id="add">add</button> //for add element
<button class="save" id="save">save</button> //for save size and position
<div class="container"></div>
</body>
</html>
Thanks everyone in advance for helping me.

JS Script position in HTML

I'm trying to create a simple app with HTMl, CSS and vanilla JS.
I've got an array, and ant to display its items in a box, with a button below it that gets the average of the array, which should also appear below the button.
So far, the layout has been very difficult, as I'm familiar with core JS and basic HTML, but never worked with scripts before. I can't make the button to be displayed below the array items and in the centre, no matter what I do. For it to appear after the array, I've applied flex box to the body, because I don't know how to create a wrapping html element, although I've seen some threads, don't know how to implement it.
Is there an easy way (avoiding JQuery) of doing this? Can't I just create a wrapping the script?
This is my code so far:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="style.css">
<title>Test</title>
</head>
<body onload="mapping()">
<script>
const array = [2, 3, 4, 5];
function mapping() {
array.map(arrayItem => {
let elements = document.createElement('p');
elements.innerHTML = arrayItem;
document.body.appendChild(elements);
elements.classList.add("numbers");
});
}
</script>
<div class='container'>
<div class='button'>
<p>
<button onClick="average()">Average</button>
</p>
</div>
<div id='val'></div>
</div>
<script>
function average() {
const array = [2, 3, 4, 5]
let count = 0
let val = array.reduce((x, y) => {
if (+y) {
count++
x += +y
}
return x
}, 0)
val = val / count;
document.getElementById('val').innerHTML += val + '<br/>';
}
</script>
</body>
</html>
body {
display: flex;
flex-direction: row-reverse;
justify-content: space-around;
align-items: center;
/* flex-wrap: wrap; */
}
.numbers {
font-size: 5em;
/* color: blue; */
/* text-orientation: unset; */
margin-top: 2em;
}
.button {
padding: 1em;
border: .2em solid red;
margin-top: 20em;
position: inherit;
}
Sorry I'm very junior and can't figure out how to do it.
I'm struggling to fully understand where the issue is, I've gone and made a jsfiddle that I think does what you're interested in.
I have a feeling the problem is the fact that you use display: flex; on the body of the document. I've surrounded the numbers in a separate div element that now has the flex-display options assigned to it.
HTML
const array = [2, 3, 4, 5];
function mapping() {
array.map(arrayItem => {
let elements = document.createElement('p');
elements.innerHTML = arrayItem;
/*
Adding the numbers to the elNumberArray div element in the HTML
*/
document.getElementById("elNumberArray").appendChild(elements);
elements.classList.add("numbers");
});
document.getElementById("elAverageButton").addEventListener("click", average);
}
function average() {
const array = [2, 3, 4, 5]
let count = 0
let val = array.reduce((x, y) => {
if (+y) {
count++
x += +y
}
return x
}, 0)
val = val / count;
document.getElementById('val').innerHTML += val + '<br/>';
}
document.onload = mapping();
body {}
/* display-flex settings are now no longer on the whole body
but set for elNumberArray div element */
#elNumberArray {
display: flex;
flex-direction: row-reverse;
justify-content: space-around;
align-items: center;
/* flex-wrap: wrap; */
}
.numbers {
font-size: 5em;
/* color: blue; */
/* text-orientation: unset; */
margin-top: 2em;
}
.button {
padding: 1em;
border: .2em solid red;
margin-top: 20em;
position: inherit;
}
<div id="elNumberArray">
<!--Numbers are now inserted here-->
</div>
<div class='container'>
<div class='button'>
<p>
<button id="elAverageButton">Average</button>
</p>
</div>
<div id='val'></div>
</div>
The button and average are now displayed below the numbers.
Is this what you were looking for?
You should place the array contents inside span tags instead of p tags.
body {
display: flex;
align-items: center;
/* flex-wrap: wrap; */
}
.numbers {
font-size: 5em;
}
.button {
padding: 1em;
border: .2em solid red;
margin-top: 20em;
}
.container{
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="style.css">
<title>Test</title>
</head>
<body onload="mapping()">
<script>
const array = [2, 3, 4, 5];
function mapping() {
array.map(arrayItem => {
let elements = document.createElement('span');
elements.innerHTML = arrayItem;
document.getElementById("numbers").appendChild(elements);
elements.classList.add("numbers");
});
}
</script>
<span id="numbers" style="margin: 20px;">
</span>
<div class='container'>
<div class='button'>
<p>
<button onClick="average()">Average</button>
</p>
</div>
<div id='val'></div>
</div>
<script>
function average() {
const array = [2, 3, 4, 5]
let count = 0
let val = array.reduce((x, y) => {
if (+y) {
count++
x += +y
}
return x
}, 0)
val = val / count;
document.getElementById('val').innerHTML += val + '<br/>';
}
</script>
</body>
</html>
JSFiddle: http://jsfiddle.net/kru10xgd/11/
const array = [2, 3, 4, 5];
let arrayContainer = document.getElementById('arrayContainer');
(function mapping() {
array.map(arrayItem => {
let element = document.createElement('p');
element.innerHTML = arrayItem;
element.classList.add("numbers");
arrayContainer.appendChild(element);
});
})();
function average() {
let count = 0
let val = array.reduce((x, y) => {
if (+y) {
count++
x += +y
}
return x
}, 0)
val = val / count;
document.getElementById('val').innerHTML += val + '<br/>';
}
.container {
width: 50%;
margin: 0 auto;
text-align: center;
transform: translate(-50%, -50%);
position: absolute;
top: 50%;
left: 50%;
}
#arrayContainer {
display: flex;
justify-content: space-evenly;
border: 1px solid;
}
.numbers {
min-width: 20px;
}
.button {
margin: 20px 0px;
}
<div class='container'>
<div id="arrayContainer"></div>
<div class='button'>
<button onClick="average()">Average</button>
</div>
<div id='val'></div>
</div>
Something like this maybe , you are trying to achieve?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- // <link rel="stylesheet" href="style.css"> -->
<title>Test</title>
<style>
.container{
width: 50%;
margin: 0 auto;
text-align: center;
transform: translate(-50%,-50%);
position: absolute;
top: 50%;
left: 50%;
}
#arrayContainer{
display: flex;
justify-content: space-evenly;
border: 1px solid;
}
.numbers {
min-width: 20px;
}
.button {
margin: 20px 0px;
}
</style>
</head>
<body>
<div class='container'>
<div id="arrayContainer"></div>
<div class='button'>
<button onClick="average()">Average</button>
</div>
<div id='val'></div>
</div>
<script>
const array = [2, 3, 4, 5];
let arrayContainer = document.getElementById('arrayContainer');
(function mapping() {
array.map(arrayItem => {
let element = document.createElement('p');
element.innerHTML = arrayItem;
element.classList.add("numbers");
arrayContainer.appendChild(element);
});
})();
function average() {
let count = 0
let val = array.reduce((x, y) => {
if (+y) {
count++
x += +y
}
return x
}, 0)
val = val / count;
document.getElementById('val').innerHTML += val + '<br/>';
}
</script>
</body>
</html>

Categories

Resources