Site Pagination


This is the evolution of this site's pagination navigation from the simple HTML navigation of 1999, to the JavaScript version in 2005 and then to the redesign in 2021.


Ever since the site was first created in 1999 there has been content that didn't fit onto one page. Pages that were part of the multipage content were named, for example, bemmy1.htm, bemmy2.htm and so on, and then the main site menu and submenus were written with each page as below.

Menu from the original site design

Above, part of the main site menu from 1999 including the awful colors that were used. Below, the Bedminister menu from the Bristol section of the site.

Menu from the original site design


In 2005, one way in which I decided to try and improve navigation around the site was to include a menu at the bottom of the pages that are a continuation of another. For example, the "Postcards" section of "Terre Haute" contained 11 pages, the "Castle" section of "Bristol, England' contained 6 pages.

What I wanted was a system where a single piece of JavaScript could write a menu showing the number of pages in the section, with links and also have links for the first, previous, next and last pages. What I came up with looks like this...

Example Multi-Page Menu

Example Multi-Page Menu
Image from Terre Haute > Postcards, page 6


I've seen menu's like this on other sites but in this case decided simply to write my own.

What I came up with is...

function multipage(){

var path = location.pathname;
path = path.replace(/\\/g, '/');
var fullName = ""
var fileName = path.substring(path.lastIndexOf('/')+1);
var numStart =\d/);
var numEnd = fileName.indexOf('.');
var pageNum = fileName.substring(numStart,numEnd);
var firstPart = fileName.substring(0, numStart);

case "tpcards" :
   fullName = "Postcards";
case "bcastle" :
   fullName = "Bristol Castle";

document.write('<p class="ctr">' + fullName + ': ');

   document.write(''<a href="' + firstPart + '1.htm">First'</a>');
   document.write(' '<a href="' + firstPart + (pageNum-1) + '.htm">Prev.'</a>');
   document.write(' Prev.');

      document.write(' '<a href="' + firstPart + cnt + '.htm">' + cnt + ''</a>');
      document.write(' ' + cnt);

   document.write(' '<a href="' + firstPart + (++pageNum) + '.htm">Next'</a>');
   document.write(' '<a href="' + firstPart + maxPages + '.htm">Last'</a>');
   document.write(' Next');
   document.write(' Last');



location.pathname is used to obtain the path from the root and the current document name. For example, /th/tpcards6.htm

path = path.replace(/\\/g, "/"); is for when the site is on a CD or hard drive. What this code does is replace all the instances of "\" in the path name and changes them to a "/". This is the regular expression form of replace that is capable of changing all the looked for characters in a string.

path.substring(path.lastIndexOf('/')+1); looks for the last instance of the substring "/" in the variable named path. and returns the position number from the left. The first character of a string starts at position 0. ie lastIndexOf() starts the search from the right of the string. In this instance it's extracting the filename from the full path.\d/); looks for any numeral in the string variable fileName and returns its position number. This is a regular expression, where \d means digit. \d\d would look for a substring of two digits. Because each of the files is named to a convention ie tpcards1.htm, tpcards2.htm etc. it's picking out the position at where the digits start. In tpcards12.htm it would return the position of the first digit it finds. In all these examples it would return the number 7.

fileName.indexOf('.'); looks for the first instance of the substring "." in the variable named fileName and returns the position number from the left. The first character of a string starts at position 0. ie IndexOf() starts the search from the left of the string. In tpcards1.htm it would return 8, in tpcards12.htm it would return 9.

fileName.substring(numStart,numEnd); uses the previous two searches to extract the number in the file name. In tpcards1.htm it would return 1, in tpcards12.htm it would return 12.

fileName.substring(0, numStart);  extracts the first part of the filename. In tpcards1.htm and tpcards12.htm it returns "tpcards"

The switch function makes the last extracted string more human readable. For example, tpcards is pretty meaningless so it makes sure it is associated with "Postcards". Because JavaScript can't search for the number of pages in a section (it has no server file search facilities) the number of files in a section has to be hard coded.

The final part of the code simply writes the links and page numbers to the HTML page. The actual page numbers are inserted using a FOR loop

Calling the function

The JavaScript function can be called by using any of the standard techniques. Because the code is used on several pages on the site I put the function in the main JS file for the site, brisray.js

The pages have to be told where this file is. This is done by putting <script type="text/javascript" src="../common/brisray.js" language="javascript"></script> in the HEAD section of each page.

Where the menu is to appear in the BODY of the page the following code is used...

<script language="JavaScript" type="text/javascript">


