# # 自定义书签

本节主要介绍书签组件的自定义方法，由于书签组件基于 tree 组件开发， 在开始前，请先了解 tree 组件的 用法 以及相关 API文档
(opens new window)。

## # 书签组件结构

本小节介绍书签相关组件的模板结构，涉及侧边栏面板组件、书签右键菜单组件以及书签树节点组件。

### # 书签面板

在内置的布局模板中，`<bookmark-v2:bookmark-tree></bookmark-v2:bookmark-tree>` 指的是左侧边栏书签面板，它实际上等同于下面的复杂模板：

    <sidebar-panel
        name="sidebar-bookmark-v2"
        class="fv__ui-sidebar-bookmark-v2"
        @tooltip
        tooltip-placement="right"
        tooltip-title="sidebar.bookmark.tooltip"
        title="sidebar.bookmark.title"
        icon-class="fv__icon-sidebar-bookmark"
        @lazy-content="active"
    >
        <bookmark-v2:bookmark-tree></bookmark-v2:bookmark-tree>
    </sidebar-panel>

在应用中，复杂模板可以替换内置的精简模板， 并修改其属性：

    <html>
        <div id="pdf-ui"></div>
        <template id="custom-bookmark-panel-template">
            <sidebar-panel
                name="sidebar-bookmark-v2"
                class="fv__ui-sidebar-bookmark-v2"
                @tooltip
                tooltip-placement="right"
                tooltip-title="Custom Bookmark Sidebar Panel Tooltip Title"
                title="Custom Bookmark Sidebar Panel Title"
                icon-class="fv__icon-sidebar-bookmark"
                @lazy-content="active"
            >
                <bookmark-v2:bookmark-tree></bookmark-v2:bookmark-tree>
            </sidebar-panel>
        </template>
    </html>
    <style>
        html{
            overflow:hidden;
        }
        body {
            height: 100vh;
        }
        #pdf-ui {
            position: relative;
            top: 50px;
        }
    </style>
    <script>
        const customBookmarkPanelTemplate = document.getElementById('custom-bookmark-panel-template').innerHTML;
        const CustomAppearance = UIExtension.appearances.adaptive.extend({
            getDefaultFragments() {
                return [{
                    target: 'sidebar-bookmark-v2',
                    action: UIExtension.UIConsts.FRAGMENT_ACTION.REPLACE,
                    template: customBookmarkPanelTemplate
                }];
            }
        });
        const libPath = window.top.location.origin + '/lib';
        const pdfui = new UIExtension.PDFUI({
                viewerOptions: {
                    libPath: libPath,
                    jr: {
                        licenseSN: licenseSN,
                        licenseKey: licenseKey
                    }
                },
                renderTo: '#pdf-ui',
                appearance: CustomAppearance,
                addons: []
        });
    </script>

    {
        "iframeOptions": {
            "style": "height: 500px"
        }
    }

### # 书签右键菜单

在内置布局模板中，`<bookmark-v2:bookmark-contextmenu @lazy></bookmark-v2:bookmark-contextmenu>` 指的是书签右键菜单，其相当于下面的模板：

    <contextmenu name="fv--bookmark-contextmenu-v2">
        <bookmark-v2:add-bookmark name="fv--bookmark-contextmenu-item-add"></bookmark-v2:add-bookmark>
        <contextmenu-separator @bookmark-v2:hide-if-no-bookmark></contextmenu-separator>
        <bookmark-v2:goto-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-goto"></bookmark-v2:goto-bookmark>
        <contextmenu-separator @bookmark-v2:hide-if-no-bookmark></contextmenu-separator>
        <bookmark-v2:cut-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-cut"></bookmark-v2:cut-bookmark>
        <bookmark-v2:paste-under-selected-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-paste-under"></bookmark-v2:paste-under-selected-bookmark>
        <bookmark-v2:paste-after-selected-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-paste-after"></bookmark-v2:paste-after-selected-bookmark>
        <bookmark-v2:delete-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-delete"></bookmark-v2:delete-bookmark>
        <bookmark-v2:set-destination @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-set-destination"></bookmark-v2:set-destination>
        <bookmark-v2:rename-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-rename"></bookmark-v2:rename-bookmark>
    </contextmenu>

在模板中，对于菜单项，我们提供了一个 `@bookmark-v2:hide-if-no-bookmark` 指令。这个指令的作用是：当文档没有书签时，右键点击书签面板，我们需要隐藏一些菜单项，只留下 `<bookmark-v2:add-bookmark>` 一个组件。

