1

I'm working on a jsfiddle, my goal here is when we click "prev/next" button, we can see 5 next or 5 prev articles but all others must be hidden.

At this time I can click on "prev / next" button, then we can see 5 next or 5 prev articles but all others articles who are already visible stay visible.

here is my example, may be someone have an easier idea :

$(document).ready(function () {
    size_article = $("#myList article").size();
    x=5;
    $('#myList article:lt('+x+')').show();
    $('#loadMore').click(function () {
        x= (x+5 <= size_article) ? x+5 : size_article;
        $('#myList article:lt('+x+')').show();
    });
    $('#showLess').click(function () {
        x=(x-5<0) ? 3 : x-5;
        $('#myList article').not(':lt('+x+')').hide();
    });
});
#myList article{
display: none;
}

#loadMore {
color: green;
cursor: pointer;
}

#showLess {
color: red;
cursor: pointer;
}

#loadMore:hover, #showLess:hover {
color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>



<div id="myList">
    <article>One</article>
    <article>Two</article>
    <article>Three</article>
    <article>Four</article>
    <article>Five</article>
    <article>Six</article>
    <article>Seven</article>
    <article>Eight</article>
    <article>Nine</article>
    <article>Ten</article>
    <article>Eleven</article>
    <article>Twelve</article>
    <article>Thirteen</article>
    <article>Fourteen</article>
    <article>Fifteen</article>
    <article>Sixteen</article>
    <article>Seventeen</article>
    <article>Eighteen</article>
    <article>Nineteen</article>
    <article>Twenty one</article>
</div>
<div id="loadMore">Load more</div>
<div id="showLess">Show less</div>
faty fatoumata
  • 205
  • 5
  • 20
  • Look into [pagination](https://getbootstrap.com/docs/4.3/components/pagination/) – EGC Oct 16 '19 at 22:20
  • This is really useful! [JSFiddle](https://jsfiddle.net/solodev/yw7y4wez/) as it gives a full example on how to implement `pagination` – EGC Oct 16 '19 at 22:21
  • Pagination is ok, but I don't think that it matches with my html part, please keep in mind that
    balises will be added automatically without any class or id that I can add manually
    – faty fatoumata Oct 16 '19 at 22:28

4 Answers4

1

You can use the slice() as $(this).slice(start_index, end_index) to get the next or prev 5 elements.

$(document).ready(function() {
  size = $('#myList article').length;
  x = 5;
  $('#myList article:lt(' + x + ')').show();
  $('#loadMore').click(function() {
    if (x + 5 > size) return;
    $('#myList article').hide();
    $('#myList article').slice(x, x + 5).show();
    x += 5;
  });
  $('#showLess').click(function() {
    if (x - 5 <= 0) return;
    $('#myList article').hide();
    x -= 5;
    $('#myList article').slice(x - 5, x).show();
  });
});
#myList article {
  display: none;
}

#loadMore {
  color: green;
  cursor: pointer;
}

#showLess {
  color: red;
  cursor: pointer;
}

#loadMore:hover,
#showLess:hover {
  color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>



<div id="myList">
  <article>One</article>
  <article>Two</article>
  <article>Three</article>
  <article>Four</article>
  <article>Five</article>
  <article>Six</article>
  <article>Seven</article>
  <article>Eight</article>
  <article>Nine</article>
  <article>Ten</article>
  <article>Eleven</article>
  <article>Twelve</article>
  <article>Thirteen</article>
  <article>Fourteen</article>
  <article>Fifteen</article>
  <article>Sixteen</article>
  <article>Seventeen</article>
  <article>Eighteen</article>
  <article>Nineteen</article>
  <article>Twenty one</article>
</div>
<div id="loadMore">Load more</div>
<div id="showLess">Show less</div>
Nidhin Joseph
  • 9,981
  • 4
  • 26
  • 48
0

As I said in my initial comments, I still think pagination is the best approach, please review it once more here: Pagination along with it's example: Pagination Example

