How to destroy a JQuery plugin instance before reinitialization? (Photoswipe)

1.2k views Asked by At

Photoswipe is a Vanilla JavaScript lightbox library. I am using a simple plugin that JQuery-fies Photoswipe. Everything works fine, except when I dynamically load new elements to the gallery and reinitiate the Photoswipe plugin, it starts screwing things up, i.e. not closing the lightbox overlays properly.

The plugin is simply called by doing $(element).photoswipe();. So I call it once when the elements div is first loaded and then again when the new elements are added. I have pinpointed the issue to the reinitiation but removing the first Photoswipe plugin call and just calling it ONCE after I add the new elements, and everything works fine that way.

I believe the error is in the init function below: if we could check for existing instance(s) of Photoswipe and kill them before creating the arrays, it should solve it. Or can we simply clear everything from memory that $(element).photoswipe(); creates. And that's where I am stuck.

Here's the JQuery Photoswipe plugin I am using:

(function($) {
$.fn.photoswipe = function(options){
    var galleries = [],
        _options = options;

    var init = function($this){
        galleries = [];
        $this.each(function(i, gallery){
            galleries.push({
                id: i,
                items: []
            });

            $(gallery).find('a').each(function(k, link) {
                var $link = $(link),
                    size = $link.data('size').split('x');
                if (size.length != 2){
                    throw SyntaxError("Missing data-size attribute.");
                }
                if ($(gallery).data('month')) {
                    $link.data('gallery-id',$(gallery).data('month'));
                } else {
                    $link.data('gallery-id',i+1);
                }

                $link.data('photo-id', k);

                var item = {
                    src: link.href,
                    msrc: link.children[0].getAttribute('src'),
                    w: parseInt(size[0],10),
                    h: parseInt(size[1],10),
                    title: $link.data('title'),
                    author: $link.data('author'),
                    el: link
                }

                galleries[i].items.push(item);

            });

            $(gallery).on('click', 'a', function(e){
                e.preventDefault();
                var gid = $(this).data('gallery-id'),
                    pid = $(this).data('photo-id');
                openGallery(gid,pid);
            });
        });
    }

    var openGallery = function(gid,pid){
        var pswpElement = document.querySelectorAll('.pswp')[0],
            items = galleries[gid-1].items,
            options = {
                history:false,
                index: pid,
                addCaptionHTMLFn: function(item, captionEl, isFake) {
                    if(!item.title) {
                        captionEl.children[0].innerText = '';
                        return false;
                    }
                    captionEl.children[0].innerHTML = item.title + '<br/><small>' + item.author + '</small>';
                    return true;
                },
                showHideOpacity: true
            };
        $.extend(options,_options);
        var gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);
        gallery.init();
    }

    // initialize
    init(this);

    return this;
};
}( jQuery ));
2

There are 2 answers

1
0pt1m1z3 On BEST ANSWER

I figured it out.

Photoswipe loads the full items array every a photo modal is opened. So that needs to be done when new elements are added is to append the new items to the array using JavaScript's array push.

0
Macsupport On

What works for me ( I'm using infinite-scroll to load new elements) is to call this:

$(gallery).off('click', 'a');

after adding the new elements and before calling:

$(element).photoswipe();