根据这个模板，我们只需要定义一个name 为 `fv--bookmark-contextmenu-v2` 的右键菜单，替换内置的书签右键菜单，就可以实现覆盖内置书签右键菜单的效果。以下是一个示例:

    <html>
        <div id="pdf-ui"></div>
        <template id="custom-contextmenu-template">
            <contextmenu name="fv--bookmark-contextmenu-v2">
                <bookmark-v2:add-bookmark name="fv--bookmark-contextmenu-item-add"></bookmark-v2:add-bookmark>
                <contextmenu-separator @bookmark-v2:hide-if-no-bookmark></contextmenu-separator>
                <bookmark-v2:goto-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-goto"></bookmark-v2:goto-bookmark>
                <contextmenu-separator @bookmark-v2:hide-if-no-bookmark></contextmenu-separator>
                <bookmark-v2:cut-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-cut"></bookmark-v2:cut-bookmark>
                <bookmark-v2:paste-under-selected-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-paste-under"></bookmark-v2:paste-under-selected-bookmark>
                <bookmark-v2:paste-after-selected-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-paste-after"></bookmark-v2:paste-after-selected-bookmark>
                <bookmark-v2:delete-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-delete"></bookmark-v2:delete-bookmark>
                <bookmark-v2:set-destination @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-set-destination"></bookmark-v2:set-destination>
                <bookmark-v2:rename-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-rename"></bookmark-v2:rename-bookmark>
            </contextmenu>
        </template>
    </html>
    <style>
        html{
            overflow:hidden;
        }
        body {
            height: 100vh;
        }
        #pdf-ui {
            position: relative;
            top: 50px;
        }
    </style>
    <script>
        const customBookmarkContextmenuTemplate = document.getElementById('custom-contextmenu-template').innerHTML;
        const CustomAppearance = UIExtension.appearances.adaptive.extend({
            getDefaultFragments() {
                return [{
                    target: 'fv--bookmark-contextmenu-v2',
                    action: UIExtension.UIConsts.FRAGMENT_ACTION.REPLACE,
                    template: customBookmarkContextmenuTemplate
                }];
            }
        });
        const libPath = window.top.location.origin + '/lib';
        const pdfui = new UIExtension.PDFUI({
                viewerOptions: {
                    libPath: libPath,
                    jr: {
                        licenseSN: licenseSN,
                        licenseKey: licenseKey
                    }
                },
                renderTo: '#pdf-ui',
                appearance: CustomAppearance,
                addons: []
        });
    </script>

    {
        "iframeOptions": {
            "style": "height: 500px"
        }
    }

当然，除了整体替换以外， 您也可以单独删除或增加菜单项：

    <html>
        <div id="pdf-ui"></div>
        <template id="custom-contextmenu-template">
            <contextmenu name="fv--bookmark-contextmenu-v2">
                <bookmark-v2:add-bookmark name="fv--bookmark-contextmenu-item-add"></bookmark-v2:add-bookmark>
                <contextmenu-separator @bookmark-v2:hide-if-no-bookmark></contextmenu-separator>
                <bookmark-v2:goto-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-goto"></bookmark-v2:goto-bookmark>
                <contextmenu-separator @bookmark-v2:hide-if-no-bookmark></contextmenu-separator>
                <bookmark-v2:cut-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-cut"></bookmark-v2:cut-bookmark>
                <bookmark-v2:paste-under-selected-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-paste-under"></bookmark-v2:paste-under-selected-bookmark>
                <bookmark-v2:paste-after-selected-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-paste-after"></bookmark-v2:paste-after-selected-bookmark>
                <bookmark-v2:delete-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-delete"></bookmark-v2:delete-bookmark>
                <bookmark-v2:set-destination @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-set-destination"></bookmark-v2:set-destination>
                <bookmark-v2:rename-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-rename"></bookmark-v2:rename-bookmark>
            </contextmenu>
        </template>
    </html>
    <style>
        html{
            overflow:hidden;
        }
        body {
            height: 100vh;
        }
        #pdf-ui {
            position: relative;
            top: 50px;
        }
    </style>
    <script>
        const customBookmarkContextmenuTemplate = document.getElementById('custom-contextmenu-template').innerHTML;

        class CustomContextMenuItemComponent extends UIExtension.SeniorComponentFactory.createSuperClass({
            template: `
                <contextmenu-item @on.click="$component.handleClick()">Custom Bookmark Contextmenu Item</contextmenu-item>
            `
        }) {
            static getName() {
                return 'custom-bookmark-contextmenu-item';
            }
            handleClick() {
                const contextmenu = this.parent;
                const target = contextmenu.getCurrentTarget();
                if(target instanceof UIExtension.components.widgets.TreeNodeComponent) {
                    alert('Click on bookmark item: ' + target.title);
                }
            }
        }

        const customModule = UIExtension.modular.module('custom', []);
        customModule.registerComponent(CustomContextMenuItemComponent);

        const CustomAppearance = UIExtension.appearances.adaptive.extend({
            getDefaultFragments() {
                return [{
                    target: '@bookmark-v2:rename-bookmark',
                    action: UIExtension.UIConsts.FRAGMENT_ACTION.REMOVE
            }, {
                target: 'fv--bookmark-contextmenu-v2',
                action: UIExtension.UIConsts.FRAGMENT_ACTION.APPEND,
                template: `<custom:custom-bookmark-contextmenu-item></custom:custom-bookmark-contextmenu-item>`
            }];
            }
        });
        const libPath = window.top.location.origin + '/lib';
        const pdfui = new UIExtension.PDFUI({
                viewerOptions: {
                    libPath: libPath,
                    jr: {
                        licenseSN: licenseSN,
                        licenseKey: licenseKey
                    }
                },
                renderTo: '#pdf-ui',
                appearance: CustomAppearance,
                addons: []
        });
    </script>

    {
        "iframeOptions": {
            "style": "height: 500px"
        }
    }

### # 书签右键菜单项

1. 添加书签菜单项：
   - 精简模板： `<bookmark-v2:add-bookmark name="fv--bookmark-contextmenu-item-add"></bookmark-v2:add-bookmark>`
   - 完整模板：`<contextmenu-item @controller="AddBookmarkController">contextmenu.bookmark.add</contextmenu-item>`
2. 跳转功能菜单项：
   - 精简模板：`<bookmark-v2:goto-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-goto"></bookmark-v2:goto-bookmark>`
   - 完整模板：`<contextmenu-item @controller="GotoBookmarkController" @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-goto">contextmenu.bookmark.goTo</contextmenu-item>`
3. 剪切功能菜单项：
   - 精简模板：`<bookmark-v2:cut-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-cut"></bookmark-v2:cut-bookmark>`
   - 完整模板：`<contextmenu-item @controller="CutBookmarkController" @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-cut">contextmenu.bookmark.cut</contextmenu-item>`
4. 粘贴书签到所选书签下面的功能菜单项：
   - 精简模板：`<bookmark-v2:paste-under-selected-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-paste-under"></bookmark-v2:paste-under-selected-bookmark>`
   - 完整模板：`<contextmenu-item @controller="PasteUnderSelectedBookmarkController as ctrl" @show="ctrl.pasteAvailable" @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-paste-under">contextmenu.bookmark.pasteUnder</contextmenu-item>`
5. 粘贴书签到所选书签后面的功能菜单项：
   - 精简模板：`<bookmark-v2:paste-after-selected-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-paste-after"></bookmark-v2:paste-after-selected-bookmark>`
   - 完整模板：`<contextmenu-item @controller="PasteAfterSelectedBookmarkController as ctrl" @show="ctrl.pasteAvailable" @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-paste-after">contextmenu.bookmark.pasteAfter</contextmenu-item>`
6. 删除书签功能菜单项：
   - 精简模板：`<bookmark-v2:delete-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-delete"></bookmark-v2:delete-bookmark>`
   - 完整模板：`<contextmenu-item @controller="DeleteBookmarkController" @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-delete">contextmenu.bookmark.delete</contextmenu-item>`
7. 设置书签目标位置菜单项：
   - 精简模板：`<bookmark-v2:set-destination @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-set-destination"></bookmark-v2:set-destination>`
   - 完整模板：`<contextmenu-item @controller="SetDestinationBookmarkController" @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-set-destination">contextmenu.bookmark.destination</contextmenu-item>`
8. 重命名书签菜单项：
   - 精简模板：`<bookmark-v2:rename-bookmark @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-rename"></bookmark-v2:rename-bookmark>`
   - 完整模板：`<contextmenu-item @controller="RenameBookmarkController" @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-rename">contextmenu.bookmark.rename</contextmenu-item>`

