skip to Main Content

I’m trying to implement Readmore/readless functionality for a Laravel feed page that returns many objects from DB. The problem is my readmore code only works for the first object but doesn’t work on subsequent objects. It’s kind of a Facebook feed page where you can view posts from friends and then click the "Readmore" button to expand a comment or a note. That’s precisely what I’m trying to implement. My "Readmore" code works only for the first object. I’d like some help with making the "Readmore" button apply to all objects from the DB.

Below is my code

**HTML**
    <div class="container row">

        @forelse ($counters as $key => $counter)

       <div>
           <h6>Title</h6>
           <p>{{ $counter->title }}</p>
       </div>
                     
       <div>
           <h6>Address</h6> 
           <p>{{ $counter->address }}</p>
       </div><span id="dots"></span><span id="moretext">

       <div>
           <h6>Email</h6>
           <p>{{ $counter->email }}</p>
       </div>
                     
       <div>
           <h6>Contact no.</h6> 
           <p>{{ $counter->contact }}</p>
       </div>

       </span><button onclick="myFunction()" id="myBtn">Read more</button>

@empty 
  No information published yet.
@endforelse 

</div>


**CSS**

  <style>
      #moretext {display: none;}
  </style>


**JS**
<script>
   function myFunction() {
        var dots = document.getElementById("dots");
        var moreText = document.getElementById("moretext");
        var btnText = document.getElementById("myBtn");

  if (dots.style.display === "none") {
      dots.style.display = "inline";
      btnText.innerHTML = "Read more"; 
      moreText.style.display = "none";
  } 
else 
{
    dots.style.display = "none";
    btnText.innerHTML = "Read less"; 
    moreText.style.display = "inline";
  }
}

</script>

2

Answers


  1. IDs need to be unique. Use a class.

    Your HTML is invalid. A span cannot contain a div. Make it a div and wrap your content and you can use delegation like this

    document.querySelector(".container").addEventListener("click", e => {
      const tgt = e.target;
      if (!tgt.matches(".readMore")) return ; // not a button
      const parent = tgt.closest(".item");
      const dots = parent.querySelector(".dots");
      const moreText = parent.querySelector(".moretext");
      dots.hidden = !dots.hidden;
      moreText.hidden = !moreText.hidden;
      tgt.textContent = dots.hidden ? "Read less" : "Read more";
    })
    .dots:after { content: "…" }
    <div class="container row">
      <div class="item">
        <div>
          <h6>Title</h6>
          <p>Title 1</p>
        </div>
        <div>
          <h6>Address</h6>
          <p>Address 1</p>
        </div><span class="dots"></span>
        <div class="moretext" hidden>
          <div>
            <h6>Email</h6>
            <p>Email 1</p>
          </div>
          <div>
            <h6>Contact no.</h6>
            <p>Contact 1</p>
          </div>
        </div>
        <button class="readMore">Read more</button>
      </div>
    
      <div class="item">
        <div>
          <h6>Title</h6>
          <p>Title 2</p>
        </div>
        <div>
          <h6>Address</h6>
          <p>Address 2</p>
        </div><span class="dots"></span>
        <div class="moretext" hidden>
          <div>
            <h6>Email</h6>
            <p>Email 2</p>
          </div>
          <div>
            <h6>Contact no.</h6>
            <p>Contact 2</p>
          </div>
        </div>
        <button class="readMore">Read more</button>
      </div>
    
    </div>

    Your code:

    <div class="container row">
      @forelse ($counters as $key => $counter)
      <div class="item">
        <div>
          <h6>Title</h6>
          <p>{{ $counter->title }}</p>
        </div>
        <div>
          <h6>Address</h6>
          <p>{{ $counter->address }}</p>
        </div>
        <span class="dots"></span>
        <div class="moretext" hidden>
          <div>
            <h6>Email</h6>
            <p>{{ $counter->email }}</p>
          </div>
          <div>
            <h6>Contact no.</h6>
            <p>{{ $counter->contact }}</p>
          </div>
        </div>
        <button class="readMore">Read more</button>
      </div>
      @empty No information published yet. 
      @endforelse
    </div>
    
    Login or Signup to reply.
  2. Ids need to be unique

    This is the code you are looking for

    <div class="container row">
    
            
            @foreach ($counters as $key => $counter)
           <div>
               <h6>Title</h6>
               <p>{{ $counter->title }}</p>
           </div>
                         
           <div>
               <h6>Address</h6> 
               <p>{{ $counter->address }}</p>
           </div><span id="dots-<?php echo $key; ?>"></span><span id="moretext-<?php echo $key; ?>">
    
           <div>
               <h6>Email</h6>
               <p>{{ $counter->email }}</p>
           </div>
                         
           <div>
               <h6>Contact no.</h6> 
               <p>{{ $counter->contact }}</p>
           </div>
    
           </span><button onclick="myFunction(this.id)" data-value="myBtn-<?php echo $key; ?>" id="myBtn-<?php echo $key; ?>">Read more</button>
    
    @empty 
      No information published yet.
    @endforeach
    
    </div>
    
    
    
      <style>
          #moretext {display: none;}
      </style>
    
    
    <script>
       var dataLength = '<?php echo sizeof($counters); ?>';
       for(var i=0; i<dataLength; i++){
           document.getElementById("moretext-"+i).style.display = 'none';
       }
       
       function myFunction(clicked_id) {
            var dataLength = '<?php echo sizeof($counters); ?>';
            //alert(dataLength);
            var dots = [];
            var moreText = [];
            var btnText = [];
            //alert(clicked_id);
            
            for(var i=0; i<dataLength; i++){
                dots.push(document.getElementById("dots-"+i));
                moreText.push(document.getElementById("moretext-"+i));
                btnText.push(document.getElementById("myBtn-"+i));
                
            if(document.getElementById("myBtn-"+i).getAttribute("data-value") == clicked_id){   
                if (dots[i].style.display === "none") {
                        dots[i].style.display = "inline";
                        btnText[i].innerHTML = "Read more"; 
                        moreText[i].style.display = "none";
                    } 
                else 
                {
                    dots[i].style.display = "none";
                    btnText[i].innerHTML = "Read less"; 
                    moreText[i].style.display = "inline";
                }
            }
                
            }
            
    
      
    }
    
    </script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search