Need help with lazyload plugin

Hi,
I’m having problems integrating the lozad.js lazy load plugin into my template.

Everything works on load but when I click on the “load more” button it breaks.
This must be pretty simple but somehow I can’t get this to work.
I appreciate any help :slight_smile:

<img class="lozad" data-src="{{ data.images.shop_catalog.url }}" alt="{{ data.post_title }}" title="{{ data.post_title }}" itemprop="image" />

and this is the js code from lozad,js

window.addEventListener('load', function() {
  var observer = lozad('.lozad', {
		loaded: function(el) {
			el.classList.add('loaded');
		}
	});
  observer.observe()})

this is the InfinitHits widget

search.addWidget(
instantsearch.widgets.infiniteHits({
		container: '#algolia-hits',
			showMoreLabel: "Load more",
			hitsPerPage: 80,
			templates: {
				empty: algolia.woocommerce.i18n.no_results_template,
				item: wp.template('instantsearch-hit')
			},
			transformData: {
				item: function(data) {
					data.formatted_price = format_price(data.price);
					data.formatted_max_price = format_price(data.max_price);
					data.formatted_regular_price = format_price(data.regular_price);
					return data;
				}
			}
		}));

Thanks for the help!

Hi @rd.intermac.
Glad to help!

it’s hard to tell what breaks from the code you’re showing.
I set up an example feature infinite Hits an a working “Show more” button: instantsearchjs-template - CodeSandbox
Can you adapt the example to demonstrate your issue?

Thank you very much

Hi,
I did add images to the product list but I don’t know how to correctly add this code to make it work when searching or when clicking on the “Show more” button.

  // Initialize library to lazy load images
  const observer = lozad(".lozad", {
    rootMargin: "300px 0px", // syntax similar to that of CSS Margin
    loaded: function(el) {
      // Custom implementation on a loaded element
      el.classList.add("loaded");
    }
  });
  observer.observe();

https://codesandbox.io/s/9z7rn3y244

( If you click on the refresh button in the browser preview the images are loaded and when scrolling the images are being added by lozad.js .)

Thanks for the help!

Ok, I have managed to make it work by adding a customInfiniteHit components and calling the .observe method on each render.

search.addWidget(
  customInfiniteHits({
    container: "#hits-container"
  })
);

search.start();

function customInfiniteHits(opts) {
  const observer = lozad(".lozad", {
    loaded: function(el) {
      el.classList.add("loaded");
    }
  });
  function render() {
    observer.observe();
  }
  function unmount() {}

  var makeInfiniteHits = instantsearch.connectors.connectInfiniteHits(
    render,
    unmount
  );
  return makeInfiniteHits({});
}

full example is here:

Awesome it works!
I implemented this in Wordpress and it’s working :smiley:
But to get this to work I needed to upgrade from InstantSearch V1 to V2.
In my template, I use this code item.lowercaseName = item.name.toLowerCase(); to give the span items a unique name for CSS styling reasons.
But after upgrading to InstantSearch V2 I get this error
"Uncaught (in promise) TypeError: Cannot read property 'toLowerCase' of undefined"

https://codesandbox.io/s/rrnyj8z8nq

This is the code that used to work for InstantSearch V1

search.addWidget(
instantsearch.widgets.refinementList({
    container: document.querySelector("#brand"),
    attributeName: "brand",
    templates: {
      header: '<h4>Header</h4>',
      item: '<span class="{{lowercaseName}}">{{lowercaseName}}</span>',
    },
    transformData: {
      item: function (item) {
        item.lowercaseName = item.name.toLowerCase();
        return item;
      }
    },
  })
);

You tranformData function sometimes fails because it assumes item.name is always defined but it’s not.
You can work around this just by checking item.name value before calling toLowerCase()

{
    transformData: {
      item: function (item) {
        if (item.name) {
           item.lowercaseName = item.name.toLowerCase();
        }
        return item;
      }
    },
}

Hi,
Thanks a lot for the reply! I still can’t get this to work. :sweat:
This is the error I get in the codesandbox

/index.js: Unexpected token, expected ; (51:23)

https://codesandbox.io/s/jjk7851yw9

I just want to get the item name for styling reasons. Maybe there is another very simple solution to achieve this?

Thanks for the help! :smiley:

Hi @rd.intermac
I had a typo in my example, I wrote it and meant if

Hi @Youcef
Ah yes, I just copied that typo :see_no_evil: after some while, I figured it out myself :smiley:
No errors and everything seems to be working, but why is {{lowercaseName}} output empty?

Best Regards!

Sorry, that’s another of my typos:

It’s the value we print rather than name


        if (item.value) {
          item.lowercaseName = item.value.toLowerCase();
        }

updated example is here: instantsearchjs-template - CodeSandbox

Hi,
Thank you very much for the help, everything is working now :smiley:
I still have one problem with implementing a shortcode into the template that needs to get the post / product ids

<?php echo do_shortcode('[ti_wishlists_addtowishlist product_id="'.get_the_ID().'"]'); ?>

Best regards,
Robin