Download This Plugin Back To jQueryScript
A jQuery plugin that opens images, video, audio, PDF, and inline source code in a gallery lightbox with zoom, keyboard navigation, and WCAG support.
documentation.html — API and usage docs.
All types rendered by the plugin. First two images are landscape and portrait — click to see zoom/pan for both orientations. Image gets zoom slider + pan. Video/audio use jPlayer. PDF uses pdf.js with page nav, zoom, rotate, thumbnails. XLSX gets "no preview" card. Custom toolbarItems (Extract, Delete) appear alongside built-in toolbar items.
$('#post-builtin').componentViewer({ toolbar: { download: true, zoom: true }, pdf: { workerSrc: 'pdf.worker.min.js' }, // Custom buttons shown alongside built-in toolbar items toolbarItems: [ { id: 'extract', icon: '<svg>...</svg>', label: 'Extract Text', shortcutKey: 'e', onClick: function(item) { alert('Extract: ' + item.title); } }, 'separator', { id: 'delete', icon: '<svg>...</svg>', label: 'Delete', onClick: function(item) { confirm('Delete ' + item.title + '?'); } } ], onDownload: function(item) { /* custom download logic */ }, onLoading: function(item) { console.log('loading', item.type); }, onOpen: function(item) { console.log('opened', item.title); }, onClose: function(item) { console.log('closed', item.title); } // No onRender → all types use built-in renderers // No onToolbar → built-in toolbar used as-is });
Custom toolbar items can define a shortcutKey. When the viewer is open, press that key to trigger the button (e.g. E for Extract, X for Delete). Press ? to open the shortcuts popup — it lists all active shortcuts, including built-in ones (F fullscreen, T theme, C carousel, S slideshow) and your custom keys.
$('#post-toolbar-shortcuts').componentViewer({ toolbar: { download: true, zoom: true }, carousel: { enabled: true }, toolbarItems: [ { id: 'extract', label: 'Extract Text', shortcutKey: 'e', icon: '...', onClick: function(item) { ... } }, 'separator', { id: 'delete', label: 'Delete', shortcutKey: 'x', icon: '...', onClick: function(item) { ... } } ] });
Same built-in renderers, but onToolbar modifies the toolbar per type.
Adds a "Share" button to PDF toolbar. Adds "Clip" button to video toolbar.
Removes items from image toolbar. All without touching the renderer.
$('#post-ontoolbar').componentViewer({ toolbar: { download: true, zoom: true }, pdf: { workerSrc: 'pdf.worker.min.js' }, toolbarItems: [ TB_EXTRACT, 'separator', TB_DELETE ], // Modify built-in toolbar per type — without replacing the renderer onToolbar: function(item, defaultToolbar, viewer) { if (item.type === 'pdf') { // Add Share button to PDF's built-in toolbar defaultToolbar.push('separator'); defaultToolbar.push({ id: 'share', label: 'Share', onClick: fn }); return defaultToolbar; } if (item.type === 'video') { // Add Clip button to video toolbar defaultToolbar.push('separator'); defaultToolbar.push({ id: 'clip', label: 'Clip', onClick: fn }); return defaultToolbar; } if (item.type === 'image') { // Remove delete button from image toolbar return defaultToolbar.filter(function(tb) { return !tb.id || tb.id !== 'delete'; }); } // return nothing → use default toolbar unchanged } });
Customer handles video rendering themselves (native <video> instead of jPlayer). PDF is rendered as a simple iframe. Audio falls through to built-in jPlayer. Image falls through to built-in. onRender gets first shot — if it renders, built-in is skipped.
$('#post-onrender').componentViewer({ toolbar: { download: true, zoom: true }, pdf: { workerSrc: 'pdf.worker.min.js' }, toolbarItems: [ TB_DELETE ], // Full override — gets first shot before built-in renderers onRender: function(item, $stage, viewer) { if (item.type === 'video') { // Custom native HTML5 video (instead of jPlayer) var $v = $('<video controls autoplay>...</video>'); $stage.append($v); return { toolbar: [ // ← full replacement, no auto download/zoom { id: 'fullscreen', onClick: fn }, 'separator', { id: 'download', onClick: fn } ], destroy: function() { $v[0].pause(); } }; } if (item.type === 'pdf') { // Custom iframe PDF (instead of pdf.js) $stage.append('<iframe src="' + item.src + '"></iframe>'); return { toolbar: [{ id: 'open-tab', onClick: fn }] }; } // Don't handle audio/image → falls through to built-in } });
Same built-in renderers with theme: 'light'. All components — shell, toolbar, zoom slider,
video controls, audio player, PDF viewer, unsupported card — adapt to the light theme.
$('#post-light').componentViewer({ theme: 'light', toolbar: { download: true, zoom: true }, pdf: { workerSrc: 'pdf.worker.min.js' }, toolbarItems: [ TB_EXTRACT ] });
Built-in markdown type renders Markdown as HTML. Content from item.content or fetched from item.src.
This page includes marked for full CommonMark support; otherwise a minimal built-in parser is used. Click the note to preview.
$('#post-markdown').componentViewer({ toolbar: { download: true } // Content from data-content; or use data-src to fetch a .md file });
data-content; second loads from data-src (URL or path like sample.md).
Set markdown: { toggleRawView: true } to show a toolbar button that toggles between rendered Markdown and raw/source view (same line-numbered style as inline). Default is false. Useful for viewing the source of a .md file without leaving the overlay.
$('#post-markdown-toggle').componentViewer({ toolbar: { download: true }, markdown: { toggleRawView: true } });
Override jPlayer's supplied via supportedVideoFormats and
supportedAudioFormats, or per-item via data-supplied.
If not provided, auto-detected from file extension.
$('#post-supplied').componentViewer({ supportedVideoFormats: 'm4v, webmv', // jPlayer supplied for video supportedAudioFormats: 'mp3, oga', // jPlayer supplied for audio }); // Per-item override via data attribute (highest priority) // <div class="cv-item" data-type="video" data-supplied="webmv" ...> // Priority: data-supplied → supportedVideoFormats/supportedAudioFormats → auto-detect
One post with multiple attachments. Each attachment is wrapped in its own container that has
only one .cv-item. The viewer is initialized on each wrapper, so clicking
an attachment opens a single-item viewer (no prev/next) for that item only.
// One post; each attachment in a wrapper with exactly one .cv-item // Init viewer on each wrapper → each opens separately as single-item $('#post-single .cv-single-item').each(function() { $(this).componentViewer({ selector: '.cv-item', toolbar: { download: true, zoom: true }, pdf: { workerSrc: 'pdf.worker.min.js' } }); });
pdf.autoFit: true (default) scales the page to fit the stage (width and height). Resize the window to see it re-fit.
Use pdf.autoFitMaxScale to cap the zoom (default 2.5). Set autoFit: false for fit-to-width only.
$('#post-pdf-autofit').componentViewer({ toolbar: { download: true, zoom: true }, pdf: { workerSrc: 'pdf.worker.min.js', autoFit: true, // scale to fit stage (width + height); default true autoFitMaxScale: 2.5 // max zoom when autoFit (default 2.5) } });
Set pdf.twoPageView: true to show a toolbar button that toggles single- and two-page view. The PDF opens in single-page view; click the button to switch to side-by-side (spreads). In two-page mode, pages are rendered in pairs (1–2, 3–4, …); the last page appears alone if the total is odd. Auto-fit scales so both pages fit in the stage.
$('#post-pdf-twopage').componentViewer({ toolbar: { download: true, zoom: true }, pdf: { workerSrc: 'pdf.worker.min.js', twoPageView: true // side-by-side page spreads } });
Use data-thumbnail or data-poster to pass a thumbnail image URL for video items.
The overlay shows this image as the poster until play. If omitted, the default (no poster) is used.
// In HTML: data-thumbnail or data-poster on the video item <div class="cv-item" data-type="video" data-src="video.mp4" data-thumbnail="https://example.com/thumb.jpg" data-title="Demo"> <img src="https://example.com/thumb.jpg" alt="" /> </div> // No plugin option needed — thumbnailUrl is read from the element $('#post-video-thumb').componentViewer({ toolbar: { download: true } });
data-thumbnail (poster in overlay). Second: same video without thumbnail (default).
When a video item has an HD/high-quality URL (via item.hdUrl in itemData or video.onGetHdUrl callback), an HD button appears in the player. Clicking it switches playback to the HD source from the current timestamp so playback continues smoothly without restarting.
// Option 1: Set item.hdUrl in itemData (e.g. from data-hd-url attribute) // Option 2: video.onGetHdUrl(item, viewer) returns the HD URL $('#post-video-hd').componentViewer({ toolbar: { download: true }, itemData: function($el, defaultItem) { if (defaultItem.type === 'video' && $el.data('hd-url')) defaultItem.hdUrl = $el.data('hd-url'); return defaultItem; } // Or: video: { onGetHdUrl: function(item, viewer) { return item.attachmentId ? getHdUrl(item.attachmentId) : null; } } });
When jPlayer and pdf.js are not loaded, the plugin still previews video, audio, and PDF:
video and audio use native HTML5 <video> and <audio> with controls;
PDF is shown in an <iframe> (browser’s built-in viewer). To try that, use a minimal page that loads only jQuery + the plugin (omit jPlayer and PDF.js). On this page, jPlayer and PDF.js are loaded, so Case 9 items use the rich players; the same markup would use native/iframe fallbacks without those scripts.
// In your page: load only jQuery + component-viewer.js (no jPlayer, no pdf.js) // <script src="jquery.min.js"></script> // <script src="component-viewer.js"></script> // Video → native <video controls>, Audio → native <audio controls>, PDF → <iframe src="..."> $('#post-no-libs').componentViewer({ toolbar: { download: true, zoom: true } });
Type inline shows file content in the center stage with white background and line numbers.
Use item.content (string) or item.src (URL to fetch as text). The toolbar includes a Copy button (inline only): clicking it copies the file content to the clipboard and shows "Copied to clipboard" for 2 seconds. For custom HTML, use onRender: if you append an element to $stage and return, that is shown instead of the built-in viewer.
// item.content = string (pre-loaded) or item.src = URL to fetch // onRender(item, $stage, viewer): if type === 'inline' and you append HTML to $stage, it replaces built-in $('#post-inline').componentViewer({ itemData: function($el) { var type = $el.data('type'); if (type === 'inline') return { type: 'inline', title: $el.data('title'), content: INLINE_SNIPPETS[$el.data('key')] }; // ... default item from $el }, toolbar: { download: true }, onRender: function(item, $stage, viewer) { if (item.type === 'inline' && item.customHtml) { $stage.append(item.customHtml); return { toolbar: [] }; } } });
item.content (snippets), item.src (fetch from URL), or custom HTML via onRender.
Type error shows the same “cannot preview” container as Data.xlsx in Case 1: file icon, name, optional extension/size, message (default “Preview is not available for this file”), and Download button when item.src or item.downloadUrl is set. Use item.message or data-message to override the text. If onRender appends HTML to $stage for this item, that is shown instead of the default container.
// item: { type: 'error', title?, message?, fileExt?, fileSize?, src?, downloadUrl? } — all from data-* or itemData $('#post-error').componentViewer({ toolbar: { download: true } });
Type html shows user-provided HTML in the stage. No toolbar, no download. If item.title is not given, the title and counter are hidden. Provide item.html (string, jQuery object, or DOM node); if missing, an error message is shown.
// item: { type: 'html', html: '<div>...</div>' or jQuery/DOM, title?: '' } $('#post-html').componentViewer({ itemData: function($el) { ... } });
src (iframe embed, e.g. Zoho WorkDrive)
When type: 'html' and item.src is set (and passes URL checks), the plugin renders a full-stage <iframe> with classes cv-html-iframe and cv-stage-iframe.
An in-stage panel (cv-html-iframe-loader) shows the same cv-spinner as the overlay loader (like inline src loading) until the iframe fires load or error. Below: sample WorkDrive embed URL (external; requires network). If the embed blocks framing on your origin, the iframe may show an error page — that still counts as loaded and removes the spinner.
// data-type="html" data-src="https://..." — item is built from DOM; no itemData required $('#post-html-iframe').componentViewer({ toolbar: { download: true, zoom: true }, loop: false });
cv-html-iframe-loader) is removed after the embed finishes loading.
For polls where each option has an image: set pollOption: { enabled: true, mode: 'radio'|'checkbox', onSelect }.
item.title stays the image name (header); item.pollOptionLabel and optional item.pollOptionId
are shown in a row above the toolbar with a radio or checkbox. onSelect(item, selected, viewer) is called when the user toggles the option.
$('#post-poll').componentViewer({ toolbar: { download: true, zoom: true }, pollOption: { enabled: true, mode: 'radio', // or 'checkbox' onSelect: function(item, selected, viewer) { /* record vote, etc. */ } }, itemData: function($el) { // title = image name; pollOptionLabel / pollOptionId from data-* return { type: 'image', title: $el.data('title'), src: ..., pollOptionLabel: $el.data('poll-option-label'), pollOptionId: $el.data('poll-option-id') }; } });
onSelect to perform the action.mode: 'checkbox'. You can select multiple options; onSelect(item, selected, viewer) is called for each toggle. Choice 2 is shown as already selected via pollOptionSelected: true (from data-poll-option-selected).
Set showAttachmentComment: true and provide item.comments (array of { title?, author?, text }). For one comment use a single-element array. Example builds comments from data-title/data-author/data-comment in itemData.
A dark semi-transparent overlay appears at the bottom of the media; a header button toggles it.
$('#post-comment').componentViewer({ showAttachmentComment: true, toolbar: { download: true, zoom: true }, itemData: function($el, defaultItem) { var t = $el.data('title'), a = $el.data('author'), c = $el.data('comment'); if (t || a || c) defaultItem.comments = [{ title: t || '', author: a || '', text: c || '' }]; return defaultItem; } });
Set showAttachmentComment: true and provide item.comments as an array of { title?, author?, text } (e.g. in itemData). The comment overlay shows one comment at a time with prev/next arrows and a counter (e.g. "Comment 1 of 3").
$('#post-comment-multi').componentViewer({ showAttachmentComment: true, toolbar: { download: true, zoom: true }, itemData: function($el, defaultItem) { if ($el.data('multi-comment')) { defaultItem.comments = [ { title: 'Review 1', author: 'Alice', text: 'First review: Great shot of the landscape.' }, { title: 'Review 2', author: 'Bob', text: 'Second take: The lighting is perfect here.' }, { text: 'Anonymous note: Captured in spring 2024.' } ]; } return defaultItem; } });
When an image has an invalid/unsafe URL or fails to load, the viewer shows an error card without a download button, and the toolbar has no download option. First item: invalid URL (not http/https). Second item: valid URL that returns 404 so the image fails to load.
// No special options — built-in image renderer shows error card (no download) when URL is unsafe or load fails $('#post-image-failure').componentViewer({ toolbar: { download: true, zoom: true } });
Use onError(context) to show your own error UI when a built-in error occurs (e.g. image load failed, PDF failed).
context has type (e.g. 'image', 'pdf'), message, item, and $stage.
Return true to skip the default error card; otherwise the plugin shows its built-in card.
$('#post-onerror').componentViewer({ toolbar: { download: true, zoom: true }, onError: function(ctx) { ctx.$stage.empty().append( '<div class="cv-error-card" style="padding:24px;text-align:center;">' + '<p style="font-size:15px;margin:0 0 8px;">Custom error: ' + ctx.type + '</p>' + '<p style="opacity:.8;font-size:13px;">' + ctx.message + '</p>' + '<p style="font-size:12px;opacity:.6;margin-top:12px;">' + (ctx.item.title || '') + '</p>' + '</div>' ); return true; // skip default error card } });
onError; we show a custom message and skip the default card.
With loop: false, prev/next do not wrap: on the first item, Previous does nothing; on the last item, Next does nothing.
Use this when you want a linear sequence without cycling back to the start or end.
$('#post-loop-false').componentViewer({ loop: false, toolbar: { download: true, zoom: true }, pdf: { workerSrc: 'pdf.worker.min.js' } });
With showCounter: false, the header does not show the "1 / N" counter.
Use this when you want a cleaner overlay without the item index.
$('#post-counter-hidden').componentViewer({ showCounter: false, toolbar: { download: true, zoom: true }, pdf: { workerSrc: 'pdf.worker.min.js' } });
With carousel: { enabled: true }, a button (thumbnails icon) appears in the overlay header. Click it to show a strip of thumbnails below the stage (centered, 4 visible at a time). Use the arrows to scroll; click a thumbnail to go to that item. Video items show data-thumbnail with a play icon. When there are more than 4 items, prev/next buttons appear (carousel.navThreshold: 4).
$('#post-carousel').componentViewer({ carousel: { enabled: true, navThreshold: 4 }, toolbar: { download: true, zoom: true }, pdf: { workerSrc: 'pdf.worker.min.js' } });
When the number of attachments is less than or equal to carousel.navThreshold, the carousel prev/next arrows are hidden. This example has 5 items with carousel.navThreshold: 6, so no arrows appear — all thumbnails fit in the strip.
$('#post-carousel-few').componentViewer({ carousel: { enabled: true, navThreshold: 6 }, toolbar: { download: true, zoom: true }, pdf: { workerSrc: 'pdf.worker.min.js' } });
One post with all built-in types: image, video, audio, PDF, inline (code), error (cannot preview), HTML, and unsupported (XLSX). Carousel view is enabled so you can see thumbnails or labels for each type in the strip.
$('#post-carousel-all-types').componentViewer({ carousel: { enabled: true }, toolbar: { download: true, zoom: true }, pdf: { workerSrc: 'pdf.worker.min.js' }, itemData: function($el, defaultItem) { var t = $el.data('type'); if (t === 'inline') { defaultItem.type = 'inline'; defaultItem.content = '// Sample code\nfunction hello() { return true; }'; } if (t === 'html') { defaultItem.type = 'html'; defaultItem.html = '<p style="padding:16px">Custom HTML content.</p>'; } return defaultItem; } });
Same set of types as Case 19 with slideshow enabled: auto-advances every 4 seconds (configurable). Use the toolbar "Play slideshow" / "Pause slideshow" to control. slideshow: { enabled: true, interval: 4, autoStart: true, advanceMedia: 'interval' }.
$('#post-slideshow-all-types').componentViewer({ carousel: { enabled: true }, slideshow: { enabled: true, interval: 4, autoStart: true, advanceMedia: 'interval' }, toolbar: { download: true, zoom: true }, pdf: { workerSrc: 'pdf.worker.min.js' }, itemData: function($el, defaultItem) { var t = $el.data('type'); if (t === 'inline') { defaultItem.type = 'inline'; defaultItem.content = '// Sample code\nfunction hello() { return true; }'; } if (t === 'html') { defaultItem.type = 'html'; defaultItem.html = '<p style="padding:16px">Custom HTML content.</p>'; } return defaultItem; } });
Same as Case 20 but with autoStart: false. The overlay opens with the toolbar showing Play slideshow; the slideshow does not start until you click it. Then it shows Pause slideshow; click again to pause. slideshow: { enabled: true, interval: 4, autoStart: false, advanceMedia: 'interval' }.
$('#post-slideshow-no-autostart').componentViewer({ carousel: { enabled: true }, slideshow: { enabled: true, interval: 4, autoStart: false, advanceMedia: 'interval' }, toolbar: { download: true, zoom: true }, pdf: { workerSrc: 'pdf.worker.min.js' } });
With stageOnly: { enabled: true }, the overlay shows only the center stage and prev/next navigation. Header (title, counter, close, theme, fullscreen, carousel) and footer (toolbar, zoom) are hidden. Close with Escape or by clicking the backdrop (if overlayClose: true). You can also pass stageOnly: true as a shorthand for { enabled: true }.
$('#post-stage-only').componentViewer({ stageOnly: { enabled: true }, overlayClose: true, keyboardNav: true });
Same as Case 22 but with stageOnly: { enabled: true, hideNavigation: true }. The prev/next arrow buttons are hidden; the user moves between images only with keyboard (Left/Right arrow keys). Close with Escape or backdrop click.
$('#post-stage-only-keyboard').componentViewer({ stageOnly: { enabled: true, hideNavigation: true }, overlayClose: true, keyboardNav: true });
Combines stageOnly: { enabled: true, hideNavigation: true } with slideshow: { enabled: true, autoStart: true, hideSlideshowButton: true }. All UI is hidden: header, footer, and prev/next buttons. The overlay shows only the stage; items auto-advance every 4 seconds. Use keyboard (Left/Right) to move or Escape to close. No Play/Pause button — close the overlay to stop the slideshow.
$('#post-slideshow-hide-btn').componentViewer({ stageOnly: { enabled: true, hideNavigation: true }, slideshow: { enabled: true, interval: 4, autoStart: true, hideSlideshowButton: true, advanceMedia: 'interval' }, overlayClose: true, keyboardNav: true });
With wcag: true, the viewer enables accessibility behavior: focus trap (Tab cycles only inside the overlay), focus save/restore on open/close, initial focus on the close button, and ARIA attributes (dialog role, aria-modal, aria-labelledby/describedby, and aria-label on buttons). Use Tab to move between controls; focus returns to the trigger when you close. Inspect the overlay buttons in DevTools to see aria-label on close, attachments, fullscreen, theme, prev/next, zoom, etc.
$('#post-wcag').componentViewer({ wcag: true, toolbar: { download: true, zoom: true }, carousel: { enabled: true }, pdf: { workerSrc: 'pdf.worker.min.js' } });
aria-label for screen readers.
With canShowTooltip: false, the viewer does not show any hover tooltips on header/footer/toolbar buttons. Buttons behave the same; only the custom tooltip popup is disabled. Compare with other cases where hovering a button shows a tooltip.
$('#post-no-tooltip').componentViewer({ canShowTooltip: false, toolbar: { download: true, zoom: true }, carousel: { enabled: true } });
GIF files are rendered as image type (use data-type="image" or omit type). The built-in image renderer uses <img src="...">, so the browser displays and animates the GIF in the viewer with the same zoom and pan behavior as other images.
$('#post-gif').componentViewer({ toolbar: { download: true, zoom: true }, carousel: { enabled: true } }); // GIF uses type "image" — no special config needed
Same as Case 21 (slideshow, manual start) but with showProgress: true. A thin progress bar appears in the footer and fills over the slide interval to show time until the next slide. Use Play slideshow to start; the bar animates each 4 seconds. slideshow: { enabled: true, interval: 4, autoStart: false, showProgress: true }.
$('#post-slideshow-progress').componentViewer({ carousel: { enabled: true }, slideshow: { enabled: true, interval: 4, autoStart: false, showProgress: true, advanceMedia: 'interval' }, toolbar: { download: true, zoom: true } });
isRTL: true)
Sets isRTL: true to render the overlay in RTL mode. This mirrors navigation placement,
carousel controls/direction, and keyboard/swipe prev-next mapping while keeping the same item data flow.
$('#post-rtl').componentViewer({ isRTL: true, carousel: { enabled: true }, toolbar: { download: true, zoom: true } });
Enable minimize: { enabled: true } to show a header minimize button. Minimizing collapses the viewer to a floating restore icon.
Click the icon to restore the current item. If the bound element becomes hidden while minimized, restore still shows the captured item snapshot.
If you click another attachment while minimized, the viewer expands and loads that clicked item.
$('#post-minimize').componentViewer({ minimize: { enabled: true }, carousel: { enabled: true }, toolbar: { download: true, zoom: true } });
// Renderer priority: // 1. onRender(item, $stage, viewer) — customer full override (first shot) // 2. Built-in renderer (image/video/audio/pdf/inline/error/html) // 3. Unsupported "no preview" card // // Toolbar priority: // onRender returns { toolbar } → full replacement (no auto download/zoom) // Built-in renderer toolbar + toolbarItems + download + zoom(image only) // → passed through onToolbar(item, toolbar, viewer) for modification // // What each type shows (built-in mode): // image → [toolbarItems] + zoom slider + download (zoom/pan built-in) // video → jPlayer in stage, [toolbarItems] + download // audio → jPlayer in stage, [toolbarItems] + download // pdf → pdf.js in stage, [thumbs|◁|page|▷|zoom±|rotate|print] + [toolbarItems] + download // inline → white bg + line numbers (item.content or item.src), [toolbarItems] + download // error → cannot-preview card (same as unsupported: icon, name, message, Download); onRender can override // html → user-provided HTML only; no toolbar, no download; title/counter hidden if no title // other → "no preview" card, [toolbarItems] + download // pollOption → when enabled and item.pollOptionLabel, row above toolbar with option label + radio/checkbox; onSelect(item, selected, viewer)
A toolbar is an array of items. Each item can be an object, a separator string, or a raw DOM element.
// ─── Toolbar Item Schema ───────────────────────────────── { id: 'download', // unique id → CSS class cv-tb-download icon: '<svg>...</svg>', // HTML string or CSS class name label: 'Download', // tooltip text showLabel: false, // if true, label shows as text beside icon className: 'my-custom-class', // extra CSS class on the button visible: true, // boolean or function(item, viewer) onClick: function(item, viewer) {} // click handler } // ─── Separator ─────────────────────────────────────────── 'separator' // or '-' // ─── Raw DOM Element ───────────────────────────────────── $('<span class="page-label">Page 1</span>')[0] // ─── Conditional Visibility ────────────────────────────── { id: 'extract', visible: function(item, viewer) { return item.type === 'image' || item.type === 'pdf'; }, onClick: function(item) { ... } } // ─── Icon as CSS class (Font Awesome, etc.) ────────────── { id: 'share', icon: 'fa-solid fa-share-nodes', label: 'Share' } // ─── Icon as SVG HTML string ───────────────────────────── { id: 'zoom', icon: '<svg width="18" height="18" ...>...</svg>' } // ─── Button with visible label text ────────────────────── { id: 'save', icon: 'fa-solid fa-floppy-disk', label: 'Save', showLabel: true } // ─── Full Example: building a toolbar array ────────────── var myToolbar = [ { id: 'prev-page', icon: '<svg>◁</svg>', label: 'Prev', onClick: function() { goToPrevPage(); } }, $('<span>Page 1 / 10</span>')[0], // raw DOM element { id: 'next-page', icon: '<svg>▷</svg>', label: 'Next', onClick: function() { goToNextPage(); } }, 'separator', { id: 'print', icon: 'fa-solid fa-print', label: 'Print', visible: function(item) { return item.type === 'pdf'; }, onClick: function() { window.print(); } }, { id: 'download', icon: $.fn.componentViewer.Icons.download, label: 'Download', onClick: function(item) { /* download logic */ } } ]; // ─── Where toolbars are used ───────────────────────────── // 1. Default custom items (shown alongside built-in zoom/download) toolbarItems: myToolbar // 2. Returned from onRender (full replacement, no auto download/zoom) onRender: function(item, $stage, viewer) { return { toolbar: myToolbar }; } // 3. Returned from built-in renderers (PDF page nav, etc.) // → merged with toolbarItems + auto download // → passed through onToolbar for modification // 4. Modified via onToolbar onToolbar: function(item, defaultToolbar, viewer) { defaultToolbar.push('separator'); defaultToolbar.push({ id: 'share', onClick: fn }); return defaultToolbar; }
// Priority order: // 1. data-supplied attribute on the element (per-item) // 2. supportedVideoFormats / supportedAudioFormats (per-post init) // 3. Auto-detect from file extension // // Extension → jPlayer format mapping: // mp4/m4v → m4v webm → webmv ogv → ogv flv → flv // mp3 → mp3 m4a → m4a ogg/oga → oga wav → wav // // Examples: // Separate formats for video and audio $('#post').componentViewer({ supportedVideoFormats: 'm4v, webmv', supportedAudioFormats: 'mp3, oga' }); // Per-item override via data attribute (highest priority) // <div class="cv-item" data-type="video" data-supplied="webmv" data-src="clip.webm"> // Auto-detect (default — no override needed) // <div class="cv-item" data-type="video" data-src="clip.mp4"> → supplied: 'm4v' // <div class="cv-item" data-type="audio" data-src="song.mp3"> → supplied: 'mp3'