Skip to content

Thumbnails ​

This section describes the UI structure, layout, and tabs of the thumbnail panel. For related fragment operations, see UI fragments. For more component APIs, see the API Reference.

Thumbnail panel component structure ​

Before customizing the thumbnail UI, understand how these components are structured:

  1. thumbnail Addon
  2. Thumbnail panel
  3. Thumbnail list

thumbnail Addon ​

Before using thumbnail components, ensure the thumbnail addon is loaded correctly (see here). For how to load addons, see here.

Thumbnail panel ​

In the built-in layout template, <thumbnail-sidebar-panel></thumbnail-sidebar-panel> is the left sidebar thumbnail panel. It is equivalent to the template below:

html
<thumbnail:sidebar-panel name="sidebar-thumbnail-panel" @lazy-content="active">
    <thumbnail:toolbar></thumbnail:toolbar>
    <thumbnail:complete-thumbnail-list></thumbnail:complete-thumbnail-list>
</thumbnail:sidebar-panel>

It contains two child components: <thumbnail:toolbar> and <thumbnail:complete-thumbnail-list>. To change the structure, you can use a template like this:

html
<thumbnail:sidebar-panel name="sidebar-thumbnail-panel" @lazy-content="active">
    <thumbnail:complete-thumbnail-list></thumbnail:complete-thumbnail-list>
    <thumbnail:toolbar></thumbnail:toolbar>
</thumbnail:sidebar-panel>

Next, replace the built-in sidebar-thumbnail-panel via fragment configuration:

html
<script>
    const libPath = window.top.location.origin + '/lib';
    const FRAGMENT_ACTION = UIExtension.UIConsts.FRAGMENT_ACTION;
    const pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: UIExtension.appearances.adaptive.extend({
            getDefaultFragments() {
                return [{
                    target: 'sidebar-thumbnail-panel',
                    action: FRAGMENT_ACTION.REPLACE,
                    template: `
                        <thumbnail:sidebar-panel name="sidebar-thumbnail-panel" @lazy-content="active">
                            <thumbnail:complete-thumbnail-list></thumbnail:complete-thumbnail-list>
                            <thumbnail:toolbar></thumbnail:toolbar>
                        </thumbnail:sidebar-panel>
                    `
                }]
            }
        }),
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
json
{
  "iframeOptions": {
    "style": "height: 500px"
  }
}

Thumbnail list ​

<thumbnail:complete-thumbnail-list> is a component that provides the full thumbnail list functionality, as shown below:

html
<thumbnail:thumbnail-list
        @thumbnail:centered
        @thumbnail:rearrange-pages
        @thumbnail:drop-to-merge-doc
        @aria:label="thumbnail:title"
>
    <thumbnail:thumbnail-item
            @foreach="thumbnail in thumbnail_list.thumbnails track by id"
            @setter.thumbnail_id="thumbnail.id"
            @lazy-content="visible"
    >
        <div class="fv__ui-thumbnail-viewer-container">
            <thumbnail:thumbnail-viewer @setter.thumbnail="thumbnail"
                                        @thumbnail:visible-rect-control></thumbnail:thumbnail-viewer>
        </div>
        <div class="fv__ui-thumbnail-item-label">@{thumbnail.pageIndex+1}</div>
    </thumbnail:thumbnail-item>
</thumbnail:thumbnail-list>

The structure of each part is described below:

NodeStructureTypeRequiredDescription
<thumbnail:thumbnail-list>@thumbnail:centeredDirectiveNoWhen the user drags the sidebar to resize it, keeps thumbnail items wrapping and centered
<thumbnail:thumbnail-list>@thumbnail:rearrange-pagesDirectiveNoSupports dragging thumbnails to reorder PDF pages
<thumbnail:thumbnail-list>@thumbnail:drop-to-merge-docDirectiveNoInserts a PDF dragged from outside into the list at the drop position
<thumbnail:thumbnail-list>@aria:label="thumbnail:title"DirectiveNoAccessibility attribute
<thumbnail:thumbnail-item>@foreach="thumbnail in thumbnail_list.thumbnails track by id"DirectiveYesDirective that builds the thumbnail list; do not change
<thumbnail:thumbnail-item>@setter.thumbnail_id="thumbnail.id"DirectiveYesRequired directive that sets the thumbnail id
<thumbnail:thumbnail-item>@lazy-content="active"DirectiveNoImproves thumbnail load performance
div.fv__ui-thumbnail-viewer-container-HTML ElementYesContainer for thumbnail-viewer; no changes needed
<thumbnail:thumbnail-viewer>@thumbnail:visible-rect-controlDirectiveNoMarks and controls the visible PDF region
div.fv__ui-thumbnail-item-label-HTML ElementNoContainer for page thumbnail info; customize to show more information

