最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Pagination Functionality using handlebars js - Stack Overflow

programmeradmin0浏览0评论

DEMO

I'am developing a Pagination Functionality using handlebars js and fetching the data from JSON.

  1. First 5 results will be shown on page load.

  2. on click of next pagination another set of 5 results will be displayed and so on.

  3. If i have total number of results 100 by displaying each 5 Results in page. Page Numbers will be 1 of 20.

  4. if the pagination has more then 5 number of Pages , I want to display "1,2,3 ... last Page Number (20)" same vice versa
  5. on load Previous Button Should be hidden when ever next page is clicked it has to be enabled.

Request to you please look into this and give some advice / suggestion on this.

Should be Like Below

Appreciate your kind help !

Thanks

  • some code sample :

        $(function () {
            var opts = {
            pageMax: 5,
            postsDiv: $('#posts'),
            dataUrl: "searchResult.json"
        }
    
        function range(i) { return i ? range(i - 1).concat(i) : [] }
    
        function loadPosts(posts) {
            opts.postsDiv.empty();
            posts.each(function () {
                var source = $("#post-template").html();
                var template = Handlebarspile(source);
                var context = {
                    title: this.title,
                    desc: this.body,
                };
                var html = template(context);
                opts.postsDiv.append(html);
            });
        }
    
        function paginate(pageCount) {
            var source = $("#pagination-template").html();
            var template = Handlebarspile(source);
            var context = { pages: range(pageCount) };
            var html = template(context);
            opts.postsDiv.after(html);
    
            function changePage(pageNumber) {
                pageItems.removeClass('active');
                pageItems.filter('[data-page="' + pageNumber + '"]').addClass('active');
                loadPosts(data.slice(pageNumber * opts.pageMax - opts.pageMax, pageNumber * opts.pageMax));
            }
    
            var pageItems = $('.pagination>li.pagination-page');
    
            pageItems.on('click', function () {
                changePage(this.getAttribute('data-page'));
            }).filter('[data-page="1"]').addClass('active');
    
            $('.pagination>li.pagination-prev').on('click', function () {
                gotoPageNumber = parseInt($('.pagination>li.active').attr('data-page')) - 1;
                if (gotoPageNumber <= 0) { gotoPageNumber = pageCount; }
                changePage(gotoPageNumber);
            });
    
            $('.pagination>li.pagination-next').on('click', function () {
                gotoPageNumber = parseInt($('.pagination>li.active').attr('data-page')) + 1;
                if (gotoPageNumber > pageCount) { gotoPageNumber = 1; }
                changePage(gotoPageNumber);
            });
        }
    
        $.ajax({
            dataType: 'json',
            url: opts.dataUrl,
            success: function (response_json) {
                data = $(response_json.records.page);
                dataCount = data.length;
    
                pageCount = Math.ceil(dataCount / opts.pageMax);
    
                if (dataCount > opts.pageMax) {
                    paginate(pageCount);
                    posts = data.slice(0, opts.pageMax);
                } else {
                    posts = data;
                }
                loadPosts(posts);
            }
        });
    });
    

DEMO

I'am developing a Pagination Functionality using handlebars js and fetching the data from JSON.

  1. First 5 results will be shown on page load.

  2. on click of next pagination another set of 5 results will be displayed and so on.

  3. If i have total number of results 100 by displaying each 5 Results in page. Page Numbers will be 1 of 20.

  4. if the pagination has more then 5 number of Pages , I want to display "1,2,3 ... last Page Number (20)" same vice versa
  5. on load Previous Button Should be hidden when ever next page is clicked it has to be enabled.

Request to you please look into this and give some advice / suggestion on this.

Should be Like Below

Appreciate your kind help !

