skip to Main Content

I have some boxes that a lot of informations inside it. I want the information less at first and if the user want to read more information, they click the button "See More". Then if they click that button, the button named "Copy" will be display and the button named "See More" will be changed into "See Less" through innerHTML.

The code below is working properly but theres a lot of Code. Is there’s a possibility to make the code shorter?



<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <title>Page title</title>

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

</head>

<body>

    <div class="wrapper">

<div class="box">

    <div class="content">

<p>This Is a Content Example</p>

    </div>

    <div class="BTN">

<button class="SM">See More</button>

<button class="Copy">Copy</button>

    </div>

</div>

<div class="box">

    <div class="content">

<p>This Is a Content Example</p>

    </div>

    <div class="BTN">

<button class="SM">See More</button>

<button class="Copy">Copy</button>

    </div>

</div>

<div class="box">

    <div class="content">

<p>This Is a Content Example</p>

    </div>

    <div class="BTN">

<button class="SM">See More</button>

<button class="Copy">Copy</button>

    </div>

</div>

    </div>

</body>

</html>

<style>

*{

margin: 0;

padding: 0;

outline: none;

}

body{

    width: 100%;

    height: 100vh;

    display: flex;

    justify-content: center;

    align-items: center;

}

.wrapper{

    width: 90%;

    display: flex;

    flex-direction: column;

}

.box{    

    height: 180px;

    background: blue;

    width: 100%;

    margin-top: 10px;

}

.content{

    height: 100%;

    width: 100%;

    display: flex;

    justify-content: center;

    align-items: center;

}

.content p{

    font-size: 22px;

    color: white;

    font-weight: bold;

}

.BTN{

    position: relative;

    width: 90%;

    margin: auto;

    display: flex;

    justify-content: space-between;

    gap: 8px;

    height: 32px;

    margin-top: -37px;

}

.BTN button{

    height: 100%;

    width: 100%;

    font-size: 18px;

    background: yellow;

    color: red;

    font-weight: bold;

    border: none;

    border-radius: 5px;

}

.Copy{

    display: none;

}

@media(min-width: 600px){

.wrapper{

    flex-direction: row;

    gap: 10px;

}

}

</style>

<script>

var a = document.getElementsByClassName("SM");

var b = document.getElementsByClassName("Copy");

a[0].addEventListener("click", function(){

    if(a[0].innerHTML == "See Less"){

    a[0].innerHTML = "See More";

    b[0].style.display = "None";    

    }else{

    a[0].innerHTML = "See Less";

    b[0].style.display = "block";

    }

});

a[1].addEventListener("click", function(){

    if(a[1].innerHTML == "See Less"){

    a[1].innerHTML = "See More";

    b[1].style.display = "None";    

    }else{

    a[1].innerHTML = "See Less";

    b[1].style.display = "block";

    }

});

a[2].addEventListener("click", function(){

    if(a[2].innerHTML == "See Less"){

    a[2].innerHTML = "See More";

    b[2].style.display = "None";    

    }else{

    a[2].innerHTML = "See Less";

    b[2].style.display = "block";

    }

});

b[0].addEventListener("click", function(){

    alert("You Copied the First Info");

    /* Please Dont Create a Code To Copy because I already know and this is a sample. But if there's a possibility to make this code shorter, please include this.*/

});

b[1].addEventListener("click", function(){

    alert("You Copied the Second Info");

});

b[2].addEventListener("click", function(){

    alert("You Copied the Third Info");

});

</script>

    

    


Anyway, if there’s a possibility to make the code shorter in JQuery, then I want to accept it.
Thank you in advance

3