However, I've implemented a simply JQuery solution that should get you out of trouble!

See the fiddle: JSFiddle

var articles = $('article');
var groupNum = 0;
var currentGroupNum = 0;
$.each(articles, function(index, value) {
  $(this).attr("class", "group" + groupNum);
  if ((index + 1) % 5 === 0) {
    groupNum++;
  }
});


$('#loadMore').on('click', function() {  
    $(".group" + currentGroupNum).show()
    currentGroupNum++;
});

$('#showLess').on('click', function() {
 $(".group" + (currentGroupNum - 1)).hide()
    currentGroupNum--;
});
#myList article {
   display: none;
}

#loadMore {
  color: green;
  cursor: pointer;
}

#showLess {
  color: red;
  cursor: pointer;
}

#loadMore:hover,
#showLess:hover {
  color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="myList">
  <article>One</article>
  <article>Two</article>
  <article>Three</article>
  <article>Four</article>
  <article>Five</article>
  <article>Six</article>
  <article>Seven</article>
  <article>Eight</article>
  <article>Nine</article>
  <article>Ten</article>
  <article>Eleven</article>
  <article>Twelve</article>
  <article>Thirteen</article>
  <article>Fourteen</article>
  <article>Fifteen</article>
  <article>Sixteen</article>
  <article>Seventeen</article>
  <article>Eighteen</article>
  <article>Nineteen</article>
  <article>Twenty one</article>
</div>
<div id="loadMore">Load more</div>
<div id="showLess">Show less</div>

Essentially, what this does is:

  1. Add a group to every 5 elements
  2. On click of show, it will keep record of the last shown group & display the next
  3. On click of hide, it will keep record of the last shown group & display one less

Any questions, let me know!

EGC
  • 1,719
  • 1
  • 9
  • 20
0

If you are interested for a bit advanced implementation, take a look at this codes.

  • It supports adding articles in runtime. Just add some article to it and it will make a group from them
  • You can configure some options like animation duration, number of items each group, article tag name or class name (need to add . manually), ...

With some modification you can make a jQuery plugin from it. Also it uses jQuery fade animation.

