Skip to content

Commit

Permalink
Merge pull request #24 from gin0115/fix/gh23-infinate-scroll-dupes
Browse files Browse the repository at this point in the history
Added in a check to ensure that a page has not already been called
  • Loading branch information
fmfernandes authored Sep 5, 2024
2 parents ec7328c + a797494 commit 85e869d
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 47 deletions.
2 changes: 1 addition & 1 deletion assets/js/build/frontend.asset.php
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<?php return array('dependencies' => array(), 'version' => '3c0f99a875b752effacc');
<?php return array('dependencies' => array(), 'version' => 'e794f26b7ef47600cb0a');
2 changes: 1 addition & 1 deletion assets/js/build/frontend.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

165 changes: 120 additions & 45 deletions assets/js/src/frontend.js
Original file line number Diff line number Diff line change
@@ -1,58 +1,133 @@
const intersectionObserver = new IntersectionObserver( ( entries ) => {

// Keep a record of the page we have loaded, per query.
const pages = {};

/**
* Gets the query and page from a URL string
* @param {string} str The query string for url
* @returns {query: number, page: number} | null
*/
const extractQueryParams = (str) => {
// Default values
let query = null;
let page = null;

// Regular expressions to match query and page
const queryMatch = str.match(/query-(\d+)/);
const pageMatch = str.match(/page=(\d+)/);

// Extract and convert to integer if matches are found
if (queryMatch) {
query = parseInt(queryMatch[1], 10);
}

if (pageMatch) {
page = parseInt(pageMatch[1], 10);
}

// If either are null, return null
if (query === null || page === null) {
return null;
}

return { query, page };
}

/**
* Checks if a given query and page is in the pages object
*
* @param {number} query The query ID
* @param {number} page The page number
*
* @returns {boolean}
*/
const isPageLoaded = (query, page) => {
if (pages[query] && pages[query].includes(page)) {
return true;
} else {
return false;
}
}

/**
* Logs a given query and page to the pages object
*
* @param {number} query The query ID
* @param {number} page The page number
*
* @returns {void}
*/
const logPage = (query, page) => {
if (!pages[query]) {
pages[query] = [];
}

pages[query].push(page);
}


const intersectionObserver = new IntersectionObserver((entries) => {
// If intersectionRatio is 0, the target is out of view.
if ( entries[ 0 ].intersectionRatio <= 0 ) return;
if (entries[0].intersectionRatio <= 0) return;

const $url = entries[0].target.href,
$container = entries[0].target
.closest('.wp-block-query')
.querySelector('.wp-block-post-template'),
$clickedButton = entries[0].target;

const $url = entries[ 0 ].target.href,
$container = entries[ 0 ].target
.closest( '.wp-block-query' )
.querySelector( '.wp-block-post-template' ),
$clickedButton = entries[ 0 ].target;
// Get the query and page from the button href.
const queryLoopParams = extractQueryParams($clickedButton.getAttribute('href'));

fetchPosts( $url, $container, $clickedButton );
} );
// If we have a page and its not already in the pages array, add it.
if (queryLoopParams && isPageLoaded(queryLoopParams.query, queryLoopParams.page) === false) {
logPage(queryLoopParams.query, queryLoopParams.page);
fetchPosts($url, $container, $clickedButton);
}
});

/**
*
* @param {*} url
* @param {*} container
* @param {*} clickedButton
*/
const fetchPosts = ( url, container, clickedButton ) => {
const fetchPosts = (url, container, clickedButton) => {
showLoader();

// Load posts via fetch from the button URL.
fetch( url, {
fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'text/html',
},
} )
.then( function ( response ) {
if ( response.ok ) {
})
.then(function (response) {
if (response.ok) {
return response.text();
}
throw new Error( 'Network response was not ok.' );
} )
.then( function ( data ) {
throw new Error('Network response was not ok.');
})
.then(function (data) {
// Get the posts container.
const temp = document.createElement( 'div' );
const temp = document.createElement('div');
temp.innerHTML = data;
const posts = temp.querySelector( '.wp-block-post-template' );
const posts = temp.querySelector('.wp-block-post-template');

// Update the posts container.
container.insertAdjacentHTML( 'beforeend', posts.innerHTML );
container.insertAdjacentHTML('beforeend', posts.innerHTML);

// Update the window URL.
window.history.pushState( {}, '', url );
window.history.pushState({}, '', url);

// Remove button.
clickedButton.remove();

hideLoader();
} )
.catch( function ( error ) {
console.error( 'Fetch error:', error );
} );
})
.catch(function (error) {
console.error('Fetch error:', error);
});
};

/**
Expand All @@ -63,11 +138,11 @@ const showLoader = () => {
'.wp-load-more__infinite-scroll'
);

if ( ! $loader?.length ) {
if (!$loader?.length) {
return;
}

$loader[ 0 ].classList.add( 'loading' );
$loader[0].classList.add('loading');
};

/**
Expand All @@ -78,54 +153,54 @@ const hideLoader = () => {
'.wp-load-more__infinite-scroll'
);

if ( ! $loader?.length ) {
if (!$loader?.length) {
return;
}

$loader[ 0 ].classList.remove( 'loading' );
$loader[0].classList.remove('loading');
intersectionObserver.observe(
document.querySelector( '.wp-load-more__button' )
document.querySelector('.wp-load-more__button')
);
};

/**
*
*/
document.addEventListener( 'DOMContentLoaded', function () {
document.addEventListener('DOMContentLoaded', function () {
'use strict';

// Cache selectors.
const buttons = document.querySelectorAll( '.wp-load-more__button' );
const buttons = document.querySelectorAll('.wp-load-more__button');
const infiniteScroll = document.querySelectorAll(
'.wp-load-more__infinite-scroll'
);

// Attach handlers all to all load more buttons.
if ( buttons?.length ) {
buttons.forEach( function ( button ) {
button.addEventListener( 'click', function ( e ) {
if (buttons?.length) {
buttons.forEach(function (button) {
button.addEventListener('click', function (e) {
e.preventDefault();

const thisButton = e.target,
container = thisButton
.closest( '.wp-block-query' )
.querySelector( '.wp-block-post-template' ),
url = thisButton.getAttribute( 'href' );
.closest('.wp-block-query')
.querySelector('.wp-block-post-template'),
url = thisButton.getAttribute('href');

// Update button text.
thisButton.innerText =
thisButton.getAttribute( 'data-loading-text' );
thisButton.getAttribute('data-loading-text');

fetchPosts( url, container, thisButton );
} );
} );
fetchPosts(url, container, thisButton);
});
});
}

// Add infinite scroll watchers if infinite scroll is enabled.
if ( infiniteScroll?.length ) {
if (infiniteScroll?.length) {
// start observing
intersectionObserver.observe(
document.querySelector( '.wp-load-more__button' )
document.querySelector('.wp-load-more__button')
);
}
} );
});

0 comments on commit 85e869d

Please sign in to comment.