Mini TOC that lists sub-headings in a single topic

This forum is for all Flare issues related to the HTML5, WebHelp, WebHelp Plus, and Adobe Air Targets
Post Reply
MattG
Propeller Head
Posts: 16
Joined: Fri Jan 08, 2010 5:01 am

Mini TOC that lists sub-headings in a single topic

Post by MattG »

In WebHelp output, is it possible to create some kind of mini-TOC at the beginning of a topic that lists all the sub-headings in that topic? Something along the lines of:

Code: Select all

This topic contains:
  - something
  - something else
  - yet another thing
I can create all this by hand, of course, but it's pretty time consuming. If there's an automatic way to do it then I'd love to know.

In case this is relevant, my topics all start with an H1 or H2 title. This is followed by a number of small sections, each of which has an H3 heading.

Matt
Andrew
Propellus Maximus
Posts: 1237
Joined: Fri Feb 10, 2006 5:37 am

Re: Mini TOC that lists sub-headings in a single topic

Post by Andrew »

I believe you can insert a mini-TOC in a master page and then apply the master page to your topic (or to all topics in a target).
Flare v6.1 | Capture 4.0.0
MattG
Propeller Head
Posts: 16
Joined: Fri Jan 08, 2010 5:01 am

Re: Mini TOC that lists sub-headings in a single topic

Post by MattG »

I've tried that but with no luck: what you suggested creates a mini-TOC that lists all topics that are below the mini-TOC in the TOC tree. At least, that's what happened when I tried it.

I'm looking for a way to list all the H3 headings in the same topic as a mini-TOC.
Andrew
Propellus Maximus
Posts: 1237
Joined: Fri Feb 10, 2006 5:37 am

Re: Mini TOC that lists sub-headings in a single topic

Post by Andrew »

MattG wrote:I've tried that but with no luck: what you suggested creates a mini-TOC that lists all topics that are below the mini-TOC in the TOC tree. At least, that's what happened when I tried it.

I'm looking for a way to list all the H3 headings in the same topic as a mini-TOC.
Ah, that makes sense. Yes, it would be nice to be able to create a mini TOC that would apply only to a topic.
Flare v6.1 | Capture 4.0.0
Nita Beck
Senior Propellus Maximus
Posts: 3669
Joined: Thu Feb 02, 2006 9:57 am
Location: Pittsford, NY

Re: Mini TOC that lists sub-headings in a single topic

Post by Nita Beck »

Matt, I don't believe that Flare provides for this particular use of miniTOCs. It's something that many of us would like to do also, exactly as you descirbe.

I suggest you add your voice to those of us who have requested this feature: http://www.madcapsoftware.com/bugs/submit.aspx
Nita
Image
RETIRED, but still fond of all the Flare friends I've made. See you around now and then!
MattG
Propeller Head
Posts: 16
Joined: Fri Jan 08, 2010 5:01 am

Re: Mini TOC that lists sub-headings in a single topic

Post by MattG »

Will do. Thanks, Nita.
DurtyMat
Sr. Propeller Head
Posts: 224
Joined: Wed Aug 22, 2007 8:09 am
Location: ClrH2o, Fl

Re: Mini TOC that lists sub-headings in a single topic

Post by DurtyMat »

this will solve your issue.

here is the link to the original source: http://www.the-art-of-web.com/javascript/buildmenu/

this is the javascript that needs to be saved to "buildmenu.js", made some minor changes, creates an UNordered list, doesn't put numbers in front of your headings, and uses h3s (not h2s like in the example)

Code: Select all

// Original JavaScript code by Chirp Internet: www.chirp.com.au
// Please acknowledge use of this code by including this header.

