Extract common methods from PDFOutlineViewer/PDFAttachmentViewer into a new abstract BaseTreeViewer class
				
					
				
			These two classes are unsurprisingly quite similar, and with upcoming changes[1] the amount of (essentially) duplicated code will increase even further. Notable changes: - Collect shared functionality in the `BaseTreeViewer` class, reducing both current and future code-duplication. - Reduce unnecessary duplication in the CSS rules, which will be particularly useful with upcoming changes. - Tweak the attachmentsView to use links, rather than buttons, to simplify (primarily) the CSS rules. --- [1] Once API support for "Optional Content" lands, I've got more-or-less finished patches to add viewer support as well.
This commit is contained in:
		
							parent
							
								
									a289eb8325
								
							
						
					
					
						commit
						6e9da55a39
					
				
							
								
								
									
										111
									
								
								web/base_tree_viewer.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								web/base_tree_viewer.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,111 @@ | ||||
| /* Copyright 2020 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. | ||||
|  */ | ||||
| 
 | ||||
| import { removeNullCharacters } from "pdfjs-lib"; | ||||
| 
 | ||||
| class BaseTreeViewer { | ||||
|   constructor(options) { | ||||
|     if (this.constructor === BaseTreeViewer) { | ||||
|       throw new Error("Cannot initialize BaseTreeViewer."); | ||||
|     } | ||||
|     this.container = options.container; | ||||
|     this.eventBus = options.eventBus; | ||||
| 
 | ||||
|     this.reset(); | ||||
|   } | ||||
| 
 | ||||
|   reset() { | ||||
|     this._lastToggleIsShow = true; | ||||
| 
 | ||||
|     // Remove the tree from the DOM.
 | ||||
|     this.container.textContent = ""; | ||||
|     // 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"); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * @private | ||||
|    */ | ||||
|   _dispatchEvent(count) { | ||||
|     throw new Error("Not implemented: _dispatchEvent"); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * @private | ||||
|    */ | ||||
|   _bindLink(element, params) { | ||||
|     throw new Error("Not implemented: _bindLink"); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * @private | ||||
|    */ | ||||
|   _normalizeTextContent(str) { | ||||
|     return removeNullCharacters(str) || /* en dash = */ "\u2013"; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Prepend a button before a tree item which allows the user to collapse or | ||||
|    * expand all tree items at that level; see `_toggleTreeItem`. | ||||
|    * @private | ||||
|    */ | ||||
|   _addToggleButton(div, hidden = false) { | ||||
|     const toggler = document.createElement("div"); | ||||
|     toggler.className = "treeItemToggler"; | ||||
|     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.insertBefore(toggler, div.firstChild); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Collapse or expand the subtree of a tree item. | ||||
|    * | ||||
|    * @param {Element} root - the root of the item (sub)tree. | ||||
|    * @param {boolean} show - whether to show the item (sub)tree. If false, | ||||
|    *   the item subtree rooted at `root` will be collapsed. | ||||
|    * @private | ||||
|    */ | ||||
|   _toggleTreeItem(root, show = false) { | ||||
|     this._lastToggleIsShow = show; | ||||
|     for (const toggler of root.querySelectorAll(".treeItemToggler")) { | ||||
|       toggler.classList.toggle("treeItemsHidden", !show); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Collapse or expand all subtrees of the `container`. | ||||
|    * @private | ||||
|    */ | ||||
|   _toggleAllTreeItems() { | ||||
|     this._toggleTreeItem(this.container, !this._lastToggleIsShow); | ||||
|   } | ||||
| 
 | ||||
|   render(params) { | ||||
|     throw new Error("Not implemented: render"); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export { BaseTreeViewer }; | ||||
| @ -13,11 +13,8 @@ | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| import { | ||||
|   createPromiseCapability, | ||||
|   getFilenameFromUrl, | ||||
|   removeNullCharacters, | ||||
| } from "pdfjs-lib"; | ||||
| import { createPromiseCapability, getFilenameFromUrl } from "pdfjs-lib"; | ||||
| import { BaseTreeViewer } from "./base_tree_viewer.js"; | ||||
| 
 | ||||
| /** | ||||
|  * @typedef {Object} PDFAttachmentViewerOptions | ||||
| @ -31,16 +28,13 @@ import { | ||||
|  * @property {Object|null} attachments - A lookup table of attachment objects. | ||||
|  */ | ||||
| 
 | ||||
| class PDFAttachmentViewer { | ||||
| class PDFAttachmentViewer extends BaseTreeViewer { | ||||
|   /** | ||||
|    * @param {PDFAttachmentViewerOptions} options | ||||
|    */ | ||||
|   constructor({ container, eventBus, downloadManager }) { | ||||
|     this.container = container; | ||||
|     this.eventBus = eventBus; | ||||
|     this.downloadManager = downloadManager; | ||||
| 
 | ||||
|     this.reset(); | ||||
|   constructor(options) { | ||||
|     super(options); | ||||
|     this.downloadManager = options.downloadManager; | ||||
| 
 | ||||
|     this.eventBus._on( | ||||
|       "fileattachmentannotation", | ||||
| @ -49,10 +43,8 @@ class PDFAttachmentViewer { | ||||
|   } | ||||
| 
 | ||||
|   reset(keepRenderedCapability = false) { | ||||
|     this.attachments = null; | ||||
| 
 | ||||
|     // Remove the attachments from the DOM.
 | ||||
|     this.container.textContent = ""; | ||||
|     super.reset(); | ||||
|     this._attachments = null; | ||||
| 
 | ||||
|     if (!keepRenderedCapability) { | ||||
|       // The only situation in which the `_renderedCapability` should *not* be
 | ||||
| @ -100,9 +92,9 @@ class PDFAttachmentViewer { | ||||
|    * NOTE: Should only be used when `URL.createObjectURL` is natively supported. | ||||
|    * @private | ||||
|    */ | ||||
|   _bindPdfLink(button, content, filename) { | ||||
|   _bindPdfLink(element, { content, filename }) { | ||||
|     let blobUrl; | ||||
|     button.onclick = () => { | ||||
|     element.onclick = () => { | ||||
|       if (!blobUrl) { | ||||
|         blobUrl = URL.createObjectURL( | ||||
|           new Blob([content], { type: "application/pdf" }) | ||||
| @ -141,8 +133,8 @@ class PDFAttachmentViewer { | ||||
|   /** | ||||
|    * @private | ||||
|    */ | ||||
|   _bindLink(button, content, filename) { | ||||
|     button.onclick = () => { | ||||
|   _bindLink(element, { content, filename }) { | ||||
|     element.onclick = () => { | ||||
|       this.downloadManager.downloadData(content, filename, ""); | ||||
|       return false; | ||||
|     }; | ||||
| @ -152,42 +144,45 @@ class PDFAttachmentViewer { | ||||
|    * @param {PDFAttachmentViewerRenderParameters} params | ||||
|    */ | ||||
|   render({ attachments, keepRenderedCapability = false }) { | ||||
|     if (this.attachments) { | ||||
|       this.reset(keepRenderedCapability === true); | ||||
|     if (this._attachments) { | ||||
|       this.reset(keepRenderedCapability); | ||||
|     } | ||||
|     this.attachments = attachments || null; | ||||
|     this._attachments = attachments || null; | ||||
| 
 | ||||
|     if (!attachments) { | ||||
|       this._dispatchEvent(/* attachmentsCount = */ 0); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     const names = Object.keys(attachments).sort(function (a, b) { | ||||
|       return a.toLowerCase().localeCompare(b.toLowerCase()); | ||||
|     }); | ||||
|     const attachmentsCount = names.length; | ||||
| 
 | ||||
|     const fragment = document.createDocumentFragment(); | ||||
|     for (let i = 0; i < attachmentsCount; i++) { | ||||
|       const item = attachments[names[i]]; | ||||
|       const filename = removeNullCharacters(getFilenameFromUrl(item.filename)); | ||||
|     let attachmentsCount = 0; | ||||
|     for (const name of names) { | ||||
|       const item = attachments[name]; | ||||
|       const filename = getFilenameFromUrl(item.filename); | ||||
| 
 | ||||
|       const div = document.createElement("div"); | ||||
|       div.className = "attachmentsItem"; | ||||
|       const button = document.createElement("button"); | ||||
|       button.textContent = filename; | ||||
|       div.className = "treeItem"; | ||||
| 
 | ||||
|       const element = document.createElement("a"); | ||||
|       if ( | ||||
|         /\.pdf$/i.test(filename) && | ||||
|         !this.downloadManager.disableCreateObjectURL | ||||
|       ) { | ||||
|         this._bindPdfLink(button, item.content, filename); | ||||
|         this._bindPdfLink(element, { content: item.content, filename }); | ||||
|       } else { | ||||
|         this._bindLink(button, item.content, filename); | ||||
|         this._bindLink(element, { content: item.content, filename }); | ||||
|       } | ||||
|       element.textContent = this._normalizeTextContent(filename); | ||||
| 
 | ||||
|       div.appendChild(element); | ||||
| 
 | ||||
|       div.appendChild(button); | ||||
|       fragment.appendChild(div); | ||||
|       attachmentsCount++; | ||||
|     } | ||||
| 
 | ||||
|     this.container.appendChild(fragment); | ||||
| 
 | ||||
|     this._dispatchEvent(attachmentsCount); | ||||
| @ -204,7 +199,7 @@ class PDFAttachmentViewer { | ||||
|       if (renderedPromise !== this._renderedCapability.promise) { | ||||
|         return; // The FileAttachment annotation belongs to a previous document.
 | ||||
|       } | ||||
|       let attachments = this.attachments; | ||||
|       let attachments = this._attachments; | ||||
| 
 | ||||
|       if (!attachments) { | ||||
|         attachments = Object.create(null); | ||||
|  | ||||
| @ -13,9 +13,8 @@ | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| import { addLinkAttributes, LinkTarget, removeNullCharacters } from "pdfjs-lib"; | ||||
| 
 | ||||
| const DEFAULT_TITLE = "\u2013"; | ||||
| import { addLinkAttributes, LinkTarget } from "pdfjs-lib"; | ||||
| import { BaseTreeViewer } from "./base_tree_viewer.js"; | ||||
| 
 | ||||
| /** | ||||
|  * @typedef {Object} PDFOutlineViewerOptions | ||||
| @ -29,30 +28,20 @@ const DEFAULT_TITLE = "\u2013"; | ||||
|  * @property {Array|null} outline - An array of outline objects. | ||||
|  */ | ||||
| 
 | ||||
| class PDFOutlineViewer { | ||||
| class PDFOutlineViewer extends BaseTreeViewer { | ||||
|   /** | ||||
|    * @param {PDFOutlineViewerOptions} options | ||||
|    */ | ||||
|   constructor({ container, linkService, eventBus }) { | ||||
|     this.container = container; | ||||
|     this.linkService = linkService; | ||||
|     this.eventBus = eventBus; | ||||
|   constructor(options) { | ||||
|     super(options); | ||||
|     this.linkService = options.linkService; | ||||
| 
 | ||||
|     this.reset(); | ||||
| 
 | ||||
|     eventBus._on("toggleoutlinetree", this.toggleOutlineTree.bind(this)); | ||||
|     this.eventBus._on("toggleoutlinetree", this._toggleAllTreeItems.bind(this)); | ||||
|   } | ||||
| 
 | ||||
|   reset() { | ||||
|     this.outline = null; | ||||
|     this.lastToggleIsShow = true; | ||||
| 
 | ||||
|     // Remove the outline from the DOM.
 | ||||
|     this.container.textContent = ""; | ||||
| 
 | ||||
|     // Ensure that the left (right in RTL locales) margin is always reset,
 | ||||
|     // to prevent incorrect outline alignment if a new document is opened.
 | ||||
|     this.container.classList.remove("outlineWithDeepNesting"); | ||||
|     super.reset(); | ||||
|     this._outline = null; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
| @ -103,84 +92,51 @@ class PDFOutlineViewer { | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Prepend a button before an outline item which allows the user to toggle | ||||
|    * the visibility of all outline items at that level. | ||||
|    * | ||||
|    * @private | ||||
|    */ | ||||
|   _addToggleButton(div, { count, items }) { | ||||
|     const toggler = document.createElement("div"); | ||||
|     toggler.className = "outlineItemToggler"; | ||||
|     if (count < 0 && Math.abs(count) === items.length) { | ||||
|       toggler.classList.add("outlineItemsHidden"); | ||||
|     } | ||||
|     toggler.onclick = evt => { | ||||
|       evt.stopPropagation(); | ||||
|       toggler.classList.toggle("outlineItemsHidden"); | ||||
| 
 | ||||
|       if (evt.shiftKey) { | ||||
|         const shouldShowAll = !toggler.classList.contains("outlineItemsHidden"); | ||||
|         this._toggleOutlineItem(div, shouldShowAll); | ||||
|       } | ||||
|     }; | ||||
|     div.insertBefore(toggler, div.firstChild); | ||||
|     const hidden = count < 0 && Math.abs(count) === items.length; | ||||
|     super._addToggleButton(div, hidden); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Toggle the visibility of the subtree of an outline item. | ||||
|    * | ||||
|    * @param {Element} root - the root of the outline (sub)tree. | ||||
|    * @param {boolean} show - whether to show the outline (sub)tree. If false, | ||||
|    *   the outline subtree rooted at |root| will be collapsed. | ||||
|    * | ||||
|    * @private | ||||
|    */ | ||||
|   _toggleOutlineItem(root, show = false) { | ||||
|     this.lastToggleIsShow = show; | ||||
|     for (const toggler of root.querySelectorAll(".outlineItemToggler")) { | ||||
|       toggler.classList.toggle("outlineItemsHidden", !show); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Collapse or expand all subtrees of the outline. | ||||
|    */ | ||||
|   toggleOutlineTree() { | ||||
|     if (!this.outline) { | ||||
|   _toggleAllTreeItems() { | ||||
|     if (!this._outline) { | ||||
|       return; | ||||
|     } | ||||
|     this._toggleOutlineItem(this.container, !this.lastToggleIsShow); | ||||
|     super._toggleAllTreeItems(); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * @param {PDFOutlineViewerRenderParameters} params | ||||
|    */ | ||||
|   render({ outline }) { | ||||
|     let outlineCount = 0; | ||||
| 
 | ||||
|     if (this.outline) { | ||||
|     if (this._outline) { | ||||
|       this.reset(); | ||||
|     } | ||||
|     this.outline = outline || null; | ||||
|     this._outline = outline || null; | ||||
| 
 | ||||
|     if (!outline) { | ||||
|       this._dispatchEvent(outlineCount); | ||||
|       this._dispatchEvent(/* outlineCount = */ 0); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     const fragment = document.createDocumentFragment(); | ||||
|     const queue = [{ parent: fragment, items: this.outline }]; | ||||
|     let hasAnyNesting = false; | ||||
|     const queue = [{ parent: fragment, items: outline }]; | ||||
|     let outlineCount = 0, | ||||
|       hasAnyNesting = false; | ||||
|     while (queue.length > 0) { | ||||
|       const levelData = queue.shift(); | ||||
|       for (const item of levelData.items) { | ||||
|         const div = document.createElement("div"); | ||||
|         div.className = "outlineItem"; | ||||
|         div.className = "treeItem"; | ||||
| 
 | ||||
|         const element = document.createElement("a"); | ||||
|         this._bindLink(element, item); | ||||
|         this._setStyles(element, item); | ||||
|         element.textContent = removeNullCharacters(item.title) || DEFAULT_TITLE; | ||||
|         element.textContent = this._normalizeTextContent(item.title); | ||||
| 
 | ||||
|         div.appendChild(element); | ||||
| 
 | ||||
| @ -189,8 +145,9 @@ class PDFOutlineViewer { | ||||
|           this._addToggleButton(div, item); | ||||
| 
 | ||||
|           const itemsDiv = document.createElement("div"); | ||||
|           itemsDiv.className = "outlineItems"; | ||||
|           itemsDiv.className = "treeItems"; | ||||
|           div.appendChild(itemsDiv); | ||||
| 
 | ||||
|           queue.push({ parent: itemsDiv, items: item.items }); | ||||
|         } | ||||
| 
 | ||||
| @ -199,10 +156,10 @@ class PDFOutlineViewer { | ||||
|       } | ||||
|     } | ||||
|     if (hasAnyNesting) { | ||||
|       this.container.classList.add("outlineWithDeepNesting"); | ||||
|       this.container.classList.add("treeWithDeepNesting"); | ||||
| 
 | ||||
|       this.lastToggleIsShow = | ||||
|         fragment.querySelectorAll(".outlineItemsHidden").length === 0; | ||||
|       this._lastToggleIsShow = | ||||
|         fragment.querySelectorAll(".treeItemsHidden").length === 0; | ||||
|     } | ||||
| 
 | ||||
|     this.container.appendChild(fragment); | ||||
|  | ||||
| @ -1169,30 +1169,23 @@ a:focus > .thumbnail > .thumbnailSelectionRing, | ||||
|   width: calc(100% - 8px); | ||||
|   top: 0; | ||||
|   bottom: 0; | ||||
|   padding: 4px 4px 0; | ||||
|   overflow: auto; | ||||
|   -webkit-overflow-scrolling: touch; | ||||
|   user-select: none; | ||||
| } | ||||
| 
 | ||||
| #outlineView { | ||||
|   padding: 4px 4px 0; | ||||
| } | ||||
| #attachmentsView { | ||||
|   padding: 3px 4px 0; | ||||
| } | ||||
| 
 | ||||
| html[dir='ltr'] .outlineWithDeepNesting > .outlineItem, | ||||
| html[dir='ltr'] .outlineItem > .outlineItems { | ||||
| html[dir='ltr'] .treeWithDeepNesting > .treeItem, | ||||
| html[dir='ltr'] .treeItem > .treeItems { | ||||
|   margin-left: 20px; | ||||
| } | ||||
| 
 | ||||
| html[dir='rtl'] .outlineWithDeepNesting > .outlineItem, | ||||
| html[dir='rtl'] .outlineItem > .outlineItems { | ||||
| html[dir='rtl'] .treeWithDeepNesting > .treeItem, | ||||
| html[dir='rtl'] .treeItem > .treeItems { | ||||
|   margin-right: 20px; | ||||
| } | ||||
| 
 | ||||
| .outlineItem > a, | ||||
| .attachmentsItem > button { | ||||
| .treeItem > a { | ||||
|   text-decoration: none; | ||||
|   display: inline-block; | ||||
|   min-width: 95%; | ||||
| @ -1206,69 +1199,52 @@ html[dir='rtl'] .outlineItem > .outlineItems { | ||||
|   line-height: 15px; | ||||
|   user-select: none; | ||||
|   white-space: normal; | ||||
| } | ||||
| 
 | ||||
| .attachmentsItem > button { | ||||
|   border: 0 none; | ||||
|   background: none; | ||||
|   cursor: pointer; | ||||
|   width: 100%; | ||||
| } | ||||
| 
 | ||||
| html[dir='ltr'] .outlineItem > a { | ||||
| html[dir='ltr'] .treeItem > a { | ||||
|   padding: 2px 0 5px 4px; | ||||
| } | ||||
| html[dir='ltr'] .attachmentsItem > button { | ||||
|   padding: 2px 0 3px 7px; | ||||
|   text-align: left; | ||||
| } | ||||
| 
 | ||||
| html[dir='rtl'] .outlineItem > a { | ||||
| html[dir='rtl'] .treeItem > a { | ||||
|   padding: 2px 4px 5px 0; | ||||
| } | ||||
| html[dir='rtl'] .attachmentsItem > button { | ||||
|   padding: 2px 7px 3px 0; | ||||
|   text-align: right; | ||||
| } | ||||
| 
 | ||||
| .outlineItemToggler { | ||||
| .treeItemToggler { | ||||
|   position: relative; | ||||
|   height: 0; | ||||
|   width: 0; | ||||
|   color: rgba(255, 255, 255, 0.5); | ||||
| } | ||||
| .outlineItemToggler::before { | ||||
| .treeItemToggler::before { | ||||
|   content: url(images/treeitem-expanded.png); | ||||
|   display: inline-block; | ||||
|   position: absolute; | ||||
| } | ||||
| .outlineItemToggler.outlineItemsHidden::before { | ||||
| .treeItemToggler.treeItemsHidden::before { | ||||
|   content: url(images/treeitem-collapsed.png); | ||||
| } | ||||
| html[dir='rtl'] .outlineItemToggler.outlineItemsHidden::before { | ||||
| html[dir='rtl'] .treeItemToggler.treeItemsHidden::before { | ||||
|   transform: scaleX(-1); | ||||
| } | ||||
| .outlineItemToggler.outlineItemsHidden ~ .outlineItems { | ||||
| .treeItemToggler.treeItemsHidden ~ .treeItems { | ||||
|   display: none; | ||||
| } | ||||
| html[dir='ltr'] .outlineItemToggler { | ||||
| html[dir='ltr'] .treeItemToggler { | ||||
|   float: left; | ||||
| } | ||||
| html[dir='rtl'] .outlineItemToggler { | ||||
| html[dir='rtl'] .treeItemToggler { | ||||
|   float: right; | ||||
| } | ||||
| html[dir='ltr'] .outlineItemToggler::before { | ||||
| html[dir='ltr'] .treeItemToggler::before { | ||||
|   right: 4px; | ||||
| } | ||||
| html[dir='rtl'] .outlineItemToggler::before { | ||||
| html[dir='rtl'] .treeItemToggler::before { | ||||
|   left: 4px; | ||||
| } | ||||
| 
 | ||||
| .outlineItemToggler:hover, | ||||
| .outlineItemToggler:hover + a, | ||||
| .outlineItemToggler:hover ~ .outlineItems, | ||||
| .outlineItem > a:hover, | ||||
| .attachmentsItem > button:hover { | ||||
| .treeItemToggler:hover, | ||||
| .treeItemToggler:hover + a, | ||||
| .treeItemToggler:hover ~ .treeItems, | ||||
| .treeItem > a:hover { | ||||
|   background-color: rgba(255, 255, 255, 0.02); | ||||
|   background-image: linear-gradient(rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0)); | ||||
|   background-clip: padding-box; | ||||
| @ -1279,7 +1255,7 @@ html[dir='rtl'] .outlineItemToggler::before { | ||||
|   color: rgba(255, 255, 255, 0.9); | ||||
| } | ||||
| 
 | ||||
| .outlineItem.selected { | ||||
| .treeItem.selected { | ||||
|   background-color: rgba(255, 255, 255, 0.08); | ||||
|   background-image: linear-gradient(rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0)); | ||||
|   background-clip: padding-box; | ||||
| @ -1745,21 +1721,21 @@ html[dir='rtl'] #documentPropertiesOverlay .row > * { | ||||
|     content: url(images/secondaryToolbarButton-documentProperties@2x.png); | ||||
|   } | ||||
| 
 | ||||
|   .outlineItemToggler::before { | ||||
|   .treeItemToggler::before { | ||||
|     transform: scale(0.5); | ||||
|     top: -1px; | ||||
|     content: url(images/treeitem-expanded@2x.png); | ||||
|   } | ||||
|   .outlineItemToggler.outlineItemsHidden::before { | ||||
|   .treeItemToggler.treeItemsHidden::before { | ||||
|     content: url(images/treeitem-collapsed@2x.png); | ||||
|   } | ||||
|   html[dir='rtl'] .outlineItemToggler.outlineItemsHidden::before { | ||||
|   html[dir='rtl'] .treeItemToggler.treeItemsHidden::before { | ||||
|     transform: scale(-0.5, 0.5); | ||||
|   } | ||||
|   html[dir='ltr'] .outlineItemToggler::before { | ||||
|   html[dir='ltr'] .treeItemToggler::before { | ||||
|     right: 0; | ||||
|   } | ||||
|   html[dir='rtl'] .outlineItemToggler::before { | ||||
|   html[dir='rtl'] .treeItemToggler::before { | ||||
|     left: 0; | ||||
|   } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user