Skip to content

Commit 96d1465

Browse files
committed
Allow to collapse/expand all the outlines in double clicking somewhere on the header bar (bug 2019550)
1 parent 0ee557c commit 96d1465

3 files changed

Lines changed: 113 additions & 10 deletions

File tree

l10n/en-US/viewer.ftl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -705,9 +705,11 @@ pdfjs-views-manager-view-selector-button =
705705
.title = Views
706706
pdfjs-views-manager-view-selector-button-label = Views
707707
pdfjs-views-manager-pages-title = Pages
708-
pdfjs-views-manager-outlines-title = Document outline
708+
pdfjs-views-manager-outlines-title1 = Document outline
709+
.title = Document outline (double-click to expand/collapse all items)
709710
pdfjs-views-manager-attachments-title = Attachments
710-
pdfjs-views-manager-layers-title = Layers
711+
pdfjs-views-manager-layers-title1 = Layers
712+
.title = Layers (double-click to reset all layers to the default state)
711713
712714
pdfjs-views-manager-pages-option-label = Pages
713715
pdfjs-views-manager-outlines-option-label = Document outline

test/integration/viewer_spec.mjs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1687,4 +1687,101 @@ describe("PDF viewer", () => {
16871687
);
16881688
});
16891689
});
1690+
1691+
describe("Double-click on title collapses/expands all outline items", () => {
1692+
let pages;
1693+
1694+
beforeEach(async () => {
1695+
pages = await loadAndWait(
1696+
"nested_outline.pdf",
1697+
"#viewsManagerToggleButton"
1698+
);
1699+
});
1700+
1701+
afterEach(async () => {
1702+
await closePages(pages);
1703+
});
1704+
1705+
it("should collapse all outline items on first double-click and expand them on second", async () => {
1706+
await Promise.all(
1707+
pages.map(async ([browserName, page]) => {
1708+
await showViewsManager(page);
1709+
1710+
await page.click("#viewsManagerSelectorButton");
1711+
await page.waitForSelector("#outlinesViewMenu", { visible: true });
1712+
await page.click("#outlinesViewMenu");
1713+
await page.waitForSelector("#outlinesView.withNesting");
1714+
1715+
// Initially all togglers must be expanded (none hidden).
1716+
const initialHiddenCount = await page.$$eval(
1717+
"#outlinesView .treeItemToggler",
1718+
togglers =>
1719+
togglers.filter(t => t.classList.contains("treeItemsHidden"))
1720+
.length
1721+
);
1722+
expect(initialHiddenCount).withContext(`In ${browserName}`).toBe(0);
1723+
1724+
// Double-click the title label (not on a button) to collapse all.
1725+
await page.click("#viewsManagerHeaderLabel", { count: 2 });
1726+
await page.waitForFunction(
1727+
() =>
1728+
document.querySelectorAll(
1729+
"#outlinesView .treeItemToggler:not(.treeItemsHidden)"
1730+
).length === 0
1731+
);
1732+
1733+
// Double-click again to expand all.
1734+
await page.click("#viewsManagerHeaderLabel", { count: 2 });
1735+
await page.waitForFunction(
1736+
() =>
1737+
document.querySelectorAll(
1738+
"#outlinesView .treeItemToggler.treeItemsHidden"
1739+
).length === 0
1740+
);
1741+
})
1742+
);
1743+
});
1744+
});
1745+
1746+
describe("Double-click on title resets all layer checkboxes", () => {
1747+
let pages;
1748+
1749+
beforeEach(async () => {
1750+
pages = await loadAndWait("issue17679.pdf", "#viewsManagerToggleButton");
1751+
});
1752+
1753+
afterEach(async () => {
1754+
await closePages(pages);
1755+
});
1756+
1757+
it("should restore all layer checkboxes to checked after unchecking them", async () => {
1758+
await Promise.all(
1759+
pages.map(async ([browserName, page]) => {
1760+
await showViewsManager(page);
1761+
1762+
await page.click("#viewsManagerSelectorButton");
1763+
await page.waitForSelector("#layersViewMenu", { visible: true });
1764+
await page.click("#layersViewMenu");
1765+
await page.waitForSelector("#layersView input[type='checkbox']");
1766+
1767+
// Uncheck all checkboxes.
1768+
const checkboxes = await page.$$(
1769+
"#layersView input[type='checkbox']"
1770+
);
1771+
for (const checkbox of checkboxes) {
1772+
await checkbox.click();
1773+
}
1774+
await page.waitForSelector("#layersView:not(:has(:checked))");
1775+
1776+
// Double-click the title label to reset layers to their default
1777+
// state.
1778+
await page.click("#viewsManagerHeaderLabel", { count: 2 });
1779+
1780+
await page.waitForSelector(
1781+
`#layersView:not(:has(input[type="checkbox"]:not(:checked)))`
1782+
);
1783+
})
1784+
);
1785+
});
1786+
});
16901787
});

web/views_manager.js

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,9 @@ class ViewsManager extends Sidebar {
158158

159159
ViewsManager.#l10nDescription ||= Object.freeze({
160160
pagesTitle: "pdfjs-views-manager-pages-title",
161-
outlinesTitle: "pdfjs-views-manager-outlines-title",
161+
outlinesTitle: "pdfjs-views-manager-outlines-title1",
162162
attachmentsTitle: "pdfjs-views-manager-attachments-title",
163-
layersTitle: "pdfjs-views-manager-layers-title",
163+
layersTitle: "pdfjs-views-manager-layers-title1",
164164
notificationButton: "pdfjs-toggle-views-manager-notification-button",
165165
toggleButton: "pdfjs-toggle-views-manager-button",
166166
});
@@ -424,6 +424,16 @@ class ViewsManager extends Sidebar {
424424
});
425425
}
426426

427+
this.viewsManagerHeaderLabel.addEventListener("dblclick", e => {
428+
if (this.active === SidebarView.OUTLINE) {
429+
eventBus.dispatch("toggleoutlinetree", { source: this });
430+
return;
431+
}
432+
if (this.active === SidebarView.LAYERS) {
433+
eventBus.dispatch("resetlayers", { source: this });
434+
}
435+
});
436+
427437
// Buttons for switching views.
428438
this.thumbnailButton.addEventListener("click", () => {
429439
this.switchView(SidebarView.THUMBS);
@@ -432,9 +442,6 @@ class ViewsManager extends Sidebar {
432442
this.outlineButton.addEventListener("click", () => {
433443
this.switchView(SidebarView.OUTLINE);
434444
});
435-
this.outlineButton.addEventListener("dblclick", () => {
436-
eventBus.dispatch("toggleoutlinetree", { source: this });
437-
});
438445

439446
this.attachmentsButton.addEventListener("click", () => {
440447
this.switchView(SidebarView.ATTACHMENTS);
@@ -443,9 +450,6 @@ class ViewsManager extends Sidebar {
443450
this.layersButton.addEventListener("click", () => {
444451
this.switchView(SidebarView.LAYERS);
445452
});
446-
this.layersButton.addEventListener("dblclick", () => {
447-
eventBus.dispatch("resetlayers", { source: this });
448-
});
449453

450454
// Buttons for view-specific options.
451455
this.viewsManagerCurrentOutlineButton.addEventListener("click", () => {

0 commit comments

Comments
 (0)