HTML Pager Finished

After quite a while, I’m back on the blog with another post. This time I managed to implement a simple but complete pager. All you need to pass to it are the IDs and how many items per page you want. Originally I had a pager that could only be used once. That was because it generated a JScript call for every page and then inserted it at the bottom into the paging.

I’m sure you can imagine what the problem with that was – of course, when there were a lot of pages, they were all displayed in a table at the bottom. Yuck! That’s why the IDs were passed to it – today it would be enough to pass it just the number of pages, which this pager works with internally anyway, because it calculates it itself. Now that I’m migrating my websites from an SQLite DB to an SQL Server DB, I’m fixing what didn’t work or finishing what worked poorly. To give you an idea of how it works, here is the source code of the pager class:

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// Class that generates paging.
/// </summary>
public class HtmlPagingGenerator //: HtmlGenerator
{
    public List<int[]> pages = new List<int[]>();
    int pageCount = -1;
    public HtmlPagingGenerator(List<int> ids, int itemsPerPage) //string _dotaz,
    {
        int count = ids.Count;
        if (count == 0)
        {
            return;
        }
        int fullPages = (count / itemsPerPage);
        int startAt = 0;
        int i = 0;
        while (true)
        {
            if (i == fullPages)
            {
                itemsPerPage = count % itemsPerPage;
            }
            if (i == fullPages + 1)
            {
                break;
            }
            i++;
            int[] nt = new int[itemsPerPage];
            ids.CopyTo(startAt, nt, 0, itemsPerPage);
            pages.Add(nt);
            pageCount++;
            startAt += itemsPerPage;
        }
    }
    private HtmlPagingGenerator()
    {
        // TODO: Complete member initialization
    }
    /// <summary>
    /// A1 numbering starts at 1
    /// </summary>
    /// <param name="currentPage" />
    /// <returns> </returns>
    public string ReturnPage(int currentPage)
    {
        int lastIndex = pages.Count - 1;
        if (currentPage < 0 && currentPage > lastIndex)
        {
            return "Invalid paging values, probably an internal application error";
        }
        return Render(currentPage, pageCount);
    }
    /// <summary>
    /// A1 numbering starts at 1.
    /// </summary>
    /// <param name="currentPage" />
    /// <param name="showBefore" />
    /// <param name="showNext" />
    /// <returns> </returns>
    public string Render(int currentPage, int pageCount)
    {
        if (pageCount != 0)
        {
            int currentPageIndex = currentPage - 1;
            bool showBefore = currentPageIndex != 0;
            bool showNext = currentPageIndex != pageCount - 1;
            //-The dots here will be separated by spaces, or no, they won't, but one ellipsis will count as 3 characters
            //-The maximum number of characters will be 29
            int remainingCharsTotal = 29;
            int remainingCharsLeft = 0;
            int remainingCharsRight = 0;
            remainingCharsTotal -= currentPage.ToString().Length + 2;
            remainingCharsLeft = remainingCharsTotal / 2;
            remainingCharsRight = remainingCharsTotal / 2;
            List<int> pagesLeft = new List<int>();
            List<int> pagesRight = new List<int>();
            if (currentPage != 1)
            {
                for (int i = currentPage - 1; i > 0; i--)
                {
                    int nextLength = i.ToString().Length + 1;
                    if (remainingCharsLeft - nextLength > -1)
                    {
                        pagesLeft.Add(i);
                        remainingCharsLeft -= nextLength;
                    }
                    else
                    {
                        break;
                    }
                }
            }
            remainingCharsRight = remainingCharsRight + remainingCharsLeft;
            for (int i = currentPage + 1; i < pageCount + 1; i++)
            {
                int nextLength = i.ToString().Length + 1;
                if (remainingCharsRight - nextLength > -1)
                {
                    pagesRight.Add(i);
                    remainingCharsRight -= nextLength;
                }
                else
                {
                    break;
                }
            }
            if (pagesLeft.Count != 0)
            {
                remainingCharsLeft = remainingCharsRight + remainingCharsLeft;
                for (int i = pagesLeft[pagesLeft.Count - 1] - 1; i > 1; i--)
                {
                    int nextLength = i.ToString().Length + 1;
                    if (remainingCharsLeft - nextLength > -1)
                    {
                        pagesLeft.Add(i);
                        remainingCharsLeft -= nextLength;
                    }
                    else
                    {
                        break;
                    }
                }
            }
            HtmlGenerator htmlGenerator = new HtmlGenerator();
            string textBeforeRapid = string.Empty;
            string textBefore = string.Empty;
            if (showBefore)
            {
                textBeforeRapid = " < <";
                textBefore = " <";
            }
            else
            {
                textBeforeRapid = "  ";
                textBefore = " ";
            }
            string textNextRapid = string.Empty;
            string textNext = string.Empty;
            if (showNext)
            {
                textNextRapid = ">>";
                textNext = ">";
            }
            else
            {
                textNextRapid = "  ";
                textNext = " ";
            }
            if (showBefore)
            {
                htmlGenerator.WriteTagWithAttr("div", "class", "prev");
                htmlGenerator.WriteTagWithAttrs("a", "runat", "server", "id", "anchorPrevRapid", "href", "javascript:", "onclick", "VypsatVysledkyNaStrance(" + 1 + ");return false;");
                htmlGenerator.WriteRaw(textBeforeRapid);
                htmlGenerator.TerminateTag("a");
                htmlGenerator.TerminateTag("div");
                htmlGenerator.WriteTagWithAttr("div", "class", "prev");
                int to = currentPage - 1;
                if (to < 1)
                {
                    to = 1;
                }
                htmlGenerator.WriteTagWithAttrs("a", "runat", "server", "id", "anchorPrev", "href", "javascript:", "onclick", "VypsatVysledkyNaStrance(" + to + ");return false;");
                htmlGenerator.WriteRaw(textBefore);
                htmlGenerator.TerminateTag("a");
                htmlGenerator.TerminateTag("div");
            }
            pagesLeft.Reverse();
            foreach (int item in pagesLeft)
            {
                AppendAnchor(htmlGenerator, true, item);
            }
            AppendAnchor(htmlGenerator, false, currentPage);
            foreach (int item in pagesRight)
            {
                AppendAnchor(htmlGenerator, true, item);
            }
            if (showNext)
            {
                htmlGenerator.WriteTagWithAttr("div", "class", "next");
                htmlGenerator.WriteTagWithAttrs("a", "runat", "server", "id", "anchorRapid", "href", "javascript:", "onclick", "VypsatVysledkyNaStrance(" + pageCount + ");return false;");
                htmlGenerator.WriteRaw(textNextRapid);
                htmlGenerator.TerminateTag("a");
                htmlGenerator.TerminateTag("div");
                htmlGenerator.WriteTagWithAttr("div", "class", "next");
                htmlGenerator.WriteTagWithAttrs("a", "runat", "server", "id", "anchorNext", "href", "javascript:", "onclick", "VypsatVysledkyNaStrance(" + (currentPage + 1).ToString() + ");return false;");
                htmlGenerator.WriteRaw(textNext);
                htmlGenerator.TerminateTag("a");
                htmlGenerator.TerminateTag("div");
            }
            return htmlGenerator.ToString();
        }
        return "";
    }
    private static int AppendAnchor(HtmlGenerator htmlGenerator, bool clickable, int item)
    {
        if (clickable)
        {
            htmlGenerator.WriteTagWithAttrs("a", "href", "javascript:", "onclick", "VypsatVysledkyNaStrance(" + item + ");return false;", "class", "pagingB");
        }
        else
        {
            htmlGenerator.WriteTagWithAttr("span", "class", "pagingB");
        }
        htmlGenerator.WriteRaw(item.ToString());
        if (clickable)
        {
            htmlGenerator.TerminateTag("a");
        }
        else
        {
            htmlGenerator.TerminateTag("span");
        }
        htmlGenerator.WriteRaw(" ");
        return item;
    }
    /// <summary>
    /// Use this method when no results can be found
    /// </summary>
    /// <returns> </returns>
    public static string NothingFound()
    {
        HtmlPagingGenerator pagingGenerator = new HtmlPagingGenerator();
        return pagingGenerator.Render(1, 0);
    }
    /// <summary>
    /// Call this method only when all results fit on 1 page
    /// </summary>
    /// <returns> </returns>
    public static string WoPaging()
    {
        HtmlPagingGenerator pagingGenerator = new HtmlPagingGenerator();
        return pagingGenerator.Render(1, 0);
    }
}

Of course, this class won’t compile for you, because it uses some of my own classes. And finally, here is a picture of what it actually looks like:

HTML Pager Finished

Categories

Leave a Reply