// This is a closure
(function($) {

  'use strict';

  $(function() {
    var
      articles_parent,
      articles,
      //-----
      btn_next,
      btn_prev,
      btn_more,
      //-----
      inside_group_tag_or_class,
      //-----
      group_class,
      active_group_class,
      animation_time;
    var
      group_count,
      group_length,
      group_counter;
    var
      in_repair,
      i;
    var click_timeout;

    // assign value to variable(s)
    articles_parent = $('#myList');
    //-----
    inside_group_tag_or_class = 'article';
    //-----
    articles = articles_parent.find('> ' + inside_group_tag_or_class);
    group_class = 'each-group';
    active_group_class = 'active-group';
    //-----
    animation_time = 260;
    //-----
    btn_next = $('#loadMore');
    btn_prev = $('#showLess');
    btn_more = $('#moreArticles');
    //-----
    in_repair = false;
    //-----
    group_counter = 1;

    // calculate group count and length
    group_count = 5;
    group_length = Math.ceil(articles.length / group_count);

    // wrap group x to a new group
    function slicer(x) {
      var
        wrapper_element,
        current_group,
        //-----
        from,
        to;

      // assign value to variable(s)
      wrapper_element = '<div class="' + group_class + '" data-group="' + group_counter++ + '" />';
      //-----
      from = x * group_count;
      to = from + group_count;
      //-----
      current_group = articles.slice(from, to);
      current_group.wrapAll(wrapper_element);
    }

    function updateSlicer() {
      articles = articles_parent.find('> ' + inside_group_tag_or_class);
      group_length = Math.ceil(articles.length / group_count);

      // call slicer function to group each n article
      for (i = 0; i < group_length; i++) {
        slicer(i);
      }
    }

    function showGroup(action, repair) {
      animateGroupItems('show', action, repair);
    }

    function hideAllGroups() {
      animateGroupItems('hide');
    }

    function animateGroupItems(action, extra, repair) {
      repair = repair === false;

      var
        all_groups,
        active_group,
        active_group_items;
      //-----
      var idx;
      //-----
      all_groups = getAllGroups();
      active_group = getActiveGroup(repair);
      active_group_items = active_group.find('> ' + inside_group_tag_or_class);

      if (action === 'show') {
        var
          show_action,
          active_group_idx,
          first_groups_index,
          last_groups_index;
        //-----
        show_action = extra;
        active_group_idx = active_group.index();
        first_groups_index = 0;
        last_groups_index = all_groups.last().index();

        // check show action
        if (show_action === 'next') {
          if (active_group_idx !== last_groups_index) {
            idx = active_group_idx + 1;
          } else {
            resetClick();
            return;
          }
          hideAllGroups();
        } else if (show_action === 'prev') {
          if (active_group_idx !== first_groups_index) {
            idx = active_group_idx - 1;
          } else {
            resetClick();
            return;
          }
          hideAllGroups();
        } else {
          idx = first_groups_index;
          hideAllGroups();
        }

        setTimeout(function() {
          // main show action
          active_group.removeClass(active_group_class);
          all_groups.eq(idx).addClass(active_group_class);
          active_group = getActiveGroup(true);
          active_group_items = active_group.find('> ' + inside_group_tag_or_class);
          //-----
          active_group_items.show();
          active_group.stop().fadeIn(animation_time, function() {
            can_click = true;
          });
        }, 2 * animation_time);
      } else if (action === 'hide') {
        all_groups.stop().fadeOut(animation_time);
      }
    }

    function getActiveGroup(repair) {
      return checkActiveGroup(repair);
    }

    function getAllGroups() {
      return articles_parent.find('.' + group_class);
    }

    function checkActiveGroup(repair) {
      repair = repair === true;

      var
        all_groups,
        active_group,
        active_group_length;

      all_groups = getAllGroups();
      active_group = articles_parent.find('.' + group_class + '.' + active_group_class);
      active_group_length = active_group.length;

      // if we don't have any active group, select first one
      if (!active_group_length) {
        all_groups.eq(0).addClass(active_group_class);
        if (repair && !in_repair) {
          in_repair = true;
          repairGroups();
        }
      }

      // if we have more than one active group, remove active class from all groups but first one
      if (active_group_length > 1) {
        active_group.not(active_group.first()).removeClass(active_group_class);
      }

      active_group = articles_parent.find('.' + group_class + '.' + active_group_class);
      return active_group;
    }

    function repairGroups() {
      var all_groups;
      all_groups = getAllGroups();
      articles.stop().fadeOut(animation_time, function() {
        all_groups.stop().fadeOut(animation_time);
      });
      showGroup();
      in_repair = false;
    }

    function resetClick() {
      clearTimeout(click_timeout);
      can_click = true;
    }

    // call slicer function to group each n article
    for (i = 0; i < group_length; i++) {
      slicer(i);
    }

    // show first group
    showGroup(false);

    var can_click = true;

    // show next group
    btn_next.on('click', function() {
      if (can_click) {
        can_click = false;
        showGroup('next');
      }
    });

    // show previous group
    btn_prev.on('click', function() {
      if (can_click) {
        can_click = false;
        showGroup('prev');
      }
    });

    // insert more article
    var counter = 1;
    btn_more.on('click', function() {
      for (var j = 0; j < 5; j++) {
        articles_parent.append($('<article/>').text('New article number ' + counter++));
      }
      updateSlicer();
    });
  });
})(jQuery);
#myList {
  min-height: 75px;
}

#myList article {
  display: none;
}

#loadMore {
  color: green;
  cursor: pointer;
}

#showLess {
  color: red;
  cursor: pointer;
}

#moreArticles {
  color: blue;
  cursor: pointer;
}

#loadMore:hover,
#showLess:hover,
#moreArticles:hover {
  color: black;
}

