2015-11-20 09:21:46 -05:00
|
|
|
/* global anchors */
|
|
|
|
|
|
|
|
// add anchor links to headers
|
|
|
|
anchors.options.placement = 'left';
|
2016-07-20 16:33:09 -04:00
|
|
|
anchors.add('h3');
|
2015-11-20 09:21:46 -05:00
|
|
|
|
|
|
|
// Filter UI
|
2018-02-12 14:58:50 -05:00
|
|
|
var tocElements = document.getElementById('toc').getElementsByTagName('li');
|
2016-07-20 16:33:09 -04:00
|
|
|
|
2018-02-12 14:58:50 -05:00
|
|
|
document.getElementById('filter-input').addEventListener('keyup', function(e) {
|
|
|
|
var i, element, children;
|
2015-11-20 09:21:46 -05:00
|
|
|
|
2018-02-12 14:58:50 -05:00
|
|
|
// enter key
|
|
|
|
if (e.keyCode === 13) {
|
|
|
|
// go to the first displayed item in the toc
|
2015-11-20 09:21:46 -05:00
|
|
|
for (i = 0; i < tocElements.length; i++) {
|
|
|
|
element = tocElements[i];
|
2018-02-12 14:58:50 -05:00
|
|
|
if (!element.classList.contains('display-none')) {
|
|
|
|
location.replace(element.firstChild.href);
|
|
|
|
return e.preventDefault();
|
2015-11-20 09:21:46 -05:00
|
|
|
}
|
|
|
|
}
|
2018-02-12 14:58:50 -05:00
|
|
|
}
|
2016-07-20 16:33:09 -04:00
|
|
|
|
2018-02-12 14:58:50 -05:00
|
|
|
var match = function() {
|
|
|
|
return true;
|
|
|
|
};
|
2016-07-20 16:33:09 -04:00
|
|
|
|
2018-02-12 14:58:50 -05:00
|
|
|
var value = this.value.toLowerCase();
|
|
|
|
|
|
|
|
if (!value.match(/^\s*$/)) {
|
|
|
|
match = function(element) {
|
|
|
|
var html = element.firstChild.innerHTML;
|
|
|
|
return html && html.toLowerCase().indexOf(value) !== -1;
|
|
|
|
};
|
2015-11-20 09:21:46 -05:00
|
|
|
}
|
2018-02-12 14:58:50 -05:00
|
|
|
|
|
|
|
for (i = 0; i < tocElements.length; i++) {
|
|
|
|
element = tocElements[i];
|
|
|
|
children = Array.from(element.getElementsByTagName('li'));
|
|
|
|
if (match(element) || children.some(match)) {
|
|
|
|
element.classList.remove('display-none');
|
|
|
|
} else {
|
|
|
|
element.classList.add('display-none');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2015-11-20 09:21:46 -05:00
|
|
|
|
2016-07-20 16:33:09 -04:00
|
|
|
var items = document.getElementsByClassName('toggle-sibling');
|
|
|
|
for (var j = 0; j < items.length; j++) {
|
|
|
|
items[j].addEventListener('click', toggleSibling);
|
|
|
|
}
|
2015-11-20 09:21:46 -05:00
|
|
|
|
2016-07-20 16:33:09 -04:00
|
|
|
function toggleSibling() {
|
|
|
|
var stepSibling = this.parentNode.getElementsByClassName('toggle-target')[0];
|
|
|
|
var icon = this.getElementsByClassName('icon')[0];
|
|
|
|
var klass = 'display-none';
|
|
|
|
if (stepSibling.classList.contains(klass)) {
|
|
|
|
stepSibling.classList.remove(klass);
|
|
|
|
icon.innerHTML = '▾';
|
|
|
|
} else {
|
|
|
|
stepSibling.classList.add(klass);
|
|
|
|
icon.innerHTML = '▸';
|
2015-11-20 09:21:46 -05:00
|
|
|
}
|
2016-07-20 16:33:09 -04:00
|
|
|
}
|
2015-11-20 09:21:46 -05:00
|
|
|
|
2016-07-20 16:33:09 -04:00
|
|
|
function showHashTarget(targetId) {
|
2018-02-12 14:58:50 -05:00
|
|
|
if (targetId) {
|
|
|
|
var hashTarget = document.getElementById(targetId);
|
|
|
|
// new target is hidden
|
|
|
|
if (
|
|
|
|
hashTarget &&
|
|
|
|
hashTarget.offsetHeight === 0 &&
|
|
|
|
hashTarget.parentNode.parentNode.classList.contains('display-none')
|
|
|
|
) {
|
|
|
|
hashTarget.parentNode.parentNode.classList.remove('display-none');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function scrollIntoView(targetId) {
|
|
|
|
// Only scroll to element if we don't have a stored scroll position.
|
|
|
|
if (targetId && !history.state) {
|
|
|
|
var hashTarget = document.getElementById(targetId);
|
|
|
|
if (hashTarget) {
|
|
|
|
hashTarget.scrollIntoView();
|
|
|
|
}
|
2015-11-20 09:21:46 -05:00
|
|
|
}
|
2016-07-20 16:33:09 -04:00
|
|
|
}
|
|
|
|
|
2018-02-12 14:58:50 -05:00
|
|
|
function gotoCurrentTarget() {
|
2016-07-20 16:33:09 -04:00
|
|
|
showHashTarget(location.hash.substring(1));
|
2018-02-12 14:58:50 -05:00
|
|
|
scrollIntoView(location.hash.substring(1));
|
|
|
|
}
|
2016-07-20 16:33:09 -04:00
|
|
|
|
2018-02-12 14:58:50 -05:00
|
|
|
window.addEventListener('hashchange', gotoCurrentTarget);
|
|
|
|
gotoCurrentTarget();
|
2016-07-20 16:33:09 -04:00
|
|
|
|
|
|
|
var toclinks = document.getElementsByClassName('pre-open');
|
|
|
|
for (var k = 0; k < toclinks.length; k++) {
|
|
|
|
toclinks[k].addEventListener('mousedown', preOpen, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
function preOpen() {
|
|
|
|
showHashTarget(this.hash.substring(1));
|
|
|
|
}
|
2018-02-12 14:58:50 -05:00
|
|
|
|
|
|
|
var split_left = document.querySelector('#split-left');
|
|
|
|
var split_right = document.querySelector('#split-right');
|
|
|
|
var split_parent = split_left.parentNode;
|
|
|
|
var cw_with_sb = split_left.clientWidth;
|
|
|
|
split_left.style.overflow = 'hidden';
|
|
|
|
var cw_without_sb = split_left.clientWidth;
|
|
|
|
split_left.style.overflow = '';
|
|
|
|
|
|
|
|
Split(['#split-left', '#split-right'], {
|
|
|
|
elementStyle: function(dimension, size, gutterSize) {
|
|
|
|
return {
|
|
|
|
'flex-basis': 'calc(' + size + '% - ' + gutterSize + 'px)'
|
|
|
|
};
|
|
|
|
},
|
|
|
|
gutterStyle: function(dimension, gutterSize) {
|
|
|
|
return {
|
|
|
|
'flex-basis': gutterSize + 'px'
|
|
|
|
};
|
|
|
|
},
|
|
|
|
gutterSize: 20,
|
|
|
|
sizes: [33, 67]
|
|
|
|
});
|
|
|
|
|
|
|
|
// Chrome doesn't remember scroll position properly so do it ourselves.
|
|
|
|
// Also works on Firefox and Edge.
|
|
|
|
|
|
|
|
function updateState() {
|
|
|
|
history.replaceState(
|
|
|
|
{
|
|
|
|
left_top: split_left.scrollTop,
|
|
|
|
right_top: split_right.scrollTop
|
|
|
|
},
|
|
|
|
document.title
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function loadState(ev) {
|
|
|
|
if (ev) {
|
|
|
|
// Edge doesn't replace change history.state on popstate.
|
|
|
|
history.replaceState(ev.state, document.title);
|
|
|
|
}
|
|
|
|
if (history.state) {
|
|
|
|
split_left.scrollTop = history.state.left_top;
|
|
|
|
split_right.scrollTop = history.state.right_top;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
window.addEventListener('load', function() {
|
|
|
|
// Restore after Firefox scrolls to hash.
|
|
|
|
setTimeout(function() {
|
|
|
|
loadState();
|
|
|
|
// Update with initial scroll position.
|
|
|
|
updateState();
|
|
|
|
// Update scroll positions only after we've loaded because Firefox
|
|
|
|
// emits an initial scroll event with 0.
|
|
|
|
split_left.addEventListener('scroll', updateState);
|
|
|
|
split_right.addEventListener('scroll', updateState);
|
|
|
|
}, 1);
|
|
|
|
});
|
|
|
|
|
|
|
|
window.addEventListener('popstate', loadState);
|