1
\$\begingroup\$

I am trying to create pagination with pure PHP and jquery. I have done this and it works exactly how I want it to work. Essentially I get all products from my database using PHP.

I then populate the whole page with the products and hide every row after the first 6 products. Then using jquery I create the pagination buttons and logic.

Now the only thing is that my code looks extremely sloppy, messy and just a nightmare if I had to come back and redo things.

If anyone is up for a challenge, I will post my js fiddle link here https://jsfiddle.net/L323d4z4/ (It's not finished so you need to make the page full width as it's not mobile friendly yet).

I will state that this is not a problem as the code works, so only have a look at this if you have free time on your hands and fancy a challenge.

For a quick look at the code layout it follows like this:

<section class="row product-row for-pag-1" style="display: block;">                            <div class="col-sm-4">
                            <article class="product">
                                <img src="http://access.jm-cms.co.uk/uploads/feature_image.jpg" class="img-responsive" alt="product 1">
                                <span class="green-header">£10.99</span>
                                <h2>Birthday Card Book</h2>
                                                                    <p></p><p class="&quot;p1&quot;">Invaluable for recording birthdays and anniversaries, th</p>
                                <div class="row cart-view-buttons">
                                    <div class="col-sm-6">
                                        <div class="add-to-cart">
                                            <a href="#">Add to cart</a>
                                        </div>

                                    </div>
                                    <div class="col-sm-6">
                                        <div class="view-product">
                                            <a href="#">View</a>
                                        </div>
                                    </div>
                                </div>
                            </article>
                        </div>
                                                <div class="col-sm-4">
                            <article class="product">
                                <img src="http://access.jm-cms.co.uk/uploads/feature_image.jpg" class="img-responsive" alt="product 1">
                                <span class="green-header">£28.50</span>
                                <h2> Chalet Embroidered Tree Cushion</h2>
                                                                    <p></p><p class="&quot;p1&quot;">Cosy up with this chalet style embroidered cushion from </p>
                                <div class="row cart-view-buttons">
                                    <div class="col-sm-6">
                                        <div class="add-to-cart">
                                            <a href="#">Add to cart</a>
                                        </div>

                                    </div>
                                    <div class="col-sm-6">
                                        <div class="view-product">
                                            <a href="#">View</a>
                                        </div>
                                    </div>
                                </div>
                            </article>
                        </div>
                                                <div class="col-sm-4">
                            <article class="product">
                                <img src="http://access.jm-cms.co.uk/uploads/feature_image.jpg" class="img-responsive" alt="product 1">
                                <span class="green-header">£14.95</span>
                                <h2>Cake Stand</h2>
                                                                    <p></p><p class="&quot;p1&quot;">Afternoon tea is the new big thing (we reckon!) Get ahea</p>
                                <div class="row cart-view-buttons">
                                    <div class="col-sm-6">
                                        <div class="add-to-cart">
                                            <a href="#">Add to cart</a>
                                        </div>

                                    </div>
                                    <div class="col-sm-6">
                                        <div class="view-product">
                                            <a href="#">View</a>
                                        </div>
                                    </div>
                                </div>
                            </article>
                        </div>
                    </section>

This is one section that holds 3 products. I show 2 rows and then display:none the rest of the rows. Each row has a class for example "for-pag-1" or "for-pag-2" This is how i link the pagination buttons to which products should display.

An example of a jquery involved:

$('.next-page').click(function(){
var lastVisible = $('.pagination').find('.showing:last');
var firstVisible = $('.pagination').find('.showing:first');

if(lastVisible.data('page') > 6) {
    firstVisible.hide();
}

$('.dots').parent('li').remove();

if(firstVisible.hasClass('active')){
    if(lastVisible.data('page') !== $('.next-page').data('page')) {
        firstVisible.removeClass('showing').removeClass('active').hide().parent('li').hide().next().children().addClass('active');
        lastVisible.parent('li').next().show().children().show().addClass('showing');

        //Show the correct products
        var newActivePage = firstVisible.parent('li').next().children().data('page');
        $('.product-row').hide();
        $('.for-pag-' + newActivePage).show();
    }
}else{
    if(lastVisible.data('page') !== $('.next-page').data('page')) {
        var currentlyActive = $('.active');
        currentlyActive.removeClass('active').parent('li').next().children().addClass('active');
        firstVisible.removeClass('showing').hide().parent('li').hide();
        lastVisible.parent('li').next().show().children().show().addClass('showing');

        //Show the correct products
        var newActivePage = currentlyActive.parent('li').next().children().data('page');
        $('.product-row').hide();
        $('.for-pag-' + newActivePage).show();
    }
}
});

As you can see straight away this is messy. So if your up for it, please take a look.

Thanks

