CSCI 3342 Web Development
Spring 2024

Client-side page updates, Part II

Working with DOM subtrees

Your childrens' childrens' children.
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:
  1. Put a class attribute (e.g. "target") on that node I want to grab
  2. 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):
  1. Set item.id = "" to remove the "template" ID
  2. Use a unique class as described above to change the quote text in the copy to the text you retreived
  3. (You may need to update your server route if it's only returning the text)
  4. 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.