How auto-generate a table of contents - javascript

I'm new to JavaScript, and for school I have to automatically make every <\h1> on my page generate into an "ol" with in every "li" a link to the place on my page where that header is placed so in the end I have a table of contents with links on every "li". So I should be able to just write text and not worry about the table of contents. Is there a way to do this without using too complixated code? And preferably not very long so I can understand it.
e.g.
<h1 id="h1-01">Title 1<\h1>
<h1 id="h1-02">Titel 2<\h1>
<h1 id="h1-03">Titel 3<\h1>
<h1 id="h1-04">Titel 4<\h1>
Make this generate like:
<ol>
<li>Title 1</li>
<li>Title 2</li>
<li>Title 3</li>
<li>Title 4</li>
</ol>
edit:
I don't want anyone to make all of my homework, this is just a tiny tiny part of the homework even. What I want to know is how do I make an organized list with list items in javascript without too complicated code. I already found a way to put every header text in a variable.
This is what I have
function generate(){
var titels = new Array();
for(var i = 1;i<10;i++){
var test = 'h1-0'+ i;
titels[i] = document.getElementById(test).textContent;
}
}
-->
</script>
The only problem is now that I have to make a list with these variables, but I haven't found anything usefull on the internet, everything that I've found uses Jquery ir is specific for someone's problem. I would also like a way to count the amount of headers I'm using but tthat's another question. Is it actually even possible to have code that gets literally implemented like I'm writing it?
like:
html.write("<ol>");
for(var i = 1, i<10,i++){
html.write("<il>" + titels[i] + "<\il>");
}
html.write("<\ol>")

I'm not going to do your homework, but will point you in a good direction.
Try building an object containing the id and the title of each entry. From there, you can use that object to build practically anything, including an ordered list.
Of course, you can hard-rewrite the h1 tags into list items, but that's just not the proper way to do it and not something you should learn from.

A start hint:
You could do it with the help of jquery.
Like this HTML:
<ol id=contents></ol>
<h1>Test</h1>
bla bla
<h1> Test2 </h1>
Ble ble ble
Jquery:
$(document).ready(function(){
$("h1").each(function(){
$("#contents").append("<li>" + $(this).html() + "</li>");
});
});

Related

Using Javascript to replace part of a <li> string removes <a> and <span> tags. How can I remove the text but not the tags?

