Allow outline to be collapsed / shown via icon.

- This commit adds a '>' before every outline item that has subitems.
- Click on the '>' to collapse all subitems under that item (which turns
  the '>' in a 'v').
- Shift + click expands/collapses all descendant items under that tree.
- Double-clicking on the "Show Document Outline" button in the toolbar
  expands/collapses all outline items.
This commit is contained in:
Rob Wu 2015-07-21 19:52:49 +02:00
parent 862342189f
commit 7c992243fd
7 changed files with 100 additions and 3 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

View File

@ -36,6 +36,7 @@ var PDFOutlineView = (function PDFOutlineViewClosure() {
this.container = options.container;
this.outline = options.outline;
this.linkService = options.linkService;
this.lastToggleIsShow = true;
}
PDFOutlineView.prototype = {
@ -44,6 +45,7 @@ var PDFOutlineView = (function PDFOutlineViewClosure() {
while (container.firstChild) {
container.removeChild(container.firstChild);
}
this.lastToggleIsShow = true;
},
/**
@ -69,6 +71,51 @@ var PDFOutlineView = (function PDFOutlineViewClosure() {
};
},
/**
* Prepend a button before an outline item which allows the user to toggle
* the visibility of all outline items at that level.
*
* @private
*/
_addToggleButton: function PDFOutlineView_addToggleButton(div) {
var toggler = document.createElement('div');
toggler.className = 'outlineItemToggler';
toggler.onclick = function(event) {
event.stopPropagation();
toggler.classList.toggle('outlineItemsHidden');
if (event.shiftKey) {
var shouldShowAll = !toggler.classList.contains('outlineItemsHidden');
this._toggleOutlineItem(div, shouldShowAll);
}
}.bind(this);
div.insertBefore(toggler, div.firstChild);
},
/**
* Toggle the visibility of the subtree of an outline item.
*
* @param {Element} root - the root of the outline (sub)tree.
* @param {boolean} state - whether to show the outline (sub)tree. If false,
* the outline subtree rooted at |root| will be collapsed.
*
* @private
*/
_toggleOutlineItem: function PDFOutlineView_toggleOutlineItem(root, show) {
this.lastToggleIsShow = show;
var togglers = root.querySelectorAll('.outlineItemToggler');
for (var i = 0, ii = togglers.length; i < ii; ++i) {
togglers[i].classList[show ? 'remove' : 'add']('outlineItemsHidden');
}
},
/**
* Collapse or expand all subtrees of the outline.
*/
toggleOutlineTree: function PDFOutlineView_toggleOutlineTree() {
this._toggleOutlineItem(this.container, !this.lastToggleIsShow);
},
render: function PDFOutlineView_render() {
var outline = this.outline;
var outlineCount = 0;
@ -80,7 +127,9 @@ var PDFOutlineView = (function PDFOutlineViewClosure() {
return;
}
var queue = [{ parent: this.container, items: this.outline }];
var fragment = document.createDocumentFragment();
var queue = [{ parent: fragment, items: this.outline }];
var hasAnyNesting = false;
while (queue.length > 0) {
var levelData = queue.shift();
for (var i = 0, len = levelData.items.length; i < len; i++) {
@ -93,6 +142,9 @@ var PDFOutlineView = (function PDFOutlineViewClosure() {
div.appendChild(element);
if (item.items.length > 0) {
hasAnyNesting = true;
this._addToggleButton(div);
var itemsDiv = document.createElement('div');
itemsDiv.className = 'outlineItems';
div.appendChild(itemsDiv);
@ -103,6 +155,11 @@ var PDFOutlineView = (function PDFOutlineViewClosure() {
outlineCount++;
}
}
if (hasAnyNesting) {
this.container.classList.add('outlineWithDeepNesting');
}
this.container.appendChild(fragment);
this._dispatchEvent(outlineCount);
}

View File

@ -1190,10 +1190,12 @@ a:focus > .thumbnail > .thumbnailSelectionRing,
padding: 3px 4px 0;
}
html[dir='ltr'] .outlineWithDeepNesting > .outlineItem,
html[dir='ltr'] .outlineItem > .outlineItems {
margin-left: 20px;
}
html[dir='rtl'] .outlineWithDeepNesting > .outlineItem,
html[dir='rtl'] .outlineItem > .outlineItems {
margin-right: 20px;
}
@ -1221,7 +1223,7 @@ html[dir='rtl'] .outlineItem > .outlineItems {
}
html[dir='ltr'] .outlineItem > a {
padding: 2px 0 5px 10px;
padding: 2px 0 5px 4px;
}
html[dir='ltr'] .attachmentsItem > button {
padding: 2px 0 3px 7px;
@ -1229,13 +1231,46 @@ html[dir='ltr'] .attachmentsItem > button {
}
html[dir='rtl'] .outlineItem > a {
padding: 2px 10px 5px 0;
padding: 2px 4px 5px 0;
}
html[dir='rtl'] .attachmentsItem > button {
padding: 2px 7px 3px 0;
text-align: right;
}
.outlineItemToggler {
position: relative;
height: 0;
width: 0;
color: hsla(0,0%,100%,.5);
}
.outlineItemToggler::before {
content: url(images/treeitem-collapsed.png);
display: inline-block;
position: absolute;
}
.outlineItemToggler.outlineItemsHidden::before {
content: url(images/treeitem-expanded.png);
}
.outlineItemToggler.outlineItemsHidden ~ .outlineItems {
display: none;
}
html[dir='ltr'] .outlineItemToggler {
float: left;
}
html[dir='rtl'] .outlineItemToggler {
float: right;
}
html[dir='ltr'] .outlineItemToggler::before {
right: 4px;
}
html[dir='rtl'] .outlineItemToggler::before {
left: 4px;
}
.outlineItemToggler:hover,
.outlineItemToggler:hover + a,
.outlineItemToggler:hover ~ .outlineItems,
.outlineItem > a:hover,
.attachmentsItem > button:hover {
background-color: hsla(0,0%,100%,.02);

View File

@ -1401,6 +1401,11 @@ function webViewerInitialized() {
PDFViewerApplication.switchSidebarView('outline');
});
document.getElementById('viewOutline').addEventListener('dblclick',
function() {
PDFViewerApplication.outline.toggleOutlineTree();
});
document.getElementById('viewAttachments').addEventListener('click',
function() {
PDFViewerApplication.switchSidebarView('attachments');