Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot read properties of undefined (reading 'width') && undefined is not an object (evaluating 'this.containerRect.height') #1485

Closed
felix-berlin opened this issue Mar 22, 2023 · 11 comments · May be fixed by #1684
Labels

Comments

@felix-berlin
Copy link

Description

Hi, we are using lightGallery in a larger project where we use Sentry for error logging. For some time now we have been receiving thousands of errors that seem to be related to lightGallery.

Unfortunately I have not been able to reproduce these errors myself. That's the reason why I created this issue.

In the following a few stack traces from Sentry:

Cannot read properties of undefined (reading 'getBoundingClientRect')

{snip} is.core.index).find(".lg-image").first().get(),i=0,r=0,s=n.getBoundingClientRect();t?(i=n.offsetHeight*t,r=n.offsetWidth*t):e?(i=s.height+e* {snip}

Cannot read properties of undefined (reading 'width')

{snip} ,e,n,i){if(!(Math.abs(e)<=0)){var r,s,o=this.containerRect.width/2+this.containerRect.left,a=this.containerRect.height/2+this.containerRect. {snip}

undefined is not an object (evaluating 'this.containerRect.height')

{snip} t,e,n,i){if(!(Math.abs(e)<=0)){var r,s,o=this.containerRect.width/2+this.containerRect.left,a=this.containerRect.height/2+this.containerRect {snip}

In the project we use Vue 2 + Laravel and lightGallery as a normal JS bundle.

Many thanks in advance!

Steps to reproduce

Unfortunately, I can't provide a demo, even though that would be much better to understand where the error might be.

JS code that you use to initialize lightGallery.

<!-- Bild-Slider in der Lightbox -->

<template>
	<div class="m-lightbox">
		<transition name="fade-fast">
			<!-- Benachrichtigung, dass der Link der Produktdetailseite in die Zwischenablage kopiert wurde -->
			<div class="c-alert c-alert--success c-alert--success-buybox-image"
				 v-if="this.showLinkCopiedTooltip">
				{{ __('product_box.tooltips.copied') }}
			</div>
		</transition>
	</div>
</template>

<script>
import lightGallery from 'lightgallery';
import 'lightgallery/css/lightgallery.css';
import 'lightgallery/css/lg-thumbnail.css';
import 'lightgallery/css/lg-video.css';
import 'lightgallery/css/lg-zoom.css';
import lgThumbnail from 'lightgallery/plugins/thumbnail';
import lgZoom from 'lightgallery/plugins/zoom';
import lgVideo from 'lightgallery/plugins/video';

export default {
	name: 'LightboxWrapper',

	props: {
		lightGallerySelector: {
			type: String,
			default: '#vendor-light-gallery',
		},
		hasInfoText: {
			type: Boolean,
			default: false,
		},
	},

	data() {
		return {
			showLinkCopiedTooltip: false,
			lightGalleryDOMElement: null,
			currentImage: null,
		};
	},

	methods: {
		initLightGallery() {
			this.$callIfElementExists(this.lightGallerySelector, el => {
				// Docs: https://www.lightgalleryjs.com/docs/settings/
				lightGallery(el, {
					plugins: [lgThumbnail, lgZoom, lgVideo],
					thumbnail: true,
					animateThumb: false,
					showThumbByDefault: false,
					licenseKey: process.env.MIX_LIGHT_GALLERY_KEY,
					speed: 500,
					download: false, // zeige keinem Download-Icon an
					autoplayFirstVideo: false, // starte Videos nicht automatisch
					strings: {
						previousSlide: this.__('slider.prev_button'),
						nextSlide: this.__('slider.next_button'),
						closeGallery: this.__('general.close'),
						playVideo: this.__('Play video'),
					},
					mobileSettings: {
						controls: false,
						showCloseIcon: true,
					},
				});

				this.lightGalleryDOMElement = el;
				this.setUpLightGalleryEventListeners();
			});
		},

		/**
		 * Initialisiere Event Listeners für die Bilder im Gallery
		 * */
		setUpLightGalleryEventListeners() {
			// Nachdem ein Bild geladen wurde, erstelle auch einen Event-Listener fürs Bild, für das Öffnen vom Kontextmenü
			// Docs: https://www.lightgalleryjs.com/docs/events/#lgSlideItemLoad
			this.lightGalleryDOMElement.addEventListener('lgSlideItemLoad', event => {
				this.currentImage = document.querySelector(`#lg-item-1-${event.detail.index} img`);

				if (!this.currentImage) return;

				this.currentImage.addEventListener('contextmenu', this.imageEventListener);
			});

			// Bevor das Gallery geschlossen wird, bzw. bevor ein Bild gewechselt wird, entferne den Event-Listener
			// Docs: https://www.lightgalleryjs.com/docs/events/#lgBeforeSlide
			this.lightGalleryDOMElement.addEventListener('lgBeforeSlide', this.removeImageEventListener);
			// Docs: https://www.lightgalleryjs.com/docs/events/#lgBeforeClose
			this.lightGalleryDOMElement.addEventListener('lgBeforeClose', this.removeImageEventListener);
		},

		/**
		 * Die Funktion die immer auf Rechtsklick vom Bild ausgeführt wird
		 * */
		imageEventListener(e) {
			e.preventDefault();
			this.$copyProductLinkToClipBoard();
		},

		/**
		 * Cleanup-Funktion für den Event-Listener
		 * */
		removeImageEventListener() {
			if (!this.currentImage) return;

			this.currentImage.removeEventListener('contextmenu', this.imageEventListener);
			this.currentImage = null;
		},
	},

	mounted() {
		this.initLightGallery();
	},
};
</script>

Sample HTML markup

@php
	$combinedImages = array_merge([data_get($article, 'images.main')], data_get($article, 'images.additional', []));
@endphp

<!-- Bild-Slider in der Buybox auf der Artikeldetailseite -->
<div class="m-buybox__wrap-img is-loading">

	<transition name="fade-fast" v-cloak>
		<!-- Benachrichtigung, dass der Link der Produktdetailseite in die Zwischenablage kopiert wurde -->
		<div class="c-alert c-alert--success c-alert--success-buybox-image"
			 v-if="this.showLinkCopiedTooltip">
			{{ __('product_box.tooltips.copied') }}
		</div>
	</transition>

	<div class="m-buybox__slider">

		<!-- Slider main container -->
		<div class="c-slider c-slider--buybox swiper-container">
			<!-- Additional required wrapper -->
			{{-- Folgendes Markup, muss kompatibel mit Anforderungen aus lightGallery sein--}}
			{{-- Für Doku dazu, siehe: https://www.lightgalleryjs.com/docs/getting-started/#the-markup --}}
			<div class="c-slider__wrapper swiper-wrapper vendor-light-gallery" id="product-slider-wrapper">

				@foreach($combinedImages as $key => $image)
					@php
						$productImage = new \App\Helpers\ImageHelper(data_get($image, 'src'));
						$imageClasses = 'c-slider__image m-buybox__img';
						if (data_get($image, 'src') !== null) $imageClasses .= ' has-pointer';
					@endphp

					<div data-src="{{ $productImage->getImage(2400) }}"
						 class="c-slider__item swiper-slide vendor-light-gallery-item"
						 data-sub-html="{{ __('product_box.product_image_info_text') }}"
						 @dragstart.prevent="()=> false"
						 @drop.prevent="()=> false"
						 @contextmenu.prevent="$copyProductLinkToClipBoard()">

						<img
							alt="{{ __('product_slider.product_img_alt', ['number' => $key, 'product' => trim(escapeZWNJChar(data_get($article, 'standard.title'))) ]) }}"
							decoding="async"
							height="566"
							width="566"
							v-on:error="$setFallbackImage($event, '600x600')"
							class="{{ $imageClasses }}"
							src="{{ $productImage->getImage(600) }}"
							loading="{{ $key === 0 ? 'eager' : 'lazy' }}"
							fetchpriority="{{ $key === 0 ? 'high' : 'low' }}"
						>

						@if(data_get($image, 'src'))
							<span class="m-buybox__info-txt">{{ __('product_box.product_image_info_text') }}</span>
						@endif
					</div>
				@endforeach

			</div>

		</div>

		@if(count($combinedImages) > 1)
			<div class="c-slider__nav c-slider__nav--prev swiper-button-prev"
				 aria-label="{{ __('slider.prev_button') }}"
				 role="button"
				 aria-controls="product-slider-wrapper">
				<i class="c-slider__nav-icon icon icon-arrow-left"></i>
			</div>
			<div class="c-slider__nav c-slider__nav--next swiper-button-next"
				 aria-label="{{ __('slider.next_button') }}"
				 role="button"
				 aria-controls="product-slider-wrapper">
				<i class="c-slider__nav-icon icon icon-arrow-left"></i>
			</div>
		@endif

		@if(data_get($article, 'homologation.icon') && data_get($article, 'homologation.value'))
			<button type="button"
					title="{{ data_get($article, 'homologation.value') }}"
					class="m-buybox__homologation"
					@click.prevent="$modal.show('homologationModal', { homologation: '{{ data_get($article, 'homologation.value') }}' })">
				<img src="{{ data_get($article, 'homologation.icon') }}"
					 alt="{{ escapeZWNJChar(data_get($article, 'homologation.value')) }}" decoding="async"
					 loading="eager">
			</button>
		@endif

	</div>

	@if(!empty(data_get($article, 'images.additional', [])) || !empty($videos))

		<div class="m-buybox__thumbnails">
			<div class="c-slider c-slider--thumbnails swiper-thumb-container">
				<div class="c-slider__wrapper swiper-wrapper">

					@unless(empty($videos))
						<a href="#productvideo" v-anchor-scroll aria-label="{{ __('product_slider.jump_to_video') }}">
							<div class="c-slider__item swiper-slide is-video-thumbnail-slide">
								<i class="fa fa-play-circle-o"></i>
							</div>
						</a>
					@endunless

					@foreach($combinedImages as $key => $image)
						@php($productImage = new \App\Helpers\ImageHelper(data_get($image, 'src')))

						<div class="c-slider__item swiper-slide">
							<img src="{{ $productImage->getImage(155) }}"
								 loading="eager"
								 decoding="async"
								 v-on:error="$setFallbackImage($event, '155x155')"
								 alt="{{ __('product_slider.product_img_alt', ['number' => $key, 'product' => trim(escapeZWNJChar(data_get($article, 'standard.title'))) ]) }}"
								 class="m-buybox__img c-slider__image">
						</div>
					@endforeach
				</div>
			</div>

		</div>
	@endif

	<lightbox light-gallery-selector=".vendor-light-gallery"></lightbox>
</div>



Environment

  • lightGallery version: 2.7.1

Cannot read properties of undefined (reading 'height')

Bildschirm­foto 2023-03-22 um 15 27 19

Cannot read properties of undefined (reading 'width')

Bildschirm­foto 2023-03-22 um 15 24 15

Additional context

@sachinchoolur
Copy link
Owner

Thanks for the detailed information.
Is it possible to disable the zoom plugin for a few days and check the results?

@felix-berlin
Copy link
Author

Yes that's possible.
Tomorrow we will deploy a new release with disabled zoom plugin and keep tracking the Sentry issue.

@felix-berlin
Copy link
Author

@sachinchoolur Looks like the errors are related to the zoom plugin. After deactivating the plugin and deploying our new release, no more Sentry errors appeared.

image

@stof
Copy link

stof commented Apr 28, 2023

I'm getting similar errors in my logs.

Looking quickly at the code of the zoom plugin, my guess is that some code reading this.containerRect can be called before the initialization happens in setZoomEssentials

@sachinchoolur
Copy link
Owner

Hey @felix-berlin and @stof ,

I tried reproducing the issue many times. But, no luck so far. I think the issue occurs when the app is re-rendering and doesn't affect the real users.

Is it possible for you to use the un-minified version of the Zoom plugin for a few days? So that we'll get better stack traces

@Kartik4152
Copy link

Kartik4152 commented Aug 10, 2023

Steps to reproduce -

  1. Open an image.
  2. Gallery will open up with a loader.
  3. Click on the loader before the image loads.
  4. Get the error below.

image

@felix-berlin
Copy link
Author

@sachinchoolur Sentry is no longer tracking some of the issues.

image

We will enable the zoom plugin again. When the errors appearing again, we will try to import the plugin unminified.

@felix-berlin
Copy link
Author

Steps to reproduce -

  1. Open an image.
  2. Gallery will open up with a loader.
  3. Click on the loader before the image loads.
  4. Get the error below.

image

I tried to reproduce the error like described, but had no luck.

@stale
Copy link

stale bot commented Oct 31, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the v1 label Oct 31, 2023
@stale stale bot closed this as completed Nov 7, 2023
@trouba
Copy link

trouba commented Jun 12, 2024

I was able to reproduce this issue on the Carousel gallery demo: https://www.lightgalleryjs.com/demos/carousel-gallery/ by clicking on the loader just before a picture is loaded

@jacobmllr95
Copy link
Contributor

We can also see in our error tracking that this issue is still present in v2.8.2.
I was able to force the error a few times after some combination of pinch-to-zoom and using the zoom buttons - but I couldn't reproduce it reliably.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants