Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Table of content moving with as you scroll down the page?

Guido Grygiel April 16, 2014

In order to make navigating within a page faster and easier, I would like to have the table of content always visible, even if scrolling down.

That’s why my question is: Is it possible to make the table of content move with you as you scroll down the page?

If that is possible, I would always have an overview over the content on the page.

Thanks a lot for your help!

6 answers

6 votes
Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 16, 2014

You could do it with some css and javascript. In your Confluence admin create a css class like the below.

.fixedPosition {
	position: fixed;
}

In the custom html section put this in the after body section.

<script type="text/javascript">
AJS.toInit(function(){
	AJS.$('.fixedPosition').each(function(){
		var clone = AJS.$(this).clone().css('visibility','hidden').removeClass('fixedPosition');
		AJS.$(this).after(clone);
	});
});
</script>

Then on your table of contents macro put the class "fixedPosition" at the bottom of the properties.

What this will do is clone your table of contents and hide the clone to reserve the original space of the table of contents because when you do a position:fixed the element is pulled out of flow and the content below it will move up.

Is this what you are looking to do?

 

 

Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 20, 2014

Does this do what you are trying to accomplish?

Guido Grygiel April 22, 2014

Hi Davin,

sorry for not answering earlier. I haven't found any time to try it. FInally I did try it today and your solution definetely tends into the right direction. Thanks a lot for your help!

However the TOC now is cloned over the regular content (as you have mentioned in your post). The problem is that the TOC now is not readable anymore, because it overlays the regular text. A (white) background would also not solve the problem, because a TOC may be so large that it covers a whole page. So I guess a perfect solution would be:

A kind of frame which is at the top of the page and contains the TOC only. I will name it "TOC-frame" from now on.

When scrolling down the page the TOC-frame is minimized to a small bar which maximizes on mouseover (or even hidden and only showing up on mouseover on the top of the page). By this the user can navigate using the TOC without seeing it all the time.

Does anyone think that is possible and how do I have to implemet it?

Thanks a lot!

Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 22, 2014

Yeah, that would definitely need to be done with JavaScript. There is nothing quick I could give you to accomplish that.

Guido Grygiel April 22, 2014

I expected soemthing like that... Anyhow thanks again for your input, the other solution works ok. Finally I combined 3 things:

- a standard confluence range (2/1 split). On the left a real TOC and on the right:

- "highlight" macro for a solid background. Here comes the "fixedPosition" CSS

- "expand" macro for the ability to have it as a one row TOC-"indicator"

When starting the page the user sees the full TOC on the left and only the minimized small 1-row-TOC on the right (which is not of interest at the moment). When scrolling down, the real TOC disappears but the one-row-expand macro moves with the page. When expanding the macro the TOC shows up.

This solution is still far from being perfect (not docked on top, covering other stuff, not disappearing after click,...), but ok. If anybody has ideas for any better solutions -> please let me know!

Milo Test
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 8, 2015

Another brilliant solution Davin!

3 votes
iaswtw June 23, 2019

Please vote on this -- https://jira.atlassian.com/browse/CONFSERVER-57903 -- for the remote possibility that Atlassian implements it.

1 vote
roman_baeriswyl July 19, 2016

I just had the same request.

Because I don't like to modify default confluence (or some might not have the rights), I added a grease-/tampermonkey script which adds a collapsible TOC at the right side of the page.

It's not the prettiest thing but it works. Here's the script for it:

// ==UserScript==
// @name         Confluence floating toc
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Adds a floating toc into Confluence
// @author       RBL
// @match        <your confluence url>
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    
    $('[data-macro-name="toc"]').each(function(){
        var clone = $(this).clone();
        var list = clone.children(":first");
        list.attr("id", "floatingToc");
        list.css("padding", "0");
        list.css("list-style-type", "none");
        clone.css("padding", "5px");
        clone.css("position", "fixed");
        clone.css("background", "white");
        clone.css("border", "1px solid grey");
        clone.css("right", "0");
        clone.css("top", "100px");
        clone.css("z-index", "9999");
        clone.prepend("<div style='float:right;'><a id='showTocLink' href='javascript&colon;$(\"#floatingToc\").show();$(\"#showTocLink\").hide();$(\"#hideTocLink\").show();'>Show</a>&nbsp;<a id='hideTocLink' href='javascript&colon;$(\"#floatingToc\").hide();$(\"#showTocLink\").show();$(\"#hideTocLink\").hide();'>Hide</a></div>");
        $(this).after(clone);
        $("#showTocLink").hide();
    });
})();

