2

I added photoswipe (v5) to a component like this:

mounted () {
    if (!document.getElementById('psw')) {
      const script = document.createElement('script')
      script.id = 'psw'
      script.type = 'module'
      script.innerHTML = `
          import PhotoSwipeLightbox from '/js/photoswipe/photoswipe-lightbox.esm.min.js';
          const lightbox = new PhotoSwipeLightbox({ 
            gallerySelector: '#gallery--productimages',
            childSelector: 'a',
            pswpModule: '/js/photoswipe/photoswipe.esm.min.js'
          });
          lightbox.init();
        `
      document.head.appendChild(script)
    }
  },

The photoswipe files are in the static folder. The script tag is added to the DOM, but photoswipe does not execute when the page is loaded the first time (from internal route link and direct server call). When I gob back an open the page again by the internal link, or refresh the page, it works. I only want to use photoswipe in this component. How can I make it work for the first page load also?

2
  • You did not found a Vue alternative to photoswipe? Commented Jul 28, 2021 at 12:25
  • The project did not have any new commit since 3 years. I'd pass on this one tbh. Google or check the packages available there github.com/vuejs/awesome-vue#overlay Commented Jul 28, 2021 at 12:30

2 Answers 2

3
+150

I don't think that is a good way to inject scripts in your app. I usually load external packages this way:

First I create PhotoSwipe.js under plugins folder:

import PhotoSwipe from '/js/photoswipe/photoswipe.esm.min.js'
import PhotoSwipeLightbox from '/js/photoswipe/photoswipe-lightbox.esm.min.js'

export default (context, inject) => {
  inject('PhotoSwipe', PhotoSwipe)
  inject('PhotoSwipeLightbox', PhotoSwipeLightbox)
}

Then I load it in the plugins attribute inside nuxt.config.js:

plugins: [
  { src: '~/plugins/PhotoSwipe', mode: 'client' }
]

Then you can use it in any page or component this way:

data () {
  return {
    lightbox: {}
  }
},

mounted () {
  this.loadPhotoSwipeLightBox()
},
beforeDestroy () {       // added
  this.closeLightBox()
},
methods: {
  loadPhotoSwipeLightBox () {
    const options = {
      // define the images to load in lightbox
      dataSource: [
        {
          src: 'https://source.unsplash.com/Volo9FYUAzU/1620x1080',
          w: 1600,
          h: 1600,
          alt: 'test image 1'
        }
      ],
      pswpModule: this.$Photoswipe
    }
    this.lightbox = new this.$PhotoswipeLightbox(options)
    this.lightbox.init()

/*    const lightbox = new this.$PhotoSwipeLightbox({ 
      gallerySelector: '#gallery--productimages',
      childSelector: 'a',
      pswpModule: this.$PhotoSwipe
    });

    lightbox.init();
*/
  },
  openLightBox () {    // this method should be called onClick on the thumbnailimage
    this.lightbox.loadAndOpen(0)  // exchange 0 with the dynamic index of the thumbnail => to do 
  },
  closeLightBox () {
    if (this.lightbox) {
      this.lightbox.destroy()
    }
  }
}

EDIT: Use injected this.$PhotoSwipe in pswpModule instead of a url. EDIT: Added closeLightBox() to close the Lightbox also by clicking the browser back-button, using dataSource-Array to get the images loaded in lightbox

Sign up to request clarification or add additional context in comments.

10 Comments

Yep, this is a far better approach to it. While loading some local minified script is still not the best and the project being abandoned for 3 years is really not helping neither.
@kissu: There is a brandnew v5 beta of Photoswipe which I want to use. I looked at the vue plugins before, but found photoswipe most suitable for my project.
@RomanWalters I've just edited my answer adding injecting PhotoSwipe library in the same plugin, and then calling to it directly from the init function instead of using a URL. I saw it in the library documentation about how to use this in ES6 modules.
@SergioCerrutti , both worked, but the beahviour is the same as with my injection. The first click opens the image directly in the browser. Going back and clicking again starts the lightbox. (The server is hidden to load the page.) Going back while the lightbox ist open, the lightbox is not destroied and ramains open on the page visited before.
@SergioCerrutti I thought I did, but tested it right now and it workes! Thanks!
|
0

To follow what you have, I think below should work. This way I think you can enclose all relevant code in your component instead of spread theme everywhere like in nuxt plugins and nuxt.config.js.

mounted () {
  const photoswipe = '/js/photoswipe/photoswipe-lightbox.esm.min.js'
  // Prevent the script being added duplicated when have multiple photoswipe components on one page.
  const existingScript = document.head.querySelector(`script[src='${photoswipe}']`)
  if (existingScript) {
    existingScript.addEventListener('load', this.init)
  } else {
    const photoswipeScript = document.createElement('script')
    photoswipeScript.addEventListener('load', this.init)
    photoswipeScript.setAttribute('src', photoswipe)
    photoswipeScript.setAttribute('type', module)
    document.head.appendChild(photoswipeScript)
  }
},
methods: {
  init () {
    const lightbox = new PhotoSwipeLightbox({
      // To support multiple components on one page, you may need to use `ref`, add `ref="gallery"` on the same element of your id `#gallery--productimages`
      gallerySelector: this.$refs.gallery,
      childSelector: 'a',
      pswpModule: '/js/photoswipe/photoswipe.esm.min.js'
    });
    lightbox.init();
  }
}

3 Comments

Thanks for that. This looks interesting to keep all in one component. I will test it next week, when I am back. But I am afraid it will not solve the problem, that the lightbox is not destroyed, when the browsers back button is clicked...
error 'PhotoSwipeLightbox' is not defined
ohh, right, I guess you need to create another js file, say lightbox.js with this line: import PhotoSwipeLightbox from '/js/photoswipe/photoswipe-lightbox.esm.min.js'; Then replace my example second line to const photoswipe = '/js/lightbox.js'

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.