Use JavaScript to add a div element to the page ten times every time the button is clicked

Here is the code I have written:

$(document).ready(function () {
          $('<button class="btn more">View More</button>')
         .appendTo(".listing-item-container")
         .click(function() {
            $(this).closest(".listing-item-container").removeClass("collapsed");
          });
          $('<button class="btn less">View Less</button>')
         .appendTo(".listing-item-container")
         .click(function() {
           $(this).closest(".listing-item-container").addClass("collapsed");
         });
      });   
.listing-item-container.collapsed > :nth-of-type(n+3) {
      display:none;
    }
    
    .listing-item-container > .more {
      display:none;
    }
    .listing-item-container > .less {
      display:block;
    }
    
    .listing-item-container.collapsed > .more {
      display:block;
    }
    .listing-item-container.collapsed > .less {
      display:none;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="listing-item-container collapsed">
        <div class="listing-item">
            <p>FEATURES</p>
            <ul class="no-list-style">
                <li>list content</li>
                <li>list content</li>
                <li>list content</li>
                <li>list content</li>
            </ul>
        </div>
        <div class="listing-item">
            <p>FEATURES</p>
            <ul class="no-list-style">
                <li>list content</li>
                <li>list content</li>
                <li>list content</li>
                <li>list content</li>
            </ul>
        </div>
        <div class="listing-item">
            <p>FEATURES</p>
            <ul class="no-list-style">
                <li>list content</li>
                <li>list content</li>
                <li>list content</li>
                <li>list content</li>
            </ul>
        </div><div class="listing-item">
            <p>FEATURES</p>
            <ul class="no-list-style">
                <li>list content</li>
                <li>list content</li>
                <li>list content</li>
                <li>list content</li>
            </ul>
        </div>
        <!--  Remaining listing-item divs here   -->
    </div>

In the code above, clicking on view more will expand all remaining 'listing item' divs, while clicking on view less collapses all the divs to display only 2.

I want the functionality to show only the next 2 'listing item' divs when I click view more, along with the corresponding button. This pattern should repeat for all the remaining 'listing item' divs, and end with a view less button displayed. Clicking view less should collapse the last 2 'listing item' divs each time.

What changes can I make to my code to achieve this desired output?

Answer №1

The secret lies in utilizing the jquery slice() function (which is similar to javascript slice() but operates on a jquery collection).

var howManyItemsToShow = 2;
$(".listing-item").hide().slice(howManyItemsToShow).show();

This code snippet will hide all the items and then display the first 2 items. This triggers a single UI update action. If you incorporate animations like .slideDown / .fadeIn, the approach will be different.

You can increment your "pagesize" value (2 in this example) each time you click and make updates accordingly.

To control the display of more/less buttons efficiently, implement a check for start/end conditions and refer to the helpful css trick:

var lines = 2;
var pagesize = 2;

// Load them up-front assuming no changes for small efficiency gain (and DRY)
var items = $(".listing-item-container .listing-item");

$(document).ready(function() {
 $('#lt;button class="btn more">View More</button>')
    .appendTo(".listing-item-container")
    .click(function() {
    
      lines += pagesize;
      items
        .show()
        .slice(lines).hide();
        
      if (lines >= items.length)
        $(this).closest(".listing-item-container").removeClass("collapsed");
    });

  $('<button class="btn less">View Less</button>')
    .appendTo(".listing-item-container")
    .click(function() {
      // Similar logic for "less" with -= and different condition checks
      // Combine with "more" button for DRYness or keep separate for clarity
      lines -= pagesize;
      items.show();
      items.slice(lines).hide();
      if (lines <= pagesize)
        $(this).closest(".listing-item-container").addClass("collapsed");
    });
});
.listing-item-container.collapsed>:nth-of-type(n+3) {
  display: none;
}

.listing-item-container>.more {
  display: none;
}

.listing-item-container>.less {
  display: block;
}

.listing-item-container.collapsed>.more {
  display: block;
}

.listing-item-container.collapsed>.less {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="listing-item-container collapsed">
  <div class="listing-item">
    <p>FEATURES</p>
    <ul class="no-list-style">
      <li>list content</li>
      <li>list content</li>
      <li>list content</li>
      <li>list content</li>
    </ul>
  </div>
  <!-- Repeat listing-item div structure multiple times -->
  <!-- Additional listing-item divs go here   -->
</div>

Answer №2

I decree that it shall be done in this manner...

((parentRef='.listing-item-container', ItemsRef='.listing-item', startView=2, addView=2 )=>
 {
  const
    listItems  = document.querySelectorAll(ItemsRef)
  , btMoreLess = document.querySelector(parentRef).appendChild( document.createElement('button'))
    ;
  btMoreLess.className = 'showMore'

  var listItemsViewCount = startView -addView;

  btMoreLess.onclick =_=>
    {
    listItemsViewCount += btMoreLess.classList.contains('Less') ? -addView : +addView
    listItems.forEach( (item,i)=> item.classList.toggle('noDisplay',i>=listItemsViewCount) )

    if (listItemsViewCount >= listItems.length)  btMoreLess.classList.add('Less')
    else if (listItemsViewCount === startView)   btMoreLess.classList.remove('Less')
    }

  btMoreLess.click()  // commence
  }
)() // IIFE termination
.noDisplay{ display:none; } 
button.showMore:before { content : 'View More'; }
button.showMore.Less:before { content : 'View Less'; }

.listing-item-container   { counter-reset: itemCounter;         }
.listing-item             { counter-increment: itemCounter;     }
.listing-item > p::before { content: counter(itemCounter) '.';  }
<div class="listing-item-container">
  <div class="listing-item">
    <p>FEATURES</p>
    <ul> <li>list content</li> <li>list content</li> <li>list content</li> <li>list content</li> </ul>
  </div>
  <div class="listing-item">
    <p>FEATURES</p>
    <ul> <li>list content</li> <li>list content</li> <li>list content</li> <li>list content</li> </ul>
  </div>
  <div class="listing-item">
    <p>FEATURES</p>
    <ul> <li>list content</li> <li>list content</li> <li>list content</li> <li>list content</li> </ul>
  </div>
  <div class="listing-item">
    <p>FEATURES</p>
    <ul> <li>list content</li> <li>list content</li> <li>list content</li> <li>list content</li> </ul>
  </div>
  <div class="listing-item">
    <p>FEATURES</p>
    <ul> <li>list content</li> <li>list content</li> <li>list content</li> <li>list content</li> </ul>
  </div>
  <div class="listing-item">
    <p>FEATURES</p>
    <ul> <li>list content</li> <li>list content</li> <li>list content</li> <li>list content</li> </ul>
  </div>
  <div class="listing-item">
    <p>FEATURES</p>
    <ul> <li>list content</li> <li>list content</li> <li>list content</li> <li>list content</li> </ul>
  </div>
  <!--  100 more listing-item divs present here   -->
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Styling <CardHeader> component with React and Material UI CSS

Incorporating React and Material UI, my goal is to arrange 3 divs within a <Card> <CardHeader/>, positioning them with left, center, and right alignment as illustrated below. The modification required is minor - I simply need to eliminate the ...

"Permission denied to access restricted URI" error encountered while attempting to utilize ng-template functionality

I am attempting to implement ng-include for recursive templates in my HTML. After testing it on jsfiddle and confirming that it works, I tried the same locally. However, I encountered the following error: Error: Access to restricted URI denied createHttpB ...

An error occurred when attempting to use the getDoc() function from Firebase within Next.js: TypeError - reading 'map' on properties of undefined

Hello everyone at StackOverflow, I ran into a problem while attempting to use .map() on a getDoc() constant in my Next.js application. The error message I'm getting is: "TypeError: Cannot read properties of undefined (reading 'map')". As a n ...

The Jquery ajax get method is malfunctioning

I've been trying out this code but it doesn't seem to be working. Apologies for the basic question, but I'm curious to understand why it's not functioning as expected. $(document).ready(function(){ $("button").click(function(){ ...

What kind of registration does React Hook Form use?

When utilizing react-hook-form alongside Typescript, there is a component that passes along various props, including register. The confusion arises when defining the type of register within an interface: export interface MyProps { title: string; ... ...

Accessing nested objects within a JavaScript array for an Express API

My current data sample looks like this: var data = [{ articles : [{ id : '0', url : 'foo', title : 'Foo', body : 'some foo bar', category : 'foo', tags : ...

What is the accurate Scrapy XPath for identifying <p> elements that are mistakenly nested within <h> tags?

I am currently in the process of setting up my initial Scrapy Spider, and I'm encountering some challenges with utilizing xpath to extract specific elements. My focus lies on (which is a Chinese website akin to Box Office Mojo). Extracting the Chine ...

Tips for inserting HTML-tagged data into a database using AJAX and PHP

var id=$("#id").val(); var status=$("#status").val(); var jtitle=$("#jtitle").val(); function submitData(){ var id=$("#id").val(); var status=$("#status").val(); var jtitle=$("#jtitle").val(); var jdesc=tinyMCE.acti ...

Troubleshooting Tips for Resolving Problems with VueJS getElementById Bug

I'm currently working with a VueJS single File component that has the following template: <template> <div class="row"> <div class="col-md-12"> <div id="hottable"></div> < ...

Issues with webpage responsiveness, width not adjusting correctly

Just completed coding my website and now I'm facing a new challenge. I am focusing on making it responsive for tablet screens (768px) starting with the header section, but for some reason, the modifications I make in the responsive.css file are not ta ...

If the FedEx function does not receive a payment, it will need to return a value of Payment Required

I am struggling with understanding functions, parameters, and arguments in JavaScript as I am new to it. My goal is to have a function that returns different values based on the payment amount. If no payment is passed, it should return "Payment Required", ...

Reduce the number of redundant fields in MongoDB collections

I'm facing an issue with my model structure. Here is the schema: var accountSchema = new mongoose.Schema({ 'seeker': { 'fullName': String, 'ageGroup': String, 'education': String, ...

Chakra UI Not Displaying Proper Responsiveness on the User Interface

I recently integrated Chakra UI for styling a project on Next.js, and while most components are functioning properly, I am facing challenges with implementing responsive layouts. The styles do not seem to adapt when the screen size is reduced. Here's ...

Transform jQuery code to its equivalent in vanilla JavaScript

While I am proficient in using jQuery, my knowledge of pure JavaScript is somewhat limited. Below is the jQuery code that I have been working with: $(document).ready(function() { $.get('http://jsonip.com/', function(r){ var ip_addre ...

Create a duplicate of a div in jQuery while also updating its contents

I need help cloning a div that has the following structure: <div id="multipleSteps"> <div id="step_1"> <input type="text" name="step_name_1" id="step_name_1"> </div> ...

What could be the reason that Vue is not evaluating anything when the directive @click is specified as "true && method"?

Consider the following scenario: LandingPage.vue <template> <button @click="handleClick">Click Me</button> </template> <script> export default { methods: { handleClick() { this.$emit("click"); } } }; < ...

What is the best way to retrieve the unique identifier of dynamically created divs and showcase a message based on that identifier?

Is it possible to retrieve the id of a dynamically generated div and show a unique message when each div is clicked in the code snippet found at this link? function get_random_color() { var letters = '0123456789ABCDEF'.split(''); ...

Minimize the size of the MUI date selector widget

I've been incorporating the MUI date picker into a data list, but I'm looking to decrease the height of the input field and adjust the positioning of the close date and calendar icons. They're currently taking up too much space between them ...

React search filter feature with dropdown selection

After successfully implementing a search filter in my React app, I encountered an issue when trying to incorporate a select tag to change the search filter criteria. class BookList extends Component { state = { search: '', selectedValue: ' ...

React-Native Error: Invalid element type detected

While attempting to run my React Native app on my iPhone using Expo, I encountered an error displayed in a red background area. Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite ...