ethan davis
ethan davis

Reputation: 35

Passing an anchor tag as itself into function instead of by id

I have built a small interactive quiz section for my website, but I know it could be structured better. Each question will have three possible answers. The way I have it set up right now, I need a unique identifier for each of the possible answers. This quickly adds up multiple questions x 3 unique ID's. Can I pass the specific through my function instead of an ID?

<a class="toggle" href="#exampleQ" id="dropQ01" onclick="setCorrect('dropQ01', '#f9a81d')">
    <b>Answer Ones</b>
</a>
<a class="toggle" href="#exampleQ" id="dropQ02" onclick="setWrong('dropQ02', '#f9a81d')">
    <b>Answer 2</b>
</a>

<a class="toggle" href="#exampleQ" id="dropQ03" onclick="setWrong('dropQ03', '#f9a81d')">
    <b>Answer 3</b>
</a>

When the options are clicked they change color.

Wrong Answer function:

var countX = 1;
function setWrong(btn, color) {
    var property = document.getElementById(btn);
    if (countX == 0) {
        property.style.backgroundColor = "#f9a81d"
        countX = 1;
    } else {
        property.style.backgroundColor = "#ff0033"
       countX = 1;
    }
}

Correct answer function.

var countC = 1;
function setCorrect(btn, color) {
    var property = document.getElementById(btn);
    if (countC == 0) {
        property.style.backgroundColor = "#f9a81d"
        countC = 1;
    } else {
        property.style.backgroundColor = "#00933B"
        countC = 1;
    }
}

If anybody sees some ways I can improve this code to be more efficient I would really appreciate it. Thank you.

Upvotes: 2

Views: 92

Answers (3)

Ishank
Ishank

Reputation: 2926

Yes, we can pass the this in the HTML mark-up but for a scalable, less redundant code, we can add the event listeners to the anchor tags after the DOM is loaded - this way you will have the this pointing to the anchor tag also you now have an event that you can use to maybe event.preventDefault(); to stop having that hash value appended in the url-

var allAnchors = document.querySelectorAll('#dropQ03, #dropQ02, #dropQ01');
var countX = 0,
  countC = 0;

var eventListener = function (event) {
  var Id = this.id;
  if (Id == "dropQ03" || Id == 'dropQ02') {
    if (countX == 0) {
      this.style.backgroundColor = "#f9a81d"
      countX = 1;
    } else {
      this.style.backgroundColor = "#ff0033"
      countX = 1;
    }
  } else {
    if (countC == 0) {
      this.style.backgroundColor = "#f9a81d"
      countC = 1;
    } else {
      this.style.backgroundColor = "#00933B"
      countC = 1;
    }
  }
}

for (var i = 0; i < allAnchors.length; i++) {
  allAnchors[i].addEventListener('click', eventListener);
}
<a class="toggle" href="#exampleQ" id="dropQ01" >
  <b>Answer Ones</b>
</a>
<a class="toggle" href="#exampleQ" id="dropQ03" >
  <b>Answer 3</b>
</a>
<a class="toggle" href="#exampleQ" id="dropQ02">
  <b>Answer 3</b>
</a>

Upvotes: 0

pilchard
pilchard

Reputation: 12909

I agree with Dan Mullin's suggestion of using this in answer to your specific question of how to avoid having to explicitly pass each ID.

In terms of overall structure you still have a lot of duplication between setCorrect and setWrong as well as the fact that implementing these per answer element has the unfortunate side effect of exposing the correct answers in the markup. Here's a quick little implementation that uses an answer key object with key/value pairs that map to the IDs of the answer elements.

const answerKey={Q01: 'a', Q02: 'd', Q03: 'b'}
let correctCount = 0;
let incorrectCount = 0;

function checkAnswer(event) {
    const [question, answer] = event.target.id.split('_');
  const correct = answerKey[question] === answer;
  if (correct) {
     event.target.style.backgroundColor =  "green";
     correctCount += 1;
     document.getElementById('correct-count').innerHTML = correctCount;
  } else {
    event.target.style.backgroundColor =  "red";
    incorrectCount +=1;
    document.getElementById('incorrect-count').innerHTML = incorrectCount;
  }
}

const answers = document.querySelectorAll('.toggle');
answers.forEach(toggle => toggle.addEventListener("click", (e) => checkAnswer(e), false));
<p>Correct: <span id="correct-count">0</span></p>
<p>Incorrect: <span id="incorrect-count">0</span></p>
<h2>Question 1</h2>
<a class="toggle" href="#exampleQ" id="Q01_a">
Answer 1
</a>

<a class="toggle" href="#exampleQ" id="Q01_b">
Answer 2
</a>

<a class="toggle" href="#exampleQ" id="Q01_c">
Answer 3
</a>

<h2>Question 2</h2>
<a class="toggle" href="#exampleQ" id="Q02_a">
Answer 1
</a>

<a class="toggle" href="#exampleQ" id="Q02_b">
Answer 2
</a>

<a class="toggle" href="#exampleQ" id="Q02_c">
Answer 3
</a>

<a class="toggle" href="#exampleQ" id="Q02_d">
Answer 4
</a>

<a class="toggle" href="#exampleQ" id="Q02_e">
Answer 5
</a>

Upvotes: 0

Dan Mullin
Dan Mullin

Reputation: 4435

Drop the id and set your onclick events like this:

<a class="toggle" href="#exampleQ" onclick="setCorrect(this, '#f9a81d')">

Doing it this way sends the element itself to the function.

Wrong answer function:

var countX = 1;
function setWrong(btn, color) {
    if (countX == 0) {
      btn.style.backgroundColor = "#f9a81d"
      countX = 1;
    } else {
      btn.style.backgroundColor = "#ff0033"
      countX = 1;
    }
}

Correct answer function

var countC = 1;
function setCorrect(btn, color) {
    if (countC == 0) {
      btn.style.backgroundColor = "#f9a81d"
      countC = 1;
    } else {
        btn.style.backgroundColor = "#00933B"
        countC = 1;
    }
}

Upvotes: 1

Related Questions