Skip to content

Digg Style Pagination Non evasive aproach

Derek Jones edited this page Jul 5, 2012 · 16 revisions

Category:Libraries

Digg Style Pagination, Based on woopsicle's article

First of all thanks to woopsicle for making the first article. If you didnt read his article please do, it may suit your needs better than this one. I personally liked it very much and helped a lot, but i wanted a different approach that didn't change the way the default CodeIgniter lib works, and I didn't have to replace any CI core files which is a pain when updating CI. Furthermore i optimized the code a bit.

The only thing needed is to create a file named MY_Pagination.php and place it under the application/libaries folder so it gets loaded automatically when the Pagination library is loaded. Open that file and copy/paste the following code:

<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
 * CodeIgniter
 *
 * An open source application development framework for PHP 4.3.2 or newer
 *
 * @package        CodeIgniter
 * @author        ExpressionEngine Dev Team
 * @copyright    Copyright (c) 2006, EllisLab, Inc.
 * @license        http://codeigniter.com/user_guide/license.html
 * @link        http://codeigniter.com
 * @since        Version 1.0
 * @filesource
 */

// ------------------------------------------------------------------------

/**
 * Pagination Class
 *
 * @package        CodeIgniter
 * @subpackage    Libraries
 * @category    Pagination
 * @author        ExpressionEngine Dev Team
 * @link        http://codeigniter.com/user_guide/libraries/pagination.html
 */
class MY_Pagination extends CI_Pagination
{
    // --------------------------------------------------------------------
    
    /**
     * Generate the pagination links
     *
     * @access    public
     * @return    string
     */    
    function create_links()
    {
        // If our item count or per-page total is zero there is no need to continue.
        if ($this->total_rows == 0 OR $this->per_page == 0)
        {
           return '';
        }

        // Calculate the total number of pages
        $num_pages = ceil($this->total_rows / $this->per_page);

        // Is there only one page? Hm... nothing more to do here then.
        if ($num_pages == 1)
        {
            return '';
        }

        // Determine the current page number.        
        $CI =& get_instance();    
        $get_page = array('page');
        $page_num = $CI->uri->uri_to_assoc($this->uri_segment, $get_page);

        if ($page_num['page'] != FALSE)
        {
            $this->cur_page = $page_num['page'];
            
            // Prep the current page - no funny business!
            $this->cur_page = (int) $this->cur_page;
        }

        $this->num_links = (int)$this->num_links;
        
        if ($this->num_links < 1)
        {
            show_error('Your number of links must be a positive number.');
        }
                
        if ( ! is_numeric($this->cur_page))
        {
            $this->cur_page = 0;
        }
        
        // Is the page number beyond the result range?
        // If so we show the last page
        if ($this->cur_page > $this->total_rows)
        {
            $this->cur_page = ($num_pages - 1) * $this->per_page;
        }
        
        $uri_page_number = $this->cur_page;
        $this->cur_page = floor(($this->cur_page/$this->per_page) + 1);

        // Calculate the start and end numbers. These determine
        // which number to start and end the digit links with
        $start = (($this->cur_page - $this->num_links) > 0) ? $this->cur_page - ($this->num_links - 1) : 1;
        $end   = (($this->cur_page + $this->num_links) < $num_pages) ? $this->cur_page + $this->num_links : $num_pages;

        // Add a trailing slash to the base URL if needed
        $this->base_url = rtrim($this->base_url, '/') .'/';

          // And here we go...
        $output = '';

        /* Render the "First" link (Optional)
        if  ($this->cur_page > $this->num_links)
        {
            $output .= $this->first_tag_open.'<a >base_url.'">'.$this->first_link.'</a>'.$this->first_tag_close;
        }
        */
        
        // Render the "previous" link
        if  ($this->cur_page != 1)
        {
            $i = $uri_page_number - $this->per_page;
            if ($i == 0) $i = '';
            $output .= $this->prev_tag_open.'<a >base_url.$i.'">'.$this->prev_link.'</a>'.$this->prev_tag_close;
        } 
        else
        {
            $output .= '<span class="disabled">'.$this->prev_link.'</span>';
        }
    
        
        //not enough pages to bother breaking it up
        if ($num_pages < 7 + ($this->num_links * 2))   
        {
            $output .= $this->pages_loop($start-1,$end);
        }
        //enough pages to hide some
        elseif($num_pages > 5 + ($this->num_links * 2))    
        {
            //Prepare First pages string
            $first_pages = $this->num_tag_open.'<a >base_url.'">1</a>'.$this->num_tag_close;
            $first_pages .= $this->num_tag_open.'<a >base_url.'page/'.$this->per_page.'">2</a>'.$this->num_tag_close;
            $first_pages .= "...";
            
            //Prepare Second pages string
            $num_pages_minus = $num_pages-1;
            $last_page_url = (($num_pages * $this->per_page) - $this->per_page);
            $secondlast_page_url = ($last_page_url - $this->per_page);
            $second_pages = "...";
            $second_pages .= $this->num_tag_open.'<a >base_url.'page/'.$secondlast_page_url.'">'.$num_pages_minus.'</a>'.$this->num_tag_close;
            $second_pages .= $this->num_tag_open.'<a >base_url.'page/'.$last_page_url.'">'.$num_pages.'</a>'.$this->num_tag_close;
        
            //close to beginning; only hide later pages
            if($this->cur_page < 1 + ($this->num_links * 2))
            {
                $output .= $this->pages_loop(1,3 + ($this->num_links * 2));
                
                $output .= $second_pages;   
            }
            //in middle; hide some front and some back
            elseif($num_pages - ($this->num_links * 2) > $this->cur_page && $this->cur_page > ($this->num_links * 2))
            {
                $output .= $first_pages;
                
                $output .= $this->pages_loop($this->cur_page - $this->num_links,$this->cur_page + $this->num_links);
                
                $output .= $second_pages;
            }
            //close to end; only hide early pages
            else
            {
                $output .= $first_pages;
                
                $output .= $this->pages_loop($num_pages - (2 + ($this->num_links * 2)),$num_pages);
            }
        }

        // Render the "next" link
        if ($this->cur_page < $num_pages)
        {
            $output .= $this->next_tag_open.'<a >base_url.($this->cur_page * $this->per_page).'">'.$this->next_link.'</a>'.$this->next_tag_close;
        } 
        else
        {
            $output .= '<span class="disabled">'.$this->next_link.'</span>';
        }

        /* Render the "Last" link (Optional)
        if (($this->cur_page + $this->num_links) < $num_pages)
        {
            $i = (($num_pages * $this->per_page) - $this->per_page);
            $output .= $this->last_tag_open.'<a >base_url.$i.'">'.$this->last_link.'</a>'.$this->last_tag_close;
        }
        */
        
        // Kill double slashes.  Note: Sometimes we can end up with a double slash
        // in the penultimate link so we'll kill all double slashes.
        $output = preg_replace("#([^:])//+#", "\\1/", $output);

        // Add the wrapper HTML if exists
        $output = $this->full_tag_open.$output.$this->full_tag_close;
        
        return $output;        
    }
    
