Merge pull request #20210 from calixteman/comment_sidebar
[Editor] Add a sidebar allowing the user to navigate between the comments in a pdf (bug 1985567)
This commit is contained in:
commit
9e2e9e2096
@ -328,6 +328,10 @@ pdfjs-comment-floating-button =
|
|||||||
.title = Comment
|
.title = Comment
|
||||||
.aria-label = Comment
|
.aria-label = Comment
|
||||||
pdfjs-comment-floating-button-label = Comment
|
pdfjs-comment-floating-button-label = Comment
|
||||||
|
pdfjs-editor-comment-button =
|
||||||
|
.title = Comment
|
||||||
|
.aria-label = Comment
|
||||||
|
pdfjs-editor-comment-button-label = Comment
|
||||||
pdfjs-editor-signature-button =
|
pdfjs-editor-signature-button =
|
||||||
.title = Add signature
|
.title = Add signature
|
||||||
pdfjs-editor-signature-button-label = Add signature
|
pdfjs-editor-signature-button-label = Add signature
|
||||||
@ -395,6 +399,23 @@ pdfjs-free-text2 =
|
|||||||
.aria-label = Text Editor
|
.aria-label = Text Editor
|
||||||
.default-content = Start typing…
|
.default-content = Start typing…
|
||||||
|
|
||||||
|
# Used to show how many comments are present in the pdf file.
|
||||||
|
# Variables:
|
||||||
|
# $count (Number) - the number of comments.
|
||||||
|
pdfjs-editor-comments-sidebar-title =
|
||||||
|
{ $count ->
|
||||||
|
[one] Comment
|
||||||
|
*[other] Comments
|
||||||
|
}
|
||||||
|
|
||||||
|
pdfjs-editor-comments-sidebar-close-button =
|
||||||
|
.title = Close the sidebar
|
||||||
|
.aria-label = Close the sidebar
|
||||||
|
pdfjs-editor-comments-sidebar-close-button-label = Close the sidebar
|
||||||
|
|
||||||
|
# Instructional copy to add a comment by selecting text or an annotations.
|
||||||
|
pdfjs-editor-comments-sidebar-no-comments = Add a comment by selecting text or an annotation.
|
||||||
|
|
||||||
## Alt-text dialog
|
## Alt-text dialog
|
||||||
|
|
||||||
# Alternative text (alt text) helps when people can't see the image.
|
# Alternative text (alt text) helps when people can't see the image.
|
||||||
|
|||||||
@ -585,6 +585,8 @@ class AnnotationEditorUIManager {
|
|||||||
|
|
||||||
#activeEditor = null;
|
#activeEditor = null;
|
||||||
|
|
||||||
|
#allEditableAnnotations = null;
|
||||||
|
|
||||||
#allEditors = new Map();
|
#allEditors = new Map();
|
||||||
|
|
||||||
#allLayers = new Map();
|
#allLayers = new Map();
|
||||||
@ -663,6 +665,8 @@ class AnnotationEditorUIManager {
|
|||||||
|
|
||||||
#showAllStates = null;
|
#showAllStates = null;
|
||||||
|
|
||||||
|
#pdfDocument = null;
|
||||||
|
|
||||||
#previousStates = {
|
#previousStates = {
|
||||||
isEditing: false,
|
isEditing: false,
|
||||||
isEmpty: true,
|
isEmpty: true,
|
||||||
@ -846,6 +850,7 @@ class AnnotationEditorUIManager {
|
|||||||
this.#altTextManager = altTextManager;
|
this.#altTextManager = altTextManager;
|
||||||
this.#commentManager = commentManager;
|
this.#commentManager = commentManager;
|
||||||
this.#signatureManager = signatureManager;
|
this.#signatureManager = signatureManager;
|
||||||
|
this.#pdfDocument = pdfDocument;
|
||||||
this._eventBus = eventBus;
|
this._eventBus = eventBus;
|
||||||
eventBus._on("editingaction", this.onEditingAction.bind(this), { signal });
|
eventBus._on("editingaction", this.onEditingAction.bind(this), { signal });
|
||||||
eventBus._on("pagechanging", this.onPageChanging.bind(this), { signal });
|
eventBus._on("pagechanging", this.onPageChanging.bind(this), { signal });
|
||||||
@ -928,6 +933,7 @@ class AnnotationEditorUIManager {
|
|||||||
this.#floatingToolbar = null;
|
this.#floatingToolbar = null;
|
||||||
this.#mainHighlightColorPicker?.destroy();
|
this.#mainHighlightColorPicker?.destroy();
|
||||||
this.#mainHighlightColorPicker = null;
|
this.#mainHighlightColorPicker = null;
|
||||||
|
this.#allEditableAnnotations = null;
|
||||||
if (this.#focusMainContainerTimeoutId) {
|
if (this.#focusMainContainerTimeoutId) {
|
||||||
clearTimeout(this.#focusMainContainerTimeoutId);
|
clearTimeout(this.#focusMainContainerTimeoutId);
|
||||||
this.#focusMainContainerTimeoutId = null;
|
this.#focusMainContainerTimeoutId = null;
|
||||||
@ -937,6 +943,7 @@ class AnnotationEditorUIManager {
|
|||||||
this.#translationTimeoutId = null;
|
this.#translationTimeoutId = null;
|
||||||
}
|
}
|
||||||
this._editorUndoBar?.destroy();
|
this._editorUndoBar?.destroy();
|
||||||
|
this.#pdfDocument = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
combinedSignal(ac) {
|
combinedSignal(ac) {
|
||||||
@ -1790,6 +1797,10 @@ class AnnotationEditorUIManager {
|
|||||||
this.#updateModeCapability = Promise.withResolvers();
|
this.#updateModeCapability = Promise.withResolvers();
|
||||||
this.#currentDrawingSession?.commitOrRemove();
|
this.#currentDrawingSession?.commitOrRemove();
|
||||||
|
|
||||||
|
if (this.#mode === AnnotationEditorType.POPUP) {
|
||||||
|
this.#commentManager?.hideSidebar();
|
||||||
|
}
|
||||||
|
|
||||||
this.#mode = mode;
|
this.#mode = mode;
|
||||||
if (mode === AnnotationEditorType.NONE) {
|
if (mode === AnnotationEditorType.NONE) {
|
||||||
this.setEditingState(false);
|
this.setEditingState(false);
|
||||||
@ -1800,9 +1811,18 @@ class AnnotationEditorUIManager {
|
|||||||
this.#updateModeCapability.resolve();
|
this.#updateModeCapability.resolve();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode === AnnotationEditorType.SIGNATURE) {
|
if (mode === AnnotationEditorType.SIGNATURE) {
|
||||||
await this.#signatureManager?.loadSignatures();
|
await this.#signatureManager?.loadSignatures();
|
||||||
}
|
}
|
||||||
|
if (mode === AnnotationEditorType.POPUP) {
|
||||||
|
this.#allEditableAnnotations ||=
|
||||||
|
await this.#pdfDocument.getAnnotationsByType(
|
||||||
|
new Set(this.#editorTypes.map(editorClass => editorClass._editorType))
|
||||||
|
);
|
||||||
|
this.#commentManager?.showSidebar(this.#allEditableAnnotations);
|
||||||
|
}
|
||||||
|
|
||||||
this.setEditingState(true);
|
this.setEditingState(true);
|
||||||
await this.#enableAll();
|
await this.#enableAll();
|
||||||
this.unselectAll();
|
this.unselectAll();
|
||||||
|
|||||||
@ -75,6 +75,7 @@ const AnnotationEditorType = {
|
|||||||
HIGHLIGHT: 9,
|
HIGHLIGHT: 9,
|
||||||
STAMP: 13,
|
STAMP: 13,
|
||||||
INK: 15,
|
INK: 15,
|
||||||
|
POPUP: 16,
|
||||||
SIGNATURE: 101,
|
SIGNATURE: 101,
|
||||||
COMMENT: 102,
|
COMMENT: 102,
|
||||||
};
|
};
|
||||||
|
|||||||
29
web/app.js
29
web/app.js
@ -493,7 +493,30 @@ const PDFViewerApplication = {
|
|||||||
: null;
|
: null;
|
||||||
const commentManager =
|
const commentManager =
|
||||||
AppOptions.get("enableComment") && appConfig.editCommentDialog
|
AppOptions.get("enableComment") && appConfig.editCommentDialog
|
||||||
? new CommentManager(appConfig.editCommentDialog, overlayManager)
|
? new CommentManager(
|
||||||
|
appConfig.editCommentDialog,
|
||||||
|
{
|
||||||
|
sidebar:
|
||||||
|
appConfig.annotationEditorParams?.editorCommentsSidebar || null,
|
||||||
|
commentsList:
|
||||||
|
appConfig.annotationEditorParams?.editorCommentsSidebarList ||
|
||||||
|
null,
|
||||||
|
commentCount:
|
||||||
|
appConfig.annotationEditorParams?.editorCommentsSidebarCount ||
|
||||||
|
null,
|
||||||
|
sidebarTitle:
|
||||||
|
appConfig.annotationEditorParams?.editorCommentsSidebarTitle ||
|
||||||
|
null,
|
||||||
|
closeButton:
|
||||||
|
appConfig.annotationEditorParams
|
||||||
|
?.editorCommentsSidebarCloseButton || null,
|
||||||
|
commentToolbarButton:
|
||||||
|
appConfig.toolbar?.editorCommentButton || null,
|
||||||
|
},
|
||||||
|
eventBus,
|
||||||
|
linkService,
|
||||||
|
overlayManager
|
||||||
|
)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const enableHWA = AppOptions.get("enableHWA"),
|
const enableHWA = AppOptions.get("enableHWA"),
|
||||||
@ -589,6 +612,10 @@ const PDFViewerApplication = {
|
|||||||
if (editorSignatureButton && AppOptions.get("enableSignatureEditor")) {
|
if (editorSignatureButton && AppOptions.get("enableSignatureEditor")) {
|
||||||
editorSignatureButton.parentElement.hidden = false;
|
editorSignatureButton.parentElement.hidden = false;
|
||||||
}
|
}
|
||||||
|
const editorCommentButton = appConfig.toolbar?.editorCommentButton;
|
||||||
|
if (editorCommentButton && AppOptions.get("enableComment")) {
|
||||||
|
editorCommentButton.parentElement.hidden = false;
|
||||||
|
}
|
||||||
this.annotationEditorParams = new AnnotationEditorParams(
|
this.annotationEditorParams = new AnnotationEditorParams(
|
||||||
appConfig.annotationEditorParams,
|
appConfig.annotationEditorParams,
|
||||||
eventBus
|
eventBus
|
||||||
|
|||||||
@ -304,6 +304,10 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
|
|
||||||
|
&:dir(rtl) {
|
||||||
|
border-radius: 6px 6px 0;
|
||||||
|
}
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
content: "";
|
content: "";
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@ -315,6 +319,7 @@
|
|||||||
background-color: var(--comment-button-fg);
|
background-color: var(--comment-button-fg);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
transform: scaleX(var(--dir-factor));
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus-visible {
|
&:focus-visible {
|
||||||
@ -351,3 +356,241 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#editorCommentsSidebar {
|
||||||
|
--comment-close-button-icon: url(images/comment-closeButton.svg);
|
||||||
|
|
||||||
|
--comment-date-fg-color: light-dark(
|
||||||
|
rgb(21 20 26 / 0.69),
|
||||||
|
rgb(251 251 254 / 0.69)
|
||||||
|
);
|
||||||
|
--comment-bg-color: light-dark(#f9f9fb, #1c1b22);
|
||||||
|
--comment-hover-bg-color: light-dark(
|
||||||
|
rgb(21 20 26 / 0.14),
|
||||||
|
rgb(251 251 254 / 0.14)
|
||||||
|
);
|
||||||
|
--comment-active-bg-color: light-dark(
|
||||||
|
rgb(21 20 26 / 0.21),
|
||||||
|
rgb(251 251 254 / 0.21)
|
||||||
|
);
|
||||||
|
--comment-border-color: light-dark(#f0f0f4, #52525e);
|
||||||
|
--comment-focus-outline-color: light-dark(#0062fa, #00cadb);
|
||||||
|
--comment-fg-color: light-dark(#15141a, #fbfbfe);
|
||||||
|
--comment-count-bg-color: light-dark(#e2f7ff, #00317e);
|
||||||
|
--comment-indicator-active-fg-color: light-dark(#0041a4, #a6ecf4);
|
||||||
|
--comment-indicator-focus-fg-color: light-dark(#5b5b66, #fbfbfe);
|
||||||
|
--comment-indicator-hover-fg-color: light-dark(#0053cb, #61dce9);
|
||||||
|
--comment-indicator-selected-fg-color: light-dark(#0062fa, #00cadb);
|
||||||
|
|
||||||
|
@media screen and (forced-colors: active) {
|
||||||
|
--comment-date-fg-color: CanvasText;
|
||||||
|
--comment-bg-color: Canvas;
|
||||||
|
--comment-hover-bg-color: SelectedItemText;
|
||||||
|
--comment-active-bg-color: SelectedItemText;
|
||||||
|
--comment-border-color: CanvasText;
|
||||||
|
--comment-fg-color: CanvasText;
|
||||||
|
--comment-count-bg-color: Canvas;
|
||||||
|
--comment-indicator-active-fg-color: SelectedItem;
|
||||||
|
--comment-indicator-focus-fg-color: CanvasText;
|
||||||
|
--comment-indicator-hover-fg-color: CanvasText;
|
||||||
|
--comment-indicator-selected-fg-color: SelectedItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
width: 239px;
|
||||||
|
height: auto;
|
||||||
|
min-width: 180px;
|
||||||
|
max-width: 632px;
|
||||||
|
padding-bottom: 16px;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
#editorCommentsSidebarHeader {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.commentCount {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 6px;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
#editorCommentsSidebarTitle {
|
||||||
|
font: menu;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 590;
|
||||||
|
line-height: normal;
|
||||||
|
font-size: 17px;
|
||||||
|
color: var(--comment-fg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#editorCommentsSidebarCount {
|
||||||
|
padding: 0 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: var(--comment-count-bg-color);
|
||||||
|
|
||||||
|
color: var(--comment-fg-color);
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
font: menu;
|
||||||
|
font-size: 13px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#editorCommentsSidebarCloseButton {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
padding: 8px;
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
mask-repeat: no-repeat;
|
||||||
|
mask-position: center;
|
||||||
|
mask-image: var(--comment-close-button-icon);
|
||||||
|
background-color: var(--comment-fg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--comment-hover-bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-color: var(--comment-active-bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
> span {
|
||||||
|
display: inline-block;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#editorCommentsSidebarList {
|
||||||
|
display: flex;
|
||||||
|
width: auto;
|
||||||
|
padding: 1px 16px 0;
|
||||||
|
gap: 10px;
|
||||||
|
flex: 1 0 0;
|
||||||
|
align-self: stretch;
|
||||||
|
align-items: flex-start;
|
||||||
|
flex-direction: column;
|
||||||
|
list-style-type: none;
|
||||||
|
|
||||||
|
.sidebarComment {
|
||||||
|
display: flex;
|
||||||
|
width: auto;
|
||||||
|
padding: 8px 16px 16px;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
align-self: stretch;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 0.5px solid var(--comment-border-color);
|
||||||
|
background-color: var(--comment-bg-color);
|
||||||
|
|
||||||
|
&:not(.noComments) {
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--comment-hover-bg-color);
|
||||||
|
|
||||||
|
time::after {
|
||||||
|
display: inline-block;
|
||||||
|
background-color: var(--comment-indicator-hover-fg-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-color: var(--comment-active-bg-color);
|
||||||
|
|
||||||
|
time::after {
|
||||||
|
display: inline-block;
|
||||||
|
background-color: var(--comment-indicator-active-fg-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:is(:focus, :focus-visible) time::after {
|
||||||
|
display: inline-block;
|
||||||
|
background-color: var(--comment-indicator-focus-fg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
outline: 2px solid var(--comment-focus-outline-color);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
.sidebarCommentText {
|
||||||
|
max-height: fit-content;
|
||||||
|
-webkit-line-clamp: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
time::after {
|
||||||
|
display: inline-block;
|
||||||
|
background-color: var(--comment-indicator-selected-fg-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebarCommentText {
|
||||||
|
font: menu;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: normal;
|
||||||
|
font-size: 15px;
|
||||||
|
width: 100%;
|
||||||
|
height: fit-content;
|
||||||
|
max-height: 80px;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
overflow: hidden;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.noComments .sidebarCommentText {
|
||||||
|
max-height: fit-content;
|
||||||
|
-webkit-line-clamp: unset;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
time {
|
||||||
|
width: 100%;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
font: menu;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: normal;
|
||||||
|
font-size: 13px;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: "";
|
||||||
|
display: none;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
mask-repeat: no-repeat;
|
||||||
|
mask-position: center;
|
||||||
|
mask-image: var(--comment-edit-button-icon);
|
||||||
|
transform: scaleX(var(--dir-factor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -13,7 +13,15 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getRGB, noContextMenu, shadow, stopEvent } from "pdfjs-lib";
|
import {
|
||||||
|
AnnotationEditorType,
|
||||||
|
getRGB,
|
||||||
|
noContextMenu,
|
||||||
|
PDFDateString,
|
||||||
|
shadow,
|
||||||
|
stopEvent,
|
||||||
|
} from "pdfjs-lib";
|
||||||
|
import { binarySearchFirstItem } from "./ui_utils.js";
|
||||||
|
|
||||||
class CommentManager {
|
class CommentManager {
|
||||||
#actions;
|
#actions;
|
||||||
@ -40,6 +48,8 @@ class CommentManager {
|
|||||||
|
|
||||||
#saveButton;
|
#saveButton;
|
||||||
|
|
||||||
|
#sidebar;
|
||||||
|
|
||||||
#uiManager;
|
#uiManager;
|
||||||
|
|
||||||
#prevDragX = Infinity;
|
#prevDragX = Infinity;
|
||||||
@ -66,6 +76,9 @@ class CommentManager {
|
|||||||
cancelButton,
|
cancelButton,
|
||||||
saveButton,
|
saveButton,
|
||||||
},
|
},
|
||||||
|
sidebar,
|
||||||
|
eventBus,
|
||||||
|
linkService,
|
||||||
overlayManager
|
overlayManager
|
||||||
) {
|
) {
|
||||||
this.#actions = actions;
|
this.#actions = actions;
|
||||||
@ -73,6 +86,7 @@ class CommentManager {
|
|||||||
this.#editMenuItem = editMenuItem;
|
this.#editMenuItem = editMenuItem;
|
||||||
this.#deleteMenuItem = deleteMenuItem;
|
this.#deleteMenuItem = deleteMenuItem;
|
||||||
this.#menu = menu;
|
this.#menu = menu;
|
||||||
|
this.#sidebar = new CommentSidebar(sidebar, eventBus, linkService);
|
||||||
this.#textInput = textInput;
|
this.#textInput = textInput;
|
||||||
this.#textView = textView;
|
this.#textView = textView;
|
||||||
this.#overlayManager = overlayManager;
|
this.#overlayManager = overlayManager;
|
||||||
@ -158,6 +172,26 @@ class CommentManager {
|
|||||||
overlayManager.register(dialog);
|
overlayManager.register(dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showSidebar(annotations) {
|
||||||
|
this.#sidebar.show(annotations);
|
||||||
|
}
|
||||||
|
|
||||||
|
hideSidebar() {
|
||||||
|
this.#sidebar.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
removeComments(ids) {
|
||||||
|
this.#sidebar.removeComments(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
selectComment(id) {
|
||||||
|
this.#sidebar.selectComment(null, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
addComment(annotation) {
|
||||||
|
this.#sidebar.addComment(annotation);
|
||||||
|
}
|
||||||
|
|
||||||
#closeMenu() {
|
#closeMenu() {
|
||||||
if (!this.#menuAC) {
|
if (!this.#menuAC) {
|
||||||
return;
|
return;
|
||||||
@ -378,4 +412,317 @@ class CommentManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CommentSidebar {
|
||||||
|
#annotations = null;
|
||||||
|
|
||||||
|
#boundCommentClick = this.#commentClick.bind(this);
|
||||||
|
|
||||||
|
#boundCommentKeydown = this.#commentKeydown.bind(this);
|
||||||
|
|
||||||
|
#sidebar;
|
||||||
|
|
||||||
|
#closeButton;
|
||||||
|
|
||||||
|
#commentsList;
|
||||||
|
|
||||||
|
#commentCount;
|
||||||
|
|
||||||
|
#sidebarTitle;
|
||||||
|
|
||||||
|
#linkService;
|
||||||
|
|
||||||
|
#elementsToAnnotations = null;
|
||||||
|
|
||||||
|
#idsToElements = null;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
{
|
||||||
|
sidebar,
|
||||||
|
commentsList,
|
||||||
|
commentCount,
|
||||||
|
sidebarTitle,
|
||||||
|
closeButton,
|
||||||
|
commentToolbarButton,
|
||||||
|
},
|
||||||
|
eventBus,
|
||||||
|
linkService
|
||||||
|
) {
|
||||||
|
this.#sidebar = sidebar;
|
||||||
|
this.#sidebarTitle = sidebarTitle;
|
||||||
|
this.#commentsList = commentsList;
|
||||||
|
this.#commentCount = commentCount;
|
||||||
|
this.#linkService = linkService;
|
||||||
|
this.#closeButton = closeButton;
|
||||||
|
|
||||||
|
closeButton.addEventListener("click", () => {
|
||||||
|
eventBus.dispatch("switchannotationeditormode", {
|
||||||
|
source: this,
|
||||||
|
mode: AnnotationEditorType.NONE,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
commentToolbarButton.addEventListener("keydown", e => {
|
||||||
|
if (e.key === "ArrowDown" || e.key === "Home" || e.key === "F6") {
|
||||||
|
this.#commentsList.firstElementChild.focus();
|
||||||
|
stopEvent(e);
|
||||||
|
} else if (e.key === "ArrowUp" || e.key === "End") {
|
||||||
|
this.#commentsList.lastElementChild.focus();
|
||||||
|
stopEvent(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.#sidebar.hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
show(annotations) {
|
||||||
|
this.#elementsToAnnotations = new WeakMap();
|
||||||
|
this.#idsToElements = new Map();
|
||||||
|
this.#annotations = annotations = annotations.filter(
|
||||||
|
a => a.popupRef && a.contentsObj?.str
|
||||||
|
);
|
||||||
|
annotations.sort(this.#sortComments.bind(this));
|
||||||
|
if (annotations.length !== 0) {
|
||||||
|
const fragment = document.createDocumentFragment();
|
||||||
|
for (const annotation of annotations) {
|
||||||
|
fragment.append(this.#createCommentElement(annotation));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#setCommentsCount(fragment);
|
||||||
|
this.#commentsList.append(fragment);
|
||||||
|
} else {
|
||||||
|
this.#setCommentsCount();
|
||||||
|
}
|
||||||
|
this.#sidebar.hidden = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hide() {
|
||||||
|
this.#sidebar.hidden = true;
|
||||||
|
this.#commentsList.replaceChildren();
|
||||||
|
this.#elementsToAnnotations = null;
|
||||||
|
this.#idsToElements = null;
|
||||||
|
this.#annotations = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeComments(ids) {
|
||||||
|
if (ids.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
new Set(this.#idsToElements.keys()).difference(new Set(ids)).size === 0
|
||||||
|
) {
|
||||||
|
this.#removeAll();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const id of ids) {
|
||||||
|
this.#removeComment(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
focusComment(id) {
|
||||||
|
const element = this.#idsToElements.get(id);
|
||||||
|
if (!element) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.#sidebar.scrollTop = element.offsetTop - this.#sidebar.offsetTop;
|
||||||
|
for (const el of this.#commentsList.children) {
|
||||||
|
el.classList.toggle("selected", el === element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#removeComment(id) {
|
||||||
|
const element = this.#idsToElements.get(id);
|
||||||
|
if (!element) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const annotation = this.#elementsToAnnotations.get(element);
|
||||||
|
const index = binarySearchFirstItem(
|
||||||
|
this.#annotations,
|
||||||
|
a => this.#sortComments(a, annotation) >= 0
|
||||||
|
);
|
||||||
|
if (index >= this.#annotations.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.#annotations.splice(index, 1);
|
||||||
|
element.remove();
|
||||||
|
this.#idsToElements.delete(id);
|
||||||
|
this.#setCommentsCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
#removeAll() {
|
||||||
|
this.#commentsList.replaceChildren();
|
||||||
|
this.#elementsToAnnotations = new WeakMap();
|
||||||
|
this.#idsToElements.clear();
|
||||||
|
this.#annotations.length = 0;
|
||||||
|
this.#setCommentsCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
selectComment(element, id = null) {
|
||||||
|
element ||= this.#idsToElements.get(id);
|
||||||
|
for (const el of this.#commentsList.children) {
|
||||||
|
el.classList.toggle("selected", el === element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addComment(annotation) {
|
||||||
|
if (this.#idsToElements.has(annotation.id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { popupRef, contentsObj } = annotation;
|
||||||
|
if (!popupRef || !contentsObj?.str) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const commentItem = this.#createCommentElement(annotation);
|
||||||
|
if (this.#annotations.length === 0) {
|
||||||
|
this.#commentsList.replaceChildren(commentItem);
|
||||||
|
this.#annotations.push(annotation);
|
||||||
|
this.#setCommentsCount();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const index = binarySearchFirstItem(
|
||||||
|
this.#annotations,
|
||||||
|
a => this.#sortComments(a, annotation) >= 0
|
||||||
|
);
|
||||||
|
this.#annotations.splice(index, 0, annotation);
|
||||||
|
if (index >= this.#commentsList.children.length) {
|
||||||
|
this.#commentsList.append(commentItem);
|
||||||
|
} else {
|
||||||
|
this.#commentsList.insertBefore(
|
||||||
|
commentItem,
|
||||||
|
this.#commentsList.children[index]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
this.#setCommentsCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
#setCommentsCount(container = this.#commentsList) {
|
||||||
|
const count = this.#idsToElements.size;
|
||||||
|
this.#sidebarTitle.setAttribute(
|
||||||
|
"data-l10n-args",
|
||||||
|
JSON.stringify({ count })
|
||||||
|
);
|
||||||
|
this.#commentCount.textContent = count;
|
||||||
|
if (count === 0) {
|
||||||
|
container.append(this.#createZeroCommentElement());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#createZeroCommentElement() {
|
||||||
|
const commentItem = document.createElement("li");
|
||||||
|
commentItem.classList.add("sidebarComment", "noComments");
|
||||||
|
commentItem.role = "button";
|
||||||
|
const textDiv = document.createElement("div");
|
||||||
|
textDiv.className = "sidebarCommentText";
|
||||||
|
textDiv.setAttribute(
|
||||||
|
"data-l10n-id",
|
||||||
|
"pdfjs-editor-comments-sidebar-no-comments"
|
||||||
|
);
|
||||||
|
commentItem.addEventListener("keydown", this.#boundCommentKeydown);
|
||||||
|
commentItem.append(textDiv);
|
||||||
|
return commentItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#createCommentElement(annotation) {
|
||||||
|
const {
|
||||||
|
creationDate,
|
||||||
|
modificationDate,
|
||||||
|
contentsObj: { str: text },
|
||||||
|
} = annotation;
|
||||||
|
const commentItem = document.createElement("li");
|
||||||
|
commentItem.role = "button";
|
||||||
|
commentItem.className = "sidebarComment";
|
||||||
|
commentItem.tabIndex = -1;
|
||||||
|
|
||||||
|
const dateDiv = document.createElement("time");
|
||||||
|
const date = PDFDateString.toDateObject(modificationDate || creationDate);
|
||||||
|
dateDiv.dateTime = date.toISOString();
|
||||||
|
const dateFormat = new Intl.DateTimeFormat(undefined, {
|
||||||
|
dateStyle: "long",
|
||||||
|
});
|
||||||
|
dateDiv.textContent = dateFormat.format(date);
|
||||||
|
|
||||||
|
const textDiv = document.createElement("div");
|
||||||
|
textDiv.className = "sidebarCommentText";
|
||||||
|
textDiv.textContent = text;
|
||||||
|
commentItem.append(dateDiv, textDiv);
|
||||||
|
commentItem.addEventListener("click", this.#boundCommentClick);
|
||||||
|
commentItem.addEventListener("keydown", this.#boundCommentKeydown);
|
||||||
|
|
||||||
|
this.#elementsToAnnotations.set(commentItem, annotation);
|
||||||
|
this.#idsToElements.set(annotation.id, commentItem);
|
||||||
|
return commentItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#commentClick({ currentTarget }) {
|
||||||
|
if (currentTarget.classList.contains("selected")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const annotation = this.#elementsToAnnotations.get(currentTarget);
|
||||||
|
if (!annotation) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { pageIndex, rect } = annotation;
|
||||||
|
const SPACE_ABOVE_ANNOTATION = 10;
|
||||||
|
this.#linkService?.goToXY(
|
||||||
|
pageIndex + 1,
|
||||||
|
rect[0],
|
||||||
|
rect[3] + SPACE_ABOVE_ANNOTATION
|
||||||
|
);
|
||||||
|
this.selectComment(currentTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
#commentKeydown(e) {
|
||||||
|
const { key, currentTarget } = e;
|
||||||
|
switch (key) {
|
||||||
|
case "ArrowDown":
|
||||||
|
(
|
||||||
|
currentTarget.nextElementSibling ||
|
||||||
|
this.#commentsList.firstElementChild
|
||||||
|
).focus();
|
||||||
|
stopEvent(e);
|
||||||
|
break;
|
||||||
|
case "ArrowUp":
|
||||||
|
(
|
||||||
|
currentTarget.previousElementSibling ||
|
||||||
|
this.#commentsList.lastElementChild
|
||||||
|
).focus();
|
||||||
|
stopEvent(e);
|
||||||
|
break;
|
||||||
|
case "Home":
|
||||||
|
this.#commentsList.firstElementChild.focus();
|
||||||
|
stopEvent(e);
|
||||||
|
break;
|
||||||
|
case "End":
|
||||||
|
this.#commentsList.lastElementChild.focus();
|
||||||
|
stopEvent(e);
|
||||||
|
break;
|
||||||
|
case "Enter":
|
||||||
|
case " ":
|
||||||
|
this.#commentClick(e);
|
||||||
|
stopEvent(e);
|
||||||
|
break;
|
||||||
|
case "ShiftTab":
|
||||||
|
this.#closeButton.focus();
|
||||||
|
stopEvent(e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#sortComments(a, b) {
|
||||||
|
if (a.pageIndex !== b.pageIndex) {
|
||||||
|
return a.pageIndex - b.pageIndex;
|
||||||
|
}
|
||||||
|
if (a.rect[3] !== b.rect[3]) {
|
||||||
|
return b.rect[3] - a.rect[3];
|
||||||
|
}
|
||||||
|
if (a.rect[0] !== b.rect[0]) {
|
||||||
|
return a.rect[0] - b.rect[0];
|
||||||
|
}
|
||||||
|
if (a.rect[1] !== b.rect[1]) {
|
||||||
|
return b.rect[1] - a.rect[1];
|
||||||
|
}
|
||||||
|
if (a.rect[2] !== b.rect[2]) {
|
||||||
|
return a.rect[2] - b.rect[2];
|
||||||
|
}
|
||||||
|
return a.id.localeCompare(b.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export { CommentManager };
|
export { CommentManager };
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
@import url(xfa_layer_builder.css);
|
@import url(xfa_layer_builder.css);
|
||||||
/* Ignored in GECKOVIEW builds: */
|
/* Ignored in GECKOVIEW builds: */
|
||||||
@import url(annotation_editor_layer_builder.css);
|
@import url(annotation_editor_layer_builder.css);
|
||||||
|
@import url(sidebar.css);
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
color-scheme: light dark;
|
color-scheme: light dark;
|
||||||
|
|||||||
37
web/sidebar.css
Normal file
37
web/sidebar.css
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/* Copyright 2025 Mozilla Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
--sidebar-bg-color: light-dark(#fff, #23222b);
|
||||||
|
--sidebar-border-color: light-dark(
|
||||||
|
rgb(21 20 26 / 0.1),
|
||||||
|
rgb(251 251 254 / 0.1)
|
||||||
|
);
|
||||||
|
--sidebar-box-shadow:
|
||||||
|
0 0.25px 0.75px light-dark(rgb(0 0 0 / 0.05), rgb(0 0 0 / 0.2)),
|
||||||
|
0 2px 6px 0 light-dark(rgb(0 0 0 / 0.1), rgb(0 0 0 / 0.4));
|
||||||
|
|
||||||
|
@media screen and (forced-colors: active) {
|
||||||
|
--sidebar-bg-color: Canvas;
|
||||||
|
--sidebar-border-color: CanvasText;
|
||||||
|
--sidebar-box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: var(--sidebar-box-shadow);
|
||||||
|
border: 1px solid var(--sidebar-border-color);
|
||||||
|
background-color: var(--sidebar-bg-color);
|
||||||
|
inset-block-start: calc(100% + var(--doorhanger-height) - 2px);
|
||||||
|
}
|
||||||
@ -67,6 +67,18 @@ class Toolbar {
|
|||||||
{ element: options.zoomOut, eventName: "zoomout" },
|
{ element: options.zoomOut, eventName: "zoomout" },
|
||||||
{ element: options.print, eventName: "print" },
|
{ element: options.print, eventName: "print" },
|
||||||
{ element: options.download, eventName: "download" },
|
{ element: options.download, eventName: "download" },
|
||||||
|
{
|
||||||
|
element: options.editorCommentButton,
|
||||||
|
eventName: "switchannotationeditormode",
|
||||||
|
eventDetails: {
|
||||||
|
get mode() {
|
||||||
|
const { classList } = options.editorCommentButton;
|
||||||
|
return classList.contains("toggled")
|
||||||
|
? AnnotationEditorType.NONE
|
||||||
|
: AnnotationEditorType.POPUP;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
element: options.editorFreeTextButton,
|
element: options.editorFreeTextButton,
|
||||||
eventName: "switchannotationeditormode",
|
eventName: "switchannotationeditormode",
|
||||||
@ -278,6 +290,8 @@ class Toolbar {
|
|||||||
|
|
||||||
#editorModeChanged({ mode }) {
|
#editorModeChanged({ mode }) {
|
||||||
const {
|
const {
|
||||||
|
editorCommentButton,
|
||||||
|
editorCommentParamsToolbar,
|
||||||
editorFreeTextButton,
|
editorFreeTextButton,
|
||||||
editorFreeTextParamsToolbar,
|
editorFreeTextParamsToolbar,
|
||||||
editorHighlightButton,
|
editorHighlightButton,
|
||||||
@ -290,6 +304,11 @@ class Toolbar {
|
|||||||
editorSignatureParamsToolbar,
|
editorSignatureParamsToolbar,
|
||||||
} = this.#opts;
|
} = this.#opts;
|
||||||
|
|
||||||
|
toggleExpandedBtn(
|
||||||
|
editorCommentButton,
|
||||||
|
mode === AnnotationEditorType.POPUP,
|
||||||
|
editorCommentParamsToolbar
|
||||||
|
);
|
||||||
toggleExpandedBtn(
|
toggleExpandedBtn(
|
||||||
editorFreeTextButton,
|
editorFreeTextButton,
|
||||||
mode === AnnotationEditorType.FREETEXT,
|
mode === AnnotationEditorType.FREETEXT,
|
||||||
@ -316,12 +335,13 @@ class Toolbar {
|
|||||||
editorSignatureParamsToolbar
|
editorSignatureParamsToolbar
|
||||||
);
|
);
|
||||||
|
|
||||||
const isDisable = mode === AnnotationEditorType.DISABLE;
|
editorCommentButton.disabled =
|
||||||
editorFreeTextButton.disabled = isDisable;
|
editorFreeTextButton.disabled =
|
||||||
editorHighlightButton.disabled = isDisable;
|
editorHighlightButton.disabled =
|
||||||
editorInkButton.disabled = isDisable;
|
editorInkButton.disabled =
|
||||||
editorStampButton.disabled = isDisable;
|
editorStampButton.disabled =
|
||||||
editorSignatureButton.disabled = isDisable;
|
editorSignatureButton.disabled =
|
||||||
|
mode === AnnotationEditorType.DISABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#updateUIState(resetNumPages = false) {
|
#updateUIState(resetNumPages = false) {
|
||||||
|
|||||||
@ -99,6 +99,7 @@
|
|||||||
--loading-icon: url(images/loading.svg);
|
--loading-icon: url(images/loading.svg);
|
||||||
--treeitem-expanded-icon: url(images/treeitem-expanded.svg);
|
--treeitem-expanded-icon: url(images/treeitem-expanded.svg);
|
||||||
--treeitem-collapsed-icon: url(images/treeitem-collapsed.svg);
|
--treeitem-collapsed-icon: url(images/treeitem-collapsed.svg);
|
||||||
|
--toolbarButton-editorComment-icon: url(images/comment-editButton.svg);
|
||||||
--toolbarButton-editorFreeText-icon: url(images/toolbarButton-editorFreeText.svg);
|
--toolbarButton-editorFreeText-icon: url(images/toolbarButton-editorFreeText.svg);
|
||||||
--toolbarButton-editorHighlight-icon: url(images/toolbarButton-editorHighlight.svg);
|
--toolbarButton-editorHighlight-icon: url(images/toolbarButton-editorHighlight.svg);
|
||||||
--toolbarButton-editorInk-icon: url(images/toolbarButton-editorInk.svg);
|
--toolbarButton-editorInk-icon: url(images/toolbarButton-editorInk.svg);
|
||||||
@ -541,6 +542,11 @@ body {
|
|||||||
mask-image: var(--toolbarButton-zoomIn-icon);
|
mask-image: var(--toolbarButton-zoomIn-icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#editorCommentButton::before {
|
||||||
|
mask-image: var(--toolbarButton-editorComment-icon);
|
||||||
|
transform: scaleX(var(--dir-factor));
|
||||||
|
}
|
||||||
|
|
||||||
#editorFreeTextButton::before {
|
#editorFreeTextButton::before {
|
||||||
mask-image: var(--toolbarButton-editorFreeText-icon);
|
mask-image: var(--toolbarButton-editorFreeText-icon);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -245,6 +245,25 @@ See https://github.com/adobe-type-tools/cmap-resources
|
|||||||
</div>
|
</div>
|
||||||
<div id="toolbarViewerRight" class="toolbarHorizontalGroup">
|
<div id="toolbarViewerRight" class="toolbarHorizontalGroup">
|
||||||
<div id="editorModeButtons" class="toolbarHorizontalGroup" role="radiogroup">
|
<div id="editorModeButtons" class="toolbarHorizontalGroup" role="radiogroup">
|
||||||
|
<div id="editorComment" class="toolbarButtonWithContainer" hidden="true">
|
||||||
|
<button id="editorCommentButton" class="toolbarButton" type="button" tabindex="0" disabled="disabled" role="radio" aria-expanded="false" aria-haspopup="true" aria-controls="editorCommentParamsToolbar" data-l10n-id="pdfjs-editor-comment-button">
|
||||||
|
<span data-l10n-id="pdfjs-editor-comment-button-label"></span>
|
||||||
|
</button>
|
||||||
|
<div class="editorParamsToolbar sidebar hidden menu" id="editorCommentParamsToolbar">
|
||||||
|
<div id="editorCommentsSidebar" class="menuContainer" role="landmark" aria-labelledby="editorCommentsSidebarHeader">
|
||||||
|
<div id="editorCommentsSidebarHeader" role="heading" aria-level="2">
|
||||||
|
<span class="commentCount">
|
||||||
|
<span id="editorCommentsSidebarTitle" data-l10n-id="pdfjs-editor-comments-sidebar-title" data-l10n-args='{ "count": 0 }'></span>
|
||||||
|
<span id="editorCommentsSidebarCount"></span>
|
||||||
|
</span>
|
||||||
|
<button id="editorCommentsSidebarCloseButton" type="button" tabindex="0" data-l10n-id="pdfjs-editor-comments-sidebar-close-button">
|
||||||
|
<span data-l10n-id="pdfjs-editor-comments-sidebar-close-button-label"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<ul id="editorCommentsSidebarList"></ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div id="editorSignature" class="toolbarButtonWithContainer" hidden="true">
|
<div id="editorSignature" class="toolbarButtonWithContainer" hidden="true">
|
||||||
<button id="editorSignatureButton" class="toolbarButton" type="button" tabindex="0" disabled="disabled" role="radio" aria-expanded="false" aria-haspopup="true" aria-controls="editorSignatureParamsToolbar" data-l10n-id="pdfjs-editor-signature-button">
|
<button id="editorSignatureButton" class="toolbarButton" type="button" tabindex="0" disabled="disabled" role="radio" aria-expanded="false" aria-haspopup="true" aria-controls="editorSignatureParamsToolbar" data-l10n-id="pdfjs-editor-signature-button">
|
||||||
<span data-l10n-id="pdfjs-editor-signature-button-label"></span>
|
<span data-l10n-id="pdfjs-editor-signature-button-label"></span>
|
||||||
|
|||||||
@ -45,6 +45,10 @@ function getViewerConfiguration() {
|
|||||||
zoomIn: document.getElementById("zoomInButton"),
|
zoomIn: document.getElementById("zoomInButton"),
|
||||||
zoomOut: document.getElementById("zoomOutButton"),
|
zoomOut: document.getElementById("zoomOutButton"),
|
||||||
print: document.getElementById("printButton"),
|
print: document.getElementById("printButton"),
|
||||||
|
editorCommentButton: document.getElementById("editorCommentButton"),
|
||||||
|
editorCommentParamsToolbar: document.getElementById(
|
||||||
|
"editorCommentParamsToolbar"
|
||||||
|
),
|
||||||
editorFreeTextButton: document.getElementById("editorFreeTextButton"),
|
editorFreeTextButton: document.getElementById("editorFreeTextButton"),
|
||||||
editorFreeTextParamsToolbar: document.getElementById(
|
editorFreeTextParamsToolbar: document.getElementById(
|
||||||
"editorFreeTextParamsToolbar"
|
"editorFreeTextParamsToolbar"
|
||||||
@ -241,6 +245,19 @@ function getViewerConfiguration() {
|
|||||||
updateButton: document.getElementById("editSignatureUpdateButton"),
|
updateButton: document.getElementById("editSignatureUpdateButton"),
|
||||||
},
|
},
|
||||||
annotationEditorParams: {
|
annotationEditorParams: {
|
||||||
|
editorCommentsSidebar: document.getElementById("editorCommentsSidebar"),
|
||||||
|
editorCommentsSidebarCount: document.getElementById(
|
||||||
|
"editorCommentsSidebarCount"
|
||||||
|
),
|
||||||
|
editorCommentsSidebarTitle: document.getElementById(
|
||||||
|
"editorCommentsSidebarTitle"
|
||||||
|
),
|
||||||
|
editorCommentsSidebarCloseButton: document.getElementById(
|
||||||
|
"editorCommentsSidebarCloseButton"
|
||||||
|
),
|
||||||
|
editorCommentsSidebarList: document.getElementById(
|
||||||
|
"editorCommentsSidebarList"
|
||||||
|
),
|
||||||
editorFreeTextFontSize: document.getElementById("editorFreeTextFontSize"),
|
editorFreeTextFontSize: document.getElementById("editorFreeTextFontSize"),
|
||||||
editorFreeTextColor: document.getElementById("editorFreeTextColor"),
|
editorFreeTextColor: document.getElementById("editorFreeTextColor"),
|
||||||
editorInkColor: document.getElementById("editorInkColor"),
|
editorInkColor: document.getElementById("editorInkColor"),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user