When customizing the thumbnail list, replace <thumbnail:complete-thumbnail-list> with the template above, as shown below:

html
<script>
    const libPath = window.top.location.origin + '/lib';
    const FRAGMENT_ACTION = UIExtension.UIConsts.FRAGMENT_ACTION;
    const pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: UIExtension.appearances.adaptive.extend({
            getDefaultFragments() {
                return [{
                    target: 'sidebar-thumbnail-panel',
                    action: FRAGMENT_ACTION.REPLACE,
                    template: `
                        <thumbnail:sidebar-panel name="sidebar-thumbnail-panel" @lazy-content="active">
                            <thumbnail:toolbar></thumbnail:toolbar>
                            <thumbnail:thumbnail-list
                                @thumbnail:centered
                                @thumbnail:rearrange-pages
                                @thumbnail:drop-to-merge-doc
                                @aria:label="thumbnail:title"
                            >
                                <thumbnail:thumbnail-item
                                    @foreach="thumbnail in thumbnail_list.thumbnails track by id"
                                    @setter.thumbnail_id="thumbnail.id"
                                    @lazy-content="visible"
                                >
                                    <div class="fv__ui-thumbnail-viewer-container">
                                        <thumbnail:thumbnail-viewer @setter.thumbnail="thumbnail" @thumbnail:visible-rect-control></thumbnail:thumbnail-viewer>
                                    </div>
                                    <div class="fv__ui-thumbnail-item-label">@{thumbnail.pageIndex+1}</div>
                                </thumbnail:thumbnail-item>
                            </thumbnail:thumbnail-list>
                        </thumbnail:sidebar-panel>
                    `
                }]
            }
        }),
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
json
{
  "iframeOptions": {
    "style": "height: 500px"
  }
}

Running the example above produces the same result as the built-in implementation.

Get started with thumbnails ​

Customizing thumbnails includes:

Customize thumbnail item information ​

Change <div class="fv__ui-thumbnail-item-label">@{thumbnail.pageIndex+1}</div> to <div class="fv__ui-thumbnail-item-label">Page: @{thumbnail.pageIndex+1}</div>. The result is shown below:

html
<script>
    const libPath = window.top.location.origin + '/lib';
    const FRAGMENT_ACTION = UIExtension.UIConsts.FRAGMENT_ACTION;
    const pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: UIExtension.appearances.adaptive.extend({
            getDefaultFragments() {
                return [{
                    target: 'sidebar-thumbnail-panel',
                    action: FRAGMENT_ACTION.REPLACE,
                    template: `
                        <thumbnail:sidebar-panel name="sidebar-thumbnail-panel" @lazy-content="active">
                            <thumbnail:toolbar></thumbnail:toolbar>
                            <thumbnail:thumbnail-list
                                @thumbnail:centered
                                @thumbnail:rearrange-pages
                                @thumbnail:drop-to-merge-doc
                                @aria:label="thumbnail:title"
                            >
                                <thumbnail:thumbnail-item
                                    @foreach="thumbnail in thumbnail_list.thumbnails track by id"
                                    @setter.thumbnail_id="thumbnail.id"
                                    @lazy-content="visible"
                                >
                                    <div class="fv__ui-thumbnail-viewer-container">
                                        <thumbnail:thumbnail-viewer @setter.thumbnail="thumbnail" @thumbnail:visible-rect-control></thumbnail:thumbnail-viewer>
                                    </div>
                                    <div class="fv__ui-thumbnail-item-label">Page: @{thumbnail.pageIndex+1}</div>
                                </thumbnail:thumbnail-item>
                            </thumbnail:thumbnail-list>
                        </thumbnail:sidebar-panel>
                    `
                }]
            }
        }),
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
json
{
  "iframeOptions": {
    "style": "height: 500px"
  }
}

You can also adjust the thumbnail structure and insert more components:

