mirror of
https://github.com/kiwix/kiwix-desktop.git
synced 2025-09-11 13:30:03 -04:00
175 lines
5.5 KiB
JavaScript
175 lines
5.5 KiB
JavaScript
/**
|
|
* Construct recurseData.str as a nested list of headers by recursively going
|
|
* through all children of elem that has header tags.
|
|
*
|
|
* References:
|
|
* https://stackoverflow.com/questions/187619/is-there-a-javascript-solution-to-generating-a-table-of-contents-for-a-page
|
|
* @param elem DOM element
|
|
* @param recurseData Object with fields: { int: level, int: count, str: toc }
|
|
*/
|
|
function recurseChild(elem, recurseData)
|
|
{
|
|
if (elem !== "undefined")
|
|
{
|
|
if(elem.nodeName.match(/^H\d+$/) && elem.textContent)
|
|
{
|
|
var headerText = elem.textContent;
|
|
var prevLevel = recurseData.level;
|
|
var level = elem.nodeName.substr(1);
|
|
var anchor = "kiwix-toc-" + recurseData.count;
|
|
recurseData.count += 1;
|
|
|
|
/* Wrap header content with something we can reference. */
|
|
elem.innerHTML = '<a href="#' + anchor + '" id="' + anchor + '" class="kiwix-toc-a">' + headerText + '</a>';
|
|
|
|
/* Start or end a list or item based on current and previous level */
|
|
if (level > prevLevel)
|
|
recurseData.toc += '<ul class="kiwix-toc-list">';
|
|
else if (level < prevLevel)
|
|
recurseData.toc += '</li></ul>';
|
|
else
|
|
recurseData.toc += '</li>';
|
|
|
|
recurseData.level = parseInt(level);
|
|
recurseData.toc += '<li class="kiwix-toc-item"><a href="#' + anchor + '" class="kiwix-toc-item-a">' +
|
|
'<span class="kiwix-tool-tip">' + headerText + '</span>' + headerText + '</a>';
|
|
}
|
|
|
|
var c = elem.children;
|
|
for (var i = 0; i < c.length; i++)
|
|
recurseChild(c[i], recurseData);
|
|
}
|
|
}
|
|
|
|
function tocHTMLStr()
|
|
{
|
|
/* level used to track current header level.
|
|
toc used to store constructed list.
|
|
count used to uniquely identify each list item in toc.
|
|
*/
|
|
var recurseData = { level: 0, toc: "", count: 0,};
|
|
recurseChild(document.body, recurseData);
|
|
|
|
/* End list when non-empty */
|
|
if (recurseData.level)
|
|
recurseData.toc += (new Array(recurseData.level + 1)).join('</ul>');
|
|
return recurseData.toc;
|
|
}
|
|
|
|
function getPixelWithZoom(pixel)
|
|
{
|
|
var zoom = window.outerWidth / window.document.documentElement.clientWidth;
|
|
return (pixel / zoom.toFixed(1)).toString() + "px";
|
|
}
|
|
|
|
function makeTOCVisible(visible)
|
|
{
|
|
var tocElem = document.getElementById("kiwix-toc-side");
|
|
tocElem.style.display = visible ? "block" : "none";
|
|
document.body.style.marginLeft = visible ? getPixelWithZoom(310) : null;
|
|
document.body.style.maxWidth = visible ? "calc(100vw - " + getPixelWithZoom(310) + ")" : null;
|
|
}
|
|
|
|
function showToolTip (elem) {
|
|
var tooltip = elem.getElementsByClassName("kiwix-tool-tip")[0];
|
|
|
|
/* Check if there is overflow. */
|
|
if (tooltip && elem.offsetWidth < elem.scrollWidth)
|
|
{
|
|
tooltip.style.display = "block";
|
|
|
|
var rect = elem.getBoundingClientRect();
|
|
tooltip.style.top = (rect.top).toString() + "px";
|
|
tooltip.style.left = getPixelWithZoom(306);
|
|
}
|
|
}
|
|
|
|
function hideToolTip (elem) {
|
|
var tooltip = elem.getElementsByClassName("kiwix-tool-tip")[0];
|
|
|
|
if (tooltip)
|
|
tooltip.style.display = "";
|
|
}
|
|
|
|
function setupTOCItems()
|
|
{
|
|
var c = document.getElementsByClassName("kiwix-toc-item-a");
|
|
for (var i = 0; i < c.length; i++)
|
|
{
|
|
if (c[i] !== "undefined" && c[i].style)
|
|
{
|
|
var p = c[i].parentNode;
|
|
var count = -1;
|
|
while (p)
|
|
{
|
|
if (p.nodeName.match(/^UL$/))
|
|
count += 1;
|
|
p = p.parentNode;
|
|
}
|
|
|
|
/* We need manual padding to achieve visual effects on hover. */
|
|
c[i].style.paddingLeft = ((count == -1 ? 0 : count) * 30).toString() + "px";
|
|
|
|
c[i].addEventListener("mouseover", (event) => { showToolTip(event.target); });
|
|
c[i].addEventListener("mouseout", (event) => { hideToolTip(event.target); });
|
|
}
|
|
}
|
|
}
|
|
|
|
function setupTOC()
|
|
{
|
|
var toc = document.createElement('div');
|
|
toc.id = "kiwix-toc";
|
|
toc.innerHTML += tocHTMLStr();
|
|
|
|
var tocTitle = document.createElement('p');
|
|
tocTitle.id = "kiwix-toc-title";
|
|
|
|
var tocHideButton = document.createElement('button');
|
|
tocHideButton.id = "kiwix-toc-hide-button"
|
|
|
|
var tocTitleDiv = document.createElement('div');
|
|
tocTitleDiv.id = "kiwix-toc-title-div";
|
|
tocTitleDiv.append(tocTitle);
|
|
tocTitleDiv.append(tocHideButton);
|
|
|
|
var tocSideDiv = document.createElement('div');
|
|
tocSideDiv.id = "kiwix-toc-side";
|
|
tocSideDiv.append(tocTitleDiv);
|
|
tocSideDiv.append(toc);
|
|
|
|
document.body.prepend(tocSideDiv);
|
|
}
|
|
|
|
function resize(){
|
|
document.getElementById("kiwix-toc-side").style.width = getPixelWithZoom(306);
|
|
|
|
if (document.getElementById("kiwix-toc-side").style.display !== "none")
|
|
{
|
|
document.body.style.marginLeft = getPixelWithZoom(310);
|
|
document.body.style.maxWidth = "calc(100vw - " + getPixelWithZoom(310) + ")";
|
|
}
|
|
}
|
|
|
|
new QWebChannel(qt.webChannelTransport, function(channel) {
|
|
|
|
var kiwixObj = channel.objects.kiwixChannelObj
|
|
setupTOC();
|
|
setupTOCItems();
|
|
|
|
document.getElementById("kiwix-toc-title").textContent = kiwixObj.tocTitle;
|
|
|
|
var tocHideButton = document.getElementById("kiwix-toc-hide-button");
|
|
tocHideButton.textContent = kiwixObj.hideButtontext;
|
|
tocHideButton.onclick = () => { kiwixObj.tocVisible = false; };
|
|
|
|
kiwixObj.tocVisibleChanged.connect(function(visible) {
|
|
makeTOCVisible(visible);
|
|
});
|
|
makeTOCVisible(kiwixObj.tocVisible);
|
|
|
|
window.onresize = resize;
|
|
resize();
|
|
});
|
|
|