Skip to content

Commit 3fb7cd4

Browse files
committed
[Editor] Add a floating button in order to highlight the text selection and add a comment (bug 1979381)
The callback called when clicking on the button is the same as the one trigged by clicking in the context menu (in m-c).
1 parent 366727d commit 3fb7cd4

File tree

8 files changed

+144
-126
lines changed

8 files changed

+144
-126
lines changed

l10n/en-US/viewer.ftl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,10 @@ pdfjs-highlight-floating-button1 =
324324
.title = Highlight
325325
.aria-label = Highlight
326326
pdfjs-highlight-floating-button-label = Highlight
327+
pdfjs-comment-floating-button =
328+
.title = Comment
329+
.aria-label = Comment
330+
pdfjs-comment-floating-button-label = Comment
327331
pdfjs-editor-signature-button =
328332
.title = Add signature
329333
pdfjs-editor-signature-button-label = Add signature

src/display/editor/toolbar.js

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ class EditorToolbar {
123123
const { editorType, _uiManager } = this.#editor;
124124

125125
const button = document.createElement("button");
126-
button.className = "delete";
126+
button.classList.add("basic", "deleteButton");
127127
button.tabIndex = 0;
128128
button.setAttribute("data-l10n-id", EditorToolbar.#l10nRemove[editorType]);
129129
this.#addListenersToElement(button);
@@ -214,7 +214,7 @@ class EditorToolbar {
214214
}
215215
}
216216

217-
class HighlightToolbar {
217+
class FloatingToolbar {
218218
#buttons = null;
219219

220220
#toolbar = null;
@@ -237,7 +237,25 @@ class HighlightToolbar {
237237
buttons.className = "buttons";
238238
editToolbar.append(buttons);
239239

240-
this.#addHighlightButton();
240+
if (this.#uiManager.hasCommentManager()) {
241+
this.#makeButton(
242+
"commentButton",
243+
`pdfjs-comment-floating-button`,
244+
"pdfjs-comment-floating-button-label",
245+
() => {
246+
this.#uiManager.commentSelection("floating_button");
247+
}
248+
);
249+
}
250+
251+
this.#makeButton(
252+
"highlightButton",
253+
`pdfjs-highlight-floating-button1`,
254+
"pdfjs-highlight-floating-button-label",
255+
() => {
256+
this.#uiManager.highlightSelection("floating_button");
257+
}
258+
);
241259

242260
return editToolbar;
243261
}
@@ -279,26 +297,20 @@ class HighlightToolbar {
279297
this.#toolbar.remove();
280298
}
281299

282-
#addHighlightButton() {
300+
#makeButton(buttonClass, l10nId, labelL10nId, clickHandler) {
283301
const button = document.createElement("button");
284-
button.className = "highlightButton";
302+
button.classList.add("basic", buttonClass);
285303
button.tabIndex = 0;
286-
button.setAttribute("data-l10n-id", `pdfjs-highlight-floating-button1`);
304+
button.setAttribute("data-l10n-id", l10nId);
287305
const span = document.createElement("span");
288306
button.append(span);
289307
span.className = "visuallyHidden";
290-
span.setAttribute("data-l10n-id", "pdfjs-highlight-floating-button-label");
308+
span.setAttribute("data-l10n-id", labelL10nId);
291309
const signal = this.#uiManager._signal;
292310
button.addEventListener("contextmenu", noContextMenu, { signal });
293-
button.addEventListener(
294-
"click",
295-
() => {
296-
this.#uiManager.highlightSelection("floating_button");
297-
},
298-
{ signal }
299-
);
311+
button.addEventListener("click", clickHandler, { signal });
300312
this.#buttons.append(button);
301313
}
302314
}
303315

304-
export { EditorToolbar, HighlightToolbar };
316+
export { EditorToolbar, FloatingToolbar };

src/display/editor/tools.js

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import {
3434
PixelsPerInch,
3535
stopEvent,
3636
} from "../display_utils.js";
37-
import { HighlightToolbar } from "./toolbar.js";
37+
import { FloatingToolbar } from "./toolbar.js";
3838

