I am trying to automatically generate a list of headings (name of the topics) from the current page. It should be displayed in the aside
element of the page.
This is what I have so far:
<main> <h2>Topic 1</h2> <h2>Topic 2</h2> <h2>Topic 3</h2> <h2>Topic 3</h2> </main> <aside> <!--automaticly generated list of heading like: <ul> <li>Topic 1</li> <li>Topic 2</li> <li>Topic 3</li> <li>Topic 4</li> </ul> --> </aside>
What do I need to do to finish this?
Well, there are different methods. Here you have one!
<main>
<h2>Topic 1</h2>
<h2>Topic 2</h2>
<h2>Topic 3</h2>
<h2>Topic 3</h2>
</main>
<aside>
<!--automaticly generated list of heading
like:
<ul>
<li>Topic 1</li>
<li>Topic 2</li>
<li>Topic 3</li>
<li>Topic 4</li>
</ul>
-->
</aside>
<script type="text/javascript">
var //Array with all the elements with tag main. It is a collection
mainEl = document.getElementsByTagName("main"),
//Because we only have one main tag, from the previous
//collection we chose the first elemnt
//From that element we create a collection with all the h2 inside
headingsEls = mainEl[0].getElementsByTagName("h2"),
//collection of elements with "aside" tag
asideEl = document.getElementsByTagName("aside"),
//We create the ul that wil hold the list
ulEl = document.createElement("ul")
//Go throw the h2 collection and for each element we create a new li element,
//we pass to it the text content and we put it on the ul
for(var i = 0; i < headingsEls.length; i++){
var liEl = document.createElement("li")
liEl.textContent = headingsEls[i].textContent
ulEl.appendChild(liEl)
}
//the new ul with the list is appended!
asideEl[0].appendChild(ulEl)
</script>
I have tried to be very descriptive but ask if you have more doubts!
Edited: I forgot that Array.from was implemented in ES2015. Changed the forEach to a for loop instead.
One way, if you're using jQuery, is to use, and in this case create, a simple plugin:
// using an Immediately-Invoked Function Expression
// to create a jQuery plugin, $.fn is the jQuery
// prototype:
(function($) {
// declaring the 'toc' property on the
// jQuery prototype as a function, into
// which options may be passed:
$.fn.toc = function(opts) {
// using jQuery.extend to extend
// the settings Object (the first
// Object inside of $.extend) with
// the user-supplied options from
// the opts Object:
let settings = $.extend({
'to': 'aside',
'link': true
}, opts),
// creating elements with jQuery, in order
// to use jQuery methods later to insert
// these elements into the document, and to
// insert other content into them:
li = $('<li />'),
// creating and inserting the <ul> object:
ul = $('<ul />').appendTo(settings.to),
a = $('<a />'),
ref;
// iterating over the passed-in jQuery collection
// the 'this' here:
this.each(function() {
// cloning the created-<li> element:
li.clone()
// appending the string of text from
// the current <h2> element:
.append(this.textContent)
// appending the cloned <li> to the
// previously-created <ul>
.appendTo(ul);
});
// if we should create links, the settings.link
// property-value is true:
if (settings.link === true) {
// again we iterate over the jQuery collection
// this time with the prop() method to set the
// id of the current <h2> element:
this.prop('id', function(i, p) {
// i: the index of the current element of
// the collection amongst the collection,
// p: the current property-value of the
// current element's specified property
// here we return the existing id if there is one,
// otherwise we return the localName of the element
// (same as the tagName but in lowercase) + the
// underscore character and the index, giving an
// id of 'h2_0', 'h2_1' etc:
return p.length ? p : this.localName + '_' + i;
// iterating over the collection still, this time
// using each():
}).each(function(i, e) {
// i: the index of the current element in
// the collection,
// e: the current DOM node (not jQuery) held
// at this point in the collection.
// storing the <li> element within the <ul>
// at the same index-point as the current element:
ref = ul.find('li').eq(i);
// cloning the created <a> element:
a.clone()
// updating its href property to be
// equal to the id of the current element
// from the collection, prefaced by a '#':
.prop('href', '#' + this.id)
// appending the contents of the <li> held
// in the ref variable:
.append(ref.contents())
// appending the created <a> element into
// the <li> element:
.appendTo(ref);
});
}
// returning the created <li> elements
// albeit append would itself return the original
// collection, the 'this' from the plugin:
return ul.find('li');
};
})(jQuery);
$('h2').toc();
(function($) { $.fn.toc = function(opts) { let settings = $.extend({ 'to': 'aside', 'link': true }, opts), li = $('<li />'), ul = $('<ul />').appendTo(settings.to), a = $('<a />'), ref; this.each(function() { li.clone().append(this.textContent).appendTo(ul); }); if (settings.link === true) { this.prop('id', function(i, p) { return p.length ? p : this.localName + '_' + i; }).each(function(i, e) { ref = ul.find('li').eq(i); a.clone().prop('href', '#' + this.id).append(ref.contents()).appendTo(ref); }); } return ul.find('li'); }; })(jQuery); $('h2').toc();
:target { color: #f90; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <main> <h2>Topic 1</h2> <h2>Topic 2</h2> <h2>Topic 3</h2> <h2>Topic 4</h2> </main> <aside></aside>
To use without creating links back to the <h2>
elements, simply set links: false
in the Object passed to the plugin:
$('h2').toc({
'link': false
});
(function($) { $.fn.toc = function(opts) { let settings = $.extend({ 'to': 'aside', 'link': true }, opts), li = $('<li />'), ul = $('<ul />').appendTo(settings.to), a = $('<a />'), ref; this.each(function() { li.clone().append(this.textContent).appendTo(ul); }); if (settings.link === true) { this.prop('id', function(i, p) { return p.length ? p : this.localName + '_' + i; }).each(function(i, e) { ref = ul.find('li').eq(i); a.clone().prop('href', '#' + this.id).append(ref.contents()).appendTo(ref); }); } return ul.find('li'); }; })(jQuery); $('h2').toc({ 'links': false });
:target { color: #f90; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <main> <h2>Topic 1</h2> <h2>Topic 2</h2> <h2>Topic 3</h2> <h2>Topic 4</h2> </main> <aside></aside>
References:
append()
. appendTo()
. clone()
. contents()
. each()
. eq()
. find()
. $.extend()
. prop()
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.