waypoints icon indicating copy to clipboard operation
waypoints copied to clipboard

Waypoints fire more than once when I reach and load new content

Open FarrisFahad opened this issue 6 years ago • 2 comments

Check out my page: www.picturepunches.com

I load waypoint once the page is loaded and every time the user reach to the bottom. I want waypoint to excute once everytime it reaches a point. But the problem is that it execute twice once new content in loaded via ajax.

Can anyone help?

FarrisFahad avatar Feb 18 '19 12:02 FarrisFahad

I face the same issue. Either Ajax content doesn't work or it works more than once, when the $items code is changed a bit.

Jayesh-Mahato avatar May 25 '20 15:05 Jayesh-Mahato

This problem also bothered me for a long time, and then I finally to solve it successfully. I will record my method for your reference:

Before set the option, the height of the container must be given to prevent the position from running away

const container = document.querySelector('.infinite-container');
let containerHight;
container.style.height = container.clientHeight + 'px';

$(window).on('load', function () {
	infiniteExample();
});
function infiniteExample() {
	const infinite = new Waypoint.Infinite({
		element: $('.infinite-container')[0],
		onBeforePageLoad: function () {
			// we use css to change height auto if user resize window, and don't remove container.style.height
			if (container.classList.contains('height-auto')) container.classList.remove('height-auto');
			containerHight = container.clientHeight;
			container.style.height = containerHight + 'px';
		},

		onAfterPageLoad: function ($items) {
			//- get new page height 
			let newLoadHight = handleLoadH($items);
			container.style.height = containerHight + newLoadHight + 'px';
			//- if last page
			if ($items.prevObject[2].className != 'infinite-more-link') {
				container.classList.add('is-done');
			}
		}
	});
};

// wirte a css .height-auto {height:auto!important}
window.addEventListener('resize', function () {
	container.classList.add('height-auto');
});

// function get new page height:
const handleLoadH = function (obj) {
	// console to check data
	//- let data = JSON.stringify(obj);
	let data = [];
	obj.each(function (item) {
		return data.push(obj[item].clientHeight);
	});
	//- console.log(data);

	//- I'm load 6 item in one page
	//- 3 item in a row on PC
	//- 2 item in a row on Table
	//- 1 item in a row on mobile
	if (window.innerWidth >= 992) {
		let row1 = data.slice(0, 3);
		let row2 = data.slice(3, 6);
		return Number(choseBig(row1)) + Number(choseBig(row2));
	} else if (window.innerWidth <= 991 && window.innerWidth >= 768) {
		let row1 = data.slice(0, 2);
		let row2 = data.slice(2, 4);
		let row3 = data.slice(4, 6);
		return Number(choseBig(row1)) + Number(choseBig(row2)) + Number(choseBig(row3));
	} else {
		return data.reduce((a, b) => a + b, 0);
	}
};
function choseBig(arr) {
	return arr.sort((a, b) => b - a).slice(0, 1);
};

Then modify infinite.js

/* Private */
Infinite.prototype.setupHandler = function () {
	this.options.handler = $.proxy(function () {
		this.options.onBeforePageLoad()
		this.destroy()
		this.$container.addClass(this.options.loadingClass)

		$.get($(this.options.more).attr('href'), $.proxy(function (data) {
			...

			if (!$newMore.length) {
				$newMore = $data.filter(this.options.more)
			}
			// change it !!
			this.options.onAfterPageLoad($items)
			//
			if ($newMore.length) {
				this.$more.replaceWith($newMore)
				this.$more = $newMore
				this.waypoint = new Waypoint(this.options)
			}
			else {
				this.$more.remove()
			}

			// this.options.onAfterPageLoad($items)
		}, this))
	}, this)
}

done, enjoy it

In 2022, there maybe have other better lazyload library, but the classic is undefeated

solhuang2201 avatar Jun 14 '22 18:06 solhuang2201