The site is now 22 years old and had 3 design changes since the original. Those have been mostly because in the original site the colours were awful and I didn't separate all the CSS from the HTML properly and the other two because I wasn't happy with it, mostly because of the main navigation. Over the years the web pages that make up the site have been getting shorter. This has mostly been because I started using things like Fancybox, version 2 or lately version 3 to use an image lightbox rather than display full-size images directly on the page. Another reason some pages have gotten shorter is that I've started using Prism code highlighter in a div with max-height set. Even so, there are some parts of the site that need multiple pages for me to tell a story.

One thing that hasn't changed is the 2005 pagination JavaScript code. The last site redesign started in December 2019 but it wasn't until January 2021 that I seriously looked at the pagination. The principles of pagination have not changed much in 15 years, compare Pagination – Examples And Good Practices (2007) by Sven Lennartz with Best Practices for Designing Pagination in Web (2017) by Abhishek Jain.

Some things about JavaScript, the way it is used, how it handles the path, and how functions are called have changed. The mime type text/javascript is no longer required in the script tag. When calling functions they no longer need to be wrapped in <!-- and --> tags.

Windows File Explorer displays displays file paths with backslashes such as C:\Users\Documents\Websites\brisray\utils. When opening files locally most modern browsers change the backslashes to forwardslashes such as file:///C:/Users/Documents/Websites/brisray/utils/pagination.htm (Chrome v88, Edge v88, Firefox v85, Opera v74). The only modern browser that does not is Internet Explorer for Windows 10 which still displays C:\Users\Documents\Websites\brisray\utils\pagination.htm. The good news is that all of them, even Internet Explorer, returns forwardslashes from JavaScript's window.location.pathname. For an explanation of the forwardslash/backslash thing see Why Windows Uses Backslashes and Everything Else Uses Forward Slashes by Chris Hoffman.

As I use simple naming system such as bemmy1, bemmy2, ... for the multiple pages in a particualr section, what the JavaScript needs to do is:

CSS styled button-like elements look attractive and are easy to use. JavaScript can take care of how many page selectors to draw and which page the user is on. I like the idea of using first, previous, next and last buttons, as well as highlighting the current page button.

What I came up with looks like this:

Menu from the original site design

The basic 2021 pagination design
The current page is in light blue and hovered link is grey

The JavaScript used looks like this:

function pagination(){
   var url = window.location.href;
   var filename = url.split("/").pop();
   var fileParts = filename.split(".");
   var firstPart = fileParts[0];
   var secondPart = fileParts[1];
   var activePage = Number(firstPart.match(/\d+/));
   var textOnly = firstPart.match(/\D+/).toString();
   var fullName = "";
   var maxPages = 0;
   var fileSection = textOnly.toLowerCase();
   case "stgeorge" :
      fullName = "St. George";
      maxPages = 4;


" + fullName + ":

"); if (activePage>1){ var firstLink = "<p><a href='" + textOnly + "1." + secondPart +"'>First</a>"; document.write(firstLink); var prevLink = "<a href='" + textOnly + (activePage-1) + "." + secondPart +"'>Previous</a>"; document.write(prevLink);} else { firstLink = "<p><a class='active'>First</a>"; document.write(firstLink); prevLink = "<a class='active'>Previous</a>"; document.write(prevLink);} var i = 0; for (i=1; i<=maxPages; i++ ){ if (i!== activePage){ document.write("<a href='" + textOnly + i + "." + secondPart +"'>" + i + "</a>"); } else { document.write("<a class='active'>" + i + "</a>");} } if (activePage<maxPages){ var nextLink = "<a href='" + textOnly + (activePage+1) + "." + secondPart +"'>Next</a>"; document.write(nextLink); var lastLink = "<a href='" + textOnly + maxPages + "." + secondPart +"'>Last</a></p>"; document.write(lastLink);} else { var nextLink = "<a class='active'>Next</a>"; document.write(nextLink); var lastLink = "<a class='active'>Last</a></p>"; document.write(lastLink);} }

The CSS for the menu is:

#pagination {text-align: center;}
#pagination a {
	text-decoration: none;
	padding: 0.6em 0.8em;
	background-color: #ffe4c4;
	border-radius: .6em;
	margin: .1em;
	display: inline-block;
	font-weight: bold;

#pagination .active {background-color: #ddd;}
#pagination a:hover:not(.active) {background-color: #00FFBF;}


8 Rules for Perfect Button Design
Best Practices for Designing Pagination in Web
How to Get Current URL in JavaScript
JavaScript - String Object - String functions and regular expressions
Object: Document - Document objects and properties (Internet Archive)
Optimal Size and Spacing for Mobile Buttons
Pagination – Examples And Good Practices
Parsing the Querystring with JavaScript - Location and document objects and properties
Strings in JavaScript - String functions
Using Regular Expressions with JavaScript and ECMAScript - Regular expressions

This page created October 19, 2005; last modified July 18, 2021