4

Below is a working pagination script that displays content from a MySQL database. I need to have the pages seamlessly load within the container "#content" rather than have the entire page refreshed. I search extensively for hours but none of the tutorials I encountered helped me implement Ajax/JQuery on this script.

Here is the code I use to display my articles + pagination.

<div id="content">
<?php
include('db.php');

$stmt = $db->query('SELECT * FROM db');
$numrows = $stmt->rowCount();
$rowsperpage=21;
$totalpages=ceil($numrows/$rowsperpage);

if(isset($pageid)&&is_numeric($pageid)){$page=$pageid;}else{$page=1;} 
if($page>$totalpages){$page = $totalpages;} 
if($page<1){$page=1;}

$offset=($page-1)*$rowsperpage;

$stmt=$db->prepare("SELECT * FROM db ORDER BY ID DESC LIMIT ?,?");
$stmt->bindValue(1, "$offset", PDO::PARAM_STR);
$stmt->bindValue(2, "$rowsperpage", PDO::PARAM_STR);

if($stmt->execute()) {
while ($row = $stmt->fetch()) {
echo '

<article>
article here
</article>

';}}

$range=4;
echo'
<div id="pagination">';

if($page>1){
echo "
<a href='http://www.domain.com/1/'><<</a>";
$prevpage = $page - 1;
echo "
<a href='http://www.domain.com/$prevpage/'><</a>";
}

for ($x = ($page - $range); $x < (($page + $range) + 1); $x++) {
if(($x>0)&&($x<= $totalpages)){
if($x==$page){
echo'
<span class="current">'.$x.'</span>';
}
else{echo"<a href='http://www.domain.com/$x/'>$x</a>";}
}
}

if($page!=$totalpages){
$nextpage=$page+1;
echo"
<a href='http://www.domain.com/$nextpage/'>></a>";
echo "
<a href='http://www.domain.com/$totalpages/'>>></a>";
} 
echo '
</div>';
?>
1
  • <a href='http://www.domain.com/1/'><<</a> Please use &lt; and &gt; not < and > when you want to output those characters. Commented Mar 1, 2013 at 1:15

2 Answers 2

3

Your setup is a little unclear, but bear with me.

I'm going to assume that on the client side you know when to load the next page (ie the user clicks a button or scrolls to the end of the page etc...) I'm also going to assume that the PHP code you've posted is in its own file and outputs only what you've posted in your question (aka it outputs only the HTML for the articles and nothing else, no wrappers, nothing, if not make it so.

What you're going to want to do is use jQuery (From your question it looks like you already have it on your site so adding another library isn't too taboo) to make an AJAX request to this PHP page. The PHP then echos out what you've posted and the jQuery inserts this on the page inside the #content div.

First a note: I wouldn't recommend having your PHP page output the content div, I would recommend having that stay on the client side and only changing the content of it to what your script returns.

To load new content, you can use this javascript function on the client side:

function makePaginationRequest( pagenum = 1 ) {
    // Make ajax request
    $.ajax("test2.php", {
        // Data to send to the PHP page
        data: { "pagenum": pagenum },

        // Type of data to receive (html)
        dataType: 'html',

        // What to do if we encounter a problem fetching it
        error: function(xhr, text){
            alert("Whoops! The request for new content failed");
        },

        // What to do when this completes succesfully 
        success: function(pagination) {
            $('#content').html(pagination);
        }
    })
}

You can place any other parameters you need to pass to the server inside the "data" object (the data: { "pagenum": pagenum }, in key-value form. As you can see from the example, you pass the page number to this function and it passes the "pagenum" request variable to the server.

You'll want to implement a better error handler obviously. As well as change the "test2.htm" filename to that of your PHP script.

A better way of doing this

I feel compelled to mention this:

The way above (what you asked for) is really a messy way of doing this. Whenever you request AJAX data from your server, the server should return content, not markup. You should then insert this content into markup on the client side.

To do this, you would modify your PHP script to first put everything in an array (or an array of array for multiple articles) like this:

while ($row = $stmt->fetch()) {
    $output_array[] = array(
        "post_title" => $row["title"],
        "post_date" => $row["date"],
        // etc....
    );
}

Then echo it like so:

die(json_encode($output_array));

Then modify your json request:

function makePaginationRequest( pagenum = 1 ) {
    $.ajax("test2.htm", {
        data: { "pagenum": pagenum },
        dataType: 'json',
        error: function(xhr, text){
            alert("Whoops! The request for new content failed");
        },
        success: function(pagination) {
            // Empty the content area
            $('#content').empty();

            // Insert each item
            for ( var i in pagination ) {
                var div = $('<article></article>');
                div.append('<span class="title">' + pagination[i].post_title + "</span>");
                div.append('<span class="date">' + pagination[i].post_date + "</span>");
                $('#content').append(div)
            }
        }
    })
}

jQuery will automagically parse this JSON output into a native javascript object for you.

Taking this approach of having the client make the markup takes alot of load off of your server, and requires less bandwith.

Food for thought, hope that helps.

Sign up to request clarification or add additional context in comments.

Comments

1

If you want to do the least amount of rewriting to your original script, the jQuery .load() method might be your best bet. You would basically just need to supply an id to the element that contains all of your articles; something like this should work:

<div id="container">

    <div id="articles-container">

        <article> ... </article>

    </div>

</div>   

<div id="pagination">
    <a href="some-valid-url">1</a> ...
</div>

Then add a script tag and some jQuery code:

<script>

    $(function(){

        $('#pagination').on('click', 'a', function(e){

            e.preventDefault();
            var url = $(this).attr('href');
            $('#container').load(url + ' #articles-container');

        });

    });

</script>

.load() will fetch the page, and if you add the optional fragment to the URL, it will filter the result to the element matching the fragment.

EDIT:

Okay, so, to make this work with your current pagination, you need to manually swap the elements. So, assuming your generated markup looks something like this:

<div id="pagination">
    <a href="/1">1</a>
    <span class="current">2</span>
    <a href="/3">3</a>
    <a href="/4">4</a>
    <a href="/5">5</a>
</div>

We want this to happen after the load() completes, so we need to add a callback function to it. I'm also adding a self reference to the clicked element, which we need later:

$(function(){

    $('#pagination').on('click', 'a', function(e){

        e.preventDefault();
        var $this = $(this);
        var url = $this.attr('href');
        $('#container').load(url + ' #articles-container', function(response, status, jqxhr){

        });

    });

});

Inside the callback is where we start manipulating #pagination. The first part is easy enough:

var $curr = $('#pagination span.current');
var page = $curr.text();

$curr.replaceWith('<a href="/' + page + '">' + page + '</a>');

Now we need to replace the link we just clicked:

$this.replaceWith('<span class="current">' + $this.text() + '</span>');

Et viola!, your pagination should be updated. Here's the whole update:

$(function(){

    $('#pagination').on('click', 'a', function(e){

        e.preventDefault();
        var $this = $(this);
        var url = $this.attr('href');
        $('#container').load(url + ' #articles-container', function(response, status, jqxhr){

            var $curr = $('#pagination span.current');
            var page = $curr.text();

            $curr.replaceWith('<a href="/' + page + '">' + page + '</a>');

            $this.replaceWith('<span class="current">' + $this.text() + '</span>');
        });

    });

});

5 Comments

Interesting, I hadn't heard of the .load() function before. +1 for clean answer.
@MikeBlouin Yeah, the new design for the jQuery API makes it not quite so painful to browse: api.jquery.com - I'm always finding something that is easier than my original solution...
This is working great! However the pagination links are not getting updated. How do I make it so the pagination updates?
@user1985705 Hmm, that would require either a couple of cascading changes to the example above, or you would need add and remove the appropriate markup in jQuery. How about you try the second option yourself for a bit, and if you can't get it I will gladly amend my answer.
I am stuck. I am getting duplicate copies of my header and footer.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.