Laws.Africa Developer Guide
  • Laws.Africa Developer Guide
  • Get Started
    • Introduction
    • Quick start
    • Works and expressions
    • Webhooks
    • Changelog
  • Tutorial
    • About the tutorial
    • Module 1: Build a legislation reader
      • Introductory concepts
      • Create a basic Django app
      • Create database models
      • Fetching the data
      • Work listing page
      • Expression detail page
      • Styling with Law Widgets
      • Adding interactivity
      • Staying up to date
    • Module 2: Enrichments and interactivity
      • Basic enrichments
      • Advanced enrichments
      • Advanced interactivity
    • Module 3: Text extraction for search and analysis
      • Why extracting text is important
      • Basics of text extraction
      • Advanced text extraction
      • Extracting text for analysis and machine learning
  • Content API Reference
    • About the Content API
    • Authentication
    • Pagination
    • Places
    • All work expressions
    • Single work expression
      • Commencements
      • Embedded images
      • Publication document
      • Table of Contents
      • Timeline
    • Taxonomy topics
    • Enrichment datasets
  • AI API Reference
    • About the AI API
    • Authentication
    • Knowledge Bases
  • How-to Guides
    • How to use the Table of Contents API
    • How to download images
Powered by GitBook
On this page
  • In this section
  • Table of Contents
  • Popups for defined terms
  • Popups for internal references
  1. Tutorial
  2. Module 1: Build a legislation reader

Adding interactivity

Adding some basic interactivity using Law Widgets.

PreviousStyling with Law WidgetsNextStaying up to date

Last updated 1 year ago

In this section

  • Add a searchable Table of Contents using Law Widgets

  • Add interactivity with Law Widgets for defined terms and internal references

Now that we have a detail page showing the content of the documents, let's add some interactivity using Laws.Africa's .

Table of Contents

A searchable Table of Contents is important to make long legislative documents easier to navigate. There are two widgets you can use for the Table of Contents:

  • - this is a basic Table of Contents tree.

  • - this is a fully searchable and collapsible Table of Contents tree that builds on top of <la-table-of-contents>.

We'll use la-table-of-contents-controller because it gives us rich functionality right out the box.

Let's divide our content section into two columns to make room for the Table of Contents in a sidebar on the left of the page.

expression_detail.html
<html>
<head>
  <title>{{ expression.title }}</title>
  <!-- add the law widgets javascript -->
  <script
    type="module"
    src="https://cdn.jsdelivr.net/npm/@lawsafrica/law-widgets@latest/dist/lawwidgets/lawwidgets.esm.js"
  ></script>
</head>
<body>
  <a href="{% url 'home' %}">Home</a>
  
  <h1>{{ expression.title }}</h1>
  
  <div style="display: flex">
    <aside style="flex: 1">
      <la-table-of-contents-controller
        items="{{ toc_json }}"
        style="position: sticky; top: 0; max-height: 100vh; overflow-y: auto;"
      ></la-table-of-contents-controller>
    </aside>
    
    <div style="flex: 3">
      <!-- use la-akoma-ntoso law widget to apply styles -->
      <la-akoma-ntoso frbr-expression-uri="{{ expression.frbr_uri }}">
        {{ expression.content|safe }}
      </la-akoma-ntoso>
    </div>
  </div>
</body>

We need to provide the <la-table-of-contents-controller> with the JSON Table of Contents data in the items attribute. This is the data that is provided by the Laws.Africa Content API.

Update the views.py to add turn the TOC information into JSON.

views.py
import json

# ...

class ExpressionDetailView(DetailView):
    model = Expression
    slug_field = 'frbr_uri'
    slug_url_kwarg = 'frbr_uri'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['toc_json'] = json.dumps(self.object.toc_json['toc'])
        return context

The page now has an interactive table of contents.

Popups for defined terms

Modify expression_detail.html to include the new widget anywhere on the page:

expression_detail.html
...
<la-decorate-terms popup-definitions link-terms></la-decorate-terms>
<la-akoma-ntoso ...>...</la-akoma-ntoso>
...

This widget will add term definition popups and links in the first <la-akoma-ntoso> element on the page. If there is more than one, you can target it specifically by providing an akoma-ntoso attribute that uses a CSS selector to identify the target element: <la-decorate-terms akoma-ntoso="#akn-doc">.

You can control the behaviour by adding or removing these attributes. Try changing them and refreshing the page to see what changes.

  • popup-definitions - controls whether definitions of terms are shown in popups

  • link-terms - controls whether references to terms are shown as clickable links.

Popups for internal references

Modify expression_detail.html to include the new widget:

expression_detail.html
...
<la-decorate-internal-refs popups flag></la-decorate-internal-refs>
<la-akoma-ntoso ...>...</la-akoma-ntoso>
...

This widget will add interactivity to internal references in the first <la-akoma-ntoso> element on the page. Like with <la-decorate-terms> , you can use the akoma-ntoso attribute to target a specific <la-akoma-ntoso> element using a CSS selector, such as <la-decorate-internal-refs akoma-ntoso="#akn-doc">.

You can control the behaviour by adding or removing these attributes. Try changing them and refreshing the page to see what changes.

  • popups - controls whether reference target elements are shown in popups

  • flag - controls whether internal references are decorated with a purple bookmark icon

We're going to use the Law Widget to add popups for defined terms that occur in a document.

We're going to use the widget to make internal references more interactive. The widget will show a purple bookmark at an internal reference, and show the content of the target element when the user hovers over the reference.

Law Widgets
<la-table-of-contents>
<la-table-of-contents-controller>
<la-decorate-terms>
<la-decorate-internal-refs>