Thanks

  • some code sample :

        $(function () {
            var opts = {
            pageMax: 5,
            postsDiv: $('#posts'),
            dataUrl: "searchResult.json"
        }
    
        function range(i) { return i ? range(i - 1).concat(i) : [] }
    
        function loadPosts(posts) {
            opts.postsDiv.empty();
            posts.each(function () {
                var source = $("#post-template").html();
                var template = Handlebars.pile(source);
                var context = {
                    title: this.title,
                    desc: this.body,
                };
                var html = template(context);
                opts.postsDiv.append(html);
            });
        }
    
        function paginate(pageCount) {
            var source = $("#pagination-template").html();
            var template = Handlebars.pile(source);
            var context = { pages: range(pageCount) };
            var html = template(context);
            opts.postsDiv.after(html);
    
            function changePage(pageNumber) {
                pageItems.removeClass('active');
                pageItems.filter('[data-page="' + pageNumber + '"]').addClass('active');
                loadPosts(data.slice(pageNumber * opts.pageMax - opts.pageMax, pageNumber * opts.pageMax));
            }
    
            var pageItems = $('.pagination>li.pagination-page');
    
            pageItems.on('click', function () {
                changePage(this.getAttribute('data-page'));
            }).filter('[data-page="1"]').addClass('active');
    
            $('.pagination>li.pagination-prev').on('click', function () {
                gotoPageNumber = parseInt($('.pagination>li.active').attr('data-page')) - 1;
                if (gotoPageNumber <= 0) { gotoPageNumber = pageCount; }
                changePage(gotoPageNumber);
            });
    
            $('.pagination>li.pagination-next').on('click', function () {
                gotoPageNumber = parseInt($('.pagination>li.active').attr('data-page')) + 1;
                if (gotoPageNumber > pageCount) { gotoPageNumber = 1; }
                changePage(gotoPageNumber);
            });
        }
    
        $.ajax({
            dataType: 'json',
            url: opts.dataUrl,
            success: function (response_json) {
                data = $(response_json.records.page);
                dataCount = data.length;
    
                pageCount = Math.ceil(dataCount / opts.pageMax);
    
                if (dataCount > opts.pageMax) {
                    paginate(pageCount);
                    posts = data.slice(0, opts.pageMax);
                } else {
                    posts = data;
                }
                loadPosts(posts);
            }
        });
    });
    
Share Improve this question edited Jul 17, 2017 at 9:00 ADreNaLiNe-DJ 4,9194 gold badges27 silver badges35 bronze badges asked Jul 14, 2017 at 6:30 DeveloperDeveloper 1,4373 gold badges23 silver badges48 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 3 +100

I had to solve a similar issue a few months ago. I found this Gist from kottenator.

Your range function is modified thusly, with c being the current page, and m your pageCount. Calls to the function have been modified a bit and a recursive call to your paginate(...) function is also added to repute the tag after navigation (also, a branch was added to your DOM appending function calls, to modify the pagination tag, I used a ternary operator. There may be more elegant to achieve this).
See this CodePen

function range(c,m) {
  var current = c || 1,
      last = m,
      delta = 2,
      left = current - delta,
      right = parseInt(current) + delta + 1,
      range = [],
      rangeWithEllipsis = [],
      l,
      t;

      range.push(1);
      for (var i = c - delta ; i <= c + delta ; i++) {
        if (i >= left && i < right && i < m && i > 1) {
          range.push(i);
        }
      }  
      range.push(m);

      for (var i of range) {
        if (l) {
          if (i - l === 2) {
            t = l+1;
            rangeWithEllipsis.push(t);
          } else if (i - l !== 1) {
            rangeWithEllipsis.push("...");
          }
        }
        rangeWithEllipsis.push(i);
        l = i;
      }
    return rangeWithEllipsis;
}

It doesn't solve exactly your problem per say, but it does paginate correctly.
If I have some time, I'll try and make it paginate the exact way you want to (it's really only about customizing the delta, left and right operand in the algorithm, and changing your pagination next and pagination prev event handler calls).

Edit I changed the algorithm to find the left and right boundary. Your index.html is also modified a bit.
The idea is to pute the left and right boundary by multiples of 5. You then create a range of the indexes to show and add an elipsis if the difference is too big. This should effectively solves your original problem.

JavaScript

getFirstDigits = (t) => {
 return parseInt(t.toString().slice(0,-1))
}

getLastDigit = (t) => {
 return parseInt(t.toString().slice(-1))
}

isMultipleOf5 = (t) => {
 return [0,5].reduce((res,curr)=>{
   return res = res || curr === getLastDigit(t);
 },false);
}

isBetween0and5 = (t) => {
  const _t = getLastDigit(t);
  return  _t < 5;
}

isBetween5and9 = (t) => {
  const _t = getLastDigit(t);
  return  _t => 5 && _t <= 9;
}

appendDigit = (t,d) => {
  return parseInt(getFirstDigits(t).toString() + d.toString())
}

getSecondRightMostDigit = (t) => {
  return parseInt(t.toString().slice(-2,-1))
}

incrementSecondDigit = (t) => {
  return t+10;
}

getLeft = (t) => {
  if(t>=10){
    if(isBetween0and5(t)) return appendDigit(t,0);
    else return appendDigit(t,5);
  } else {
    if (t<5) return 0;
    else return 5;
  }
}

getRight = (t) => {
  if(t<5) return 5;
  else if (t<10) return 10;
  else if(isBetween0and5(t)) return appendDigit(t,5)
  else return appendDigit(incrementSecondDigit(t),0);
}

