1

I have following html with css style and js:

<p>This is a text
  <br />
  <a ref="##" onclick="showHideBlocks('i1', 'i2')">
    <span id="i1" class="show">(show more)</span>
  </a>
</p>
<p id="i2" class="hidden">This is hidden text
  <br />
  <a ref="##" onclick="showHideBlocks('i1', 'i2')">(hide me) 
  </a>
</p>

and my css:

.show {
  display: block;
}
.hidden {
  display: none;
}

In web view: this shows like this as expected.

 This is a text
 (show more)

and here is the js function:

function showHideBlock(id) 
{
  var e = document.getElementById(id);
  var display = e.style.display;
  console.log(typeof display)
  console.log(display)
  if (display === 'block') {
    display = 'none';
  } else {
    display = 'block';
  }
  e.style.display = display;
}

function showHideBlocks(id1, id2)
{
  showHideBlock(id1);
  showHideBlock(id2);
}

First time, I click on "(show more)", the hidden block is displayed, partially as expected:

This is text
(show more)

This is hidden text
(hide me)

However, the text "(show more)" is still displayed, expected hidden! This is expected:

This is text

This is hidden text
(hide me)

Then, I click on "(hide me)", the text "(show more)" and the next paragraph are all hidden. That means the subsequently calls are working (since display are assigned by string 'block' or 'none').

This is text

I have added log message to the js function. I notice that for the first time, display is string type but value is empty!(the second line should be empty, I use "" to emphasize the empty)

string
""

How can I get its property as "block" or "none" for the first time?

Thanks @AnhPC03 for correction. But the problem is still the same. I have updated codes in the question. Actually the above codes are simplified from my project.

8
  • style.display will only show the value found in the style attribute - not the actual display value. If you don't specify style="display:block" to start with - this code does not work as you are only showing if it is set to none. You could change the if statement to if(display === "block" || display === ""){ as long as you aren't hiding via CSS. Commented Jul 22, 2022 at 4:27
  • The example you've shown here is different from your original code. Here you are specifying style="display:block" whereas on your original code, you are not. Commented Jul 22, 2022 at 4:28
  • @David.Chu.ca Your code is working perfectly fine. Please check the same in jsFiddle jsfiddle.net/4ho0mf6r . Commented Jul 22, 2022 at 4:29
  • @Rylee, true my original codes using css instead of style directly in html. I removed the original link, avoid complicate the question. The issue is that "(show me)" is not set to hidden first the 1st click. 2nd click, "(show me)" and the 2nd para are gone (hidden). Commented Jul 22, 2022 at 4:38
  • The code you've posted here works completely fine. Have you tried adjusting that if statement? Commented Jul 22, 2022 at 4:45

3 Answers 3

2

I'd suggest toggling a class. I've adjust your code to show how you can do this simply.

function showHideBlock(id) 
{
  var e = document.getElementById(id);
  
  if (e.classList.contains("hidden")) {
    e.classList.remove("hidden");
  } else {
    e.classList.add("hidden");
  }
}

function showHideBlocks(id1, id2)
{
  showHideBlock(id1);
  showHideBlock(id2);
}
.hidden {
  display: none;
}
<p>This is a text
  <br />
  <a ref="##" onclick="showHideBlocks('i1', 'i2')">
    <span id="i1" class="show">(show more)</span>
  </a>
</p>
<p id="i2" class="hidden">This is hidden text
  <br />
  <a ref="##" onclick="showHideBlocks('i1', 'i2')">(hide me) 
  </a>
</p>

Sign up to request clarification or add additional context in comments.

4 Comments

No need for a "show" class here. If you wanted to include that, you would have additional logic for handling that.
Just different way to get class name to achieve the expected result. Looks good. @Rylee
it looks that a tag may have a list of classes. One of them is just for hidden, and others for other UI format, right?
That's totally up to you and how you want each class to effect an element. By having a separate class for hiding it can make things simpler. Just be aware that you may need to use display: hidden !important within the rule if there are more specific rules that also change the display.
2

UPDATED
After the author edit his post
Because in the first block, you have class instead of style="display: block;" in your span, so that you need to check if display property is presented or not. If not, get property of that class in css file using getComputedStyle method.

function showHideBlock(id) 
{
  var e = document.getElementById(id);
  var display = e.style.display;
  if (display === "") {
    let style = getComputedStyle(e);
    display = style.display;
  }
  if (display === 'block') {
    display = 'none';
  } else {
    display = 'block';
  }
  e.style.display = display;
}

function showHideBlocks(id1, id2)
{
  showHideBlock(id1);
  showHideBlock(id2);
}

4 Comments

I have updated me codes in the question. But the problem is not resolved with the correction. Thanks!
@David.Chu.ca I add two " notations and it works. You could check it here
you are right. I have updated my question and comments. In the case of css, it is not working. jsfiddle.net/9q7d3s1n/2
@David.Chu.ca I've updated my answer, check it in here
1

Here you go with Solution 1

    function showHideBlock(id) 
    {
      var e = document.getElementById(id);
      if (e.classList.contains("show")) {
        e.classList.remove("show");
        e.classList.add("hidden");
      } else {
        e.classList.remove("hidden");
        e.classList.add("show");
      }
    }

    function showHideBlocks(id1, id2)
    {
      showHideBlock(id1);
      showHideBlock(id2);
    }
    .show {
      display: block;
    }

    .hidden{
      display: none;
    }
    <p>This is a text
    <br />
    <a ref="##" onclick="showHideBlocks('i1', 'i2')">
      <span id="i1" class="show">
        (show more)
      </span>
      </a></p>
    <p id="i2" class="hidden">This is hidden text<br />
    <a ref="##" onclick="showHideBlocks('i1', 'i2')">(hide me)</a></p>

    <p>
    Another test with inline style.
    </p>

    <p>This is a text
    <br />
    <a ref="##" onclick="showHideBlocks('i3', 'i4')">
      <span id="i3" class="show">
        (show more)
      </span>
      </a></p>
    <p id="i4" class="hidden">This is hidden text<br />
    <a ref="##" onclick="showHideBlocks('i3', 'i4')">(hide me)</a></p>

Here you go with Solution 2

function showHideBlock(id) 
{
  document.getElementById(id).classList.toggle("hidden")
}

function showHideBlocks(id1, id2)
{
  showHideBlock(id1);
  showHideBlock(id2);
}
.hidden{
  display: none;
}
<p>This is a text
<br />
<a ref="##" onclick="showHideBlocks('i1', 'i2')">
  <span id="i1">
    (show more)
  </span>
  </a></p>
<p id="i2" class="hidden">This is hidden text<br />
<a ref="##" onclick="showHideBlocks('i1', 'i2')">(hide me)</a></p>

<p>
Another test with inline style.
</p>

<p>This is a text
<br />
<a ref="##" onclick="showHideBlocks('i3', 'i4')">
  <span id="i3">
    (show more)
  </span>
  </a></p>
<p id="i4" class="hidden">This is hidden text<br />
<a ref="##" onclick="showHideBlocks('i3', 'i4')">(hide me)</a></p>

3 Comments

Looks good for both solutions. One thing about "Another test", it looks as same as "This is a test". Should the 2nd test using style="display: none;"?
@David.Chu.ca Are you looking for class and inline css based solution in a single method?
Thank you! That's OK. I think the current version is working.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.