Maybe this helps someone smile

roman_baeriswyl July 20, 2016

I already have an update so that it also works with very long Tocs (scrollable).

Here's the update:

// ==UserScript==
// @name         Confluence floating toc
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  Adds a floating toc into Confluence
// @author       RBL
// @match        <your url here>
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    $('[data-macro-name="toc"]').each(function(){
        var clone = $(this).clone();
        var list = clone.children(":first");
        list.attr("id", "floatingToc");
        list.css("padding", "0");
        list.css("list-style-type", "none");
        clone.attr("id", "floatingTocContainer");
        clone.css("padding", "5px");
        clone.css("position", "fixed");
        clone.css("background", "white");
        clone.css("border", "1px solid grey");
        clone.css("right", "0");
        clone.css("top", "80px");
        clone.css("max-height", "calc(100% - 100px)");
        clone.css("overflow-y", "auto");
        clone.css("z-index", "9999");
        clone.prepend("<div style='float:right;'><a id='showTocLink' href='javascript&colon;$(\"#floatingToc\").show();$(\"#showTocLink\").hide();$(\"#hideTocLink\").show();'>Show</a><a id='hideTocLink' href='javascript&colon;$(\"#floatingToc\").hide();$(\"#showTocLink\").show();$(\"#hideTocLink\").hide();'>Hide</a></div>");
        $(this).after(clone);
        $("#showTocLink").hide();
    });
})();
roman_baeriswyl July 20, 2016

Sorry for the spam, I have one more updated version: Smaller font and some configuration values at the top:

// ==UserScript==
// @name         Confluence floating toc
// @namespace    http://tampermonkey.net/
// @version      0.3
// @description  Adds a floating toc into Confluence
// @author       RBL
// @match        <your confluence url>
// @grant        none
// ==/UserScript==

(function() {    
    'use strict';
    var fontSize = '10px';
    var distanceTop = '80px';
    var distanceBottom = 'calc(100% - 100px)';
    var hideOnStart = false;
    $('[data-macro-name="toc"]').each(function(){
        var clone = $(this).clone();
        var list = clone.children(":first");
        list.attr("id", "floatingToc");
        list.css("padding", "0");
        list.css("list-style-type", "none");
        clone.attr("id", "floatingTocContainer");
        clone.css("padding", "5px");
        clone.css("position", "fixed");
        clone.css("background", "white");
        clone.css("border", "1px solid grey");
        clone.css("right", "0");
        clone.css("top", distanceTop);
        clone.css("max-height", distanceBottom);
        clone.css("overflow-y", "auto");
        clone.css("z-index", "9999");
        clone.css("font-size", fontSize);
        clone.prepend("<div style='float:right;'><a id='showTocLink' href='javascript&colon;$(\"#floatingToc\").show();$(\"#showTocLink\").hide();$(\"#hideTocLink\").show();'>Show</a><a id='hideTocLink' href='javascript&colon;$(\"#floatingToc\").hide();$(\"#showTocLink\").show();$(\"#hideTocLink\").hide();'>Hide</a></div>");
        $(this).after(clone);
        if (hideOnStart) {
            $("#floatingToc").hide();
            $("#showTocLink").show();
            $("#hideTocLink").hide();
        } else {
            $("#floatingToc").show();
            $("#showTocLink").hide();
            $("#hideTocLink").show();
        }
    });
})();
roman_baeriswyl July 22, 2016

And another update:
The ToC is now also visible on pages which do not have their own toc! I generelly build my own toc in all cases. Also there is some more configuration (check the variables at the top).

