EmbedPDF

Turn features off

Leave out a feature, everywhere it appears, with disable:

{ disable: ['redaction', 'measurement'] }

The Redact and Measure tabs are gone, with their tools, panels, menu rows and shortcuts.

Which one to use#

Three questions, three tools. Each one only takes away:

You want to sayUseReach
Where something goeslayoutOne place: a bar or a menu. It can still be elsewhere, and its shortcut still works.
Whether this viewer has itdisable, or readOnlyEverywhere at once: every button, menu row, tab, panel and shortcut
What this user may doscopeEverything, your code included: the engine refuses it

A button shows when it’s in the layout, isn’t disabled, is allowed by the scope, and makes sense right now (Copy needs a selection).

I wantWrite
No annotating at alldisable: ['annotations']
No highlighter anywhere: toolbar, selection bar, shortcutdisable: ['annotations.highlight']
Only the toolbar’s Highlight button gonedisable: ['tool:highlight']
The highlighter in my own bar instead of the Annotate barlayout.remove('tool:highlight', { from: 'annotate' }), then add it to yours
No Measure tab, and no measuringdisable: ['measurement']
No Measure tab, but its tools in my own barlayout.removeBar('measure'), then add the tools to yours
No downloading in this viewerdisable: ['documents.download']
This user may never download, not even from codeLeave doc.download out of the scope
Read-onlyreadOnly: true
Read-only, but people fill in the formreadOnly: { except: ['forms.filling'] }

Turn off a feature, or one button#

disable takes two kinds of names, in one list:

  • A feature, such as annotations, or a part of one, such as annotations.highlight. Everything that belongs to it goes.
  • One command, such as tool:highlight. Its name has a colon. Only that command goes; the rest of its feature stays.
{ disable: ['forms.building', 'annotations.drawing', 'document:open'] }
FeatureIts partsOff with readOnly
annotations.highlight, .markup (underline, strike out, squiggly), .drawing (ink and ink highlighter), .text (text boxes, callouts, insert and replace text), .notes, .linksall
shapesyes
stampsStamps and imagesyes
comments.writing (new comments and replies).writing only, so people still read them
forms.filling, .buildingboth
signatures.signing, .checking.signing only
redactionyes
measurementyes
pagesRotating, moving, inserting and deleting pagesyes
attachments.adding (the attachment tool).adding only
text.selection, .copyno
searchno
thumbnails, outlineno
documents.open, .download, .print, .tabsno

A mode tab disappears by itself when only its bar’s dependent groups, undo, redo and style, are left, so disable: ['shapes'] removes the Shapes tab. Annotations, comments and form values already in the document still show; only making and changing them goes.

disable and readOnly follow their props: change them while the viewer runs, and the tools disappear or come back without a reload.

Read-only#

{ readOnly: true }

It turns off every feature that changes the document, marked in the table above. People still scroll, zoom, search, select and copy text, read annotations and comments, follow links, download and print. A small View only label in the toolbar says why the tools are gone.

Keep one way of changing it with except, and combine it with disable for what else should go:

{
  readOnly: { except: ['forms.filling'] },
  disable: ['documents.download', 'documents.print'],
}

That’s a form people fill in and can’t otherwise change, with no download or print button.

What a user may do#

disable and readOnly decide what the viewer offers. To decide what a user may do, give the document a scope: the list of permissions the engine checks on every call, from a button or from your code.

{
  scope: ['doc.open', 'doc.render', 'doc.text.select', 'doc.text.search', 'doc.annotate.read'],
  identity: { displayName: 'Ada Lovelace' },
}

Without a scope, the user may do what the file allows: everything, unless the PDF restricts itself, such as no printing, as in Acrobat. scope: ['*'] ignores the file’s permission flags. The scope and every permission in it are the headless ones.

What the scope doesn’t allow is hidden, like a disabled feature: a user without doc.annotate.modify gets no annotation tools and no Annotate tab. To show those buttons greyed out instead, with the reason in their tooltip, for example to offer an upgrade:

{ notAllowed: 'disable' }

The PDF’s own restrictions#

A PDF can carry restrictions of its own, set by its author with an owner password, such as no printing or no copying. They count when the scope includes 'pdf.permissions', which grants what the file allows:

{ scope: ['pdf.permissions'] }

Permissions add up: a scope that lists 'doc.print' next to 'pdf.permissions' allows printing even when the file says no. To let the file decide, list 'pdf.permissions' and leave its permissions out. The same rule holds on the server, so a document behaves the same on both engines.

Your own code#

  • Commands follow the viewer. A disabled command doesn’t run, from a button or from viewer.commands.execute(), because commands are what the interface does.
  • Plugins follow the scope. viewer.get('form').importValues(…) works in a read-only viewer, so your app can fill in a form from its own data and show it read-only.

So disable and readOnly are about the interface, and scope is about security. Someone who opens the browser’s developer tools can call the plugins too, so whatever a user truly may not do belongs in the scope.

Good to know#

Shortcuts don’t fall through#

A turned-off or not-allowed command still catches its keys. Ctrl/Cmd+C on text the user may not copy says so, instead of the browser doing something else with the key.

Your own commands#

A command of yours joins features through categories, so disable turns it off with them, and a name of your own makes a new feature: categories: ['acme.review'], then disable: ['acme.review']. A command that needs a permission says which with requires. See Buttons & commands.

Was this page helpful?

Your feedback goes directly to the documentation team.