function buildMenu(target_id, heading_tag)
{
  // abort if using MSIE (Mac) or DHTML functions not present
  if(navigator.userAgent.indexOf("Mac_PowerPC") != -1) return;
  if(!document.createElement) return;

  // the element identified by target_id will contain the menu
  var target = document.getElementById(target_id);

  // scan the DOM for tags matching heading_tag (eg. 'H2')
  var headings = document.getElementsByTagName(heading_tag);

  if(headings.length > 1) {
    // found two or more headings - start building ordered list
    var menuList = document.createElement('UL');

    // for each heading on the page
    for(var i=0; i < headings.length; i++) {

      // use exising id or add new id to heading to use as anchor
      var anchorName = "section_" + i;
      if(headings[i].id == '') {
        headings[i].setAttribute('id', anchorName);
      } else {
        anchorName = headings[i].id;
      }

      // extract text from heading
      var headingText = headings[i].firstChild.nodeValue

      // prefix heading with number
      // headings[i].firstChild.nodeValue = (i+1) + ". " + headingText;

      // create link to heading
      var menuLink = document.createElement('A');
      menuLink.setAttribute('href', '#' + anchorName);
      menuLink.appendChild(document.createTextNode(headingText));

      // create list item to contain link
      var listItem = document.createElement('LI');
      listItem.appendChild(menuLink);

      // append list item to list
      menuList.appendChild(listItem);
    }

    // remove contents of target element
    while(target.hasChildNodes()) target.removeChild(target.firstChild);

    // insert list into target element
    target.appendChild(menuList);
  } else {
    // no headings found - remove target element from page
    target.parentNode.removeChild(target);
  }
}
add this inside the <head> of topics, this could be added to masterpages technically

Code: Select all

<script type="text/javascript" src="buildmenu.js"></script>
add this to the body tag, where h2 needs to be the heading level you want to use (in your case h3)

Code: Select all

<body onLoad="buildMenu('target_id', 'h2');">
or add this below the body tag (again h3 not h2)
<script type="text/javascript">
window.onload = function() { buildMenu('target_id', 'h2'); }
</script>

then add this to the body of your text where you want the list to appear, where "submenu" is the "target_id" found in the body or under-the-body scripts:
<div id="submenu" style="border: 2px solid blue;">building menu...</div>
<script type="text/javascript" src="/buildmenu.js"></script>
<script type="text/javascript">
function buildmenu_init() { buildMenu('submenu', 'h2'); }
var oldonload = window.onload;
if(typeof window.onload != 'function') {
window.onload = buildmenu_init;
} else {
window.onload = function() {
oldonload();
buildmenu_init();
}
}
</script>
Flare: I bought it ... so that means I can break it, right?
DurtyMat
Sr. Propeller Head
Posts: 224
Joined: Wed Aug 22, 2007 8:09 am
Location: ClrH2o, Fl

Re: Mini TOC that lists sub-headings in a single topic

Post by DurtyMat »

so hopefully that isnt too confusing, but it should solve your issues :D
Flare: I bought it ... so that means I can break it, right?
MattG
Propeller Head
Posts: 16
Joined: Fri Jan 08, 2010 5:01 am

Re: Mini TOC that lists sub-headings in a single topic

Post by MattG »

Ah! Excellent. That works a treat. I had to make a few alterations to make it Flare-compatible and I thought I'd pass these on.