I am using Zendesk Help Center but customizing it with JS so apologies if that makes this more difficult.
I have many (~2000) articles which begin with "KCS - " (for instance, KCS - How to Issue a Bill). I now want to remove that "KCS - " from all of the article titles. I successfully used the following code to remove the "KCS - " from those titles:
$('h1').each(function() {
var text = $(this).text();
$(this).text(text.replace('KCS - ', ''));
This works for the articles themselves, but the "KCS - " still appears in search results. I tried the following code to deal with that:
$('li').addClass('search-result').each(function() {
var text = $(this).text();
$(this).text(text.replace('KCS - ',''));
This does remove the "KCS - " but it also removed and tags and results in plain text instead of links appearing in the search results.
I've attached screenshots of the search result code before and after trying to remove the "KCS - ". If anyone has an idea of how I can remove the "KCS - " from the search results without breaking the rest of the code, I would be very grateful. Thanks for your time and thoughts.
Edit: I've posted the browser output as opposed to using screenshots.
Pre-Removal:
`
KCS - Documents: Adding New Files and Folders
<span class="search-result-votes">-1</span>
<div class="search-result-meta">by <a target="_zendesk_lotus" href="/access/return_to?return_to=https://clio1440180657.zendesk.com/agent/users/1229273507/tickets">Name Changed</a> <time datetime="2015-08-26T15:51:48Z" title="2015-08-26 07:51" data-datetime="relative">2 years ago</time> in Working with Clovis Documents > Working with Clovis Documents</div>
<div class="search-result-description">Creating a <em>New</em> Folder You can add a standalone folder from the "All <em>Files</em>" list or from within any other <em>document</em>...</div>
</li> `
Post-Removal
`
Documents: Adding New Files and Folders
-1
by *name changed* 2 years ago in Working with Clovis Documents > Working with Clovis Documents
Creating a New Folder You can add a standalone folder from the "All Files" list or from within any other document...
</li>
`
You are using the text() function on the entire HTML element, which destroys your html tags and converts the entire <div> to a string value.
Instead, target the <a> element inside the <li> like so:
$('li').addClass('search-result').find('a:first-child').each(function() {
var text = $(this).text();
$(this).text(text.replace('KCS - ',''));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>
KCS - This is a Search Result Item
<div>Result content...</div>
</li>
<li>
KCS - This is a Search Result Item
<div>Result content...</div>
</li>
<li>
KCS - This is a Search Result Item
<div>Result content...</div>
</li>
</ul>
Note: If you are confident that the <a>element (the link) is always the first child of the <li>, I suggest keeping this as-is, using the :first-child pseudo class.

Parsing structure/hierarchy of html and recreating it in a different form with javascript

I am trying to crawl some webpages with javascript to gather information about content's hierarchy. I'm using casperjs to do the crawling, that is working ok so far.
The information that I want to parse is structured like this:
<ul>
<a></a>
<li>
<h3>
<a>
Category
<span>Description for Category</span>
</a>
</h3>
<div>
<ul>
<li>
<a>SubCategory</a>
</li>
</ul>
</div>
</li>
</ul>
But what I want to end up with is this.
<ul>
<li>Category
<ul>
<li>SubCategory</li>
</ul>
</li>
</ul>
I want to use the above html in a different webpage, so basically I'll be writing it to a file from casperjs so that I can then copy paste it into another document. I'm crawling because it's a tedious thing to do manually (90 some pages and lots of data per page).
What's the best way to deconstruct/parse a hierarchy, and then recreate it? Stay within the DOM and restructure using JQuery? Pull it out into a tree structure and rebuild it later?
Please note that this is a particular solution and will only work for the specific layout of code that you provided:
I created a parser in jQuery that receives HTML markup in a textarea and converts it into the format that you are using:
$(function(){
$("button").click(function(){
//Read in HTML
$("#parser").html($("textarea").val());
//Parse
var categories = $("#parser > ul").find("li h3 a");
$(categories).find("span").remove();
//Output result
var output = "<ul>\n";
for(var i = 0; i < categories.length; i++)
{
//Get subcategories for this category
var subCategories = $($(categories[i])).closest("h3").siblings("div").find("ul li a");
//Add markup to output
output += "\t<li>" + minimize($($(categories[i])).html()) + "\n\t\t<ul>\n";
for(var j = 0; j < subCategories.length; j++)
{
output += "\t\t\t<li>"+$($(subCategories[j])).html() + "&lt/li>\n"
}
output += "\t\t</ul>\n\t</li>\n</ul>\n"
}
$("#result").html(output);
});
});
//Removes all white-space characters from the string.
function minimize(str)
{
return str.replace(/\s{2,}/g, '');
}
JSFiddle
It was a lot of work and is very customized. As I said earlier, if you look at the different selectors that are used here, this code is very tailored to this specific code layout.
Example:
var categories = $("#parser > ul").find("li h3 a");
This looks for a ul element just below parser that contains <a>s inside of <h3>s inside of <li>s to find the categories and then later uses
$($(categories[i])).closest("h3").siblings("div").find("ul li a");
which looks for an <h3> above the category <a> that has a sibling <div> with children <ul><li><a></a></li></ul>
So if the format is not this:
<ul>
<li>
<h3>
<a>Category</a>
</h3>
<div>
<ul>
<li>
<a>Subcategory</a>
</li>
</ul>
</div>
</li>
</ul>
It will not work.
I ended up going with this approach:
Scrape the tags from the existing website and assemble them into an array nested javascript object.
Writing them out with JSON.stringify to a file
Loading them into a new page as Javascript objects, and build the ul/li structure with a recursive function that traversed the javascript object.
I found it too hard to get my head around modifying the DOM as with the other answer(s). It was easier to break it down into multiple steps, with a well structured javascript object in the middle.

Inserting HTML into tag using JavaScript

I'm having a problem with JavaScript/jQuery at the moment where I'm trying to access the element inside the h4 element in my code. I'm doing this because I would like to dynamically display to the user how many guides are available in each "h4" section. For the PC section, it should display "4 reviews available" and for the Xbox One section, it should display "3 reviews available". However, both say " reviews available", and I'm assuming it's because I'm not using the jQuery functions properly. Here's the HTML code:
<h4><li class="console">PC (<span class="number"></span> reviews available)</li></h4>
<div class="gameList">
<ul>
<li class="game">Guide #1</li>
<li class="game">Guide #2</li>
<li class="game">Guide #3</li>
<li class="game">Guide #4</li>
</ul>
</div>
<h4><li class="console">Xbox One (<span class="number"></span> reviews available)</li></h4>
<div class="gameList">
<ul>
<li class="game">Guide #1</li>
<li class="game">Guide #2</li>
<li class="game">Guide #3</li>
</ul>
</div>
And here's the jQuery/JavaScript code:
$("h4").each(function() {
var node = $(this).children().children(); // gets node that has "number" class
var count = $(this).next().children().children().length; // gets number of li tags
node.innerHTML = count;
});
I tested whether or not it's properly getting the correct node and count by using the alert function for JavaScript, but for some reason, node.innerHTML = count won't display the contents of "content" properly in the element. Rather, it just displays a blank. Does anyone know why?
Its a jquery object not a DOM one..use this...
node.html(count);
node is a jQuery object here. It does not have "innerHTML". Instead you can use one of these:
node.html(count);
node.get(0).innerHTML = count;
node.get(0) will give you first DOM object from jQuery one.
A good practice is to prefix or suffix all jQuery objects with $ (e.g. $node), so that you will always know if a variable is meant to be a jQuery object.
use find() lot more cleaner and readable
$("h4").each(function() {
var $this=$(this);
var node = $this.find('.number');
var count = $this.next().find('li').length; // gets number of li tags
node.text(count); //or html()
});
and you have come invalid HTML li in h4 make sure you change that
working fiddle here
Do not use .children().children().
Only one .children() would do.
$(this).children('.game');
Also innerHTML is plain javascript. use .html(value) as node is JQuery Object.
$("h4").each(function() {
var node = $(this).children('.number');
var count = $(this).next().children('li').length;
node.html(count);
});
Reference to JQuery APIs:
.html()
.children()
$("h4").each(function() {
var $spanNumber = $('.console .number', this),
gameListCount = $(this).next().find('ul li').size();
$spanNumber.text(gameListCount)
});
You may use this also,
$("h4").each(function() {
var node = $(this).find('.number');
var count = $(this).next().find('.game').length;
node.html(count);
});

handlebars.js just stopped working?

I have an interesting problem. Ive had a handlebars.js template thats been working for a week and just stopped. I was hoping someone might have an idea as to why.
Heres the template
<script id="banners-template" type="text/x-handlebars-template">
<div class="banner-container" >
{{#banners}}
<ul class="banner" >
<li><div class="checkbox"></div></li>
<li>{{publisher_status}}</li>
<li>Test Link</li>
<li><img class="banner" src="{{imageurl}}"/></li>
<li>{{description}}</li>
<li>{{width}}x{{height}}</li>
</ul>
{{/banners}}
</div>
</script>
Heres the code that works with this.
var bannersRawTemplate = $("#banners-template").html();
var bannersTemplate = Handlebars.compile(bannersRawTemplate);
data = '{"banners":[{"type":"banner","width":125}]}';
alert(bannersTemplate(data));
I realize that type is not accessed in the template above but it shouldnt matter. I should still get the code inside of the "banners" array loop displayed once. This is not the case. The only part of the template that displays is . Its like its not seeing the banners array inside the JSON.
Any ideas?
Thanks in advance.
Is there a particular reason you don't pass in the actual JSON, and instead pass a string? From my experience with Mustache, and a cursory review of the Handlebars.js documentation, you should be passing:
JSON.parse('{"banners":[{"type":"banner","width":125}]}');
And, assuming the code you've shown is "really real", why not just:
{"banners":[{"type":"banner","width":125}]}
This is, of course, assuming that the issue really isn't that you've got a list with just one element.

Questions about $., .parent(node) and nodes in javascript

The following is a part of jstree, http://www.jstree.com/ code.
And I have a couple of questions about this javascript/jquery to ask. (actually pretty much all)
$('#pages-wrapper').tree({
callback:{
"onchange":function(node,tree){
document.location='pages.php?action=edit&id='+node.id.replace(/.*_/,'');
},
"onmove":function(node){
var p=$.tree.focused().parent(node);
var new_order=[],nodes=node.parentNode.childNodes;
for(var i=0;i<nodes.length;++i)new_order.push(nodes[i].id.replace(/.*_/,''));
$.getJSON('/ww.admin/pages/move_page.php?id='+node.id.replace(/.*_/,'')+
'&parent_id='+(p==-1?0:p[0].id.replace(/.*_/,''))+'&order='+new_order);
}
Q1. What $ in var p=$.tree is doing?
Q2. What is .parent(node) referencing to?
Q3. Is this line, var new_order=[],nodes=node.parentNode.childNodes; declearing two variables at the same time? And what is node.parentNode.childNodes doing?
Thanks in advance.
The followings are additional codes.
html is the following
<div id="pages-wrapper">
<ul>
<li id="page_24">
<ins> </ins>Home
</li>
<li id="page_25">
<ins> </ins>Second Page
</li>
<li id="page_30"><ins> </ins>Information
<ul>
<li id="page_31"><ins> </ins>Illustration</li>
</ul>
</li>
....
....
move_page.php
require '../admin_libs.php';// this one does all the db queries
$id=(int)$_REQUEST['id'];
$to=(int)$_REQUEST['parent_id'];
$order=explode(',',$_REQUEST['order']);
dbQuery("update pages set parent=$to where id=$id");
for($i=0;$i<count($order);++$i){
$pid=(int)$order[$i];
dbQuery("update pages set ord=$i where id=$pid");
echo "update pages set ord=$i where id=$pid\n";
}
What $ in var p=$.tree is doing?
$ is a helper object used by the popular javascript frameworks jQuery, prototype etc.
$.tree is referring to a extension tree which is defined somewhere.
What is .parent(node) referencing to?
Looks like it finds the parent node for of the currently selected node, to know the parentID which is passed to the php script. (You will need to let us know what the tree framework you are using...)
Is this line, var
new_order=[],nodes=node.parentNode.childNodes;
declearing two variables at the same
time?
Yes, it is declaring 2 seperate variable on the same line which is legel Javascript.
And what is
node.parentNode.childNodes doing?
It gets the list of the sibling elements for the current node selected.

Categories

Resources