以上是 Foxit PDF SDK for Web 支持的内置书签右键菜单项。应用层可以复用这些菜单项的 `@controller` 实现，替换内置菜单项来实现自定义菜单项功能。以下是一个示例：

    <html>
        <div id="pdf-ui"></div>
    </html>
    <style>
        html{
            overflow:hidden;
        }
        body {
            height: 100vh;
        }
        #pdf-ui {
            position: relative;
            top: 50px;
        }
    </style>
    <script>

        class CustomContextMenuItemComponent extends UIExtension.SeniorComponentFactory.createSuperClass({
            template: `
                <contextmenu-item @controller="bookmark-v2:RenameBookmarkController" @bookmark-v2:hide-if-no-bookmark name="fv--bookmark-contextmenu-item-rename" @on.click="$component.handleClick()">contextmenu.bookmark.rename</contextmenu-item>
            `
        }) {
            static getName() {
                return 'custom-bookmark-contextmenu-item';
            }
            handleClick() {
                const contextmenu = this.parent;
                const target = contextmenu.getCurrentTarget();
                if(target instanceof UIExtension.components.widgets.TreeNodeComponent) {
                    console.log('Rename bookmark item: ' + target.title);
                }
            }
        }

        const customModule = UIExtension.modular.module('custom', []);
        customModule.registerComponent(CustomContextMenuItemComponent);

        const CustomAppearance = UIExtension.appearances.adaptive.extend({
            getDefaultFragments() {
                return [{
                    target: '@bookmark-v2:rename-bookmark',
                    action: UIExtension.UIConsts.FRAGMENT_ACTION.REPLACE,
                    template: `<custom:custom-bookmark-contextmenu-item></custom:custom-bookmark-contextmenu-item>`
                }];
            }
        });
        const libPath = window.top.location.origin + '/lib';
        const pdfui = new UIExtension.PDFUI({
                viewerOptions: {
                    libPath: libPath,
                    jr: {
                        licenseSN: licenseSN,
                        licenseKey: licenseKey
                    }
                },
                renderTo: '#pdf-ui',
                appearance: CustomAppearance,
                addons: []
        });
    </script>

    {
        "iframeOptions": {
            "style": "height: 500px"
        }
    }

### # 书签树节点

书签树节点，也就是 TreeNodeComponent
(opens new window)。它与 PDF 文档的书签数据同步，随着书签数据的创建或删除移动而被创建或销毁。因此，要自定义书签树节点，需要通过事件来完成。TreeComponent
(opens new window) 组件开放了这两个事件：

1. `create-tree-node` 事件，在创建树节点时触发，可以用于修改树节点外观以及注册树节点上的事件等。
2. `destroy-tree-node` 事件，在树节点被销毁时触发，可以用于释放一些数据，避免内存泄露。

以下是一个示例， 展示了如何将树节点的文本内容替换为链接：

    <html>
        <div id="pdf-ui"></div>
    </html>
    <style>
        html{
            overflow:hidden;
        }
        body {
            height: 100vh;
        }
        #pdf-ui {
            position: relative;
            top: 50px;
        }
    </style>
    <script>
        const libPath = window.top.location.origin + '/lib';
        const pdfui = new UIExtension.PDFUI({
                viewerOptions: {
                    libPath: libPath,
                    jr: {
                        licenseSN: licenseSN,
                        licenseKey: licenseKey
                    }
                },
                renderTo: '#pdf-ui',
                appearance: UIExtension.appearances.adaptive,
                addons: []
        });
        pdfui.getRootComponent().then(root => {
            return root.querySelector('@bookmark-v2:bookmark-tree').getTree()
        }).then(tree => {
            tree.on('create-tree-node', treeNode => {
                const newTitleElement = document.createElement('a');
                treeNode.titleElement.replaceWith(newTitleElement);
                treeNode.titleElement = newTitleElement;
                newTitleElement.target="about:blank";
                newTitleElement.href="https://foxit.com"
            })
        })
    </script>

    {
        "iframeOptions": {
            "style": "height: 500px"
        }
    }

## # 书签 Service API

基于 PDFViewCtrl 层和 UIExtension 层之间的差异，我们将书签 API 分为两部分，并提供了两个 Service 实例：

1. BookmarkDataService
   (opens new window): PDFViewCtrl 层的书签数据服务。当您的应用程序是基于 PDFViewCtrl 开发时，只能使用此服务提供的 API 进行扩展。

2. BookmarkUIService
   (opens new window): 基于 `BookmarkDataService` 封装的 UIExtension 层 API，它封装了`BookmarkDataService` 的部分 API，用于支持 UI 层的视图和数据同步以及支持 undo-redo 功能。

   UIExtension 层也可以使用 `BookmarkDataService`，但除了封装在`BookmarkUIService` 中的 API。具体细节，请参考 API参考手册
   (opens new window)。