// ==UserScript==
// @name         Confluence floating toc
// @namespace    http://tampermonkey.net/
// @version      0.4
// @description  Adds a floating toc into Confluence
// @author       RBL
// @match        <your confluence url>
// @grant        none
// ==/UserScript==

// Setup variables
var fontSize = '10px'; // General size of the links
var distanceTop = '80px'; // Distance from the top
var distanceBottom = 'calc(100% - 100px)'; // Distance from the bottom
var initiallyCollapsed = false; // Flag if it should be collapsed when loaded
var showWithoutToc = true; // Flag if it should be created when no toc was added to the page
var hideEmpty = true; // Flag if empty levels should be hidden


// Entry "class"
function Entry(id, text, level, parent) {
    this.id = id;
    this.text = text;
    this.level = level;
    this.parent = parent;
    this.subElements = [];
}

Entry.prototype.addChild = function(child) {
    this.subElements.push(child);
};

// "Main"
(function() {
    'use strict';

    if (!showWithoutToc) {
        // Check if the toc exists
        if (!$('[data-macro-name="toc"]').length) {
            // It doesn't so don't do anything
            return;
        }
    }

    // Build the list with headers
    var rootElement = new Entry('root', '', 0, undefined);
    var lastElement = rootElement;
    $('#main-content').find($("h1, h2, h3, h4, h5, h6")).each(function() {
        // Parse the object information
        var thisLevel = parseInt($(this).prop("nodeName").substring(1));
        var thisId = $(this).prop("id");
        var thisText = $(this).text();
        // Check for level changes with the last element
        var levelDiff = thisLevel - lastElement.level;
        if (levelDiff > 0) {
            // Higher level
            for (var i=1; i<levelDiff; i++) {
                // Add intermediate elements if some levels were skipped
                var intermediateElement = new Entry('intermediate', '', lastElement.level+i, lastElement);
                lastElement.addChild(intermediateElement);
                lastElement = intermediateElement;
            }
            var thisElement = new Entry(thisId, thisText, thisLevel, lastElement);
            lastElement.addChild(thisElement);
            lastElement = thisElement;
        } else if (levelDiff <= 0) {
            // Same or lower level
            // Loop to go down as needed
            for (var i=0; i<Math.abs(levelDiff); i++) {
                lastElement = lastElement.parent;
            }
            var thisElement = new Entry(thisId, thisText, thisLevel, lastElement.parent);
            lastElement.parent.addChild(thisElement);
            lastElement = thisElement;
        }
    });

    // Log
    //rootElement.subElements.forEach(function(entry) { console.log(entry); });


    var newElement = $('<div></div>');
    var currentList = $('<ul></ul>');
    newElement.append(currentList);
    var currentLevel= 1;
    rootElement.subElements.forEach(function(entry) {
        createEntry(currentList, entry);
    });
    $('#main-content').append(newElement);

    // Add styles and ids
    newElement.attr("id", "floatingTocContainer");
    newElement.css("padding", "5px");
    newElement.css("position", "fixed");
    newElement.css("background", "white");
    newElement.css("border", "1px solid grey");
    newElement.css("right", "0");
    newElement.css("top", distanceTop);
    newElement.css("max-height", distanceBottom);
    newElement.css("overflow-y", "auto");
    newElement.css("z-index", "9999");
    newElement.css("font-size", fontSize);
    newElement.prepend("<div style='float:right;'><a id='showTocLink' href='javascript&colon;$(\"#floatingToc\").show();$(\"#showTocLink\").hide();$(\"#hideTocLink\").show();'>Show</a><a id='hideTocLink' href='javascript&colon;$(\"#floatingToc\").hide();$(\"#showTocLink\").show();$(\"#hideTocLink\").hide();'>Hide</a></div>");
    currentList.attr("id", "floatingToc");
    currentList.css("padding", "0");
    currentList.css("list-style-type", "none");
    currentList.css("font-size", fontSize);
    currentList.css("line-height", 1);
    // Initialize
    $("#floatingToc").toggle(!initiallyCollapsed);
    $("#showTocLink").toggle(initiallyCollapsed);
    $("#hideTocLink").toggle(!initiallyCollapsed);
})();

