Allow to collapse/expand all the outlines in double clicking somewhere on the header bar (bug 2019550)

This commit is contained in:
Calixte Denizet 2026-03-11 18:52:40 +01:00
parent 0ee557cd60
commit 96d1465aab
3 changed files with 113 additions and 10 deletions

View File

@ -705,9 +705,11 @@ pdfjs-views-manager-view-selector-button =
.title = Views
pdfjs-views-manager-view-selector-button-label = Views
pdfjs-views-manager-pages-title = Pages
pdfjs-views-manager-outlines-title = Document outline
pdfjs-views-manager-outlines-title1 = Document outline
.title = Document outline (double-click to expand/collapse all items)
pdfjs-views-manager-attachments-title = Attachments
pdfjs-views-manager-layers-title = Layers
pdfjs-views-manager-layers-title1 = Layers
.title = Layers (double-click to reset all layers to the default state)
pdfjs-views-manager-pages-option-label = Pages
pdfjs-views-manager-outlines-option-label = Document outline

View File

@ -1687,4 +1687,101 @@ describe("PDF viewer", () => {
);
});
});
describe("Double-click on title collapses/expands all outline items", () => {
let pages;
beforeEach(async () => {
pages = await loadAndWait(
"nested_outline.pdf",
"#viewsManagerToggleButton"
);
});
afterEach(async () => {
await closePages(pages);
});
it("should collapse all outline items on first double-click and expand them on second", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
await showViewsManager(page);
await page.click("#viewsManagerSelectorButton");
await page.waitForSelector("#outlinesViewMenu", { visible: true });
await page.click("#outlinesViewMenu");
await page.waitForSelector("#outlinesView.withNesting");
// Initially all togglers must be expanded (none hidden).
const initialHiddenCount = await page.$$eval(
"#outlinesView .treeItemToggler",
togglers =>
togglers.filter(t => t.classList.contains("treeItemsHidden"))
.length
);
expect(initialHiddenCount).withContext(`In ${browserName}`).toBe(0);
// Double-click the title label (not on a button) to collapse all.
await page.click("#viewsManagerHeaderLabel", { count: 2 });
await page.waitForFunction(
() =>
document.querySelectorAll(
"#outlinesView .treeItemToggler:not(.treeItemsHidden)"
).length === 0
);
// Double-click again to expand all.
await page.click("#viewsManagerHeaderLabel", { count: 2 });
await page.waitForFunction(
() =>
document.querySelectorAll(
"#outlinesView .treeItemToggler.treeItemsHidden"
).length === 0
);
})
);
});
});
describe("Double-click on title resets all layer checkboxes", () => {
let pages;
beforeEach(async () => {
pages = await loadAndWait("issue17679.pdf", "#viewsManagerToggleButton");
});
afterEach(async () => {
await closePages(pages);
});
it("should restore all layer checkboxes to checked after unchecking them", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
await showViewsManager(page);
await page.click("#viewsManagerSelectorButton");
await page.waitForSelector("#layersViewMenu", { visible: true });
await page.click("#layersViewMenu");
await page.waitForSelector("#layersView input[type='checkbox']");
// Uncheck all checkboxes.
const checkboxes = await page.$$(
"#layersView input[type='checkbox']"
);
for (const checkbox of checkboxes) {
await checkbox.click();
}
await page.waitForSelector("#layersView:not(:has(:checked))");
// Double-click the title label to reset layers to their default
// state.
await page.click("#viewsManagerHeaderLabel", { count: 2 });
await page.waitForSelector(
`#layersView:not(:has(input[type="checkbox"]:not(:checked)))`
);
})
);
});
});
});

View File

@ -158,9 +158,9 @@ class ViewsManager extends Sidebar {
ViewsManager.#l10nDescription ||= Object.freeze({
pagesTitle: "pdfjs-views-manager-pages-title",
outlinesTitle: "pdfjs-views-manager-outlines-title",
outlinesTitle: "pdfjs-views-manager-outlines-title1",
attachmentsTitle: "pdfjs-views-manager-attachments-title",
layersTitle: "pdfjs-views-manager-layers-title",
layersTitle: "pdfjs-views-manager-layers-title1",
notificationButton: "pdfjs-toggle-views-manager-notification-button",
toggleButton: "pdfjs-toggle-views-manager-button",
});
@ -424,6 +424,16 @@ class ViewsManager extends Sidebar {
});
}
this.viewsManagerHeaderLabel.addEventListener("dblclick", e => {
if (this.active === SidebarView.OUTLINE) {
eventBus.dispatch("toggleoutlinetree", { source: this });
return;
}
if (this.active === SidebarView.LAYERS) {
eventBus.dispatch("resetlayers", { source: this });
}
});
// Buttons for switching views.
this.thumbnailButton.addEventListener("click", () => {
this.switchView(SidebarView.THUMBS);
@ -432,9 +442,6 @@ class ViewsManager extends Sidebar {
this.outlineButton.addEventListener("click", () => {
this.switchView(SidebarView.OUTLINE);
});
this.outlineButton.addEventListener("dblclick", () => {
eventBus.dispatch("toggleoutlinetree", { source: this });
});
this.attachmentsButton.addEventListener("click", () => {
this.switchView(SidebarView.ATTACHMENTS);
@ -443,9 +450,6 @@ class ViewsManager extends Sidebar {
this.layersButton.addEventListener("click", () => {
this.switchView(SidebarView.LAYERS);
});
this.layersButton.addEventListener("dblclick", () => {
eventBus.dispatch("resetlayers", { source: this });
});
// Buttons for view-specific options.
this.viewsManagerCurrentOutlineButton.addEventListener("click", () => {