    function pages_loop ($start,$end) 
    {
        $output = "";
        
        for ($loop = $start; $loop <= $end; $loop++)
        {
            $i = ($loop * $this->per_page) - $this->per_page;
            
            if ($i >= 0)
            {
                if ($loop == $this->cur_page)
                {
                    $output .= $this->cur_tag_open.$loop.$this->cur_tag_close; // Current page
                }
                else
                {
                    $n = ($i == 0) ? '' : 'page/'.$i;
                    $output .= $this->num_tag_open.'<a >base_url.$n.'">'.$loop.'</a>'.$this->num_tag_close;
                }
            }
        }
        
        return $output;
    
    }

}
?&gt;

This will replace the create_links() function that the Pagination library uses to generate the page links. You're done! You now have Digg like functionality in the pagination. It will work exactly the same as the default lib so you don't have to change anything.

If you want to add the look, you can create a css file with the code that woopsicle kindly provided:

div.pagination
{
    padding: 3px;
    margin: 3px;
}

div.pagination a
{
    padding: 2px 5px 2px 5px;
    margin: 2px;
    border: 1px solid #AAAADD;
    text-decoration: none; /* no underline */
    color: #000099;
}

div.pagination a:hover, div.pagination a:active
{
    border: 1px solid #000099;
    color: #000;
}

div.pagination span.current
{
    padding: 2px 5px 2px 5px;
    margin: 2px;
    border: 1px solid #000099;
    font-weight: bold;
    background-color: #993300;
    color: #FFF;
}
div.pagination span.disabled
{
    padding: 2px 5px 2px 5px;
    margin: 2px;
    border: 1px solid #EEE;
    color: #DDD;
}

And then

<div class="pagination">
&lt;?=$this->pagination->create_links();?&gt;
</div>

Thats all, hope it helps. If you have anything to add/optimize please do.

Category:Contributions::Libraries::PHP

Clone this wiki locally