8

I have a Photoswipe (http://photoswipe.com) image gallery on my site, and the css class is not resetting/clearing to remove the view after I close a gallery for the second time.

ex. User opens item 1, AJAX populates the figure(s) into the picture div. User clicks an image from item 1 and Photoswipe opens the image properly (setting the following class):

class="pswp pswp--supports-fs pswp--open pswp--animate_opacity pswp--notouch pswp--css_animation pswp--svg pswp--animated-in pswp--visible"

User closes the image from item 1, class resets as normal:

class="pswp"

User closes item 1 and JS/JQuery clears all html in picture div. User opens item 2, AJAX populates the figure into the picture div. User clicks an image from item 2 and Photoswipe opens the image properly setting the same class as before.

class="pswp pswp--supports-fs pswp--open pswp--animate_opacity pswp--notouch pswp--css_animation pswp--svg pswp--animated-in pswp--visible"

This is where the problem occurs. User closes the image from item 2 and the only thing that changes is:

aria-hidden="true"

but the class does not clear, it remains:

class="pswp pswp--supports-fs pswp--open pswp--animate_opacity pswp--notouch pswp--css_animation pswp--svg pswp--animated-in pswp--visible"

when it should change to:

class="pswp"

This disables all interaction on the website since there is an invisible div/class on top of everything. The class needs to be changed back to pswp somehow.

AJAX/JS To Populate picture div (I added an id to the div):

if (i == 0) {
    $('#listing_photos_container').append('<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject"><a href="' + json[i].image_url + '" itemprop="contentUrl" data-size="512x400" data-index="' + i + '"><img src="' + json[i].image_url + '" height="400" width="600" itemprop="thumbnail" alt="listingPhoto" class="listing-photo"></a></figure>');
} else {
    $('#listing_photos_container').append('<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject" class="listing-photo-holder"><a href="' + json[i].image_url + '" itemprop="contentUrl" data-size="512x400" data-index="' + i + '"><img src="' + json[i].image_url + '" height="400" width="600" itemprop="thumbnail" alt="listingPhoto" class="listing-photo-holder"></a></figure>');
 }

JS/JQuery to clear photo div:

 $('#listing_photos_container').html('');

EDIT: The click listener function is running twice when a users clicks the photo to bring full screen. This is the code for the listener:

$.ajax({
    type: "POST",
    url: 'http://example.com/action?action=photos',
    data: {id: id},
    success: function (data) {
        console.log('API Call - Photos');
        json = JSON.parse(data);
        $('#listing_photos_container').html('');
        for (var i = 0; i < json.length; i++) {
            // Styling code here
        }
        $('#list_header').html(
            (function($) {
                $('.picture').each( function() {
                    var $pic = $(this),
                    getItems = function() {
                        var items = [];
                        $pic.find('a').each(function() {
                            var $href = $(this).attr('href'),
                                $size = $(this).data('size').split('x'),
                                $width = $size[0],$height = $size[1];
                            var item = {
                                src : $href,
                                w   : $width,
                                h   : $height
                            }
                            items.push(item);
                        });
                        return items;
                    }
                    var items = getItems();
                    console.log('Items for PSWP' + items); 
                    alert('Alert Point 1'); // This is called once, (as it should).
                    var $pswp = $('.pswp')[0];
                    $pic.on('click', 'figure', function(event) {
                        // This block is called twice..
                        alert('Click Funct');
                        event.preventDefault();
                        var $index = $(this).index();
                        var options = {
                            index: $index,
                            bgOpacity: 0.7,
                            showHideOpacity: true
                        }
                        // Initialize PhotoSwipe
                        alert('Setting new PhotoSwipe');
                        var lightBox = new PhotoSwipe($pswp, PhotoSwipeUI_Default, items, options);
                        lightBox.init();
                    }); // End $pic.on
                });// End .picture each
            })(jQuery)
        ); // End list_header.html
    } // End AJAX Success
}); // End AJAX
MBarton
  • 2,087
  • 2
  • 14
  • 17

3 Answers3

8

You may have already fixed this, but in case someone else falls upon this.

This can happen if you trigger opening the gallery more than once without closing it. It may be that you have registered multiple click handlers to open the gallery or for some reason the event is being fired twice.

It happens because in the init function the current class name of the pswp element is retrieved and cached, then on destroy the class name is restored. When the second open occurs without destroy being called _initialClassName will be set to class="pswp pswp--supports-fs pswp--open pswp--animate_opacity pswp--notouch pswp--css_animation pswp--svg pswp--animated-in pswp--visible" as your are seeing

Line 776 of photoswipe.js where initialclass is set

_initalClassName = template.className;

Breakpoint this in your browser to see if it is called multiple times when opening

Line 942 onwards destroy function

destroy: function() {
    _shout('destroy');

Breakpoint this in your browser to ensure it is being called for every time open is called

Final Solution

The problem is that when opening the popup and loading the images you are filling #listing_photos_container with your photos, then adding a click handler to open photoswipe. This click handler is added to the top element, so will remain when the popup is closed, then the next time it is opened a new click handler will be added.

To fix this you just need to unbind the click handler when closing the popup, you can do this with $(".picture").off('click'); somewhere inside your closeListing() function

ndonohoe
  • 9,320
  • 2
  • 18
  • 25
  • I have still not yet fixed the issue, so thank you very much. What I am filling a map with markers and on the click showing a gallery of images from that location. I'll investigate that area of code and report back. Is their a way that I can force destory? – MBarton Jul 17 '15 at 22:36
  • Destroy occurs whenever you close the gallery, either by swiping it away, pressing escape or clicking the close button, so it is probably being called correctly. I would investigate to see why it isn't being called first, I'll add some extra info to my answer – ndonohoe Jul 18 '15 at 10:18
  • You are correct that the issue is the init is being called twice when opening. I am not sure why though I added an edit that has the code the is being ran twice. The first image works normally (1 initial and 1 destroy called), the second view calls the initial twice on the image click, and destroy once. I am still investigating.. JS is not my strongest language. – MBarton Jul 20 '15 at 20:28
  • So it is the issue of the _initialClassName getting set to the "pswp pswp--supports-fs..." becuase of it being called twice. I can confirm that is the issue. Still trying to figureout why the click event is being called twice.. After adding the breakpoints and going step-by-step I saw that the first load image is set first, then gets updated to the proper second photo – MBarton Jul 20 '15 at 21:40
  • Would it be possible to get a minimal working version up on plunker or with the stack snippets functionality? I'm struggling to visualise what it is you are trying to do just from these code snippets. – ndonohoe Jul 20 '15 at 22:04
  • I'm using Polymer and had the same issue, click event was binded multiple time due to the way polymer dom-change. I would unbind event right before binding again. – Vin Lim Nov 15 '15 at 12:18
  • Was this issue ever resolved? I've been having the same problem. Like MBarton said "JS is not my strongest language"... Not really getting where to put the "$(".picture").off('click');"? In my case .picture is .slide, but I still don't really understand where this goes to unbind. Where is the closeListing() function? – axelra82 Nov 09 '16 at 14:11
  • closeListing() is specific to this persons code. Your solution will probably be different, but similar. Post a question with your code if you are unsure – ndonohoe Nov 10 '16 at 10:52
4

It's quite simple, before every .click(...) you need to write .unbind('click').

Example:

$('a#open-photoswipe').unbind('click').click(function() {
    // open photoswipe here
});
Giub Bass
  • 41
  • 1
0

Was having similar problem - just define lightBox as global variable. And on destroy define it as null. And in beginning of function where You initialize lightBox just check if lighBox is already defined, then do return.

Nick Bristol
  • 64
  • 1
  • 3