\$\endgroup\$
2
  • \$\begingroup\$ On the markup one thing I have to point out is the incorrect use of the <section> element which is defined that it is a generic element not intended for styling purposes. Likewise <article> has been used incorrectly for the same reason. \$\endgroup\$
    – Brett Ryan
    Jun 21, 2016 at 12:12
  • \$\begingroup\$ Now for the actual solution, I would recommend using knockoutjs to provide pagination of your data model of which an example exists. \$\endgroup\$
    – Brett Ryan
    Jun 21, 2016 at 12:20

1 Answer 1

1
\$\begingroup\$

If you have the means to use knockoutjs then an solution may be used that provides a model of your total products with a windowed view to that product listing.

A working jsfiddle based on your sample has been created.

First we will create an array of objects representing your product:

function product (url, price, name, desc) {
  return {
    name: name,
    href: url,
    price: price,
    desc: desc
  };
}

var data = [
  product("http://access.jm-cms.co.uk/uploads/featuire_image.jpg", '£ 78.00',
          "Soil and Compost 10mm",
          "Unscreened topsoil, dug straight from the ground."),
  product("http://access.jm-cms.co.uk/uploads/feature_image.jpg", '£ 69.00',
          "As Dug Topsoil",
          "Unscreened topsoil, dug straight from the ground."),
  product("http://access.jm-cms.co.uk/uploads/g1022-5-210x174.png", '£ 78.00',
          "Sand and Loam Topdressing",
          "Sandy loam soil has more sand than top soil, so is fast"),
  product("http://access.jm-cms.co.uk/uploads/feature_image.jpg", '£ 10.99',
          "Birthday Card Book",
          "Invaluable for recording birthdays and anniversaries, th"),
  product("http://access.jm-cms.co.uk/uploads/feature_image.jpg", '£ 28.50',
          "Chalet Embroidered Tree Cushion",
          "Cosy up with this chalet style embroidered cushion from"),
  product("http://access.jm-cms.co.uk/uploads/feature_image.jpg", '£ 14.95',
          "Cake Stand",
          "Afternoon tea is the new big thing (we reckon!) Get ahea"),
  product("http://access.jm-cms.co.uk/uploads/feature_image.jpg", '£ 90.00',
          "Delete This Product",
          "This product is here to be deleted")
];

You could instead make this an ajax request to load your data.

Now we can create the ViewModel for the view which will control the data. This is loosely based on the knockoutjs paged grid example.

$(function () {
  var ViewModel = function (data) {
    var self = this;

    self.data = data;
    self.page = ko.observable(0);
    self.pageSize = 3;
    self.start = ko.observable(0);

    self.view = ko.computed(function () {
      var start = self.pageSize * self.page();
      self.start(start);
      return ko.unwrap(self.data).slice(start, start + self.pageSize);
    });
    self.max = ko.computed(function () {
      return Math.ceil(ko.unwrap(self.data).length / self.pageSize) - 1;
    });
    self.prev = function () {
      if (!self.isFirst()) {
        self.page(self.page() - 1);
      }
    };
    self.next = function () {
      if (!self.isLast()) {
        self.page(self.page() + 1);
      }
    };
    self.isFirst = function () {
      return self.page() === 0;
    };
    self.isLast = function () {
      return self.page() === self.max();
    };
  };

  ko.applyBindings(new ViewModel(data));
});

We can now bind to the UI for both the product listing view of the windowed area of the product listing followed by the pagination control. You may repeat the pagination control above the product listing.

<div class="container">

  <!-- product listing -->
  <div class="row" data-bind="foreach: view">
    <div class="col-sm-4">
      <div class="thumbnail">
        <img data-bind="attr: {src: href, alt: name}" class="img-responsive"/>
        <div class="caption">
          <h5 data-bind="text: price"></h5>
          <h2 data-bind="text: name"></h2>
          <p data-bind="text: desc"></p>
          <p>
            <a class="btn btn-primary" href="#">Add</a>
            <a class="btn btn-default" href="#">View</a>
          </p>
        </div>
      </div>
    </div>
  </div>

</div>

And the pagination controls. These can appear within the same container, anywhere else on the page, and be repeated.

<div class="container">

  <!-- page navigation controls -->
  <nav>
    <ul class="pagination">
      <li data-bind="css: { disabled: $root.isFirst() }">
        <a href="#" aria-label="Previous"
           data-bind="click: function() { $root.prev(); }">
          <span aria-hidden="true">&laquo;</span>
        </a>
      </li>
      <!-- ko foreach: ko.utils.range(0, max) -->
      <li data-bind="css: { active: $data === $root.page() }">
        <a href="#" data-bind="text: $data + 1,
                              click: function() { $root.page($data); }"></a>
      </li>
      <!-- /ko -->
      <li data-bind="css: { disabled: $root.isLast() }">
        <a href="#" aria-label="Next"
           data-bind="click: function() { $root.next(); }">
          <span aria-hidden="true">&raquo;</span>
        </a>
      </li>
    </ul>
  </nav>

</div>
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.