{"id":305,"date":"2012-12-09T19:55:11","date_gmt":"2012-12-09T19:55:11","guid":{"rendered":"http:\/\/tregner.com\/flare-blog\/?p=305"},"modified":"2012-12-09T19:55:30","modified_gmt":"2012-12-09T19:55:30","slug":"sorting-tocs-in-and-output-with-javascript","status":"publish","type":"post","link":"https:\/\/tregner.com\/flare-blog\/sorting-tocs-in-and-output-with-javascript\/","title":{"rendered":"Sorting TOCs in an Output with JavaScript"},"content":{"rendered":"<p>Having discussed\u00a0<a title=\"sorting TOCs in a project\" href=\"https:\/\/tregner.com\/flare-blog\/sorting-tocs-in-a-project\/\" target=\"_blank\">sorting TOCs in a project<\/a> before a build, let\u2019s look at sorting a TOC in an HTML5 target output with JavaScript.<\/p>\n<p>I\u2019m using Google Chrome to test the JavaScript on the <a title=\"online help files for MadCap Flare version 8\" href=\"http:\/\/webhelp.madcapsoftware.com\/flare8\/Default.htm\" target=\"_blank\">online help files for MadCap Flare version 8<\/a>. Please note that I am using Flare online help because it is a\u00a0recognizable, high quality HTML5 output. I don&#8217;t work for MadCap Software or have any involvement with that help file.<\/p>\n<p>In the screen shot, notice the unordered list for the TOC is being inspected with the developer tools in Chrome. To bring up these tools, right-click somewhere on a page displayed in Chrome and select <strong>Inspect element<\/strong>.<\/p>\n<figure id=\"attachment_310\" aria-describedby=\"caption-attachment-310\" style=\"width: 628px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/toc-node-in-chrome1.png\"><img loading=\"lazy\" class=\"size-full wp-image-310   \" title=\"toc-node-in-chrome\" src=\"https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/toc-node-in-chrome1.png\" alt=\"TOC tree in Google Chrome\" width=\"628\" height=\"441\" srcset=\"https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/toc-node-in-chrome1.png 628w, https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/toc-node-in-chrome1-300x210.png 300w, https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/toc-node-in-chrome1-624x438.png 624w\" sizes=\"(max-width: 628px) 100vw, 628px\" \/><\/a><figcaption id=\"caption-attachment-310\" class=\"wp-caption-text\">TOC tree in Google Chrome<\/figcaption><\/figure>\n<p>The unordered list has a class value of \u201ctree\u201d (ul.tree). The children are list items (li) and the class varies depending on the state of the node and the position in the tree. For example, the skin changes the class value when the node is selected. In the next image, the <em>Welcome<\/em> topic is selected. Notice the value is:<\/p>\n<p>tree-node tree-node-leaf tree-node-selected<\/p>\n<figure id=\"attachment_312\" aria-describedby=\"caption-attachment-312\" style=\"width: 628px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/toc-tree-node-leaf-in-chrome.png\"><img loading=\"lazy\" class=\"size-full wp-image-312\" title=\"toc-tree-node-leaf-in-chrome\" src=\"https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/toc-tree-node-leaf-in-chrome.png\" alt=\"TOC tree node in Google Chrome\" width=\"628\" height=\"441\" srcset=\"https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/toc-tree-node-leaf-in-chrome.png 628w, https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/toc-tree-node-leaf-in-chrome-300x210.png 300w, https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/toc-tree-node-leaf-in-chrome-624x438.png 624w\" sizes=\"(max-width: 628px) 100vw, 628px\" \/><\/a><figcaption id=\"caption-attachment-312\" class=\"wp-caption-text\">TOC tree node in Google Chrome<\/figcaption><\/figure>\n<p>For this post, only the top nodes will be sorted. To test getting those, JavaScript can be executed from the <strong>Console<\/strong> which is the option on the far right of the developer tools. This will retrieve the child nodes of the first ul.tree element on the page:<\/p>\n<pre>document.getElementsByClassName(\"tree\")[0].childNodes<\/pre>\n<p>In the next screen shot, this has been executed.<\/p>\n<figure id=\"attachment_316\" aria-describedby=\"caption-attachment-316\" style=\"width: 628px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/child-nodes-of-tree-retrieved-with-javascript.png\"><img loading=\"lazy\" class=\"size-full wp-image-316\" title=\"child-nodes-of-tree-retrieved-with-javascript\" src=\"https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/child-nodes-of-tree-retrieved-with-javascript.png\" alt=\"child nodes of TOC tree retrieved with JavaScript\" width=\"628\" height=\"441\" srcset=\"https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/child-nodes-of-tree-retrieved-with-javascript.png 628w, https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/child-nodes-of-tree-retrieved-with-javascript-300x210.png 300w, https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/child-nodes-of-tree-retrieved-with-javascript-624x438.png 624w\" sizes=\"(max-width: 628px) 100vw, 628px\" \/><\/a><figcaption id=\"caption-attachment-316\" class=\"wp-caption-text\">Child nodes of TOC tree retrieved with JavaScript<\/figcaption><\/figure>\n<p>The result can be assigned to an array and sorted. Once sorted, the content of the list items can be replaced with the sorted content. But the class for the li elements must also be changed. Not only does that class change dynamically when you select the entry but the class varies depending on placement in the tree. To be safe, the class name should also convey.<\/p>\n<p>Rather than multidimensional arrays, JavaScript allows for arrays of objects or arrays of arrays. To keep the class value and the inner HTML together, an array of objects can be used. The sort will be performed on the text of the label. The label text appears as the third descendant of the list item. But there is no other text so it can be taken from the list item itself. Here is a good discussion on Stack Overflow: <a href=\"http:\/\/stackoverflow.com\/questions\/2808926\/javascript-multidimensional-arrays\">http:\/\/stackoverflow.com\/questions\/2808926\/javascript-multidimensional-arrays<\/a>.<\/p>\n<p>For basics about JavaScript arrays:\u00a0<a title=\"w3schools.com JavaScript Array Object tutorial\" href=\"http:\/\/www.w3schools.com\/js\/js_obj_array.asp\" target=\"_blank\">w3schools.com JavaScript Array Object tutorial<\/a><\/p>\n<p>Since the sort is to be performed on an array of objects, a sort function must be specified. This is a good explanation: <a href=\"http:\/\/www.javascriptkit.com\/javatutors\/arraysort2.shtml\">http:\/\/www.javascriptkit.com\/javatutors\/arraysort2.shtml<\/a>. In addition to placing the inner HTML and the class for the node in an array, the label text from the inner HTML is pulled as as a separate piece. The sort is based on the label text. This makes it easier to identify. Otherwise the script would have to drill in to the inner HTML for each node during the sort.<\/p>\n<p>Here is the the code:<\/p>\n<pre class=\"lang:js decode:true\" title=\"TOC top nodes JavaScript sort\">var topNodes = document.getElementsByClassName(\"tree\")[0].childNodes;\r\nvar nodeHtmlAndClasses = [];\r\n\r\nfor (var i = 0, l = topNodes.length; i &lt; l; i++) {\r\n    var nodeHtmlAndClass = { iH: topNodes[i].innerHTML, cN: topNodes[i].className, lbl: topNodes[i].textContent };\r\n    nodeHtmlAndClasses.push(nodeHtmlAndClass);\r\n}\r\n\r\nnodeHtmlAndClasses.sort(function (a, b) {\r\n    var labelA = a.lbl.toLowerCase(), labelB = b.lbl.toLowerCase()\r\n    if (labelA &lt; labelB)\r\n        return -1\r\n    if (labelA &gt; labelB)\r\n        return 1\r\n    return 0\r\n});\r\n\r\nfor (var i = 0, l = topNodes.length; i &lt; l; i++) {\r\n    topNodes[i].innerHTML = nodeHtmlAndClasses[i][\"iH\"];\r\n    topNodes[i].className = nodeHtmlAndClasses[i][\"cN\"];\r\n}<\/pre>\n<p>To test, you can open an HTML5 output and execute the copied code from the developer tools in a browser. Here is the TOC before:<\/p>\n<figure id=\"attachment_320\" aria-describedby=\"caption-attachment-320\" style=\"width: 543px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/toc-before.png\"><img loading=\"lazy\" class=\"size-full wp-image-320\" title=\"toc-before\" src=\"https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/toc-before.png\" alt=\"TOC before sorting with a JavaScript\" width=\"543\" height=\"735\" srcset=\"https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/toc-before.png 543w, https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/toc-before-221x300.png 221w\" sizes=\"(max-width: 543px) 100vw, 543px\" \/><\/a><figcaption id=\"caption-attachment-320\" class=\"wp-caption-text\">TOC before sorting with a JavaScript<\/figcaption><\/figure>\n<p>And here is the TOC in alphabetical order after executing the JavaScript:<\/p>\n<figure id=\"attachment_321\" aria-describedby=\"caption-attachment-321\" style=\"width: 543px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/toc-after.png\"><img loading=\"lazy\" class=\"size-full wp-image-321\" title=\"toc-after\" src=\"https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/toc-after.png\" alt=\"TOC after sorting with a JavaScript\" width=\"543\" height=\"735\" srcset=\"https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/toc-after.png 543w, https:\/\/tregner.com\/flare-blog\/wp-content\/uploads\/2012\/12\/toc-after-221x300.png 221w\" sizes=\"(max-width: 543px) 100vw, 543px\" \/><\/a><figcaption id=\"caption-attachment-321\" class=\"wp-caption-text\">TOC after sorting with a JavaScript<\/figcaption><\/figure>\n<p>What next?<\/p>\n<p>You can add this script to a function and configure a toolbar button to execute it when clicked. MadCap Software has recently posted instructions about how to do that:<\/p>\n<p><a title=\"Adding Custom Buttons to HTML5 (and WebHelp) Outputs\" href=\"http:\/\/www.madcapsoftware.com\/blog\/2012\/12\/04\/adding-custom-buttons-to-html5-and-webhelp-outputs\/\" target=\"_blank\">Adding Custom Buttons to HTML5 (and WebHelp) Outputs<\/a><\/p>\n<p>It would also be nice to script the return to the original order or to script flattening or sorting at each level as was described in the previous post. But I&#8217;ll end this post with an appeal for comments about what kinds of sorting would be useful in Flare HTML5 outputs. The spam system on this blog has been changed. If you don&#8217;t see you comment published, please email info@tregner.com so I can track your comment down.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Having discussed\u00a0sorting TOCs in a project before a build, let\u2019s look at sorting a TOC in an HTML5 target output with JavaScript. I\u2019m using Google Chrome to test the JavaScript on the online help files for MadCap Flare version 8. Please note that I am using Flare online help because it is a\u00a0recognizable, high quality&hellip; <a class=\"more-link\" href=\"https:\/\/tregner.com\/flare-blog\/sorting-tocs-in-and-output-with-javascript\/\">Continue reading <span class=\"screen-reader-text\">Sorting TOCs in an Output with JavaScript<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[4],"tags":[],"_links":{"self":[{"href":"https:\/\/tregner.com\/flare-blog\/wp-json\/wp\/v2\/posts\/305"}],"collection":[{"href":"https:\/\/tregner.com\/flare-blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tregner.com\/flare-blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tregner.com\/flare-blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tregner.com\/flare-blog\/wp-json\/wp\/v2\/comments?post=305"}],"version-history":[{"count":16,"href":"https:\/\/tregner.com\/flare-blog\/wp-json\/wp\/v2\/posts\/305\/revisions"}],"predecessor-version":[{"id":327,"href":"https:\/\/tregner.com\/flare-blog\/wp-json\/wp\/v2\/posts\/305\/revisions\/327"}],"wp:attachment":[{"href":"https:\/\/tregner.com\/flare-blog\/wp-json\/wp\/v2\/media?parent=305"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tregner.com\/flare-blog\/wp-json\/wp\/v2\/categories?post=305"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tregner.com\/flare-blog\/wp-json\/wp\/v2\/tags?post=305"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}