Trees are very useful data structures in large part because of their recursive nature. Any part of a tree is
also a tree, and behaves the same way as the tree as a whole. In the DOM, when we grab a node to work with,
that node is the root of a subtree that works mostly the way as the whole tree starting at document
.
We can also create and manipulate trees outside the DOM and then insert them into the DOM, or remove subtrees
from the DOM.
For this module, you'll be continuing to work with the same code from the last module. To get started, clone
the repository below, which has a single file: quotes2-mockup.html
. Open that file in your browser
to see how we're going to visually update the quote list page (Step 2 of the last module).
Copy your work from the last module into this repository. You'll be working from the Step 2 ("Manipulating the page")
so you will need:
.gitignore
package.json
package-lock.json
quotes.sqlite
server.js
static/quote_list.html
static/quote_list.js
Update quote_list.html
and quote_list.js
so that the quote data is displayed as in the new quotes2-mockup.html
.
When dynamically creating complex HTML structures, it is better to include that structure hidden on the page as a template.
This allows you to copy that subtree, edit parts of it, and insert the copy back into the DOM. This makes it far easier to
make changes to the HTML and see that they are correct, and allows your designers to work directly with the HTML.
First, copy one of the list items from the mockup into your working html page. You can put it inside the list or out,
depending on whether you clear the list on retrieve or not. Put an ID on the <li>
node so that you can
easily grab the root of that subtree as the "template".
Next, alter your client-side JavaScript code. In the last assignment, you retrieved the quote data and looped over it creating
simple <li>
elements and inserting them into the list on the page. Change that code so that instead, you
grab the root of the template subtree and copy it like so:
const item = template.cloneNode(true);
Now your page should display the same number of copies of the template in the list as there are quotes in your database.
Next, you need to alter each copy with the quote data. From the root of the DOM, we have been using
getElementById
a lot to grab elements on the page. This method does
not work on subtrees, presumably because IDs are supposed to be
unique in the DOM. Instead, we will use the similar
getElementsByClassName
to grab nodes within a subtree. For
example, if I have a subtree called
part
, and I want to retrieve a certain node in that subtree, then I would:
- Put a class attribute (e.g. "target") on that node I want to grab
- Use
part.getElementsByClassName("target")[0]
to reference it
Note that I am using
[0]
because I know that there is only one node with that class in the subtree. This is fine
as long as I am using that particular class name as a unique-to-the-template identifier.
In your client-side code, after you clone the template and before you insert it (assuming it's named
item
):
- Set
item.id = ""
to remove the "template" ID
- Use a unique class as described above to change the quote text in the copy to the text you retreived
- (You may need to update your server route if it's only returning the text)
- Do the same for speaker and source
Finally, add the d-none
class to the template so that it is hidden, and update your code to use
item.classList.remove('d-none')
so that the copies are visible. Sometimes in debugging you will
make the template visible again so that you can see things.