IMPORTANT: on 27 August 2010 I edited the following so that it was compatible with Internet Explorer and not just Firefox. If you looked at this post beforehadn then you may want to revisit your code.
  • I created a snippet that contained all the code, including the scripts and the <div> tag that contains the menu. This way, I can just throw the snippet into any topic that I want to contain a submenu. Here's my snippet:

    Code: Select all

    <?xml version="1.0" encoding="utf-8"?>
    <html xmlns:MadCap="http://www.madcapsoftware.com/Schemas/MadCap.xsd" MadCap:lastBlockDepth="3" MadCap:lastHeight="80" MadCap:lastWidth="752">
        <body>
            <script type="text/javascript" src="buildMenu.js" />
            <script type="text/javascript">  
                function buildmenu_init() { buildMenu('submenu', 'h3'); } 
                var oldonload = window.onload; 
                if(typeof window.onload != 'function') { 
                    window.onload = buildmenu_init; 
                } else { 
                    window.onload = function() { 
                        oldonload(); buildmenu_init(); 
                    } 
                } 
            </script>
            <table class="inThisTopic">
                <tbody>
                    <tr>
                        <td>
                            <p>In this topic...</p>
                            <div id="submenu">building menu...</div>
                        </td>
                    </tr>
                </tbody>
            </table>
        </body>
    </html>
  • The submenu didn't work if a sub-heading contained a bookmark so I changed it slightly. Also, I apply the "table1" class to my list items; not essential but you might like to see how it's done.

    Here's my script, stored as buildMenu.js in the same directory as the snippet. That's very important: THE SNIPPET AND buildMenu.js GO INTO THE SAME DIRECTORY.

    Code: Select all

    // Original JavaScript code by Chirp Internet: www.chirp.com.au
    // Please acknowledge use of this code by including this header.
    
    function buildMenu(target_id, heading_tag)
    {
        // abort if using MSIE (Mac) or DHTML functions not present
        if(navigator.userAgent.indexOf("Mac_PowerPC") != -1) return;
        if(!document.createElement) return;
    
        // the element identified by target_id will contain the menu
        var target = document.getElementById(target_id);
    
        // scan the DOM for tags matching heading_tag (eg. 'H2')
        var headings = document.getElementsByTagName(heading_tag);
    
        if(headings.length > 1) {
            // found two or more headings - start building ordered list
            var menuList = document.createElement('UL');
    
            // for each heading on the page
            for(var i=0; i < headings.length; i++) {
    
                // use exising id or add new id to heading to use as anchor
                var anchorName = "section_" + i;
                if(headings[i].id == '') {
                headings[i].setAttribute('id', anchorName);
                } else {
                anchorName = headings[i].id;
                }
    
                // Extract text from heading.
    	
    			// MODIFICATION
                // In the original Chirp Internet code, this used firstChild instead
                // of lastChild. However, Flare sometime starts headings with a 
                // bookmark, so using lastChild means that the ignores the bookmark 
                // at the start of the heading.
    	
                var headingText = headings[i].lastChild.nodeValue
    
                // prefix heading with number
                // headings[i].lastChild.nodeValue = (i+1) + ". " + headingText;
    
                // create link to heading
                var menuLink = document.createElement('A');
                menuLink.setAttribute('href', '#' + anchorName);
                menuLink.appendChild(document.createTextNode(headingText));
    
                // create list item to contain link, set it's class 
                // and append it to the menu.
                var listItem = document.createElement('LI');
                listItem.setAttribute("class", "table1");
                listItem.appendChild(menuLink);
    
                // append list item to list
                menuList.appendChild(listItem);
            }
    
            // remove contents of target element
            while(target.hasChildNodes()) target.removeChild(target.firstChild);
    
            // insert list into target element
            target.appendChild(menuList);
            } else {
            // no headings found - remove target element from page
            target.parentNode.removeChild(target);
        }
    }
  • Now to insert a mini-TOC into any topic I simply insert my snippet.
FYI why did I modify the script? Well, Flare always puts bookmarks at the start of a heading. Hence if a heading is...

Code: Select all

<h3><a name="ThisIsABookmark"></a>Some Text</h3>
..then the line...

Code: Select all

var headingText = headings[i].firstChild.nodeValue
...picks up the bookmark instead of the text. This means that the resulting submenu is empty for this heading.

A rather crude workaround is to use the line...

Code: Select all

var headingText = headings[i].lastChild.nodeValue
...which picks up the text at the end of the heading rather then the bookmark at the beginning.

This still doesn't work with headings that contains any tags such as <b> <code> etc. In my case this isn't a problem but it might be any issue for others.
Last edited by MattG on Fri Oct 08, 2010 10:01 am, edited 1 time in total.
jcoria
Propeller Head
Posts: 83
Joined: Mon Oct 22, 2007 12:57 pm

Re: Mini TOC that lists sub-headings in a single topic

Post by jcoria »

I am having difficulty in getting this to work properly. Moreover, inserting the code. Using the html text editor in Flare keeps placing the span tags around everything...

What is the best method to bring in the JS file? Use windows explorer?

I really like this feature in RH, because it is so easy to setup and make useful as well as format. I have definitely put the request in for this feature.

Right now, we are at a turning point to go with Flare or stay with RH.

Any suggestions or walk through on inserting the code would be helpful.

Thank you.

JC
LTinker68
Master Propellus Maximus
Posts: 7247
Joined: Thu Feb 16, 2006 9:38 pm

Re: Mini TOC that lists sub-headings in a single topic

Post by LTinker68 »

You can't insert Javascript or any other type of code via the XML Editor (i.e., the authoring environment). Flare just treats it as normal content. After all, how does it know you're trying to insert code to be run as opposed to code to be read by the user?