function createEntry(parentList, entry) {
    var listItem = $('<li/>', {html: '<a href="#' + entry.id + '">' + entry.text + '</a>'});
    // Hide the list icon for helper levels
    if (entry.id == 'intermediate') {
        listItem.css("list-style-type", "none");
    }
    // Add the subelements
    if (entry.subElements.length > 0) {
        var innerList = $('<ul></ul>');
        innerList.css("padding-left", "20px");
        var hasRealChild = false;
        entry.subElements.forEach(function(innerEntry) {
            createEntry(innerList, innerEntry);
            if (innerEntry.id != 'intermediate') {
                hasRealChild = true;
            }
        });
        // Check if the subelements contain at least one real child
        if (hideEmpty && !hasRealChild) {
            // It doesn't, so hide this level completely
            innerList.css("padding", "0px");
        }
        listItem.append(innerList);
    }
    parentList.append(listItem);
}

 

 

Wendy Podgursky September 14, 2016

Great stuff Roman!

Anyone know of a way to make this kind of scrolling TOC work on Cloud? 

Like Racheli Nehemia likes this
Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 14, 2016

A user script like the one above is the only way to do it with the cloud offering.

Carla Gray November 11, 2016

I'm a space admin (not a Confluence admin). I'm not sure where to add this code. Can someone please let me know where that is?

Like # people like this
Deleted user November 13, 2016

You actually do not add it to confluence. It is "injected" into the website via an addon to your browser (Tampermonkey for Chrome, Greasemonkey for Firefox). With this addon you can add JavaScript code which should be injected on pages. You need to adjust the @match in the script above to match your confluence base url.

Hope this helped.

roman_baeriswyl November 13, 2016

Here's a new version of it by the way. This one should work better when skipping some headings (eg. using only h1 and h3):

// ==UserScript==
// @name         Confluence floating toc
// @namespace    http://tampermonkey.net/
// @version      0.5
// @description  Adds a floating toc into Confluence
// @author       RBL
// @match        <your confluence url>
// @grant        none
// ==/UserScript==

// Setup variables
var fontSize = '10px'; // General size of the links
var distanceTop = '80px'; // Distance from the top
var distanceBottom = 'calc(100% - 100px)'; // Distance from the bottom
var initiallyCollapsed = false; // Flag if it should be collapsed when loaded
var showWithoutToc = true; // Flag if it should be created when no toc was added to the page
var hideEmpty = true; // Flag if empty levels should be hidden

// Entry "class"
function Entry(id, text, level, parent) {
    this.id = id;
    this.text = text;
    this.level = level;
    this.parent = parent;
    this.subElements = [];
}

Entry.prototype.addChild = function(child) {
    this.subElements.push(child);
};

