0

I have set a toggle event in JavaScript, but when the page loads I have to click twice on the element for it to fire. After that it responds normally to just one click but as soon as I refresh the page it happens again.

This is where it happens:

enter image description here

This is the website and you can clearly see the behavior yourself: https://n-ii-ma.github.io/Portfolio-Website/

This is the JS code for the event:

/* Read More */
let readMore1 = document.getElementById('show-card-1');
let readMore2 = document.getElementById('show-card-2');
let readMore3 = document.getElementById('show-card-3');

/* Projects Description */
let desc1 = document.getElementById('details1');
let desc2 = document.getElementById('details2');
let desc3 = document.getElementById('details3');

/* Toggle Description */
readMore1.onclick = function() {
    if (desc1.style.display === 'none') {
        desc1.style.display = 'block';
        readMore1.style.color = 'DeepPink';
        readMore1.innerText = 'Read Less';
    }
    else {
        desc1.style.display = 'none';
        readMore1.style.color = '';
        readMore1.innerText = 'Read More';
    }
}

readMore2.onclick = function() {
    if (desc2.style.display === 'none') {
        desc2.style.display = 'block';
        readMore2.style.color = 'DeepPink';
        readMore2.innerText = 'Read Less';
    }
    else {
        desc2.style.display = 'none';
        readMore2.style.color = '';
        readMore2.innerText = 'Read More';
    }
}

readMore3.onclick = function() {
    if (desc3.style.display === 'none') {
        desc3.style.display = 'block';
        readMore3.style.color = 'DeepPink';
        readMore3.innerText = 'Read Less';
    }
    else {
        desc3.style.display = 'none';
        readMore3.style.color = '';
        readMore3.innerText = 'Read More';
    }
}

Do you know how I can solve this issue?

Nima
  • 996
  • 2
  • 9
  • 37

3 Answers3

3

You've set your desc sections to display: none using CSS, but the element.style.property syntax can only access inline styles.

This means that on the first call for example, desc1.style.display equals "", not none. This adds the display: none property to inline styles in the else block, and from there the code works normally.

To test both CSS and inline styles, you should use window.getComputedStyle:

if (getComputedStyle(desc1).display === "none") {
    desc1.style.display = 'block';
    readMore1.style.color = 'DeepPink';
    readMore1.innerText = 'Read Less';
}
lawrence-witt
  • 8,094
  • 3
  • 13
  • 32
  • 1
    Worked like a charm. Thanks! I also found another solution myself. When negating the if statement as follows: desc1.style.display !== 'block' , the results become as expected. – Nima Sep 16 '21 at 15:09
1

You have defined the onClick even as below:

   if (desc1.style.display === 'none') {
        desc1.style.display = 'block';
        readMore1.style.color = 'DeepPink';
        readMore1.innerText = 'Read Less';
    }
    else {
        desc1.style.display = 'none';
        readMore1.style.color = '';
        readMore1.innerText = 'Read More';
    }

When you click for the first time desc1.style.display is coming as blank.

So it's going into else part and not displaying it.

You need to add style.display as none on the first load or add another condition in if to have desc1.style.display === '' like below:

let readMore1 = document.getElementById('show-card-1');

let desc1 = document.getElementById('details1');

readMore1.onclick = function() {
  if (desc1.style.display === 'none' || desc1.style.display === '') {
    desc1.style.display = 'block';
    readMore1.style.color = 'DeepPink';
    readMore1.innerText = 'Read Less';
  } else {
    desc1.style.display = 'none';
    readMore1.style.color = '';
    readMore1.innerText = 'Read More';
  }
}
<div class="project-title" id="project1">
  <div class="title">
    <h3>Tea Cozy</h3>
    <p id="show-card-1">Read More</p>
  </div>
</div>

<div class="project-desc" id="details1" style="display: none;">
  <p>This was my first website that I published to GitHub Pages. It was quite challenging at the time, but it greatly helped me learn a lot to hone my skills.</p>
  <a href="https://n-ii-ma.github.io/Tea-Cozy/" class="address" target="_blank">Tea Cozy</a>
  <div class="tech">
    <i class="fab fa-html5 fa-2x" aria-hidden="true"></i>
    <i class="fab fa-css3-alt fa-2x" aria-hidden="true"></i>
    <i class="fab fa-git fa-2x" aria-hidden="true"></i>
    <i class="fab fa-github fa-2x" aria-hidden="true"></i>
  </div>
</div>
Ashu
  • 2,066
  • 3
  • 19
  • 33
  • Changing it to none indeed fixes it but now the toggle doesn't work anymore and it's not toggling back. (I tried replacing the second load with the first one too and the results were the same) – Nima Sep 16 '21 at 14:55
1

element.style.display only gives you the non computed styles. So it will not return the styles you assigned via classes or ids in a css file.

To check that, you can use getComputedStyle().

See this example:

const elm1 = document.getElementById('hello')
const elm2 = document.getElementById('bye')

console.log('non-computed# hello:', elm1.style.display)
console.log('computed #hello:', getComputedStyle(elm1).display)

console.log('non-computed #bye:', getComputedStyle(elm2).display)
#hello {
  display: none;
}
<h1 id="hello"></h1>
<h1 id="bye" style="display: none"></h1>
S.Visser
  • 4,645
  • 1
  • 22
  • 43