function range(c,m) {
  var current = c || 1,
      last = m,
      delta = 2,
      left = getLeft(c),
      right = getRight(c),
      range = [],
      rangeWithEllipsis = [],
      l,
      t;

      var rightBoundary = right < 5 ? 5 : right;
      for (var i = left ; i < rightBoundary ; ++i) {
        if( i < m && i > 0) range.push(i);
      }  
      range.push(m);

      for (var i of range) {
        if (l) {
          if (i - l === 2) {
            t = l+1;
            rangeWithEllipsis.push(t);
          } else if (i - l !== 1){
            rangeWithEllipsis.push("...");
          }
        }
        rangeWithEllipsis.push(i);
        l = i;
      }
    return rangeWithEllipsis;
}

HTML/HandleBars

<!doctype html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Handlebars Pagination</title>
    <link href="main.css" rel="stylesheet" />
    <script src="jquery.min.js"></script>
    <script src="handlebars.min.js"></script>
    <script src="functions.js"></script>
</head>

<body class="container">

    <div id="posts"></div>

    <script id="pagination-template" type="text/x-handlebars-template">
        <ul class="pagination">
            <li class="pagination-prev"><a href="#">&laquo;</a></li>

            {{#each pages}}
            <li class="pagination-page" data-page="{{this}}"><a href="#">{{this}}</a></li>
            {{/each}}

            <li class="pagination-next"><a href="#">&raquo;</a></li>
        </ul>
    </script>


    <script id="post-template" type="text/x-handlebars-template">
        <div class="score-structural score-column2-wideright search-listings post">
            <div class="score-right">
                <h4>{{record_count}}</h4>
                <h5 style="z-index: 1;">
                    <a href="#"> {{ title }} </a>
                </h5>
                <p style="z-index: 1;"> {{ desc }} </p>
            </div>
        </div>
        <hr>
    </script>

</body>

</html>

<script>
     $(function () {
        var opts = {
            pageMax: 2,
            postsDiv: $('#posts'),
            dataUrl: "searchResult.json"
        }

        function loadPosts(posts) {
            opts.postsDiv.empty();
            posts.each(function () {
                var source = $("#post-template").html();
                var template = Handlebars.pile(source);
                var context = {
                    title: this.title,
                    desc: this.body,
                };
                var html = template(context);
                opts.postsDiv.append(html);
            });
            hidePrev();
        }

        function hidePrev() { $('.pagination .pagination-prev').hide(); }
        function showPrev() { $('.pagination .pagination-prev').show(); }

        function hideNext() { $('.pagination .pagination-next').hide(); }
        function showNext() { $('.pagination .pagination-next').show(); }

        function paginate(page,pageCount) {
            var source = $("#pagination-template").html();
            var template = Handlebars.pile(source);
            var context = { pages: range(page,pageCount) };
            console.log(range(page,pageCount));
            var html = template(context);
            var paginationTag = opts.postsDiv.parent().find(".pagination");
            paginationTag.length > 0 ? paginationTag.replaceWith(html) : opts.postsDiv.before(html);

            function changePage(page) {
                pageItems.removeClass('active');
                pageItems.filter('[data-page="' + page + '"]').addClass('active');
                loadPosts(data.slice(page * opts.pageMax - opts.pageMax, page * opts.pageMax));
                paginate(page,pageCount);
                if (gotoPageNumber <= 1) {
                    hidePrev();
                }
            }

            var pageItems = $('.pagination>li.pagination-page');
            var pageItemsLastPage = $('.pagination li').length - 2;
            pageItems.removeClass('active');
            pageItems.filter('[data-page="' + page + '"]').addClass('active');

            pageItems.on('click', function () {
                getDataPageNo = this.getAttribute('data-page')
                console.log(getDataPageNo)
                changePage(getDataPageNo);
                if (getDataPageNo == 1) {
                    hidePrev()
                }
                else if (getDataPageNo == pageItemsLastPage) {
                    hideNext();
                }
                else {
                    showPrev();
                    showNext();
                }
            });

            $('.pagination>li.pagination-prev').on('click', function () {
                gotoPageNumber = parseInt($('.pagination>li.active').attr('data-page')) - 1;
                changePage(gotoPageNumber);
            });

            $('.pagination>li.pagination-next').on('click', function () {
                gotoPageNumber = parseInt($('.pagination>li.active').attr('data-page')) + 1;
                if (gotoPageNumber > pageCount) {
                    gotoPageNumber = 1;
                    showPrev();
                }
                changePage(gotoPageNumber);
            });
        }

        $.ajax({
            dataType: 'json',
            url: opts.dataUrl,
            success: function (response_json) {
                data = $(response_json.records.page);
                dataCount = data.length;

                pageCount = Math.ceil(dataCount / opts.pageMax);

                if (dataCount > opts.pageMax) {
                    paginate(1,pageCount);
                    posts = data.slice(0, opts.pageMax);
                } else {
                    posts = data;
                }
                loadPosts(posts);
            }
        });

    });

</script>
发布评论

评论列表(0)

  1. 暂无评论