To insert code, you have to open the topic in the Internal Text Editor. You can do so by opening the topic in the XML Editor and clicking the icon that opens the topic in the Internal Text Editor (sorry, I don't have Flare running, so I can't describe where the icon is located). You can also open it by right-clicking on a topic in the Content Explorer pane and selecting Open with > Internal Text Editor.

When you're viewing a topic in the Internal Text Editor you're interacting with the topic's content and its page code, so you can insert Javascript, refine the attributes of a specific tag, or enter more content, so long as it's properly encased in HTML tags. However, if you're new to modifying page code or HTML tags or anything else, you could make a copy of the topic before modifying its page code, because if you screw something up in the page code, then you may be unable to open the topic in the XML Editor and Flare will throw errors at you (most of which aren't that descriptive).
Image

Lisa
Eagles may soar, but weasels aren't sucked into jet engines.
Warning! Loose nut behind the keyboard.
jcoria
Propeller Head
Posts: 83
Joined: Mon Oct 22, 2007 12:57 pm

Re: Mini TOC that lists sub-headings in a single topic

Post by jcoria »

Thanks Lisa,

Here is the test topic I am trying: What am I doing wrong? Or can you not see the appropriate output in Preview mode?

Code: Select all

<?xml version="1.0" encoding="utf-8"?>
<html xmlns:MadCap="http://www.madcapsoftware.com/Schemas/MadCap.xsd" MadCap:lastBlockDepth="2" MadCap:lastHeight="383" MadCap:lastWidth="807">
    <head>
        <script type="text/javascript" src="buildmenu.js">
        </script>
    </head>
    <body>
		<body onLoad="buildMenu('target_id', 'h2');">
        <h1>testing topic</h1>
        <div id="submenu" style="border: 2px solid blue;">building menu...</div>
        <script type="text/javascript" src="/buildmenu.js">
        </script>
        <script type="text/javascript">
			function buildmenu_init() { buildMenu('submenu', 'h2'); }
			var oldonload = window.onload;
			if(typeof window.onload != 'function') {
			window.onload = buildmenu_init;
			} else {
			window.onload = function() {
			oldonload();
			buildmenu_init();
			}
			}
		</script>
        <h2>Delete this text and replace it with your own content.</h2>
        <h2>griddle</h2>
        <h2>Middle</h2>
        <h2>fiddle</h2>
        <h2>piddle</h2>
        <p> </p>
    </body>
	</body>
    </html>
LTinker68
Master Propellus Maximus
Posts: 7247
Joined: Thu Feb 16, 2006 9:38 pm

Re: Mini TOC that lists sub-headings in a single topic

Post by LTinker68 »

jcoria wrote:Or can you not see the appropriate output in Preview mode?
Probably not, since the Preview mode isn't a full browser. It used to be you couldn't even do some of the Flare effects in the Preview window or click on a link to test it, although most of that is supported now, I believe. Try building the output and see if it works.
Image

Lisa
Eagles may soar, but weasels aren't sucked into jet engines.
Warning! Loose nut behind the keyboard.
MattG
Propeller Head
Posts: 16
Joined: Fri Jan 08, 2010 5:01 am

Re: Mini TOC that lists sub-headings in a single topic

Post by MattG »

I think I've found your problem. I suspect that this line...

Code: Select all

<script type="text/javascript" src="/buildmenu.js">

...cannot find the file called buildmenu.js.

Firstly, remove the slash from src="/buildmenu.js".

Secondly, make sure that the buildmenu.js file in the same directory as the file containing <script type="text/javascript" src="/buildmenu.js">. This is probably rather inconvenient if you're calling buildmenu.js from lots of topics, which is why I suggest you:

1. put your mini-TOC into a snippet, including the <script type="text/javascript" src="/buildmenu.js">
2. store both the snippet and buildmenu.js in the same directory.
3. insert the snippet into the topics that contains your <h2> elements.

To tidy up, you can probably remove the script from the <head> element (because you're currently calling the script twice) and remove onLoad=... from your <body> element. In fact, you've got two <body> elements and one can be deleted; I've noticed this extra <body> tends to happen if you copy all of one topic and paste it into another.

Let us know how you get on.

Matt
Post Reply