Skip to content

Instantly share code, notes, and snippets.

@kingkool68
Last active January 4, 2018 21:27
Show Gist options
  • Save kingkool68/9277919 to your computer and use it in GitHub Desktop.
Save kingkool68/9277919 to your computer and use it in GitHub Desktop.
Plugin for handling the URLs to make infinite scrolling work properly on pages like this http://www.pewresearch.org/category/publications/
jQuery(document).ready(function() {
//Set-up some constants.
var scrollTimeout;
var scrollUsePushStateInstead = false; //Set to true to make the history stack of the browser include every point when posts were loaded. It's kind of annoying.
var scrollDelay = 200; //Milliseconds
var scrollLoading = false;
var triggerOffset = $(document).height() - $('#pagination').siblings().eq(-4).offset().top; //The point of this is to do one calculation up front instead of multiple calculations every time the infinite scroll is triggered.
// Simple feature detection for History Management (borrowed from Modernizr)
function supportsHistory() {
return !!(window.history && history.pushState);
}
if( supportsHistory() ) {
$(window).on('scroll', function() {
toInfinityAndBeyond();
});
}
//The function that does all of the work.
function toInfinityAndBeyond() {
if( scrollLoading ) {
return;
}
//if( scrollTrigger < $(document).scrollTop()) {
if( $(document).height() - triggerOffset < $(document).scrollTop() + $(window).height() ) {
var nextURL = $('#pagination').find('.next').eq(0).attr('href');
if( !nextURL ) {
return;
}
$.ajax({
type: 'GET',
url: nextURL,
beforeSend: function() {
// block potentially concurrent requests
scrollLoading = true;
},
success: function(data) {
$('#pagination').before( $(data).find('#content').html() ).remove();
var newPageNum = nextURL.match(/\/page\/(\d+)\//)[1];
regexp = /\/(pages?)\/([0-9]+)-?([0-9])*\/?$/;
var newPath = window.location.href;
if( regexp.test(newPath) ) {
parts = regexp.exec(newPath);
//Assign different parts to more understandable labels. Assume the following example: http://example.com/thing/pages/2-4/
matchingPattern = parts[0]; // -> /pages/2-4/
pageLabel = parts[1].toLowerCase(); // -> pages
pageStart = parts[2]; // -> 2
pageEnd = parts[3]; // -> 4
if( pageEnd > 0 && pageStart == 1 ) {
pageStart = pageEnd;
pageEnd = false;
}
var blackMagic = new RegExp(matchingPattern, 'ig');
//We're dealing with /pages/x-x/
replacement = '/pages/' + pageStart + '-' + newPageNum + '/';
if( !pageEnd ) {
//We're dealing /page/x/ or /pages/x/
replacement = '/pages/' + newPageNum + '/';
if( pageLabel == 'page' ) {
replacement = '/pages/' + pageStart + '-' + newPageNum + '/';
}
}
newPath = newPath.replace( blackMagic, replacement);
} else {
//There is no /page/ or /pages/ in the URL. We'll assume we can just append a new /pages/ path to the current URL.
newPath += 'pages/' + newPageNum + '/';
}
newPath = '/' + newPath.split('/').slice(3).join('/');
if( scrollUsePushStateInstead ) {
window.history.pushState(null, null, path);
} else {
window.history.replaceState(null, null, newPath);
}
// unblock more requests (reset loading status)
scrollLoading = false;
},
dataType: "html"
});
}
}
});
<?php
/*
Plugin Name: Pew Infinite Scroll
Description: "To infinity... and beyond!"
Author: Russell Heimlich
Author URI: http://www.russellheimlich.com/
Version: 0.1
*/
//Lets make rewrites work properly
//$pageregex = $this->pagination_base . '/?([0-9]{1,})/?$';
function pew_infinite_scroll_rewrite_rules() {
/*
global $wp_rewrite;
$rewrite_tags = array(
array( '%pages%', '/?([0-9]{1,}\-[0-9]{1,})/?$', 'pages='),
);
foreach( $rewrite_tags as $tag ):
$wp_rewrite->add_rewrite_tag( $tag[0], $tag[1], $tag[2] );
endforeach;
*/
add_rewrite_endpoint( 'pages', EP_ALL );
}
add_action('init', 'pew_infinite_scroll_rewrite_rules');
function pew_infinite_scroll_pre_get_posts( $query ) {
if ( is_admin() || !$query->is_main_query() )
return;
if ( $query->is_archive() && ( $pages = pew_infinite_scroll_get_pages() ) ) {
$start = $pages->start;
if( $start == -1 ) {
$query->set( 'nopaging', true );
} else {
$query->set( 'paged', $start );
}
return;
}
}
add_action( 'pre_get_posts', 'pew_infinite_scroll_pre_get_posts' );
function pew_infinite_scroll_post_limits( $limit ) {
global $wp_query;
if ( is_admin() || !$wp_query->is_main_query() ) {
return $limit;
}
if( $pages = pew_infinite_scroll_get_pages() ) {
if( $pages->start == -1 ) {
return $limit;
}
$new_limit = $pages->diff * $pages->posts_per_page + $pages->posts_per_page;
$limit = str_replace(', ' . $pages->posts_per_page, ', ' . $new_limit, $limit);
}
return $limit;
}
add_filter( 'post_limits', 'pew_infinite_scroll_post_limits' );
function pew_infinite_scroll_wp() {
global $wp_query, $paged;
$pages = pew_infinite_scroll_get_pages();
if( !$pages || !$pages->end ) {
return;
}
$wp_query->set('paged', $pages->end);
$paged = get_query_var( 'paged' );
}
add_action( 'wp', 'pew_infinite_scroll_wp' );
function pew_infinite_scroll_redirect_canonical( $redirect_url, $requested_url ) {
//Kill the canonical 'paged' redirect if the pages query var is set. In other words we don't want /category/publications/?pages=1-10 to redirect to /category/publications/page/10/?pages=1-10 which is what would happen by default.
if( get_query_var('pages') ) {
$redirect_url = trailingslashit($requested_url);
}
return $redirect_url;
}
add_filter( 'redirect_canonical', 'pew_infinite_scroll_redirect_canonical', 10, 2 );
function pew_infinite_scroll_get_pagenum_link($result) {
if( $pages = pew_infinite_scroll_get_pages() ) {
$result = preg_replace('/pages\/([\d\-]+|all)\//i', '', $result); //Strip out anything that matches pages/{any digit or hypen or the word all}/
}
return $result;
}
add_filter('get_pagenum_link', 'pew_infinite_scroll_get_pagenum_link');
function pew_infinite_scroll_enqueue_script() {
if( is_archive() ) {
wp_enqueue_script( 'pew-infinite-scroll' );
}
}
add_action( 'wp_enqueue_scripts', 'pew_infinite_scroll_enqueue_script' );
/***
* Helper Functions
***/
function pew_infinite_scroll_get_pages() {
$pages_var = get_query_var('pages');
if( !$pages_var ) {
return false;
}
$start = 1;
$end = false;
$pages = explode( '-', $pages_var );
if( count($pages) < 2 && isset($pages[0]) && !empty( $pages[0] ) ) {
if( strtolower($pages[0]) == 'all' ) {
$start = -1;
$end = false;
} else {
$end = intval($pages[0]);
}
} else {
$pages = array_map('intval', $pages);
if( isset($pages[0]) && !empty( $pages[0] ) ) {
$start = $pages[0];
}
if( isset( $pages[1] ) && !empty( $pages[1] ) ) {
$end = $pages[1];
}
}
return (object) array(
'start' => $start,
'end' => $end,
'diff' => abs( $end - $start ),
'posts_per_page' => intval(get_option('posts_per_page'))
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment