Skip to content.

A Note About Website Navigation

Skip to main menu.

For users of screen readers, depending on the screen resolution, the two checkboxes are for opening and closing the side menus that appear to the left and right side of the screen. This is designed both for large screens and for mobile devices with a touch screen. Checking either the main menu or sidebar checkboxes causes the menu to open from the left or right side of the screen, respectively. Clearing the checkox in either the main menu or sidebar closes the menu. The checkboxes are visible to screen readers such as JAWS and NVDA for Windows, Voiceover for Mac, and Orca screen reader for Linux. When a screen reader says "clickable" for both main menu and sidebar, that is for the respective checkboxes. End of explaination.

Viewing Single Blog Post

New Addition to my Website: Pagination (ClassicPress)

As a web developer of my website, I have implemented pagination that allows anyone to view more posts by page and be able to view blog posts by month and year. I created a custom theme from scratch so that I can personalize my website to my liking. I wanted to give the pagination system an "electronic" look.

Pagination along with month and year for my website
This screenshot shows pagination implemented in my website. In my development machine, I have set the number of posts per page to 5 in order to demonstrate the effect. I blurred the surrounding image to cut the file size by half.

For those with eyesight, you can click in the image to see a full screen of my desktop that shows the pagination system in effect.

Here's the code if any web developers want to implement it into their WordPress/ClassicPress website. I grabbed and modified the code from the kriesi.at website and once I got it done, I then wanted to add a month/year functionality into my pagination system. Even though I did seek help from the ClassicPress forum in my thread regarding getting the latest archive in an array instead of a link, I was able to do it myself with the help of this webpage that contained the function called wp_get_archives(). Here is a code taken from the wordpress.org site.