### # 示例 1

该示例展示如何通过 `BookmarkDataService` 获取和打印文档的一级书签：

    <html>
    <label>Select a PDF file with bookmarks:
        <input type="file" id="file">
    </label>
    <hr style="width: 100%;">
    <div id="pdf-viewer"></div>
    </html>
    <script>
        const libPath = window.top.location.origin + '/lib';
        const ePDFViewer = document.getElementById('pdf-viewer');
        const pdfViewer = new PDFViewCtrl.PDFViewer({
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            },
            customs: {
                ScrollWrap: PDFViewCtrl.DivScrollWrap.create(ePDFViewer)
            }
        });
        pdfViewer.init(ePDFViewer);
        document.getElementById('file').onchange = function(e){
            if(!this.value) {
                return;
            }
            pdfViewer.openPDFByFile(e.target.files[0]);
            this.value = '';
        };
        pdfViewer.eventEmitter.on(PDFViewCtrl.ViewerEvents.openFileSuccess, () => {
            const bookmarkDataService = pdfViewer.getBookmarkDataService();
            bookmarkDataService.getFirstLevelBookmarks().then(firstLevelBookmarks => {
                console.log(firstLevelBookmarks);
            });
        })
    </script>
    <style>
    body {
        display: flex;
        flex-direction: column;
    }
    #pdf-viewer {
        width: 100%;
        flex: 1;
        overflow: auto;
    }
    </style>

    {
        "iframeOptions": {
            "style": "height: 500px"
        }
    }

### # 示例 2

该示例展示如何通过 `BookmarkUIService` 创建和删除书签：

    <html>
        <div id="pdf-ui"></div>
        <template id="custom-toolbar-template">
             <div class="custom-toolbar" @var.toolbar="$component">
                <xbutton @on.click="toolbar.addBookmark()">Create</xbutton>
                <xbutton @on.click="toolbar.deleteSelectedBookmark()">Delete</xbutton>
            </div>
        </template>
    </html>
    <style>
        html{
            overflow:hidden;
        }
        body {
            height: 100vh;

        }
        #pdf-ui {
            position: relative;
            top: 50px;
        }
        .custom-toolbar {
            display: flex;
            gap: 10px;
            border-bottom: 1px solid #f0f0f0;
            padding: 5px 0;
        }
    </style>
    <script>
        const customBookmarkContextmenuTemplate = document.getElementById('custom-toolbar-template').innerHTML;

        class CustomBookmarkToolbarComponent extends UIExtension.SeniorComponentFactory.createSuperClass({
            template: customBookmarkContextmenuTemplate
        }) {
            static getName() {
                return 'custom-bookmark-toolbar';
            }
            addBookmark() {
                const service = this.getPDFUI().getBookmarkUIService();
                const text = prompt("Create new bookmark", "Untitled");
                service.addBookmark({
                    title: text,
                    relationship: PDF.bookmark.BookmarkRelationship.LAST_CHILD
                })
            }
            deleteSelectedBookmark() {
                const service = this.getPDFUI().getBookmarkUIService();
                const bookmarkId = service.getCurrentActiveBookmarkId();
                if(bookmarkId === undefined) {
                    alert('You did not select a bookmark');
                    return;
                }
                const confirmed = confirm('Are you sure you want to delete this bookmark? ')
                if(confirmed) {
                    service.deleteBookmark(bookmarkId)
                }
            }
        }

        const customModule = UIExtension.modular.module('custom', []);
        customModule.registerComponent(CustomBookmarkToolbarComponent);

        const CustomAppearance = UIExtension.appearances.adaptive.extend({
            getDefaultFragments() {
                return [{
                    target: 'sidebar-bookmark-v2',
                    action: UIExtension.UIConsts.FRAGMENT_ACTION.PREPEND,
                    template: `<custom:custom-bookmark-toolbar></custom:custom-bookmark-toolbar>`
                }];
            }
        });
        const libPath = window.top.location.origin + '/lib';
        const pdfui = new UIExtension.PDFUI({
                viewerOptions: {
                    libPath: libPath,
                    jr: {
                        licenseSN: licenseSN,
                        licenseKey: licenseKey
                    }
                },
                renderTo: '#pdf-ui',
                appearance: CustomAppearance,
                addons: []
        });
    </script>

    {
        "iframeOptions": {
            "style": "height: 500px"
        }
    }