diff --git a/web/base_tree_viewer.js b/web/base_tree_viewer.js index a3ef2c21d..882d386a2 100644 --- a/web/base_tree_viewer.js +++ b/web/base_tree_viewer.js @@ -14,6 +14,7 @@ */ import { removeNullCharacters } from "./ui_utils.js"; +import { stopEvent } from "pdfjs-lib"; const TREEITEM_OFFSET_TOP = -100; // px const TREEITEM_SELECTED_CLASS = "selected"; @@ -39,10 +40,10 @@ class BaseTreeViewer { this._currentTreeItem = null; // Remove the tree from the DOM. - this.container.textContent = ""; + this.container.replaceChildren(); // Ensure that the left (right in RTL locales) margin is always reset, // to prevent incorrect tree alignment if a new document is opened. - this.container.classList.remove("treeWithDeepNesting"); + this.container.classList.remove("withNesting"); } /** @@ -84,15 +85,6 @@ class BaseTreeViewer { if (hidden) { toggler.classList.add("treeItemsHidden"); } - toggler.onclick = evt => { - evt.stopPropagation(); - toggler.classList.toggle("treeItemsHidden"); - - if (evt.shiftKey) { - const shouldShowAll = !toggler.classList.contains("treeItemsHidden"); - this._toggleTreeItem(div, shouldShowAll); - } - }; div.prepend(toggler); } @@ -128,9 +120,20 @@ class BaseTreeViewer { */ _finishRendering(fragment, count, hasAnyNesting = false) { if (hasAnyNesting) { - this.container.classList.add("treeWithDeepNesting"); - + this.container.classList.add("withNesting"); this._lastToggleIsShow = !fragment.querySelector(".treeItemsHidden"); + this.container.addEventListener("click", e => { + const { target } = e; + if (!target.classList.contains("treeItemToggler")) { + return; + } + stopEvent(e); + target.classList.toggle("treeItemsHidden"); + if (e.shiftKey) { + const shouldShowAll = !target.classList.contains("treeItemsHidden"); + this._toggleTreeItem(this.container, shouldShowAll); + } + }); } // Pause translation when inserting the tree into the DOM. this._l10n.pause(); diff --git a/web/pdf_layer_viewer.js b/web/pdf_layer_viewer.js index c5759a6b9..e8290b4c0 100644 --- a/web/pdf_layer_viewer.js +++ b/web/pdf_layer_viewer.js @@ -171,8 +171,12 @@ class PDFLayerViewer extends BaseTreeViewer { queue.push({ parent: itemsDiv, groups: groupId.order }); } else { const group = optionalContentConfig.getGroup(groupId); - + const label = document.createElement("label"); const input = document.createElement("input"); + label.append( + input, + document.createTextNode(this._normalizeTextContent(group.name)) + ); this._bindLink(element, { groupId, input }); input.type = "checkbox"; input.checked = group.visible; @@ -182,10 +186,6 @@ class PDFLayerViewer extends BaseTreeViewer { visible: input.checked, }); - const label = document.createElement("label"); - label.textContent = this._normalizeTextContent(group.name); - - label.append(input); element.append(label); layersCount++; } diff --git a/web/tree.css b/web/tree.css index 5c6804326..2dd628dc4 100644 --- a/web/tree.css +++ b/web/tree.css @@ -13,7 +13,7 @@ * limitations under the License. */ -.treeWithDeepNesting { +.treeView { --treeitem-color: light-dark(rgb(0 0 0 / 0.8), rgb(255 255 255 / 0.8)); --treeitem-bg-color: light-dark(rgb(0 0 0 / 0.15), rgb(255 255 255 / 0.15)); --treeitem-hover-color: light-dark(rgb(0 0 0 / 0.9), rgb(255 255 255 / 0.9)); @@ -28,17 +28,53 @@ --treeitem-expanded-icon: url(images/treeitem-expanded.svg); --treeitem-collapsed-icon: url(images/treeitem-collapsed.svg); - .treeItemToggler::before { - /* All matching images have a size of 16x16 - * All relevant containers have a size of 28x28 */ - position: absolute; - display: inline-block; - width: 16px; - height: 16px; + &.withNesting { + .treeItemToggler { + &::before { + /* All matching images have a size of 16x16 + * All relevant containers have a size of 28x28 */ + position: absolute; + display: inline-block; + width: 16px; + height: 16px; + inset-inline-end: 4px; - content: ""; - background-color: var(--toolbar-icon-bg-color); - mask-size: cover; + content: ""; + background-color: var(--toolbar-icon-bg-color); + mask-image: var(--treeitem-expanded-icon); + mask-size: cover; + } + + position: relative; + float: var(--inline-start); + height: 0; + width: 0; + color: rgb(255 255 255 / 0.5); + + &.treeItemsHidden { + &::before { + mask-image: var(--treeitem-collapsed-icon); + transform: scaleX(var(--dir-factor)); + } + + ~ .treeItems { + display: none; + } + } + + &:hover + a, + &:hover ~ .treeItems { + background-color: var(--treeitem-bg-color); + background-clip: padding-box; + border-radius: 2px; + color: var(--treeitem-hover-color); + } + } + + > .treeItem, + .treeItem > .treeItems { + margin-inline-start: 20px; + } } &#layersView .treeItem > a { @@ -47,19 +83,15 @@ } > label { + display: flex; + align-items: center; padding-inline-start: 4px; > input { - float: var(--inline-start); margin-top: 1px; } } } - > .treeItem, - .treeItem > .treeItems { - margin-inline-start: 20px; - } - .treeItem { > a { text-decoration: none; @@ -76,7 +108,7 @@ line-height: 15px; user-select: none; white-space: normal; - cursor: pointer; + cursor: default; &:hover { background-color: var(--treeitem-bg-color); @@ -91,35 +123,4 @@ color: var(--treeitem-selected-color); } } - - .treeItemToggler { - position: relative; - float: var(--inline-start); - height: 0; - width: 0; - color: rgb(255 255 255 / 0.5); - - &::before { - inset-inline-end: 4px; - mask-image: var(--treeitem-expanded-icon); - } - - &.treeItemsHidden { - &::before { - mask-image: var(--treeitem-collapsed-icon); - transform: scaleX(var(--dir-factor)); - } - - ~ .treeItems { - display: none; - } - } - - &:hover:is(+ a, ~ .treeItems) { - background-color: var(--treeitem-bg-color); - background-clip: padding-box; - border-radius: 2px; - color: var(--treeitem-hover-color); - } - } } diff --git a/web/viewer.html b/web/viewer.html index e373314df..164767607 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -175,9 +175,9 @@ See https://github.com/adobe-type-tools/cmap-resources
- + - +