Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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
You can’t perform that action at this time.