html
<script>
    const libPath = window.top.location.origin + '/lib';
    const FRAGMENT_ACTION = UIExtension.UIConsts.FRAGMENT_ACTION;
    const pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: UIExtension.appearances.adaptive.extend({
            getDefaultFragments() {
                return [{
                    target: 'sidebar-thumbnail-panel',
                    action: FRAGMENT_ACTION.REPLACE,
                    template: `
                        <thumbnail:sidebar-panel name="sidebar-thumbnail-panel" @lazy-content="active">
                            <thumbnail:toolbar></thumbnail:toolbar>
                            <thumbnail:thumbnail-list
                                @thumbnail:centered
                                @thumbnail:rearrange-pages
                                @thumbnail:drop-to-merge-doc
                                @aria:label="thumbnail:title"
                            >
                                <thumbnail:thumbnail-item
                                    @foreach="thumbnail in thumbnail_list.thumbnails track by id"
                                    @setter.thumbnail_id="thumbnail.id"
                                    @lazy-content="visible"
                                >
                                    <div class="my-thumbnail-item-toolbox">
                                        <button @controller="thumbnail:DeletePageController">delete</button>
                                        <button @controller="thumbnail:RotateRightController">rotate right</button>
                                        <button @controller="thumbnail:RotateLeftController">rotate left</button>
                                    </div>
                                    <div class="fv__ui-thumbnail-viewer-container">
                                        <thumbnail:thumbnail-viewer @setter.thumbnail="thumbnail" @thumbnail:visible-rect-control></thumbnail:thumbnail-viewer>
                                    </div>
                                </thumbnail:thumbnail-item>
                            </thumbnail:thumbnail-list>
                        </thumbnail:sidebar-panel>
                    `
                }]
            }
        }),
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
<style>
    .my-thumbnail-item-toolbox {
        display: flex;
        padding: 0.2em 0;
        flex-direction: row;
    }

    .my-thumbnail-item-toolbox button {
        height: 2em;
        line-height: 1;
        font-size: 12px;
    }
</style>
json
{
  "iframeOptions": {
    "style": "height: 500px"
  }
}

Customize the thumbnail context menu ​

The thumbnail context menu template is shown below:

html
<contextmenu name="fv--thumbnail-contextmenu" @thumbnail:permission>
    <contextmenu-item feature="rotate" name="contextmenu-item-thumbnail-rotate-left"
                      @controller="thumbnail:RotateLeftController">thumbnail:contextmenu.rotateLeft
    </contextmenu-item>
    <contextmenu-item feature="rotate" name="contextmenu-item-thumbnail-rotate-right"
                      @controller="thumbnail:RotateRightController">thumbnail:contextmenu.rotateRight
    </contextmenu-item>
    <contextmenu-separator></contextmenu-separator>
    <contextmenu-item feature="insert" name="contextmenu-item-thumbnail-add-blank-page"
                      @controller="thumbnail:InsertBlankPageController">thumbnail:contextmenu.addBlankPage
    </contextmenu-item>
    <contextmenu-separator></contextmenu-separator>
    <thumbnail:delete-page-contextmenu-item
            name="contextmenu-item-thumbnail-delete"></thumbnail:delete-page-contextmenu-item>
</contextmenu>

You can remove or add menu items by changing the fragment configuration:

html
<script>
    var libPath = window.top.location.origin + '/lib';
    var FRAGMENT_ACTION = UIExtension.UIConsts.FRAGMENT_ACTION;
    var customModule = UIExtension.modular.module('custom', []);

    customModule.registerController(UIExtension.Controller.extend({
        mounted: function () {
            pdfui.callAddonAPI('Thumbnail', 'onSelectThumbnail', [function (currentSelectedPageIndexes) {
                console.log(currentSelectedPageIndexes);
            }]).then(removeListener => {
                this.addDestroyHook(removeListener);
            })
        }
    }, {
        getName: function () {
            return 'CustomThumbnailItemOperationController';
        }
    }));

    var pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: UIExtension.appearances.adaptive.extend({
            getDefaultFragments() {
                return [{
                    target: 'contextmenu-item-thumbnail-delete',
                    action: FRAGMENT_ACTION.REMOVE
                }, {
                    target: 'fv--thumbnail-contextmenu',
                    action: FRAGMENT_ACTION.APPEND,
                    template: `<contextmenu-item @controller="thumbnail:DeletePageController">Custom delete page menu</contextmenu-item>`
                }, {
                    target: 'fv--thumbnail-contextmenu',
                    action: FRAGMENT_ACTION.APPEND,
                    template: `<contextmenu-item @controller="custom:CustomThumbnailItemOperationController">Custom Action</contextmenu-item>`
                }]
            }
        }),
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
json
{
  "iframeOptions": {
    "style": "height: 500px"
  }
}