3939
function bindEvents(obj, element, names) {
4040
for (const name of names) {
@@ -631,7 +631,7 @@ class AnnotationEditorUIManager {
631631

632632
#highlightWhenShiftUp = false;
633633

634-
#highlightToolbar = null;
634+
#floatingToolbar = null;
635635

636636
#idManager = new IdManager();
637637

@@ -908,8 +908,8 @@ class AnnotationEditorUIManager {
908908
this.#altTextManager?.destroy();
909909
this.#commentManager?.destroy();
910910
this.#signatureManager?.destroy();
911-
this.#highlightToolbar?.hide();
912-
this.#highlightToolbar = null;
911+
this.#floatingToolbar?.hide();
912+
this.#floatingToolbar = null;
913913
this.#mainHighlightColorPicker?.destroy();
914914
this.#mainHighlightColorPicker = null;
915915
if (this.#focusMainContainerTimeoutId) {
@@ -1157,7 +1157,7 @@ class AnnotationEditorUIManager {
11571157
return null;
11581158
}
11591159

1160-
highlightSelection(methodOfCreation = "") {
1160+
highlightSelection(methodOfCreation = "", comment = false) {
11611161
const selection = document.getSelection();
11621162
if (!selection || selection.isCollapsed) {
11631163
return;
@@ -1175,7 +1175,7 @@ class AnnotationEditorUIManager {
11751175
const layer = this.#getLayerForTextLayer(textLayer);
11761176
const isNoneMode = this.#mode === AnnotationEditorType.NONE;
11771177
const callback = () => {
1178-
layer?.createAndAddNewEditor({ x: 0, y: 0 }, false, {
1178+
const editor = layer?.createAndAddNewEditor({ x: 0, y: 0 }, false, {
11791179
methodOfCreation,
11801180
boxes,
11811181
anchorNode,
@@ -1187,6 +1187,9 @@ class AnnotationEditorUIManager {
11871187
if (isNoneMode) {
11881188
this.showAllEditors("highlight", true, /* updateButton = */ true);
11891189
}
1190+
if (comment) {
1191+
editor?.editComment();
1192+
}
11901193
};
11911194
if (isNoneMode) {
11921195
this.switchToMode(AnnotationEditorType.HIGHLIGHT, callback);
@@ -1195,7 +1198,11 @@ class AnnotationEditorUIManager {
11951198
callback();
11961199
}
11971200

1198-
#displayHighlightToolbar() {
1201+
commentSelection(methodOfCreation = "") {
1202+
this.highlightSelection(methodOfCreation, /* comment */ true);
1203+
}
1204+
1205+
#displayFloatingToolbar() {
11991206
const selection = document.getSelection();
12001207
if (!selection || selection.isCollapsed) {
12011208
return;
@@ -1206,8 +1213,8 @@ class AnnotationEditorUIManager {
12061213
if (!boxes) {
12071214
return;
12081215
}
1209-
this.#highlightToolbar ||= new HighlightToolbar(this);
1210-
this.#highlightToolbar.show(textLayer, boxes, this.direction === "ltr");
1216+
this.#floatingToolbar ||= new FloatingToolbar(this);
1217+
this.#floatingToolbar.show(textLayer, boxes, this.direction === "ltr");
12111218
}
12121219

12131220
/**
@@ -1241,7 +1248,7 @@ class AnnotationEditorUIManager {
12411248
const selection = document.getSelection();
12421249
if (!selection || selection.isCollapsed) {
12431250
if (this.#selectedTextNode) {
1244-
this.#highlightToolbar?.hide();
1251+
this.#floatingToolbar?.hide();
12451252
this.#selectedTextNode = null;
12461253
this.#dispatchUpdateStates({
12471254
hasSelectedText: false,
@@ -1258,7 +1265,7 @@ class AnnotationEditorUIManager {
12581265
const textLayer = anchorElement.closest(".textLayer");
12591266
if (!textLayer) {
12601267
if (this.#selectedTextNode) {
1261-
this.#highlightToolbar?.hide();
1268+
this.#floatingToolbar?.hide();
12621269
this.#selectedTextNode = null;
12631270
this.#dispatchUpdateStates({
12641271
hasSelectedText: false,
@@ -1267,7 +1274,7 @@ class AnnotationEditorUIManager {
12671274
return;
12681275
}
12691276

1270-
this.#highlightToolbar?.hide();
1277+
this.#floatingToolbar?.hide();
12711278
this.#selectedTextNode = anchorNode;
12721279
this.#dispatchUpdateStates({
12731280
hasSelectedText: true,
@@ -1315,7 +1322,7 @@ class AnnotationEditorUIManager {
13151322
if (this.#mode === AnnotationEditorType.HIGHLIGHT) {
13161323
this.highlightSelection(methodOfCreation);
13171324
} else if (this.#enableHighlightFloatingButton) {
1318-
this.#displayHighlightToolbar();
1325+
this.#displayFloatingToolbar();
13191326
}
13201327
}
13211328

@@ -1606,6 +1613,9 @@ class AnnotationEditorUIManager {
16061613
case "highlightSelection":
16071614
this.highlightSelection("context_menu");
16081615
break;
1616+
case "commentSelection":
1617+
this.commentSelection("context_menu");
1618+
break;
16091619
}
16101620
}
16111621

test/integration/freetext_editor_spec.mjs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2591,7 +2591,7 @@ describe("FreeText Editor", () => {
25912591
await commit(page);
25922592

25932593
// Delete it in using the button.
2594-
await page.click(`${editorSelector} button.delete`);
2594+
await page.click(`${editorSelector} button.deleteButton`);
25952595
await page.waitForFunction(
25962596
sel => !document.querySelector(sel),
25972597
{},
@@ -2644,7 +2644,7 @@ describe("FreeText Editor", () => {
26442644
await selectAll(page);
26452645

26462646
// Delete it in using the button.
2647-
await page.focus(`${editorSelector} button.delete`);
2647+
await page.focus(`${editorSelector} button.deleteButton`);
26482648
await page.keyboard.press("Enter");
26492649
await page.waitForFunction(
26502650
sel => !document.querySelector(sel),
@@ -2885,8 +2885,8 @@ describe("FreeText Editor", () => {
28852885
await commit(page);
28862886
await waitForSerialized(page, 1);
28872887

2888-
await page.waitForSelector(`${editorSelector} button.delete`);
2889-
await page.click(`${editorSelector} button.delete`);
2888+
await page.waitForSelector(`${editorSelector} button.deleteButton`);
2889+
await page.click(`${editorSelector} button.deleteButton`);
28902890
await waitForSerialized(page, 0);
28912891

28922892
const twoToFourteen = Array.from(new Array(13).keys(), n => n + 2);
@@ -2935,8 +2935,8 @@ describe("FreeText Editor", () => {
29352935
await commit(page);
29362936
await waitForSerialized(page, 1);
29372937

2938-
await page.waitForSelector(`${editorSelector} button.delete`);
2939-
await page.click(`${editorSelector} button.delete`);
2938+
await page.waitForSelector(`${editorSelector} button.deleteButton`);
2939+
await page.click(`${editorSelector} button.deleteButton`);
29402940
await waitForSerialized(page, 0);
29412941

29422942
const twoToOne = Array.from(new Array(13).keys(), n => n + 2).concat(
@@ -3271,8 +3271,8 @@ describe("FreeText Editor", () => {
32713271
await commit(page);
32723272
await waitForSerialized(page, 1);
32733273

3274-
await page.waitForSelector(`${editorSelector} button.delete`);
3275-
await page.click(`${editorSelector} button.delete`);
3274+
await page.waitForSelector(`${editorSelector} button.deleteButton`);
3275+
await page.click(`${editorSelector} button.deleteButton`);
32763276
await waitForSerialized(page, 0);
32773277
await page.waitForSelector("#editorUndoBar", { visible: true });
32783278

@@ -3299,8 +3299,8 @@ describe("FreeText Editor", () => {
32993299
await commit(page);
33003300
await waitForSerialized(page, 1);
33013301

3302-
await page.waitForSelector(`${editorSelector} button.delete`);
3303-
await page.click(`${editorSelector} button.delete`);
3302+
await page.waitForSelector(`${editorSelector} button.deleteButton`);
3303+
await page.click(`${editorSelector} button.deleteButton`);
33043304
await waitForSerialized(page, 0);
33053305

33063306
await page.waitForFunction(() => {
@@ -3332,8 +3332,8 @@ describe("FreeText Editor", () => {
33323332
await commit(page);
33333333
await waitForSerialized(page, 1);
33343334

3335-
await page.waitForSelector(`${editorSelector} button.delete`);
3336-
await page.click(`${editorSelector} button.delete`);
3335+
await page.waitForSelector(`${editorSelector} button.deleteButton`);
3336+
await page.click(`${editorSelector} button.deleteButton`);
33373337
await waitForSerialized(page, 0);
33383338

33393339
await page.waitForSelector("#editorUndoBar", { visible: true });

0 commit comments

Comments
 (0)