Answers


  1. Array forEach can help

    [...a] creates an Array from a

    .forEach((el, i) gives you an index (i) for the appropriate b and you can use el instead of a[i] – up to you really

    const a = document.getElementsByClassName("SM");
    const b = document.getElementsByClassName("Copy");
    [...a].forEach((el, i) => a.addEventListener('click', function () {
        if (el.innerHTML == "See Less") {
            el.innerHTML = "See More";
            b[i].style.display = "None";
        } else {
            el.innerHTML = "See Less";
            b[i].style.display = "block";
        }
    }));
    [...b].forEach((el, i) => b.addEventListener("click", function () {
        alert(`You copied ${['First', 'Second', 'Third']} Info`);
    });
    
    Login or Signup to reply.
  2. You can achieve the same via jquery with very simple code.

    Sample example:

    $('.SM').click(function() {
      $(this).next('.Copy').toggle(); // hide show copy button
      //code to change button text
      $(this).text(function(i, text){
          return text === "See More" ? "See less" : "See More";
      })
    });
    * {
      margin: 0;
      padding: 0;
      outline: none;
    }
    
    body {
      width: 100%;
      height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    
    .wrapper {
      width: 90%;
      display: flex;
      flex-direction: column;
    }
    
    .box {
      height: 180px;
      background: blue;
      width: 100%;
      margin-top: 10px;
    }
    
    .content {
      height: 100%;
      width: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    
    .content p {
      font-size: 22px;
      color: white;
      font-weight: bold;
    }
    
    .BTN {
      position: relative;
      width: 90%;
      margin: auto;
      display: flex;
      justify-content: space-between;
      gap: 8px;
      height: 32px;
      margin-top: -37px;
    }
    
    .BTN button {
      height: 100%;
      width: 100%;
      font-size: 18px;
      background: yellow;
      color: red;
      font-weight: bold;
      border: none;
      border-radius: 5px;
    }
    
    .Copy {
      display: none;
    }
    
    @media(min-width: 600px) {
      .wrapper {
        flex-direction: row;
        gap: 10px;
      }
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <!DOCTYPE html>
    
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>Page title</title>
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    
    <body>
      <div class="wrapper">
        <div class="box">
          <div class="content">
            <p>This Is a Content Example</p>
          </div>
          <div class="BTN">
            <button class="SM">See More</button>
            <button class="Copy">Copy</button>
          </div>
        </div>
        <div class="box">
          <div class="content">
            <p>This Is a Content Example</p>
          </div>
          <div class="BTN">
            <button class="SM">See More</button>
            <button class="Copy">Copy</button>
          </div>
        </div>
        <div class="box">
          <div class="content">
            <p>This Is a Content Example</p>
          </div>
          <div class="BTN">
            <button class="SM">See More</button>
            <button class="Copy">Copy</button>
          </div>
        </div>
      </div>
    </body>
    
    </html>

    Note: Make sure the jQuery library is included on your page otherwise this code will not work.

    Login or Signup to reply.
  3. In your original post you require 2 parts to your solution: the first is making your overall code shorter/simplified and the second is to leverage the use of JQuery to do so.

    We can skip using the direct functionality to edit and read the DOM (i.e. innerHTML and getElementsByClassName) since we can use jQuery to handle the click events and dynamically update the content of each box.

    First we will condense the markup & styling as such:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Page title</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <div class="wrapper"></div>
    </body>
    </html>
    <style>
        /* Your CSS styles here */
    </style>
    

    Notice that we only have the div with the "wrapper" class. We will use this as our starting point to generate the box contents.

    Next we will update our script to generate the content using jQuery as well as enable all of the necessary functionality. Note, make sure to include the latest version of the jQuery library.

    <script src="https://code.jquery.com/jquery-*.*.*.min.js"></script>
    <script>
        // Array containing the content for each box
        const boxContents = [
            'This is the first box content',
            'This is the second box content',
            'This is the third box content'
        ];
    
        // Function to toggle content visibility and button text
        function toggleContent(index) {
            const boxContent = $('.content p').eq(index);
            const seeMoreBtn = $('.SM').eq(index);
            const copyBtn = $('.Copy').eq(index);
    
            if (seeMoreBtn.text() === 'See More') {
                boxContent.text(boxContents[index]);
                seeMoreBtn.text('See Less');
                copyBtn.show();
            } else {
                boxContent.text('This Is a Content Example');
                seeMoreBtn.text('See More');
                copyBtn.hide();
            }
        }
    
        // Click event for "See More" buttons
        $('.wrapper').on('click', '.SM', function () {
            const index = $('.SM').index(this);
            toggleContent(index);
        });
    
        // Click event for "Copy" buttons
        $('.wrapper').on('click', '.Copy', function () {
            const index = $('.Copy').index(this);
            alert(`${index + 1}`);
            // Copy functionality can continue here
        });
    
        // Function to generate the dynamic markup for boxes
        function generateBoxes() {
            const wrapper = $('.wrapper');
    
            // Iterate through boxContents array and create the markup for each box
            for (let i = 0; i < boxContents.length; i++) {
                const boxMarkup = `
                    <div class="box">
                        <div class="content">
                            <p>This Is a Content Example</p>
                        </div>
                        <div class="BTN">
                            <button class="SM">See More</button>
                            <button class="Copy">Copy</button>
                        </div>
                    </div>
                `;
                wrapper.append(boxMarkup);
            }
        }
    
        // When the document is ready, generate the boxes and enable the functionality
        $(document).ready(function () {
            generateBoxes();
        });
    </script>
    

    Since the original post contained three boxes we have created a const called boxContents which contains a value for each box. This value will appear when you click on the ‘See More’ button. When the document loads for the first time, jQuery will trigger the function generateBoxes which will run through the array provided by boxContents. This will generate the necessary HTML for us instead of needing to manually add it for each individual box.

    Now that we have our boxes we need to create the two events for the buttons. This can also be done in jQuery. Note that in the script we need to use .wrapper as our starting point in the reference. This is because we are generating the html for the boxes after the DOM loads. If we try to make .SM and .Copy a direct reference like this:

    $('.SM').on('click', function () {});
    

    Then the code will not run. In both of our event functions we track the index of the button. This index is based on the correlating value of the boxContents. For the ‘See More’ button it triggers the toggleContent function which will add the value in boxContents to the correlating box.

    Note: your css will remain unchanged in this scenario.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search