.each-group {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="myList">
  <article>One</article>
  <article>Two</article>
  <article>Three</article>
  <article>Four</article>
  <article>Five</article>
  <article>Six</article>
  <article>Seven</article>
  <article>Eight</article>
  <article>Nine</article>
  <article>Ten</article>
  <article>Eleven</article>
  <article>Twelve</article>
  <article>Thirteen</article>
  <article>Fourteen</article>
  <article>Fifteen</article>
  <article>Sixteen</article>
  <article>Seventeen</article>
  <article>Eighteen</article>
  <article>Nineteen</article>
  <article>Twenty</article>
</div>
<div id="loadMore">Load more</div>
<div id="showLess">Show less</div>
<div id="moreArticles">Add more article</div>
MMDM
  • 465
  • 3
  • 11
-1

You are looking for pagination. There are several ways or libraries that can implement it. If you want something in raw javascript, you can look at this: Simple pagination in javascript. This matches with your expectations I assume.

You can do something like this:

var current_page = 1;
var records_per_page = 5;
var listing_table = document.querySelectorAll('#myList article');

function prevPage() {
  if (current_page > 1) {
    current_page--;
    changePage(current_page);
  }
}

function nextPage() {
  if (current_page < numPages()) {
    current_page++;
    changePage(current_page);
  }
}

function changePage(page) {
  var btn_next = document.getElementById("loadMore");
  var btn_prev = document.getElementById("showLess");
  // Validate page
  if (page < 1) page = 1;
  if (page > numPages()) page = numPages();

  for (i = 0; i < listing_table.length; i++) {
    listing_table[i].style.display = "none";
  }

  listing_table.innerHTML = "";
  for (var i = (page - 1) * records_per_page; i < (page * records_per_page); i++) {
    listing_table[i].style.display = "block";
  }

  if (page == 1) {
    btn_prev.style.visibility = "hidden";
  } else {
    btn_prev.style.visibility = "visible";
  }

  if (page == numPages()) {
    btn_next.style.visibility = "hidden";
  } else {
    btn_next.style.visibility = "visible";
  }
}

function numPages() {
  return Math.ceil(listing_table.length / records_per_page);
}

window.onload = function() {
  changePage(1);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<div id="myList">
  <article>One</article>
  <article>Two</article>
  <article>Three</article>
  <article>Four</article>
  <article>Five</article>
  <article>Six</article>
  <article>Seven</article>
  <article>Eight</article>
  <article>Nine</article>
  <article>Ten</article>
  <article>Eleven</article>
  <article>Twelve</article>
  <article>Thirteen</article>
  <article>Fourteen</article>
  <article>Fifteen</article>
  <article>Sixteen</article>
  <article>Seventeen</article>
  <article>Eighteen</article>
  <article>Nineteen</article>
  <article>Twenty one</article>
</div>
<div id="loadMore" onclick="nextPage()">Load more</div>
<div id="showLess" onclick="prevPage()">Show less</div>
G-Cyrillus
  • 101,410
  • 14
  • 105
  • 129
Sakibur Rahman
  • 834
  • 3
  • 10
  • 26
  • the problem here is that I will use json, I will want to add that to specific page who will generate articles when I create one, and all articles who will be generated will be added to the list – faty fatoumata Oct 16 '19 at 22:33
  • So you want to use json? – Sakibur Rahman Oct 16 '19 at 22:38
  • I think I can't, in my case I can only play with css and javascript on balises who will appear automatically in my page. Css will help me to hide articles and js will help me to show articles 5 by 5, like pagination. In my example all is ok, I just need to hide five previous articles when I click on next, same for prev – faty fatoumata Oct 16 '19 at 22:41
  • Updated the answer. Please check. – Sakibur Rahman Oct 16 '19 at 23:01
  • 1
    hum can't make it work when I test it on jsfiddle, please try it : https://jsfiddle.net/xo4z79da/ – faty fatoumata Oct 16 '19 at 23:04