Shoji

Custom plugin + custom data

Each photo below carries a data-shoji-metadata-id attribute — not one of Shoji's own named fields, so it's captured into item.data['metadata-id'] (see the Getting started guide). The plugin below reads it on every afterOpen, and adds its own toolbar button — the whole plugin is about 15 lines.

Shoji not yet initialized.

Code

The markup — any data-shoji-* attribute Shoji doesn't already know about:

<a href="photo-1-full.jpg" data-shoji-metadata-id="catalog-101" data-shoji-width="800" data-shoji-height="600">
  <img src="photo-1-thumb.jpg" alt="Photo 1">
</a>
<a href="photo-2-full.jpg" data-shoji-metadata-id="catalog-102" data-shoji-width="800" data-shoji-height="600">
  <img src="photo-2-thumb.jpg" alt="Photo 2">
</a>
<a href="photo-3-full.jpg" data-shoji-metadata-id="catalog-103" data-shoji-width="800" data-shoji-height="600">
  <img src="photo-3-thumb.jpg" alt="Photo 3">
</a>

The plugin — exactly what's running above, no options object needed:

const MetadataPlugin = {
  name: 'metadataPlugin',
  init(ctx) {
    const button = document.createElement('button');
    button.type = 'button';
    button.className = 'shoji-toolbar-button'; // 44px circle, hover/focus states — all free
    button.textContent = 'ID';
    button.setAttribute('aria-label', 'Show metadata id');
    button.addEventListener('click', () => {
      const item = ctx.gallery.items[ctx.gallery.currentIndex];
      alert(`metadata-id: ${item.data?.['metadata-id']}`);
    });
    ctx.ui.toolbar('right', button);

    ctx.on('afterOpen', ({ index }) => {
      console.log(ctx.gallery.items[index].data); // { 'metadata-id': 'catalog-101' }
    });
  },
};

new Shoji('#gallery', { plugins: [MetadataPlugin] });