// "Main"
(function() {
    'use strict';
    if (!showWithoutToc) {
        // Check if the toc exists
        if (!$('[data-macro-name="toc"]').length) {
            // It doesn't so don't do anything
            return;
        }
    }

    // Build the list with headers
    var rootElement = new Entry('root', '', 0, undefined);
    var lastElement = rootElement;
    $('#main-content').find($('h1, h2, h3, h4, h5, h6')).each(function() {
        // Parse the object information
        var thisLevel = parseInt($(this).prop('nodeName').substring(1));
        var thisId = $(this).prop('id');
        var thisText = $(this).text();
        // Check for level changes with the last element
        var levelDiff = thisLevel - lastElement.level;
        if (levelDiff > 0) {
            // Higher level
            for (var i = 1; i < levelDiff; i++) {
                // Add intermediate elements if some levels were skipped
                var intermediateElement = new Entry('intermediate', '', lastElement.level + i, lastElement);
                lastElement.addChild(intermediateElement);
                lastElement = intermediateElement;
            }
            var thisElement = new Entry(thisId, thisText, thisLevel, lastElement);
            lastElement.addChild(thisElement);
            lastElement = thisElement;
        } else if (levelDiff <= 0) {
            // Same or lower level
            // Loop to go down as needed
            for (var i = 0; i < Math.abs(levelDiff); i++) {
                lastElement = lastElement.parent;
            }
            var thisElement = new Entry(thisId, thisText, thisLevel, lastElement.parent);
            lastElement.parent.addChild(thisElement);
            lastElement = thisElement;
        }
    });

    // Log
    //rootElement.subElements.forEach(function(entry) { console.log(entry); });

    var newElement = $('<div></div>');
    var currentList = $('<ul></ul>');
    newElement.append(currentList);
    var currentLevel= 1;
    createEntry(rootElement, currentList);
    $('#main-content').append(newElement);

    // Add styles and ids
    newElement.attr("id", "floatingTocContainer");
    newElement.css("padding", "5px");
    newElement.css("position", "fixed");
    newElement.css("background", "white");
    newElement.css("border", "1px solid grey");
    newElement.css("right", "0");
    newElement.css("top", distanceTop);
    newElement.css("max-height", distanceBottom);
    newElement.css("overflow-y", "auto");
    newElement.css("z-index", "9999");
    newElement.css("font-size", fontSize);
    newElement.prepend("<div style='float:right;'><a id='showTocLink' href=\"javascript&colon;void(0)\" onclick='javascript&colon;$(\"#floatingToc\").show();$(\"#showTocLink\").hide();$(\"#hideTocLink\").show();return false;'>Show</a><a id='hideTocLink' href=\"javascript&colon;void(0)\" onclick='javascript&colon;$(\"#floatingToc\").hide();$(\"#showTocLink\").show();$(\"#hideTocLink\").hide();return false;'>Hide</a></div>");
    currentList.attr("id", "floatingToc");
    currentList.css("padding", "0");
    currentList.css("list-style-type", "none");
    currentList.css("font-size", fontSize);
    currentList.css("line-height", 1);

    // Initialize
    $("#floatingToc").toggle(!initiallyCollapsed);
    $("#showTocLink").toggle(initiallyCollapsed);
    $("#hideTocLink").toggle(!initiallyCollapsed);
})();

function createEntry(parentElement, parentList) {
    var hasRealChild = false;
    parentElement.subElements.forEach(function(entry) {
        var listItem = $('<li/>', {html: '<a href="#' + entry.id + '">' + entry.text + '</a>'});
        // Hide the list icon for helper levels
        if (entry.id == 'intermediate') {
            listItem.css("list-style-type", "none");
            listItem.css("padding", "0px");
        } else {
            hasRealChild = true;
        }
        // Add the subelements
        if (entry.subElements.length > 0) {
            var innerList = $('<ul></ul>');
            innerList.css("padding-left", "20px");
            createEntry(entry, innerList);
            listItem.append(innerList);
        }
        parentList.append(listItem);
    });
    // Check if the subelements contain at least one real child
    if (hideEmpty && !hasRealChild) {
        // It doesn't, hide this level completely
        parentList.css("padding", "0px");
        parentList.css("list-style-type", "none");
        console.log("bla");
    }
}
Like Ben Johnson likes this
Rodrigo Teixeira March 24, 2019

@roman_baeriswyl  Assuming my URL is https://test.atlassian.net, how would that reflect on the script after the changes? I can't make it to work? Should we include the space destination URL as well?

0 votes
Michael Yang - Shinetech Software
Marketplace Partner
Marketplace Partners provide apps and integrations available on the Atlassian Marketplace that extend the power of Atlassian products.
October 25, 2019

Just published a free macro for floating TOC. Simple to use! https://marketplace.atlassian.com/1221271 

Christian Lämmerer March 18, 2020

hi michael, 

the link does not work.

christian 

Like Elridge Bibera likes this
Michael Yang - Shinetech Software
Marketplace Partner
Marketplace Partners provide apps and integrations available on the Atlassian Marketplace that extend the power of Atlassian products.
March 18, 2020

The short link is expired. Use this:

Easy Heading Free Macro for Confluence

Christian Lämmerer March 18, 2020

thank you, but this macro does not work in the cloud, does it?

Michael Yang - Shinetech Software
Marketplace Partner
Marketplace Partners provide apps and integrations available on the Atlassian Marketplace that extend the power of Atlassian products.
March 28, 2020

