I’m using the infinite load optional feature for a large list of newsfeed cards. Each card has a CTA button which has a GSAP hover interaction and it works on the cards that initially load with the page but the interaction doesn’t work on any of the items that is loaded as you scroll further down the page. The link still works and will open the new page, just the hover interaction isn’t working.
Here is the page on the staging site that this is happening on: https://skycar.webflow.io/newsfeed
Here is the read-only link for the page where I’ve implemented the solution in the Webflow Project:
Read-only link
I’m using a solution for the GSAP interaction from Timothy Ricks found here: GSAP Interaction
Hey @michaellee2245! Can you share the snippet used to initiate the Gsap?
Tha solution would be to add the CMS Load callback and rerun the snippet once new items are rendered on page.
Here is the callback in case you want to give it a shot
window.fsAttributes = window.fsAttributes || [];
window.fsAttributes.push([
'cmsload',
(listInstances) => {
console.log('cmsload Successfully loaded!');
// The callback passes a `listInstances` array with all the `CMSList` instances on the page.
const [listInstance] = listInstances;
// The `renderitems` event runs whenever the list renders items after switching pages.
listInstance.on('renderitems', (renderedItems) => {
console.log(renderedItems);
});
},
]);
Sorry for the late reply Luis. Here is the GSAP code that initiates the clip path hover effect:
// Button Clip Path Hover
$("[data-btn='wrap']").each(function () {
const clipEl = $(this).find("[data-btn='clip']").attr("aria-hidden", "true");
const durationSetting = 0.4;
const easeSetting = "power2.out";
function getPercentTop(el, e) {
let elTop = el.offset().top - $(window).scrollTop();
let mouseTop = e.pageY - $(window).scrollTop() - elTop;
return (mouseTop / el.innerHeight()) * 100;
}
function getPercentLeft(el, e) {
let elLeft = el.offset().left;
let mouseLeft = e.pageX - elLeft;
return (mouseLeft / el.innerWidth()) * 100;
}
$(this).on("mouseenter", function (e) {
let percentTop = getPercentTop($(this), e);
let percentLeft = getPercentLeft($(this), e);
gsap.set(clipEl, { display: "flex" });
gsap.fromTo(
clipEl, { clipPath: `circle(0% at ${percentLeft}% ${percentTop}%)` }, {
clipPath: `circle(141.4% at ${percentLeft}% ${percentTop}%)`,
duration: durationSetting,
ease: easeSetting
});
});
$(this).on("mouseleave", function (e) {
let percentTop = getPercentTop($(this), e);
let percentLeft = getPercentLeft($(this), e);
gsap.to(clipEl, {
clipPath: `circle(0% at ${percentLeft}% ${percentTop}%)`,
overwrite: true,
duration: durationSetting,
ease: easeSetting
});
});
});
Would I just use the callback in script tags before the closing body tag in the custom code? I don’t need to add it to an existing function or anything right? Thanks for your help!
Hey @michaellee2245! That is correct, the added callback should go in the </body>
section of the custom code. I see you are using Slater, the callback may also be added there.
I can’t test the code at the moment because disabling the Slater script breaks the page on my end but please test and let me know.
I moved the code to a function called gsapInit
that is called when CMS Load is done loading and each time new items are rendered. This should query all newly rendered data-button='wrap'
and re-initiate the hover effect.
window.fsAttributes = window.fsAttributes || [];
window.fsAttributes.push([
'cmsload',
(listInstances) => {
console.log('cmsload Successfully loaded!');
const [listInstance] = listInstances;
const gsapInit = function() {
const clipEl = $(this).find("[data-btn='clip']").attr('aria-hidden', 'true');
const durationSetting = 0.4;
const easeSetting = 'power2.out';
const getPercentTop = (el, e) => {
let elTop = el.offset().top - $(window).scrollTop();
let mouseTop = e.pageY - $(window).scrollTop() - elTop;
return (mouseTop / el.innerHeight()) * 100;
}
const getPercentLeft = (el, e) => {
let elLeft = el.offset().left;
let mouseLeft = e.pageX - elLeft;
return (mouseLeft / el.innerWidth()) * 100;
}
$(this).on('mouseenter', function(e) {
let percentTop = getPercentTop($(this), e);
let percentLeft = getPercentLeft($(this), e);
gsap.set(clipEl, { display: 'flex' });
gsap.fromTo(
clipEl,
{ clipPath: `circle(0% at ${percentLeft}% ${percentTop}%)` },
{
clipPath: `circle(141.4% at ${percentLeft}% ${percentTop}%)`,
duration: durationSetting,
ease: easeSetting,
}
);
});
$(this).on('mouseleave', function(e) {
let percentTop = getPercentTop($(this), e);
let percentLeft = getPercentLeft($(this), e);
gsap.to(clipEl, {
clipPath: `circle(0% at ${percentLeft}% ${percentTop}%)`,
overwrite: true,
duration: durationSetting,
ease: easeSetting,
});
});
};
// Button Clip Path Hover
$("[data-btn='wrap']").each(gsapInit);
listInstance.on('renderitems', (renderedItems) => {
console.log(renderedItems);
$("[data-btn='wrap']").each(gsapInit);
});
},
]);
1 Like
Hey @Support-Luis,
Sorry to resurrect this issue, but I’ve ended up using this same infinite style load more on the projects page of this website as well. Now, I don’t know if I should open a new conversation or not, but it seemed related enough to this so I thought I’d reply to you here.
This projects page has two instances of Load More one for the filters (which you helped me with in this thread https://forum.finsweet.com/t/cms-filter-cms-load-more-loaded-items-wont-filter/2554/5).
Now the issue here is I have tags that utilize the same GSAP interaction and I tried adding the code you already gave me for the GSAP interaction thinking it would work the same for the newly loaded projects, but it didn’t. And maybe that is because it’s the second Load More instance on the page? I also have this custom code which is used to change out the custom cursor when hovering on one of the project links in the grid and it works on the initially loaded items, but not any of the newly loaded ones.
$('.work_featured-link, .work-gallery_link, .gallery_project-link').on('mouseenter', function () {
$('.cursor_dot-wrapper').addClass('cursor-invisible');
$('.cursor-eye').removeClass('cursor-invisible');
$('.cursor').css('mix-blend-mode', 'normal');
});
$('.work_featured-link, .work-gallery_link, .gallery_project-link').on('mouseleave', function () {
$('.cursor_dot-wrapper').removeClass('cursor-invisible');
$('.cursor-eye').addClass('cursor-invisible');
$('.cursor').css('mix-blend-mode', 'difference');
});
The page is found at the link below and the read-only link as well. Any help solving this would be much appreciated!
https://preview.webflow.com/preview/skycar?utm_medium=preview_link&utm_source=designer&utm_content=skycar&preview=9d5c3b49ba4c73029fb803c76dc14aca&pageId=65c68a5711deda99b0b758f4&locale=en&workflow=preview
Hey @michaellee2245! That is correct, since we have two lists, each needs it’s own renderItems
event listener.
We can target all instances on the page like this
listInstances.forEach((listInstance) => {
console.log(listInstance);
listInstance.on('renderitems', (renderedItems) => {
console.log(renderedItems);
$("[data-btn='wrap']").each(gsapInit);
});
});
This will also work if in the future you decide to add more lists to this page.
regarding the cursor change, where is this ran? if it is a function you can also call it on the renderitems event callback if it should work for both lists.
1 Like
Awesome!! Thanks! As for the cursor, the code is stored in Slater in my global.js file as it runs on all pages. Right now, it’s just running as I shared it in those two jQuery functions one for the mouse enter and one for the mouse leave. It’s not stored in a function. Can I add the code as is? or is your recommendation to add it to a function and then call that function?
There is also a weird behavior that happens when additional items are loaded to the project grid. When I scroll back up to the top all of the hero content just disappears. I took out the load more attribute and went to the bottom of the list and then back up and the content is there like it should be. Do you have any idea why this would be happening?
EDIT:
I figured out it was from the reset interactions attribute that I added on. I need the reset interactions because I have an interaction when you hover over the project that needs to be reset, but can I have that only apply to the grid of projects or will it always apply to the whole page and affect the elements at the top of the page with Webflow interactions?
Thanks for the update @michaellee2245! I’m afraid the resetix
attribute resets all the interactions on the page.
The attribute will reset the interaction engine so any interaction with an initial state will return to it and appear broken. We can work around this by using the effects panel to simulate the initial state of the interactions present on the page.
Thanks for all your help @Support-Luis! Everything seems to be working well now on the page. You’re a serious boss
1 Like