if ( 'monthly' == $r['type'] ) {
    $query = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`,"
        ." count(ID) as posts FROM $wpdb->posts $join $where"
        ." GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date $order $limit";
    $key = md5( $query );
    $key = "wp_get_archives:$key:$last_changed";
    if ( ! $results = wp_cache_get( $key, 'posts' ) ) { 
        $results = $wpdb->get_results( $query );
        wp_cache_set( $key, $results, 'posts' );
    }   
    if ( $results ) { 
        $after = $r['after'];
        foreach ( (array) $results as $result ) { 
            $url = get_month_link( $result->year, $result->month );
            /* translators: 1: month name, 2: 4-digit year */
            $text = sprintf( __( '%1$s %2$d' ), $wp_locale->get_month( $result->month ), $result->year );
            if ( $r['show_post_count'] ) { 
                $r['after'] = ' (' . $result->posts . ')' . $after;
            }
            $output .= get_archives_link( $url, $text, $r['format'], $r['before'], $r['after'] );
        }   
    }   
}

So I looked over the code and I saw that there is a $result variable that is converted into an array. I took that code from the WordPress.org website and I modified the code to suit my needs in functions.php inside my custom theme folder.

function monthly_archive_array() {
    global $wpdb;
    $r['type'] = 'monthly';
    $where = apply_filters( 'getarchives_where',
        "WHERE post_type = 'post' AND post_status = 'publish'", $r );

    $last_changed = wp_cache_get( 'last_changed', 'posts' );
    if ( ! $last_changed ) {
        $last_changed = microtime();
        wp_cache_set( 'last_changed', $last_changed, 'posts' );
    }

    /**
     * Filter the SQL JOIN clause for retrieving archives.
     *
     * @since 2.2.0
     *
     * @param string $sql_join Portion of SQL query containing JOIN clause.
     * @param array  $r        An array of default arguments.
     */
    $join = apply_filters( 'getarchives_join', '', $r );
    
    $query = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date ASC";
    $key = md5( $query );
    $key = "wp_get_archives:$key:$last_changed";
    if ( ! $results = wp_cache_get( $key, 'posts' ) ) {
        $results = $wpdb->get_results( $query );
        wp_cache_set( $key, $results, 'posts' );
    }
    if ( $results ) {
        return (array)$results;
    }
}

$archiveMonthlyList = monthly_archive_array();

function get_monthly_archive_array() {
    global $archiveMonthlyList;
    return $archiveMonthlyList;
}

Note that in the last 6 lines of code, I decided to have a function (get_monthly_archive_array()) get the result from a variable ($archiveMonthlyList). When I go to my website, ClassicPress executes a functions.php file in my custom theme folder so that I don't get the data from the database twice. Yet I actually do have wp_get_archives() in my sidebar, so I did have my website execute the same SQL statement twice. Well, one is in descending order from the newest to the oldest in the sidebar and I wanted to get the month and year of all the published posts from oldest to newest. If I replace the built-in function in my sidebar with my own function which exposes an array, I should be able to improve performance for my website, although probably not by much.

function constructLinkFromYearMonth($array, $index, $nextMonth) {
    $offset = ($nextMonth === true) ? 1 : -1;
    $spanlsaquote =  ($offset === -1) ? "<span class='visualonly'>‹ </span>" : "";
    $spanrsaquote =  ($offset ===  1) ? "<span class='visualonly'> ›</span>" : "";
    $prevNextMonth = ($offset === -1) ? "Previous" : "Next";
    echo "<a href='".get_month_link($array[$index + $offset]->year,$array[$index + $offset]->month )
        ."'>".$spanlsaquote."<span class='screenreader'>".$prevNextMonth." month: </span><span class='narrow-screen'>"
        .showMonthYearLocale(
        [$array[$index + $offset]->year,$array[$index + $offset]->month])."</span>".$spanrsaquote."</a>";
}

function show_pagination() {
    global $paged;
    if(empty($paged)) $paged = 1;
    
    global $wp_query;
    $pages = $wp_query->max_num_pages;
    if(!$pages)
    {
        $pages = 1;
    }

    echo "<div class='pagination'>";
    echo "<h3>View More Posts By Month or Page</h3>";
    echo "<div class='pagination_area'>";

    echo "<div class='pagination_top'>";

    // Get the list of months and years from the archive in an array.
    $monthlyArchive = get_monthly_archive_array();
    // If there is year/month in URL, get it and trim the leading and
    // trailing slashes. Example: 2021/04
    $currentMonthYear = trim($_SERVER['REQUEST_URI'],'/');
    // array[0] = year, array[1] = month
    // Example: array[0] = "2021", array[1] = "04"
    $curMonthYearArray = explode('/',$currentMonthYear);
    if(preg_match("/^[0-9]{4}\/(0[1-9]|1[0-2])$/",$curMonthYearArray[0].'/'.$curMonthYearArray[1])) {
        // array[0] = year, array[1] = month
        // Example: array[0] = "2021", array[1] = "04"
        $curMonthYearArray = explode('/',$currentMonthYear);
        // Initialize a blank array for integers.
        $intCurMonthYearArray = Array();
        // Convert strings to integers in an array in a new variable.
        foreach($curMonthYearArray as $curMonthYear)
            $intCurMonthYearArray[] = (int)$curMonthYear;
        // Initialize the integer for the index.
        $indexOfMonthYearArray = 0;
        foreach ($monthlyArchive as $key => $val) {
           if ((int)$val->year === $intCurMonthYearArray[0] &&
               (int)$val->month === $intCurMonthYearArray[1]) {
               $indexOfMonthYearArray = $key;
           }
        }

        echo "<ul class='pagination_month'>";
        echo "<li class='month_current'>";
        echo "<span>".showMonthYearLocale($curMonthYearArray)."</span>";
        echo "</li>";
        if($indexOfMonthYearArray > 0) {
            echo "<li class='month_prev'>";
            constructLinkFromYearMonth($monthlyArchive, $indexOfMonthYearArray, false);
            echo "</li>";
        } else echo "<li class='month_prev smallfontsize'><a class='screenreader'>Beginning of current month</a></li>";
        if($indexOfMonthYearArray + 1 < count($monthlyArchive)) {
            echo "<li class='month_next'>";
            constructLinkFromYearMonth($monthlyArchive, $indexOfMonthYearArray, true);
            echo "</li>";
        } else echo "<li class='month_next smallfontsize'><a class='screenreader'>End of current month</a></li>";
        echo "</ul>";
    } else {
        $latest = $monthlyArchive[count($monthlyArchive) - 1];
        echo "<div class='pagination_month msg'><span>View latest posts since "
            ."<a class='date-narrow' href='".get_month_link($latest->year,$latest->month )
            ."'>".showMonthYearLocale([$latest->year,$latest->month])."</a>.</span></div>";
    }

    echo "</div>";

    if(1 != $pages)
    {
        echo "<div class='pagination_bottom'>";
        echo "<div class='pagination_prevbtns'>";
        if($paged > 2)
            echo "<a href='".get_pagenum_link($paged - 2)."'>«</a>";
        else echo "<a class='visualonly pagination_disbtn'>«</a>";
        if($paged > 1)
            echo "<a class='pageprev' href='".get_pagenum_link($paged - 1)."'>‹</a>";
        else echo "<a class='pageprev visualonly pagination_disbtn'>‹</a>";
        echo "</div>";

        echo "<ul class='pagination_slot'>";
        for ($i=1; $i <= $pages; $i++)
        {
            echo "<li>";
            echo ($paged == $i)? "<a class='pagination_number current'><span class='screenreader'>Current Page: </span>".$i."</a>":"<a href='".get_pagenum_link($i)."' class='pagination_number' >".$i."</a>";
            echo "</li>";
        }
        echo "</ul>";

        echo "<div class='pagination_nextbtns'>";
        if ($paged < $pages)
            echo "<a class='pagenext' href='".get_pagenum_link($paged + 1)."'>›</a>";  
        else echo "<a class='pagenext visualonly pagination_disbtn'>›</a>";
        if ($paged < $pages-1)
            echo "<a href='".get_pagenum_link($paged + 2)."'>»</a>";
        else echo "<a class='visualonly pagination_disbtn'>»</a>";
        echo "</div></div></div></div>\n";
    } else {
        echo "<div class='pagination_bottom'>";
        echo "<div class='pagination_prevbtns'>";
        echo "<a class='visualonly pagination_disbtn'>«</a>";
        echo "<a class='pageprev visualonly pagination_disbtn'>‹</a>";
        echo "</div>";
        echo "<div class='pagination_slot msg'><span class='nopages'>Only 1 page shown.</span></div>";
        echo "<div class='pagination_nextbtns'>";
        echo "<a class='pagenext visualonly pagination_disbtn'>›</a>";
        echo "<a class='visualonly pagination_disbtn'>»</a>";
        echo "</div></div></div></div>\n";
    }
    
}

function monthly_archive_array() {
    global $wpdb;
    $r['type'] = 'monthly';
    $where = apply_filters( 'getarchives_where',
        "WHERE post_type = 'post' AND post_status = 'publish'", $r );

    $last_changed = wp_cache_get( 'last_changed', 'posts' );
    if ( ! $last_changed ) {
        $last_changed = microtime();
        wp_cache_set( 'last_changed', $last_changed, 'posts' );
    }

    /**
     * Filter the SQL JOIN clause for retrieving archives.
     *
     * @since 2.2.0
     *
     * @param string $sql_join Portion of SQL query containing JOIN clause.
     * @param array  $r        An array of default arguments.
     */
    $join = apply_filters( 'getarchives_join', '', $r );
    
    $query = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date ASC";
    $key = md5( $query );
    $key = "wp_get_archives:$key:$last_changed";
    if ( ! $results = wp_cache_get( $key, 'posts' ) ) {
        $results = $wpdb->get_results( $query );
        wp_cache_set( $key, $results, 'posts' );
    }
    if ( $results ) {
        return (array)$results;
    }
}

$archiveMonthlyList = monthly_archive_array();

function get_monthly_archive_array() {
    global $archiveMonthlyList;
    return $archiveMonthlyList;
}

The reason why I decided to remove the range variable is so I want viewers in mobile devices to be able to scroll through pages horizontally (left/right). Of course, for desktop users I could add some JavaScript code that allows me to add/remove numbers based on the current page number and based on the width of the web browser. However, I am a heavy proponent of not using JavaScript whenever possible. I want everyone without JavaScript or for those such as me who use NoScript to enjoy the full potential of my website.

Web development is hard work, but at the end of the day, I enjoyed it a lot. Thanks for reading and enjoy visiting my site!

And note to self: I need to encode HTML code even if it's inside a <pre> tag before I break my website when publishing my post. Don't forget to do the same if you are a web developer as well. Use &lt; for < and &gt; for >. You can also use &quot; for " as well. View the source code for my post to see what I did. In Firefox, open the context menu and choose "View Page Source." Same goes for Google Chrome.

Updated as of July 3, 2021 at 12:44 AM: Added <wbr /> tag to a long function in order to break the function into two lines. This is useful for mobile devices. All today's mobile devices should support HTML5 by now.


Article published: 2021-05-01 08:57

Categories: The World of Computers, Scripting and Programming,

About Grayson Peddie

Hello! I am a web developer and I have a passion for the world of Information Technology. I currently hold 4 CompTIA certificates (A+, Network+, Security+, and CySA+) including Cisco's CCNA (Cisco Certified Network Associate) certificate. Speaking of web development, I am a web accessibility enthusiast. I make sure that users of screen readers and keyboard users who cannot use a mouse can be able to access my website with just only the keyboard. Plus, I have learned a whole lot about Web Content Accessibility Guidelines.

So what are my hobbies? Aside from web development, I watch Star Trek: The Next Generation from time to time during the nights. I listen to music from the likes of David Arkenstone, Yanni, Checkfield, Cucso, Looreena McKennitt, Clannad, 2002, Enya, and even soundtrack from EPCOT Center (1982-1994), Tomorrowland, WALL-E, and TRON: Legacy. Oh, yes! Tomorrowland, TRON: Legacy, and WALL-E are the three movies I watch during Friday nights and every Friday night is my pizza night. I'm an optimist who likes to see what kind of future the world would look like. That's why I follow The Venus Project on Twitter (here's the website to The Venus Project. I do have a lot to cover in my introductory article in my website, so if you want to go in-depth and know more about me, that is the article to visit.