No, it does not. We have plan to support cloud in the future.

Like Michael Schaufelberger likes this
Stig Grafsrønningen January 13, 2021

Michael,

Any progress on the cloud version of this? 

Michael Yang - Shinetech Software
Marketplace Partner
Marketplace Partners provide apps and integrations available on the Atlassian Marketplace that extend the power of Atlassian products.
January 13, 2021

@STI  Sorry, we did research but we are not able to implement this floating TOC for Cloud. It does not allow developer to inject javascript codes to the main page to display a floating customized TOC.

Michael Yang - Shinetech Software
Marketplace Partner
Marketplace Partners provide apps and integrations available on the Atlassian Marketplace that extend the power of Atlassian products.
January 13, 2021

@Davin Studer Do you know if it's possible to implement a floating TOC addon for confluence cloud?

Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 14, 2021

The only way I can think to do it would be with a user script for your browsers. There is one provided above. Unfortunately, Cloud has technical limitations that are sometimes hard to work around.

Michael Yang - Shinetech Software
Marketplace Partner
Marketplace Partners provide apps and integrations available on the Atlassian Marketplace that extend the power of Atlassian products.
January 17, 2021

Got it. Thank you!

dschulten February 26, 2022

@roman_baeriswyl's last version did not toggle the toc properly in our Confluence Version 7.13.1, clicking Show replaced the whole page with [Object object]. What helped was to define functions for showing and hiding the toc.

Put the following script into an HTML macro at the bottom of the page (sry this editor kills indentation when pasting) or use tampermonkey with Roman's Userscript annotation:

<script type="text/javascript"> 
// Setup variables
var fontSize = '10px'; // General size of the links
var distanceTop = '80px'; // Distance from the top
var distanceBottom = 'calc(100% - 100px)'; // Distance from the bottom
var initiallyCollapsed = true; // Flag if it should be collapsed when loaded
var showWithoutToc = true; // Flag if it should be created when no toc was added to the page
var hideEmpty = true; // Flag if empty levels should be hidden


// Entry "class"
function Entry(id, text, level, parent) {
this.id = id;
this.text = text;
this.level = level;
this.parent = parent;
this.subElements = [];
}

Entry.prototype.addChild = function(child) {
this.subElements.push(child);
};

function showToc() {
$("#floatingToc").show();
$("#showTocLink").hide();
$("#hideTocLink").show();
}

function hideToc() {
$("#floatingToc").hide();
$("#showTocLink").show();
$("#hideTocLink").hide();
}  

// "Main"
(function() {
'use strict';

if (!showWithoutToc) {
// Check if the toc exists
if (!$('[data-macro-name="toc"]').length) {
// It doesn't so don't do anything
return;
}
}

// Build the list with headers
var rootElement = new Entry('root', '', 0, undefined);
var lastElement = rootElement;
$('#main-content').find($("h1, h2, h3, h4, h5, h6")).each(function() {
// Parse the object information
var thisLevel = parseInt($(this).prop("nodeName").substring(1));
var thisId = $(this).prop("id");
var thisText = $(this).text();
// Check for level changes with the last element
var levelDiff = thisLevel - lastElement.level;
if (levelDiff > 0) {
// Higher level
for (var i=1; i<levelDiff; i++) {
// Add intermediate elements if some levels were skipped
var intermediateElement = new Entry('intermediate', '', lastElement.level+i, lastElement);
lastElement.addChild(intermediateElement);
lastElement = intermediateElement;
}
var thisElement = new Entry(thisId, thisText, thisLevel, lastElement);
lastElement.addChild(thisElement);
lastElement = thisElement;
} else if (levelDiff <= 0) {
// Same or lower level
// Loop to go down as needed
for (var i=0; i<Math.abs(levelDiff); i++) {
lastElement = lastElement.parent;
}
var thisElement = new Entry(thisId, thisText, thisLevel, lastElement.parent);
lastElement.parent.addChild(thisElement);
lastElement = thisElement;
}
});

// Log
//rootElement.subElements.forEach(function(entry) { console.log(entry); });


var newElement = $('<div></div>');
var currentList = $('<ul></ul>');
newElement.append(currentList);
var currentLevel= 1;
rootElement.subElements.forEach(function(entry) {
createEntry(currentList, entry);
});
$('#main-content').append(newElement);

// Add styles and ids
newElement.attr("id", "floatingTocContainer");
newElement.css("padding", "5px");
newElement.css("position", "fixed");
newElement.css("background", "white");
newElement.css("border", "1px solid grey");
newElement.css("right", "0");
newElement.css("top", distanceTop);
newElement.css("max-height", distanceBottom);
newElement.css("overflow-y", "auto");
newElement.css("z-index", "9999");
newElement.css("font-size", fontSize);
newElement.prepend("<div style='float:right;'><a id='showTocLink' href='javascript&colon;showToc()'>Inhalt</a><a id='hideTocLink' href='javascript&colon;hideToc()'>ausblenden</a></div>");
currentList.attr("id", "floatingToc");
currentList.css("padding", "0");
currentList.css("list-style-type", "none");
currentList.css("font-size", fontSize);
currentList.css("line-height", 1);
// Initialize
$("#floatingToc").toggle(!initiallyCollapsed);
$("#showTocLink").toggle(initiallyCollapsed);
$("#hideTocLink").toggle(!initiallyCollapsed);
})();

