Advanced interactivity

Adjusting content styles based on enrichment information.

In this section

  • Use enrichment information to dynamically adjust the styles for displayed content.

Highlighting tagged provisions

Our final piece of interactivity will add an option to highlight provisions that have been tagged with a particular enrichment.
We're going to build the following:
  • A dropdown that lets the user choose one of the enrichments.
  • When an item is chosen, dim all the text of the document, except those portions that have the chosen enrichment.
Add a new button beneath the btn-comment button in expression_detail.html:
expression_detail.html
# ...
<button id="btn-comment" style="position: fixed; top: 10px; right: 10px;">Add comment...</button>
<select id="select-enrichments" style="position: fixed; top: 40px; right: 10px;">xx</select>
Add a new javascript block to populate the dropdown from the items in the gutter, and handles the interactivity when an item is chosen.
expression_detail.html
<script>
const select = document.getElementById('select-enrichments');
// add a mutation observer to take action when items are added to the gutter
function updateHighlightOptions () {
// empty the options
while (select.firstChild) select.removeChild(select.firstChild);
// add the empty option
const option = document.createElement('option');
option.innerText = "(off)";
option.value = "";
select.appendChild(option);
// unique text of gutter items
const items = [...new Set([...document.querySelectorAll('la-gutter-item')].map((item) => item.innerText))];
items.sort();
// add the items as options to the dropdown
for (const item of items) {
const option = document.createElement('option');
option.innerText = item;
option.value = item;
select.appendChild(option);
}
}
const observer = new MutationObserver(() => {
window.setTimeout(updateHighlightOptions, 500);
});
observer.observe(document.getElementById('gutter'), { childList: true });
updateHighlightOptions();
// when the select changes, highlight the provisions that match by adding a class to those provisions
select.addEventListener('change', (e) => {
const doc = document.getElementsByTagName('la-akoma-ntoso')[0];
// remove any existing highlights
for (const provision of document.querySelectorAll('.highlight')) {
provision.classList.remove('highlight');
}
const selected = e.target.value;
if (selected) {
// turn on highlighting
doc.classList.add('highlighting');
// mark each highlighted element
for (const item of document.querySelectorAll('la-gutter-item')) {
if (item.innerText === selected) {
const anchor = item.getAttribute('anchor');
const provision = doc.querySelector(`[id="${anchor.slice(1)}"]`);
if (provision) {
provision.classList.add('highlight');
}
}
}
} else {
// turn off highlighting
doc.classList.remove('highlighting');
}
});
</script>
Finally, let's add the necessary styling to handle the new .highlight and .highlighting classes.
Add this block in the <head> tag of expression_detail.html.
expression_detail.html
<style>
.highlighting {
color: lightgrey;
}
.highlighting .highlight {
color: black;
background-color: palegreen;
}
</style>
Load the page and choose an item from the dropdown: