Click event on array with multiple elements but individually [closed] - javascript

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I'm trying to cycle through an array with a for...of loop but need each element in the array to be a separate click event (not grabbing all of them) - without using jQuery.
Here's what I have so far ...
const dataScrollTo = document.querySelectorAll('[data-scroll-to]');
let ss = 1000;
let o = 0;
const scrollMe = function scrollMe() {
for (const el of dataScrollTo) {
const trigger = el.getAttribute('data-scroll-to');
const target = document.getElementById(trigger);
const dsoGet = el.getAttribute('data-scroll-offset');
const dssGet = el.getAttribute('data-scroll-speed');
target.scrollIntoView({
behavior: 'smooth'
});
if (dsoGet) {
o = dsoGet;
}
if (dssGet) {
ss = dssGet;
}
}
};
document.addEventListener('click', scrollMe);
And the HTML (there are a few navigation divs similar to this one).
<div>
<a class="icon-link" data-scroll-to="research" data-scroll-offset="60">
</a>
</div>

You should add the event listener to each element, not document. The listener can use this to tell which element was clicked on.
function scrollMe() {
const el = this;
const trigger = el.getAttribute('data-scroll-to');
const target = document.getElementById(trigger);
const dsoGet = el.getAttribute('data-scroll-offset');
const dssGet = el.getAttribute('data-scroll-speed');
target.scrollIntoView({
behavior: 'smooth'
});
if (dsoGet) {
o = dsoGet;
}
if (dssGet) {
ss = dssGet;
}
}
dataScrollTo.forEach(el => el.addEventListener("click", scrollMe));

Related

Create a dynamic function with JS [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 days ago.
Improve this question
I'm working in a project to create a knife in 3 parts and I want to create something like this. I don't really know if it's possible.
//selector
const imgBlade = document.querySelector('.piece__blade');
const imgPart = document.querySelector('.piece__part');
const imgMatter = document.querySelector('.piece__matter');
// here only 3 parts to create the knife but i have alot of more thant that
const shinyBladeImagePath = /img/products/shinyblade.png;
const centralePartImagePath = /img/products/centralePart.png;
const woodCentralePartPath = /img/products/woodCentralePart.png;
class piece {
constructor(name, info, path) {
this.name = name;
this.info = info;
this.path = path;
}
}
let shinyBlade = new piece('SB', 'Shiny Blade', shinyBladeImgPath);
let centralePart = new piece('CP', 'Centrale Part', centralePartImagePath);
let woodCentralePart = new piece('W01', 'Wood Centrale Part', woodCentralePartPath);
class knife {
constructor(blade, part, matter) {
this.blade = blade;
this.part = part;
this.matter = matter;
}
}
let firstKnife = new knife(shinyBlade, centralePart, woodCentralePartPath);
// here I want to create a function to create a dynamic "object" :
function showKnife(event) {
// Here I want to change path with on a click event
imgBlade.src = ;
imgPiece.src = ;
imgMatter.src = ;
}
shinyBladeTitle.addEventListener('click', () => {
showKnife.imgBlade.blade.path;
// here I want to click on a title option and change the imgBlade.src on my function
});
centralePartTitle.addEventListener('click', () => {
showKnife.imgPiece.piece.path;
// here I want to click on a title option and change the imgPiece.src on my function
});
woodTitle.addEventListener('click', () => {
showKnife.imgMatter.matter.path;
// here I want to click on a title option and change the imgPiece.src on my function
});
<div>
<img alt="Blade" src="/img/products/BLANK.png">
<img alt="Part" src="/img/products/BLANK.png">
<img alt="Piece" src="/img/products/BLANK.png">
</div>

getting NaN when asking for video duration [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
Can anyone help me understand why console.log(this.getPlayerDuration()) inside of setAttendancePromptTimeLimit() is returning NaN?
// video-player.js
const videoP = document.querySelector('#in-course-player')
class videoPlyer {
constructor(videoElem){
this.vidPlayer = videoElem
}
play = function(cb){
arguments.length ? cb : console.log('play')
}
addListener = (elem, event, cb) => {
elem.addEventListener(event, cb)
}
getPlayerCurrentTime = () => this.vidPlayer.currentTime
getPlayerDuration = () => this.vidPlayer.duration
showVideoDuration = function(cb){
arguments.length ? cb : this.addListener(this.vidPlayer, 'loadedmetadata', () =>
console.log(this.getPlayerDuration()))
}
setAttendancePromptTimeLimit = cb => {
// returns NAN
console.log(this.getPlayerDuration())
}
init = () => {
//returns 16.1
this.showVideoDuration()
//returns NAN
this.setAttendancePromptTimeLimit()
}
}
const coursePlayer = new videoPlyer(videoP)
coursePlayer.init()
[...] If no media data is available, the value NaN is returned. [...]
https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/duration

Splice an array in react keeps removing the first element [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
Working on my todo app, when I want to remove an element from an array, it keeps removing the first element all the time...
I cant find why.
Any ideas? I copy the bit of code that is linked to my remove function !
THANK YOU!
function App () {
const [activities, setActivities] = useState([]);
const [color, setColor] = useState ('Black');
const [complete, setComplete] = useState([]);
//ADD NEW ACTIVITY
/* activities*/
function addActivity (data) {
let newActivity = { data, done:false, isMotivating: false, id: sum , color: 'Black' }
sum++;
setActivities((activities) => [ ...activities, newActivity])
//console.log(`App: ${JSON.stringify(data)}`)
};
function toggleColor (a) {
setColor ('')
activities[a.id].isMotivating = activities[a.id].isMotivating ? false : true
if (activities[a.id].isMotivating === false) {
setColor ('green')
activities[a.id].color = color
} else {
setColor ('red')
activities[a.id].color = color
}
console.log(activities[a.id])
return activities;
}
function removeTodo (id ) {
const newTodos = [...activities];
newTodos.splice(id, 1);
setActivities(newTodos);
};
}
Your sum seems to be declared via let/var which will be initialized to 0 on each re-render so each of your id is probably set to 0.
You can instead use useRef like so :-
const uuid = useRef(0);
Inside addActivity
function addActivity (data) {
let newActivity = { data, done:false, isMotivating: false, id:uuid.current , color: 'Black' }
uuid.current++;
setActivities((activities) => [ ...activities, newActivity])
//console.log(`App: ${JSON.stringify(data)}`)
};
But not sure if using id as index to splice is best way to go here since you're always removing stuff, your array length will change.

Can't add an event listener to an element from an API

I am building a trivia webapp using an API and i want to add an event listener to the button with the correct answer so that when the user clicks it it will display a message saying they're right and it'll get a new question.
Here's how the code looks:
function useApiData(triviaObj) {
let answers = sortArrayRandomly([
triviaObj.results[0].correct_answer,
triviaObj.results[0].incorrect_answers[0],
triviaObj.results[0].incorrect_answers[1],
triviaObj.results[0].incorrect_answers[2],
]);
document.querySelector("#category").innerHTML = `Category: ${triviaObj.results[0].category}`;
document.querySelector("#difficulty").innerHTML = `Difficulty: ${triviaObj.results[0].difficulty}`;
document.querySelector("#question").innerHTML = `Question: ${triviaObj.results[0].question}`;
document.querySelector("#answer1").innerHTML = `${answers[0]}`;
document.querySelector("#answer2").innerHTML = `${answers[1]}`;
document.querySelector("#answer3").innerHTML = `${answers[2]}`;
document.querySelector("#answer4").innerHTML = `${answers[3]}`;
let rightAnswer = triviaObj.results[0].correct_answer;
rightAnswer.addEventListener("click", correctAnswer);
console.log(answers);
}
function correctAnswer() {
alert("correct");
getTrivia();
}
It tells me that the AddEventListener is not a function, how can I fix this?
Use a loop to fill in the answer elements. In that loop you can check if the current answer is the correct answer and add the event listener.
answers.forEach((answer, i) => {
let button = document.querySelector(`#answer${i+1}`);
button.innerHTML = answer;
if (answer == triviaObj.results[0].correct_answer) {
button.addEventListener("click", correctAnswer);
} else {
button.removeEventListener("click", correctAnswer);
}
});
Event listeners go on DOM elements, not on pieces of data or other variables. Try finding the correct answer element and attaching the event listener to that:
const rightAnswer = triviaObj.results[0].correct_answer;
const matchingAnswer = answers.find((x) => x === rightAnswer);
const rightElement = Array.from(document.querySelectorAll('*[id^="answer"]'))
.find((el) => el.innerText.includes(rightAnswer))
rightElement.addEventListener("click", correctAnswer);
Assuming that triviaObj.results[0].correct_answer is a number representing the correct answer, then:
Replace
let rightAnswer = triviaObj.results[0].correct_answer;
with
let rightAnswer = document.querySelector(`#answer${triviaObj.results[0].correct_answer}`);
This is much more simple than Zan Anger's solution.

Go to nextURL on local server

I need to go to the next URL after a correct answer on a quiz. I have an assignment where I'm creating a Quiz game with questions from a server at the university. When the person is correct the game gets the next question on the server with a XMLHttpRequest.
How can I somehow us a 'nextURL' here or is there no such term?
function Question () {
let quizQuestion = new window.XMLHttpRequest()
quizQuestion.open('GET', 'http://vhost3.lnu.se:20080/question/1')
quizQuestion.onload = function () {
let ourData = JSON.parse(quizQuestion.responseText)
let questionDiv = document.querySelector('#question')
questionDiv.innerText = ourData.question
}
quizQuestion.send()
answer()
}
function answer () {
let quizQuestion = new window.XMLHttpRequest()
let answerDiv = document.querySelector('#answer')
let button = document.createElement('button')
button.type = 'button'
button.setAttribute('id', 'send')
button.innerText = 'Answer'
answerDiv.appendChild(button)
button.addEventListener('click', function () {
quizQuestion.open('POST', 'http://vhost3.lnu.se:20080/answer/1')
quizQuestion.setRequestHeader('Content-type', 'application/json')
quizQuestion.send(JSON.stringify({answer: inputText.value}))
quizQuestion.onreadystatechange = function () {
console.log(quizQuestion.response)
let ourAnswer = JSON.parse(quizQuestion.responseText)
let answerDiv = document.querySelector('#answer')
answerDiv.innerText = ourAnswer.message
}
})
}
So if the value in ({answer: inputText.value}) is correct I want to go to the next question, which in this case is in quizQuestion.open('GET', 'http://vhost3.lnu.se:20080/question/21')
Based on what you've written, it looks like "next URL" at any given moment would be next in a list that you've been given, and it's up to you to figure out how to retrieve the appropriate one after a correct answer.
We'll assume the question numbers in your assignment are non-sequential (moving from question 1 to question 21 in your example), and that no questions repeat. Is there a list of the questions in the order you need on the server? If the list is in an array, can you access it based on the index of the current question?
If not, assuming you already know the list of questions in the desired order, you can do this in your own code. Suppose you put your question numbers into an array, and store the current question number, like so:
let questionNums = [1,21,14,9,6,23]
let currQuestionNum = questionNums[0]
This lets you concatenate the desired question number onto your base URL as
'http://vhost3.lnu.se:20080/question/' + currQuestionNum.toString().
Then, when you've checked if the answer is correct, you can move to the next question in the array:
if (questionNums.indexOf(currQuestionNum)+1 != questionNums.length){
currQuestionNum = questionNums[questionNums.indexOf(currQuestionNum)+1]
}
else{
//end the quiz
}
To use this with the concatenation example above, you'll need to modify your Question and answer functions to accept question numbers as parameters:
function Question (questionNum) {
let quizQuestion = new window.XMLHttpRequest()
quizQuestion.open('GET', 'http://vhost3.lnu.se:20080/question/'+questionNum)
quizQuestion.onload = function () {
let ourData = JSON.parse(quizQuestion.responseText)
let questionDiv = document.querySelector('#question')
questionDiv.innerText = ourData.question
}
quizQuestion.send()
answer(questionNum)
}
function answer (questionNum) {
let quizQuestion = new window.XMLHttpRequest()
let answerDiv = document.querySelector('#answer')
//Local answerNum variable
let answerNum = questionNum
let button = document.createElement('button')
button.type = 'button'
button.setAttribute('id', 'send')
button.innerText = 'Answer'
answerDiv.appendChild(button)
button.addEventListener('click', function () {
quizQuestion.open('POST', 'http://vhost3.lnu.se:20080/answer/'+answerNum)
quizQuestion.setRequestHeader('Content-type', 'application/json')
quizQuestion.send(JSON.stringify({answer: inputText.value}))
quizQuestion.onreadystatechange = function () {
console.log(quizQuestion.response)
let ourAnswer = JSON.parse(quizQuestion.responseText)
let answerDiv = document.querySelector('#answer')
answerDiv.innerText = ourAnswer.message
}
})
}
Note the local answerNum variable - this is added so that, if quesitonNum changes before the anonymous function is called on a click event, the value won't be affected.

Categories

Resources