arnowelzel / lightbox-photoswipe

Integration of PhotoSwipe to WordPress
https://arnowelzel.de/wp/en/projects/wordpress/lightbox-with-photoswipe
GNU General Public License v2.0
27 stars 7 forks source link

Adding images dynamically to Photoswipe after they are loaded with ajax #92

Open haraldballuch opened 2 years ago

haraldballuch commented 2 years ago

As far as I understand, this should work already. See for example https://wordpress.org/support/topic/pswp-on-images-loaded-via-ajax-have-stopped-working-as-of-v3-0-7/ Is there a special way how the new images should be added to the page? In my case I simply load the content of a wordpress page into an overlay. And in this content are images and/or galleries. In other cases it seems, that the images are added to a gallery, that is already noticed by photoswipe and maybe this makes a difference? Is there a way to get this to work in my case?

arnowelzel commented 2 years ago

Yes handling images which are added to the DOM is indeed already solved by adding a handler in the frontend script long ago:

https://github.com/arnowelzel/lightbox-photoswipe/blob/5.0.4/src/js/frontend.js#L470-L486

https://github.com/arnowelzel/lightbox-photoswipe/blob/5.0.4/assets/ps5/frontend.js#L467-L483

However this only works if the document itself is changed and therefore the DOM triggers the mutation observer.

If this does not work for you, you can try the following:

Extend src/frontend.js and assets/ps5/frontend.js with a global reference to lbwpsInit() so the function can be called if needed:

lbwpsReady(function() {
    window.lbwpsPhotoSwipe = null;
    window.lbwpsInit = lbwpsInit;

Run the minifier script to update the minifed versions of the script:

php build.php

Then you can call that function if needed to add the gallery data:

lbwpsInit(true);

If this works for you I will include this with the next update.

haraldballuch commented 2 years ago

Thank you very much, for your answer! I expected, that this wouldn't work because I already saw that the MutationOberver fires if I open the overlay and lbwpsInit(true) is executed. And indeed it didn't change the behavior. The only difference is, that lbwpsInit(true) is run multiple times, if I execute it via my script too. To me it seems, that the problem is, that lbwpsInit doesn't find the images. Interestingly if I close the overlay lbwpsInit(true) is not executed in every case. On a first glance it looks like it is only executed if there is an image in the overlay, but not, if there is no image or if there is only a gallery with images. When I open an overlay lbwpsInit(true) is run every time, and it makes no difference if there are images or galleries or no images and no galleries in the added content.

haraldballuch commented 2 years ago

Is it possible, that my html, that is loaded into the overlay should have been parsed by lbps on server side with php to add some attributes? And that the images are not added to the lightbox because the attributes are missing? I use WP_Query to get the post and after the_post I use get_template_part() to put the content of the post (it is a CPT) into the overlay. Maybe there is some hook not called, that would be called in case of showing a post in the standard way and that would instantiate the processing by lbps?

arnowelzel commented 2 years ago

Yes, the image links (not the images, its the links to the images which are important) need certain attributes to be usable. These are normally added by my plugin to the HTML code using an output filter.

The minimum required attributes are data-lbwps-width and data-lbwps-height which tell PhotoSwipe the exact dimensions of the image. In addition you can also provide a lower resolution preview with data-lbwps-srcsmall which should have the same aspect ratio as the final image. My plugin usually automatically detects lower resolution version from the WordPress media library and uses them for the opening transition.

For example see the source here: https://wordpress-demo.arnowelzel.de/lightbox-with-photoswipe-5-overlay-caption/

<a href="https://wordpress-demo.arnowelzel.de/wp-content/uploads/2020/07/DSC00746.jpg"
data-lbwps-width="5472"
data-lbwps-height="3648"
data-lbwps-srcsmall="https://wordpress-demo.arnowelzel.de/wp-content/uploads/2020/07/DSC00746-300x200.jpg"
data-lbwps-caption="This is a place in &lt;b&gt;Augsburg&lt;/b&gt;."
data-lbwps-exif="&lt;span class=&quot;pswp__caption__exif_camera&quot;&gt;SONY DSC-RX100M4&lt;/span&gt; &lt;span class=&quot;pswp__caption__exif_focal&quot;&gt;70mm&lt;/span&gt; &lt;span class=&quot;pswp__caption__exif_fstop&quot;&gt;f/8&lt;/span&gt; &lt;span class=&quot;pswp__caption__exif_shutter&quot;&gt;1/80s&lt;/span&gt; &lt;span class=&quot;pswp__caption__exif_iso&quot;&gt;ISO200&lt;/span&gt; &lt;span class=&quot;pswp__caption__exif_datetime&quot;&gt;2018-09-15&lt;/span&gt; ">
haraldballuch commented 2 years ago

Thank you for your explanation! So the good news is, that your MutationOberserver probably works and that only the missing attributes are the problem. Would there be a way how I send my html through your filter before I put it into the overlay? The php code that creates the html is inside wordpress. So in principle wordpress and your plugin should be "there" somehow. If this is not possible, there is probably no other way, but to write some code to add this information to the tags myself. By the way: Thank you for your help. And thank you for your brilliant plugin!

haraldballuch commented 2 years ago

This is a dirty workaround, that seems to work sufficiently in my case: use LightboxPhotoSwipe\LightboxPhotoSwipe;

and then later in the function that responds to the ajax call:

$photoswipe = new LightboxPhotoSwipe(''); ob_start([$photoswipe, 'filterOutput']); get_template_part( 'template-parts/content', get_post_type() );

It would be a bit less dirty if it would be possible to use the class in a static way. But I am not sure if it would be possible to declare these functions static or if there are some constrains that impede this. I didn't test it a lot, but for example the option that galleries are in a separate lightbox doesn't work, if the html is parsed in this way. What do you think of this? Would there be a better way to accomplish this?

arnowelzel commented 2 years ago

This looks dangerous to me, since the constructor of LightboxPhotoSwipe\LightboxPhotoSwipe also registers filters and hooks for activating and deactivating the plugin and I don't know what happens if the same hooks get registered with an empty parameter for the main plugin file (which is the parameter for the constructor).

The plugin initializes a new instance of its main class as $lightbox_photoswipe. So you might also use:

ob_start();
get_template_part( 'template-parts/content', get_post_type());
$output = ob_get_clean();
echo $lightbox_photoswipe->filteroutput($output);