Shoji

Methods & properties

The full gallery instance surface — everything callable/readable on a new Shoji(el, options) result. Full type signatures are also in the API reference; this page groups them by what they're for.

Navigation

Method What it does
gallery.open(index?) Opens the lightbox, to index (default: the index option, or 0). No-op if already open.
gallery.close() Closes it, animating back into the origin thumbnail if one can be found. Always works, even with closable: false — that option only gates the four viewer-triggered close paths (button, backdrop, Escape, swipe), never this call.
gallery.goTo(index, options?) Jumps to index directly — always clamps an out-of-range value (a directed jump, not a step, so loop doesn't apply). { animate: false } skips the configured mode transition for an instant jump.
gallery.next() / gallery.prev() Steps one slide — wraps past the ends by default (loop: true), clamps instead if you set it false.

Data

Method What it does
gallery.updateSlides(items, currentIndex?) Replaces the item list — dynamic mode's core update path. Diffs by id (falling back to src) to preserve the active slide across the change when possible, instead of resetting to index 0.
gallery.addSlides(items, atIndex?) Sugar over updateSlides() for inserting — splices into a copy of the current list (default: append at the end) and hands the result off. Array.prototype.splice semantics for atIndex (negative counts from the end).
gallery.removeSlides(match) Sugar for removing — a single id/index, or an array mixing both. match as a number is a position in the list as it is now, resolved before any removal ([0, 1] removes the first two items, not "index 0, then whatever became index 1 after that").
gallery.refresh() Selector-mode only — re-scans the DOM and calls updateSlides() with the result. A no-op (with a console warning) in dynamic mode; call updateSlides() yourself there instead.

Instance lifecycle

Method What it does
gallery.reinit(options?) Full teardown + reconstruction on the same gallery object, not a new one — any held reference (Gallery.getInstance(el) included) keeps working across the call. Omit options to rebuild unchanged (a hard reset); pass new ones to reconfigure structurally (e.g. a different plugins list). gallery.on(...) listeners do not survive — the event bus is fully cleared, same as destroy() — re-on() anything you still need afterward.
gallery.destroy() Removes all listeners, DOM, observers, and any plugin's own cleanup (init()'s returned function). Idempotent — a second call is a no-op.

Introspection

Member What it tells you
gallery.items The current item list (readonly GalleryItem[]).
gallery.currentIndex The active slide's index.
gallery.isOpen true from the first open() until close()/destroy().
gallery.isDestroyed true once destroy() has run — a defensive check for a possibly-stale held reference.
gallery.controlsHidden Whether auto-hide currently has the toolbar/nav/counter/caption faded out. controls:hide/controls:show (see the Events guide) report every transition; this is for code that mounts later and needs the current state immediately.
gallery.hideControls() Forces the same fade the idle auto-hide timer would eventually trigger on its own — for a plugin or host that wants to hide controls immediately on its own trigger, without waiting out autoHideDelay. A no-op while a control is genuinely hovered/focused, same as the timer itself.
gallery.getActiveMedia() The active slide's .shoji-slide-media container element, or null once destroyed.
gallery.getOriginElement(index) The thumbnail for index — a data-shoji-id marker if present, else the scanned selector-mode element, else null. What the open/close zoom transition animates to/from.
gallery.markIntentionalScroll() Tells the page-scroll lock not to restore the pre-open scroll position on close() — for a plugin (like ActiveThumbnail) that deliberately scrolls the host page while the lightbox is open. Exposed as a method rather than left as something a plugin imports from a core module directly, since the core+plugins standalone distribution (see Getting started) bundles each plugin file separately from core — a direct import would silently get its own disconnected copy of that internal state in that distribution mode. Going through the shared Gallery instance always reaches the real one, regardless of which distribution shape loaded it.
gallery.getActivePlugins() Names of plugins that actually initialized on this instance — deduplicated, excluding invalid entries or ones skipped for an unmet requires. See the Plugins guide.

Events

gallery.on(event, fn) returns an unsubscribe function — there's no separate off(). Full event catalog on the Events guide.

const unsubscribe = gallery.on('afterSlide', ({ index }) => console.log(index));
unsubscribe();

Static (on Shoji/Gallery, not an instance)

Member What it does
Gallery.getInstance(el) The gallery constructed on el, if any — undefined otherwise.
Gallery.instances() Every live gallery on the page — an iterator, for page-wide teardown or devtools inspection.
Shoji.version The loaded library's version string, read from package.json at build time — e.g. for including in a bug report.

For plugin authors

gallery.registerZoomGate(isZoomed) is a specialized hook (single mutable slot, not a multi-subscriber event) that suspends core's own drag-to-navigate/drag-to-close entirely while the registered predicate returns true — what the Zoom plugin uses so a pan gesture while zoomed in never also changes slides. Only relevant if you're building something with its own pan/zoom interaction; see the Plugins guide for the rest of the plugin-authoring surface (ctx.gallery is this same full method list, from inside a plugin's init()).