function createEntry(parentList, entry) {
var listItem = $('<li/>', {html: '<a href="#' + entry.id + '">' + entry.text + '</a>'});
// Hide the list icon for helper levels
if (entry.id == 'intermediate') {
listItem.css("list-style-type", "none");
}
// Add the subelements
if (entry.subElements.length > 0) {
var innerList = $('<ul></ul>');
innerList.css("padding-left", "20px");
var hasRealChild = false;
entry.subElements.forEach(function(innerEntry) {
createEntry(innerList, innerEntry);
if (innerEntry.id != 'intermediate') {
hasRealChild = true;
}
});
// Check if the subelements contain at least one real child
if (hideEmpty && !hasRealChild) {
// It doesn't, so hide this level completely
innerList.css("padding", "0px");
}
listItem.append(innerList);
}
parentList.append(listItem);
} </script>

 

Michael Yang - Shinetech Software
Marketplace Partner
Marketplace Partners provide apps and integrations available on the Atlassian Marketplace that extend the power of Atlassian products.
December 15, 2022

@Christian Lämmerer @Stig Grafsrønningen @Guido Grygiel Just give you an update.We've recently released the cloud version for our floating table of contents macro, you can give a try if you were interested in: https://marketplace.atlassian.com/apps/1221271/?hosting=cloud

0 votes
Alan Old August 13, 2019

@Davin Studer 

I'm a space admin but I can't see specifically where I should be creating the CSS Class.  I can navigate to this area @"Space Tools / Look and Feel / Style Sheet"

but I only see an option to create a CSS stylesheet and nothing about custom html

 

The above looks like it will effect the whole space.  If you have any guidance or link to a good article on how to create custom CSS classes that would be very useful

 

Many thanks.

Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
August 19, 2019

The custom html portion is in Confluence Admin -> Look and Feel -> Custom HTML. This would only affect TOC macros with fixedPosition put in the CSS Class Name attribute.

Like # people like this
Alan Old August 20, 2019

Thanks David.  I've tested this in our dev instance it works well so many thanks for the initial post and follow up to my question.

We do have a custom banner at the top of all our pages that seems to impact the overall UX including this CSS stylesheet.  because of the banner, when navigating using the fixed position TOC the heading selected is always just off the top of the page.  Is there an easy way to adjust for that in the stylesheet?

0 votes
Rodrigo Teixeira March 24, 2019

@roman_baeriswyl Assuming my URL is https://test.atlassian.net, how would that reflect on the script after the changes? I can't make it to work? Should we include the space destination URL as well?

Abhir Joshi April 22, 2019

Modify @match in the comment as follows:

// @match        https://test.atlassian.net/*

Note the '*' at the end of the URL.

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events