1*8c35d5eeSXin LiTocTypeEnum = { 2*8c35d5eeSXin Li VERTICAL: 1, 3*8c35d5eeSXin Li HORIZONTAL: 2 4*8c35d5eeSXin Li}; 5*8c35d5eeSXin Li 6*8c35d5eeSXin Lifunction CreateTOC(tocElement) { 7*8c35d5eeSXin Li 8*8c35d5eeSXin Li // Find the toc element DIV. We'll place our TOC there. 9*8c35d5eeSXin Li var toc = document.getElementById(tocElement); 10*8c35d5eeSXin Li 11*8c35d5eeSXin Li var tocTypeClass = toc.className; 12*8c35d5eeSXin Li var tocType; 13*8c35d5eeSXin Li 14*8c35d5eeSXin Li switch (tocTypeClass) { 15*8c35d5eeSXin Li case 'horizontal_toc': 16*8c35d5eeSXin Li tocType = TocTypeEnum.HORIZONTAL; 17*8c35d5eeSXin Li break; 18*8c35d5eeSXin Li case 'vertical_toc': 19*8c35d5eeSXin Li tocType = TocTypeEnum.VERTICAL; 20*8c35d5eeSXin Li break; 21*8c35d5eeSXin Li default: 22*8c35d5eeSXin Li tocType = TocTypeEnum.VERTICAL; 23*8c35d5eeSXin Li break; 24*8c35d5eeSXin Li } 25*8c35d5eeSXin Li 26*8c35d5eeSXin Li // If toc_levels is defined, set headingLevels to it. 27*8c35d5eeSXin Li // Otherwise, use default value of "h2,h3" 28*8c35d5eeSXin Li var headingLevels; 29*8c35d5eeSXin Li if (typeof toc_levels === 'undefined') { 30*8c35d5eeSXin Li headingLevels = 'h2,h3'; 31*8c35d5eeSXin Li } else { 32*8c35d5eeSXin Li 33*8c35d5eeSXin Li } 34*8c35d5eeSXin Li 35*8c35d5eeSXin Li // Collect all section heading elements in an array 36*8c35d5eeSXin Li var headings = document.querySelectorAll(headingLevels); 37*8c35d5eeSXin Li 38*8c35d5eeSXin Li // Add TOC title elements 39*8c35d5eeSXin Li var tocHeadingDiv = document.createElement('div'); 40*8c35d5eeSXin Li toc.appendChild(tocHeadingDiv); 41*8c35d5eeSXin Li tocHeadingDiv.className = 'toc_title'; 42*8c35d5eeSXin Li var tocHeading = document.createElement('h3'); 43*8c35d5eeSXin Li toc.appendChild(tocHeading); 44*8c35d5eeSXin Li tocHeading.className = 'ignoreLink'; 45*8c35d5eeSXin Li tocHeading.id = 'toc'; 46*8c35d5eeSXin Li var tocText = document.createTextNode('Table of Contents'); 47*8c35d5eeSXin Li tocHeading.appendChild(tocText); 48*8c35d5eeSXin Li 49*8c35d5eeSXin Li // Add table and tbody 50*8c35d5eeSXin Li var tocTable = document.createElement('table'); 51*8c35d5eeSXin Li if (tocType == TocTypeEnum.VERTICAL) { 52*8c35d5eeSXin Li tocTable.className = 'columns'; 53*8c35d5eeSXin Li } 54*8c35d5eeSXin Li toc.appendChild(tocTable); 55*8c35d5eeSXin Li 56*8c35d5eeSXin Li var tbody_element = document.createElement('tbody'); 57*8c35d5eeSXin Li tbody_element.setAttribute('valign', 'top'); 58*8c35d5eeSXin Li tbody_element.className = 'toc'; 59*8c35d5eeSXin Li tocTable.appendChild(tbody_element); 60*8c35d5eeSXin Li 61*8c35d5eeSXin Li // Get the highest level heading 62*8c35d5eeSXin Li var firstHeading = headings[0]; 63*8c35d5eeSXin Li var masterLevel = parseInt(headingLevels.charAt(1)); 64*8c35d5eeSXin Li 65*8c35d5eeSXin Li // Get the lowest heading level 66*8c35d5eeSXin Li var lowestLevel = parseInt(headingLevels.charAt(headingLevels - 1)); 67*8c35d5eeSXin Li 68*8c35d5eeSXin Li switch (tocType) { 69*8c35d5eeSXin Li case TocTypeEnum.HORIZONTAL: 70*8c35d5eeSXin Li CreateHorizontalTOC(headings, masterLevel, lowestLevel, tbody_element); 71*8c35d5eeSXin Li break; 72*8c35d5eeSXin Li case TocTypeEnum.VERTICAL: 73*8c35d5eeSXin Li CreateVerticalTOC(headings, masterLevel, lowestLevel, tbody_element); 74*8c35d5eeSXin Li break; 75*8c35d5eeSXin Li default: 76*8c35d5eeSXin Li } 77*8c35d5eeSXin Li} 78*8c35d5eeSXin Li 79*8c35d5eeSXin Lifunction CreateHorizontalTOC( 80*8c35d5eeSXin Li headings, masterLevel, lowestLevel, tbody_element) { 81*8c35d5eeSXin Li 82*8c35d5eeSXin Li // Initialize the header counter 83*8c35d5eeSXin Li var h = 0; 84*8c35d5eeSXin Li var ignoreChildren = false; 85*8c35d5eeSXin Li 86*8c35d5eeSXin Li while (h < headings.length) { 87*8c35d5eeSXin Li // Get current heading 88*8c35d5eeSXin Li var heading = headings[h]; 89*8c35d5eeSXin Li 90*8c35d5eeSXin Li // Get the current heading level 91*8c35d5eeSXin Li var level = parseInt(heading.tagName.charAt(1)); 92*8c35d5eeSXin Li 93*8c35d5eeSXin Li if (isNaN(level) || level < 1 || level > lowestLevel) continue; 94*8c35d5eeSXin Li 95*8c35d5eeSXin Li // If level is a masterLevel, make it a TOC parent category 96*8c35d5eeSXin Li if ((level == masterLevel) && (!hasClass(heading, 'ignoreLink'))) { 97*8c35d5eeSXin Li toc_current_row = AddTOCMaster(tbody_element, heading); 98*8c35d5eeSXin Li ignoreChildren = false; 99*8c35d5eeSXin Li } 100*8c35d5eeSXin Li 101*8c35d5eeSXin Li if ((level == masterLevel) && (hasClass(heading, 'ignoreLink'))) { 102*8c35d5eeSXin Li ignoreChildren = true; 103*8c35d5eeSXin Li } 104*8c35d5eeSXin Li 105*8c35d5eeSXin Li if ((level != masterLevel) && (!ignoreChildren)) { 106*8c35d5eeSXin Li AddTOCElements(toc_current_row, heading); 107*8c35d5eeSXin Li } 108*8c35d5eeSXin Li 109*8c35d5eeSXin Li // Advance the header counter 110*8c35d5eeSXin Li h++; 111*8c35d5eeSXin Li } 112*8c35d5eeSXin Li} 113*8c35d5eeSXin Li 114*8c35d5eeSXin Li// Adds a master Table of Content heading 115*8c35d5eeSXin Lifunction AddTOCMaster(tocTable, heading) { 116*8c35d5eeSXin Li 117*8c35d5eeSXin Li // Add the table row scaffolding 118*8c35d5eeSXin Li var toc_tr = document.createElement('tr'); 119*8c35d5eeSXin Li tocTable.appendChild(toc_tr); 120*8c35d5eeSXin Li toc_tr.setAttribute('valign', 'top'); 121*8c35d5eeSXin Li var toc_tr_td = document.createElement('td'); 122*8c35d5eeSXin Li toc_tr.appendChild(toc_tr_td); 123*8c35d5eeSXin Li var toc_category = document.createElement('div'); 124*8c35d5eeSXin Li toc_tr_td.appendChild(toc_category); 125*8c35d5eeSXin Li toc_category.className = 'toc_category'; 126*8c35d5eeSXin Li 127*8c35d5eeSXin Li // Create the link to this header 128*8c35d5eeSXin Li var link = document.createElement('a'); 129*8c35d5eeSXin Li link.href = '#' + heading.id; // Create the anchor link 130*8c35d5eeSXin Li link.textContent = heading.textContent; // Link text is same as heading 131*8c35d5eeSXin Li toc_category.appendChild(link); 132*8c35d5eeSXin Li 133*8c35d5eeSXin Li // Add the container table cell for its children 134*8c35d5eeSXin Li var toc_td = document.createElement('td'); 135*8c35d5eeSXin Li toc_tr.appendChild(toc_td); 136*8c35d5eeSXin Li var toc_td_div = document.createElement('div'); 137*8c35d5eeSXin Li toc_td_div.className = 'toc_stylepoint'; 138*8c35d5eeSXin Li toc_td.appendChild(toc_td_div); 139*8c35d5eeSXin Li 140*8c35d5eeSXin Li return (toc_td_div); 141*8c35d5eeSXin Li} 142*8c35d5eeSXin Li 143*8c35d5eeSXin Li// Adds Table of Contents element to a master heading as children 144*8c35d5eeSXin Lifunction AddTOCElements(toc_div, heading) { 145*8c35d5eeSXin Li 146*8c35d5eeSXin Li if (heading.offsetParent === null) { 147*8c35d5eeSXin Li // The element is currently hidden, so don't create a TOC entry 148*8c35d5eeSXin Li } else { 149*8c35d5eeSXin Li // Create the list item element 150*8c35d5eeSXin Li var toc_list_element = document.createElement('li'); 151*8c35d5eeSXin Li toc_list_element.className = 'toc_entry'; 152*8c35d5eeSXin Li toc_div.appendChild(toc_list_element); 153*8c35d5eeSXin Li 154*8c35d5eeSXin Li // Create the link to this header 155*8c35d5eeSXin Li var link = document.createElement('a'); 156*8c35d5eeSXin Li link.href = '#' + heading.id; // Create the anchor link 157*8c35d5eeSXin Li link.textContent = heading.textContent; // Link text is same as heading 158*8c35d5eeSXin Li toc_list_element.appendChild(link); 159*8c35d5eeSXin Li } 160*8c35d5eeSXin Li} 161*8c35d5eeSXin Li 162*8c35d5eeSXin Lifunction CreateVerticalTOC(headings, masterLevel, lowestLevel, tbody_element) { 163*8c35d5eeSXin Li 164*8c35d5eeSXin Li // Create the Column scaffolding 165*8c35d5eeSXin Li var toc_tr = document.createElement('tr'); 166*8c35d5eeSXin Li tbody_element.appendChild(toc_tr); 167*8c35d5eeSXin Li var toc_tr_td = document.createElement('td'); 168*8c35d5eeSXin Li toc_tr_td.className = 'two_columns'; 169*8c35d5eeSXin Li toc_tr.appendChild(toc_tr_td); 170*8c35d5eeSXin Li 171*8c35d5eeSXin Li 172*8c35d5eeSXin Li // Initialize the header counter and the current row 173*8c35d5eeSXin Li var h = 0; 174*8c35d5eeSXin Li var toc_current_col = null; 175*8c35d5eeSXin Li var ignoreChildren = false; 176*8c35d5eeSXin Li 177*8c35d5eeSXin Li while (h < headings.length) { 178*8c35d5eeSXin Li // Get current heading 179*8c35d5eeSXin Li var heading = headings[h]; 180*8c35d5eeSXin Li 181*8c35d5eeSXin Li // Get the current heading level 182*8c35d5eeSXin Li var level = parseInt(heading.tagName.charAt(1)); 183*8c35d5eeSXin Li 184*8c35d5eeSXin Li if (isNaN(level) || level < 1 || level > lowestLevel) continue; 185*8c35d5eeSXin Li 186*8c35d5eeSXin Li // If level is a masterLevel, make it a TOC parent category 187*8c35d5eeSXin Li if ((level == masterLevel) && (!hasClass(heading, 'ignoreLink'))) { 188*8c35d5eeSXin Li if (heading.offsetParent === null) { 189*8c35d5eeSXin Li // The element is currently hidden, so don't create a TOC entry 190*8c35d5eeSXin Li } else { 191*8c35d5eeSXin Li var td_dl = document.createElement('dl'); 192*8c35d5eeSXin Li toc_tr_td.appendChild(td_dl); 193*8c35d5eeSXin Li var td_dt = document.createElement('dt'); 194*8c35d5eeSXin Li td_dl.appendChild(td_dt); 195*8c35d5eeSXin Li toc_current_col = td_dl; 196*8c35d5eeSXin Li 197*8c35d5eeSXin Li // Create the link to this header 198*8c35d5eeSXin Li var link = document.createElement('a'); 199*8c35d5eeSXin Li link.href = '#' + heading.id; // Create the anchor link 200*8c35d5eeSXin Li link.textContent = heading.textContent; // Link text is same as heading 201*8c35d5eeSXin Li td_dt.appendChild(link); 202*8c35d5eeSXin Li ignoreChildren = false; 203*8c35d5eeSXin Li } 204*8c35d5eeSXin Li } 205*8c35d5eeSXin Li 206*8c35d5eeSXin Li // If level is a masterLevel but it's specified to ignore links, skip it 207*8c35d5eeSXin Li // and its children. 208*8c35d5eeSXin Li if ((level == masterLevel) && (hasClass(heading, 'ignoreLink'))) { 209*8c35d5eeSXin Li ignoreChildren = true; 210*8c35d5eeSXin Li } 211*8c35d5eeSXin Li 212*8c35d5eeSXin Li if ((level != masterLevel) && (!ignoreChildren)) { 213*8c35d5eeSXin Li if (heading.offsetParent === null) { 214*8c35d5eeSXin Li // The element is currently hidden, so don't create a TOC entry 215*8c35d5eeSXin Li } else { 216*8c35d5eeSXin Li var td_dd = document.createElement('dd'); 217*8c35d5eeSXin Li toc_current_col.appendChild(td_dd); 218*8c35d5eeSXin Li // Create the link to this header 219*8c35d5eeSXin Li var link = document.createElement('a'); 220*8c35d5eeSXin Li link.href = '#' + heading.id; // Create the anchor link 221*8c35d5eeSXin Li link.textContent = heading.textContent; // Link text is same as heading 222*8c35d5eeSXin Li td_dd.appendChild(link); 223*8c35d5eeSXin Li } 224*8c35d5eeSXin Li } 225*8c35d5eeSXin Li 226*8c35d5eeSXin Li // Advance the header counter 227*8c35d5eeSXin Li h++; 228*8c35d5eeSXin Li } 229*8c35d5eeSXin Li} 230*8c35d5eeSXin Li 231*8c35d5eeSXin Li/* 232*8c35d5eeSXin Li * Utility function for finding elements with a given 233*8c35d5eeSXin Li * class. 234*8c35d5eeSXin Li */ 235*8c35d5eeSXin Lifunction hasClass(element, cls) { 236*8c35d5eeSXin Li return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1; 237*8c35d5eeSXin Li} 238*8c35d5eeSXin Li 239*8c35d5eeSXin Li/* 240*8c35d5eeSXin Li * Linkify all h2 through h4 headers, except for those marked 241*8c35d5eeSXin Li * "ignoreLink" 242*8c35d5eeSXin Li */ 243*8c35d5eeSXin Li 244*8c35d5eeSXin Li// Add the link image to the element. 245*8c35d5eeSXin Lifunction LinkifyHeader(header, fileName, sizePixels) { 246*8c35d5eeSXin Li var link = document.createElement('a'); 247*8c35d5eeSXin Li link.href = '#' + header.id; 248*8c35d5eeSXin Li link.setAttribute('alt', 'link to ' + header.id); 249*8c35d5eeSXin Li link.innerHTML = 250*8c35d5eeSXin Li '<img src="include/' + fileName + '"' + 251*8c35d5eeSXin Li ' width=' + sizePixels + 252*8c35d5eeSXin Li ' height=' + sizePixels + 253*8c35d5eeSXin Li ' style="float:left;position:relative;bottom:5px;">'; 254*8c35d5eeSXin Li header.appendChild(link); 255*8c35d5eeSXin Li} 256*8c35d5eeSXin Li 257*8c35d5eeSXin Li// Find all elements of the given tag and linkify if 258*8c35d5eeSXin Li// they don't have 'ignoreLink' in their class. 259*8c35d5eeSXin Lifunction LinkifyHeadersForTag(tagName) { 260*8c35d5eeSXin Li var headers = document.getElementsByTagName(tagName); 261*8c35d5eeSXin Li var header; 262*8c35d5eeSXin Li for (var j = 0; j != headers.length; j++) { 263*8c35d5eeSXin Li header = headers[j]; 264*8c35d5eeSXin Li if (!hasClass(header, 'ignoreLink') && ('id' in header)) { 265*8c35d5eeSXin Li if (header.id != '') { 266*8c35d5eeSXin Li LinkifyHeader(header, 'link.png', 21); 267*8c35d5eeSXin Li header.style.left = '-46px'; 268*8c35d5eeSXin Li header.style.position = 'relative'; 269*8c35d5eeSXin Li } 270*8c35d5eeSXin Li } 271*8c35d5eeSXin Li } 272*8c35d5eeSXin Li} 273*8c35d5eeSXin Li 274*8c35d5eeSXin Li// Linkify all h2, h3, and h4s. h1s are titles. 275*8c35d5eeSXin Lifunction LinkifyHeaders() { 276*8c35d5eeSXin Li LinkifyHeadersForTag('h2'); 277*8c35d5eeSXin Li LinkifyHeadersForTag('h3'); 278*8c35d5eeSXin Li LinkifyHeadersForTag('h4'); 279*8c35d5eeSXin Li} 280*8c35d5eeSXin Li 281*8c35d5eeSXin Li/* 282*8c35d5eeSXin Li * Initialize the style guide by showing all internal 283*8c35d5eeSXin Li * elements and then linkifying the headers. 284*8c35d5eeSXin Li */ 285*8c35d5eeSXin Li 286*8c35d5eeSXin Lifunction initStyleGuide() { 287*8c35d5eeSXin Li LinkifyHeaders(); 288*8c35d5eeSXin Li CreateTOC('tocDiv'); 289*8c35d5eeSXin Li} 290